CVE-2010-3333 RTF Shellcode Carver (Step 1)

There seems to be a lot of requests for an executable carver for CVE-2010-3333 (RTF exploit). Generically speaking, carving out an executable from a malicious document is a three step process. The first step is to extract the shellcode, second is to reverse the shellcode and lastly create a decoder. For an example of a decode see the following post. Below we can see the header, exploit and the start of the shellcode.
0000000: 7b5c 7274 6631 7b5c 7368 707b 5c73 707b  {\rtf1{\shp{\sp{
0000010: 5c73 6e20 7046 7261 676d 656e 7473 7d7b  \sn pFragments}{
0000020: 5c73 7620 393b 323b 3131 3131 3131 3131  \sv 9;2;11111111
0000030: 6163 6338 3131 3131 3131 3131 3131 3131  acc8111111111111
0000040: 3131 3131 3131 3131 3131 3131 3131 3131  1111111111111111
0000050: 3131 3131 3131 3131 3131 3131 3131 3131  1111111111111111
0000060: 3131 3131 3131 3131 3131 3131 3131 3131  1111111111111111
0000070: 3131 3131 3131 3131 3131 3131 3131 3131  1111111111111111
0000080: 3131 3131 3131 3131 3131 3131 3930 3930  1111111111119090
0000090: 3930 3930 3930 3930 3930 3930 3930 3930  9090909090909090
00000a0: 3930 3930 3930 3930 3930 3930 3930 3930  9090909090909090
00000b0: 3930 3930 3930 3930 3930 3930 3930 3930  9090909090909090
00000c0: 3930 3930 3930 3930 3930 3930 3930 3930  9090909090909090
00000d0: 3930 3930 3930 3930 3930 3930 3930 3930  9090909090909090
         ....
Extracting the shellcode from this particular exploit is a little tedious. The shellcode sits in the document as ASCII. The ASCII will need to be read two chars at a time and then converted to hex. Example: the ASCII string '90' needs to be 0x90, which is the opcode for NOP. The huge '90' is our NOP slide. Once this conversion has been done we can analyze the shellcode with a disassembler. Rather than manually carving out the binary of the shellcode the following script can be used. rtf-carv.py
import sys
from StringIO import StringIO

def parse_rtf(f):
    d = f.read()
    # \rtf & \shp 
    if d.find('\x7b\x5c\x72') != -1 and d.find('\x5c\x73\x68\x70') != -1  and d.find('\x5c\x73\x70') != -1:
        addr = d.find('\x5c\x73\x76') 
        if addr != -1:
            f.seek(addr)
            flag = 0
            while(1):
                try:
                    byte = f.read(1)
                except:
                    # breaks if end of file is found
                    return None
                if byte == ';':
                    flag = flag + 1
                if flag == 2:
                    return f.tell()
        return None 
    else:
        return None

def extract_sc(f, addr):
    f.seek(addr)
    b = f.read(2)
    buff = ''
    while(1):
        try:
            buff = buff + chr(int(b,16))
        except ValueError:
            return buff
        b = f.read(2)
      
def main():
        if len(sys.argv) < 2:
            print 'usage: rtf-carv.py <bad.rtf>' 
            print 'output: binary shellcode in sc.bin'
            return
        else:
            try:
                f = open(sys.argv[1], 'rb')
            except Exception:
                print '[ERROR] CAN NOT OPEN FILE'
                return
            a = parse_rtf(f)
            if a == None:
                print 'RTF Signature not found'
                return 
            sc = extract_sc(f,a)
            try: 
                out = open('sc.bin', 'wb+')
            except Exception:
                print '[Error] COULD NOT WRITE SHELLCODE'
            print '\t[SUCESS] Shellcode written to out.sc'
            out.write(sc)
            out.close()
            
if __name__ == '__main__':
   main()
C:\Documents and Settings\XOR\cve-2010-3333>rtf-carv.py "CVE-2010-3333_2010-12-16_HealthTips_ATT27390.doc="
        [SUCESS] Shellcode written to sc.bin
Hexdump of the sc.bin
0000000: 1111 1111 acc8 1111 1111 1111 1111 1111  ................
0000010: 1111 1111 1111 1111 1111 1111 1111 1111  ................
0000020: 1111 1111 1111 1111 1111 1111 1111 1111  ................
0000030: 1111 9090 9090 9090 9090 9090 9090 9090  ................
0000040: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000050: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000060: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000070: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000080: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000090: 9090 9090 9090 9090 9090 9090 9090 9090  ................
Disassembly:
....
0000c47d (01) 90                       NOP
0000c47e (01) 90                       NOP
0000c47f (01) 90                       NOP
0000c480 (01) 90                       NOP
0000c481 (01) 90                       NOP
0000c482 (01) 41                       INC ECX
0000c483 (01) 41                       INC ECX
0000c484 (01) 41                       INC ECX
0000c485 (01) 41                       INC ECX
0000c486 (01) 41                       INC ECX
0000c487 (01) 41                       INC ECX
0000c488 (01) 41                       INC ECX
0000c489 (01) 41                       INC ECX
0000c48a (01) 41                       INC ECX
0000c48b (01) 41                       INC ECX
0000c48c (01) 41                       INC ECX
0000c48d (01) 41                       INC ECX
0000c48e (05) e801000000               CALL 0xc494
From here the shellcode will need to be reversed to find the encoding loop. Hope this helps with one step in the carving process.

No comments:

Post a Comment