djcsdy / swfmill

Generate or decompile Adobe Flash SWF files using an XML dialect. Inspect and modify the XML by hand, or by using a built in XSLT processor.
http://www.swfmill.org/
GNU General Public License v2.0
131 stars 28 forks source link

Integer overflow in SWF::Reader::getWord and the repair plan in the last of the report #51

Open jinyu00 opened 6 years ago

jinyu00 commented 6 years ago

When open a crafted swf file , it could tigger Integer overflow

Let's see gdb output


Program received signal SIGSEGV, Segmentation fault.
0x000000000047aa6c in SWF::Reader::getWord (this=this@entry=0xd94970) at SWFReader.cpp:46
46          int r = data[pos++];
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────
*RAX  0x82208
*RBX  0xd94990 —▸ 0x919c10 —▸ 0x8612e0 (SWF::Header::~Header()) ◂— lea    rsp, [rsp - 0x98]
*RCX  0xb8dd12f2
*RDX  0xb8dd12f1
*RDI  0xd94970 —▸ 0x7ffff7f46010 ◂— 0x2b0000002c010088
*RSI  0xffffffffb8dd12f0
*R8   0x7ffff7f46010 ◂— 0x2b0000002c010088
*R9   0x3e
 R10  0x0
*R11  0x246
*R12  0x82208
*R13  0xda9760 —▸ 0x91b2e0 —▸ 0x8731f0 (SWF::DoAction::~DoAction()) ◂— lea    rsp, [rsp - 0x98]
*R14  0xd94970 —▸ 0x7ffff7f46010 ◂— 0x2b0000002c010088
*R15  0x7fffffffe300 ◂— 0x100000000000009 /* '\t' */
*RBP  0xd94970 —▸ 0x7ffff7f46010 ◂— 0x2b0000002c010088
*RSP  0x7fffffffe218 —▸ 0x48c791 ◂— movzx  ebp, ax
*RIP  0x47aa6c (SWF::Reader::getWord()+140) ◂— movzx  r9d, byte ptr [r8 + rsi]
──────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────
 ► 0x47aa6c <SWF::Reader::getWord()+140>    movzx  r9d, byte ptr [r8 + rsi]
   0x47aa71 <SWF::Reader::getWord()+145>    mov    dword ptr [rdi + 8], ecx
   0x47aa74 <SWF::Reader::getWord()+148>    movsxd rdi, edx
   0x47aa77 <SWF::Reader::getWord()+151>    movzx  eax, byte ptr [r8 + rdi]
   0x47aa7c <SWF::Reader::getWord()+156>    shl    eax, 8
   0x47aa7f <SWF::Reader::getWord()+159>    add    eax, r9d
   0x47aa82 <SWF::Reader::getWord()+162>    ret    

   0x47aa83 <SWF::Reader::getWord()+163>    nop    dword ptr [rax + rax]
   0x47aa88 <SWF::Reader::getWord()+168>    add    eax, 1
   0x47aa8b <SWF::Reader::getWord()+171>    mov    dword ptr [rdi + 0x14], 2
   0x47aa92 <SWF::Reader::getWord()+178>    mov    dword ptr [rdi + 8], eax
───────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]───────────────────────────────────────
   41       if (pos+2 > length) {
   42           err = Reader::eof;
   43           pos = length+1;
   44           return 0;
   45       }
 ► 46       int r = data[pos++];
   47       r += data[pos++]<<8;
   48       return r;
   49   }
   50 
   51   uint32_t Reader::getInt() {
───────────────────────────────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────
00:0000│ rsp  0x7fffffffe218 —▸ 0x48c791 ◂— movzx  ebp, ax
01:0008│      0x7fffffffe220 —▸ 0xd94990 —▸ 0x919c10 —▸ 0x8612e0 (SWF::Header::~Header()) ◂— lea    rsp, [rsp - 0x98]
... ↓
03:0018│      0x7fffffffe230 —▸ 0xd94970 —▸ 0x7ffff7f46010 ◂— 0x2b0000002c010088
04:0020│      0x7fffffffe238 ◂— 0x82208
05:0028│      0x7fffffffe240 —▸ 0xda9760 —▸ 0x91b2e0 —▸ 0x8731f0 (SWF::DoAction::~DoAction()) ◂— lea    rsp, [rsp - 0x98]
06:0030│      0x7fffffffe248 —▸ 0x7fffffffe300 ◂— 0x100000000000009 /* '\t' */
07:0038│      0x7fffffffe250 —▸ 0xd94990 —▸ 0x919c10 —▸ 0x8612e0 (SWF::Header::~Header()) ◂— lea    rsp, [rsp - 0x98]
─────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────
 ► f 0           47aa6c SWF::Reader::getWord()+140
   f 1           48c791
   f 2           56641e
   f 3           487518
   f 4           4a7337
   f 5     7ffff6296830 __libc_start_main+240
Program received signal SIGSEGV (fault address 0x7fffb0d17300)
pwndbg> vmmap 0x7ffff7f46010
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
    0x7ffff7f46000     0x7ffff7fd5000 rw-p    8f000 0      
pwndbg> p dataa
No symbol "dataa" in current context.
pwndbg> p data
$1 = (const unsigned char *) 0x7ffff7f46010 "\210"
pwndbg> p pos
$2 = -1193471247
pwndbg> pwd
/home/haclh/vmdk/fuzz_workplace/swfmill-0.3.6/src
pwndbg> bt
#0  0x000000000047aa6c in SWF::Reader::getWord (this=this@entry=0xd94970) at SWFReader.cpp:46
#1  0x000000000048c791 in SWF::Tag::get (r=r@entry=0xd94970, end=end@entry=533000, ctx=ctx@entry=0x7fffffffe300) at SWFTag.cpp:8
#2  0x000000000056641e in SWF::Header::parse (this=this@entry=0xd94990, r=r@entry=0xd94970, end=533000, ctx=ctx@entry=0x7fffffffe300) at gSWFPa
#3  0x0000000000487518 in SWF::File::load (this=this@entry=0x7fffffffe2f0, fp=fp@entry=0xd91b30, _ctx=_ctx@entry=0x7fffffffe300, filesize=files
#4  0x00000000004a7337 in swfmill_swf2xml (argc=<optimized out>, argv=<optimized out>) at swfmill.cpp:135
#5  0x00007ffff6296830 in __libc_start_main (main=0x408890 <main(int, char**)>, argc=3, argv=0x7fffffffe4e8, init=<optimized out>, fini=<optimix7fffffffe4d8) at ../csu/libc-start.c:291
#6  0x0000000000409509 in _start ()

As you can see , The program crash in SWF::Reader::getWord ( SWFReader.cpp )

    uint16_t Reader::getWord() {
        if (pos+2 > length) {
            err = Reader::eof;
            pos = length+1;
            return 0;
        }
        int r = data[pos++];
        r += data[pos++]<<8;  // crash at here !!!!
        return r;
    }

From the gdb debug infomation , the pos is negative number

pwndbg> p pos
$2 = -1193471247

so when access data[pos] ( data + pos ), it could access invalid memory.

The vulnerability locate in SWFReader.cpp and SWFReader.h .

    class Reader {
        protected:
            int pos, length;
    };

The pos and length is signed int value.

And when read data from file , it could call Reader::getXXX .

For example , Reader::getData 's code are as below:

bool Reader::getData(void *dst, size_t len) {
    if (pos+len > length) {
        err = Reader::eof;
        pos = length+1;
        return false;
    } else {
        memcpy(dst, &data[pos], len);
        pos += len;
        return true;
    }
}

When read data from file , the pos would add , although pos+len > length.

It can lead pos to be negative number

The fix method is to change the type of pos and length to unsigned int in SWFReader.h

protected:
    // the uncompressed swf data and our position within
    const unsigned char *data;
    unsigned int pos, length;

The poc file

https://gitee.com/hac425/fuzz_data/blob/master/swf_seg_poc_12
djcsdy commented 6 years ago

Thanks!