Skip to content
This repository has been archived by the owner on Apr 20, 2023. It is now read-only.

Exploitable bug on pe_exports function from exports.c #35

Closed
saullocarvalho opened this issue May 30, 2021 · 0 comments · Fixed by #36
Closed

Exploitable bug on pe_exports function from exports.c #35

saullocarvalho opened this issue May 30, 2021 · 0 comments · Fixed by #36

Comments

@saullocarvalho
Copy link
Contributor

saullocarvalho commented May 30, 2021

Hello guys.

I have found a bug on pe_exports function from exports.c which allows me to exploit readpe.exe program from pev 0.81 (last release).

The issue occurs on the following lines:

libpe/exports.c

Lines 104 to 132 in 07f90de

uint64_t offsets_to_Names[exp->NumberOfFunctions];
memset(offsets_to_Names, 0, sizeof(offsets_to_Names)); // This is needed for VLAs.
//
// Names
//
for (uint32_t i=0; i < exp->NumberOfNames; i++) {
uint64_t entry_ordinal_list_ptr = offset_to_AddressOfNameOrdinals + sizeof(uint16_t) * i;
uint16_t *entry_ordinal_list = LIBPE_PTR_ADD(ctx->map_addr, entry_ordinal_list_ptr);
if (!pe_can_read(ctx, entry_ordinal_list, sizeof(uint16_t))) {
// TODO: Should we report something?
break;
}
const uint16_t ordinal = *entry_ordinal_list;
uint64_t entry_name_list_ptr = offset_to_AddressOfNames + sizeof(uint32_t) * i;
uint32_t *entry_name_list = LIBPE_PTR_ADD(ctx->map_addr, entry_name_list_ptr);
if (!pe_can_read(ctx, entry_name_list, sizeof(uint32_t))) {
// TODO: Should we report something?
break;
}
const uint32_t entry_name_rva = *entry_name_list;
const uint64_t entry_name_ofs = pe_rva2ofs(ctx, entry_name_rva);
offsets_to_Names[ordinal] = entry_name_ofs;
}

The array offsets_to_Names is dynamically allocated on the stack using exp->NumberOfFunctions as its size (line 104). However, the loop starting at line 111 uses exp->NumberOfNames to iterate over it and set values at line 132. Therefore, this snippet assumes that exp->NumberOfFunctions is greater than ordinal at each iteration.

That condition may be followed by compilers, but not by hackers. What happens if I craft a PE file with ordinal greater than or equal to exp->NumberOfFunctions? Depending on the values, I am able to overwrite the return address of pe_exports function. On Windows 7 and Windows Server 2008 (systems on which I could produce higher impact), I may even use a ROP chain to get an arbitrary code execution.

I have recorded a PoC video to proof the exploitability of the bug on readpe.exe: https://drive.google.com/file/d/1zBH9ykgmHlnWQEBDIxwrYG8CTrHtUf26/view?usp=sharing.

If you guys need any more details about the bug, I am at your disposal!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants