zbnysjwsnd8 发表于 2017-7-29 10:42

一个娱乐CM的爆破 + 追码

本帖最后由 zbnysjwsnd8 于 2017-7-29 23:04 编辑

CM地址:http://www.52pojie.cn/thread-629598-1-1.html
这篇文章不好写 而且我还是小菜 哪里有错了请大牛们指出。调试前先预测代码的实现,这是个好习惯。若预测有误也没关系,从头开始调试即可。但若是有幸预测正确,则可以节省大量调试时间。
                                                                                                                                                                                 -------《逆向工程·核心原理》
0x0 程序截图

0x1 注册码的存放方式
OD载入 输入假码 然后给GetWindowTextA下断点。

然后执行到4050C1处。观察一下eax寄存器:

eax存放我刚刚输入的假码的地址。然后 程序将我刚刚输入的假码的地址放在了中004050C1|.8945 F8       MOV , EAX;将注册码保存到中程序又取出注册码 然后复制到剪辑板中.004050D4|> \68 04000080   PUSH 0x80000004
004050D9|.6A 00         PUSH 0x0
004050DB|.8B45 F8       MOV EAX,                      ;取出注册码
004050DE|.85C0          TEST EAX, EAX
004050E0|.75 05         JNZ SHORT 004050E7
004050E2|.B8 5FE14200   MOV EAX, 0042E15F
004050E7|>50            PUSH EAX
004050E8|.68 01000000   PUSH 0x1
004050ED|.BB C8020000   MOV EBX, 0x2C8
004050F2|.E8 19520100   CALL 0041A310                     ;拷贝到剪辑板

0041A310/$55            PUSH EBP                                             ;置剪辑板文本
0041A311|.56            PUSH ESI                                             ;CrackMe.<ModuleEntryPoint>
0041A312|.8B7424 10   MOV ESI, DWORD PTR SS:
0041A316|.33ED          XOR EBP, EBP
0041A318|.85F6          TEST ESI, ESI                                          ;CrackMe.<ModuleEntryPoint>
0041A31A|.74 77         JE SHORT 0041A393
0041A31C|.55            PUSH EBP                                             ; /hWnd = 0019FF94
0041A31D|.FF15 44C24100 CALL DWORD PTR DS:[<&USER32.OpenClipboard>]            ; \OpenClipboard
0041A323|.85C0          TEST EAX, EAX
0041A325|.74 6C         JE SHORT 0041A393
0041A327|.53            PUSH EBX
0041A328|.57            PUSH EDI                                             ;CrackMe.<ModuleEntryPoint>
0041A329|.FF15 4CC24100 CALL DWORD PTR DS:[<&USER32.EmptyClipboard>]         ; [EmptyClipboard
0041A32F|.8BFE          MOV EDI, ESI                                           ;CrackMe.<ModuleEntryPoint>
0041A331|.83C9 FF       OR ECX, 0xFFFFFFFF
0041A334|.33C0          XOR EAX, EAX
0041A336|.F2:AE         REPNE SCAS BYTE PTR ES:
0041A338|.F7D1          NOT ECX                                                ;CrackMe.<ModuleEntryPoint>
0041A33A|.51            PUSH ECX                                             ; /MemSize = 401000 (4198400.)
0041A33B|.6A 42         PUSH 0x42                                              ; |Flags = GHND
0041A33D|.FF15 B8C04100 CALL DWORD PTR DS:[<&KERNEL32.GlobalAlloc>]            ; \GlobalAlloc
0041A343|.8BD8          MOV EBX, EAX
0041A345|.85DB          TEST EBX, EBX
0041A347|.74 3D         JE SHORT 0041A386
0041A349|.53            PUSH EBX                                             ; /hMem = 002D4000
0041A34A|.FF15 B4C04100 CALL DWORD PTR DS:[<&KERNEL32.GlobalLock>]             ; \GlobalLock
0041A350|.8BD0          MOV EDX, EAX
0041A352|.8BFE          MOV EDI, ESI                                           ;CrackMe.<ModuleEntryPoint>
0041A354|.83C9 FF       OR ECX, 0xFFFFFFFF
0041A357|.33C0          XOR EAX, EAX
0041A359|.F2:AE         REPNE SCAS BYTE PTR ES:
0041A35B|.F7D1          NOT ECX                                                ;CrackMe.<ModuleEntryPoint>
0041A35D|.2BF9          SUB EDI, ECX                                           ;CrackMe.<ModuleEntryPoint>
0041A35F|.53            PUSH EBX                                             ; /hMem = 002D4000
0041A360|.8BC1          MOV EAX, ECX                                           ; |CrackMe.<ModuleEntryPoint>
0041A362|.8BF7          MOV ESI, EDI                                           ; |CrackMe.<ModuleEntryPoint>
0041A364|.8BFA          MOV EDI, EDX                                           ; |CrackMe.<ModuleEntryPoint>
0041A366|.C1E9 02       SHR ECX, 0x2                                           ; |
0041A369|.F3:A5         REP MOVS DWORD PTR ES:, DWORD PTR DS:      ; |
0041A36B|.8BC8          MOV ECX, EAX                                           ; |
0041A36D|.83E1 03       AND ECX, 0x3                                           ; |
0041A370|.F3:A4         REP MOVS BYTE PTR ES:, BYTE PTR DS:          ; |
0041A372|.FF15 A8C04100 CALL DWORD PTR DS:[<&KERNEL32.GlobalUnlock>]         ; \GlobalUnlock
0041A378|.53            PUSH EBX                                             ; /hData = 002D4000
0041A379|.6A 01         PUSH 0x1                                             ; |Format = CF_TEXT
0041A37B|.FF15 48C24100 CALL DWORD PTR DS:[<&USER32.SetClipboardData>]         ; \SetClipboardData
0041A381|.BD 01000000   MOV EBP, 0x1
0041A386|>FF15 3CC24100 CALL DWORD PTR DS:[<&USER32.CloseClipboard>]         ; [CloseClipboard
0041A38C|.5F            POP EDI                                                ;kernel32.774938F4
0041A38D|.5B            POP EBX                                                ;kernel32.774938F4
0041A38E|.8BC5          MOV EAX, EBP
0041A390|.5E            POP ESI                                                ;kernel32.774938F4
0041A391|.5D            POP EBP                                                ;kernel32.774938F4
0041A392|.C3            RETN
0041A393|>8BC5          MOV EAX, EBP
0041A395|.5E            POP ESI                                                ;kernel32.774938F4
0041A396|.5D            POP EBP                                                ;kernel32.774938F4
0041A397\.C3            RETN
然后程序又休眠了200毫秒
0040510A|> \68 01030080   PUSH 0x80000301
0040510F|.6A 00         PUSH 0x0
00405111|.68 C8000000   PUSH 0xC8
00405116|.68 01000000   PUSH 0x1
0040511B|.BB 7C060000   MOV EBX, 0x67C
00405120|.E8 1B460100   CALL 00419740
00419740/$8B4424 08   MOV EAX, DWORD PTR SS:
00419744|.50            PUSH EAX                                 ; /Timeout = 0. ms
00419745|.FF15 58C04100 CALL DWORD PTR DS:[<&KERNEL32.Sleep>]    ; \Sleep
0041974B\.C3            RETN
这有可能就是为了多线程做准备了。。
0x2 多线程
给OpenClipboard下断点 然后OD查看一下线程

圈起来的这两个线程需要特别注意一下(程序启动时就已经被创建了。)OD看看这两个线程的代码
00405131   .56            PUSH ESI                                 ;CrackMe.<ModuleEntryPoint>
00405132   .57            PUSH EDI                                 ;CrackMe.<ModuleEntryPoint>
00405133   .53            PUSH EBX
00405134   .E8 53FFFFFF   CALL 0040508C
00405139   .5B            POP EBX                                  ;kernel32.774938F4
0040513A   .5F            POP EDI                                  ;kernel32.774938F4
0040513B   .5E            POP ESI                                  ;kernel32.774938F4
0040513C   .C3            RETN

00402E9A   .56            PUSH ESI
00402E9B   .57            PUSH EDI
00402E9C   .53            PUSH EBX
00402E9D   .E8 54E4FFFF   CALL 004012F6
00402EA2   .5B            POP EBX                                  ;CrackMe.0040512D
00402EA3   .5F            POP EDI                                  ;CrackMe.0040512D
00402EA4   .5E            POP ESI                                  ;CrackMe.0040512D
00402EA5   .C3            RETN
可以看到 这两个线程分别调用了 0x0040508C 和 0x004012F6 这两个函数那么删掉之前设置的断点 给这两个函数下断点.F9运行 程序会在0x40508C处断下0x3 寻找点击按钮后执行的代码的所在地址
0x40508C处有段代码需要注意一下:00405095|.833D C6F64200>CMP DWORD PTR DS:, 0x1
0040509C|.0F85 68000000 JNZ 0040510A

我这里执行的时候 0x0042F6C6 处的值不是1给0x42F6C6下硬件写入断点(大小是1) 并禁用那两个线程的断点 F9运行。程序会在0x0040518B处断下00405178/$55            PUSH EBP                                 ;从剪辑板中取出注册码
00405179|.8BEC          MOV EBP, ESP
0040517B|.81EC 04000000 SUB ESP, 0x4
00405181|.C705 C6F64200>MOV DWORD PTR DS:, 0x1 ;注意这里 改写了0x42F6C6处的值为1

0040518B|.68 00000000   PUSH 0x0 ;在这里断下
00405190|.BB C4020000   MOV EBX, 0x2C4
00405195|.E8 76440100   CALL 00419610                            ;取剪辑板文本
0040519A|.83C4 04       ADD ESP, 0x4
0040519D|.8945 FC       MOV , EAX                     ;保存到中



00419610/$57            PUSH EDI                                          ;取剪辑板文本
00419611|.33FF          XOR EDI, EDI                                    ;CrackMe.<ModuleEntryPoint>
00419613|.57            PUSH EDI                                          ; /hWnd = 00401000
00419614|.FF15 44C24100 CALL DWORD PTR DS:[<&USER32.OpenClipboard>]       ; \OpenClipboard
0041961A|.85C0          TEST EAX, EAX
0041961C|.74 42         JE SHORT 00419660
0041961E|.56            PUSH ESI                                          ;CrackMe.<ModuleEntryPoint>
0041961F|.6A 01         PUSH 0x1                                          ; /Format = CF_TEXT
00419621|.FF15 40C24100 CALL DWORD PTR DS:[<&USER32.GetClipboardData>]    ; \GetClipboardData
00419627|.8BF0          MOV ESI, EAX
00419629|.85F6          TEST ESI, ESI                                     ;CrackMe.<ModuleEntryPoint>
0041962B|.74 28         JE SHORT 00419655
0041962D|.56            PUSH ESI                                          ; /hMem = 00401000
0041962E|.FF15 B4C04100 CALL DWORD PTR DS:[<&KERNEL32.GlobalLock>]      ; \GlobalLock
00419634|.8BD0          MOV EDX, EAX
00419636|.83C9 FF       OR ECX, 0xFFFFFFFF
00419639|.8BFA          MOV EDI, EDX                                    ;CrackMe.<ModuleEntryPoint>
0041963B|.33C0          XOR EAX, EAX
0041963D|.F2:AE         REPNE SCAS BYTE PTR ES:
0041963F|.F7D1          NOT ECX                                           ;CrackMe.<ModuleEntryPoint>
00419641|.49            DEC ECX                                           ;CrackMe.<ModuleEntryPoint>
00419642|.51            PUSH ECX                                          ;CrackMe.<ModuleEntryPoint>
00419643|.52            PUSH EDX                                          ;CrackMe.<ModuleEntryPoint>
00419644|.E8 D7130000   CALL 0041AA20
00419649|.83C4 08       ADD ESP, 0x8
0041964C|.8BF8          MOV EDI, EAX
0041964E|.56            PUSH ESI                                          ; /hMem = 00401000
0041964F|.FF15 A8C04100 CALL DWORD PTR DS:[<&KERNEL32.GlobalUnlock>]      ; \GlobalUnlock
00419655|>FF15 3CC24100 CALL DWORD PTR DS:[<&USER32.CloseClipboard>]      ; [CloseClipboard
0041965B|.8BC7          MOV EAX, EDI                                    ;CrackMe.<ModuleEntryPoint>
0041965D|.5E            POP ESI                                           ;kernel32.774938F4
0041965E|.5F            POP EDI                                           ;kernel32.774938F4
0041965F|.C3            RETN
00419660|>8BC7          MOV EAX, EDI                                    ;CrackMe.<ModuleEntryPoint>
00419662|.5F            POP EDI                                           ;kernel32.774938F4
00419663\.C3            RETN

执行完这段代码后 观察一下eax寄存器

这个1234567890是我输入的假码
因此这段代码就是将之前复制到剪辑板中的注册码读取出来。
有意思的是:在第一次执行这个函数(0x00405178)的时候 0x42F6C6 处的值是0 并且在执行这个函数之前 0x42F6C6 的值并没有改变。(在这个函数的函数头 0x00405178 处下断点 然后禁用之前设置的所有断点 删掉之前设置的硬件断点(重新在0x42F6C6处下硬件写入断点)重新载入程序然后F9运行可得知) 执行以后 0x42F6C6 处的值才被改变为1而在这里00405095 |. 833D C6F64200>CMP DWORD PTR DS:, 0x1
0040509C |. 0F85 68000000 JNZ 0040510A
这段代码判断0x42F6C6处的值是不是1 如果不是的话就转移 到0x0040510A处继续执行。0040510A|> \68 01030080   PUSH 0x80000301
0040510F|.6A 00         PUSH 0x0
00405111|.68 C8000000   PUSH 0xC8
00405116|.68 01000000   PUSH 0x1
0040511B|.BB 7C060000   MOV EBX, 0x67C
00405120|.E8 1B460100   CALL 00419740 ;休眠200毫秒
00405125|.83C4 10       ADD ESP, 0x10
00405128|.E8 5FFFFFFF   CALL 0040508C
0040512D|.8BE5          MOV ESP, EBP
0040512F|.5D            POP EBP                                  ;0080D250
00405130\.C3            RETN

因此这个函数(0x00405178)在第一次调用的时候 并不是由 0x40508C 处调用的。好了回到正题。我们要寻找的是 点击按钮以后 程序会执行哪些代码。一个线程一个线程看。先看0x40508C处我怀疑如果点击了按钮以后 JNZ就不会实现转移。不过这个应该是不可能的。因为在第一次执行0x00405178这个函数的时候 0x42F6C6 处的值是0 执行以后 0x42F6C6 处的值是1如果0x42F6C6 处的值是1 那么这个JNZ就不会实现转移而在第一次执行的时候 我们并没有点击[注册]按钮因此0x40508C处可以排除掉那还剩下一个线程 0x004012F6删掉之前设置的所有断点 给0x004012F6 处下断点。F9运行 程序直接在这里断下F8一直单步到这里00401395|> \837D F0 00    CMP , 0x0
00401399|.0F84 93000000 JE 00401432
这个跳转还是蛮长的 猜测一下:如果点击了按钮以后 JE是不是就不会转移了呢?因为转移的话 就会执行下面的代码:00401432|> \68 01030080   PUSH 0x80000301
00401437|.6A 00         PUSH 0x0
00401439|.68 C8000000   PUSH 0xC8
0040143E|.68 01000000   PUSH 0x1
00401443|.BB 7C060000   MOV EBX, 0x67C
00401448|.E8 F3820100   CALL 00419740                            ;休眠200毫秒
0040144D|.83C4 10       ADD ESP, 0x10
00401450|.E8 A1FEFFFF   CALL 004012F6
00401455|.8BE5          MOV ESP, EBP
00401457|.5D            POP EBP                                  ;CrackMe.00401455
00401458\.C3            RETN
休眠200毫秒以后又重新调用这个函数了。所以我猜想 点击了按钮以后 JE就不会转移 那么我们验证一下在这个指令(JE 00401432)的下一条指令(0040139F    PUSH 0x80000004)下断点 然后删掉0x004012F6 处的断点 F9运行 点击一下[注册按钮]可以看到程序直接断了下来 因此 这个地址(0040139F)就是我们要找的地址0x4 验证的地方(爆破 + 追码)在0x1中 我们知道了 剪辑板中存放注册码那么我们给00419610 (取剪辑板文本)下断看看一直F8 看看能不能在这里断下来。断下来了 然后执行到返回 到达0x401972处。查看一下eax寄存器可以看到 这个又是取出了我输入的假码F8继续往下走00401990|.68 010100A0   PUSH 0xA0000101
00401995|.6A 00         PUSH 0x0
00401997|.68 8AE14200   PUSH 0042E18A
0040199C|.68 01000000   PUSH 0x1
004019A1|.BB 68010000   MOV EBX, 0x168
004019A6|.E8 95790100   CALL 00419340
004019AB|.83C4 10       ADD ESP, 0x10
执行完这个call以后 eax寄存器是这样的不知道这是干什么的 不要管他继续往下004019C9|.6A 01         PUSH 0x1
004019CB|.B8 A7E14200   MOV EAX, 0042E1A7
004019D0|.8945 F4       MOV , EAX
004019D3|.8D45 F4       LEA EAX,
004019D6|.50            PUSH EAX
004019D7|.8D45 F8       LEA EAX,
004019DA|.50            PUSH EAX
004019DB|.E8 2D010000   CALL 00401B0D                            ;'52pojiE'
004019E0|.8945 F0       MOV , EAX                     ;保存执行完这个call以后 eax寄存器中的地址指向"52pojiE"这个字符串继续往下004019F6|.50            PUSH EAX
004019F7|.8B5D F8       MOV EBX,
004019FA|.85DB          TEST EBX, EBX
004019FC|.74 09         JE SHORT 00401A07
004019FE|.53            PUSH EBX
004019FF|.E8 A2750100   CALL 00418FA6
00401A04|.83C4 04       ADD ESP, 0x4
00401A07|>58            POP EAX                                  ;007B0238
00401A08|.8945 F8       MOV , EAX                     ;保存到中
00401A0B|.8B45 F8       MOV EAX,
00401A0E|.50            PUSH EAX
00401A0F|.FF75 FC       PUSH                            ;输入的假码
00401A12|.E8 98FEFFFF   CALL 004018AF                            ;比较文本
00401A17|.83C4 08       ADD ESP, 0x8
比较文本函数:004018AF/$8B5424 04   MOV EDX, DWORD PTR SS:
004018B3|.8B4C24 08   MOV ECX, DWORD PTR SS:
004018B7|.85D2          TEST EDX, EDX
004018B9|.75 0D         JNZ SHORT 004018C8
004018BB|.33C0          XOR EAX, EAX
004018BD|.85C9          TEST ECX, ECX
004018BF|.74 06         JE SHORT 004018C7
004018C1|.8039 00       CMP BYTE PTR DS:, 0x0
004018C4|.74 01         JE SHORT 004018C7
004018C6|.48            DEC EAX
004018C7|>C3            RETN
004018C8|>85C9          TEST ECX, ECX
004018CA|.75 09         JNZ SHORT 004018D5
004018CC|.33C0          XOR EAX, EAX
004018CE|.803A 00       CMP BYTE PTR DS:, 0x0
004018D1|.74 01         JE SHORT 004018D4
004018D3|.40            INC EAX
004018D4|>C3            RETN
004018D5|>E8 53160000   CALL 00402F2D
004018DA|.90            NOP
004018DB|.75 37         JNZ SHORT 00401914
004018DD|>8B02          /MOV EAX, DWORD PTR DS:
004018DF|.3A01          |CMP AL, BYTE PTR DS:
004018E1|.75 2B         |JNZ SHORT 0040190E
004018E3|.0AC0          |OR AL, AL
004018E5|.74 24         |JE SHORT 0040190B
004018E7|.3A61 01       |CMP AH, BYTE PTR DS:
004018EA|.75 22         |JNZ SHORT 0040190E
004018EC|.0AE4          |OR AH, AH
004018EE|.74 1B         |JE SHORT 0040190B
004018F0|.C1E8 10       |SHR EAX, 0x10
004018F3|.3A41 02       |CMP AL, BYTE PTR DS:
004018F6|.75 16         |JNZ SHORT 0040190E
004018F8|.0AC0          |OR AL, AL
004018FA|.74 0F         |JE SHORT 0040190B
004018FC|.3A61 03       |CMP AH, BYTE PTR DS:
004018FF|.75 0D         |JNZ SHORT 0040190E
00401901|.83C1 04       |ADD ECX, 0x4
00401904|.83C2 04       |ADD EDX, 0x4
00401907|.0AE4          |OR AH, AH
00401909|.^ 75 D2         \JNZ SHORT 004018DD
0040190B|>33C0          XOR EAX, EAX
0040190D|.C3            RETN
0040190E|>1BC0          SBB EAX, EAX
00401910|.D1E0          SHL EAX, 1
00401912|.40            INC EAX
00401913|.C3            RETN
00401914|>F7C2 01000000 TEST EDX, 0x1
0040191A|.74 14         JE SHORT 00401930
0040191C|.8A02          MOV AL, BYTE PTR DS:
0040191E|.42            INC EDX
0040191F|.3A01          CMP AL, BYTE PTR DS:
00401921|.^ 75 EB         JNZ SHORT 0040190E
00401923|.41            INC ECX
00401924|.0AC0          OR AL, AL
00401926|.^ 74 E3         JE SHORT 0040190B
00401928|.F7C2 02000000 TEST EDX, 0x2
0040192E|.^ 74 AD         JE SHORT 004018DD
00401930|>66:8B02       MOV AX, WORD PTR DS:
00401933|.83C2 02       ADD EDX, 0x2
00401936|.3A01          CMP AL, BYTE PTR DS:
00401938|.^ 75 D4         JNZ SHORT 0040190E
0040193A|.0AC0          OR AL, AL
0040193C|.^ 74 CD         JE SHORT 0040190B
0040193E|.3A61 01       CMP AH, BYTE PTR DS:
00401941|.^ 75 CB         JNZ SHORT 0040190E
00401943|.0AE4          OR AH, AH
00401945|.^ 74 C4         JE SHORT 0040190B
00401947|.83C1 02       ADD ECX, 0x2
0040194A\.^ EB 91         JMP SHORT 004018DD
这段代码 用我们输入的假码和"52pojiE"进行比较因为这两个字符串不一样 所以返回-1(eax = 0xFFFFFFFF)然后紧接着 有个比较返回值的00401A1A|.83F8 00       CMP EAX, 0x0
00401A1D|.0F85 4C000000 JNZ 00401A6F
这个JNZ实现的话(eax != 0)函数就直接返回。那么把这个JNZ用NOP填充 然后F9运行一下试试00401A1D      90            NOP
00401A1E      90            NOP
00401A1F      90            NOP
00401A20      90            NOP
00401A21      90            NOP
00401A22      90            NOP
突然提示破解成功所以这个JNZ就是关键跳转那么注册码应该很明显了 就是52pojiE附一个成功的截图:

zbnysjwsnd8 发表于 2017-7-31 10:11

xiao_ya 发表于 2017-7-31 10:10
执行到4050C1处,是怎么执行的?求大神为小白解惑

一路F8就能到{:1_902:}

wuyasos 发表于 2017-7-29 10:58

讲的比较详细,支持下,多多分析,值得学习

天秤男 发表于 2017-7-29 11:02

这个壁纸不错啊求壁纸~

swx5201314 发表于 2017-7-29 11:14

谢谢分享思路{:301_993:}

Crack-L 发表于 2017-7-29 11:29

感谢这么好的教材

左殇魂 发表于 2017-7-29 11:59

学习一下。

【健谈】 发表于 2017-7-29 13:43

谢谢老师分享!收藏,学习。

丶徐三岁 发表于 2017-7-29 13:53

学习了   感谢

丛林男孩 发表于 2017-7-29 14:10

支持一下。爆破

SourceWater 发表于 2017-7-29 15:53

学习了,看起来还是有些不懂,慢慢研究
页: [1] 2 3
查看完整版本: 一个娱乐CM的爆破 + 追码