1.** *首先使用PEid工具对软件进行分析,查看是否有壳*
答:.pediy区块是外壳程序所加载的部分,所以改程序有壳。
2. *若有壳,按照所学的脱壳方式进行脱壳*
*(1)查找程序的原始入口OEP,根据跨段指令寻找OEP*
- 运行OllyDbg,调试选项中“Event”将暂停点设置在主模块的入口点。打开CRACKME.EXE,程序会停在00408000h处。
2)按F8执行到00408001h处,再按F7跳转到004080C8h处。
3)004080C8h一直运行到00408135h处,会跳转到00020000h处。
跳转后:
4)从00020000h执行到000200A5h处,000200A5h到000200F0h处是一个循环,右键选中000200F2h处,按F4跳出循环到000200F2h处。
5)从000200F2h处执行到00020147h处,jmp short 00020147指令表示00020147h处到00020178h处是一个循环;jmp short 0002010C指令表示0002010Ch处到0002017Dh处是一个循环;跳出这两个循环,到0002017Fh处。
6)0002017Fh处会跳转到000201F6h处。
- 从0000201F6h处执行到00020282h处、00020283h处、00020283h处,分别可以看到popad、push 401000、retn。至此,OEP就找到了,是401000。
*(2)抓取内存映像文件*
1)运行CRACKME.EXE程序,运行LordPE,在LordPE的选项中勾选“Full dump header from disk”,在窗口选择CRACKME,点击右键,执行“修正镜像大小”,接着执行“dump full(完整转存)”命令,即可转去内存数据并保存在文件里。命名为dumped.exe。
*(3)重建输入表*
1)使用ImportREC工具进行修复。先运行CRACKME.EXE,接着运行ImportREC。
2)在下列表框中选择CRACKME.EXE进程,在OEP处填入OEP的RVA值1000,单击“IAT AutoSearch”按钮,让其自动检查IAT的偏移和大小。弹出如下对话框:
表示输入的OEP发挥作用了。
3)单击“Get Imports”按钮,让其分析IAT结构得到基本信息
4)单击“Fix Dump”,选择刚才抓取的dumped.exe映像文件,将自动创建一个dumped_.exe文件。这个就是脱壳后的文件了,该文件可以正常运行。接着使用PEiD.exe查看脱壳前后的区段表。
脱壳前:
脱壳后:
*3.脱壳后再对软件代码进行分析,分析出自己姓名所对应的正确的序列号*
1)打开OllyDbg,选择dumped_.exe进行分析。
2)先在00401226h处设置断点,在注册表填入自定义姓名和序列号。
3)按F9后,得到下图所示;在00401228h处显示了Name框的内容,在00401233h处显示了序列号Serial框的内容。
4)接下来分析下图语句,首先是一个用户名的计算函数,然后是一个序列号的计算函数,接着比较两个函数计算的结果是否相等,相等则提示正确。
00401228h call dumped_.0040137E //用户名的计算函数
00401238h call dumped_.004013D8 //序列号的计算函数
00401241h cmp eax,ebx //比较用户名字和序列号计算的结果
00401243h je short dumped_.0040124C //相等则提示正确
00401245h call dumped_.00401362 //错误提示
0040124Ch call dumped_.0040134D //正确提示
5)用户名算法分析
0040137Eh先取出用户名,依次去出名字字符串的单字符,将用户名中的英文单词全部转换为大写。
0040137Eh mov esi, dword ptr ss:[esp+0x4] //esi=username
00401389h cmp a1, 0x41 //比较是否小于A
0040138Dh cmp a1, 0x5A //比较是否大于Z
00401391h Inc esi //username>>1
00401394h call dumped_.004013D2 //将小写字母转成大写
接着进入4013C2这个函数,将用户名每一位的ASCII值相加。
6)序列号算法分析
取出每一位的ASCII值,然后减去0x30,即将字母转化为数字然后用edi乘0xA(0x10),接着用edi再加上序列号。(edi与0x1234进行异或)
序列号edi校验:
比较edi与ebx是否相等:
*4.********写出注册机********代码如下:*
#include<bits/stdc++.h>
using namespace std;
int main()
{
string username;
printf("请输入用户名: ");
cin >> username;
int result = 0, l = username.length();
for(int i=0; i<l; i++){
if(username[i]>='a'&&username[i]<='z'){
username[i] = username[i]-'a' + 'A';
}
result += username[i];
}
result ^= 0x5678;
result ^= 0x1234;
printf("%d\n", result);
return 0;
}