接上一篇 软件逆向破解零基础入门实战5 我们继续学习软件逆向破解零基础入门第6篇。这次的练习程序也是Delphi写的程序,功能也相对简单。 一个简单的crackme程序,难度1颗星,要求输入正确的用户名和注册码将下面2个按钮隐藏显示出后面的图片。 上一篇中讲到找按钮或功能函数是将反汇编出来的所有段头进行下断点,看看它在哪里断下就是关键位置。本篇我们就不用这么麻烦了,我们借助工具来快速找关键位置和功能。
这款工具就是:DarkDe4.exe,它可以直接把Delphi写的软件直接可视化显示出来。(具体工具大家可百度搜索自行下载) 运行DarkDe4
将要反汇编的软件直接拖入进来,等待工具自动处理完毕如下图:
中文软件,具体功能按钮自己点击了解即可。我们直接选择 过程,这里就有很多的事件了。从名字可以看出 如okclick和cancellaclick就可能是软件上的下面的2个按钮了。这里要关注的就是RVA代码,将要分析的软件 aLoNg3x.1.exe拖进OllyDBG 按下ctrl+g把DarkDe4逆向出来的所有RVA地址下断点。此时发现在输入框输入一个字就会断下来。这是我输入注册码断下的位置:我们直接F8单步走一遍发现它取了用户名的长度和5对比00442A6B |. E8 C40FFCFF call aLoNg3x_.00403A3400442A70 |. 83F8 05 cmp eax,0x500442A73 |. 7E 53 jle short aLoNg3x_.00442AC8
大概是用户名长度要大于5。下面这里是对用户名进行逐字取值计算00442AA2 |. 0FAFCE |imul ecx,esi00442AA5 |. 0FAFC8 |imul ecx,eax00442AA8 |. 03D9 |add ebx,ecx00442AAA |. 40 |inc eax00442AAB |. 4A |dec edx
IMUL是x86架构中的有符号整数乘法指令,用于执行带符号数的乘法运算。
ADD是Intel x86架构的汇编语言算术指令,用于执行寄存器、内存地址与立即数之间的加法运算,结果存储在目标操作数中。
INC 指令:递增操作
dec 是汇编语言中的一条减量指令
与之前一样,我们先试试能不能直接修改它关键位置随便输入内容进行注册。
F8往下走,注意这句:
00442AB8 |. 81FB 9A020000 cmp ebx,0x29A00442ABE |. 75 04 jnz short aLoNg3x_.00442AC400442AC0 |. B3 01 mov bl,0x1
前面获取用户名计算得到的值与0x29a比较,相等给BL赋值。我们直接修改寄存器窗口中的Z标志让它不跳转后继续F8返回到这里00442E5B |. E8 DCFBFFFF call aLoNg3x_.00442A3C00442E60 |. 84C0 test al,al00442E62 |. 74 0F je short aLoNg3x_.00442E73
对AL进行了比较,没跳转。给DL赋值了1,F9运行程序,可以看到OK按钮变成了可用状态。接着点OK按钮,继续分析它的功能,进入到OK按钮功能代码里,注意这段:00442D80 |. 8078 47 01 cmp byte ptr ds:[eax+0x47],0x100442D84 |. 75 12 jnz short aLoNg3x_.00442D9800442D86 |. BA 002E4400 mov edx,aLoNg3x_.00442E00 ; 000442D8B |. 8B83 E0020000 mov eax,dword ptr ds:[ebx+0x2E0]00442D91 |. E8 5A05FEFF call aLoNg3x_.004232F000442D96 |. EB 3F jmp short aLoNg3x_.00442DD7
注释后有个0,分析得到它是给注册码框清0的,这里我们需要直接跳过去,在寄存器窗口把Z标志双击设置为0,F8往下又进入新函数有个算法:
00442BF9 |> /8D45 F4 /lea eax,[local.3]00442BFC |. |E8 0310FCFF |call aLoNg3x_.00403C0400442C01 |. |8D4430 FF |lea eax,dword ptr ds:[eax+esi-0x1]00442C05 |. |50 |push eax00442C06 |. |8B45 F8 |mov eax,[local.2]00442C09 |. |0FB64430 FF |movzx eax,byte ptr ds:[eax+esi-0x1]00442C0E |. |F7E8 |imul eax00442C10 |. |0FBFC0 |movsx eax,ax00442C13 |. |F7EE |imul esi00442C15 |. |B9 19000000 |mov ecx,0x1900442C1A |. |99 |cdq00442C1B |. |F7F9 |idiv ecx00442C1D |. |83C2 41 |add edx,0x4100442C20 |. |58 |pop eax ; 0018F8D400442C21 |. |8810 |mov byte ptr ds:[eax],dl00442C23 |. |4E |dec esi00442C24 |. |85F6 |test esi,esi00442C26 |.^\75 D1 \jnz short aLoNg3x_.00442BF9
大致是取假注册码运行,先不管它。往下看有个关键位置:
00442C33 |. /75 17 jnz short aLoNg3x_.00442C4C00442C35 |. |8B45 FC mov eax,[local.1]00442C38 |. |8B55 F4 mov edx,[local.3]00442C3B |. |E8 040FFCFF call aLoNg3x_.00403B4400442C40 |. |75 04 jnz short aLoNg3x_.00442C46
第一个JNZ不能让它跳,修改Z标志,到后面这个CALL看到EAX和EDX有2个值分别为:
堆栈 ss:[0018F5B8]=01CB7328, (ASCII "BADQUVA")
eax=01CB7314, (ASCII "it0365")
真假码?
应该是进行对比,显然不相等后面的JNZ跳转了。
00442C40 |. /75 04 jnz short aLoNg3x_.00442C4600442C42 |. |B3 01 mov bl,0x1
不能让它跳,修改Z标志。F8到返回到这里:
00442DC1 |. E8 DAFDFFFF call aLoNg3x_.00442BA000442DC6 |. 84C0 test al,al00442DC8 |. 74 0D je short aLoNg3x_.00442DD7 ; ?
JE未跳转,直接F9可以看到OK按钮就隐藏了。
现在分析Cancella按钮,同样点击它断下后F8走到这个位置:
00442EE7 |. E8 08FCFFFF call aLoNg3x_.00442AF400442EEC |. 84C0 test al,al00442EEE |. 74 1C je short aLoNg3x_.00442F0C
和OK按钮类似的代码
这是取用户名计算的算法函数,同样里面的DL要给它赋值,具体操作同上面一样的。这里的JE也是不能跳的,跳了就把注册码清0了.修改后,F9看到直接破解了。两按钮直接隐藏成功。
我们这种直接修改执行流程的方法还是可行的。刚才这种是动态修改的,如何永久保存修改的地方让它直接可以使用呢?
非常简单,一共要修改的为3处。
第一处:
00442E60 |. 84C0 test al,al00442E62 |. 74 0F je short aLoNg3x_.00442E73
在JE处右键--二进制--NOP填充不让它跳
第二处:
00442D80 |. 8078 47 01 cmp byte ptr ds:[eax+0x47],0x100442D84 |. 75 12 jnz short aLoNg3x_.00442D98
把JNZ改为JMP(双击代码或按空格)
00442D80 |. 8078 47 01 cmp byte ptr ds:[eax+0x47],0x100442D84 EB 12 jmp short aLoNg3x_.00442D98
第三处:
00442DC6 |. 84C0 test al,al00442DC8 |. 74 0D je short aLoNg3x_.00442DD7 ; ?
第四处:
00442EEC |. 84C0 test al,al00442EEE |. 74 1C je short aLoNg3x_.00442F0C
也是要NOP掉
随后把所有修改的内容直接保存为一个新的EXE程序,就直接破解过掉了注册的限制。
单击右键 选择 复制到可执行程序---所有修改
选择 全部复制
再右键保存文件即可!
随便输入内容点击就可以隐藏了。
破解的效果达到了,但不符作者的要求。作者要求输入正确的用户和密码实现隐藏。
前面我们大概走了一遍,也大概知道整个过程。现在梳理下:
首先在用户名框输入内容使OK按钮可用,接着按OK按钮让按钮隐藏最后按清理按钮也隐藏。
上面分析我们注意到取用户名计算与注册码计算的位置有关键对比和判断。看看能不能直接在内存中找到正确的用户名和注册码。
一、分析取用户名框的代码尝试获取注册码
将所有的断点禁用,菜单栏---查看--断点,或点工具栏上B图标,进入窗口右键 全部禁用。
运行软件,随便输入用户名和密码
再把所有断点启动,点击输入框按下键盘断下后F8分析
00442A93 |> /8B4D FC /mov ecx,[local.1]00442A96 |. |0FB64C01 FF |movzx ecx,byte ptr ds:[ecx+eax-0x1]00442A9B |. |8B75 FC |mov esi,[local.1]00442A9E |. |0FB63406 |movzx esi,byte ptr ds:[esi+eax]00442AA2 |. |0FAFCE |imul ecx,esi00442AA5 |. |0FAFC8 |imul ecx,eax00442AA8 |. |03D9 |add ebx,ecx00442AAA |. |40 |inc eax00442AAB |. |4A |dec edx00442AAC |.^\75 E5 \jnz short aLoNg3x_.00442A9300442AAE |> 8B45 F8 mov eax,[local.2]00442AB1 |. E8 BA4BFCFF call aLoNg3x_.0040767000442AB6 |. 2BD8 sub ebx,eax00442AB8 |. 81FB 9A020000 cmp ebx,0x29A00442ABE |. 75 04 jnz short aLoNg3x_.00442AC400442AC0 |. B3 01 mov bl,0x1
这段代码对用户名进行运算后与注册码的值相减看是否等于29a决定后面Bl=1的跳转是否有效。
00442AB6 |. 2BD8 sub ebx,eax
eax=0001E240
ebx=0003A81A
EBX为用户名运算后的值,我们猜想下3A81A减多少等于0X29A。那就把3A81A-29A=3A580(转10进制238976)就是注册码了。
输入注册码后OK按钮可以用了,点击OK按钮继续看。
按下OK按钮后,断到这里,这个清0的操作似乎避不开?cmp byte ptr ds:[eax+0x47],0x1 这段【EAX+0X47]的值从哪来的?猜测只有是把清0按钮隐藏才能给[eax+0x47]赋值。OK按钮才不会清0!
于是我们先分析下Cancella按钮,将它隐藏。F9运行程序,点击清0按钮。
00442B25 |. 8B45 FC mov eax,[local.1]00442B28 |. 0FB640 04 movzx eax,byte ptr ds:[eax+0x4]00442B2C |. B9 07000000 mov ecx,0x700442B31 |. 33D2 xor edx,edx00442B33 |. F7F1 div ecx ; user32.76E4690100442B35 |. 8BC2 mov eax,edx00442B37 |. 83C0 02 add eax,0x200442B3A |. E8 E1FEFFFF call aLoNg3x_.00442A2000442B3F |. 8BF0 mov esi,eax00442B41 |. 33DB xor ebx,ebx00442B43 |. 8B45 FC mov eax,[local.1]00442B46 |. E8 E90EFCFF call aLoNg3x_.00403A3400442B4B |. 85C0 test eax,eax00442B4D |. 7E 16 jle short aLoNg3x_.00442B6500442B4F |. BA 01000000 mov edx,0x100442B54 |> 8B4D FC /mov ecx,[local.1]00442B57 |. 0FB64C11 FF |movzx ecx,byte ptr ds:[ecx+edx-0x1]00442B5C |. 0FAFCE |imul ecx,esi00442B5F |. 03D9 |add ebx,ecx ; user32.76E4690100442B61 |. 42 |inc edx00442B62 |. 48 |dec eax00442B63 |.^ 75 EF \jnz short aLoNg3x_.00442B5400442B65 |> 2B5D F8 sub ebx,[local.2]00442B68 |. 81FB 697A0000 cmp ebx,0x7A6900442B6E |. 75 04 jnz short aLoNg3x_.00442B7400442B70 |. B3 01 mov bl,0x100442B72 |. EB 06 jmp short aLoNg3x_.00442B7A
看这也是一段算法,经过运算后的值和0x7a69比较,前面分析给BL=1应该是控制OK按钮是否可用和清0的关键。
zgx:it0365经过算法运算得出的结果为:ebx=0000067C,我们用0000067C-7a69=FFFFFFFFFFFF8C13(十进制:-29677)是个负数。用这个数去注册看看
可以看到结果相等后,JNZ没跳了。直接F9看下
成功将按钮隐藏同时OK按钮也变得可用。
继续点OK按钮,断下这里
清0也失效了,说明这个软件要先隐藏清0按钮的。
点击OK按钮断到这里也有个算法:
00442BF7 |. /7C 2F jl short aLoNg3x_.00442C2800442BF9 |> |8D45 F4 /lea eax,[local.3]00442BFC |. |E8 0310FCFF |call aLoNg3x_.00403C0400442C01 |. |8D4430 FF |lea eax,dword ptr ds:[eax+esi-0x1]00442C05 |. |50 |push eax00442C06 |. |8B45 F8 |mov eax,[local.2]00442C09 |. |0FB64430 FF |movzx eax,byte ptr ds:[eax+esi-0x1]00442C0E |. |F7E8 |imul eax00442C10 |. |0FBFC0 |movsx eax,ax00442C13 |. |F7EE |imul esi00442C15 |. |B9 19000000 |mov ecx,0x1900442C1A |. |99 |cdq00442C1B |. |F7F9 |idiv ecx00442C1D |. |83C2 41 |add edx,0x4100442C20 |. |58 |pop eax ; 0018F5CC00442C21 |. |8810 |mov byte ptr ds:[eax],dl00442C23 |. |4E |dec esi00442C24 |. |85F6 |test esi,esi00442C26 |.^|75 D1 \jnz short aLoNg3x_.00442BF900442C28 |> \8B45 F4 mov eax,[local.3]00442C2B |. 8B55 FC mov edx,[local.1]00442C2E |. E8 110FFCFF call aLoNg3x_.00403B4400442C33 |. 75 17 jnz short aLoNg3x_.00442C4C
00442C28 |> \8B45 F4 mov eax,[local.3]00442C2B |. 8B55 FC mov edx,[local.1]00442C2E |. E8 110FFCFF call aLoNg3x_.00403B44
edx=00637314, (ASCII "gzx:it0365")
eax=0063732C, (ASCII "AAWOAA")
因为不相等所以跳转了。
00442C33 |. /75 17 jnz short aLoNg3x_.00442C4C00442C35 |. |8B45 FC mov eax,[local.1]00442C38 |. |8B55 F4 mov edx,[local.3]00442C3B |. |E8 040FFCFF call aLoNg3x_.00403B4400442C40 |. |75 04 jnz short aLoNg3x_.00442C4600442C42 |. |B3 01 mov bl,0x100442C44 |. |EB 06 jmp short aLoNg3x_.00442C4C
F9按钮未隐藏,无效。现在输入追踪出来的用户名试试AAWOAA
成功隐藏。说明追踪到的用户名和注册码是有效的!
经过以上分析大致了解了软件的注册流程:
1、通过用户名计算出值与0x7a69进行比较把清0功能禁用和按钮隐藏并将OK按钮可用。
2、通过上面计算得到的数值做为注册码然后运算得出用户名。一致就隐藏按钮。
关于注册机大家分析完后,参考前面文章用AI写算法代码即可。
阅读原文:https://mp.weixin.qq.com/s/KYX-Ghh4to8YmdZpolZHFA
该文章在 2025/12/11 17:56:14 编辑过