没想发帖太少,不能发到『软件保护与分析』版块。。
不好意思,用记事本写的笔记。。。将就着看吧。
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
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!