这个题目的分值是200,对我来说是个不小的挑战啊。
查了一下壳,没有发现什么
真的这么简单?拖入IDA观察:
呃呃呃,果然不简单;在IDA里面没有任何函数的痕迹。只有一个.text段。
猜测,应该是加了某种壳对源程序加密过。用OD载入。
看到OD的提示,再看到这里的循环pushad,看来应该是有壳,可是工具又查不出来,手动?
这时想到了ESP定律,记录个大佬的ESP定律讲解链接:https://blog.youkuaiyun.com/D_R_L_T/article/details/74625872
将的很详细具体。
我就抱着试一试的态度开始了ESP大法的操作。
1、先F8到pushad下一条指令,找到此时的ESP
2、转到ESP地址出的数据,下硬件内存访问断点。
3、F9到popad附近
4、F8单步寻找popad
5、附近找到jmp指令(一般是大的jmp)
6、跳过去就是OEP啦
嗯哼,接下来就可以用OD的插件Ollydump脱壳dump下来啦:
到底是不是呢?我们将dump下来的程序拖进IDA查看,会发现已经建立了函数。
接下来就是F5啦:
对这些函数逐个查看(详细的就不讲了)。
每个函数的功能:
sub_4018F0 下载一张图片,得到图片的字节数,返回存储图片数据的缓冲区的首地址。
sub_401740 初始化一个byte数组 KEY[264]
sub_401800 一个算法,得到与文件等长一段数据存在缓冲区buffer
sub_401220 对上述得到的缓冲区的数据进行一个简单的异或
纪录下自己的掉进的坑:在初始化数组时,自己没有注意到移位运算的优先级低于 加减 ,导致得到了乱码,半天才找到错误(长记性)。
附送逆向get的代码(C++):
#include<bits/stdc++.h>
using namespace std;
int main()
{
FILE *fp,*dump;
fp =fopen("x.jpg","rb");
dump = fopen("shell.txt","wb");
fseek(fp,0,SEEK_END);
int file_len = ftell(fp);//文件的长度
fseek(fp,0,SEEK_SET);
cout<<file_len<<endl;
char file[file_len];
fread(file,file_len,1,fp);
fclose(fp);
unsigned char key[264];
long long first = 0x4A8754F5745174;
for(int i=0;i<8;i++)
{
key[i] = 0;
}
for(int i=0;i<256;i++)
key[i+8] = ((i + (first >>(i % 8 * 8)))&0xff);//运算符的优先级
int len = 264;
int dkey[len/4];
int temp;
unsigned char temp4,temp5;
for(int i=0;i<len/4;i++)
{
temp = 0;
for(int j=3;j>-1;j--)
{
temp = (temp<<8) + key[4 * i + j];
}
dkey[i] = temp;
}
char flag[file_len];
for(int i=0;i<file_len;i++)
{
dkey[0] = (dkey[0]+ 1)%256;
dkey[1] = (key[dkey[0] + 8] + dkey[1])%256;
temp4 = key[dkey[0] + 8];
temp5 = key[dkey[1] + 8];
key[dkey[0] + 8] = temp5;
key[dkey[1] + 8] = temp4;
flag[i] = (key[(temp4 + temp5 )%256 + 8] ^ file[i] ^ i)%256;
fputc(flag[i],dump);
}
fclose(dump);
/*
for(int i=file_len-1;i>=4;i --)
{
if(flag[i]==0x68)
{
printf("%c%c%c%c",flag[i-4],flag[i-3],flag[i-2],flag[i-1]);
i -= 4;
}
}
cout<<endl;
*/
return 0;
}
可以用16进制编辑器打开得到的文件
可以看到很多字符,但好像是无序的;查看大佬的WP知道这是shellcode(惊)。
自己在OD找段空白,copy进去:
啊哈哈,刚好最近看书看到这段类似的代码实现;
PEB-> PEB_LAR_DATA-> InInitalizationOrderMouduleList->DLL->API
继续往下看;
push一段字符串
注意小端序,即可得到了flag.