逆向工程初步160个crackme-------6

天大地大妈咪最大 提交于 2020-01-31 05:24:08

工具:1. 按钮事件地址转换器E2A
2. PEID
3. Ollydbg
同样我们先来运行一下这个程序,
在这里插入图片描述
ok按钮是被禁用的,有一个help按钮点击后弹出一个消息框:消息框显示提示信息为。本程序需要输入正确的姓名的序列号,把OK按钮和Cancella按钮隐藏显示出其后面的RingZero的LOGO
在这里插入图片描述我们随便输入姓名和序列号
在这里插入图片描述
发现OK还是禁用的,那我们就点击Canella试试,发现没用并且序列号被清零在这里插入图片描述
我们熟悉完程序后,正式开始分析。
我们还是先用PEID看看其文件信息,
在这里插入图片描述发现其是用Delphi编写的32位程序,我们打开OD载入程序。
运行程序随便输入用户名和序列号
在这里插入图片描述
随后我们需要分析其对应的各个按钮事件,用E2A打开程序文件查看各个按钮事件对应的地址,因为OK按键被禁用所以我们先分析Cancela按钮消息,用E2A程序打开查看Cancella按钮事件的地址
在这里插入图片描述然后在OD中搜索此地址并下段,然后单击CancellaClick按钮程序会停在此地址处
在这里插入图片描述然后单步向下并且注意跳转指令(因为我们输入的是错误的注册码,所以程序走的肯定是不正确的分支,所以我们就和程序反着来,显式改变eip,逆其道而为之),先看看这样后能不能满足条件(如果能满足在回头来分析如何让其实现跳转)。
在这里插入图片描述F8向下分析遇见一个跳转指令,按此程序其是要跳转(那么我们就逆其道而为之),显式改变eip为00442EF0,然后执行程序
在这里插入图片描述
发现CancellaClick按钮没了,而且OK被启用了(那么正好我们再来分析一下OK按钮),用E2A查找OK按钮的地址
在这里插入图片描述在OD中搜索地址并下断点后点击OK按钮,点击后程序将停在此地址处
在这里插入图片描述F8单步运行,直到遇见判断跳转指令在这里插入图片描述其程序要跳转(我们就逆其道而为之),显式改变eip为00442dca后,运行程序在这里插入图片描述运行程序后,程序的OK按钮也去除了(哈哈!完成任务)
在这里插入图片描述
下面我们就看如何能让程序实现这两个跳转,
下面我们我们先来分析一下第一处跳转(即在按CancellaClick按钮处的跳转)
重新加载程序然后运行并输入用户名和序列号,
在这里插入图片描述
然后点击Cancella按钮程序停在其按钮事件处理处,我们向下分析看见测试指令前面的关键函数,我们需要分析这个关键函数,F8向下运行并F7进入关键函数
在这里插入图片描述分析关键函数

00442AF4  /$  55            push ebp
00442AF5  |.  8BEC          mov ebp,esp
00442AF7  |.  83C4 F8       add esp,-0x8
00442AFA  |.  53            push ebx
00442AFB  |.  56            push esi
00442AFC  |.  8955 F8       mov [local.2],edx
00442AFF  |.  8945 FC       mov [local.1],eax
00442B02  |.  8B45 FC       mov eax,[local.1]
00442B05  |.  E8 DE10FCFF   call aLoNg3x_.00403BE8
00442B0A  |.  33C0          xor eax,eax
00442B0C  |.  55            push ebp
00442B0D  |.  68 902B4400   push aLoNg3x_.00442B90
00442B12  |.  64:FF30       push dword ptr fs:[eax]
00442B15  |.  64:8920       mov dword ptr fs:[eax],esp
00442B18  |.  8B45 FC       mov eax,[local.1]
00442B1B  |.  E8 140FFCFF   call aLoNg3x_.00403A34                   ;  求用户名长度
00442B20  |.  83F8 05       cmp eax,0x5                              ;  用户名长度不能小于5
00442B23  |.  7E 53         jle XaLoNg3x_.00442B78
00442B25  |.  8B45 FC       mov eax,[local.1]
00442B28  |.  0FB640 04     movzx eax,byte ptr ds:[eax+0x4]          ;  eax = 用户名的第五个字符
00442B2C  |.  B9 07000000   mov ecx,0x7
00442B31  |.  33D2          xor edx,edx
00442B33  |.  F7F1          div ecx
00442B35  |.  8BC2          mov eax,edx
00442B37  |.  83C0 02       add eax,0x2                              ;  eax = eax % 7 +2
00442B3A  |.  E8 E1FEFFFF   call aLoNg3x_.00442A20                   ;  计算eax的阶乘
00442B3F  |.  8BF0          mov esi,eax
00442B41  |.  33DB          xor ebx,ebx
00442B43  |.  8B45 FC       mov eax,[local.1]
00442B46  |.  E8 E90EFCFF   call aLoNg3x_.00403A34                   ;  计算用户名的长度
00442B4B  |.  85C0          test eax,eax
00442B4D  |.  7E 16         jle XaLoNg3x_.00442B65
00442B4F  |.  BA 01000000   mov edx,0x1
00442B54  |>  8B4D FC       /mov ecx,[local.1]                       ;  此循环用用户名的每一个字符乘以esi(esi为eax的阶乘),结果存在ebx中
00442B57  |.  0FB64C11 FF   |movzx ecx,byte ptr ds:[ecx+edx-0x1]
00442B5C  |.  0FAFCE        |imul ecx,esi
00442B5F  |.  03D9          |add ebx,ecx
00442B61  |.  42            |inc edx
00442B62  |.  48            |dec eax
00442B63  |.^ 75 EF         \jnz XaLoNg3x_.00442B54
00442B65  |>  2B5D F8       sub ebx,[local.2]                        ;  用 ebx - 局部变量2
00442B68  |.  81FB 697A0000 cmp ebx,0x7A69
00442B6E  |.  75 04         jnz XaLoNg3x_.00442B74                   ;  if(ebx == 0x7a69)   ebx=1;  else  ebx=0
00442B70  |.  B3 01         mov bl,0x1
00442B72  |.  EB 06         jmp XaLoNg3x_.00442B7A
00442B74  |>  33DB          xor ebx,ebx
00442B76  |.  EB 02         jmp XaLoNg3x_.00442B7A
00442B78  |>  33DB          xor ebx,ebx
00442B7A  |>  33C0          xor eax,eax
00442B7C  |.  5A            pop edx
00442B7D  |.  59            pop ecx
00442B7E  |.  59            pop ecx
00442B7F  |.  64:8910       mov dword ptr fs:[eax],edx
00442B82  |.  68 972B4400   push aLoNg3x_.00442B97
00442B87  |>  8D45 FC       lea eax,[local.1]
00442B8A  |.  E8 290CFCFF   call aLoNg3x_.004037B8
00442B8F  \.  C3            retn
00442B90   .^ E9 E306FCFF   jmp aLoNg3x_.00403278
00442B95   .^ EB F0         jmp XaLoNg3x_.00442B87
00442B97   .  8BC3          mov eax,ebx                              ;  ebx =eax,因为要想不跳转 al不为0,即ebx不能为0
00442B99   .  5E            pop esi
00442B9A   .  5B            pop ebx
00442B9B   .  59            pop ecx
00442B9C   .  59            pop ecx
00442B9D   .  5D            pop ebp
00442B9E   .  C3            retn


if((ebx-局部变量2 )== 0x7a69) 则会使al=1从而达到目的不跳转。
而ebx是由 用户名的每一位分别乘以 ((用户名第五个字符%7+2)的阶乘)的累加
而我们需要分析局部变量2怎么来的,
mov [local.2],edx可得其是由edx得到的,再往关键函数上分析看edx是怎么得到的

在这里插入图片描述

00442ECC  |.  8B45 FC       mov eax,[local.1]                        ;  eax = 填写的注册码
00442ECF  |.  E8 9C47FCFF   call aLoNg3x_.00407670                   ;  将注册码变为10进制形式
00442ED4  |.  50            push eax                                 ;  返回值入栈
00442ED5  |.  8D55 FC       lea edx,[local.1]
00442ED8  |.  8B83 DC020000 mov eax,dword ptr ds:[ebx+0x2DC]
00442EDE  |.  E8 DD03FEFF   call aLoNg3x_.004232C0
00442EE3  |.  8B45 FC       mov eax,[local.1]
00442EE6  |.  5A            pop edx                                  ;  栈中值出栈到edx
00442EE7  |.  E8 08FCFFFF   call aLoNg3x_.00442AF4
00442EEC  |.  84C0          test al,al


所以要想去掉cancella按钮,并启用OK按钮就用户名和注册码应该满足条件为
用户名的每一位分别乘以 ((用户名第五个字符%7+2)的阶乘)的累加 减去 注册码 等于0x7a69

如果用户名为987654,则注册码为204103我们重新填写并点击Cancella按钮后程序如我们所愿,在这里插入图片描述
然后我们分析OK按钮事件处理的第二处判断跳转
用E2A查看OK按钮事件地址
在这里插入图片描述在OD中搜索并下断点后,单击OK按钮程序会停在此地址处
在这里插入图片描述F8向下运行并进入测试转移指令前的关键函数,并分析此关键函数的代码

00442BA0  /$  55            push ebp
00442BA1  |.  8BEC          mov ebp,esp
00442BA3  |.  6A 00         push 0x0
00442BA5  |.  6A 00         push 0x0
00442BA7  |.  6A 00         push 0x0
00442BA9  |.  53            push ebx
00442BAA  |.  56            push esi
00442BAB  |.  8BF2          mov esi,edx
00442BAD  |.  8945 FC       mov [local.1],eax
00442BB0  |.  8B45 FC       mov eax,[local.1]
00442BB3  |.  E8 3010FCFF   call aLoNg3x_.00403BE8
00442BB8  |.  33C0          xor eax,eax
00442BBA  |.  55            push ebp
00442BBB  |.  68 672C4400   push aLoNg3x_.00442C67
00442BC0  |.  64:FF30       push dword ptr fs:[eax]
00442BC3  |.  64:8920       mov dword ptr fs:[eax],esp
00442BC6  |.  33DB          xor ebx,ebx
00442BC8  |.  8D55 F8       lea edx,[local.2]
00442BCB  |.  8BC6          mov eax,esi
00442BCD  |.  E8 6E4AFCFF   call aLoNg3x_.00407640
00442BD2  |.  8D45 F4       lea eax,[local.3]
00442BD5  |.  8B55 F8       mov edx,[local.2]
00442BD8  |.  E8 730CFCFF   call aLoNg3x_.00403850
00442BDD  |.  8B45 F8       mov eax,[local.2]
00442BE0  |.  E8 4F0EFCFF   call aLoNg3x_.00403A34                   ;  求长度
00442BE5  |.  83F8 05       cmp eax,0x5
00442BE8  |.  7E 60         jle XaLoNg3x_.00442C4A
00442BEA  |.  8B45 F8       mov eax,[local.2]
00442BED  |.  E8 420EFCFF   call aLoNg3x_.00403A34                   ;  求注册码长度
00442BF2  |.  8BF0          mov esi,eax
00442BF4  |.  83FE 01       cmp esi,0x1
00442BF7  |.  7C 2F         jl XaLoNg3x_.00442C28
00442BF9  |>  8D45 F4       /lea eax,[local.3]                       ;  此循环将  (注册码的每一个字符乘以本身后)* 注册码长度 % 19 + 0x41
00442BFC  |.  E8 0310FCFF   |call aLoNg3x_.00403C04                  ;  得到的字符与原字符替代保存到局部变量3中
00442C01  |.  8D4430 FF     |lea eax,dword ptr ds:[eax+esi-0x1]
00442C05  |.  50            |push eax
00442C06  |.  8B45 F8       |mov eax,[local.2]
00442C09  |.  0FB64430 FF   |movzx eax,byte ptr ds:[eax+esi-0x1]
00442C0E  |.  F7E8          |imul eax
00442C10  |.  0FBFC0        |movsx eax,ax
00442C13  |.  F7EE          |imul esi
00442C15  |.  B9 19000000   |mov ecx,0x19
00442C1A  |.  99            |cdq
00442C1B  |.  F7F9          |idiv ecx
00442C1D  |.  83C2 41       |add edx,0x41
00442C20  |.  58            |pop eax
00442C21  |.  8810          |mov byte ptr ds:[eax],dl
00442C23  |.  4E            |dec esi
00442C24  |.  85F6          |test esi,esi
00442C26  |.^ 75 D1         \jnz XaLoNg3x_.00442BF9
00442C28  |>  8B45 F4       mov eax,[local.3]
00442C2B  |.  8B55 FC       mov edx,[local.1]
00442C2E  |.  E8 110FFCFF   call aLoNg3x_.00403B44                   ;  比较eax 和 edx所指的字符串是否相等
00442C33  |.  75 17         jnz XaLoNg3x_.00442C4C                   ;  if(eax == ecx)     ebx = 1;   else    ebx = 0
00442C35  |.  8B45 FC       mov eax,[local.1]
00442C38  |.  8B55 F4       mov edx,[local.3]
00442C3B  |.  E8 040FFCFF   call aLoNg3x_.00403B44
00442C40  |.  75 04         jnz XaLoNg3x_.00442C46
00442C42  |.  B3 01         mov bl,0x1
00442C44  |.  EB 06         jmp XaLoNg3x_.00442C4C
00442C46  |>  33DB          xor ebx,ebx
00442C48  |.  EB 02         jmp XaLoNg3x_.00442C4C
00442C4A  |>  33DB          xor ebx,ebx
00442C4C  |>  33C0          xor eax,eax
00442C4E  |.  5A            pop edx
00442C4F  |.  59            pop ecx
00442C50  |.  59            pop ecx
00442C51  |.  64:8910       mov dword ptr fs:[eax],edx
00442C54  |.  68 6E2C4400   push aLoNg3x_.00442C6E
00442C59  |>  8D45 F4       lea eax,[local.3]
00442C5C  |.  BA 03000000   mov edx,0x3
00442C61  |.  E8 760BFCFF   call aLoNg3x_.004037DC
00442C66  \.  C3            retn
00442C67   .^ E9 0C06FCFF   jmp aLoNg3x_.00403278
00442C6C   .^ EB EB         jmp XaLoNg3x_.00442C59
00442C6E   .  8BC3          mov eax,ebx                              ;  eax  = ebx,  要想让al不等于0,则ebx不能为0
00442C70   .  5E            pop esi
00442C71   .  5B            pop ebx
00442C72   .  8BE5          mov esp,ebp
00442C74   .  5D            pop ebp
00442C75   .  C3            retn


eax所指的字符串是 (注册码的每一个字符乘以本身后)* 注册码长度 % 19 + 0x41得到的新字符串
ebx所指的字符串为用户名。

if(eax所指的字符串 == ebx所指的字符串)
 ebx=1;
else
 ebx=0;

当ebx==1时,则eax也为1,不发生跳转从而使OK按钮隐藏

所以用户名等于(注册码的每一个字符乘以本身后)* 注册码长度 % 19 + 0x41得到的字符串
此时注册码为204103,其对应的用户名为 : AIMEUG
重新输入用户名点击OK后,程序如我们所愿显示出RingZero的logo
在这里插入图片描述
总结:程序逆向可以先采用 “逆其道而为之”的思想,显示改变eip试探程序是否能如我们所愿,如果如我们所愿就返回分析如何满足条件让其自主执行正确的分支。另外有关delphi程序注意使用E2A按钮事件地址转换器从而在OD中追踪相应的按钮事件

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!