先贴个查themida版本的脚本(可查DLL,刚看Kissy的录象学的呵呵):
var tmp
var tmpbp
bc
BPHWCALL
gpa "LoadLibraryA", "kernel32.dll"
mov tmpbp,$RESULT
cmp tmpbp,0
je exit
bphws tmpbp ,"x"
loop:
esto
mov tmp,[esp+04]
cmp [tmp],"NTDLL" //为NTDLL的时候themida段解压完成
jnz loop
bphwc tmpbp
rtu
GMEMI eip, MEMORYBASE
mov tmp,$RESULT
BPHWCALL
find tmp,#000004000000322E# //特征码
cmp $RESULT,0
jz next
jmp message
next:
find tmp,#000004000000312E# //特征码
cmp $RESULT,0
jz exit
message:
mov tmp,$RESULT
mov verStr,"Themida/winlicense version: "
add tmp,6
READSTR [tmp],5
add verStr,$RESULT
msg verStr
exit:
ret
OD载入DLL,停在入口
1021A000 > 83EC 04 sub esp, 4 //////此处下硬件执行端点
1021A003 50 push eax
1021A004 53 push ebx
1021A005 E8 01000000 call 1021A00B
1021A00A CC int3
1021A00B 58 pop eax
1021A00C 8BD8 mov ebx, eax
1021A00E 40 inc eax
1021A00F 2D 00601300 sub eax, 136000
1021A014 2D EFDF6000 sub eax, 60DFEF
1021A019 05 E4DF6000 add eax, 60DFE4
1021A01E 803B CC cmp byte ptr [ebx], 0CC
1021A021 75 19 jnz short 1021A03C
1021A023 C603 00 mov byte ptr [ebx], 0
1021A026 BB 00100000 mov ebx, 1000
1021A02B 68 5401E762 push 62E70154
1021A030 68 34175C6E push 6E5C1734
1021A035 53 push ebx
1021A036 50 push eax
1021A037 E8 0A000000 call 1021A046
1021A03C 83C0 14 add eax, 14
1021A03F 894424 08 mov dword ptr [esp+8], eax
1021A043 5B pop ebx
1021A044 58 pop eax
1021A045 C3 retn
下完硬断直接点F9运行,再关闭Loaddll窗口,断在壳入口,F7走,没几步就到OEP
100E7563 68 BA3F0A10 push 100A3FBA
100E7568 833C24 00 cmp dword ptr [esp], 0
100E756C 75 09 jnz short 100E7577
100E756E 83C4 04 add esp, 4
100E7571 B8 01000000 mov eax, 1
100E7576 C3 retn
OEP:
100A3FBA . 837C24 08 01 cmp dword ptr [esp+8], 1
100A3FBF . 75 05 jnz short 100A3FC6
100A3FC1 . E8 70030000 call 100A4336
100A3FC6 > FF7424 04 push dword ptr [esp+4]
100A3FCA . 8B4C24 10 mov ecx, dword ptr [esp+10]
100A3FCE . 8B5424 0C mov edx, dword ptr [esp+C]
100A3FD2 . E8 CDFEFFFF call 100A3EA4
100A3FD7 . 59 pop ecx
100A3FD8 . C2 0C00 retn 0C
100A3FDB $ 6A 14 push 14
100A3FDD . 68 50300C10 push 100C3050
100A3FE2 . E8 85010000 call 100A416C
100A3FE7 . 8365 FC 00 and dword ptr [ebp-4], 0
100A3FEB > FF4D 10 dec dword ptr [ebp+10]
100A3FEE . 78 3A js short 100A402A
100A3FF0 . 8B4D 08 mov ecx, dword ptr [ebp+8]
100A3FF3 . 2B4D 0C sub ecx, dword ptr [ebp+C]
100A3FF6 . 894D 08 mov dword ptr [ebp+8], ecx
100A3FF9 . FF55 14 call dword ptr [ebp+14]
右键查找->所有模块间的调用,点几个地址一看,调用方法分2种
一种从输入表取地址
10007B37 |. 8B1D B8600A10 mov ebx, dword ptr [100A60B8] ; kernel32.InterlockedDecrement
10007B3D |. 74 0E je short 10007B4D
10007B3F |. 57 push edi ; /pVar
10007B40 |. FFD3 call ebx ; \InterlockedDecrement
另一种直接调用地址
100499B2 6A 00 push 0
100499B4 6A 00 push 0
100499B6 51 push ecx
100499B7 90 nop
100499B8 E8 381CCD67 call USER32.InvalidateRect //call 77D1B5F5
100499BD 85C0 test eax, eax
后一种显然不行,DLL会重定位。看来需要处理下输入表。
数据窗口看下现成的输入表,Cltr G 100A60B8, 上下拉一下100A60B8,明显是个连续的输入表
猜测应该是个完整的输入表吧(可以随便找一个 下硬件写入断点跟到输入表处理)。
我懒,也看不明白TMD具体怎么处理的输入表,干脆就拿这个完整的输入表修复那些直接调用的地址。先把这个输入表保存一份 从100A6000~100A6720
找个直接调用的地址 100499B9 下硬件写入断点 重新载入2次断下后断在地址写入:
10205D81 8847 04 mov byte ptr [edi+4], al
10205D84 8B85 E918100A mov eax, dword ptr [ebp+A1018E9]
10205D8A 2BC7 sub eax, edi
10205D8C 83E8 04 sub eax, 4
10205D8F AB stos dword ptr es:[edi] ///此处EDI既是100499B9
10205D90 AD lods dword ptr [esi]
10205D91 C746 FC 0000000>mov dword ptr [esi-4], 0
这里就是直接写调用地址的地方。
删除原来的断点,重新载入DLL,在10205D90, OEP:100A3FBA 下硬件执行断点
F9执行到10205D90断下, 此时100A6000的内容还是空的,把原来保存的输入表复制过来
到这里就可以写个脚本:
var iattmp
var tmp
next:
cmp eip, 10205D90 ////断在OEP就结束
jnz out
mov tmp, 100A6000 ///从保存的完整输入表里搜索
mov iattmp,eax
add iattmp,edi
cmp iattmp,XXXXXXX ///DLL起始地址 保证是输入函数
jb loopiat:
cmp iattmp,XXXXXXX////DLL模块末地址
jb nexttmp
loopiat:
cmp iattmp, [tmp]
jnz iatadd
sub edi,6
repl edi, #90E9#, #FF25#, 2 ///替换成输入表的形式CALL [100A6XXX]
repl edi, #90E8#, #FF15#, 2
add edi,2
mov [edi],tmp
add edi,4
esto
jmp nexttmp
iatadd:
add tmp,4
cmp tmp, 100A6720
jnz loopiat
nexttmp:
esto
jmp next
msg "!!!!!!"
out:
pause
跑这个脚本,够慢的, 哈哈 刚学 不会写。
最后停到OEP LordPE->loaddll, ImportREC pickdll修复输入表。
完工了一大半了,最后重定位吧。
找个带固定地址的地方,就开头吧
10001000 . 8BC1 mov eax, ecx
10001002 . C700 90670A10 mov dword ptr [eax], 100A6790
10001008 . C3 retn
在10001004下硬件写入断点,2次断下后断在
101F7AF5 /0F84 81000000 je 101F7B7C
101F7AFB |81E3 FF0F0000 and ebx, 0FFF
101F7B01 |03D8 add ebx, eax
101F7B03 |83BD 351F100A 0>cmp dword ptr [ebp+A101F35], 0 ////此处EBX为需要重定位的地址
101F7B0A |0F84 1B000000 je 101F7B2B
101F7B10 |807B FF C5 cmp byte ptr [ebx-1], 0C5
101F7B14 |0F85 11000000 jnz 101F7B2B
101F7B1A |83BD C128100A 0>cmp dword ptr [ebp+A1028C1], 0
101F7B21 |0F84 04000000 je 101F7B2B
101F7B27 |C643 FF E9 mov byte ptr [ebx-1], 0E9
101F7B2B |807B FE C5 cmp byte ptr [ebx-2], 0C5
101F7B2F |0F85 19000000 jnz 101F7B4E
101F7B35 |807B 03 90 cmp byte ptr [ebx+3], 90
101F7B39 |0F85 0F000000 jnz 101F7B4E
101F7B3F |C643 FE E9 mov byte ptr [ebx-2], 0E9
101F7B43 |0F84 33000000 je 101F7B7C
101F7B49 |E9 1E000000 jmp 101F7B6C
101F7B4E |807B FE CC cmp byte ptr [ebx-2], 0CC
101F7B52 |0F85 14000000 jnz 101F7B6C
101F7B58 |807B 03 90 cmp byte ptr [ebx+3], 90
101F7B5C |0F85 0A000000 jnz 101F7B6C
101F7B62 |C643 FE E8 mov byte ptr [ebx-2], 0E8
101F7B66 |0F84 10000000 je 101F7B7C
101F7B6C |813B 90909090 cmp dword ptr [ebx], 90909090
101F7B72 |0F84 04000000 je 101F7B7C
101F7B78 |2933 sub dword ptr [ebx], esi ///断在这
101F7B7A |013B add dword ptr [ebx], edi ; CrySyste.10000000
101F7B7C \83C1 02 add ecx, 2
101F7B7F 83EA 02 sub edx, 2
这里要在上面注释的地方补丁,不然上面处理的输入表没法重定位了。在101F7B03jmp 打个补丁就行了..有点要注意,有的DLL比较大,HideOd分配的内存不够用,需要改下HideOd VirtualAlloc分配的大小。最后Loadpe加个差不多大的区段, 把重定位的补丁加进去,ReloREC修复下OK了。
中间出现异常结束程序基本就是OD没藏好。可能隐藏插件有兼容性,我2台电脑同样设置,一台没问题,另一台总是时不时异常。我开始还以为什么anti,搞的我郁闷了2天,换台电脑才脱了。
是国外某游戏的DLL,连接不放了。
初次学习脱壳,失误难免。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)