Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEX: read_uleb128_bounded(), fix buffer-overflow #1949

Merged
merged 1 commit into from
Aug 16, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 47 additions & 10 deletions libyara/modules/dex/dex.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,39 +369,56 @@ end_declarations

// https://android.googlesource.com/platform/dalvik/+/android-4.4.2_r2/libdex/Leb128.cpp

static int32_t read_uleb128(const uint8_t* pStream, uint32_t* size)
static int32_t read_uleb128_bounded(
const uint8_t* pStream,
const uint8_t* pStreamEnd,
uint32_t* size,
bool* error)
{
const uint8_t* ptr = pStream;
int32_t result = 0;

*error = false;
if (ptr == pStreamEnd)
goto error;

int32_t result = *(ptr++);
result = *(ptr++);
*size = *size + 1;

if (result > 0x7f)
{
if (ptr == pStreamEnd)
goto error;
int cur = *(ptr++);
*size = *size + 1;
result = (result & 0x7f) | ((cur & 0x7f) << 7);

if (cur > 0x7f)
{
if (ptr == pStreamEnd)
goto error;
cur = *(ptr++);
*size = *size + 1;
result |= (cur & 0x7f) << 14;

if (cur > 0x7f)
{
if (ptr == pStreamEnd)
goto error;
cur = *(ptr++);
*size = *size + 1;
result |= (cur & 0x7f) << 21;

if (cur > 0x7f)
{
if (ptr == pStreamEnd)
goto error;
/*
* Note: We don't check to see if cur is out of
* range here, meaning we tolerate garbage in the
* high four-order bits.
*/
cur = *(ptr++);
cur = *ptr;
*size = *size + 1;
result |= cur << 28;
}
Expand All @@ -410,6 +427,17 @@ static int32_t read_uleb128(const uint8_t* pStream, uint32_t* size)
}

return result;

error:
*error = true;
return result;
}


static int32_t read_uleb128(const uint8_t* pStream, uint32_t* size)
{
bool error;
return read_uleb128_bounded(pStream, (const uint8_t*) SIZE_MAX, size, &error);
}


Expand Down Expand Up @@ -700,20 +728,29 @@ uint32_t load_encoded_method(
printf("[DEX] Parse encoded method start_offset:0x%zx\n", start_offset);
#endif

if (!fits_in_dex(dex, dex->data + start_offset, sizeof(uint32_t) * 3))
const uint8_t* data_cur_start = dex->data + start_offset;
if (!fits_in_dex(dex, data_cur_start, sizeof(uint32_t) * 3))
return 0;

const uint8_t* data_end = dex->data + dex->data_size;
uint32_t current_size = 0;
bool error = false;
encoded_method_t encoded_method;

encoded_method.method_idx_diff = (uint32_t) read_uleb128(
(dex->data + start_offset + current_size), &current_size);
encoded_method.method_idx_diff = (uint32_t) read_uleb128_bounded(
(data_cur_start + current_size), data_end, &current_size, &error);
if (error)
return 0;

encoded_method.access_flags = (uint32_t) read_uleb128(
(dex->data + start_offset + current_size), &current_size);
encoded_method.access_flags = (uint32_t) read_uleb128_bounded(
(data_cur_start + current_size), data_end, &current_size, &error);
if (error)
return 0;

encoded_method.code_off = (uint32_t) read_uleb128(
(dex->data + start_offset + current_size), &current_size);
encoded_method.code_off = (uint32_t) read_uleb128_bounded(
(data_cur_start + current_size), data_end, &current_size, &error);
if (error)
return 0;

yr_set_integer(
encoded_method.method_idx_diff,
Expand Down