Skip to content

Commit

Permalink
Fix MachO::Binary::shift_command (#1131)
Browse files Browse the repository at this point in the history
* Fix MachO::Binary::shift_command virtual_address

Function argument `from_offset` is a file offset that we need to adjust
before adding to VA of segment.

Co-authored-by: Richard Dzenis <rdzenis@whitecryption.com>

* Fix symbols shift in MachO::Binary::shift_command

Fix adjustments of symbols: their values should be compared
to VA instead of file offset.

Co-authored-by: Richard Dzenis <rdzenis@whitecryption.com>

* Add test for shift of symbols in MachO

* Cleanup tests/macho/test_symbols.py

---------

Co-authored-by: Uldis Kalnins <ukalnins@whitecryption.com>
Co-authored-by: Romain Thomas <me@romainthomas.fr>
  • Loading branch information
3 people committed Dec 12, 2024
1 parent 2239937 commit e557086
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 4 deletions.
7 changes: 3 additions & 4 deletions src/MachO/Binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ void Binary::shift_command(size_t width, uint64_t from_offset) {
uint64_t virtual_address = 0;

if (segment != nullptr) {
virtual_address = segment->virtual_address() + from_offset;
virtual_address = segment->virtual_address() + from_offset - segment->file_offset();
}

if (const SegmentCommand* text = get_segment("__TEXT")) {
Expand All @@ -640,9 +640,8 @@ void Binary::shift_command(size_t width, uint64_t from_offset) {

for (std::unique_ptr<Symbol>& s : symbols_) {
if (s->type() == Symbol::TYPE::SECTION) {
uint64_t value = s->value();
if (value > from_offset) {
s->value(value + width);
if (s->value() > virtual_address) {
s->value(s->value() + width);
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions tests/macho/test_symbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,21 @@ def test_demangling():

assert macho.symbols[1].demangled_name == "void __cxxabiv1::(anonymous namespace)::demangle<__cxxabiv1::(anonymous namespace)::Db>(char const*, char const*, __cxxabiv1::(anonymous namespace)::Db&, int&)"
assert macho.symbols[486].demangled_name == "___cxa_deleted_virtual"

def test_symbol_shift():
bin_path = pathlib.Path(get_sample("MachO/MachO64_x86-64_binary_sym2remove.bin"))
macho = lief.MachO.parse(bin_path.as_posix()).at(0)

shift = 0x4000
loadcommands_end = macho.imagebase + 32 + macho.header.sizeof_cmds # sizeof(mach_header_64) + size of load command table
def get_shifted_symbol(sym):
value = sym.value
if value > loadcommands_end:
value += shift
return (sym.name, value)

check_symbols = {get_shifted_symbol(sym) for sym in macho.symbols if sym.raw_type & 0x0E == lief.MachO.Symbol.TYPE.SECTION}
macho.shift(shift)
shifted_symbols = {(sym.name, sym.value) for sym in macho.symbols if sym.raw_type & 0x0E == lief.MachO.Symbol.TYPE.SECTION}

assert shifted_symbols == check_symbols

0 comments on commit e557086

Please sign in to comment.