一个简单压缩壳的脱壳
这个样本就不发了 发了 估计也没人愿意调木马 最初曾经上来求助该壳的脱法,但是因为加壳的程序是个木马所以没人帮忙,不得已只有自己上场了壳是个 未知壳
00411314 >33FF XOR EDI,EDI
00411316 B8 D8DFDD06 MOV EAX,6DDDFD8
0041131B 33C9 XOR ECX,ECX
0041131D BB 51134100 MOV EBX,b2ce2819.00411351 ;自解密的起始地址
00411322 81FF 0F270000 CMP EDI,270F
00411328 75 02 JNZ SHORT b2ce2819.0041132C
0041132A 2803 SUB BYTE PTR DS:,AL ;解密的算法 只是简单的减KEY 为D8,DF,DD,06循环
0041132C 43 INC EBX
0041132D C1E8 08 SHR EAX,8
00411330 41 INC ECX
00411331 83F9 04 CMP ECX,4
00411334 75 0A JNZ SHORT b2ce2819.00411340
00411336 B8 D8DFDD06 MOV EAX,6DDDFD8
0041133B B9 00000000 MOV ECX,0
00411340 81FB 53164100 CMP EBX,b2ce2819.00411653 ;解密的终止地址
00411346^ 72 DA JB SHORT b2ce2819.00411322
00411348 47 INC EDI
00411349 81FF 15270000 CMP EDI,2715
0041134F^ 76 C5 JBE SHORT b2ce2819.00411316 ;整个循环干扰性比较大 只有当EDI为270F 才执行解密流程
解密后:
00411351 90 NOP
00411352 90 NOP
00411353 90 NOP
00411354 23C9 AND ECX,ECX
00411356 23C9 AND ECX,ECX
00411358 23C9 AND ECX,ECX
0041135A 23C9 AND ECX,ECX
0041135C 23C9 AND ECX,ECX
0041135E 23C9 AND ECX,ECX
00411360 23C9 AND ECX,ECX
00411362 23C9 AND ECX,ECX
00411364 23C9 AND ECX,ECX
00411366 23C9 AND ECX,ECX
00411368 23C9 AND ECX,ECX
0041136A 23C9 AND ECX,ECX
0041136C 23C9 AND ECX,ECX
0041136E 23C9 AND ECX,ECX
00411370 23C9 AND ECX,ECX
...................................
...................................
00411392 B9 D8DFDD06 MOV ECX,6DDDFD8
00411397 3B0C24 CMP ECX,DWORD PTR SS:
0041139A 0F84 8C010000 JE b2ce2819.0041152C ;通过这个比较来执行不同的流程
004113A0 B9 00000000 MOV ECX,0
004113A5 BB 51134100 MOV EBX,b2ce2819.00411351
004113AA 83C3 32 ADD EBX,32
004113AD 8B0424 MOV EAX,DWORD PTR SS:
004113B0 43 INC EBX
004113B1 81FB 53164100 CMP EBX,b2ce2819.00411653
004113B7^ 75 F4 JNZ SHORT b2ce2819.004113AD
004113B9 41 INC ECX
004113BA 81F9 905F0100 CMP ECX,15F90
004113C0^ 75 E3 JNZ SHORT b2ce2819.004113A5;这个循环的作用 只是使ECX=15F90,EBX=411653(上面解密数据的终止地址)
004113C2 33C0 XOR EAX,EAX
004113C4 8B0424 MOV EAX,DWORD PTR SS: ;esp指向的是KERNEL里的一个地址这里使用它来得到KERNEL的基地址
004113C7 66:33C0 XOR AX,AX
;四个函数名的HASH值压入堆栈
004113CA 68 FFFF0000 PUSH 0FFFF
004113CF 68 B674755D PUSH 5D7574B6 ;VirtualProtect
004113D4 68 2207E471 PUSH 71E40722 ;LoadLibraryA
004113D9 68 80EFF815 PUSH 15F8EF80 ;GetProcAddress
004113DE 68 EC5863D6 PUSH D66358EC ;Exitprocess
004113E3 8BFC MOV EDI,ESP
004113E5 66:8138 4D5A CMP WORD PTR DS:,5A4D ;比较DOS HEADER
004113EA 75 13 JNZ SHORT b2ce2819.004113FF
004113EC 8B50 3C MOV EDX,DWORD PTR DS:
004113EF 81FA 00100000 CMP EDX,1000
004113F5 77 08 JA SHORT b2ce2819.004113FF
004113F7 66:813C10 5045CMP WORD PTR DS:,4550 ;比较PE HEADER
004113FD 74 07 JE SHORT b2ce2819.00411406
004113FF 2D 00000100 SUB EAX,10000
00411404^ EB DF JMP SHORT b2ce2819.004113E5 ;循环结束时EAX里存放的是KERNEL的基址,EDX里存放的是PE HEADER的RVA
00411406 50 PUSH EAX ;kernel基址入栈
00411407 8B7410 78 MOV ESI,DWORD PTR DS:;导出表RVA
0041140B 03F0 ADD ESI,EAX 导出表VA
0041140D 83C6 18 ADD ESI,18 IMAGE_EXPORT_DIRECTORY.NumberOfNames的VA
00411410 93 XCHG EAX,EBX
00411411 AD LODS DWORD PTR DS:
00411412 50 PUSH EAX 保存IMAGE_EXPORT_DIRECTORY.NumberOfNames
00411413 AD LODS DWORD PTR DS: IMAGE_EXPORT_DIRECTORY.AddressOfFunctions的VA
00411414 50 PUSH EAX 保存IMAGE_EXPORT_DIRECTORY.AddressOfFunctions
00411415 AD LODS DWORD PTR DS: AddressOfNames的VA
00411416 50 PUSH EAX 保存AddressOfNames
00411417 03C3 ADD EAX,EBX
00411419 50 PUSH EAX 得到 函数名地址表的VA
0041141A AD LODS DWORD PTR DS: AddressOfNameOrdinals的VA
0041141B 50 PUSH EAX 保存AddressOfNameOrdinals
0041141C 8BEC MOV EBP,ESP ;通过EBP寻址
0041141E 8B4D 10 MOV ECX,DWORD PTR SS: ;NumberOfNames以函数名导出的函数数目
00411421 33D2 XOR EDX,EDX
00411423 8B75 04 MOV ESI,DWORD PTR SS: 函数名地址表的VA
00411426 8B36 MOV ESI,DWORD PTR DS: 存放函数名的RVA
00411428 03F3 ADD ESI,EBX 存放函数名的VA
0041142A 33C0 XOR EAX,EAX
0041142C 50 PUSH EAX
0041142D C1C8 07 ROR EAX,7
00411430 310424 XOR DWORD PTR SS:,EAX
00411433 AC LODS BYTE PTR DS:
00411434 84C0 TEST AL,AL
00411436^ 75 F5 JNZ SHORT b2ce2819.0041142D 得到导出表函数名的HASH值
;下面是 通过遍历导出表得到 所需函数的地址,原理很简单 但很常用。。。今天调试的一个驱动壳 也是靠PE结构来得到ntkrnlpa的导出函数
00411438 58 POP EAX
00411439 57 PUSH EDI
0041143A 813F FFFF0000 CMP DWORD PTR DS:,0FFFF
00411440 74 09 JE SHORT b2ce2819.0041144B
00411442 3B07 CMP EAX,DWORD PTR DS:
00411444 74 0F JE SHORT b2ce2819.00411455
00411446 83C7 04 ADD EDI,4
00411449^ EB EF JMP SHORT b2ce2819.0041143A 与上面压入堆栈的函数名HASH值比较
0041144B 5F POP EDI
0041144C 8345 04 04 ADD DWORD PTR SS:,4
00411450 42 INC EDX
00411451^ E2 D0 LOOPD SHORT b2ce2819.00411423
00411453 /EB 2C JMP SHORT b2ce2819.00411481 ;函数地址得到后 从这里跳出
00411455 |D1E2 SHL EDX,1 ;这句执行前EDX为特定函数在AddressOfNameOrdinals数组下标
这句执行后 等于EDX*2(AddressOfNameOrdinals为字数组)
00411457 |8B4D 00 MOV ECX,DWORD PTR SS:
0041145A |03CB ADD ECX,EBX
0041145C |03CA ADD ECX,EDX
0041145E |8B09 MOV ECX,DWORD PTR DS: ;得到特定函数的导出序号相对于NBASE的偏移
00411460 |81E1 FFFF0000 AND ECX,0FFFF
00411466 |8B55 0C MOV EDX,DWORD PTR SS:
00411469 |03D3 ADD EDX,EBX
0041146B |C1E1 02 SHL ECX,2 AddressOfFunctions为双字数组存放的是函数地址的RVA
0041146E |03D1 ADD EDX,ECX
00411470 |8B12 MOV EDX,DWORD PTR DS: 得到特定函数的RVA
00411472 |03D3 ADD EDX,EBX
00411474 |8917 MOV DWORD PTR DS:,EDX 得到特定函数的VA
00411476 |8B4D 08 MOV ECX,DWORD PTR SS:
00411479 |03CB ADD ECX,EBX
0041147B |894D 04 MOV DWORD PTR SS:,ECX
0041147E |5F POP EDI
0041147F^|EB 9D JMP SHORT b2ce2819.0041141E
00411481 83EF 04 SUB EDI,4
00411484 8BE7 MOV ESP,EDI
00411486 8B5C24 08 MOV EBX,DWORD PTR SS:
0041148A 8BFC MOV EDI,ESP
0041148C 83EF 04 SUB EDI,4
0041148F 57 PUSH EDI
00411490 6A 40 PUSH 40
00411492 68 00100000 PUSH 1000
00411497 68 00004000 PUSH b2ce2819.00400000 ; ASCII "MZ"
0041149C FFD3 CALL EBX ; kernel32.VirtualProtect;将400000开始的大小为1000的内存页属性改变为可读写可执行
0041149E BF 00004000 MOV EDI,b2ce2819.00400000 ; ASCII "MZ" PE头的VA
004114A3 037F 3C ADD EDI,DWORD PTR DS: ;修正PE头里的值
004114A6 C787 A0000000 0>MOV DWORD PTR DS:,13000 ;IMAGE_DIRECTORY_ENTRY_BASERELOC的起始地址
004114B0 C787 A4000000 3>MOV DWORD PTR DS:,1338 ;IMAGE_DIRECTORY_ENTRY_BASERELOC的大小
004114BA C787 80000000 0>MOV DWORD PTR DS:,0 ;IMAGE_DIRECTORY_ENTRY_IMPORT的起始地址
004114C4 C787 84000000 0>MOV DWORD PTR DS:,0 ;IMAGE_DIRECTORY_ENTRY_IMPORT的大小
004114CE 8BD7 MOV EDX,EDI
004114D0 83C2 18 ADD EDX,18 ;IMAGE_OPTIONAL_HEADER32的起始地址
004114D3 33C9 XOR ECX,ECX
004114D5 66:8B4F 14 MOV CX,WORD PTR DS: ;IMAGE_OPTIONAL_HEADER32 的大小
004114D9 03D1 ADD EDX,ECX ;定位到节表
004114DB 66:33C9 XOR CX,CX
004114DE 8B72 0C MOV ESI,DWORD PTR DS: ;节区的起始RVA
004114E1 81C6 00004000 ADD ESI,b2ce2819.00400000 ; ASCII "MZ"
004114E7 60 PUSHAD
004114E8 8BFC MOV EDI,ESP
004114EA 83EF 04 SUB EDI,4
004114ED 57 PUSH EDI
004114EE 6A 40 PUSH 40
004114F0 FF72 08 PUSH DWORD PTR DS: ;节区大小
004114F3 56 PUSH ESI
004114F4 FFD3 CALL EBX ;将节的内存属性改变为可读可写可执行
004114F6 61 POPAD
004114F7 83C2 28 ADD EDX,28
004114FA 66:41 INC CX
004114FC 66:3B4F 06 CMP CX,WORD PTR DS:
00411500^ 72 DC JB SHORT b2ce2819.004114DE ;改变PE文件所有节的属性 一共有3个节
00411502 83EA 28 SUB EDX,28 ;定位到最后一个节
00411505 8B42 0C MOV EAX,DWORD PTR DS: ;最后一个节的起始RVA
00411508 0342 10 ADD EAX,DWORD PTR DS: ;+在文件中对齐后的尺寸
0041150B 05 00004000 ADD EAX,b2ce2819.00400000 ; ASCII "MZ"
00411510 83C0 64 ADD EAX,64
00411513 60 PUSHAD
00411514 8BF8 MOV EDI,EAX
00411516 BE 51134100 MOV ESI,b2ce2819.00411351
0041151B B9 53164100 MOV ECX,b2ce2819.00411653
00411520 2BCE SUB ECX,ESI
00411522 F3:A4 REP MOVS BYTE PTR ES:,BYTE PTR DS: ;将第一次解密的代码 拷到最后一个节偏移64H的内存中
00411524 61 POPAD
00411525 68 D8DFDD06 PUSH 6DDDFD8 ;通过比较是否是6DDDFD8来执行解密后代码另一个流程
0041152A FFE0 JMP EAX
0041503F 5E POP ESI ; b2ce2819.00413000
00415040 05 53164100 ADD EAX,b2ce2819.00411653
00415045 2D 51134100 SUB EAX,b2ce2819.00411351 ;得到 复制后解密代码的终止地址
0041504A 8BD8 MOV EBX,EAX
0041504C 33C0 XOR EAX,EAX
0041504E 66:8B47 06 MOV AX,WORD PTR DS: ;节的数目
00415052 66:48 DEC AX
00415054 6BC0 28 IMUL EAX,EAX,28
00415057 2BD0 SUB EDX,EAX ;定位到第一个节
00415059 66:33C9 XOR CX,CX
0041505C 8B72 0C MOV ESI,DWORD PTR DS: ;节的起始RVA
0041505F 81C6 00004000 ADD ESI,b2ce2819.00400000 ; ASCII "MZ"
00415065 33C0 XOR EAX,EAX
00415067 8A06 MOV AL,BYTE PTR DS: 解压开始
00415069 03F0 ADD ESI,EAX
0041506B 60 PUSHAD
0041506C 8BFB MOV EDI,EBX
0041506E E8 1E000000 CALL b2ce2819.00415091 ;解压关键CALL
00415073 8B0E MOV ECX,DWORD PTR DS:
00415075 8BFE MOV EDI,ESI
00415077 2BF8 SUB EDI,EAX
00415079 8BF3 MOV ESI,EBX
0041507B F3:A4 REP MOVS BYTE PTR ES:,BYTE PTR DS:;将解压后的数据拷贝回原来的节
0041507D 61 POPAD
0041507E 83C2 28 ADD EDX,28
00415081 66:41 INC CX
00415083 66:3B4F 06 CMP CX,WORD PTR DS:
00415087^ 72 D3 JB SHORT b2ce2819.0041505C
00415089 B8 B15B4000 MOV EAX,b2ce2819.00405BB1
0041508E FFD0 CALL EAX ;跟进这里就是OEP了最初有点怀疑 因为IAT里没有导入函数 索性把样本完整分析一遍后
可以确定跟进去的就是OEP 木马本身调用的函数都是动态调用所以IAT里没有函数
00415090 C3 RETN
;解压关键CALL
;每一节解密的前8个字节中 第一个DWORD值代表解压后节的大小,第二个DWORD值代表解压前 从解密后的8字节开始 的数据大小
00415091 60 PUSHAD
00415092 BB 3B5FCA3A MOV EBX,3ACA5F3B
00415097 B9 00000000 MOV ECX,0
0041509C BA 00000000 MOV EDX,0
004150A1 281E SUB BYTE PTR DS:,BL ;解密KEY 为3B,5F,CA,3A循环
004150A3 C1EB 08 SHR EBX,8
004150A6 41 INC ECX
004150A7 83F9 04 CMP ECX,4
004150AA 75 0A JNZ SHORT b2ce2819.004150B6
004150AC BB 3B5FCA3A MOV EBX,3ACA5F3B
004150B1 B9 00000000 MOV ECX,0
004150B6 46 INC ESI
004150B7 42 INC EDX
004150B8 83FA 08 CMP EDX,8
004150BB^ 7C E4 JL SHORT b2ce2819.004150A1
004150BD 7F 05 JG SHORT b2ce2819.004150C4
004150BF 8B46 FC MOV EAX,DWORD PTR DS:
004150C2 03C6 ADD EAX,ESI
004150C4 3BF0 CMP ESI,EAX
004150C6^ 7C D9 JL SHORT b2ce2819.004150A1
004150C8 61 POPAD
...........................................下面的就是解压过程 不贴代码了
[ 本帖最后由 xhn1002 于 2008-8-29 17:47 编辑 ] 看得不太懂 楼主开始求人脱,现在都会自己脱,恭喜啊
页:
[1]