Giter VIP home page Giter VIP logo

libpe's Introduction

libpe's People

Contributors

chkhalt avatar claudiobizzotto avatar davidpolverari avatar felipensp avatar fgarcia0x0 avatar fredericopissarra avatar g5pw avatar gogootaku avatar jweyrich avatar jwilk avatar khorben avatar merces avatar saullocarvalho avatar sgn avatar xxami avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libpe's Issues

Exploitable bug on pe_exports function from exports.c

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!

Fix memory leaks in hashes.c

Valgrind shows memory leaks at 5 places in file:

==1369== 17 bytes in 1 blocks are definitely lost in loss record 1 of 27
==1369==    at 0x4C2DBCD: malloc (vg_replace_malloc.c:299)
==1369==    by 0x586E799: strdup (strdup.c:42)
==1369==    by 0x4E503AB: get_hashes (in /usr/local/lib/libpe.so.1.0)
==1369==    by 0x4E505D2: get_headers_dos_hash (in /usr/local/lib/libpe.so.1.0)
==1369==    by 0x4E5078F: get_headers_hash (in /usr/local/lib/libpe.so.1.0)
==1369==    by 0x109106: main (in /home/boddu/github/boddumanohar/exe-check)
==1369==
==1369== 18 bytes in 1 blocks are definitely lost in loss record 2 of 27
==1369==    at 0x4C2DBCD: malloc (vg_replace_malloc.c:299)
==1369==    by 0x586E799: strdup (strdup.c:42)
==1369==    by 0x4E503AB: get_hashes (in /usr/local/lib/libpe.so.1.0)
==1369==    by 0x4E50646: get_headers_coff_hash (in /usr/local/lib/libpe.so.1.0)
==1369==    by 0x4E508BC: get_headers_hash (in /usr/local/lib/libpe.so.1.0)
==1369==    by 0x109106: main (in /home/boddu/github/boddumanohar/exe-check)
==1369==
==1369== 25 bytes in 1 blocks are definitely lost in loss record 3 of 27
==1369==    at 0x4C2DBCD: malloc (vg_replace_malloc.c:299)
==1369==    by 0x586E799: strdup (strdup.c:42)
==1369==    by 0x4E503AB: get_hashes (in /usr/local/lib/libpe.so.1.0)
==1369==    by 0x4E506E0: get_headers_optional_hash (in /usr/local/lib/libpe.so.1.0)
==1369==    by 0x4E5082D: get_headers_hash (in /usr/local/lib/libpe.so.1.0)
==1369==    by 0x109106: main (in /home/boddu/github/boddumanohar/exe-check)
==1369==
==1369== 51 bytes in 8 blocks are definitely lost in loss record 5 of 27
==1369==    at 0x4C2DBCD: malloc (vg_replace_malloc.c:299)
==1369==    by 0x586E799: strdup (strdup.c:42)
==1369==    by 0x4E503AB: get_hashes (in /usr/local/lib/libpe.so.1.0)
==1369==    by 0x4E50B17: get_sections_hash (in /usr/local/lib/libpe.so.1.0)
==1369==    by 0x1092BB: main (in /home/boddu/github/boddumanohar/exe-check)

==1369== 129,173 (24 direct, 129,149 indirect) bytes in 1 blocks are definitely lost in loss record 27 of 27
==1369==    at 0x4C2DBCD: malloc (vg_replace_malloc.c:299)
==1369==    by 0x4E511DA: imphash_load_imported_functions (in /usr/local/lib/libpe.so.1.0)
==1369==    by 0x4E517E7: pe_imphash (in /usr/local/lib/libpe.so.1.0)
==1369==    by 0x109E64: main (in /home/boddu/github/boddumanohar/exe-check)
==1369==

The first 4 errror are due to crypto library we are using.
EVP_cleanup(); which we used before exiting calc_hash will only clean the used memory partially.

And the last one is because, we are not freeing the linked list (where head variable is the head of the linked list). Each node is added after each call to imphash_load_imported_functions function.

A small question

Hello guys,

I didn't understand the reason for this 'if'. I think it will match with PE files having only one section in which the field VirtualAddress is greater than rva. In this case, is it rva pointing to some header? Wouldn't be better return the difference between rva and imagebase?

Cheers!

Add pesec.c to libpe

I the pull #14 I did not move code of pesec.c

What I am assuming is that we going to move everything to libpe and make PEV use libpe as a dependency completely. If I am correct, we should move pesec.c code to libpe ( I will make of list of things that are yet to be moved) so that we can release the next version which completely uses libpe. This will make the code of PEV a lot cleaner.

Release

Hi,

I am trying to package pev for Alpine Linux but the tarball is missing libpe.

Would it be possible to make a tagged release matching the latest release of pev?

Handling of Exports slightly off

From the comments:
// We want to use NumberOfFunctions for looping as it's the total number of functions/symbols
// exported by the module. On the other hand, NumberOfNames is the number of
// functions/symbols exported by name only.

exports->functions_count = exp->NumberOfFunctions;
const size_t functions_size = exp->NumberOfFunctions * sizeof(pe_exported_function_t);
exports->functions = malloc(functions_size);
if (exports->functions == NULL) {
	exports->err = LIBPE_E_ALLOCATION_FAILURE;
	return exports;
}
memset(exports->functions, 0, functions_size);

for (uint32_t i=0; i < exp->NumberOfFunctions; i++) {

This is slightly wrong. NumberOfNames can differ from NumberOfFunctions, either smaller or larger. You really have three things to deal with:
NumberOfFunctions - All Symbols exported
NumberOfNames - All names that match up to symbols
Function exported by ordinal only

For this last one, you need to take all functions, and subtract out the ones that got names. The ones that are left are the ones exported by ordinal only.

Also, the 'ordinal' is actually a 'hint', which is the actual offset into the first array, meaning it is zero based. Any usage of ordinals is purely on the input side, meaning, if a user calls get pointer and uses an ordinal, the ordinal base is subtracted to give you the 0-index. The named things don't actually do this calculation, they just use the offset directly (counter to MS documentation).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.