-
-
Notifications
You must be signed in to change notification settings - Fork 363
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
[WIP] Implement PE & MDMP base relocations. DO NOT MERGE YET! #4711
base: dev
Are you sure you want to change the base?
Conversation
* Add missing `PE_IMAGE_FILE_MACHINE` types * Add PE base relocation types Everything is based off of Microsoft's PE format documentation [found here](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format)
Some things I wasn't sure about:
|
@@ -554,30 +638,16 @@ err: | |||
} | |||
|
|||
static int has_canary(RzBinFile *bf) { | |||
// XXX: We only need imports here but this causes leaks, we need to wait for the below. This is a horrible solution! | |||
// TODO: use O(1) when imports sdbized |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this comment too
For now, I think some code duplication is fine. Sharing the code between two plugins is non-trivial at this point. |
64455b5
to
7cac944
Compare
@@ -0,0 +1,74 @@ | |||
// SPDX-FileCopyrightText: 2024 Roee Toledano <roeetoledano10@gmail.com> | |||
// SPDX-License-Identifier: LGPL-3.0-only | |||
#include "pe.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please leave 1 empty line between SPDX headers and first #include
@@ -0,0 +1,4 @@ | |||
// SPDX-FileCopyrightText: 2024 Roee Toledano <roeetoledano10@gmail.com> | |||
// SPDX-License-Identifier: LGPL-3.0-only | |||
#define RZ_BIN_PE64 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be tested via distro-
branch before merge. @XVilka
librz/bin/format/pe/pe_relocs.c
Outdated
rz_buf_read(b, ent_buf, sizeof(ent_buf)); | ||
reloc = rz_read_ble16(ent_buf, big_endian); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use the rz_buf_read_ble16_offset
which is a special api which updates automatically the offset/address parameter and returns true on successful read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also be sure to check the boolean return value to fail gracefully.
librz/bin/format/pe/pe_relocs.c
Outdated
rz_buf_read(b, block_buf, sizeof(block_buf)); | ||
RzBinPeRelocBlock block; | ||
PE_READ_STRUCT_FIELD_L(block_buf, block, RzBinPeRelocBlock, page_rva, 32); | ||
PE_READ_STRUCT_FIELD_L(block_buf, block, RzBinPeRelocBlock, block_size, 32); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can do the same here using rz_buf_read_bleXX_offset
and checking the return value.
you can do this in a static function like this and fail when returns false.
librz/bin/format/pe/pe_relocs.c
Outdated
|
||
do { | ||
bytes_read += 2; | ||
RzBinPeRelocEnt reloc; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
always init this to 0.
RzBinPeRelocEnt reloc; | |
RzBinPeRelocEnt reloc = 0; |
librz/bin/format/pe/pe_relocs.c
Outdated
do { | ||
ut8 block_buf[sizeof(RzBinPeRelocBlock)]; | ||
rz_buf_read(b, block_buf, sizeof(block_buf)); | ||
RzBinPeRelocBlock block; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RzBinPeRelocBlock block; | |
RzBinPeRelocBlock block = { 0 }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please always initialize the variables to 0
or NULL
so we can avoid random crashes and weird unintentional behavior.
* Remove old code of setting import entries to PE relocations * Parse PE base relocations * Implement converting from the specific RzBinPeRelocEnt type to the general RzBinReloc type * Implement corrent type naming of PE relocations
* Removed a.exe and b.exe tests, as they don't contain base relocations and swapped them with good tests * Corrected the olds tests 1. Need to add MDMP 2. Need to implement PE relocs patching to get the other tests to work
librz/bin/format/pe/pe.h
Outdated
// encoding is 12 bits for type and 4 bits for offset. | ||
// See: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#the-reloc-section-image-only | ||
#define PE_RELOC_ENT_TYPE(val) ((val) >> 12) | ||
#define PE_RELOC_ENT_OFFSET(val) ((val)&0b111111111111) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm not sure how 0b111111111111
is portable. use hex (0xfff
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, totally forgot about that. I'll fix it
* Fix error caused when there are no relocations. Solved by adding a function checking whether relocation vector is empty or not
* Added freeing relocation vector and fixed correct setting of bin->relocs in case there has been an error
Sorry for the ugly commit history. I could rebase interactive + squash with the old ones so it's easier to review. |
All tests are green except flagspace tests. Because there is no symbol associated with base relocations, they have no name associated with them, so I'm not sure how we can use flags here |
rz_vector_foreach (bin->relocs, pe_reloc) { | ||
RzBinReloc *general_reloc = RZ_NEW0(RzBinReloc); | ||
if (!general_reloc) { | ||
RZ_LOG_WARN("Failed to convert PE reloc to general reloc\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RZ_LOG_WARN("Failed to convert PE reloc to general reloc\n"); | |
RZ_LOG_ERROR("Failed to allocate PE RzBinReloc\n"); |
if (!general_reloc) { | ||
RZ_LOG_WARN("Failed to convert PE reloc to general reloc\n"); | ||
rz_bin_reloc_free(general_reloc); | ||
continue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if alloc fails, then there is no memory left.
You should probably do the following instead of calling continue
:
rz_vector_free(bin->relocs);
return ret;
Your checklist for this pull request
Detailed description
Up until now PE relocations were implemented as imports, which is incorrect. The PE format uses base relocations for image files (ie executable files) and classic COFF relocations for object files.
Implemented so far:
Still need to implement:
relocation patching- Rizin always loads the binary in it's expected base address, so no patching is needed (I added a detailed comment about this inrelocs
function inbin_pe.inc
)make MDMP use the new base relocationMDMP doesn't have relocations, only imports.add COFF relocations for object filestechnically PE can have COFF relocations since it's based off of COFF, but COFF relocations are only used for for object files, and there is no reason to use PE for object files, so it's never actually used.Notes:
type
andoffset
to apply the relocation in....
Test plan
All tests green, except the MDMP & and the ones dependent of relocation patching.
...
Closing issues
...