Headline
CVE-2021-45423: Exploitable bug on pe_exports function from exports.c · Issue #35 · merces/libpe
A Buffer Overflow vulnerabilityexists in Pev 0.81 via the pe_exports function from exports.c… The array offsets_to_Names is dynamically allocated on the stack using exp->NumberOfFunctions as its size. However, the loop uses exp->NumberOfNames to iterate over it and set its components value. Therefore, the loop code assumes that exp->NumberOfFunctions is greater than ordinal at each iteration. This can lead to arbitrary code execution.
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:
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!