一个小木马脱壳 请虚拟机下调试 相关文件见附件 未知壳相当简单 但是典型 有stolen code和overlay 只是练习脱壳 所以没有分析木马
初次实战 一路F8
载入:
00410336 > $ 57 PUSH EDI
00410337 . 8BFC MOV EDI,ESP
00410339 . 83EC 26 SUB ESP,26
0041033C . C74424 0E 000>MOV DWORD PTR SS:[ESP+E],0
00410344 > C74424 06 FB6>MOV DWORD PTR SS:[ESP+6],DC8A65FB ;解密key
0041034C . C74424 02 000>MOV DWORD PTR SS:[ESP+2],0
00410354 . BE D5034100 MOV ESI,1.004103D5 ;解密起始地址
00410359 . 897424 12 MOV DWORD PTR SS:[ESP+12],ESI
0041035D > EB 00 JMP SHORT 1.0041035F
0041035F > BE 7A210000 MOV ESI,217A
00410364 . 03F7 ADD ESI,EDI
00410366 . 2BF4 SUB ESI,ESP ;esi + esp + (esp-26h) = esi + 26h
00410368 . 397424 0E CMP DWORD PTR SS:[ESP+E],ESI ;[esp+e]计数器
0041036C . 74 02 JE SHORT 1.00410370
0041036E . EB 0C JMP SHORT 1.0041037C
00410370 > 8B7424 12 MOV ESI,DWORD PTR SS:[ESP+12] ;[esp+e] == esi时 才开始解密
00410374 . 8A6424 06 MOV AH,BYTE PTR SS:[ESP+6]
00410378 . 2826 SUB BYTE PTR DS:[ESI],AH
0041037A . EB 00 JMP SHORT 1.0041037C
0041037C > 834424 12 01 ADD DWORD PTR SS:[ESP+12],1
00410381 . C16C24 06 02 SHR DWORD PTR SS:[ESP+6],2
00410386 . C16C24 06 02 SHR DWORD PTR SS:[ESP+6],2
0041038B . C16C24 06 02 SHR DWORD PTR SS:[ESP+6],2
00410390 . C16C24 06 02 SHR DWORD PTR SS:[ESP+6],2 ;右移8位 即右移一个字节
00410395 . 834424 02 01 ADD DWORD PTR SS:[ESP+2],1
0041039A . 837C24 02 04 CMP DWORD PTR SS:[ESP+2],4
0041039F . 75 10 JNZ SHORT 1.004103B1
004103A1 . C74424 06 FB6>MOV DWORD PTR SS:[ESP+6],DC8A65FB
004103A9 . C74424 02 000>MOV DWORD PTR SS:[ESP+2],0
004103B1 > BE 98064100 MOV ESI,1.00410698 ;解密终止地址
004103B6 . 397424 12 CMP DWORD PTR SS:[ESP+12],ESI
004103BA .^ 72 A1 JB SHORT 1.0041035D
004103BC . FF4424 0E INC DWORD PTR SS:[ESP+E]
004103C0 . 817C24 0E 332>CMP DWORD PTR SS:[ESP+E],2333
004103C8 .^ 0F86 76FFFFFF JBE 1.00410344
//整个解密过程 简单但是干扰性极大 [esp+e]为21A0时解密才开始 解密过程的key为DC8A65FB 变换过程 循环右移一个字节
00410407 |. 33C0 XOR EAX,EAX
00410409 |. 8B0424 MOV EAX,DWORD PTR SS:[ESP] ;kernel里的一个地址送eax
0041040C |. 66:33C0 XOR AX,AX
0041040F |. 68 FFFF0000 PUSH 0FFFF ;函数名HASH值入栈
00410414 |. 68 B674755D PUSH 5D7574B6 ;GetProcAddress
00410419 |. 68 2207E471 PUSH 71E40722 ;LoadLibraryA
0041041E |. 68 80EFF815 PUSH 15F8EF80 ;VirtualProtect
00410423 |. 68 EC5863D6 PUSH D66358EC ;ExitProcess
00410428 |. 8BFC MOV EDI,ESP ;EDI 用来定位 堆栈
0041042A |> 66:8138 4D5A /CMP WORD PTR DS:[EAX],5A4D ;PE
0041042F |. 75 13 |JNZ SHORT 1.00410444
00410431 |. 8B50 3C |MOV EDX,DWORD PTR DS:[EAX+3C]
00410434 |. 81FA 00100000 |CMP EDX,1000
0041043A |. 77 08 |JA SHORT 1.00410444
0041043C |. 66:813C10 504>|CMP WORD PTR DS:[EAX+EDX],4550 ;MZ
00410442 |. 74 07 |JE SHORT 1.0041044B
00410444 |> 2D 00000100 |SUB EAX,10000 ; UNICODE "ALLUSERSPROFILE=C:\Documents and Settings\All Users"
00410449 |.^ EB DF \JMP SHORT 1.0041042A
//寻找kernel 基址
0041044B |> \50 PUSH EAX ; kernel32.7C800000
0041044C |. 8B7410 78 MOV ESI,DWORD PTR DS:[EAX+EDX+78] ; 定位到DataDirectory[0].VirtualAddress
00410450 |. 03F0 ADD ESI,EAX ; 定位到导出表
00410452 |. 83C6 18 ADD ESI,18 ;IMAGE_EXPORT_DIRECTORY.NumberOfNames
00410455 |. 93 XCHG EAX,EBX
00410456 |. AD LODS DWORD PTR DS:[ESI]
00410457 |. 50 PUSH EAX ;IMAGE_EXPORT_DIRECTORY.NumberOfNames入栈
00410458 |. AD LODS DWORD PTR DS:[ESI]
00410459 |. 50 PUSH EAX ;IMAGE_EXPORT_DIRECTORY.AddressOfFunctions入栈
0041045A |. AD LODS DWORD PTR DS:[ESI]
0041045B |. 50 PUSH EAX ;IMAGE_EXPORT_DIRECTORY.AddressOfNames入栈
0041045C |. 03C3 ADD EAX,EBX
0041045E |. 50 PUSH EAX ;IMAGE_EXPORT_DIRECTORY.AddressOfNames+ImageBase入栈
0041045F |. AD LODS DWORD PTR DS:[ESI]
00410460 |. 50 PUSH EAX ;IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals入栈
00410461 |. 8BEC MOV EBP,ESP ;EBP指向IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals
00410463 |> 8B4D 10 /MOV ECX,DWORD PTR SS:[EBP+10] ;IMAGE_EXPORT_DIRECTORY.NumberOfNames
00410466 |. 33D2 |XOR EDX,EDX
00410468 |> 8B75 04 |/MOV ESI,DWORD PTR SS:[EBP+4] ;IMAGE_EXPORT_DIRECTORY.AddressOfNames+ImageBase
0041046B |. 8B36 ||MOV ESI,DWORD PTR DS:[ESI] ;ESI 为 函数名的起始地址RVA
0041046D |. 03F3 ||ADD ESI,EBX ;得到函数名地址VA
0041046F |. 33C0 ||XOR EAX,EAX
00410471 |. 50 ||PUSH EAX
00410472 |> C1C8 07 ||/ROR EAX,7
00410475 |. 310424 |||XOR DWORD PTR SS:[ESP],EAX
00410478 |. AC |||LODS BYTE PTR DS:[ESI]
00410479 |. 84C0 |||TEST AL,AL
0041047B |.^ 75 F5 ||\JNZ SHORT 1.00410472 ;函数名HASH
0041047D |. 58 ||POP EAX
0041047E |. 57 ||PUSH EDI
0041047F |> 813F FFFF0000 ||/CMP DWORD PTR DS:[EDI],0FFFF ;函数是否 地址都找到 找到就跳
00410485 |. 74 09 |||JE SHORT 1.00410490
00410487 |. 3B07 |||CMP EAX,DWORD PTR DS:[EDI] ;比较函数名HASH值
00410489 |. 74 0F |||JE SHORT 1.0041049A
0041048B |. 83C7 04 |||ADD EDI,4
0041048E |.^ EB EF ||\JMP SHORT 1.0041047F
00410490 |> 5F ||POP EDI
00410491 |. 8345 04 04 ||ADD DWORD PTR SS:[EBP+4],4 ;移到下一个函数名起始地址
00410495 |. 42 ||INC EDX
00410496 |.^ E2 D0 |\LOOPD SHORT 1.00410468
00410498 |. EB 2C |JMP SHORT 1.004104C6
0041049A |> D1E2 |SHL EDX,1
0041049C |. 8B4D 00 |MOV ECX,DWORD PTR SS:[EBP] ;IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals
0041049F |. 03CB |ADD ECX,EBX ;IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals+IMAGEBASE
004104A1 |. 03CA |ADD ECX,EDX ;得到特定函数 序号地址
004104A3 |. 8B09 |MOV ECX,DWORD PTR DS:[ECX] ;得到函数序号
004104A5 |. 81E1 FFFF0000 |AND ECX,0FFFF
004104AB |. 8B55 0C |MOV EDX,DWORD PTR SS:[EBP+C] ;IMAGE_EXPORT_DIRECTORY.AddressOfFunctions
004104AE |. 03D3 |ADD EDX,EBX ;IMAGE_EXPORT_DIRECTORY.AddressOfFunctions+IAMGEBASE
004104B0 |. C1E1 02 |SHL ECX,2
004104B3 |. 03D1 |ADD EDX,ECX
004104B5 |. 8B12 |MOV EDX,DWORD PTR DS:[EDX]
004104B7 |. 03D3 |ADD EDX,EBX ;得到函数VA
004104B9 |. 8917 |MOV DWORD PTR DS:[EDI],EDX ;存放函数地址
004104BB |. 8B4D 08 |MOV ECX,DWORD PTR SS:[EBP+8]
004104BE |. 03CB |ADD ECX,EBX
004104C0 |. 894D 04 |MOV DWORD PTR SS:[EBP+4],ECX
004104C3 |. 5F |POP EDI
004104C4 |.^ EB 9D \JMP SHORT 1.00410463
//想起failwest的shellcode。。。。。
004104C6 |> \83EF 04 SUB EDI,4
004104C9 |. 8BE7 MOV ESP,EDI
004104CB |. 8B5C24 08 MOV EBX,DWORD PTR SS:[ESP+8]
004104CF |. 8BFC MOV EDI,ESP
004104D1 |. 83EF 04 SUB EDI,4
004104D4 |. 57 PUSH EDI
004104D5 |. 6A 40 PUSH 40 ;PAGE_EXECUTE_READWRITE
004104D7 |. 68 00100000 PUSH 1000
004104DC |. 68 00004000 PUSH 1.00400000
004104E1 |. FFD3 CALL EBX ; VirtualProtect修改PE头属性为可读可写可执行
004104E3 |. BF 00004000 MOV EDI,1.00400000 ;IMAGEBASE
004104E8 |. 037F 3C ADD EDI,DWORD PTR DS:[EDI+3C] ;IMAGE_NT_HEADER
004104EB |. C787 A0000000>MOV DWORD PTR DS:[EDI+A0],12000 ;重定位表IMAGE_DIRECTORY_ENTRY_BASERELOC.VirtualAddress
004104F5 |. C787 A4000000>MOV DWORD PTR DS:[EDI+A4],11E4 ;IMAGE_DIRECTORY_ENTRY_BASERELOC.Size
004104FF |. C787 80000000>MOV DWORD PTR DS:[EDI+80],0 ;IMAGE_DIRECTORY_ENTRY_IMPORT.VirtualAddress清空了导入表偏移
00410509 |. C787 84000000>MOV DWORD PTR DS:[EDI+84],0 ;IMAGE_DIRECTORY_ENTRY_IMPORT.Size
00410513 |. 8BD7 MOV EDX,EDI ;IMAGE_NT_HEADER
00410515 |. 83C2 18 ADD EDX,18 ;IMAGE_OPTIONAL_HEADER32
00410518 |. 33C9 XOR ECX,ECX
0041051A |. 66:8B4F 14 MOV CX,WORD PTR DS:[EDI+14] ;SizeOfOptionalHeader
0041051E |. 03D1 ADD EDX,ECX ;定位到节表IMAGE_SECTION_HEADER
00410520 |. 33C9 XOR ECX,ECX
00410522 |> 8B72 0C /MOV ESI,DWORD PTR DS:[EDX+C] ;IMAGE_SECTION_HEADER.VirtualAddress
00410525 |. 81C6 00004000 |ADD ESI,1.00400000 ;IMAGE_SECTION_HEADER.VirtualAddress+IMAGEBASE
0041052B |. 60 |PUSHAD
0041052C |. 8BFC |MOV EDI,ESP
0041052E |. 83EF 04 |SUB EDI,4
00410531 |. 57 |PUSH EDI
00410532 |. 6A 40 |PUSH 40
00410534 |. FF72 08 |PUSH DWORD PTR DS:[EDX+8] ;IMAGE_SECTION_HEADER.VirtualSize
00410537 |. 56 |PUSH ESI
00410538 |. FFD3 |CALL EBX ;VirtualProtect
0041053A |. 61 |POPAD
0041053B |. 83C2 28 |ADD EDX,28
0041053E |. 41 |INC ECX
0041053F |. 81F9 03000000 |CMP ECX,3
00410545 |.^ 72 DB \JB SHORT 1.00410522 ;将PE文件前3个节属性变为可读可写可执行
00410547 |. 83EA 28 SUB EDX,28 ;定位到第3个节的节表
0041054A |. 8B42 0C MOV EAX,DWORD PTR DS:[EDX+C] ;IMAGE_SECTION_HEADER.VirtualAddress
0041054D |. 0342 10 ADD EAX,DWORD PTR DS:[EDX+10] ;+ IMAGE_SECTION_HEADER.SizeOfRawData
00410550 |. 05 00004000 ADD EAX,1.00400000 ;定位到节空隙
00410555 |. 83C0 64 ADD EAX,64
00410558 |. 60 PUSHAD
00410559 |. 8BF8 MOV EDI,EAX
0041055B |. BE D5034100 MOV ESI,1.004103D5 ;首次解密的起始地址
00410560 |. B9 98064100 MOV ECX,1.00410698 ;首次解密的终止地址
00410565 |. 2BCE SUB ECX,ESI
00410567 |. F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
;将壳代码复制到节表间隙中去 想写插入型病毒的可以参考这里怎样定位的
00410569 |. 61 POPAD
0041056A |. 68 FB658ADC PUSH DC8A65FB
0041056F |. FFE0 JMP EAX ;跳
00413667 . B9 FB658ADC MOV ECX,DC8A65FB ;注意上面入栈的 再看看这里 该壳有多种变形壳 但是都是通过 比较一个DWORD 来确定 运行流程
0041366C . 3B0C24 CMP ECX,DWORD PTR SS:[ESP]
0041366F . 0F84 8B010000 JE 1.00413800 ;跳到壳的第二部分
00413675 . B8 00000000 MOV EAX,0
00413800 > \5E POP ESI
00413801 . 05 98064100 ADD EAX,1.00410698
00413806 . 2D D5034100 SUB EAX,1.004103D5 ;重定位壳代码的 结束地址
0041380B . 8BD8 MOV EBX,EAX
0041380D . 33C0 XOR EAX,EAX
0041380F . B8 03000000 MOV EAX,3
00413814 . 48 DEC EAX
00413815 . 6BC0 28 IMUL EAX,EAX,28
00413818 . 2BD0 SUB EDX,EAX ;定位到第1个节的IMAGE_SECTION_HEADER
0041381A . 33C9 XOR ECX,ECX
0041381C > 8B72 0C MOV ESI,DWORD PTR DS:[EDX+C] ;IMAGE_SECTION_HEADER[0].VirtualAddress
0041381F . 81C6 00004000 ADD ESI,1.00400000 ;+IMAGEBASE
00413825 . 33C0 XOR EAX,EAX
00413827 . 8A06 MOV AL,BYTE PTR DS:[ESI] ;每个节的开始 都有一个结构
00413829 . 03F0 ADD ESI,EAX
0041382B . 60 PUSHAD
0041382C . 8BFB MOV EDI,EBX
0041382E . E8 1F000000 CALL 1.00413852 ;解压CALL跟进去看看
{
00413852 /$ 60 PUSHAD
00413853 |. BB D218CF1F MOV EBX,1FCF18D2
00413858 |. B9 00000000 MOV ECX,0
0041385D |. BA 00000000 MOV EDX,0
00413862 |> 281E /SUB BYTE PTR DS:[ESI],BL
00413864 |. C1EB 08 |SHR EBX,8
00413867 |. 41 |INC ECX
00413868 |. 83F9 04 |CMP ECX,4
0041386B |. 75 0A |JNZ SHORT 1.00413877
0041386D |. BB D218CF1F |MOV EBX,1FCF18D2
00413872 |. B9 00000000 |MOV ECX,0
00413877 |> 46 |INC ESI
00413878 |. 42 |INC EDX
00413879 |. 83FA 08 |CMP EDX,8
0041387C |.^ 7C E4 |JL SHORT 1.00413862
0041387E |. 7F 05 |JG SHORT 1.00413885 ;EDX为8时才 解密
00413880 |. 8B46 FC |MOV EAX,DWORD PTR DS:[ESI-4] ;解密后的[ESI-4]代表 需解压的代码 终止地址
00413883 |. 03C6 |ADD EAX,ESI
00413885 |> 3BF0 |CMP ESI,EAX
00413887 |.^ 7C D9 \JL SHORT 1.00413862
00413889 |. 61 POPAD
//下面是解压过程 代码不贴了
}
每个节的第1个字节 代表需解密的代码在节中偏移,解密后的代码的第2个DWORD值代表需解压的代码的大小
导入表在第3个节中 第3次解压将导入表破坏
00413833 . 8B0E MOV ECX,DWORD PTR DS:[ESI]
00413835 . 8BFE MOV EDI,ESI
00413837 . 2BF8 SUB EDI,EAX
00413839 . 8BF3 MOV ESI,EBX
0041383B . F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI];将解压后的代码复制回原地
0041383D . 61 POPAD
0041383E . 83C2 28 ADD EDX,28
00413841 . 41 INC ECX
00413842 . 81F9 03000000 CMP ECX,3
00413848 .^ 72 D2 JB SHORT 1.0041381C ;循环解压3个节
0041384A . B8 2D704000 MOV EAX,1.0040702D
0041384F . FFD0 CALL EAX ;进入OEP
00413851 . C3 RETN
简便方法:该壳 在最后解压3个节 并破坏原IAT 所以在原IAT 下硬件写入断点 就可停在0041383B 往下再走几步就到
OEP了
修复IAT:整个壳 虽然清0了导入表偏移并破坏了导入表结构 但是该导入表是伪导入表 无论是壳 还是木马本身都跟该导入表中函数无关 dump后 importfix 检测到导入表但是无导入函数 直接运行后错误 所以仔细跟了下 是堆栈引起的 写了个脚本修复了下 运行后 dump 可以直接运行
脚本:
var iataddress
var mem
var xxx
var org_esp
var oep
var yyy
gmi eip, IDATATABLE
mov iataddress, $RESULT
bphws iataddress, "w"
run
bphwcall
findop eip, #ffd0#
bp $RESULT
run
bc eip
sti
msg "到达oep,开始修补堆栈,修补后会改变OEP"
mov oep, eip
alloc 1000
mov mem, $RESULT
mov xxx, mem
mov org_esp, esp
@continue:
add esp, 4
cmp [esp], 0000ffff
jnz @continue
@next:
mov [xxx], #68#,1
inc xxx
mov [xxx], [esp]
sub esp,4
add xxx,4
cmp esp, org_esp
jae @next
mov [xxx], #ff25#, 2
add xxx, 2
mov [xxx], iataddress
add xxx, 4
sub xxx, mem
mov [iataddress], oep
add iataddress, 4
mov eip, iataddress
mov yyy, mem
@orz:
cmp xxx, 0
je @exit
mov [iataddress], [yyy], 1
inc iataddress
inc yyy
dec xxx
jmp @orz
@exit:
msg "修补完成,可以dump"
free mem
ret
overlay处理:直接把原文件的overlay贴到 脱壳后的文件末尾就可以了
注意下:
1:我的虚拟机里XP版本过老 木马运行后 系统崩溃
可能是XP版本问题,换了个新版本的XP 运行正常 但是因为新版本的XP 没有弄测试
环境 所以不能肯定
2:在某个系统下调试 就不要换其它系统,修复堆栈里存放的函数地址 是直接从堆栈中读取的而不是 自己写动态获取过程得到的 所以 肯定不能跨系统版本运行 脚本运行过程中 会有个断点下在数据段的警告 确定就可以了
3:木马有危险,切记虚拟机下调试 稍微看了下 没有新技术 以后有时间再仔细分析 字符串都是加密的 不停的拷贝自身。。
- 标 题:简单小木马脱壳
- 作 者:徐大力
- 时 间:2008-12-27 14:56:49
- 链 接:http://bbs.pediy.com/showthread.php?t=79532