如何把shellcode转换成exe文件分析

华盟原创文章投稿奖励计划

前言

在分析shellcode时,静态分析或者使用scdbg模拟分析都不够准确,如果转换成exe文件那么就可以用debugger或者IDA分析,会方便很多。

样本分析

这里以CVE-2013-3346
的样本为例,使用peepdf分析样本:

$ python peepdf.py -i -f ~/Downloads/sample.pdf                                                                                                                                                

File: sample.pdf

MD5: 6776bda19a3a8ed4c2870c34279dbaa9

SHA1: ad6a3564e125683a791ee98c5d1e66e1d9c6877d

Size: 177511 bytes

Version: 1.1

Binary: False

Linearized: False

Encrypted: False

Updates: 0

Objects: 4

Streams: 2

Comments: 0

Errors: 1

Version 0:

Catalog: 1

Info: No

Objects (4): [1, 2, 3, 10]

Errors (1): [3]

Streams (2): [10, 3]

Encoded (0): []

Objects with JS code (1): [3]

Suspicious elements:

/AcroForm: [1]

/OpenAction: [1]

/XFA: [1]

/JS: [2]

/JavaScript: [2]

其中Objects with JS code (1): [3]可知对象3是一段js代码:

PPDF> object 3

<< >>

stream

if(app.media.getPlayers().length >= 1) Q=~[];Q={___:++Q,$$$$:(![]+"")[Q],__$:++Q,$_$_:(![]+"")[Q],_$_:++Q,$_$$:({}+"")[Q],$$_$:(Q[Q]+"")[Q],_$$:++Q,$$$_:(!""+"")[Q],$__:++Q,$_$:++Q,$$__:({}+"")[Q],$$_:++Q,$$$:++Q,$___:++Q,$__$:++Q};Q.$_=(Q.$_=Q+"")[Q.$_$]+(Q._$=Q.$_[Q.__$])+(Q.$$=(Q.$+"")[Q.__$])+((!Q)+"")[Q._$$]+(Q.__=Q.$_[Q.$$_])+(Q.$=(!""+"")[Q.__$])+(Q._=(!""+"")[Q._$_])+Q.$_[Q.$_$]+Q.__+Q._$+Q.$;Q.$$=Q.$+(!""+"")[Q._$$]+Q.__+Q._+Q.$+Q.$$;Q.$=(Q.___)[Q.$_][Q.$_];Q.$(Q.$(Q.$$+"\""+"\\"+Q.__$+Q.$$_+Q.$$_+Q.$_$_+"\\"+Q.__$+Q.$$_+Q._$_+"\\"+Q.$__+Q.___+"\\"+Q.__$+Q.$$_+Q._$$+"\\"+Q.__$+Q.$_$+Q.___+Q.$$$_+(![]+"")[Q._$_]+(![]+"")[Q._$_]+Q.$$__+Q._$+Q.$$_$+Q.$$$_+"\\"+Q.$__+Q.___+"=\\"+Q.$__+Q.___+Q._+"\\"+Q.__$+Q.$_$+Q.$$_+Q.$$$_+"\\"+Q.__$+Q.$$_+Q._$$+Q.$$__+Q.$_$_+"\\"+Q.__$+Q.$$_+Q.___+Q.$$$_+"(\\\"%"+Q._+Q.___+Q.

...

这里要把从Q=~[]开始的加密代码拷贝到文件中。

这里的代码是用jjencode加密过的,使用peepdf自带的解密工具可以还原出js代码:

PPDF> js_jjdecode file /Users/seviezhou/Downloads/sample.js $> jsdecode

PPDF> js_analyse variable jsdecode $> shellcode

PPDF> show jsdecode

var shellcode = unescape("%u\00E8%u\0000%u\5D00%u\ED83%u\E905%u\008B%u\0000%u\5052%u\D231%u\C031%u\F980%u\7501%u\6604%u\EBAD%u\AC01%u\003C%u\0D74%u\613C%u\0272%u\202C%u\CAC1%u\010D%u\EBC2%u\39E3%u...

var executable = "";

var rop9 = "";

rop9 += unescape("%u\313d%u\4a82");

rop9 += unescape("%u\a713%u\4a82");

rop9 += unescape("%u\1f90%u\4a80");

...

...

PPDF> show shellcode

e8 00 00 00 00 5d 83 ed 05 e9 8b 00 00 00 52 50   |.....]........RP|

31 d2 31 c0 80 f9 01 75 04 66 ad eb 01 ac 3c 00   |1.1....u.f....<.|

74 0d 3c 61 72 02 2c 20 c1 ca 0d 01 c2 eb e3 39   |t.<ar., .......9|

da 58 5a c3 56 89 da b2 3c 31 c0 66 8b 02 01 d8   |.XZ.V...<1.f....|

8b 50 78 01 da 52 51 8b 4a 18 8b 42 20 01 d8 8b   |.Px..RQ.J..B ...|

38 01 df 53 8b 1e 87 f7 51 31 c9 e8 ae ff ff ff   |8..S....Q1......|

59 5b 87 f7 75 02 eb 08 83 c0 04 49 e3 22 eb df   |Y[..u......I."..|

8b 42 18 29 c8 89 c1 8b 42 24 01 d8 66 8b 0c 48   |.B.)....B$..f..H|

8b 42 1c 01 d8 c1 e1 02 01 c8 8b 00 01 d8 89 06   |.B..............|

59 5a 83 c6 04 e2 ae 5e c3 31 d2 64 8b 52 30 8b   |YZ.....^.1.d.R0.|

...

js代码主要是shellcode的布置和堆喷射还有rop的构造,这里的shellcode利用CVE-2013-5065绕过了沙箱。将shellcode提取出来使用scdbg分析得到如下结果:

...

401215  SetFilePointer(hFile=1a4, dist=0, 0, FILE_BEGIN) = 0

401221  GetFileSize(1a4, 0) = ffffffff

401215  SetFilePointer(hFile=1a8, dist=0, 0, FILE_BEGIN) = 0

401221  GetFileSize(1a8, 0) = ffffffff

401215  SetFilePointer(hFile=1ac, dist=0, 0, FILE_BEGIN) = 0

401221  GetFileSize(1ac, 0) = ffffffff

401215  SetFilePointer(hFile=1b0, dist=0, 0, FILE_BEGIN) = 0

401221  GetFileSize(1b0, 0) = ffffffff

401215  SetFilePointer(hFile=1b4, dist=0, 0, FILE_BEGIN) = 0

401221  GetFileSize(1b4, 0) = ffffffff

401221   83F8FF                          cmp eax,0xffffffff              step: 1647274  foffset: 221

eax=ffffffff  ecx=0         edx=12fdbc    ebx=1b4

esp=12fdb0    ebp=2000      esi=12fdc8    edi=12fdb4     EFL 44 P Z

dbg> Disassemble address (default eip): (hex/reg) 0x401221

401221

Number of instructions to dump (max 100): (int/reg) 100

100

401221   83F8FF                          cmp eax,0xffffffff

401224   74E3                            jz 0x401209   ^^

401226   3D00100000                      cmp eax,0x1000

40122b   7CDC                            jl 0x401209   ^^

40122d   89C5                            mov ebp,eax

40122f   89E0                            mov eax,esp

401231   31C9                            xor ecx,ecx

401233   51                              push ecx

401234   50                              push eax

401235   6A04                            push byte 0x4

401237   57                              push edi

401238   53                              push ebx

401239   FF5630                          call [esi+0x30]

40123c   813F25504446                    cmp dword [edi],0x46445025

401242   75C5                            jnz 0x401209   ^^

401244   83C408                          add esp,0x8

...

dbg> Set eip (VA or file offset) : (hex/reg) 0x401244

401244

401244   83C408                          add esp,0x8

dbg>

40125a  VirtualAlloc(base=0 , sz=1ffc) = 731000

401265  ReadFile(hFile=1b4, buf=731000, numBytes=1ffc) = 0

4012b0  GetTempPathA(len=c8, buf=12fcfc) = 25

4012be  GetTempFileNameA(path=C:\Users\SEVIEZ~1\AppData\Local\Temp\, prefix=12fcf8, unique=0, buf=12f

cfc) = 429E

         Path = C:\Users\SEVIEZ~1\AppData\Local\Temp\429E.tmp

4012e0  CreateFileA(C:\Users\SEVIEZ~1\AppData\Local\Temp\429E.tmp) = 8

SafeMalloc Failed/refused to allocate 0x0 bytes exiting...

一开始分析就会陷入一个死循环,然后尝试改变eip得到了一些api的调用。

转换shellcode为exe

还是看不出什么,这里我们把shellcode转换成exe文件来分析,首先我尝试了shellcode2exe.py,可转换结果并不是一个合法的exe文件,这里讲一个通用的方法,这里要用到yasm.exegolink.exe下载地址:

yasm-1.3.0-win64.exe

yasm-1.3.0-win32.exe

golink

下载对应位数的yasmgolink,分别重命名为yasm.exegolink.exe

然后用winhex等十六进制编辑器把shellcode保存为shellcode.bin:

$ hexdump shellcode.bin

0000000 e8 00 00 00 00 5d 83 ed 05 e9 8b 00 00 00 52 50

0000010 31 d2 31 c0 80 f9 01 75 04 66 ad eb 01 ac 3c 00

0000020 74 0d 3c 61 72 02 2c 20 c1 ca 0d 01 c2 eb e3 39

0000030 da 58 5a c3 56 89 da b2 3c 31 c0 66 8b 02 01 d8

0000040 8b 50 78 01 da 52 51 8b 4a 18 8b 42 20 01 d8 8b

...

然后新建一个文件shellcode.asm,内容如下:

$ cat shellcode.asm

Global Start

SECTION 'foo' write, execute,read

Start:

incbin "shellcode.bin"

最后把yasm.exegolink.exeshellcode.asmshellcode.bin放在同一个目录下,以32位系统为例,依次执行如下命令:

yasm.exe -f win32 -o shellcode.obj shellcode.asm

golink /ni /entry Start shellcode.obj

最后可以得到shellcode.exe:

C:\Users\seviezhou\Desktop>yasm.exe -f win32 -o shellcode.obj shellcode.asm

C:\Users\seviezhou\Desktop>golink /ni /entry Start shellcode.obj

C:\Users\seviezhou\Desktop>dir shellcode.exe

 驱动器 C 中的卷没有标签。

 卷的序列号是 0A63-F3E0

 C:\Users\seviezhou\Desktop 的目录

2017/11/02  20:18             2,048 shellcode.exe

               1 个文件          2,048 字节

               0 个目录 49,720,483,840 可用字节

然后就可以放到debugger中调试:

00401000 > $ E8 00000000    CALL shellcod.00401005                   ; \shellcod.00401005

00401005   $ 5D             POP EBP

00401006   . 83ED 05        SUB EBP,5

00401009   . E9 8B000000    JMP shellcod.00401099

0040100E  /$ 52             PUSH EDX

0040100F  |. 50             PUSH EAX

00401010  |. 31D2           XOR EDX,EDX

00401012  |> 31C0           /XOR EAX,EAX

可以看到入口点确实是shellcode的起始位置,单步跟随后可以在栈上找到程序使用的api:

0012FF54   7685214F  kernel32.ExitProcess

0012FF58   76852FB6  kernel32.VirtualAlloc

0012FF5C   7684A629  kernel32.DeviceIoControl

0012FF60   7684CEE8  RETURN to kernel32.CreateFileA

0012FF64   7684CAC4  kernel32.GetCurrentProcessId

0012FF68   7685395C  kernel32.LoadLibraryA

0012FF6C   7688E5FD  kernel32.WinExec

0012FF70   76851400  kernel32.WriteFile

0012FF74   7684CA7C  kernel32.CloseHandle

0012FF78   76866A65  kernel32.GetTempPathA

0012FF7C   7686695F  kernel32.GetTempFileNameA

0012FF80   76840273  kernel32.GetFileSize

0012FF84   768496FB  kernel32.ReadFile

0012FF88   7684DB36  kernel32.SetFilePointer

然后就可以分析shellcode了,当然也可以放到IDA中分析。

也可以把上述两条命令写成shellcode2exe.bat文件:

@echo off

@if "%1"=="" goto help

@echo Global Start > shellcode.asm

@echo SECTION 'foo' write, execute,read >> shellcode.asm

@echo Start:       >> shellcode.asm

@echo incbin "%2"  >> shellcode.asm

@yasm.exe -f win%1 -o shellcode.obj shellcode.asm

@golink /ni /entry Start shellcode.obj

@dir shellcode.exe

@goto exit

@:help

@echo Converts shellcode to exe

@echo Required Arguments:

@echo arg1 - architecture: 32 or 64 

@echo arg2 - shellcode file name

@echo current dir is %cd%

@:exit

echo.

运行结果:

C:\Users\seviezhou\Desktop>shellcode2exe.bat

Converts shellcode to exe

Required Arguments:

arg1 - architecture: 32 or 64

arg2 - shellcode file name

current dir is C:\Users\seviezhou\Desktop

C:\Users\seviezhou\Desktop>shellcode2exe.bat 32 shellcode.bin

 驱动器 C 中的卷没有标签。

 卷的序列号是 0A63-F3E0

 C:\Users\seviezhou\Desktop 的目录

2017/11/02  20:26             2,048 shellcode.exe

               1 个文件          2,048 字节

               0 个目录 49,720,455,168 可用字节

成功得到exe文件。

总结

当分析shellcode时,可以结合多种方法分析,静态或者动态,才能更好的分析代码的行为,这时能够转换成可执行文件分析就是很好的方法。

本文原创,作者:AlexFrankly,其版权均为华盟网所有。如需转载,请注明出处:https://www.77169.net/html/184465.html

发表评论