小菜对于TMD1.82分析
大牛们的强大.自己也要努力,当然有时看脚本,有时出现这样,那样特征码.说实话我根无法知道这样的特
征是在那提取的为什么要在那.要知道这些也只有自己通过实践去找到答案了.
我选择的是Themida v1.8.2.0加壳程序,加壳设置除了没有选择OEP处理,其它都是默认的设置.好了
既然加好壳了我来去OEP看看吧!
我通过对VirtualAllocEx函数下断,按Shift+F9 十九次程序运行,OK那我就按十八次后删除断点,再在代码段下
在访问上设置F2断点,断在此处。00419F77 8BF0 mov esi,eax
00419F79 A1 80F84400 mov eax,dword ptr ds:[0x44F880]
00419F7E 8906 mov dword ptr ds:[esi],eax
00419F80 8D56 04 lea edx,dword ptr ds:[esi+0x4]
00419F83 B8 ECD34400 mov eax,delphi7?0044D3EC
00419F88 B9 02000000 mov ecx,0x2
00419F8D E8 2689FEFF call delphi7?004028B8
00419F92 BA 2C9F4100 mov edx,delphi7?00419F2C
00419F97 8D46 05 lea eax,dword ptr ds:[esi+0x5]
00419F9A E8 ADFFFFFF call delphi7?00419F4C
00419F9F 8946 06 mov dword ptr ds:[esi+0x6],eax
00419FA2 8D5E 0A lea ebx,dword ptr ds:[esi+0xA]
00419FA5 C603 E8 mov byte ptr ds:[ebx],0xE8
00419FA8 8D56 04 lea edx,dword ptr ds:[esi+0x4]
00419FAB 8BC3 mov eax,ebx
00419FAD E8 9AFFFFFF call delphi7?00419F4C
复制代码F8单步会来到:0044 CAA8 A1 B8DF4400 mov eax,dword ptr ds:[0x44DFB8]
0044CA AD 8B00 mov eax,dword ptr ds:[eax]
0044CAAF E8 9CE6FFFF call delphi7?0044B150
0044CAB4 8B0D 94E04400 mov ecx,dword ptr ds:[0x44E094] ; delphi7?0044FBD0
0044CABA A1 B8DF4400 mov eax,dword ptr ds:[0x44DFB8]
0044CABF 8B00 mov eax,dword ptr ds:[eax]
0044CAC1 8B15 F0C64400 mov edx,dword ptr ds:[0x44C6F0] ; delphi7?0044C73C
0044CAC7 E8 9CE6FFFF call delphi7?0044B168
0044CACC A1 B8DF4400 mov eax,dword ptr ds:[0x44DFB8]
0044CAD1 8B00 mov eax,dword ptr ds:[eax]
0044CAD3 E8 10E7FFFF call delphi7?0044B1E8
0044CAD8 E8 4372FBFF call delphi7?00403D20
0044CADD 8D40 00 lea eax,dword ptr ds:[eax]
复制代码向上拉就看到这段代挺像delphi程序0044CA98 55 push ebp
0044CA99 8BEC mov ebp,esp
0044CA9B 83C4 F0 add esp,-0x10
0044CA9E B8 B8C84400 mov eax,delphi7?0044C8B8
0044CAA3 E8 2091FBFF call delphi7?00405BC8
0044CAA8 A1 B8DF4400 mov eax,dword ptr ds:[0x44DFB8]
0044CAAD 8B00 mov eax,dword ptr ds:[eax]
0044CAAF E8 9CE6FFFF call delphi7?0044B150
0044CAB4 8B0D 94E04400 mov ecx,dword ptr ds:[0x44E094] ; delphi7?0044FBD0
0044CABA A1 B8DF4400 mov eax,dword ptr ds:[0x44DFB8]
0044CABF 8B00 mov eax,dword ptr ds:[eax]
0044CAC1 8B15 F0C64400 mov edx,dword ptr ds:[0x44C6F0] ; delphi7?0044C73C
0044CAC7 E8 9CE6FFFF call delphi7?0044B168
0044CACC A1 B8DF4400 mov eax,dword ptr ds:[0x44DFB8]
0044CAD1 8B00 mov eax,dword ptr ds:[eax]
0044CAD3 E8 10E7FFFF call delphi7?0044B1E8
0044CAD8 E8 4372FBFF call delphi7?00403D20
0044CADD 8D40 00 lea eax,dword ptr ds:[eax
复制代码我们去第一个CALL里看看,可以到jmp [xxxxxxxx]被处理成这样记个来吧00405B04 90 nop
00405B05 - E9 56B26D02 jmp 02AE0D60
00405B0A 8BC0 mov eax,eax
00405B0C 90 nop
00405B0D - E9 DEAD6D02 jmp 02AE08F0
00405B12 8BC0 mov eax,eax
00405B14 90 nop
00405B15 - E9 9FAC6D02 jmp 02AE07B9
00405B1A 8BC0 mov eax,eax
00405B1C 90 nop
00405B1D - E9 78A96D02 jmp 02AE049A
复制代码好了重载OD,既然加壳软件对代码作了处理.那我们就去跟一跟是乍样处理的吧!对代码段处理了就应对
代码进行写操作吧!!!打开内存镜像在代码段下内存访问断点,不停按Shift+F9 ,注意寄存器窗口.如果出现API
函数时,停下来
EAX 0045011C delphi7?0045011C
ECX 7C9210E0 ntdll.RtlLeaveCriticalSection
EDX 5DECA5C2
EBX 006BF497 delphi7?006BF497
ESP 0012FF64
EBP F6E56041
ESI 006B922D delphi7?006B922D
EDI 7C9210E0 ntdll.RtlLeaveCriticalSection
EIP 006BF364 delphi7?006BF364程序就断到此处了
006BF364 8908 mov dword ptr ds:[eax],ecx ; ntdll.RtlLeaveCriticalSection
//////////////////////////
mov dword ptr ds:[eax],ecx
注意此句汇编它把ECX的数据写到某个地址去
而此时ECX存放的是API的地址,这里可能是填充API的地方
数据窗口地址跟随一下看看
00450114 00000000
00450118 029E0000
0045011C 00000000
00450120 00000000
00450124 00000000
00450128 00000000
0045012C 00000000
00450130 00000000
00450134 00000000
00450138 00000000
0045013C 00000000
00450140 00000000
eax == 0045011C,0045011C现在数据是0,单步一下在观察
00450114 00000000
00450118 029E0000
0045011C 7C9210E0 ntdll.RtlLeaveCriticalSection
00450120 00000000
00450124 00000000
/////////////////////////
006BF366 AD lods dword ptr ds:[esi]
006BF367 C746 FC 0000000>mov dword ptr ds:[esi-0x4],0x0
006BF36E 89B5 051F7409 mov dword ptr ss:[ebp+0x9741F05],esi
006BF374 83F8 FF cmp eax,-0x1
006BF377 0F85 20000000 jnz delphi7?006BF39D
006BF37D 813E DDDDDDDD cmp dword ptr ds:[esi],0xDDDDDDDD
006BF383 0F85 14000000 jnz delphi7?006BF39D
006BF389 C706 00000000 mov dword ptr ds:[esi],0x0
006BF38F 83C6 04 add esi,0x4
006BF392 89B5 051F7409 mov dword ptr ss:[ebp+0x9741F05],esi
006BF398 ^ E9 EDF6FFFF jmp delphi7?006BEA8A
复制代码取消断点F9运行,出现程序界面再到数据窗口,Ctrl+G 0045011C 去
看看会发现从00450118-004506D4
00450638 02E404EF
0045063C 02E4074C
00450640 02E409D9
00450644 02E50000
00450648 02E50383
0045064C 00000000
00450650 02E503DC
00450654 00000000
00450658 770FAB10 OLEAUT32.SafeArrayPtrOfIndex
0045065C 770F515A OLEAUT32.SafeArrayGetUBound
00450660 770F51A6 OLEAUT32.SafeArrayGetLBound
00450664 770FAA55 OLEAUT32.SafeArrayCreate
00450668 770F6BBB OLEAUT32.VariantChangeType
0045066C 770F4CFD OLEAUT32.VariantCopy
00450670 770F48F0 OLEAUT32.VariantClear
00450674 770F4950 OLEAUT32.VariantInit
既有API函数也有一些有规律未知数值,因此基本可以确认
006BF364 8908 mov dword ptr ds:[eax],ecx
这段代码在处理IAT
重载OD 在006BF364 处下硬件执行断点,F9运行断下来了!!!!!!!!!!!!!!006BF364 8908 mov dword ptr ds:[eax],ecx
006BF366 AD lods dword ptr ds:[esi]
006BF367 C746 FC 0000000>mov dword ptr ds:[esi-0x4],0x0
006BF36E 89B5 051F7409 mov dword ptr ss:[ebp+0x9741F05],esi
006BF374 83F8 FF cmp eax,-0x1
006BF377 0F85 20000000 jnz delphi7?006BF39D
复制代码F8单步这非常大的回跳
006BF458 ^ E9 11FFFFFF jmp delphi7?006BF36E
继续F8吧注意这句代码,这句是从某个地址取出kernel32的基址
006BEC2C 8B0B mov ecx,dword ptr ds:[ebx] ; kernel32.7C80000ds
[ebx]==[02820000]=7C800000 (kernel32.7C800000)
继续F8吧来到006BEC9B再单步一下
006BEC9B FFD3 call ebx
006BEC9D 83BD 71297409 0>cmp dword ptr ss:[ebp+0x9742971],0x0
寄存窗口出现了API的地址
EAX 7C9210E0 ntdll.RtlLeaveCriticalSection
ECX 7C800000 kernel32.7C800000
EDX 5DECA5C2
EBX 006BF497 delphi7?006BF497
ESP 0012FF64
EBP F6E56041
ESI 006B9229 delphi7?006B9229
EDI 0040136D delphi7?0040136D
EIP 006BECA4 delphi7?006BECA4
继续F8吧又会来到
006BF364 8908 mov dword ptr ds:[eax],ecx
我们来总结一下吧.
1.通过006BEC9D上面的一系列运算得到API函数的地址
2.通过判断该API是否要加密,要加密就进行运算,并把结果填充入IAT
不加密就直接填充API
3.我们写个简单脚本测试一下吧
bphwcall
var addr
bphws 006BEC9B ,"x"
bphws 006BF364,"x"
bphws 0044CA98,"x"
loop:
esto
cmp eip,0044CA98
je exit
cmp eip,006BF364
je ssss
sto
sto
mov addr,eax
esto
sto
mov [eax],addr
jmp loop
ssss:
sto
jmp loop
exit:
ret
脚本跑完去看看效果
00450118 7C93137A ntdll.RtlDeleteCriticalSection
0045011C 7C9210E0 ntdll.RtlLeaveCriticalSection
00450120 7C921000 ntdll.RtlEnterCriticalSection
00450124 7C809F91 kernel32.InitializeCriticalSection
00450128 7C809B84 kernel32.VirtualFree
0045012C 7C809AF1 kernel32.VirtualAlloc
00450130 7C8099CF kernel32.LocalFree
00450134 7C809A2D kernel32.LocalAlloc
00450138 7C81127A kernel32.GetVersion
0045013C 7C8097D0 kernel32.GetCurrentThreadId
00450140 7C80981A kernel32.InterlockedDecrement
00450144 7C809806 kernel32.InterlockedIncrement
00450148 7C80BA71 kernel32.VirtualQuery
0045014C 7C80A174 kernel32.WideCharToMultiByte
00450150 7C809C98 kernel32.MultiByteToWideChar
00450154 7C80BE56 kernel32.lstrlenA
00450158 7C8101B1 kernel32.lstrcpynA
0045015C 7C801D53 kernel32.LoadLibraryExA
00450160 7C80A4B5 kernel32.GetThreadLocale
00450164 7C801EF2 kernel32.GetStartupInfoA
00450168 7C80AE40 kernel32.GetProcAddress
0045016C 7C80B741 kernel32.GetModuleHandleA
00450170 7C80B56F kernel32.GetModuleFileNameA
00450174 7C80D302 kernel32.GetLocaleInfoA
00450178 7C812FBD kernel32.GetCommandLineA
0045017C 7C80AC7E kernel32.FreeLibrary
00450180 7C813879 kernel32.FindFirstFileA
00450184 7C80EE77 kernel32.FindClose
00450188 7C81CB12 kernel32.ExitProcess
0045018C 7C810E27 kernel32.WriteFile
00450190 7C863FCA kernel32.UnhandledExceptionFilter
00450194 7C94ABC5 ntdll.RtlUnwind
00450198 7C812AA9 kernel32.RaiseException
看样子挺OK好了IAT修复一半,接就搞定
看样子挺OK好了IAT修复一半,接就搞定
00405B04 90 nop
00405B05 - E9 56B26D02 jmp 02AE0D60
00405B0A 8BC0 mov eax,eax
重载OD,在数据窗口Ctrl+g到00405B04地址看看并设置成反汇编显示
00405B04 AF scas dword ptr es:[edi]
00405B05 CD 06 int 0x6
00405B07 38DE cmp dh,bl
00405B09 BC 5B1D18BE mov esp,0xBE181D5B
00405B0E D5 E5 aad 0xE5
00405B10 C3 retn
00405B11 67:B8 A9BA344C mov eax,0x4C34BAA9
在00405B0D下硬件写入断点F9运行两次断下来了
数据窗口显示
00405B03 90 nop
00405B04 90 nop
00405B05 90 nop
00405B06 90 nop
00405B07 90 nop
00405B08 90 nop
00405B09 90 nop
00405B0A 8BC0 mov eax,eax
00405B0C 90 nop
00405B0D 90 nop
00405B0E 90 nop
00405B0F 90 nop
00405B10 90 nop
00405B11 90 nop
00405B12 8BC0 mov eax,eax
这段代码负责填充9090909090,这不是我想要的,取消断点
00405B0C 90 nop
00405B0D 90 nop
00405B0E 90 nop
00405B0F 90 nop
00405B10 90 nop
00405B11 90 nop
00405B12 8BC0 mov eax,eax
下个内存写入断点,F9运行断在了,
006BF44F AB stos dword ptr es:[edi]
F8单步后数据窗口显示00405B0D被填充了
//////////////////////////////////////////////////////
数据窗口:
00405B06 90 nop
00405B07 90 nop
00405B08 90 nop
00405B09 90 nop
00405B0A 8BC0 mov eax,eax
00405B0C 90 nop
00405B0D - E9 A3AE6D02 jmp 02AE09B5
00405B12 8BC0 mov eax,eax
EAX 026DAEA3
ECX 02AE09B5
EDX 029C03F6
EBX 006B2436 delphi7?006B2436
ESP 0012FF60
EBP F6E56041
ESI 006B968D delphi7?006B968D
EDI 00405B12 delphi7?00405B12
EIP 006BF450 delphi7?006BF450
////////////////////////////////////////////////////////
006BF450 AD lods dword ptr ds:[esi]
006BF451 C746 FC 0000000>mov dword ptr ds:[esi-0x4],0x0
006BF458 ^ E9 11FFFFFF jmp delphi7?006BF36E
我们发现006BF44F AB stos dword ptr es:[edi]填充后
再无其他地址对它进行写操作.因此我们要处理
00405B0C 90 nop
00405B0D - E9 A3AE6D02 jmp 02AE09B5
单步到006BF458这个地址最最好的位置
提取一下特征码AB AD C7 46 FC 00 00 00 00
接下来应该对00405B04进行填充
00405B03 90 nop
00405B04 90 nop
00405B05 90 nop
00405B06 90 nop
00405B07 90 nop
00405B08 90 nop
00405B09 90 nop
00405B0A 8BC0 mov eax,eax
我们载入无壳delphi程序进入第一个CALL
00405B03 90 nop
00405B04 $- FF25 E4014500 jmp dword ptr ds:[<&kernel32.GetModuleHa>; kernel32.GetModuleHandleA
00405B0A 8BC0 mov eax,eax
00405B0C $- FF25 E0014500 jmp dword ptr ds:[<&kernel32.LocalAlloc>>; kernel32.LocalAlloc
00405B12 8BC0 mov eax,eax
00405B14 $- FF25 DC014500 jmp dword ptr ds:[<&kernel32.TlsGetValue>; kernel32.TlsGetValue
00405B1A 8BC0 mov eax,eax
00405B1C $- FF25 D8014500 jmp dword ptr ds:[<&kernel32.TlsSetValue>; kernel32.TlsSetValue
可以看出如果不对此地址代码处理那么应该写回
00405B03 90 nop
00405B04 $- FF25 E4014500 jmp dword ptr ds:[<&kernel32.GetModuleHa>; kernel32.GetModuleHandleA
好了不多说了单步F8一直来到
006BEC9B FFD3 call ebx
006BEC9D 83BD 71297409 0>cmp dword ptr ss:[ebp+0x9742971],0x0
提取一下特征码
查看一下寄存器
EAX 7C80B741 kernel32.GetModuleHandleA
ECX 7C800000 kernel32.7C800000
EDX 5DECA5C2
EBX 006BF497 delphi7?006BF497
ESP 0012FF64
EBP F6E56041
ESI 006B9699 delphi7?006B9699
EDI 00405B12 delphi7?00405B12
EIP 006BEC9D delphi7?006BEC9D
发现EAX中的数据是GetModuleHandleA的地址OK.这不正是要写回00405B04这个地址的函数!!!!
但是单步再走到
006BF44F AB stos dword ptr es:[edi]
006BF450 AD lods dword ptr ds:[esi]
006BF451 C746 FC 0000000>mov dword ptr ds:[esi-0x4],0x0
却发现被处理成了
00405B04 90 nop
00405B05 - E9 56B26D02 jmp 02AE0D60
好了我单步跟了这段代码得到从以下信息整理:
1.在006BEC9B FFD3 call ebx过后寄存器出的API函数地址正是006BF44F AB stos dword ptr es:[edi]
处理掉的函数.
2.因此我只需要006BF44F AB stos dword ptr es:[edi]执行完后把006BEC9B FFD3 call ebx得到的
函数地址写回去就OK.
3.因为IAT前面已修复,我可以将在006BEC9B FFD3 call ebx获取的API函数地址与IAT表进行
比对,在IAT中找到相应API存放地址(xxxxxxxx).
4.找API存放地址(xxxxxxxx).就可以把jmp 02AE0D60修复成 jmp [xxxxxxxx]