想了想 还是发这儿比较合适。
这篇希望是自己第一篇,关于导入表方面的手记 。 紕漏請指正.
很乱
文中所用OD :OllyICE + Phant0m +StrongOD
调试文件为 1.02试用TTP 主程序. (貌似 .记得不清楚)
TT 的文件头变异使OD 不能正常识别
解決可见
TTProtect ANIT 原理小窥
http://www.unpack.cn/viewthread.php?tid=26393&extra=page%3D1
OD地址跟bujin888的不同
找和改的方法调试自己的OD
bp CreateFileA
回到程序流程
和能正常加载的PE文件对比
SEARCH
837DF40275138D4E505168EAC14B00E83563FFFF83C408
改作
837DF402EB138D4E505168EAC14B00E83563FFFF83C408
跳过后正常加载。
把改好的OD 储存
在碰主程序前我们先看看输入表
TTProtect.exe
初步看到了TT 调用了LoadLibraryA GetProcAddress
估计是定位原导入表API 所用。
可以考虑设断点查看流程。
用修改好的OD加载 TTPROTECT.EXE
设开始时断在系统断点
下断bp LoadLibraryA
第一次 gdi32.dll
第二次是加载kernel32.dll CALL 来源是TTPROTECT.exe中
得知这是解密流程,ALT+F9返回011E556C
FPU中eax,ecx,ebp,edi 都储存了KERNEL32中一些地址 EAX的是基址
EAX 7C800000 kernel32.7C800000
ECX 7C801BF6 kernel32.7C801BF6
EDX 00150608
EBX 00000000
ESP 0012FF84
EBP 7C801D77 kernel32.LoadLibraryA
ESI 0000000C
EDI 7C80ADA0 kernel32.GetProcAddress
EIP 011E556C TTProtec.011E556C
011E556C 8B2D 304F1E01 mov ebp, dword ptr [11E4F30]
011E5572 8BF0 mov esi, eax esi变成KERNEL32基址
011E5574 33C0 xor eax, eax
011E5576 3BEB cmp ebp, ebx
011E5578 C6C2 C7 mov dl, 0C7
011E557B 0F8E 20000000 jle 011E55A1
011E5581 8A0C05 344F1E01 mov cl, byte ptr [eax+11E4F34] \
011E5588 32CA xor cl, dl |
011E558A 888C04 10000000 mov byte ptr [esp+eax+10], cl |--明显地这里是一个異或的CYCLE 讀表XOR
011E5591 81C0 01000000 add eax, 1 |获得API名字符串 再写进堆棧
011E5597 32D1 xor dl, cl /
011E5599 3BC5 cmp eax, ebp -这里检查是否完畢
011E559B ^ 0F8C E0FFFFFF jl 011E5581
011E55A1 8D8C24 10000000 lea ecx, dword ptr [esp+10] ecx 变成virtualalloc
011E55A8 51 push ecx virtualalloc字串进棧
011E55A9 56 push esi 7C800000 哟
011E55AA 889C2C 18000000 mov byte ptr [esp+ebp+18], bl
011E55B1 FFD7 call edi 查找API 地址
011E55B3 8B2D 714A1E01 mov ebp, dword ptr [11E4A71] 这里ptr [11E4A71]中的值搬进EBP 再次構作解密循環
011E55B9 8905 05031E01 mov dword ptr [11E0305], eax 很明显 干这么多是找ADDRESS 当然要保存吧
011E55BF 33C0 xor eax, eax
011E55C1 3BEB cmp ebp, ebx
011E55C3 C6C2 C7 mov dl, 0C7
011E55C6 0F8E 2C000000 jle 011E55F8
下两句没看出来
011E55CC E9 07000000 jmp 011E55D8
011E55D1 8DA424 00000000 lea esp, dword ptr [esp] 花指令?!
以下的是解密下一個項的循環 跟上面大多一样
011E55D8 8A0C05 754A1E01 mov cl, byte ptr [eax+11E4A75]
011E55DF 32CA xor cl, dl
011E55E1 888C04 10000000 mov byte ptr [esp+eax+10], cl
011E55E8 81C0 01000000 add eax, 1
011E55EE 32D1 xor dl, cl
011E55F0 3BC5 cmp eax, ebp
011E55F2 ^ 0F8C E0FFFFFF jl 011E55D8
011E55F8 8D9424 10000000 lea edx, dword ptr [esp+10] 这次使用EDX
011E55FF 52 push edx
011E5600 56 push esi
011E5601 889C2C 18000000 mov byte ptr [esp+ebp+18], bl
011E5608 FFD7 call edi 找virtualfree地址
011E560A 8B2D B7511E01 mov ebp, dword ptr [11E51B7] 再構循環 可见EBP在解密的过程中很重要 和循環次數有關不能錯
011E5610 8905 1D071E01 mov dword ptr [11E071D], eax 保存 注意 不同循環所解出的地址分得比较开
011E5616 33C0 xor eax, eax
011E5618 3BEB cmp ebp, ebx
011E561A C6C2 C7 mov dl, 0C7
011E5854 E9 07000000 jmp 011E5860
011E5859 8D1C1D 00000000 lea ebx, dword ptr [ebx]花指令?!
011E5860 8A0C05 46491E01 mov cl, byte ptr [eax+11E4946]
011E5867 32CA xor cl, dl
011E5869 888C04 10000000 mov byte ptr [esp+eax+10], cl
011E5870 81C0 01000000 add eax, 1
011E5876 32D1 xor dl, cl
011E5878 3BC5 cmp eax, ebp
011E587A ^ 0F8C E0FFFFFF jl 011E5860
011E5880 8D8C24 10000000 lea ecx, dword ptr [esp+10]
011E5887 51 push ecx
011E5888 56 push esi
011E5889 889C2C 18000000 mov byte ptr [esp+ebp+18], bl
011E5890 FFD7 call edi
011E5892 8B2D 92541E01 mov ebp, dword ptr [11E5492]
011E5898 8905 88011E01 mov dword ptr [11E0188], eax
011E589E 33C0 xor eax, eax
011E58A0 3BEB cmp ebp, ebx
多COPY份作对比
向下翻翻11E5A21 暫時解密完了.
看看以下如何处理
EAX 7C80C058 kernel32.ExitThread
ECX 7C939AEB ntdll.7C939AEB
EDX 7C99C0D8 ntdll.7C99C0D8
EBX 00000000
ESP 0012FF90
EBP 0000000A
ESI 7C800000 kernel32.7C800000
EDI 7C80ADA0 kernel32.GetProcAddress
壳把这两个重要的API地址提取到ECX EDX 然后把堆棧中的数据弹出
011E5A21 8B0D 56E11D01 mov ecx, dword ptr [11DE156] ; kernel32.LoadLibraryA
011E5A27 8B15 5AE11D01 mov edx, dword ptr [11DE15A] ; kernel32.GetProcAddress
011E5A2D 5F pop edi ; kernel32.GetProcAddress
011E5A2E 5E pop esi
011E5A2F 5D pop ebp
011E5A30 8905 5AF61D01 mov dword ptr [11DF65A], eax
011E5A36 890D F4FA1D01 mov dword ptr [11DFAF4], ecx 中和以上 这里其实是一个把地址提出再保存的过程
011E5A3C 8915 65F11D01 mov dword ptr [11DF165], edx
011E5A42 5B pop ebx
011E5A43 81C4 20000000 add esp, 20 \ 本来ESP指向字串ExitThread 但现在跳到空白处
011E5A49 50 push eax |---- 在分别PUSH进一些參數.
011E5A4A 57 push edi |
011E5A4B 53 push ebx /
011E5A4C 9C pushfd
011E5A4D E8 03000000 call 011E5A55
有部分获得地址后马上CALL 后续 @@
总结:
1)文件头變異
2)API一贯 用LoadLibraryA 和 GetProcAddress 恢复并保存.
3)解密地址过程通用的地方如下
jle XXXXXXXX 地址相对
mov cl, byte ptr [FPU+XXXXXXXX] \ 重点
* xor cl, dl |
* mov byte ptr [esp+eax+10], cl |--明显地这里是一个異或的CYCLE 讀表XOR
* add eax, 1 |获得API名字符串 再写进堆棧
* xor dl, cl /
* cmp eax, ebp -这里检查是否完畢
jl XXXXXXXX 向上的循環
lea FPU, dword ptr [esp+10] FPU 和下面一句對應.
push FPU Api字串进棧
* push esi 7C800000 哟
* mov byte ptr [esp+ebp+18], bl
* call edi 查找API 地址
mov ebp, dword ptr [XXXXXXXX] 这里再次構作解密循環?
mov dword ptr [XXXXXXXX], eax 很明显 干这么多是找ADDRESS 当然要保存吧
* xor eax, eax
* cmp ebp, ebx
* mov dl, 0C7
主要相连而不变的有以上3塊
刚才好像看见有另一种,是查找地址后马上CALL的 。先玩网游去。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)