一、破解目标: 联众台球圣手v4.7试用版

二、破解工具:OllyDbg v1.10,ImportREC 1.6 Final,LordPE

三、破解作者:csjwaman

四、破解过程:

1.寻找版本号:


用PEiD扫描,提示为Armadillo 1.xx - 2.xx -> Silicon Realms Toolworks [Overlay]。这其实是误报,实际应为ARM3.60双进程非标准壳。

因为是双进程的,先用以下脚本转换为单进程:

//转单进程脚本
msg "请忽略所有异常,并添加忽略C000001E异常,然后运行本脚本!"
gpa "OpenMutexA","kernel32.dll"
bp $RESULT
esto
exec
pushad
pushfd
push edx
xor eax,eax
push eax
push eax
call kernel32.CreateMutexA
popfd
popad
jmp kernel32.OpenMutexA
ende
bc eip
msg "现已转换成单进程!"
ret


运行脚本后停在:

77E62391 k>  55                   push ebp///停在这里。
77E62392     8BEC                 mov ebp,esp
77E62394     51                   push ecx
77E62395     51                   push ecx
77E62396     837D 10 00           cmp dword ptr ss:[ebp+10],0
77E6239A     56                   push esi
77E6239B     0F84 C2E30100        je 77E80763                                ; 77E80763
77E623A1     64:A1 18000000       mov eax,dword ptr fs:[18]
77E623A7     FF75 10              push dword ptr ss:[ebp+10]

SHIFT+F9运行,出现异常:

00D306A7     A1 3857D400          mov eax,dword ptr ds:[D45738]
00D306AC     8B0D 9455D400        mov ecx,dword ptr ds:[D45594]              ; Ball4.004EC260
00D306B2     8B04B0               mov eax,dword ptr ds:[eax+esi*4]///停在这里。
00D306B5     3341 54              xor eax,dword ptr ds:[ecx+54]
00D306B8     8B0D 9455D400        mov ecx,dword ptr ds:[D45594]              ; Ball4.004EC260
00D306BE     3341 04              xor eax,dword ptr ds:[ecx+4]
00D306C1     8B0D 9455D400        mov ecx,dword ptr ds:[D45594]              ; Ball4.004EC260
00D306C7     3341 74              xor eax,dword ptr ds:[ecx+74]
00D306CA     8B0D 9455D400        mov ecx,dword ptr ds:[D45594]              ; Ball4.004EC260
00D306D0     3341 30              xor eax,dword ptr ds:[ecx+30]
00D306D3     8B0D 9455D400        mov ecx,dword ptr ds:[D45594]              ; Ball4.004EC260
00D306D9     3341 20              xor eax,dword ptr ds:[ecx+20]

出现上述,说明这是非标准加壳方式。现在搜索所有参考文本串,然后查找字符“armVersion”,找到后在上一行就可以看到字符“3.60”。这就是版本号了。



2.寻找OEP和DUMP进程

重新加载程序,下断BP WaitForDebugEvent,断下后堆栈如下:

0012DAC0    004C1D67   /CALL 到 WaitForDebugEvent 来自 Ball4.004C1D61
0012DAC4    0012EB84   |pDebugEvent = 0012EB84///进数据窗口。
0012DAC8    000003E8   \Timeout = 1000. ms

取消断点,然后bp WriteProcessMemory 再F9,内存窗口数据如下:

0012EB84  01 00 00 00 E4 0A 00 00  ...?..
0012EB8C  E8 0A 00 00 01 00 00 80  ?....
0012EB94  00 00 00 00 00 00 00 00  ........
0012EB9C  38 77 49 00 02 00 00 00  8wI....
0012EBA4  00 00 00 00 38 77 49 00  ....8wI.
0012EBAC  38 77 49 00 00 00 00 00  8wI.....
0012EBB4  01 C7 4F E1 00 00 00 00  荗?...

其中497738就是OEP地址了。

ALT+F9返回:

004C5C6E    .  85C0               test eax,eax///返回这里。
004C5C70    .  75 4B              jnz short 004C5CBD                         ;  004C5CBD
004C5C72    .  50                 push eax
004C5C73    .  F7D0               not eax
004C5C75    .  0FC8               bswap eax
004C5C77    .  58                 pop eax

这里搜索所有命令“or eax,FFFFFFF8”,结果:

004C23D6   or eax,FFFFFFF8///双击这行。
004C2933   or eax,FFFFFFF8
004C5C6E   test eax,eax 

双击后来到:

004C238A    > \83BD D0F5FFFF 00   cmp dword ptr ss:[ebp-A30],0/////下断,Shift+F9中断下来  把[ebp-A30]=[0012EB70]=00000005清0
004C2391    .  0F8C A9020000      jl 004C2640                                ;  004C2640
004C2397    .  8B8D D0F5FFFF      mov ecx,dword ptr ss:[ebp-A30]
004C239D    .  3B0D E4254F00      cmp ecx,dword ptr ds:[4F25E4]///注意[4F25E4]  
004C23A3    .  0F8D 97020000      jge 004C2640//解码结束后跳转004C2640,到004C2640处下断
004C23A9    .  8B95 44F6FFFF      mov edx,dword ptr ss:[ebp-9BC]
004C23AF    .  81E2 FF000000      and edx,0FF
004C23B5    .  85D2               test edx,edx
004C23B7    .  0F84 AD000000      je 004C246A                                ;  004C246A
004C23BD    .  6A 00              push 0
004C23BF    .  8BB5 D0F5FFFF      mov esi,dword ptr ss:[ebp-A30]
004C23C5    .  C1E6 04            shl esi,4
004C23C8    .  8B85 D0F5FFFF      mov eax,dword ptr ss:[ebp-A30]
004C23CE    .  25 07000080        and eax,80000007
004C23D3    .  79 05              jns short 004C23DA                         ;  004C23DA
004C23D5    .  48                 dec eax
004C23D6    .  83C8 F8            or eax,FFFFFFF8///来到这里。
004C23D9    .  40                 inc eax
004C23DA    >  33C9               xor ecx,ecx
004C23DC    .  8A88 800A4F00      mov cl,byte ptr ds:[eax+4F0A80]
004C23E2    .  8B95 D0F5FFFF      mov edx,dword ptr ss:[ebp-A30]
004C23E8    .  81E2 07000080      and edx,80000007
004C23EE    .  79 05              jns short 004C23F5                         ;  004C23F5
004C23F0    .  4A                 dec edx
004C23F1    .  83CA F8            or edx,FFFFFFF8
004C23F4    .  42                 inc edx
004C23F5    >  33C0               xor eax,eax
004C23F7    .  8A82 810A4F00      mov al,byte ptr ds:[edx+4F0A81]
004C23FD    .  8B3C8D 60C24E00    mov edi,dword ptr ds:[ecx*4+4EC260]
004C2404    .  333C85 60C24E00    xor edi,dword ptr ds:[eax*4+4EC260]
004C240B    .  8B8D D0F5FFFF      mov ecx,dword ptr ss:[ebp-A30]
004C2411    .  81E1 07000080      and ecx,80000007
004C2417    .  79 05              jns short 004C241E                         ;  004C241E
004C2419    .  49                 dec ecx
004C241A    .  83C9 F8            or ecx,FFFFFFF8
004C241D    .  41                 inc ecx
004C241E    >  33D2               xor edx,edx
004C2420    .  8A91 820A4F00      mov dl,byte ptr ds:[ecx+4F0A82]
004C2426    .  333C95 60C24E00    xor edi,dword ptr ds:[edx*4+4EC260]
004C242D    .  8B85 D0F5FFFF      mov eax,dword ptr ss:[ebp-A30]
004C2433    .  99                 cdq
004C2434    .  B9 1C000000        mov ecx,1C
004C2439    .  F7F9               idiv ecx
004C243B    .  8BCA               mov ecx,edx
004C243D    .  D3EF               shr edi,cl
004C243F    .  83E7 0F            and edi,0F
004C2442    .  03F7               add esi,edi
004C2444    .  8B15 D4254F00      mov edx,dword ptr ds:[4F25D4]
004C244A    .  8D04B2             lea eax,dword ptr ds:[edx+esi*4]
004C244D    .  50                 push eax
004C244E    .  8B8D D0F5FFFF      mov ecx,dword ptr ss:[ebp-A30]
004C2454    .  51                 push ecx
004C2455    .  E8 FF1F0000        call 004C4459                              ;  004C4459
004C245A    .  83C4 0C            add esp,0C
004C245D    .  25 FF000000        and eax,0FF///这里开始Patch 
004C2462    .  85C0               test eax,eax
004C2464    .  0F84 D6010000      je 004C2640                                ;  004C2640
004C246A    >  837D D8 00         cmp dword ptr ss:[ebp-28],0
004C246E    .  75 28              jnz short 004C2498                         ;  004C2498
004C2470    .  8B15 B8C24E00      mov edx,dword ptr ds:[4EC2B8]
004C2476    .  3315 CCC24E00      xor edx,dword ptr ds:[4EC2CC]
004C247C    .  3315 D0C24E00      xor edx,dword ptr ds:[4EC2D0]
004C2482    .  81E2 00002000      and edx,200000
004C2488    .  85D2               test edx,edx

Patch代码:

004C245D       FF85 D0F5FFFF      inc dword ptr ss:[ebp-A30]
004C2463       C705 E8254F00 0100>mov dword ptr ds:[4F25E8],1
004C246D     ^ E9 18FFFFFF        jmp 004C238A                               ;  004C238A
004C2472       90                 nop
004C2473       90                 nop

用以上代码欺骗主进程解码。

SHIFT+F9,程序断在:

004C2640    > \E9 E00F0000        jmp 004C3625///断在这里。
004C2645    >  8B0D A0C24E00      mov ecx,dword ptr ds:[4EC2A0]
004C264B    .  81F1 050000C0      xor ecx,C0000005
004C2651    .  398D D8F5FFFF      cmp dword ptr ss:[ebp-A28],ecx

此时子进程代码全部解开,运行LordPE,完全Dump出子进程。



3.寻找IAT


将DUMP出来的程序OEP改为97738,然后用OD载入,跟踪几步就可以找到IAT。

004063B8   - FF25 0CD24900        jmp dword ptr ds:[49D20C]
004063BE     8BC0                 mov eax,eax
004063C0   - FF25 08D24900        jmp dword ptr ds:[49D208]                  ; kernel32.LocalAlloc
004063C6     8BC0                 mov eax,eax
004063C8   - FF25 04D24900        jmp dword ptr ds:[49D204]                  ; kernel32.TlsGetValue
004063CE     8BC0                 mov eax,eax
004063D0   - FF25 00D24900        jmp dword ptr ds:[49D200]                  ; kernel32.TlsSetValue
004063D6     8BC0                 mov eax,eax

0049D13C  00 00 00 00 12 9D F6 77  ....濚w
0049D144  80 B3 F5 77 A0 B2 F5 77  初w_蝉w
0049D14C  45 A7 E5 77 CB 15 E6 77  Eуw?鎤
0049D154  72 AC E5 77 A0 60 E5 77  rw_`鍂
。。。。。。
0049D884  CB 3D 40 77 8B 88 D1 00  ?@w媹?
0049D88C  58 0F DB 77 C3 88 D1 00  X踳脠?
0049D894  6B 65 72 6E 65 6C 33 32  kernel32
0049D89C  2E 64 6C 6C 00 00 00 00  .dll....

IAT地址49D13C 大小49D894-49D13C=758


重新载入主程序,BP DebugActiveProcess  中断后看堆栈:

0012DAC4    004C1BDB   /CALL 到 DebugActiveProcess 来自 Ball4.004C1BD5
0012DAC8    00000F2C   \ProcessId = F2C

新开一个OllyDbg,附加进程ID E2C的子进程(每次子进程ID会不同)
F9,再F12,会暂停在EP处:

004D1999 B>/$- EB FE              jmp short 004D1999 ///在此死循环。
004D199B   |?  EC                 in al,dx
004D199C   |.  6A FF              push -1
004D199E   |.  68 501C4F00        push 4F1C50
004D19A3   |.  68 80134D00        push 4D1380                                ;  SE handler installation
004D19A8   |.  64:A1 00000000     mov eax,dword ptr fs:[0]
004D19AE   |.  50                 push eax
004D19AF   |.  64:8925 00000000   mov dword ptr fs:[0],esp

将4D1999处代码改回558B :

004D1999 B>    55                 push ebp///改回后的代码。
004D199A       8BEC               mov ebp,esp
004D199C       6A FF              push -1
004D199E       68 501C4F00        push 4F1C50
004D19A3       68 80134D00        push 4D1380                                ;  SE handler installation
004D19A8       64:A1 00000000     mov eax,dword ptr fs:[0]
004D19AE       50                 push eax

现在再用上述脚本转换为单进程。然后下断HE GetModuleHandleA    SHIFT+F9 断下后堆栈如下:


0012ECC8    77C059FC   /CALL 到 GetModuleHandleA 来自 msvcrt.77C059F6
0012ECCC    77BE31AC   \pModule = "kernel32.dll"
。。。。。。
0012BF20    00BFC807   /CALL 到 GetModuleHandleA 来自 00BFC801
0012BF24    00C0D6C8   \pModule = "kernel32.dll"
0012BF28    00C0E67C   ASCII "VirtualAlloc"
0012BF20    00BFC824   /CALL 到 GetModuleHandleA 来自 00BFC81E
0012BF24    00C0D6C8   \pModule = "kernel32.dll"
0012BF28    00C0E670   ASCII "VirtualFree"

0012BC98    00BE799B   /CALL 到 GetModuleHandleA 来自 00BE7995
0012BC9C    0012BDD4   \pModule = "kernel32.dll"


堆栈如上变化时,取消GetModuleHandleA处断点,Alt+F9返回:

00BE799B     8B0D E011C100        mov ecx,dword ptr ds:[C111E0]
00BE79A1     89040E               mov dword ptr ds:[esi+ecx],eax
00BE79A4     A1 E011C100          mov eax,dword ptr ds:[C111E0]
00BE79A9     393C06               cmp dword ptr ds:[esi+eax],edi
00BE79AC     75 16                jnz short 00BE79C4
00BE79AE     8D85 B4FEFFFF        lea eax,dword ptr ss:[ebp-14C]
00BE79B4     50                   push eax
00BE79B5     FF15 CC80C000        call dword ptr ds:[C080CC]                 ; kernel32.LoadLibraryA
00BE79BB     8B0D E011C100        mov ecx,dword ptr ds:[C111E0]
00BE79C1     89040E               mov dword ptr ds:[esi+ecx],eax
00BE79C4     A1 E011C100          mov eax,dword ptr ds:[C111E0]
00BE79C9     393C06               cmp dword ptr ds:[esi+eax],edi
00BE79CC     0F84 AD000000        je 00BE7A7F///改为JMP
00BE79D2     33C9                 xor ecx,ecx
00BE79D4     8B03                 mov eax,dword ptr ds:[ebx]
00BE79D6     3938                 cmp dword ptr ds:[eax],edi
00BE79D8     74 06                je short 00BE79E0
00BE79DA     41                   inc ecx
00BE79DB     83C0 0C              add eax,0C
00BE79DE   ^ EB F6                jmp short 00BE79D6
00BE79E0     8BC1                 mov eax,ecx
00BE79E2     C1E0 02              shl eax,2
。。。。。。
00BE7A7F     83C3 0C              add ebx,0C
00BE7A82     83C6 04              add esi,4
00BE7A85     397B FC              cmp dword ptr ds:[ebx-4],edi
00BE7A88   ^ 0F85 CCFEFFFF        jnz 00BE795A
00BE7A8E     EB 03                jmp short 00BE7A93

SHIFT+F9来到OEP处,由于代码没有解密,所以程序无法运行。

00497738     66:C7                ??? ///停在这里。
0049773A     6C                   ins byte ptr es:[edi],dx
0049773B     DFF7                 fcomip st,st(7)
0049773D     BC 38B44705          mov esp,547B438
00497742     80B407 A176A392 C4   xor byte ptr ds:[edi+eax+92A376A1],0C4
0049774A     2915 33C780B4        sub dword ptr ds:[B480C733],edx


用ImportREC手动填入OEP=97738,RVA=9D13C,SIZE=758,去掉不可用的指针即可获得完整的IAT。

FIX,完工。