好友
阅读权限 30
听众
最后登录 1970-1-1
玖公子
发表于 2019-8-19 13:01
本帖最后由 玖公子 于 2019-8-19 13:07 编辑
再识破解 与程序(C语言控制台程序)之间的关系
前言:楼主看了好多大佬的cm,我一个都不会破解 ,所以,自己写了一个c语言控制台程序,
然后发到https://www.52pojie.cn/thread-1009793-1-1.html 这个区了!
程序比较简单,很多坛友基本连我的程序源码都给复原了!
1.这一次楼主不再使用VC 6.0编译器了,使用的是vs 2010编译器!程序由c语言编写,
当然了,还是一个控制台程序,不过给它加了一个弹窗功能(MessageBox函数)!
接下来我们就开始分析了,文章的程序和源代码见文章末尾链接!
2.将程序载入OD,停留在
[Asm] 纯文本查看 复制代码
004014AC > $ E8 78040000 call 玖公子练.00401929
004014B1 .^ E9 B3FDFFFF jmp 玖公子练.00401269
004014B6 > 8BFF mov edi,edi
004014B8 /. 55 push ebp
004014B9 |. 8BEC mov ebp,esp
004014BB |. 81EC 28030000 sub esp,0x328
我们F8向下单步走,经过那个jmp来到了
[Asm] 纯文本查看 复制代码
00401269 > /6A 10 push 0x10
0040126B . |68 98224000 push 玖公子练.00402298
00401270 . |E8 0B060000 call 玖公子练.00401880
00401275 . |33DB xor ebx,ebx
00401277 . |391D 80334000 cmp dword ptr ds:[0x403380],ebx
0040127D . |75 0B jnz short 玖公子练.0040128A
0040127F . |53 push ebx
00401280 . |53 push ebx
00401281 . |6A 01 push 0x1
00401283 . |53 push ebx
00401284 . |FF15 2C204000 call dword ptr ds:[<&KERNEL32.HeapSetInf>; kernel32.HeapSetInformation
我们继续F8向下走,来到了
[Asm] 纯文本查看 复制代码
00401367 > \A1 1C304000 mov eax,dword ptr ds:[0x40301C]
0040136C . 8B0D 84204000 mov ecx,dword ptr ds:[<&MSVCR100.__inite>; msvcr100.__initenv
00401372 . 8901 mov dword ptr ds:[ecx],eax
00401374 . FF35 1C304000 push dword ptr ds:[0x40301C]
0040137A . FF35 20304000 push dword ptr ds:[0x403020]
00401380 . FF35 18304000 push dword ptr ds:[0x403018]
00401386 . E8 A5FDFFFF call 玖公子练.00401130
在00401386这个call F8程序直接跑飞,那我们记下这个地址,重新载入程序,Ctrl+G输入00401386,
回车,F4运行到这里,然后F7跟进这个Call,来到了
[Asm] 纯文本查看 复制代码
00401130 /$ 55 push ebp
00401131 |. 8BEC mov ebp,esp
00401133 |. 83EC 2C sub esp,0x2C
00401136 |. A1 00304000 mov eax,dword ptr ds:[0x403000]
0040113B |. 33C5 xor eax,ebp
0040113D |. 8945 FC mov [local.1],eax
00401140 |. 56 push esi
00401141 |. 57 push edi ; 玖公子练.00403374
00401142 |. 8D7D E8 lea edi,[local.6]
00401145 |. E8 76FFFFFF call 玖公子练.004010C0
0040114A |. 8B35 A8204000 mov esi,dword ptr ds:[<&MSVCR100.printf>>; msvcr100.printf
00401150 |. 8BC7 mov eax,edi ; 玖公子练.00403374
00401152 |. 50 push eax ; /<%s> = "/="
00401153 |. 68 3C214000 push 玖公子练.0040213C ; |您当前用户码为:%s\n
00401158 |. FFD6 call esi ; \printf
0040115A |. 68 50214000 push 玖公子练.00402150 ; 请输入您的16位激活码:
0040115F |. FFD6 call esi
00401161 |. 8D4D D4 lea ecx,[local.11]
00401164 |. 51 push ecx ; /s = offset msvcr100.__initenv
00401165 |. FF15 A4204000 call dword ptr ds:[<&MSVCR100.gets>] ; \gets
0040116B |. 8BC7 mov eax,edi ; 玖公子练.00403374
0040116D |. 83C4 10 add esp,0x10
00401170 |. 8D50 01 lea edx,dword ptr ds:[eax+0x1]
00401173 |> 8A08 /mov cl,byte ptr ds:[eax]
00401175 |. 40 |inc eax
00401176 |. 84C9 |test cl,cl
00401178 |.^ 75 F9 \jnz short 玖公子练.00401173
0040117A |. 2BC2 sub eax,edx
0040117C |. 50 push eax
0040117D |. 8D55 E8 lea edx,[local.6]
00401180 |. 52 push edx
00401181 |. E8 7AFEFFFF call 玖公子练.00401000
00401186 |. 83C4 08 add esp,0x8
00401189 |. 8D4D D4 lea ecx,[local.11]
0040118C |. 8D45 E8 lea eax,[local.6]
0040118F |. 90 nop
00401190 |> 8A10 /mov dl,byte ptr ds:[eax]
00401192 |. 3A11 |cmp dl,byte ptr ds:[ecx]
00401194 |. 75 1A |jnz short 玖公子练.004011B0
00401196 |. 84D2 |test dl,dl
00401198 |. 74 12 |je short 玖公子练.004011AC
0040119A |. 8A50 01 |mov dl,byte ptr ds:[eax+0x1]
0040119D |. 3A51 01 |cmp dl,byte ptr ds:[ecx+0x1]
004011A0 |. 75 0E |jnz short 玖公子练.004011B0
004011A2 |. 83C0 02 |add eax,0x2
004011A5 |. 83C1 02 |add ecx,0x2
004011A8 |. 84D2 |test dl,dl
004011AA |.^ 75 E4 \jnz short 玖公子练.00401190
004011AC |> 33C0 xor eax,eax
004011AE |. EB 05 jmp short 玖公子练.004011B5
004011B0 |> 1BC0 sbb eax,eax
004011B2 |. 83D8 FF sbb eax,-0x1
004011B5 |> 85C0 test eax,eax
004011B7 |. 75 14 jnz short 玖公子练.004011CD
004011B9 |. 50 push eax ; /Style = 0x8|MB_ICONHAND|MB_DEFBUTTON3|MB_TASKMODAL|3D0C80
004011BA |. 68 68214000 push 玖公子练.00402168 ; |玖公子
004011BF |. 68 70214000 push 玖公子练.00402170 ; |恭喜你,成功了!
004011C4 |. 50 push eax ; |hOwner = 003D2E98
004011C5 |. FF15 BC204000 call dword ptr ds:[<&USER32.MessageBoxW>>; \MessageBoxW
004011CB |. EB 22 jmp short 玖公子练.004011EF
004011CD |> 6A 30 push 0x30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004011CF |. 68 68214000 push 玖公子练.00402168 ; |玖公子
004011D4 |. 68 84214000 push 玖公子练.00402184 ; |激活码错误,程序退出!
004011D9 |. 6A 00 push 0x0 ; |hOwner = NULL
004011DB |. FF15 BC204000 call dword ptr ds:[<&USER32.MessageBoxW>>; \MessageBoxW
004011E1 |. 8D45 E8 lea eax,[local.6]
004011E4 |. 50 push eax
004011E5 |. 68 9C214000 push 玖公子练.0040219C ; 正确的激活码是:%s\n
004011EA |. FFD6 call esi
004011EC |. 83C4 08 add esp,0x8
004011EF |> 68 B0214000 push 玖公子练.004021B0 ; /pause
004011F4 |. FF15 A0204000 call dword ptr ds:[<&MSVCR100.system>] ; \system
004011FA |. 8B4D FC mov ecx,[local.1]
004011FD |. 83C4 04 add esp,0x4
00401200 |. 5F pop edi ; 玖公子练.0040138B
00401201 |. 33CD xor ecx,ebp
00401203 |. 33C0 xor eax,eax
00401205 |. 5E pop esi ; 玖公子练.0040138B
00401206 |. E8 04000000 call 玖公子练.0040120F
0040120B |. 8BE5 mov esp,ebp
0040120D |. 5D pop ebp ; 玖公子练.0040138B
0040120E \. C3 retn
根据后面的注释,我们知道这是生成用户码,不用管,继续F8向下走!
看到程序00401165在这个call这里跑飞了
[Asm] 纯文本查看 复制代码
00401165 |. FF15 A4204000 call dword ptr ds:[<&MSVCR100.gets>] ; \gets
0040116B |. 8BC7 mov eax,edi
0040116D |. 83C4 10 add esp,0x10
00401170 |. 8D50 01 lea edx,dword ptr ds:[eax+0x1]
00401173 |> 8A08 /mov cl,byte ptr ds:[eax]
00401175 |. 40 |inc eax
00401176 |. 84C9 |test cl,cl
00401178 |.^ 75 F9 \jnz short 玖公子练.00401173
不慌,我们随便输入一个激活码,发现程序又断了下来,而且并没有弹出错误对话框!
我们继续F8向下走,来到了
[Asm] 纯文本查看 复制代码
00401181 |. E8 7AFEFFFF call 玖公子练.00401000
00401186 |. 83C4 08 add esp,0x8
00401189 |. 8D4D D4 lea ecx,[local.11]
0040118C |. 8D45 E8 lea eax,[local.6]
0040118F |. 90 nop
看到没,这个call 00401000,上一篇帖子https://www.52pojie.cn/thread-1008818-1-1.html 已经介绍了
这是code(代码段),开始执行我们的代码了!所以这里我们F7跟进去看看
[Asm] 纯文本查看 复制代码
00401000 /$ 55 push ebp
00401001 |. 8BEC mov ebp,esp
00401003 |. 83EC 40 sub esp,0x40
00401006 |. A1 00304000 mov eax,dword ptr ds:[0x403000]
0040100B |. 33C5 xor eax,ebp
0040100D |. 8945 FC mov [local.1],eax
00401010 |. 8B45 08 mov eax,[arg.1]
00401013 |. 56 push esi ; msvcr100.printf
00401014 |. 57 push edi
00401015 |. B9 0D000000 mov ecx,0xD
0040101A |. BE 04214000 mov esi,玖公子练.00402104 ; QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm
QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm这里这个字符串我们要留意,很可能是加密的密钥!
然后我们继续向下F8观察
[Asm] 纯文本查看 复制代码
00401036 |> /8A1430 mov dl,byte ptr ds:[eax+esi]
00401039 |. 80FA 30 cmp dl,0x30 ; Switch (cases 30..39)
0040103C |. 7C 14 jl short 玖公子练.00401052
0040103E |. 80FA 39 cmp dl,0x39
00401041 |. 7F 0F jg short 玖公子练.00401052
00401043 |. 75 06 jnz short 玖公子练.0040104B
00401045 |. C60430 30 mov byte ptr ds:[eax+esi],0x30 ; Case 39 ('9') of switch 00401039
00401049 |. EB 33 jmp short 玖公子练.0040107E
0040104B |> FEC2 inc dl
0040104D |. 881430 mov byte ptr ds:[eax+esi],dl
00401050 |. EB 2C jmp short 玖公子练.0040107E
00401052 |> 8D45 C4 lea eax,[local.15] ; Default case of switch 00401039
00401055 |. 33C9 xor ecx,ecx
00401057 |. 8D78 01 lea edi,dword ptr ds:[eax+0x1]
0040105A |. 8D9B 00000000 lea ebx,dword ptr ds:[ebx]
00401060 |> 8A18 /mov bl,byte ptr ds:[eax]
00401062 |. 40 |inc eax
00401063 |. 84DB |test bl,bl
00401065 |.^ 75 F9 \jnz short 玖公子练.00401060
00401067 |. 2BC7 sub eax,edi
00401069 |. 74 10 je short 玖公子练.0040107B
0040106B |. EB 03 jmp short 玖公子练.00401070
0040106D | 8D49 00 lea ecx,dword ptr ds:[ecx]
00401070 |> 3A540D C4 /cmp dl,byte ptr ss:[ebp+ecx-0x3C]
00401074 |. 74 24 |je short 玖公子练.0040109A
00401076 |. 41 |inc ecx
00401077 |. 3BC8 |cmp ecx,eax
00401079 |.^ 72 F5 \jb short 玖公子练.00401070
0040107B |> 8B45 C0 mov eax,[local.16]
0040107E |> 46 inc esi ; Cases 30 ('0'),31 ('1'),32 ('2'),33 ('3'),34 ('4'),35 ('5'),36 ('6'),37 ('7'),38 ('8') of switch 00401039
0040107F |. 3B75 0C cmp esi,[arg.2]
00401082 |.^ 7C B2 jl short 玖公子练.00401036
这一段代码我们在单步跟的时候,注意右边的寄存器窗口,可以发现它是把我们的用户码push压栈,然后使用
我们发现这个应该是比较数字,然后里面有inc指令(加一指令),那么我们猜测这里是把数字全部加1处理!
处理完后,我们就从00401074 这里跳转到了0040109A 这一行,我们继续F8单步到0040109B这一行,看到
[Asm] 纯文本查看 复制代码
0040109B |. 3BC8 cmp ecx,eax
0040109D |. 8B45 C0 mov eax,[local.16]
004010A0 |. 75 06 jnz short 玖公子练.004010A8
004010A2 |. C60430 51 mov byte ptr ds:[eax+esi],0x51
004010A6 |.^ EB D6 jmp short 玖公子练.0040107E
004010A8 |> 8A540D C5 mov dl,byte ptr ss:[ebp+ecx-0x3B]
004010AC |. 881430 mov byte ptr ds:[eax+esi],dl
004010AF \.^ EB CD jmp short 玖公子练.0040107E
又是一个比较,我们再按一次F8,观察一下信息窗口!
堆栈 ss:[0012FEF8]=0012FF64, (ASCII "GB0QNZ4PIF8LPO4K")
eax=00000033
很明显还是对我们的用户码进行处理!
我们单步到这一行004010A8 |> \8A540D C5 mov dl,byte ptr ss:[ebp+ecx-0x3B]
再看信息窗口:
堆栈 ss:[0012FF0B]=48 ('H')
dl=47 ('G')
跳转来自 004010A0
这是将dl的值从G修改为H,而G是我们用户码的第一个字母,我们再来看一下QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm
这串字符,从G到H向右挪了一位,我们继续F8,我们看004010AF \.^\EB CD jmp short 玖公子练.0040107E这一行,跳到了
[Asm] 纯文本查看 复制代码
0040107E |> 46 inc esi ; Cases 30 ('0'),31 ('1'),32 ('2'),33 ('3'),34 ('4'),35 ('5'),36 ('6'),37 ('7'),38 ('8') of switch 00401039
0040107F |. |3B75 0C cmp esi,[arg.2]
00401082 |.^|7C B2 jl short 玖公子练.00401036
然后有一个inc指令,执行了加1操作,那么这个程序肯定就是将字符串加1,使用密钥,向右移动一个,数字直接加1。
我们运行完后,经过00401099 这个retn回到了
[Asm] 纯文本查看 复制代码
00401186 |. 83C4 08 add esp,0x8
00401189 |. 8D4D D4 lea ecx,[local.11]
0040118C |. 8D45 E8 lea eax,[local.6]
0040118F |. 90 nop
这两个lea传送指令,我们观察信息窗口:
堆栈地址=0012FF50, (ASCII "HGVF5DFG5CVB8KJN2")
ecx=0012FF50, (ASCII "HGVF5DFG5CVB8KJN2")
00401189第一句就是把我输入的激活码传送过来给了ecx
堆栈地址=0012FF64, (ASCII "HN1WMX5AOG9ZAP5L")
eax=00000001
0040118C这一句就是将加密后的字符串(真正的激活码)传送给eax
我们继续F8单步向下走,看到
[Asm] 纯文本查看 复制代码
00401190 |> /8A10 /mov dl,byte ptr ds:[eax]
00401192 |. |3A11 |cmp dl,byte ptr ds:[ecx]
00401194 |. |75 1A |jnz short 玖公子练.004011B0
00401196 |. |84D2 |test dl,dl
00401198 |. |74 12 |je short 玖公子练.004011AC
0040119A |. |8A50 01 |mov dl,byte ptr ds:[eax+0x1]
0040119D |. |3A51 01 |cmp dl,byte ptr ds:[ecx+0x1]
004011A0 |. |75 0E |jnz short 玖公子练.004011B0
004011A2 |. |83C0 02 |add eax,0x2
004011A5 |. |83C1 02 |add ecx,0x2
004011A8 |. |84D2 |test dl,dl
004011AA |.^\75 E4 \jnz short 玖公子练.00401190
这一串代码就是在比较我们输入的激活码与真正的激活码是否相等!
我们继续F8,看下面这一片代码
[Asm] 纯文本查看 复制代码
004011B5 |> \85C0 test eax,eax
004011B7 |. 75 14 jnz short 玖公子练.004011CD
004011B9 |. 50 push eax ; /Style = 0xF|70|300|3000|MB_NOFOCUS|FFFF4C80
004011BA |. 68 68214000 push 玖公子练.00402168 ; |玖公子
004011BF |. 68 70214000 push 玖公子练.00402170 ; |恭喜你,成功了!
004011C4 |. 50 push eax ; |hOwner = FFFFFFFF
004011C5 |. FF15 BC204000 call dword ptr ds:[<&USER32.MessageBoxW>>; \MessageBoxW
004011CB |. EB 22 jmp short 玖公子练.004011EF
004011CD |> 6A 30 push 0x30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004011CF |. 68 68214000 push 玖公子练.00402168 ; |玖公子
004011D4 |. 68 84214000 push 玖公子练.00402184 ; |激活码错误,程序退出!
004011D9 |. 6A 00 push 0x0 ; |hOwner = NULL
004011DB |. FF15 BC204000 call dword ptr ds:[<&USER32.MessageBoxW>>; \MessageBoxW
004011E1 |. 8D45 E8 lea eax,[local.6]
004011E4 |. 50 push eax
004011E5 |. 68 9C214000 push 玖公子练.0040219C ; 正确的激活码是:%s\n
004011EA |. FFD6 call esi ; msvcr100.printf
004011EC |. 83C4 08 add esp,0x8
004011EF |> 68 B0214000 push 玖公子练.004021B0 ; /pause
004011F4 |. FF15 A0204000 call dword ptr ds:[<&MSVCR100.system>] ; \system
004011FA |. 8B4D FC mov ecx,[local.1]
004011FD |. 83C4 04 add esp,0x4
00401200 |. 5F pop edi ; 玖公子练.00403374
00401201 |. 33CD xor ecx,ebp
00401203 |. 33C0 xor eax,eax
00401205 |. 5E pop esi ; 玖公子练.00403374
00401206 |. E8 04000000 call 玖公子练.0040120F
0040120B |. 8BE5 mov esp,ebp
0040120D |. 5D pop ebp ; 玖公子练.00403374
0040120E \. C3 retn
通过观察我们知道,004011B7这个jnz跳转只要不实现,就会弹出成功窗口!
我们把这两句nop掉保存出去,随便输入一个激活码,发现程序确实不会弹出错误提示框,
但是也没有弹出正确的提示框!
3.我们观察一下,发现弹错误对话框时hOwner = NULL,而此时,我们的成功对话框不是这个值,
所以这里不会弹窗!我们还记得这两句吧
00401189 |. 8D4D D4 lea ecx,[local.11] //我们输入的激活码
0040118C |. 8D45 E8 lea eax,[local.6] //正确的激活码
右键删除分析,看到
00401189 8D4D D4 lea ecx,dword ptr ss:[ebp-0x2C]
0040118C 8D45 E8 lea eax,dword ptr ss:[ebp-0x18]
我么只需要将第一行改成 lea ecx,dword ptr ss:[ebp-0x18]这个,这样就是把正确的激活码传递给了ecx,
因此,后面不管怎么比较,两个激活码绝对相等,程序成功破解了!
楼主比较菜,不会用IDA ,只会OD的基本用法,所以全程F8单步跟!
据大佬说,可以直接搜索中文字符串就可以到达我最后的那几行代码,
还有的说,可以直接Ctrl+G到00401000开始跟!
楼主后面会再接再厉,继续学习破解技术!
PS:楼主刚学c语言不久,以前没学过编程,也没接触过破解,分析的不对的地方欢迎大佬们指正,
萌新一枚,希望能从大佬们这里偷师!
源程序和代码下载的地址:https://www.lanzouj.com/i5nsmmf
免费评分
查看全部评分