Skip to content

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

Open
@jinyu00

Description

@jinyu00

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions