1.** *首先使用PEid工具对软件进行分析,查看是否有壳*

答:.pediy区块是外壳程序所加载的部分,所以改程序有壳。

img
img



2. *若有壳,按照所学的脱壳方式进行脱壳*

*(1)查找程序的原始入口OEP,根据跨段指令寻找OEP*
  1. 运行OllyDbg,调试选项中“Event”将暂停点设置在主模块的入口点。打开CRACKME.EXE,程序会停在00408000h处。
img

2)按F8执行到00408001h处,再按F7跳转到004080C8h处。

img

3)004080C8h一直运行到00408135h处,会跳转到00020000h处。

img
img

跳转后:

img

4)从00020000h执行到000200A5h处,000200A5h到000200F0h处是一个循环,右键选中000200F2h处,按F4跳出循环到000200F2h处。

img

5)从000200F2h处执行到00020147h处,jmp short 00020147指令表示00020147h处到00020178h处是一个循环;jmp short 0002010C指令表示0002010Ch处到0002017Dh处是一个循环;跳出这两个循环,到0002017Fh处。

img

6)0002017Fh处会跳转到000201F6h处。

img
img

  1. 从0000201F6h处执行到00020282h处、00020283h处、00020283h处,分别可以看到popad、push 401000、retn。至此,OEP就找到了,是401000。
img

img

*(2)抓取内存映像文件*

1)运行CRACKME.EXE程序,运行LordPE,在LordPE的选项中勾选“Full dump header from disk”,在窗口选择CRACKME,点击右键,执行“修正镜像大小”,接着执行“dump full(完整转存)”命令,即可转去内存数据并保存在文件里。命名为dumped.exe。

img
img

2) dumped.exe文件是不可运行的
img

*(3)重建输入表*

1)使用ImportREC工具进行修复。先运行CRACKME.EXE,接着运行ImportREC。
img


2)在下列表框中选择CRACKME.EXE进程,在OEP处填入OEP的RVA值1000,单击“IAT AutoSearch”按钮,让其自动检查IAT的偏移和大小。弹出如下对话框:

img

表示输入的OEP发挥作用了。

3)单击“Get Imports”按钮,让其分析IAT结构得到基本信息

img

4)单击“Fix Dump”,选择刚才抓取的dumped.exe映像文件,将自动创建一个dumped_.exe文件。这个就是脱壳后的文件了,该文件可以正常运行。接着使用PEiD.exe查看脱壳前后的区段表。

脱壳前:

img

脱壳后:

img

*3.脱壳后再对软件代码进行分析,分析出自己姓名所对应的正确的序列号*

1)打开OllyDbg,选择dumped_.exe进行分析。

img

2)先在00401226h处设置断点,在注册表填入自定义姓名和序列号。

img

3)按F9后,得到下图所示;在00401228h处显示了Name框的内容,在00401233h处显示了序列号Serial框的内容。

img


4)接下来分析下图语句,首先是一个用户名的计算函数,然后是一个序列号的计算函数,接着比较两个函数计算的结果是否相等,相等则提示正确。

img
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)用户名算法分析
img

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 //将小写字母转成大写

img

接着进入4013C2这个函数,将用户名每一位的ASCII值相加。

img

6)序列号算法分析

img

取出每一位的ASCII值,然后减去0x30,即将字母转化为数字然后用edi乘0xA(0x10),接着用edi再加上序列号。(edi与0x1234进行异或)


序列号edi校验:

img

比较edi与ebx是否相等:

img

*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;

}