玖公子 发表于 2019-8-15 14:26

初识破解与程序(C语言控制台程序)之间的关系

本帖最后由 玖公子 于 2019-8-16 09:50 编辑

我是刚来论坛的,第一次发帖!
对版规不是很熟悉,如果发错区了,请管理大大手下留情,不要扣分,谢谢!

初识破解与程序之间的关系:
1、用VC++6.0编写一个简单的C语言程序
这个程序我们输入正确的key,就能输出成功的提示信息!

程序和源代码见附件!

2、我们将程序载入OD,停在了
0040130D >/$55            push ebp
0040130E|.8BEC          mov ebp,esp
00401310|.6A FF         push -0x1
00401312|.68 B8604000   push test01.004060B8
00401317|.68 EC2C4000   push test01.00402CEC                     ;SE 处理程序安装
0040131C|.64:A1 0000000>mov eax,dword ptr fs:
00401322|.50            push eax
00401323|.64:8925 00000>mov dword ptr fs:,esp
0040132A|.83EC 10       sub esp,0x10
0040132D|.53            push ebx
0040132E|.56            push esi
0040132F|.57            push edi
00401330|.8965 E8       mov ,esp
00401333|.FF15 04604000 call dword ptr ds:[<&KERNEL32.GetVersion>;kernel32.GetVersion
00401339|.33D2          xor edx,edx                              ;ntdll.KiFastSystemCallRet
0040133B|.8AD4          mov dl,ah
0040133D|.8915 44994000 mov dword ptr ds:,edx          ;ntdll.KiFastSystemCallRet

我们F8向下走,看到call test01.00401000
00401378|> \8365 FC 00    and ,0x0
0040137C|.E8 B4000000   call test01.00401435
00401381|.FF15 00604000 call dword ptr ds:[<&KERNEL32.GetCommand>; [GetCommandLineA
00401387|.A3 449E4000   mov dword ptr ds:,eax
0040138C|.E8 5C150000   call test01.004028ED
00401391|.A3 20994000   mov dword ptr ds:,eax
00401396|.E8 05130000   call test01.004026A0
0040139B|.E8 47120000   call test01.004025E7
004013A0|.E8 7E050000   call test01.00401923
004013A5|.A1 54994000   mov eax,dword ptr ds:
004013AA|.A3 58994000   mov dword ptr ds:,eax
004013AF|.50            push eax
004013B0|.FF35 4C994000 push dword ptr ds:
004013B6|.FF35 48994000 push dword ptr ds:
004013BC|.E8 3FFCFFFF   call test01.00401000

00401000我们知道这是code(代码)段,004013BC这一行F7进去,来到了
00401000/$E8 BB000000   /call test01.004010C0
00401005|.85C0          |test eax,eax
00401007|.75 0F         |jnz short test01.00401018
00401009|.68 44704000   |push test01.00407044                  ;很遗憾,失败了! \n
0040100E|.E8 7F020000   |call test01.00401292
00401013|.83C4 04       |add esp,0x4
00401016|.^ EB E8         \jmp short test01.00401000
00401018|>68 30704000   push test01.00407030                     ;恭喜你,成功了! \n

很明显,这里有一个判断语句,只要将jnz改成jmp,将程序保存出去,就破解成功了!

3.我们在00401000这个call继续F7进去,看到了
004010C0/$83EC 14       sub esp,0x14
004010C3|.57            push edi
004010C4|.68 68704000   push test01.00407068                     ;请输入一个key:\n
004010C9|.E8 C4010000   call test01.00401292
004010CE|.8D4424 08   lea eax,dword ptr ss:
004010D2|.50            push eax
004010D3|.E8 EB010000   call test01.004012C3
004010D8|.8D7C24 0C   lea edi,dword ptr ss:
004010DC|.83C9 FF       or ecx,-0x1
004010DF|.33C0          xor eax,eax
004010E1|.F2:AE         repne scas byte ptr es:
004010E3|.F7D1          not ecx                                  ;test01.004070F0
004010E5|.49            dec ecx                                  ;test01.004070F0
004010E6|.51            push ecx                                 ;test01.004070F0
004010E7|.8D4C24 10   lea ecx,dword ptr ss:
004010EB|.51            push ecx                                 ;test01.004070F0
004010EC|.E8 5FFFFFFF   call test01.00401050
004010F1|.83C4 10       add esp,0x10
004010F4|.5F            pop edi                                  ;test01.00401005
004010F5|.83C4 14       add esp,0x14
004010F8\.C3            retn

这里有三个call,后面retn就回到了00401005比较的地方了!第一个call应该是获取用户输入的函数,
我们从004010D3第二个callF7进去看看!
004012C3/$56            push esi
004012C4|.57            push edi
004012C5|.8B7C24 0C   mov edi,dword ptr ss:
004012C9|.8BF7          mov esi,edi
004012CB|>FF0D 84704000 /dec dword ptr ds:
004012D1|.78 10         |js short test01.004012E3
004012D3|.A1 80704000   |mov eax,dword ptr ds:         ;99\n\n\n
004012D8|.0FB600      |movzx eax,byte ptr ds:
004012DB|.FF05 80704000 |inc dword ptr ds:             ;test01.00409E60
004012E1|.EB 0B         |jmp short test01.004012EE
004012E3|>68 80704000   |push test01.00407080                  ;99\n\n\n
004012E8|.E8 13FEFFFF   |call test01.00401100
004012ED|.59            |pop ecx                                 ;test01.004010D8
004012EE|>83F8 0A       |cmp eax,0xA
004012F1|.74 12         |je short test01.00401305
004012F3|.83F8 FF       |cmp eax,-0x1
004012F6|.74 05         |je short test01.004012FD
004012F8|.8806          |mov byte ptr ds:,al
004012FA|.46            |inc esi
004012FB|.^ EB CE         \jmp short test01.004012CB
004012FD|>3BF7          cmp esi,edi
004012FF|.75 04         jnz short test01.00401305
00401301|.33FF          xor edi,edi
00401303|.EB 03         jmp short test01.00401308
00401305|>8026 00       and byte ptr ds:,0x0
00401308|>8BC7          mov eax,edi
0040130A|.5F            pop edi                                  ;test01.004010D8
0040130B|.5E            pop esi                                  ;test01.004010D8
0040130C\.C3            retn

从004012CB这里到004012FB这里就是循环加密字符串的地方,004012E8这个call我们F7进去,
F8向下继续走,看到00401148|.E8 93040000   call test01.004015E0这一行再次F7进去。
继续F8,发现00401664这个callF8后,程序跑起来了
00401664|.FF15 20604000 call dword ptr ds:[<&KERNEL32.ReadFile>] ; \ReadFile

我们切换到程序,输入几个字符,继续向下F8,观察这段代码!
004016E7|> /8B45 10       /mov eax,                         ;test01.00409E60
004016EA|. |8A00          |mov al,byte ptr ds:
004016EC|. |3C 1A         |cmp al,0x1A
004016EE|. |0F84 AE000000 |je test01.004017A2
004016F4|. |3C 0D         |cmp al,0xD
004016F6|. |74 0B         |je short test01.00401703
004016F8|. |8807          |mov byte ptr ds:,al
004016FA|. |47            |inc edi                                 ;test01.00409E60
004016FB|. |FF45 10       |inc                            ;test01.00409E60
004016FE|. |E9 91000000   |jmp test01.00401794
00401703|> |49            |dec ecx                                 ;test01.00409E70
00401704|. |394D 10       |cmp ,ecx                         ;test01.00409E70
00401707|. |73 18         |jnb short test01.00401721
00401709|. |8B45 10       |mov eax,                         ;test01.00409E60
0040170C|. |40            |inc eax                                 ;test01.00409E60
0040170D|. |8038 0A       |cmp byte ptr ds:,0xA
00401710|. |75 06         |jnz short test01.00401718
00401712|. |8345 10 02    |add ,0x2
00401716|. |EB 5E         |jmp short test01.00401776
00401718|> |C607 0D       |mov byte ptr ds:,0xD
0040171B|. |47            |inc edi                                 ;test01.00409E60
0040171C|. |8945 10       |mov ,eax                         ;test01.00409E60
0040171F|. |EB 73         |jmp short test01.00401794
00401721|> |8D45 F4       |lea eax,
00401724|. |6A 00         |push 0x0                              ; /pOverlapped = NULL
00401726|. |50            |push eax                              ; |pBytesRead = test01.00409E60
00401727|. |FF45 10       |inc                            ; |test01.00409E60
0040172A|. |8D45 FF       |lea eax,dword ptr ss:          ; |
0040172D|. |6A 01         |push 0x1                              ; |BytesToRead = 0x1
0040172F|. |50            |push eax                              ; |Buffer = test01.00409E60
00401730|. |8B03          |mov eax,dword ptr ds:            ; |
00401732|. |FF3430      |push dword ptr ds:             ; |hFile = 6F6C2049
00401735|. |FF15 20604000 |call dword ptr ds:[<&KERNEL32.ReadFile>>; \ReadFile
0040173B|. |85C0          |test eax,eax                            ;test01.00409E60
0040173D|. |75 0A         |jnz short test01.00401749
0040173F|. |FF15 1C604000 |call dword ptr ds:[<&KERNEL32.GetLastEr>; [GetLastError
00401745|. |85C0          |test eax,eax                            ;test01.00409E60
00401747|. |75 47         |jnz short test01.00401790
00401749|> |837D F4 00    |cmp ,0x0
0040174D|. |74 41         |je short test01.00401790
0040174F|. |8B03          |mov eax,dword ptr ds:
00401751|. |F64430 04 48|test byte ptr ds:,0x48
00401756|. |74 13         |je short test01.0040176B
00401758|. |8A45 FF       |mov al,byte ptr ss:
0040175B|. |3C 0A         |cmp al,0xA
0040175D|. |74 17         |je short test01.00401776
0040175F|. |C607 0D       |mov byte ptr ds:,0xD
00401762|. |8B0B          |mov ecx,dword ptr ds:
00401764|. |47            |inc edi                                 ;test01.00409E60
00401765|. |884431 05   |mov byte ptr ds:,al
00401769|. |EB 29         |jmp short test01.00401794
0040176B|> |3B7D 0C       |cmp edi,                         ;test01.00409E60
0040176E|. |75 0B         |jnz short test01.0040177B
00401770|. |807D FF 0A    |cmp byte ptr ss:,0xA
00401774|. |75 05         |jnz short test01.0040177B
00401776|> |C607 0A       |mov byte ptr ds:,0xA
00401779|. |EB 18         |jmp short test01.00401793
0040177B|> |6A 01         |push 0x1
0040177D|. |6A FF         |push -0x1
0040177F|. |FF75 08       |push
00401782|. |E8 E4180000   |call test01.0040306B
00401787|. |83C4 0C       |add esp,0xC
0040178A|. |807D FF 0A    |cmp byte ptr ss:,0xA
0040178E|. |74 04         |je short test01.00401794
00401790|> |C607 0D       |mov byte ptr ds:,0xD
00401793|> |47            |inc edi                                 ;test01.00409E60
00401794|> |8B4D F8       |mov ecx,                     ;test01.00409E70
00401797|. |394D 10       |cmp ,ecx                         ;test01.00409E70
0040179A|.^\0F82 47FFFFFF \jb test01.004016E7

核心加密代码如下(这段代码循环对字符串进行处理):
004016E7|> /8B45 10       /mov eax,                         ;test01.00409E65
004016EA|. |8A00          |mov al,byte ptr ds:
004016EC|. |3C 1A         |cmp al,0x1A
004016EE|. |0F84 AE000000 |je test01.004017A2
004016F4|. |3C 0D         |cmp al,0xD
004016F6|. |74 0B         |je short test01.00401703
004016F8|. |8807          |mov byte ptr ds:,al
004016FA|. |47            |inc edi                                 ;test01.00409E65
004016FB|. |FF45 10       |inc                            ;test01.00409E65

将我们输入的字符串赋值给eax,每次加1。这里需要百度一下inc指令的作用!
加一指令inc
inc a 相当于 add a,1 //i++
优点 速度比sub指令快,占用空间小
这条指令执行结果影响AF、OF、PF、SF、ZF标志位,但不影响CF进位标志位。

4.找到了加密算法,我们接着去找加密后的字符串,肯定是有个比较,才能判断是否跳转成功or失败!
第3步刚开始的时候有三个call,第二个call是加密字符串,第三个call肯定是进行了比较,因为retn后
就直接跳转到成功or失败了!
我们Ctrl+G输入第三个call的地址004010EC,F4运行过来(切到程序程序窗口,输入一串字母,停在了这里),
然后F7进去,看到
00401060|> /8A1C08      /mov bl,byte ptr ds:
00401063|. |FEC3          |inc bl
00401065|. |881C08      |mov byte ptr ds:,bl
00401068|. |40            |inc eax
00401069|. |3BC2          |cmp eax,edx
0040106B|.^\7C F3         \jl short test01.00401060

在这里我们输入的字符串一个一个就循环加密完成了!

0040106D|> \BE 58704000   mov esi,test01.00407058                  ;J!mpwf!63qpkjf
这个J!mpwf!63qpkjf就是要比较的字符串!

00401074|> /8A10          /mov dl,byte ptr ds:
00401076|. |8A1E          |mov bl,byte ptr ds:
00401078|. |8ACA          |mov cl,dl
0040107A|. |3AD3          |cmp dl,bl
0040107C|. |75 28         |jnz short test01.004010A6
0040107E|. |84C9          |test cl,cl
00401080|. |74 16         |je short test01.00401098
00401082|. |8A50 01       |mov dl,byte ptr ds:
00401085|. |8A5E 01       |mov bl,byte ptr ds:
00401088|. |8ACA          |mov cl,dl
0040108A|. |3AD3          |cmp dl,bl
0040108C|. |75 18         |jnz short test01.004010A6
0040108E|. |83C0 02       |add eax,0x2
00401091|. |83C6 02       |add esi,0x2
00401094|. |84C9          |test cl,cl
00401096|.^\75 DC         \jnz short test01.00401074
这一段代码就是在将我们输入的字符串加密后与J!mpwf!63qpkjf这个字符串逐个比较!

如果相等,执行下面的汇编代码
00401098|> \33C0          xor eax,eax
0040109A|.33C9          xor ecx,ecx
0040109C|.85C0          test eax,eax
0040109E|.0f94c1      sete cl
004010A1|.5E            pop esi                                  ;test01.004013C1
004010A2|.8BC1          mov eax,ecx
004010A4|.5B            pop ebx                                  ;test01.004013C1
004010A5|.C3            retn

如果不相等,执行下面的汇编代码
004010A6|> \1BC0          sbb eax,eax
004010A8|.5E            pop esi                                  ;test01.004013C1
004010A9|.83D8 FF       sbb eax,-0x1
004010AC|.33C9          xor ecx,ecx
004010AE|.85C0          test eax,eax
004010B0|.0f94c1      sete cl
004010B3|.8BC1          mov eax,ecx
004010B5|.5B            pop ebx                                  ;test01.004013C1
004010B6\.C3            retn

然后就返回到00401000这一行,执行test eax,eax语句,决定输出成功or失败!


至此,程序分析完毕,如有认识不到位的地方,请大牛们指正!

源程序和代码下载的地址:https://www.lanzouj.com/i5l2laj

璐璐诺 发表于 2019-8-16 02:52

这个好的教程怎么没人回复 赞个

bluerabbit 发表于 2019-8-16 08:12

谢谢楼主分享

weidian 发表于 2019-8-16 08:43

厉害厉害,谢谢楼主分享

学士天下 发表于 2019-8-16 08:45

感谢大神分享,点赞!!!

top倷 发表于 2019-8-16 09:48

支持一下

侧耳i 发表于 2019-8-16 11:42

感谢!!

冰雪冬樱250 发表于 2019-8-16 14:15

厉害厉害,谢谢楼主分享

forrest888 发表于 2019-8-16 15:28

支持一下

Aksa 发表于 2019-8-16 21:39

看到这个才发现自己差了很多呀,真的很厉害,{:1_893:}
页: [1] 2
查看完整版本: 初识破解与程序(C语言控制台程序)之间的关系