文章作者: xiaobaozi49
刚刚开始 F7 加密壳,ExeStealth是个最基本的加密壳, 它有反调试反跟踪,IAT加密,花指令,文件校验,内存校验等手段,不过都是最基本方式
所以一开始拿它下手是在合适不过的了
OD载入
00423060 > /EB 58 jmp short _ExeStea.004230BA
一开始就跳 - -!
004230BA 90 nop
004230BB 60 pushad
004230BC 90 nop
004230BD E8 00000000 call _ExeStea.004230C2 ; 自定位call
004230C2 5D pop ebp
004230C3 81ED F7274000 sub ebp, _ExeStea.004027F7 ; 获取自定位偏移量
004230C9 B9 15000000 mov ecx, 15
004230CE 83C1 04 add ecx, 4
004230D1 83C1 01 add ecx, 1
004230D4 EB 05 jmp short _ExeStea.004230DB
004230D6 - EB FE jmp short _ExeStea.004230D6
004230D8 83C7 56 add edi, 56
004230DB EB 00 jmp short _ExeStea.004230DD
004230DD EB 00 jmp short _ExeStea.004230DF
004230DF 83E9 02 sub ecx, 2
004230E2 81C1 78432765 add ecx, 65274378
004230E8 EB 00 jmp short _ExeStea.004230EA
004230EA 81C1 10259400 add ecx, 942510
004230F0 81E9 63850000 sub ecx, 8563
004230F6 B9 960C0000 mov ecx, 0C96
004230FB 90 nop
004230FC 8DBD 74284000 lea edi, dword ptr ss:[ebp+402874]
00423102 8BF7 mov esi, edi
00423104 AC lods byte ptr ds:[esi]
00423105 F8 clc
00423106 2C ED sub al, 0ED
00423108 F8 clc
00423109 2AC1 sub al, cl
0042310B F8 clc
0042310C F9 stc
0042310D 2AC1 sub al, cl
0042310F F9 stc
00423110 04 4D add al, 4D
00423112 F8 clc
00423113 F8 clc
00423114 2AC1 sub al, cl
00423116 04 D4 add al, 0D4
00423118 F9 stc
00423119 2C B8 sub al, 0B8
0042311B F9 stc
0042311C F9 stc
0042311D F9 stc
0042311E 04 47 add al, 47
00423120 02C1 add al, cl
00423122 34 90 xor al, 90
00423124 F8 clc
00423125 90 nop
00423126 F8 clc
00423127 F8 clc
00423128 04 50 add al, 50
0042312A 2C ED sub al, 0ED
0042312C F8 clc
0042312D 2AC1 sub al, cl
0042312F F8 clc
00423130 F9 stc
00423131 2AC1 sub al, cl
00423133 F9 stc
00423134 04 4D add al, 4D
00423136 F8 clc
00423137 F8 clc
00423138 2AC1 sub al, cl
0042313A 04 D4 add al, 0D4
0042313C AA stos byte ptr es:[edi]
0042313D ^ E2 C5 loopd short _ExeStea.00423104 ; 解压下面的代码
0042313F C2 5631 retn 3156 ; 解压这里到00423dd5的核心代码和数据
00423142 288E 421D3492 sub byte ptr ds:[esi+92341D42], cl
00423148 CA 1383 retf 8313
0042314B E3 04 jecxz short _ExeStea.00423151
把壳的核心代码和数据解压出来,0042313F到00423dd5是壳的核心代码和数据,前面只是引导代码
在0042313F F4。OK代码已经解压完毕
0042313F 8B4424 20 mov eax, dword ptr ss:[esp+20] ; kernel32.761C4911
00423143 8B4424 20 mov eax, dword ptr ss:[esp+20]
00423147 83C0 0E add eax, 0E ; 废指令
0042314A 83E8 0E sub eax, 0E
0042314D 83C0 0E add eax, 0E
00423150 83E8 0E sub eax, 0E
00423153 40 inc eax
00423154 78 1D js short _ExeStea.00423173
00423156 C785 FC2F4000 0>mov dword ptr ss:[ebp+402FFC], 1
00423160 EB 11 jmp short _ExeStea.00423173
00423162 8B4424 20 mov eax, dword ptr ss:[esp+20]
00423166 83C0 0E add eax, 0E
00423169 83E8 0E sub eax, 0E
0042316C 83C0 0E add eax, 0E
0042316F 83E8 0E sub eax, 0E
00423172 40 inc eax
00423173 8D85 95274000 lea eax, dword ptr ss:[ebp+402795]
00423179 B9 06070000 mov ecx, 706
0042317E E8 41020000 call _ExeStea.004233C4 ; 求壳入口之后的0x706个字节校验和
00423183 8985 F82F4000 mov dword ptr ss:[ebp+402FF8], eax ; 保存校验和
00423189 8B85 F02F4000 mov eax, dword ptr ss:[ebp+402FF0]
0042318F 83E0 01 and eax, 1
00423192 74 40 je short _ExeStea.004231D4
00423194 8DB5 38344000 lea esi, dword ptr ss:[ebp+403438]
0042319A 8D85 F6284000 lea eax, dword ptr ss:[ebp+4028F6] ; 新的EIP(异常的下一条指令)
004231A0 8946 08 mov dword ptr ds:[esi+8], eax ; 保存新的eip
004231A3 8BFD mov edi, ebp ; 保存ebp
004231A5 8D85 862F4000 lea eax, dword ptr ss:[ebp+402F86] ; 取异常处理Handle
004231AB 33DB xor ebx, ebx
004231AD 50 push eax
004231AE 64:FF33 push dword ptr fs:[ebx]
004231B1 64:8923 mov dword ptr fs:[ebx], esp
004231B4 BD 4B484342 mov ebp, 4243484B ; 清除ebp
004231B9 66:B8 0400 mov ax, 4 ; 清除ax
004231BD EB 01 jmp short _ExeStea.004231C0 ; 花指令
004231BF FFCC dec esp ; int3异常触发异常
004231C1 8BEF mov ebp, edi
004231C3 33DB xor ebx, ebx
004231C5 64:8F03 pop dword ptr fs:[ebx]
004231C8 83C4 04 add esp, 4
004231CB 3C 04 cmp al, 4
004231CD 74 05 je short _ExeStea.004231D4
004231CF EB 01 jmp short _ExeStea.004231D2
开始执行壳的核心代码,首先求解压出来壳的核心代码求校验和并保存,在后面校验壳代码是否被修改过的时候使用
然后就是一个异常来反调试,通过int3来触发(没看到INT3? 看看004231BF这字节码为FFCC,FF是花指令),在异常前清除
Ebp,在异常Handle中恢复Ebp,并修改EIP到异常发生的下一条指令,就跳过了异常
在INT3的下一条指令004231C1下断,然后一直走
004231D4 8B85 E82F4000 mov eax, dword ptr ss:[ebp+402FE8] ; _ExeStea.00400000
004231DA 0340 3C add eax, dword ptr ds:[eax+3C]
004231DD 05 80000000 add eax, 80
004231E2 8B08 mov ecx, dword ptr ds:[eax]
004231E4 038D E82F4000 add ecx, dword ptr ss:[ebp+402FE8]
004231EA 83C1 10 add ecx, 10
004231ED 8B01 mov eax, dword ptr ds:[ecx]
004231EF 0385 E82F4000 add eax, dword ptr ss:[ebp+402FE8]
004231F5 8B18 mov ebx, dword ptr ds:[eax] ; 获取LoadLibrary地址
004231F7 899D 44344000 mov dword ptr ss:[ebp+403444], ebx ; 保存LoadLibrary地址
004231FD 83C0 04 add eax, 4
00423200 8B18 mov ebx, dword ptr ds:[eax] ; 获取GetProcAddress地址
00423202 899D 48344000 mov dword ptr ss:[ebp+403448], ebx ; 保存GetProcAddress地址
00423208 8D85 4C344000 lea eax, dword ptr ss:[ebp+40344C]
0042320E 50 push eax
0042320F FF95 44344000 call dword ptr ss:[ebp+403444] ; LoadLibrary加载kernel32
00423215 8BF0 mov esi, eax
00423217 8985 59344000 mov dword ptr ss:[ebp+403459], eax ; 保存kernel32基址
0042321D 8D85 5D344000 lea eax, dword ptr ss:[ebp+40345D]
00423223 E8 96000000 call _ExeStea.004232BE ; 获取GetModuleHandleA地址
00423228 8985 6E344000 mov dword ptr ss:[ebp+40346E], eax ; 保存GetModuleHandleA地址
0042322E 8D85 72344000 lea eax, dword ptr ss:[ebp+403472]
00423234 E8 85000000 call _ExeStea.004232BE ; 获取VirtualProtect地址
00423239 8985 81344000 mov dword ptr ss:[ebp+403481], eax ; 保存VirtualProtect地址
0042323F 8D85 85344000 lea eax, dword ptr ss:[ebp+403485]
00423245 E8 74000000 call _ExeStea.004232BE ; 保存GetModuleFileNameA地址
0042324A 8985 98344000 mov dword ptr ss:[ebp+403498], eax
00423250 8D85 9C344000 lea eax, dword ptr ss:[ebp+40349C]
00423256 E8 63000000 call _ExeStea.004232BE ; 保存CreateFileA地址
0042325B 8985 A8344000 mov dword ptr ss:[ebp+4034A8], eax
00423261 8D85 AC344000 lea eax, dword ptr ss:[ebp+4034AC]
00423267 E8 52000000 call _ExeStea.004232BE ; 保存GlobalAlloc地址
0042326C 8985 B8344000 mov dword ptr ss:[ebp+4034B8], eax
00423272 8D85 BC344000 lea eax, dword ptr ss:[ebp+4034BC]
00423278 E8 41000000 call _ExeStea.004232BE ; 保存GlobalFree地址
0042327D 8985 C7344000 mov dword ptr ss:[ebp+4034C7], eax
00423283 8D85 CB344000 lea eax, dword ptr ss:[ebp+4034CB]
00423289 E8 30000000 call _ExeStea.004232BE ; 保存ReadFile地址
0042328E 8985 D4344000 mov dword ptr ss:[ebp+4034D4], eax
00423294 8D85 D8344000 lea eax, dword ptr ss:[ebp+4034D8]
0042329A E8 1F000000 call _ExeStea.004232BE ; 保存GetFileSize地址
0042329F 8985 E4344000 mov dword ptr ss:[ebp+4034E4], eax
004232A5 8D85 E8344000 lea eax, dword ptr ss:[ebp+4034E8]
004232AB E8 0E000000 call _ExeStea.004232BE ; 保存CloseHandle地址
004232B0 8985 F4344000 mov dword ptr ss:[ebp+4034F4], eax
004232B6 8D85 FC294000 lea eax, dword ptr ss:[ebp+4029FC]
004232BC 50 push eax
004232BD C3 retn
这一段主要是获取一些壳所需API的地址,用于检验文件是否被修改和填充IAT的时候用
004232C7 F785 F02F4000 1>test dword ptr ss:[ebp+402FF0], 10
004232D1 74 37 je short _ExeStea.0042330A
004232D3 64:FF35 3000000>push dword ptr fs:[30] ; 获取PEB
004232DA 58 pop eax
004232DB 85C0 test eax, eax
004232DD 78 0F js short _ExeStea.004232EE
004232DF 8B40 0C mov eax, dword ptr ds:[eax+C]
004232E2 8B40 0C mov eax, dword ptr ds:[eax+C]
004232E5 C740 20 0010000>mov dword ptr ds:[eax+20], 1000
004232EC EB 1C jmp short _ExeStea.0042330A
004232EE 6A 00 push 0
004232F0 FF95 6E344000 call dword ptr ss:[ebp+40346E]
004232F6 85D2 test edx, edx
004232F8 79 10 jns short _ExeStea.0042330A
004232FA 837A 08 FF cmp dword ptr ds:[edx+8], -1
004232FE 75 0A jnz short _ExeStea.0042330A
00423300 8B52 04 mov edx, dword ptr ds:[edx+4]
00423303 C742 50 0010000>mov dword ptr ds:[edx+50], 1000
0042330A 8BBD E82F4000 mov edi, dword ptr ss:[ebp+402FE8]
00423310 037F 3C add edi, dword ptr ds:[edi+3C] ; 定位到PE_NT_HEADER
00423313 8BB5 E82F4000 mov esi, dword ptr ss:[ebp+402FE8]
00423319 8B4F 54 mov ecx, dword ptr ds:[edi+54] ; 获取DOS,PE,区块头的总大小
0042331C 8D85 26354000 lea eax, dword ptr ss:[ebp+403526]
00423322 50 push eax
00423323 6A 04 push 4
00423325 51 push ecx
00423326 FFB5 E82F4000 push dword ptr ss:[ebp+402FE8]
0042332C FF95 81344000 call dword ptr ss:[ebp+403481] ; 修改PE头属性可写可拷贝
00423332 F785 F02F4000 0>test dword ptr ss:[ebp+402FF0], 8
0042333C 0F84 A7000000 je _ExeStea.004233E9
00423342 68 04010000 push 104
00423347 8DBD 26354000 lea edi, dword ptr ss:[ebp+403526]
0042334D 57 push edi
0042334E 6A 00 push 0
00423350 FF95 98344000 call dword ptr ss:[ebp+403498] ; GetModuleFileNameA获取自身文件名
00423356 6A 00 push 0
00423358 68 80000000 push 80
0042335D 6A 03 push 3
0042335F 6A 00 push 0
00423361 6A 01 push 1
00423363 68 00000080 push 80000000
00423368 57 push edi
00423369 FF95 A8344000 call dword ptr ss:[ebp+4034A8] ; CreateFileA打开自身文件
0042336F 83F8 FF cmp eax, -1
00423372 75 04 jnz short _ExeStea.00423378
00423374 33C0 xor eax, eax
00423376 EB 71 jmp short _ExeStea.004233E9
00423378 8BF8 mov edi, eax
0042337A 6A 00 push 0
0042337C 57 push edi
0042337D FF95 E4344000 call dword ptr ss:[ebp+4034E4] ; GetFileSize获取文件大小
00423383 83E8 05 sub eax, 5 ; 文件大小-5
00423386 96 xchg eax, esi
00423387 56 push esi
00423388 6A 40 push 40
0042338A FF95 B8344000 call dword ptr ss:[ebp+4034B8] ; GlobalAlloc分配文件大小的内存
00423390 0BC0 or eax, eax
00423392 75 02 jnz short _ExeStea.00423396
00423394 EB 4A jmp short _ExeStea.004233E0
00423396 93 xchg eax, ebx
00423397 6A 00 push 0
00423399 8D85 26354000 lea eax, dword ptr ss:[ebp+403526]
0042339F 50 push eax
004233A0 56 push esi
004233A1 53 push ebx
004233A2 57 push edi
004233A3 FF95 D4344000 call dword ptr ss:[ebp+4034D4] ; ReadFile读取整个自身文件到内存
004233A9 8BC3 mov eax, ebx
004233AB 8BCE mov ecx, esi
004233AD 53 push ebx
004233AE 57 push edi
004233AF E8 10000000 call _ExeStea.004233C4 ; 求从文件中读出到内存的校验和
004233B4 8985 F42F4000 mov dword ptr ss:[ebp+402FF4], eax ; 保存校验和
004233BA 5F pop edi
004233BB 5B pop ebx
004233BC 8D85 0D2B4000 lea eax, dword ptr ss:[ebp+402B0D]
004233C2 50 push eax
004233C3 C3 retn
修改PE头属性为可写可拷贝,分配内存,读取整个文件到内存中求校验和并保存,在之后校验文件是否被修改的时候用
004233D8 53 push ebx
004233D9 FF95 C7344000 call dword ptr ss:[ebp+4034C7] ; GlobalAlloc释放掉内存
004233DF 96 xchg eax, esi
004233E0 50 push eax
004233E1 57 push edi
004233E2 FF95 F4344000 call dword ptr ss:[ebp+4034F4] ; CloseHandle关闭文件句柄
004233E8 58 pop eax
004233E9 8B85 E82F4000 mov eax, dword ptr ss:[ebp+402FE8]
004233EF BB 01000000 mov ebx, 1
004233F4 E8 08000000 call _ExeStea.00423401 ; 解压原程序各个区段
004233F9 8D85 262C4000 lea eax, dword ptr ss:[ebp+402C26]
004233FF 50 push eax
00423400 C3 retn
开始解压原程序的各个区段。跟进CALL 00423401看看解压过程
00423401 8BF8 mov edi, eax
00423403 037F 3C add edi, dword ptr ds:[edi+3C] ; 获取PE_NT_HEADER
00423406 8BF7 mov esi, edi
00423408 81C6 F8000000 add esi, 0F8 ; 获取一个区段表
0042340E 33D2 xor edx, edx ; 对比区段名
00423410 813E 72737263 cmp dword ptr ds:[esi], 63727372 ; 判断该区段是否需要解压
00423416 75 05 jnz short _ExeStea.0042341D
00423418 E9 C5000000 jmp _ExeStea.004234E2
0042341D 813E 2E727372 cmp dword ptr ds:[esi], 7273722E
00423423 75 05 jnz short _ExeStea.0042342A
00423425 E9 B8000000 jmp _ExeStea.004234E2
0042342A 813E 2E726573 cmp dword ptr ds:[esi], 7365722E
00423430 75 05 jnz short _ExeStea.00423437
00423432 E9 AB000000 jmp _ExeStea.004234E2
00423437 813E 2E656461 cmp dword ptr ds:[esi], 6164652E
0042343D 75 05 jnz short _ExeStea.00423444
0042343F E9 9E000000 jmp _ExeStea.004234E2
00423444 813E 72656C6F cmp dword ptr ds:[esi], 6F6C6572
0042344A 75 05 jnz short _ExeStea.00423451
0042344C E9 91000000 jmp _ExeStea.004234E2
00423451 813E 2E72656C cmp dword ptr ds:[esi], 6C65722E
00423457 75 05 jnz short _ExeStea.0042345E
00423459 E9 84000000 jmp _ExeStea.004234E2
0042345E 813E 6E6F6573 cmp dword ptr ds:[esi], 73656F6E
00423464 75 02 jnz short _ExeStea.00423468
00423466 EB 7A jmp short _ExeStea.004234E2
00423468 813E 45786553 cmp dword ptr ds:[esi], 53657845
0042346E 75 02 jnz short _ExeStea.00423472
00423470 EB 70 jmp short _ExeStea.004234E2
00423472 813E 2E656461 cmp dword ptr ds:[esi], 6164652E
00423478 75 02 jnz short _ExeStea.0042347C
0042347A EB 66 jmp short _ExeStea.004234E2
0042347C 837E 14 00 cmp dword ptr ds:[esi+14], 0 ; 区段的文件偏移
00423480 74 06 je short _ExeStea.00423488
00423482 837E 10 00 cmp dword ptr ds:[esi+10], 0 ; 区段在文件中长度
00423486 75 02 jnz short _ExeStea.0042348A
00423488 EB 58 jmp short _ExeStea.004234E2
0042348A 60 pushad
0042348B 8B4E 10 mov ecx, dword ptr ds:[esi+10] ; 取区段的在文件中的大小
0042348E 0BDB or ebx, ebx
00423490 75 0C jnz short _ExeStea.0042349E
00423492 8B76 14 mov esi, dword ptr ds:[esi+14]
00423495 03F0 add esi, eax
00423497 E8 B0F8FFFF call _ExeStea.00422D4C
0042349C EB 0A jmp short _ExeStea.004234A8
0042349E 8B76 0C mov esi, dword ptr ds:[esi+C] ; 区段的RVA
004234A1 03F0 add esi, eax ; 获取区段的基址VA
004234A3 E8 02000000 call _ExeStea.004234AA ; 解压原程序各个区段
004234A8 EB 37 jmp short _ExeStea.004234E1
004234AA 8BFE mov edi, esi
004234AC AC lods byte ptr ds:[esi]
004234AD F9 stc
004234AE 2C B8 sub al, 0B8
004234B0 F9 stc
004234B1 F9 stc
004234B2 F9 stc
004234B3 04 47 add al, 47
004234B5 02C1 add al, cl
004234B7 34 90 xor al, 90
004234B9 F8 clc
004234BA 90 nop
004234BB F8 clc
004234BC F8 clc
004234BD 04 50 add al, 50
004234BF 2C ED sub al, 0ED
004234C1 F8 clc
004234C2 2AC1 sub al, cl
004234C4 F8 clc
004234C5 F9 stc
004234C6 2AC1 sub al, cl
004234C8 F9 stc
004234C9 04 4D add al, 4D
004234CB F8 clc
004234CC F8 clc
004234CD 2AC1 sub al, cl
004234CF 04 D4 add al, 0D4
004234D1 F9 stc
004234D2 2C B8 sub al, 0B8
004234D4 F9 stc
004234D5 F9 stc
004234D6 F9 stc
004234D7 04 47 add al, 47
004234D9 02C1 add al, cl
004234DB 34 90 xor al, 90
004234DD AA stos byte ptr es:[edi]
004234DE ^ E2 CC loopd short _ExeStea.004234AC ; 循环解压原程序的一个区段
004234E0 C3 retn
004234E1 61 popad
004234E2 83C6 28 add esi, 28
004234E5 42 inc edx
004234E6 66:3B57 06 cmp dx, word ptr ds:[edi+6] ; 是否所有区段都处理?
004234EA ^ 0F85 20FFFFFF jnz _ExeStea.00423410 ; 继续处理下一个区段
004234F0 C3 retn
读取PE头来获取区段的属性,逐个区段解压。继续走
004234F1 8B9D E82F4000 mov ebx, dword ptr ss:[ebp+402FE8] ; _ExeStea.00400000
004234F7 90 nop
004234F8 039D EC2F4000 add ebx, dword ptr ss:[ebp+402FEC] ; 获取OEP
004234FE C1CB 07 ror ebx, 7 ; 将OEP变形保存
00423501 895C24 10 mov dword ptr ss:[esp+10], ebx
00423505 8D9D 1D2F4000 lea ebx, dword ptr ss:[ebp+402F1D]
0042350B 895C24 1C mov dword ptr ss:[esp+1C], ebx
0042350F 8BBD E82F4000 mov edi, dword ptr ss:[ebp+402FE8]
00423515 037F 3C add edi, dword ptr ds:[edi+3C]
00423518 8B9F C0000000 mov ebx, dword ptr ds:[edi+C0] ; 获取TLS
0042351E 83FB 00 cmp ebx, 0
00423521 74 0F je short _ExeStea.00423532
00423523 039D E82F4000 add ebx, dword ptr ss:[ebp+402FE8]
00423529 8B43 08 mov eax, dword ptr ds:[ebx+8]
0042352C C700 00000000 mov dword ptr ds:[eax], 0
00423532 8B85 F42F4000 mov eax, dword ptr ss:[ebp+402FF4] ; 读取校验和
00423538 0BC0 or eax, eax
0042353A 74 0D je short _ExeStea.00423549
0042353C 3B85 22354000 cmp eax, dword ptr ss:[ebp+403522] ; 比较校验和,判断文件是否被修改
00423542 74 05 je short _ExeStea.00423549
00423544 E9 AF010000 jmp _ExeStea.004236F8
00423549 8DB5 00304000 lea esi, dword ptr ss:[ebp+403000] ; 获取变形的输入表
0042354F F785 F02F4000 2>test dword ptr ss:[ebp+402FF0], 20
00423559 74 49 je short _ExeStea.004235A4
0042355B 56 push esi
0042355C 8DBD 26354000 lea edi, dword ptr ss:[ebp+403526]
00423562 33C9 xor ecx, ecx
00423564 EB 17 jmp short _ExeStea.0042357D
00423566 8B56 04 mov edx, dword ptr ds:[esi+4] ; 获取该IID的IAT偏移
00423569 0395 E82F4000 add edx, dword ptr ss:[ebp+402FE8] ; 加上基址,得到IAT的RVA
0042356F EB 04 jmp short _ExeStea.00423575
00423571 41 inc ecx
00423572 83C2 04 add edx, 4
00423575 833A 00 cmp dword ptr ds:[edx], 0 ; 计算IAT数组的元素个数
00423578 ^ 75 F7 jnz short _ExeStea.00423571
0042357A 83C6 0C add esi, 0C ; 下一个IID结构(每个IID长度为C)
0042357D 837E 04 00 cmp dword ptr ds:[esi+4], 0
00423581 ^ 75 E3 jnz short _ExeStea.00423566 ; 是否所有Dll已经处理完
00423583 33D2 xor edx, edx
00423585 B8 05000000 mov eax, 5 ; 所有IAT数组的元素总个数*5
0042358A F7E1 mul ecx
0042358C 50 push eax
0042358D 6A 00 push 0
0042358F FF95 B8344000 call dword ptr ss:[ebp+4034B8] ; GlobalAlloc分配相应大小的空间
00423595 0BC0 or eax, eax
00423597 75 05 jnz short _ExeStea.0042359E
00423599 83C4 04 add esp, 4
0042359C 61 popad
0042359D C3 retn
0042359E 8907 mov dword ptr ds:[edi], eax
004235A0 8947 04 mov dword ptr ds:[edi+4], eax
004235A3 5E pop esi
004235A4 E9 42010000 jmp _ExeStea.004236EB
004235A9 8B1E mov ebx, dword ptr ds:[esi] ; 获取加密的Dll名字的字符串
004235AB 039D E82F4000 add ebx, dword ptr ss:[ebp+402FE8]
004235B1 8BC3 mov eax, ebx
004235B3 E8 08000000 call _ExeStea.004235C0 ; 解密导入Dll名字的字符串
004235B8 8D85 082D4000 lea eax, dword ptr ss:[ebp+402D08]
004235BE 50 push eax
004235BF C3 retn
004235C0 56 push esi
004235C1 57 push edi
004235C2 8BF0 mov esi, eax
004235C4 8BF8 mov edi, eax
004235C6 AC lods byte ptr ds:[esi]
004235C7 C0C8 04 ror al, 4
004235CA AA stos byte ptr es:[edi]
004235CB 803F 00 cmp byte ptr ds:[edi], 0 ; 清除字符串
004235CE ^ 75 F6 jnz short _ExeStea.004235C6
004235D0 5F pop edi
004235D1 5E pop esi
004235D2 C3 retn
004235D3 53 push ebx
004235D4 FF95 44344000 call dword ptr ss:[ebp+403444] ; Loadlibrary加载导入的Dll
004235DA 85C0 test eax, eax
004235DC 0F84 16010000 je _ExeStea.004236F8
004235E2 50 push eax ; 保存加载Dll的基址
004235E3 F785 F02F4000 0>test dword ptr ss:[ebp+402FF0], 4
004235ED 74 0E je short _ExeStea.004235FD
004235EF 8D85 322D4000 lea eax, dword ptr ss:[ebp+402D32]
004235F5 50 push eax ; 压入返回地址
004235F6 8BC3 mov eax, ebx
004235F8 E9 48020000 jmp _ExeStea.00423845 ; 清空字符串函数,是一个call,改成jmp了
004235FD 5B pop ebx ; 取出Dll的基址
004235FE 8B4E 08 mov ecx, dword ptr ds:[esi+8]
00423601 0BC9 or ecx, ecx
00423603 75 03 jnz short _ExeStea.00423608
00423605 8B4E 04 mov ecx, dword ptr ds:[esi+4]
00423608 038D E82F4000 add ecx, dword ptr ss:[ebp+402FE8] ; 获取API名字字符串
0042360E 8B56 04 mov edx, dword ptr ds:[esi+4]
00423611 0395 E82F4000 add edx, dword ptr ss:[ebp+402FE8] ; 获取IAT地址
00423617 E9 C3000000 jmp _ExeStea.004236DF
0042361C F701 00000080 test dword ptr ds:[ecx], 80000000 ; 是否为序号输入
00423622 75 4B jnz short _ExeStea.0042366F
00423624 8B01 mov eax, dword ptr ds:[ecx]
00423626 83C0 02 add eax, 2
00423629 0385 E82F4000 add eax, dword ptr ss:[ebp+402FE8]
0042362F 50 push eax
00423630 E8 8BFFFFFF call _ExeStea.004235C0 ; 解密API的字符串
00423635 58 pop eax
00423636 8BF8 mov edi, eax
00423638 52 push edx
00423639 51 push ecx
0042363A 50 push eax
0042363B 53 push ebx
0042363C FF95 48344000 call dword ptr ss:[ebp+403448] ; GetProcAddress获取API地址
00423642 0BC0 or eax, eax
00423644 75 07 jnz short _ExeStea.0042364D
00423646 59 pop ecx
00423647 5A pop edx
00423648 E9 AB000000 jmp _ExeStea.004236F8
0042364D 59 pop ecx
0042364E 5A pop edx
0042364F 60 pushad
00423650 F785 F02F4000 0>test dword ptr ss:[ebp+402FF0], 4
0042365A 74 0E je short _ExeStea.0042366A
0042365C 8D85 9F2D4000 lea eax, dword ptr ss:[ebp+402D9F] ; 需要清空的字符串
00423662 50 push eax ; 压入返回地址
00423663 8BC7 mov eax, edi
00423665 E9 DB010000 jmp _ExeStea.00423845 ; call清空字符串,伪装成jmp了
0042366A 61 popad
0042366B 8902 mov dword ptr ds:[edx], eax ; 保存API地址到IAT
0042366D EB 19 jmp short _ExeStea.00423688
0042366F 52 push edx
00423670 51 push ecx
00423671 8B01 mov eax, dword ptr ds:[ecx]
00423673 2D 00000080 sub eax, 80000000
00423678 50 push eax
00423679 53 push ebx
0042367A FF95 48344000 call dword ptr ss:[ebp+403448]
00423680 85C0 test eax, eax
00423682 74 74 je short _ExeStea.004236F8
00423684 59 pop ecx
00423685 5A pop edx
00423686 8902 mov dword ptr ds:[edx], eax
00423688 F785 F02F4000 2>test dword ptr ss:[ebp+402FF0], 20
00423692 74 45 je short _ExeStea.004236D9
00423694 83BD FC2F4000 0>cmp dword ptr ss:[ebp+402FFC], 0
0042369B 74 14 je short _ExeStea.004236B1
0042369D 81FB 00000070 cmp ebx, 70000000
004236A3 72 08 jb short _ExeStea.004236AD
004236A5 81FB FFFFFF77 cmp ebx, 77FFFFFF
004236AB 76 0E jbe short _ExeStea.004236BB
004236AD EB 2A jmp short _ExeStea.004236D9
004236AF EB 0A jmp short _ExeStea.004236BB
004236B1 81FB 00000080 cmp ebx, 80000000
004236B7 73 02 jnb short _ExeStea.004236BB
004236B9 EB 1E jmp short _ExeStea.004236D9
004236BB 57 push edi
004236BC 56 push esi
004236BD 8DBD 26354000 lea edi, dword ptr ss:[ebp+403526]
004236C3 8B77 04 mov esi, dword ptr ds:[edi+4]
004236C6 8932 mov dword ptr ds:[edx], esi ; 将IAT里地址改写分配的内存地址
004236C8 2BC6 sub eax, esi
004236CA 83E8 05 sub eax, 5
004236CD C606 E9 mov byte ptr ds:[esi], 0E9 ; 修改分配内存中的指令为jmp APIXX
004236D0 8946 01 mov dword ptr ds:[esi+1], eax
004236D3 8347 04 05 add dword ptr ds:[edi+4], 5 ; 下一个填充到IAT的地址
004236D7 5E pop esi
004236D8 5F pop edi
004236D9 83C1 04 add ecx, 4 ; 下一个API名字字符串
004236DC 83C2 04 add edx, 4 ; IAT数组下一个元素
004236DF 8339 00 cmp dword ptr ds:[ecx], 0
004236E2 ^ 0F85 34FFFFFF jnz _ExeStea.0042361C ; 继续下一个API的处理
004236E8 83C6 0C add esi, 0C
004236EB 837E 04 00 cmp dword ptr ds:[esi+4], 0
004236EF ^ 0F85 B4FEFFFF jnz _ExeStea.004235A9 ; 继续下一个Dll的处理
004236F5 33C0 xor eax, eax
004236F7 40 inc eax
004236F8 83F8 01 cmp eax, 1
004236FB 74 02 je short _ExeStea.004236FF
开始填充IAT了,首先获取变形的输入表,然后填充IAT,然后再将IAT简单加密。
变形的IAT的 IID结构是这样的
004238CB 00006630 Offset_DllName
004238CF 00006000 Offset_FirstThunk
004238D3 0000651C Offset_OriginalFirstThunk
一个IID存放3个偏移
004238D7 000066A8 Offset_DllName
004238DB 000060C4 Offset_FirstThunk
004238DF 000065E0 Offset_OriginalFirstThunk
但是,DllName,OriginalFirstThunk中的字符串全部都是加密的。
在使用LoadLibrary和GetProcAddress的时候先解密出字符串,然后再调用函数,调用完成后清除字符串
填充IAT的过程如下:
首先GlobalAlloc分配一块内存地址
1.Loadlibrary加载导入的Dll
2.循环使用GetProcAddress获取API地址
3.填充API地址到IAT数组
4.将IAT中的API地址改成分配内存的中地址
5.在上述内存地址处写入 jmp APIXX 的形式的指令
最后在IAT就是如下形式:
00406000 00253058
00406004 0025305D
00406008 00253062
0040600C 00253067
00406010 0025306C
00406014 00253071
而IAT中的地址的内容就是
00253058 - E9 59E2F575 jmp kernel32.lstrcatA
0025305D - E9 A9DBF775 jmp kernel32.GetVolumeInformationA
00253062 - E9 DA64F775 jmp kernel32.lstrlenA
00253067 - E9 E91EF775 jmp kernel32.CompareStringW
0025306C - E9 1260F775 jmp kernel32.CompareStringA
00253071 - E9 EC2DF775 jmp kernel32.GetStringTypeW
就是将IAT进行了重定向,这样便不能 一目了然IAT中的API地址
实现了最简单的IAT加密吧算是。
IAT填充完毕之后,开始检测调试和内存文件校验
00423723 8D85 95274000 lea eax, dword ptr ss:[ebp+402795]
00423729 B9 06070000 mov ecx, 706
0042372E EB 01 jmp short _ExeStea.00423731
00423730 - E9 E88EFCFF jmp 003EC61D
00423735 FFEB jmp far ebx ; 非法使用寄存器
00423737 01C7 add edi, eax
00423739 8B9D F82F4000 mov ebx, dword ptr ss:[ebp+402FF8]
0042373F 33C3 xor eax, ebx
00423741 74 08 je short _ExeStea.0042374B
00423743 EB 01 jmp short _ExeStea.00423746
00423745 2C 61 sub al, 61
00423747 EB 01 jmp short _ExeStea.0042374A
00423749 E8 C38DBD9B call 9BFFC511
0042374E 2E:40 inc eax
00423750 008B F7B9DF00 add byte ptr ds:[ebx+DFB9F7], cl
00423756 0000 add byte ptr ds:[eax], al
00423758 33DB xor ebx, ebx
花指令还是不少,慢慢跟
00423731 E8 8EFCFFFF call _ExeStea.004233C4 ; 求壳入口点之后0x706字节的校验和
00423736 EB 01 jmp short _ExeStea.00423739
00423738 C7 ??? ; 未知命令
00423739 8B9D F82F4000 mov ebx, dword ptr ss:[ebp+402FF8]
0042373F 33C3 xor eax, ebx ; 判断是否壳代码是否被修改
0042373F 33C3 xor eax, ebx ; 判断是否壳代码是否被修改
00423741 74 08 je short _ExeStea.0042374B
00423743 EB 01 jmp short _ExeStea.00423746
再次求壳代码的校验和,然后判断和先计算的校验和是否相等来判断壳代码是否被修改,接着走
0042374B 8DBD 9B2E4000 lea edi, dword ptr ss:[ebp+402E9B]
00423751 8BF7 mov esi, edi
00423753 B9 DF000000 mov ecx, 0DF
00423758 33DB xor ebx, ebx
0042375A AC lods byte ptr ds:[esi]
0042375B 34 77 xor al, 77
0042375D 2AC3 sub al, bl
0042375F C0C0 02 rol al, 2
00423762 AA stos byte ptr es:[edi]
00423763 43 inc ebx
00423764 ^ E2 F4 loopd short _ExeStea.0042375A ; 循环解压下面一段代码
00423766 14 15 adc al, 15
00423768 37 aaa
00423769 67:6372 6D arpl word ptr ss:[bp+si+6D], si
又是解压一段代码, 在00423766 F4
00423766 8D85 F8344000 lea eax, dword ptr ss:[ebp+4034F8] ; 指向IsDebuggerPresent字符串
0042376C 50 push eax
0042376D FFB5 59344000 push dword ptr ss:[ebp+403459]
00423773 FF95 48344000 call dword ptr ss:[ebp+403448] ; GetPorcAddress获取IsDebuggerPresent的地址
00423779 0BC0 or eax, eax
0042377B 74 08 je short _ExeStea.00423785
0042377D FFD0 call eax ; 调用IsDebuggerPresent检测调试器
0042377F 0BC0 or eax, eax
00423781 74 02 je short _ExeStea.00423785 ; 没有发现调试器则跳走
00423783 61 popad
00423784 C3 retn ; 发现调试器返回到错误的地址造成程序异常结束
00423785 F785 F02F4000 0>test dword ptr ss:[ebp+402FF0], 1
0042378F 74 4F je short _ExeStea.004237E0
通过IsDebuggerPresent检测调试器,发现调试器则跳到错误的地址使程序异常结束
00423785 F785 F02F4000 0>test dword ptr ss:[ebp+402FF0], 1
0042378F 74 4F je short _ExeStea.004237E0
00423791 8DB5 38344000 lea esi, dword ptr ss:[ebp+403438]
00423797 8D85 F02E4000 lea eax, dword ptr ss:[ebp+402EF0]
0042379D 8946 08 mov dword ptr ds:[esi+8], eax
004237A0 33DB xor ebx, ebx
004237A2 8D85 B72F4000 lea eax, dword ptr ss:[ebp+402FB7]
004237A8 50 push eax ; 异常处理Handle
004237A9 64:FF33 push dword ptr fs:[ebx]
004237AC 64:8923 mov dword ptr fs:[ebx], esp
004237AF 8BFD mov edi, ebp
004237B1 B8 00440000 mov eax, 4400
004237B6 EB 01 jmp short _ExeStea.004237B9
004237B8 C7 ??? ; 花指令
004237B9 CD 68 int 68 ; 产生异常
004237BB 33DB xor ebx, ebx
004237BD 64:8F03 pop dword ptr fs:[ebx]
004237C0 83C4 04 add esp, 4
004237C3 66:81FF 9712 cmp di, 1297
又是一个异常通过 INT68触发,异常Handle什么也没做,只是修改EIP为异常的下一条指令跳过异常
0042381A 32C0 xor al, al
0042381C 8DBD 95274000 lea edi, dword ptr ss:[ebp+402795]
00423822 B9 88070000 mov ecx, 788
00423827 AA stos byte ptr es:[edi]
00423828 ^ E2 FD loopd short _ExeStea.00423827 ; 清除壳代码
0042382A 8DBD 7A2F4000 lea edi, dword ptr ss:[ebp+402F7A]
00423830 B9 90050000 mov ecx, 590
00423835 AA stos byte ptr es:[edi]
00423836 ^ E2 FD loopd short _ExeStea.00423835 ; 清除壳代码
00423838 61 popad
00423839 50 push eax ; 异常Handle
0042383A 33C0 xor eax, eax
0042383C 64:FF30 push dword ptr fs:[eax]
0042383F 64:8920 mov dword ptr fs:[eax], esp
00423842 EB 01 jmp short _ExeStea.00423845 ; 跳到内容为全0的地址去执行触发异常
最后清除壳代码,再次引发异常来修改EIP为OEP
异常Handle如下
004237EB 57 push edi
004237EC 8B45 10 mov eax, dword ptr ss:[ebp+10]
004237EF 8BB8 C4000000 mov edi, dword ptr ds:[eax+C4] ; 获取esp
004237F5 FF37 push dword ptr ds:[edi]
004237F7 33FF xor edi, edi
004237F9 64:8F07 pop dword ptr fs:[edi] ; 恢复异常链
004237FC 8380 C4000000 0>add dword ptr ds:[eax+C4], 8 ; 恢复堆栈
00423803 8BB8 A4000000 mov edi, dword ptr ds:[eax+A4]
00423809 C1C7 07 rol edi, 7 ; 还原变形的OEP
0042380C 89B8 B8000000 mov dword ptr ds:[eax+B8], edi ; 更改EIP到OEP
00423812 B8 00000000 mov eax, 0
00423817 5F pop edi
00423818 C9 leave
00423819 C3 retn
恢复了异常链并且修改EIP到OEP
总结:
加壳之后程序大小没有很大变化,只是增加了一个壳的区段,因为壳没有对原程序进行压缩,而
只是对原程序进行了一些xor和sar等运算而已
壳的运行流程:
1.解压出壳的核心代码和数据
2.求出壳代码和文件的校验和
3.解压原程序
4.校验文件是否被修改
5.填充并加密IAT
6.通过IsDebuggerPresent检测调试
7.校验壳代码是否被修改
8.清除壳的代码和数据
9.通过异常修改EIP到OEP
最基本的加密壳就分析完了,脱壳也非常简单,DUMP后修复下IAT就可以了
已经有(0)位网友发表了评论,你也评一评吧!
原创文章如转载,请注明:转载自Eddy Blog
原文地址:http://www.rrgod.com/decryption/371.html 欢迎订阅Eddy Blog。
Tags:ExeStealth