没想发帖太少,不能发到『软件保护与分析』版块。。
不好意思,用记事本写的笔记。。。将就着看吧。

Crypkey
skw主程序脱壳

by yusilk
2008.7.1



工具:OllyICE+PUPE+ImpREC+PETools
目的:SKW停在OEP,dump出PE文件,并让SKW创建的调试进程自动修复CC的代码。

用ollyice载入分析后的程序入口如下

skw.<模块入口> $  8B1D 4C605A00 MOV EBX,DWORD PTR DS:[5A604C]
005A6170   .  83FB 00       CMP EBX,0
005A6173   .  75 1C         JNZ SHORT skw.005A6191
005A6175   .  C705 4C605A00>MOV DWORD PTR DS:[5A604C],1
005A617F   .  68 80605A00   PUSH skw.005A6080                        ;  ASCII "KERNEL32.DLL"
005A6184   .  E8 EB200000   CALL skw.005A8274
005A6189   .  83C4 04       ADD ESP,4
005A618C   .  E8 07000000   CALL skw.005A6198
005A6191   >- FF25 00605A00 JMP NEAR DWORD PTR DS:[5A6000]           ;  skw.00401000
005A6197   .  C3            RETN
005A6198  /$  E8 5F000000   CALL skw.005A61FC
005A619D  |.  C705 64605A00>MOV DWORD PTR DS:[5A6064],skw.005A6000
005A61A7  |.  C705 68605A00>MOV DWORD PTR DS:[5A6068],skw.005A6004
005A61B1  |.  C705 6C605A00>MOV DWORD PTR DS:[5A606C],0
005A61BB  |.  C705 70605A00>MOV DWORD PTR DS:[5A6070],1234
005A61C5  |.  C705 74605A00>MOV DWORD PTR DS:[5A6074],skw.005A6020   ;  ASCII "CKSPISH"
005A61CF  |.  6A 00         PUSH 0
005A61D1  |.  FF15 FE605A00 CALL NEAR DWORD PTR DS:[5A60FE]
005A61D7  |.  A3 78605A00   MOV DWORD PTR DS:[5A6078],EAX
005A61DC  |.  C705 7C605A00>MOV DWORD PTR DS:[5A607C],skw.005A6050   ;  ASCII "CKSMDSH"
005A61E6  |.  68 64605A00   PUSH skw.005A6064
005A61EB  |.  E8 40210000   CALL skw.005A8330
005A61F0  |.  C705 4C605A00>MOV DWORD PTR DS:[5A604C],2
005A61FA  \.  C3            RETN

005A6191   >- FF25 00605A00 JMP NEAR DWORD PTR DS:[5A6000]           ;  skw.00401000
由可以知道程序的OEP是在401000,至于为什么是在这里,让自己跟踪理解。

005A6191   >- FF25 00605A00 JMP NEAR DWORD PTR DS:[5A6000]           ;  skw.00401000
patch FF25为CC25,目的是让程序运行到此处时出现int 3异常,并让调试进程接管。 
记住地址005A6191

Patch后如下代码:

skw.<模块入口> $  8B1D 4C605A00 MOV EBX,DWORD PTR DS:[5A604C]
005A6170   .  83FB 00       CMP EBX,0
005A6173   .  75 1C         JNZ SHORT skw.005A6191
005A6175   .  C705 4C605A00>MOV DWORD PTR DS:[5A604C],1
005A617F   .  68 80605A00   PUSH skw.005A6080                        ;  ASCII "KERNEL32.DLL"
005A6184   .  E8 EB200000   CALL skw.005A8274
005A6189   .  83C4 04       ADD ESP,4
005A618C   .  E8 07000000   CALL skw.005A6198
005A6191   >  CC            INT3          ;Patch
005A6192   ?  25 00605A00   AND EAX,5A6000
005A6197   .  C3            RETN
005A6198  /$  E8 5F000000   CALL skw.005A61FC
005A619D  |.  C705 64605A00>MOV DWORD PTR DS:[5A6064],skw.005A6000
005A61A7  |.  C705 68605A00>MOV DWORD PTR DS:[5A6068],skw.005A6004
005A61B1  |.  C705 6C605A00>MOV DWORD PTR DS:[5A606C],0
005A61BB  |.  C705 70605A00>MOV DWORD PTR DS:[5A6070],1234
005A61C5  |.  C705 74605A00>MOV DWORD PTR DS:[5A6074],skw.005A6020   ;  ASCII "CKSPISH"
005A61CF  |.  6A 00         PUSH 0
005A61D1  |.  FF15 FE605A00 CALL NEAR DWORD PTR DS:[5A60FE]
005A61D7  |.  A3 78605A00   MOV DWORD PTR DS:[5A6078],EAX
005A61DC  |.  C705 7C605A00>MOV DWORD PTR DS:[5A607C],skw.005A6050   ;  ASCII "CKSMDSH"
005A61E6  |.  68 64605A00   PUSH skw.005A6064
005A61EB  |.  E8 40210000   CALL skw.005A8330
005A61F0  |.  C705 4C605A00>MOV DWORD PTR DS:[5A604C],2
005A61FA  \.  C3            RETN

一路跟踪来到这里
005A8EAD  |.  E8 52FEFFFF   CALL skw.005A8D04
005A8EB2  |.  C645 F4 63    MOV BYTE PTR SS:[EBP-C],63
005A8EB6  |.  C645 F5 6B    MOV BYTE PTR SS:[EBP-B],6B
005A8EBA  |.  C645 F6 73    MOV BYTE PTR SS:[EBP-A],73
005A8EBE  |.  C645 F7 72    MOV BYTE PTR SS:[EBP-9],72
005A8EC2  |.  83C4 08       ADD ESP,8
005A8EC5  |.  8D95 D4FEFFFF LEA EDX,[LOCAL.75]
005A8ECB  |.  C645 F8 00    MOV BYTE PTR SS:[EBP-8],0
005A8ECF  |.  52            PUSH EDX
005A8ED0  |.  8D4D F4       LEA ECX,[LOCAL.3]
005A8ED3  |.  6A 00         PUSH 0
005A8ED5  |.  51            PUSH ECX
005A8ED6  |.  8D85 D0FDFFFF LEA EAX,[LOCAL.140]
005A8EDC  |.  50            PUSH EAX
005A8EDD  |.  FF15 C6C25A00 CALL NEAR DWORD PTR DS:[5AC2C6]          ;  kernel32.GetTempFileNameA
005A8EE3  |.  8D95 CCFCFFFF LEA EDX,[LOCAL.205]

堆栈中我们可以看到:
0013F948   0013FF84  ASCII "cksr"
0013F94C   00000000
0013F950   0013FE64  ASCII "C:\DOCUME~2\yusilk\LOCALS~1\Temp\cksX.tmp"
0013F954   7C9157A1  ntdll.7C9157A1
0013F958   0013FA84
0013F95C   000067CA
0013F960   0013F6D0

继续跟踪到这里。
005A8FEF  |> \6A 00         PUSH 0
005A8FF1  |.  68 00010000   PUSH 100
005A8FF6  |.  6A 02         PUSH 2
005A8FF8  |.  6A 00         PUSH 0
005A8FFA  |.  6A 00         PUSH 0
005A8FFC  |.  8D95 D4FEFFFF LEA EDX,[LOCAL.75]
005A9002  |.  68 000000C0   PUSH C0000000
005A9007  |.  52            PUSH EDX
005A9008  |.  FF15 50C25A00 CALL NEAR DWORD PTR DS:[5AC250]          ;  kernel32.CreateFileA

创建一个名字为cksX.tmp的文件,

005A9072  |.  8B0D 34965A00 MOV ECX,DWORD PTR DS:[5A9634]
005A9078  |.  51            PUSH ECX
005A9079  |.  68 38965A00   PUSH skw.005A9638                        ;  ASCII "MZP"
005A907E  |.  8B45 EC       MOV EAX,[LOCAL.5]
005A9081  |.  50            PUSH EAX
005A9082  |.  FF15 4DC35A00 CALL NEAR DWORD PTR DS:[5AC34D]          ;  kernel32.WriteFile
005A9088  |.  85C0          TEST EAX,EAX

堆栈中可以看到:
0013F938   0013FE64  ASCII "C:\DOCUME~2\yusilk\LOCALS~1\Temp\cksX.tmp"
0013F93C   C0000000
0013F940   0000003C  |hFile = 0000003C (window)
0013F944   005A9638  |Buffer = skw.005A9638
0013F948   00002A00  |nBytesToWrite = 2A00 (10752.)
0013F94C   0013FF8C  |pBytesWritten = 0013FF8C
0013F950   00000000  \pOverlapped = NULL

0013F944   005A9638  |Buffer = skw.005A9638
这是所创建文件cksX.tmp对应在主程序中的位置。。

继续跟踪到这里。在005A9391下断,这里有一些步骤要操作。
005A9366  |.  83C4 08       ADD ESP,8
005A9369  |.  8D85 C4F9FFFF LEA EAX,[LOCAL.399]
005A936F  |.  8D95 D4F9FFFF LEA EDX,[LOCAL.395]
005A9375  |.  8D8D 18FAFFFF LEA ECX,[LOCAL.378]
005A937B  |.  50            PUSH EAX
005A937C  |.  52            PUSH EDX
005A937D  |.  6A 00         PUSH 0
005A937F  |.  6A 00         PUSH 0
005A9381  |.  6A 00         PUSH 0
005A9383  |.  6A 01         PUSH 1
005A9385  |.  6A 00         PUSH 0
005A9387  |.  6A 00         PUSH 0
005A9389  |.  51            PUSH ECX
005A938A  |.  8D85 D4FEFFFF LEA EAX,[LOCAL.75]
005A9390  |.  50            PUSH EAX
005A9391  |.  FF15 72C25A00 CALL NEAR DWORD PTR DS:[5AC272]          ;  kernel32.CreateProcessA
005A9397  |.  85C0          TEST EAX,EAX
005A9399  |.  75 1A         JNZ SHORT skw.005A93B5
005A939B  |.  6A 00         PUSH 0
005A939D  |.  8D95 D4FEFFFF LEA EDX,[LOCAL.75]
005A93A3  |.  52            PUSH EDX
005A93A4  |.  68 FBC05A00   PUSH skw.005AC0FB                        ;  ASCII "There was an error executing a required program. This program may be corrupt."
005A93A9  |.  6A 00         PUSH 0
005A93AB  |.  FF15 6DC35A00 CALL NEAR DWORD PTR DS:[5AC36D]          ;  USER32.MessageBoxA
005A93B1  |.  33C0          XOR EAX,EAX
005A93B3  |.  EB 54         JMP SHORT skw.005A9409
005A93B5  |>  8B55 18       MOV EDX,[ARG.5]
005A93B8  |.  8B45 0C       MOV EAX,[ARG.2]
005A93BB  |.  8B0A          MOV ECX,DWORD PTR DS:[EDX]
005A93BD  |.  8948 0C       MOV DWORD PTR DS:[EAX+C],ECX
005A93C0  |.  8B55 1C       MOV EDX,[ARG.6]
005A93C3  |.  8B45 0C       MOV EAX,[ARG.2]
005A93C6  |.  8B0A          MOV ECX,DWORD PTR DS:[EDX]
005A93C8  |.  8948 10       MOV DWORD PTR DS:[EAX+10],ECX
005A93CB  |.  68 70110100   PUSH 11170                               ;  UNICODE "ing 2, AuthenticAMD"
005A93D0  |.  8B55 E8       MOV EDX,[LOCAL.6]
005A93D3  |.  52            PUSH EDX
005A93D4  |.  FF15 3FC35A00 CALL NEAR DWORD PTR DS:[5AC33F]          ;  kernel32.WaitForSingleObject
005A93DA  |.  85C0          TEST EAX,EAX
005A93DC  |.  74 1F         JE SHORT skw.005A93FD



堆栈中可以看到:
0013F92C   0013FE64  |ModuleFileName = "C:\DOCUME~2\yusilk\LOCALS~1\Temp\cksX.tmp"
0013F930   0013F9A8  |CommandLine = "runtime.exe AB4 44 50 5A6020 "D:\Crack tools\Crypkey系列\skw主程序脱壳\skw.exe""
0013F934   00000000  |pProcessSecurity = NULL
0013F938   00000000  |pThreadSecurity = NULL
0013F93C   00000001  |InheritHandles = TRUE
0013F940   00000000  |CreationFlags = 0
0013F944   00000000  |pEnvironment = NULL
0013F948   00000000  |CurrentDir = NULL
0013F94C   0013F964  |pStartupInfo = 0013F964
0013F950   0013F954  \pProcessInfo = 0013F954

找到cksX.tmp文件,它位于\Local Settings\Temp,用另一个OllyICE打开cksX.tmp,
cksX.<模块入>/$  E8 07000000   CALL cksX.0040100C
00401005  |.  6A 00         PUSH 0                                   ; /ExitCode = 0
00401007  \.  E8 88150000   CALL <JMP.&KERNEL32.ExitProcess>         ; \ExitProcess
0040100C   $  55            PUSH EBP
0040100D   .  8BEC          MOV EBP,ESP
0040100F   .  83C4 84       ADD ESP,-7C
00401012   .  53            PUSH EBX
00401013   .  56            PUSH ESI
00401014   .  57            PUSH EDI
00401015   .  8D7D 84       LEA EDI,DWORD PTR SS:[EBP-7C]
00401018   .  68 D0070000   PUSH 7D0                                 ; /Timeout = 2000. ms
0040101D   .  E8 D8150000   CALL <JMP.&KERNEL32.Sleep>               ; \Sleep
00401022   .  E8 45070000   CALL cksX.0040176C
00401027   .  84C0          TEST AL,AL
00401029   .  0F84 70020000 JE cksX.0040129F
0040102F   .  FF35 38334000 PUSH DWORD PTR DS:[403338]               ; /ProcessId = 0
00401035   .  E8 48150000   CALL <JMP.&KERNEL32.DebugActiveProcess>  ; \DebugActiveProcess
0040103A   .  85C0          TEST EAX,EAX
0040103C   .  75 18         JNZ SHORT cksX.00401056

入口地址在401000,我们要把入口处的代码E807改一下,改为EBFE。

修改后如下:

cksX.<模块入> $- EB FE         JMP SHORT cksX.<模块入口点>
00401002      00            DB 00
00401003      00            DB 00
00401004   .  006A 00       ADD BYTE PTR DS:[EDX],CH                 ; |
00401007   .  E8 88150000   CALL <JMP.&KERNEL32.ExitProcess>         ; \ExitProcess
0040100C   .  55            PUSH EBP
0040100D   .  8BEC          MOV EBP,ESP
0040100F   .  83C4 84       ADD ESP,-7C
00401012   .  53            PUSH EBX
00401013   .  56            PUSH ESI
00401014   .  57            PUSH EDI
00401015   .  8D7D 84       LEA EDI,DWORD PTR SS:[EBP-7C]
00401018   .  68 D0070000   PUSH 7D0                                 ; /Timeout = 2000. ms
0040101D   .  E8 D8150000   CALL <JMP.&KERNEL32.Sleep>               ; \Sleep
00401022   .  E8 45070000   CALL cksX.0040176C
00401027   .  84C0          TEST AL,AL

保存修改后的文件为cksX.tmp,因为等一下SKW会运行这个文件。这样改目的是让程序进入死循环里,以便调试。
修改完就可以关闭。

继续跟踪来到这里:

005A93C8  |.  8948 10       MOV DWORD PTR DS:[EAX+10],ECX
005A93CB  |.  68 70110100   PUSH 11170                               ;  UNICODE "ing 2, AuthenticAMD"
005A93D0  |.  8B55 E8       MOV EDX,[LOCAL.6]
005A93D3  |.  52            PUSH EDX
005A93D4  |.  FF15 3FC35A00 CALL NEAR DWORD PTR DS:[5AC33F]          ;  kernel32.WaitForSingleObject
005A93DA  |.  85C0          TEST EAX,EAX
005A93DC  |.  74 1F         JE SHORT skw.005A93FD

在这里要把PUSH 11170,Patch为PUSH -1 

Patch后代码为:
005A93CB      6A FF         PUSH -1
005A93CD      90            NOP
005A93CE      90            NOP
005A93CF      90            NOP
005A93D0  |.  8B55 E8       MOV EDX,[LOCAL.6]
005A93D3  |.  52            PUSH EDX
005A93D4  |.  FF15 3FC35A00 CALL NEAR DWORD PTR DS:[5AC33F]          ;  kernel32.WaitForSingleObject
005A93DA  |.  85C0          TEST EAX,EAX

堆栈:
0013F94C   0000003C  |hObject = 0000003C (window)
0013F950   FFFFFFFF  \Timeout = INFINITE
0013F954   0000005C


做完以上操作,按F9放开让程序跑起来,并用OllyICE插件OllyHelper中的Detach功能,脱离SKW进程。
打开进程列表,选择cksX.tmp进程,并附加上该进程,进行调试。

未命名的窗口, 条目 0
 进程=000007E8
 名称=cksX
 路径=C:\DOCUME~2\yusilk\LOCALS~1\Temp\cksX.tmp

附上进程后,按F9,再按F12,停在入口处401000
如下:

cksX.<模块入> $- EB FE         JMP SHORT cksX.<模块入口点>
00401002      00            DB 00
00401003      00            DB 00
00401004   .  006A 00       ADD BYTE PTR DS:[EDX],CH                 ; |
00401007   .  E8 88150000   CALL <JMP.&KERNEL32.ExitProcess>         ; \ExitProcess
0040100C   .  55            PUSH EBP
0040100D   .  8BEC          MOV EBP,ESP
0040100F   .  83C4 84       ADD ESP,-7C
00401012   .  53            PUSH EBX
00401013   .  56            PUSH ESI
00401014   .  57            PUSH EDI
00401015   .  8D7D 84       LEA EDI,DWORD PTR SS:[EBP-7C]
00401018   .  68 D0070000   PUSH 7D0                                 ; /Timeout = 2000. ms
0040101D   .  E8 D8150000   CALL <JMP.&KERNEL32.Sleep>               ; \Sleep
00401022   .  E8 45070000   CALL cksX.0040176C
00401027   .  84C0          TEST AL,AL
00401029   .  0F84 70020000 JE cksX.0040129F
0040102F   .  FF35 38334000 PUSH DWORD PTR DS:[403338]               ; /ProcessId = 0
00401035   .  E8 48150000   CALL <JMP.&KERNEL32.DebugActiveProcess>  ; \DebugActiveProcess
0040103A   .  85C0          TEST EAX,EAX

恢复刚才Patch的代码EBFE为E807,

如下:
cksX.<模块入>/$  E8 07000000   CALL cksX.0040100C
00401005  |.  6A 00         PUSH 0                                   ; /ExitCode = 0
00401007  \.  E8 88150000   CALL <JMP.&KERNEL32.ExitProcess>         ; \ExitProcess
0040100C   $  55            PUSH EBP
0040100D   .  8BEC          MOV EBP,ESP
0040100F   .  83C4 84       ADD ESP,-7C
00401012   .  53            PUSH EBX
00401013   .  56            PUSH ESI
00401014   .  57            PUSH EDI
00401015   .  8D7D 84       LEA EDI,DWORD PTR SS:[EBP-7C]
00401018   .  68 D0070000   PUSH 7D0                                 ; /Timeout = 2000. ms
0040101D   .  E8 D8150000   CALL <JMP.&KERNEL32.Sleep>               ; \Sleep
00401022   .  E8 45070000   CALL cksX.0040176C
00401027   .  84C0          TEST AL,AL
00401029   .  0F84 70020000 JE cksX.0040129F
0040102F   .  FF35 38334000 PUSH DWORD PTR DS:[403338]               ; /ProcessId = 0
00401035   .  E8 48150000   CALL <JMP.&KERNEL32.DebugActiveProcess>  ; \DebugActiveProcess
0040103A   .  85C0          TEST EAX,EAX

在00401035下断。。记住这段代码PUSH DWORD PTR DS:[403338],后面我们会用到它。。让调试进程脱离SKW进程。


00401029   . /0F84 70020000 JE cksX.0040129F
0040102F   . |FF35 38334000 PUSH DWORD PTR DS:[403338]               ; /ProcessId = E84
00401035   . |E8 48150000   CALL <JMP.&KERNEL32.DebugActiveProcess>  ; \DebugActiveProcess

SKW ProcessId = E84

用OllyICE查找模块间调用功能,例出所有函数调用。
查找ContinueDebugEvent,共有3条调用。跟进查看代码。在第2条函数调用我们可以看到以下代码:

0040156D  |> \807D FF CC    CMP BYTE PTR SS:[EBP-1],0CC
00401571  |.  74 1E         JE SHORT cksX.00401591
00401573  |.  68 02000100   PUSH 10002                               ; /ContinueStatus = DBG_CONTINUE
00401578  |.  FF73 08       PUSH DWORD PTR DS:[EBX+8]                ; |ThreadId
0040157B  |.  FF73 04       PUSH DWORD PTR DS:[EBX+4]                ; |ProcessId
0040157E  |.  E8 E70F0000   CALL <JMP.&KERNEL32.ContinueDebugEvent>  ; \ContinueDebugEvent
00401583  |.  68 5C334000   PUSH cksX.0040335C                       ; /pCriticalSection = cksX.0040335C
00401588  |.  E8 37100000   CALL <JMP.&KERNEL32.LeaveCriticalSection>; \LeaveCriticalSection
0040158D  |.  B0 01         MOV AL,1
0040158F  |.  EB 4F         JMP SHORT cksX.004015E0
00401591  |>  6A 00         PUSH 0
00401593  |.  6A 00         PUSH 0
00401595  |.  57            PUSH EDI
00401596  |.  E8 31050000   CALL cksX.00401ACC        ;;;------->
0040159B  |.  83C4 0C       ADD ESP,0C
0040159E  |.  84C0          TEST AL,AL
004015A0  |.  74 22         JE SHORT cksX.004015C4

当SKW进程运行遇到int 3异常时,会来到这里,并传递出现异常的地址到EDI。

SKW创建的的调试进程会计数有多少个代码异常了,进行解码,并恢复代码到SKW,当达到特定次数后,又会重新把解码的代码段用CC来填充。我们要调试进程把所有CC解码,且不能让调试进程再把解码

后的代码重新用CC填充。

跟踪到这里,

00401B64  /$  55            PUSH EBP
00401B65  |.  8BEC          MOV EBP,ESP
00401B67  |.  53            PUSH EBX
00401B68  |.  8B5D 08       MOV EBX,[ARG.1]
00401B6B  |.  8B43 4C       MOV EAX,DWORD PTR DS:[EBX+4C]
00401B6E  |.  3B43 48       CMP EAX,DWORD PTR DS:[EBX+48]
00401B71  |.  75 34         JNZ SHORT cksX.00401BA7
00401B73  |.  8B53 3C       MOV EDX,DWORD PTR DS:[EBX+3C]
00401B76  |.  8B4B 44       MOV ECX,DWORD PTR DS:[EBX+44]
00401B79  |.  FF348A        PUSH DWORD PTR DS:[EDX+ECX*4]
00401B7C  |.  53            PUSH EBX
00401B7D  |.  E8 A2040000   CALL cksX.00402024
00401B82  |.  83C4 08       ADD ESP,8
00401B85  |.  FF43 40       INC DWORD PTR DS:[EBX+40]
00401B88  |.  FF43 44       INC DWORD PTR DS:[EBX+44]
00401B8B  |.  8B43 44       MOV EAX,DWORD PTR DS:[EBX+44]
00401B8E  |.  3B43 48       CMP EAX,DWORD PTR DS:[EBX+48]
00401B91  |.  72 05         JB SHORT cksX.00401B98
00401B93  |.  33D2          XOR EDX,EDX
00401B95  |.  8953 44       MOV DWORD PTR DS:[EBX+44],EDX
00401B98  |>  8B4B 40       MOV ECX,DWORD PTR DS:[EBX+40]
00401B9B  |.  3B4B 48       CMP ECX,DWORD PTR DS:[EBX+48]
00401B9E  |.  72 1A         JB SHORT cksX.00401BBA
00401BA0  |.  33C0          XOR EAX,EAX
00401BA2  |.  8943 40       MOV DWORD PTR DS:[EBX+40],EAX
00401BA5  |.  EB 13         JMP SHORT cksX.00401BBA
00401BA7  |>  FF43 40       INC DWORD PTR DS:[EBX+40]
00401BAA  |.  FF43 4C       INC DWORD PTR DS:[EBX+4C]
00401BAD  |.  8B53 40       MOV EDX,DWORD PTR DS:[EBX+40]
00401BB0  |.  3B53 48       CMP EDX,DWORD PTR DS:[EBX+48]
00401BB3  |.  72 05         JB SHORT cksX.00401BBA
00401BB5  |.  33C9          XOR ECX,ECX
00401BB7  |.  894B 40       MOV DWORD PTR DS:[EBX+40],ECX
00401BBA  |>  8B43 3C       MOV EAX,DWORD PTR DS:[EBX+3C]
00401BBD  |.  8B53 40       MOV EDX,DWORD PTR DS:[EBX+40]
00401BC0  |.  8B4D 0C       MOV ECX,[ARG.2]
00401BC3  |.  890C90        MOV DWORD PTR DS:[EAX+EDX*4],ECX
00401BC6  |.  5B            POP EBX
00401BC7  |.  5D            POP EBP
00401BC8  \.  C3            RETN

我们只要把    00401B71  |.  75 34         JNZ SHORT cksX.00401BA7
这里的代码Patch 为00401B71      EB 34         JMP SHORT cksX.00401BA7

Patch后如下:
00401B64  /$  55            PUSH EBP
00401B65  |.  8BEC          MOV EBP,ESP
00401B67  |.  53            PUSH EBX
00401B68  |.  8B5D 08       MOV EBX,[ARG.1]
00401B6B  |.  8B43 4C       MOV EAX,DWORD PTR DS:[EBX+4C]
00401B6E  |.  3B43 48       CMP EAX,DWORD PTR DS:[EBX+48]
00401B71      EB 34         JMP SHORT cksX.00401BA7
00401B73  |.  8B53 3C       MOV EDX,DWORD PTR DS:[EBX+3C]
00401B76  |.  8B4B 44       MOV ECX,DWORD PTR DS:[EBX+44]
00401B79  |.  FF348A        PUSH DWORD PTR DS:[EDX+ECX*4]
00401B7C  |.  53            PUSH EBX
00401B7D  |.  E8 A2040000   CALL cksX.00402024

我们还要把下面这段代码进行修改

0040156D  |> \807D FF CC    CMP BYTE PTR SS:[EBP-1],0CC
00401571  |.  74 1E         JE SHORT cksX.00401591
00401573  |.  68 02000100   PUSH 10002                               ; /ContinueStatus = DBG_CONTINUE
00401578  |.  FF73 08       PUSH DWORD PTR DS:[EBX+8]                ; |ThreadId
0040157B  |.  FF73 04       PUSH DWORD PTR DS:[EBX+4]                ; |ProcessId
0040157E  |.  E8 E70F0000   CALL <JMP.&KERNEL32.ContinueDebugEvent>  ; \ContinueDebugEvent
00401583  |.  68 5C334000   PUSH cksX.0040335C                       ; /pCriticalSection = cksX.0040335C
00401588  |.  E8 37100000   CALL <JMP.&KERNEL32.LeaveCriticalSection>; \LeaveCriticalSection
0040158D  |.  B0 01         MOV AL,1
0040158F  |.  EB 4F         JMP SHORT cksX.004015E0
00401591  |>  6A 00         PUSH 0
00401593  |.  6A 00         PUSH 0
00401595  |.  57            PUSH EDI
00401596  |.  E8 31050000   CALL cksX.00401ACC
0040159B  |.  83C4 0C       ADD ESP,0C
0040159E  |.  84C0          TEST AL,AL
004015A0  |.  74 22         JE SHORT cksX.004015C4
004015A2  |.  6A 00         PUSH 0                                   ; /RegionSize = 0
004015A4  |.  6A 00         PUSH 0                                   ; |RegionBase = NULL
004015A6  |.  FF35 3C334000 PUSH DWORD PTR DS:[40333C]               ; |hProcess = 000007D0
004015AC  |.  E8 E90F0000   CALL <JMP.&KERNEL32.FlushInstructionCach>; \FlushInstructionCache
004015B1  |.  FF8D E8FDFFFF DEC [LOCAL.134]
004015B7  |.  8D95 30FDFFFF LEA EDX,[LOCAL.180]
004015BD  |.  52            PUSH EDX                                 ; /pContext
004015BE  |.  56            PUSH ESI                                 ; |hThread
004015BF  |.  E8 30100000   CALL <JMP.&KERNEL32.SetThreadContext>    ; \SetThreadContext
004015C4  |>  68 02000100   PUSH 10002                               ; /ContinueStatus = DBG_CONTINUE
004015C9  |.  FF73 08       PUSH DWORD PTR DS:[EBX+8]                ; |ThreadId
004015CC  |.  FF73 04       PUSH DWORD PTR DS:[EBX+4]                ; |ProcessId
004015CF  |.  E8 960F0000   CALL <JMP.&KERNEL32.ContinueDebugEvent>  ; \ContinueDebugEvent
004015D4  |.  68 5C334000   PUSH cksX.0040335C                       ; /pCriticalSection = cksX.0040335C
004015D9  |.  E8 E60F0000   CALL <JMP.&KERNEL32.LeaveCriticalSection>; \LeaveCriticalSection
004015DE  |.  33C0          XOR EAX,EAX
004015E0  |>  5F            POP EDI
004015E1  |.  5E            POP ESI
004015E2  |.  5B            POP EBX
004015E3  |.  8BE5          MOV ESP,EBP
004015E5  |.  5D            POP EBP
004015E6  \.  C3            RETN


修改为下面这样的代码:

0040156D   > \807D FF CC    CMP BYTE PTR SS:[EBP-1],0CC
00401571   .  BF 00104000   MOV EDI,401000      ;-----SKW程序入口地址
00401576   .  6A 00         PUSH 0
00401578   .  6A 00         PUSH 0
0040157A   .  57            PUSH EDI        ;-----出现int 3的地址
0040157B      E8 4C050000   CALL cks1.00401ACC
00401580      83C4 0C       ADD ESP,0C
00401583      83C7 20       ADD EDI,20        ;-----假设最小的CC块大小为20H
00401586      81FF 00BC4E00 CMP EDI,4EC000      ;-----SKW的代码段结束处
0040158C    ^ 72 E8         JB SHORT cks1.00401576    ;-----循环解码
0040158E   .  EB 12         JMP SHORT cks1.004015A2    
00401590      FF35 38334000 PUSH DWORD PTR DS:[403338]    ;-----SKW进程ID
00401596      E8 169F457C   CALL kernel32.DebugActiveProcessStop;-----Detach SKW进程
0040159B      C3            RETN
0040159C      90            NOP
0040159D      90            NOP
0040159E      90            NOP
0040159F      90            NOP
004015A0      90            NOP
004015A1      90            NOP
004015A2   >  6A 00         PUSH 0                                   ; /RegionSize = 0
004015A4   .  6A 00         PUSH 0                                   ; |RegionBase = NULL
004015A6   .  FF35 3C334000 PUSH DWORD PTR DS:[40333C]               ; |hProcess = 000007D0
004015AC   .  E8 E90F0000   CALL <JMP.&KERNEL32.FlushInstructionCach>; \FlushInstructionCache
004015B1   .  FF8D E8FDFFFF DEC DWORD PTR SS:[EBP-218]
004015B7   .  8D95 30FDFFFF LEA EDX,DWORD PTR SS:[EBP-2D0]
004015BD   .  52            PUSH EDX                                 ; /pContext
004015BE   .  56            PUSH ESI                                 ; |hThread
004015BF   .  E8 30100000   CALL <JMP.&KERNEL32.SetThreadContext>    ; \SetThreadContext
004015C4   .  68 02000100   PUSH 10002                               ; /ContinueStatus = DBG_CONTINUE
004015C9   .  FF73 08       PUSH DWORD PTR DS:[EBX+8]                ; |ThreadId
004015CC   .  FF73 04       PUSH DWORD PTR DS:[EBX+4]                ; |ProcessId
004015CF   .  E8 960F0000   CALL <JMP.&KERNEL32.ContinueDebugEvent>  ; \ContinueDebugEvent
004015D4   .  68 5C334000   PUSH cks1.0040335C                       ; /pCriticalSection = cks1.0040335C
004015D9   .  E8 E60F0000   CALL <JMP.&KERNEL32.LeaveCriticalSection>; \LeaveCriticalSection
004015DE   .  33C0          XOR EAX,EAX
004015E0   >  5F            POP EDI
004015E1   .  5E            POP ESI
004015E2   .  5B            POP EBX
004015E3   .  8BE5          MOV ESP,EBP
004015E5   .  5D            POP EBP
004015E6    ^ EB A8         JMP SHORT cks1.00401590

我们还必须在004015CF处下断。按F9,调试进程运行了。并在004015CF断下来,这时用PETools可以把SKW进程Dump下来,另存为Dumped.exe,还可以用ImpREC得到IAT。
由于ImpREC有几个函数没有完全认出,所以要用到PUPE来修改SKW进程,手动修复这几个函数,所以工作还没完。

用PUPE读出SKW进程地址005A6191,2 bytes,读到的是CC25,与我们之前所修改的CC25对应,现在我们要改为EBFE,让程序进入死循环里。以便调试。
这时我们可以完全放开cksX.tmp调试进程了。或者关闭调试进程。


用OllyICE打开进程列表,附加到SKW进程,按F9,再按F12,程序停在这里。恢复EBFE为FF25。



005A6191  - EB FE           JMP SHORT skw.005A6191
005A6193    0060 5A         ADD BYTE PTR DS:[EAX+5A],AH
005A6196    00C3            ADD BL,AL
005A6198    E8 5F000000     CALL skw.005A61FC
005A619D    C705 64605A00 0>MOV DWORD PTR DS:[5A6064],skw.005A6000
005A61A7    C705 68605A00 0>MOV DWORD PTR DS:[5A6068],skw.005A6004
005A61B1    C705 6C605A00 0>MOV DWORD PTR DS:[5A606C],0
005A61BB    C705 70605A00 3>MOV DWORD PTR DS:[5A6070],1234
005A61C5    C705 74605A00 2>MOV DWORD PTR DS:[5A6074],skw.005A6020   ; ASCII "CKSPISH"
005A61CF    6A 00           PUSH 0
005A61D1    FF15 FE605A00   CALL NEAR DWORD PTR DS:[5A60FE]          ; kernel32.GetModuleHandleA
005A61D7    A3 78605A00     MOV DWORD PTR DS:[5A6078],EAX
005A61DC    C705 7C605A00 5>MOV DWORD PTR DS:[5A607C],skw.005A6050   ; ASCII "CKSMDSH"
005A61E6    68 64605A00     PUSH skw.005A6064
005A61EB    E8 40210000     CALL skw.005A8330

用ImpREC发现有几个函数可疑,
011C52C识别为LockResource,用OllyICE查看011C52C+400000 =051C52C

内存数据->7C80CD27=,所对应的函数为

kernel32.SetHandleCount      8BFF            MOV EDI,EDI
7C80CD29                     55              PUSH EBP
7C80CD2A                     8BEC            MOV EBP,ESP
7C80CD2C                     8B45 08         MOV EAX,DWORD PTR SS:[EBP+8]
7C80CD2F                     5D              POP EBP
7C80CD30                     C2 0400         RETN 4
7C80CD33                     90              NOP

011CC4C识别为DestroyCursor,用OllyICE查看011CC4C+400000 =051CC4C
011CC50识别为DestroyCursor,用OllyICE查看011CC50+400000 =051CC50
051CC4C->内存数据=7E42D312,所对应的函数为
051CC50->内存数据=7E42D312,所对应的函数为

USER32.DestroyIcon         /$  8BFF          MOV EDI,EDI
7E42D314                   |.  55            PUSH EBP
7E42D315                   |.  8BEC          MOV EBP,ESP
7E42D317                   |.  6A 01         PUSH 1
7E42D319                   |.  FF75 08       PUSH [ARG.1]
7E42D31C                   |.  E8 09000000   CALL USER32.7E42D32A
7E42D321                   |.  5D            POP EBP
7E42D322                   \.  C2 0400       RETN 4

011CDF8识别为RegisterClipboardFormatA,用OllyICE查看011CDF8+400000 =051CDF8
011CDFC识别为RegisterClipboardFormatA,用OllyICE查看011CDFC+400000 =051CDFC
051CDF8->内存数据=7E418E28,所对应的函数为
051CDFC->内存数据=7E418E28,所对应的函数为

USER32.RegisterWindowMessageA       8BFF          MOV EDI,EDI
7E418E2A                         .  55            PUSH EBP
7E418E2B                         .  8BEC          MOV EBP,ESP
7E418E2D                         .  83EC 10       SUB ESP,10
7E418E30                         .  8365 FC 00    AND DWORD PTR SS:[EBP-4],0
7E418E34                         .  56            PUSH ESI
7E418E35                         .  6A 01         PUSH 1
7E418E37                         .  FF75 08       PUSH DWORD PTR SS:[EBP+8]
7E418E3A                         .  8D45 F0       LEA EAX,DWORD PTR SS:[EBP-10]
7E418E3D                         .  50            PUSH EAX

手动修复以上函数。
再修复IAT表,最后把修复的程序改名为SKW.EXE。。。

运行一下。一切正常。。。。

做完收工。。


2008.7.1