查看: 477|回复: 0

[转载图文] 一个简单运行时解密+CRC校验的patchme分析

[复制链接]
发表于 2020-5-4 10:06:52 | 显示全部楼层 |阅读模式


今天朋友给我发了patchme,他很多地方不懂,叫我帮他分析。
我分析完发现这个作者真是用心良苦,专为新手练习特意写的。分析完 觉得有点意思,就发出来给大家分享一下。




一个简单运行时解密+CRC校验的patchme分析

一个简单运行时解密+CRC校验的patchme分析
              

一个简单运行时解密+CRC校验的patchme分析

一个简单运行时解密+CRC校验的patchme分析

打开程序,很简单, 一个提示框,一个对话框,作者要求就是修改这两个字符串。




一个简单运行时解密+CRC校验的patchme分析

一个简单运行时解密+CRC校验的patchme分析



OD载入,ep代码很简单整洁,这是汇编写的吧(我猜)。



一个简单运行时解密+CRC校验的patchme分析

一个简单运行时解密+CRC校验的patchme分析


国际惯例,搜索字符串,没找到提示框和对话框的字符串,早做好心理准备肯定是搜不到的了。



既然这样我们就一句句代码来分析吧。。。。。。。


我们看到上面ep代码,就一个call,肯定进去,F8再F7进去代码如下。。。。。

[Asm] 纯文本查看 复制代码
[pre]004010E9  /$  B8 F5104000   mov eax,unpackme.004010F5
004010EE  |.  50            push eax
004010EF  |.  E8 A7FFFFFF   call unpackme.0040109B
004010F4  \.  C3            retn
[/pre]


这。。。。。压入004010F5作为参数继续Call。。。。我们还是F8 F8 F7进去call unpackme.0040109B,代码如下。。。。
[Asm] 纯文本查看 复制代码
[pre]0040109B  /$  50            push eax                                 ;  unpackme.004010F5
0040109C  |.  8BD8          mov ebx,eax
0040109E  |.  B9 54010000   mov ecx,0x154
004010A3  |>  8033 44       /xor byte ptr ds:[ebx],0x44
004010A6  |.  83E9 01       |sub ecx,0x1
004010A9  |.  43            |inc ebx
004010AA  |.  83F9 00       |cmp ecx,0x0
004010AD  |.^ 75 F4         \jnz short unpackme.004010A3
004010AF  |.  50            push eax
004010B0  |.  E8 08000000   call unpackme.004010BD
004010B5  |.  50            push eax
004010B6  |.  E8 7EFFFFFF   call unpackme.00401039
004010BB  |.  58            pop eax
004010BC  \.  C3            retn
[/pre]


代码真是非常简洁明了,一个循环两个call。。。我们先看这个循环是什么鬼。。。
[Asm] 纯文本查看 复制代码
[pre]0040109B  /$  50            push eax                                 ;  F8往下走
0040109C  |.  8BD8          mov ebx,eax
0040109E  |.  B9 54010000   mov ecx,0x154                            ;  循环次数,154
004010A3  |>  8033 44       /xor byte ptr ds:[ebx],0x44              ;  ebx=004010f5,用ebx异或44,解密(4010f5~401248)区域
004010A6  |.  83E9 01       |sub ecx,0x1
004010A9  |.  43            |inc ebx
004010AA  |.  83F9 00       |cmp ecx,0x0
004010AD  |.^ 75 F4         \jnz short unpackme.004010A3
[/pre]


我发现我写得好像过于详细。。。。。
知道循环是什么鬼之后就在 004010AF|.50    push eax 下段点然后F9跑过循环。
然后进入004010B0|.E8 08000000 call unpackme.004010BD
看看又是什么鬼。。。。。。
代码如下

[Asm] 纯文本查看 复制代码
[pre]004010BD  /$  50            push eax                                 ;  F8走下去
004010BE  |.  BB 07104000   mov ebx,unpackme.00401007
004010C3  |.  B9 7F000000   mov ecx,0x7F                             ;  循环次数7F
004010C8  |>  8033 07       /xor byte ptr ds:[ebx],0x7               ;  ebx=401007,用ebx异或7,解密(401007~401085)区域
004010CB  |.  83E9 01       |sub ecx,0x1
004010CE  |.  43            |inc ebx
004010CF  |.  83F9 00       |cmp ecx,0x0
004010D2  |.^ 75 F4         \jnz short unpackme.004010C8
004010D4  |.  8BD8          mov ebx,eax
004010D6  |.  B9 54010000   mov ecx,0x154                            ;  又一个循环,154次
004010DB  |>  8033 11       xor byte ptr ds:[ebx],0x11               ;  ebx=004010f5,用ebx异或11,解密(4010f5~401248)区域
004010DE  |.  83E9 01       sub ecx,0x1                              ;  又是刚才那个区域,双重加密啊啊啊啊
004010E1  |.  43            inc ebx
004010E2  |.  83F9 00       cmp ecx,0x0
004010E5  |.^ 75 F4         jnz short unpackme.004010DB
004010E7  |.  58            pop eax
004010E8  \.  C3            retn                                     ;  解密完就返回
[/pre]


这个CALL就是分别解密(401007~401085和4010f5~401248)两个区域,弄懂走下一个call :004010B6|.E8 7EFFFFFF call unpackme.00401039

哎呀,这个call的地址留意一下, call 00401039;之前分析的”用ebx异或7,解密(401007~401085)区域“,正好在上面xor 7解密的那个区域。
进去代码如下


[Asm] 纯文本查看 复制代码
[pre]00401039   $  50            push eax
0040103A   .  8BD8          mov ebx,eax
0040103C   .  B9 54010000   mov ecx,0x154                            ;  循环154次
00401041   .  BA 00000000   mov edx,0x0                              ;  初始化edx
00401046   >  0313          add edx,dword ptr ds:[ebx]               ;  ebx=004010F5,又是那个双重加密的区域,将(4010f5~401248)区域累计相加,结果存edx
00401048   .  83E9 01       sub ecx,0x1
0040104B   .  43            inc ebx
0040104C   .  83F9 00       cmp ecx,0x0
0040104F   .^ 75 F5         jnz short unpackme.00401046
00401051   .  B8 4A124000   mov eax,unpackme.0040124A
00401056   .  BE 80124000   mov esi,unpackme.00401280
0040105B   .  50            push eax
0040105C   .  56            push esi
0040105D   .  E8 28000000   call unpackme.0040108A                   ;  解密IAT。
00401062   .  81FA B08DEB31 cmp edx,0x31EB8DB0                       ;  edx和31eb8db0比较 ,这就是CRC校验,你修改过就会提示错误。
00401068   .  74 19         je short unpackme.00401083               ;  是否提示crc校验错误的跳转
0040106A   .  6A 30         push 0x30
0040106C   .  68 32104000   push unpackme.00401032                   ;  Error:
00401071   .  68 09104000   push unpackme.00401009                   ;  CrC of this file has been modified !!!
00401076   .  6A 00         push 0x0
00401078   .  E8 E5010000   call unpackme.00401262
0040107D   .  50            push eax
0040107E   .  E8 F1010000   call unpackme.00401274
00401083   >  E9 96010000   jmp unpackme.0040121E                    ;  跳到程序的oep
00401088   .  58            pop eax
00401089   .  C3            retn
[/pre]


这是最简单的CRC校验了,我们继续来看OEP的代码情况,如下:

[Asm] 纯文本查看 复制代码
[pre]0040121E    6A 00           push 0x0
00401220    E8 55000000     call <jmp.&kernel32.GetModuleHandleA>    ; GetModuleHandleA 是取DLL的运行句柄的,在创建窗口时候用这个能给窗口赋值正确的句柄和运行id
00401225    A3 18304000     mov dword ptr ds:[0x403018],eax
0040122A    6A 00           push 0x0
0040122C    68 F5104000     push unpackme.004010F5                   ; 显示对话框的过程
00401231    6A 00           push 0x0
00401233    68 24304000     push unpackme.00403024                   ; TESTWIN
00401238    FF35 18304000   push dword ptr ds:[0x403018]
0040123E    E8 0D000000     call <jmp.&user32.DialogBoxParamA>       ; DialogBoxParam函数根据对话框模板资源创建一个模态的对话框
00401243    50              push eax
00401244    E8 2B000000     call <jmp.&kernel32.ExitProcess>         ; 退出
[/pre]



代码整洁的不习惯。。。程序流程很明了,提示对话框然后退出, 看看函数DialogBoxParam第四个参数是IpDialogFunc:指向对话框过程的指针。有关更详细的关于对话框过程的信息,请参见DialogProc。
我们要分析参数是0040122C push 004010F5 ; 显示对话框的过程,所以进入004010F5 细看整个流程。没错就是那个加密两次还要crc校验的重要区域,代码如下:


[Asm] 纯文本查看 复制代码
[pre]004010F5   .  55            push ebp
004010F6   .  8BEC          mov ebp,esp
004010F8   .  83C4 C0       add esp,-0x40
004010FB   .  817D 0C 10010>cmp dword ptr ss:[ebp+0xC],0x110
00401102   .  0F85 C8000000 jnz unpackme.004011D0
00401108   .  EB 17         jmp short unpackme.00401121
0040110A   .  59 6F 75 20 6>ascii "You must unpack "
0040111A   .  6D 65 20 21 2>ascii "me !!!",0
00401121   >  EB 1C         jmp short unpackme.0040113F
00401123   .  59 6F 75 20 6>ascii "You must patch t"
00401133   .  68 69 73 20 4>ascii "his NAG !!!",0
0040113F   >  EB 24         jmp short unpackme.00401165
00401141   .  3C 3C 3C 20 4>ascii "<<< Ap0x / Patch"
00401151   .  20 26 20 55 6>ascii " & Unpack Me #1 "
00401161   .  3E 3E 3E 00   ascii ">>>",0
00401165   >  68 41114000   push unpackme.00401141                   ; /lParam = 0x401141
0040116A   .  6A 00         push 0x0                                 ; |wParam = 0x0
0040116C   .  6A 0C         push 0xC                                 ; |Message = WM_SETTEXT
0040116E   .  FF75 08       push dword ptr ss:[ebp+0x8]              ; |hWnd
00401171   .  E8 F2000000   call <jmp.&user32.SendMessageA>          ; \SendMessageA
00401176   .  68 C8000000   push 0xC8                                ; /RsrcName = 200.
0040117B   .  FF35 18304000 push dword ptr ds:[0x403018]             ; |hInst = NULL
00401181   .  E8 D6000000   call <jmp.&user32.LoadIconA>             ; \LoadIconA
00401186   .  A3 20304000   mov dword ptr ds:[0x403020],eax
0040118B   .  FF35 20304000 push dword ptr ds:[0x403020]             ; /lParam = 0x0
00401191   .  6A 01         push 0x1                                 ; |wParam = 0x1
00401193   .  68 80000000   push 0x80                                ; |Message = WM_SETICON
00401198   .  FF75 08       push dword ptr ss:[ebp+0x8]              ; |hWnd
0040119B   .  E8 C8000000   call <jmp.&user32.SendMessageA>          ; \SendMessageA
004011A0   .  BB 01000000   mov ebx,0x1
004011A5   .  68 0A114000   push unpackme.0040110A                   ; /You must unpack me !!!
004011AA   .  6A 64         push 0x64                                ; |ControlID = 64 (100.)
004011AC   .  FF75 08       push dword ptr ss:[ebp+0x8]              ; |hWnd
004011AF   .  E8 BA000000   call <jmp.&user32.SetDlgItemTextA>       ; \SetDlgItemTextA
004011B4   .  6A 40         push 0x40                                ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
004011B6   .  68 41114000   push unpackme.00401141                   ; |<<< Ap0x / Patch & Unpack Me #1 >>>
004011BB   .  68 23114000   push unpackme.00401123                   ; |You must patch this NAG !!!
004011C0   .  FF75 08       push dword ptr ss:[ebp+0x8]              ; |hOwner
004011C3   .  E8 9A000000   call <jmp.&user32.MessageBoxA>           ; \MessageBoxA
004011C8   .  33C0          xor eax,eax
004011CA   .  C9            leave
004011CB   .  C2 1000       retn 0x10
[/pre]


终于找到我们要修改的字符串了,经过两次解密才出现的字符串,来我们开始想办法避开校验打补丁。
经过上面分析我们知道要在程序解密之后,然后CRC校验结束之后打补丁即可,正好利用原来00401083 >jmp 0040121E ; 跳到程序的oep,这条指令
这里改成JMP XXXXXX 空白区域修改完字符串再跳回OEP,有想法就开干~~~~


先找个空白区域,我经过搜索000发现00401280开始就是空白了。

首先在00401083 > E9 96010000 jmp unpackme.0040121E 改00401083 /E9 F8010000 jmp unpackme.00401280。
哎,不对,留意一下这个地址00401083,再看看上面的分析(004010C8 |> 8033 07 /xor byte ptr ds:[ebx],0x7 ; ebx=401007,用ebx异或7,解密(401007~401085)区域),正好在这个加密的区域。
所以我们的修改指令正常写下去是不行的,要加密让程序运行时解密出正确的指令,可以用 xor加密,经E9 F8010000 xor 7= EE FF060000,修改后
[Asm] 纯文本查看 复制代码
[pre]00401083    EE              out dx,al                                         ; 跳到程序的oep
00401084    FF06            inc dword ptr ds:[esi]
00401086    0000            add byte ptr ds:[eax],al
[/pre]

这个指令是未解密的,所以看不懂,解密后这个指令就会变成E9 F8010000 jmp 00401280,然后再到00401280把修改字符串的指令写上去就可以了:

[Asm] 纯文本查看 复制代码
[pre]00401280   .  B9 0C000000   mov ecx,0x1b
00401285   .  BE A8124000   mov esi,unpackme.004012A8
0040128A   .  BF 23114000   mov edi,unpackme.00401123                         ;  ASCII 0C,": u8 &!u%4!6"
0040128F   .  F3:A4         rep movs byte ptr es:[edi],byte ptr ds:[esi]      ;  //修改提示框
00401291   .  B9 09000000   mov ecx,0x15
00401296   .  BE B4124000   mov esi,unpackme.004012B4
0040129B   .  BF 0A114000   mov edi,unpackme.0040110A                         ;  ASCII 0C,": u8 &!u ;%4"
004012A0   .  F3:A4         rep movs byte ptr es:[edi],byte ptr ds:[esi]      ;  修改对话框
004012A2   .^ E9 77FFFFFF   jmp unpackme.0040121E                             ;  跳回OEP
004012A7      90            nop
004012A8   .  B8 C9B5F4CC   mov eax,0xCCF4B5C9                                ;  用来替换提示框的字符串
004012AD   .^ E1 CA         loopde short unpackme.00401279
004012AF   .  BE BFF20000   mov esi,0xF2BF
004012B4   .  B5 BD         mov ch,0xBD                                       ;  用来替换对话框的字符串
004012B6   .  C1CB D5       ror ebx,0xD5
004012B9   .^ E2 C0         loopd short unpackme.0040127B
004012BB   .  EF            out dx,eax
004012BC   .  BE CDC4DCCE   mov esi,0xCEDCC4CD
004012C1   .  AA            stos byte ptr es:[edi]
004012C2   .  CB            retf
004012C3      F9            db F9
004012C4      D3            db D3
004012C5      FB            db FB
004012C6      CE            db CE
004012C7      AA            db AA
[/pre]



右键》保存》OK,过解密,过校验就是这么简单。。。。

之前我为什么说作者用心良苦,你会发现,会莫名其妙多个空白区域,然后刚好又是没加密的区域。~~~为了你们新手也是操碎了心。


游客,如果您要查看本帖隐藏内容请回复




温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的最好奖励,还可以获得学币奖励,请尊重作者的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
论坛交流群:672619046
微信公众号
快速回复 返回顶部 返回列表