一个小木马脱壳  请虚拟机下调试 相关文件见附件 未知壳相当简单 但是典型 有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:木马有危险,切记虚拟机下调试 稍微看了下 没有新技术 以后有时间再仔细分析 字符串都是加密的 不停的拷贝自身。。

上传的附件 分析.rar [请到论坛下载:http://bbs.pediy.com/showthread.php?t=79532 ]