From c5df1bf9d788344192b1a63690d8d5845b713f29 Mon Sep 17 00:00:00 2001 From: kat Date: Tue, 4 Jun 2024 10:59:44 -0400 Subject: [Mach-O] Fix issue where imported symbols did not have relocations applied, Fix an issue with binding opcode 0xC0 --- view/macho/machoview.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++------ view/macho/machoview.h | 4 +++- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/view/macho/machoview.cpp b/view/macho/machoview.cpp index c01acadd..69b81df6 100644 --- a/view/macho/machoview.cpp +++ b/view/macho/machoview.cpp @@ -1992,6 +1992,12 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_ EndBulkModifySymbols(); + for (auto& [relocation, name] : header.externalRelocations) + { + if (auto symbol = GetSymbolByRawName(name, GetExternalNameSpace()); symbol) + DefineRelocation(m_arch, relocation, symbol, relocation.address); + } + auto relocationHandler = m_arch->GetRelocationHandler("Mach-O"); if (relocationHandler) { @@ -2465,6 +2471,7 @@ void MachoView::ParseDynamicTable(BinaryReader& reader, MachOHeader& header, BNS try { reader.Seek(tableOffset); auto table = reader.Read(tableSize); + BNRelocationInfo externReloc; BNSymbolType symtype = incomingType; // uint64_t ordinal = 0; @@ -2525,6 +2532,15 @@ void MachoView::ParseDynamicTable(BinaryReader& reader, MachOHeader& header, BNS throw MachoFormatException(); DefineMachoSymbol(symtype, string(name), address, binding, true); + + memset(&externReloc, 0, sizeof(externReloc)); + externReloc.nativeType = BINARYNINJA_MANUAL_RELOCATION; + externReloc.address = address; + externReloc.size = m_addressSize; + externReloc.pcRelative = false; + externReloc.external = true; + header.externalRelocations.emplace_back(externReloc, string(name)); + address += m_addressSize; break; case BindOpcodeDoBindAddAddressULEB: @@ -2532,6 +2548,15 @@ void MachoView::ParseDynamicTable(BinaryReader& reader, MachOHeader& header, BNS throw MachoFormatException(); DefineMachoSymbol(symtype, string(name), address, binding, true); + + memset(&externReloc, 0, sizeof(externReloc)); + externReloc.nativeType = BINARYNINJA_MANUAL_RELOCATION; + externReloc.address = address; + externReloc.size = m_addressSize; + externReloc.pcRelative = false; + externReloc.external = true; + header.externalRelocations.emplace_back(externReloc, string(name)); + address += m_addressSize; address += readLEB128(table, tableSize, i); break; @@ -2540,6 +2565,14 @@ void MachoView::ParseDynamicTable(BinaryReader& reader, MachOHeader& header, BNS throw MachoFormatException(); DefineMachoSymbol(symtype, string(name), address, binding, true); + + memset(&externReloc, 0, sizeof(externReloc)); + externReloc.nativeType = BINARYNINJA_MANUAL_RELOCATION; + externReloc.address = address; + externReloc.size = m_addressSize; + externReloc.pcRelative = false; + externReloc.external = true; + header.externalRelocations.emplace_back(externReloc, string(name)); address += m_addressSize; address += (imm * m_addressSize); break; @@ -2552,8 +2585,17 @@ void MachoView::ParseDynamicTable(BinaryReader& reader, MachOHeader& header, BNS uint64_t skip = readLEB128(table, tableSize, i); for (; count > 0; count--) { - address += skip + m_addressSize; DefineMachoSymbol(symtype, string(name), address, binding, true); + + memset(&externReloc, 0, sizeof(externReloc)); + externReloc.nativeType = BINARYNINJA_MANUAL_RELOCATION; + externReloc.address = address; + externReloc.size = m_addressSize; + externReloc.pcRelative = false; + externReloc.external = true; + header.externalRelocations.emplace_back(externReloc, string(name)); + + address += skip + m_addressSize; } break; } @@ -2595,7 +2637,7 @@ void MachoView::ParseSymbolTable(BinaryReader& reader, MachOHeader& header, cons if (header.chainedFixupsPresent) { m_logger->LogDebug("Chained Fixups"); - ParseChainedFixups(header.chainedFixups); + ParseChainedFixups(header, header.chainedFixups); } if (header.exportTriePresent && header.isMainHeader) ParseExportTrie(reader, header.exportTrie); @@ -2793,9 +2835,7 @@ void MachoView::ParseSymbolTable(BinaryReader& reader, MachOHeader& header, cons } - - -void MachoView::ParseChainedFixups(linkedit_data_command chainedFixups) +void MachoView::ParseChainedFixups(MachOHeader& header, linkedit_data_command chainedFixups) { if (!chainedFixups.dataoff) return; @@ -3103,10 +3143,18 @@ void MachoView::ParseChainedFixups(linkedit_data_command chainedFixups) if (!entry.name.empty()) { reloc.address = targetAddress; - DefineRelocation(m_arch, reloc, 0, reloc.address); - DefineMachoSymbol(ImportedDataSymbol, entry.name, + DefineMachoSymbol(ImportAddressSymbol, entry.name, targetAddress, entry.weak ? WeakBinding : GlobalBinding, true); + + BNRelocationInfo externReloc; + memset(&externReloc, 0, sizeof(externReloc)); + externReloc.nativeType = BINARYNINJA_MANUAL_RELOCATION; + externReloc.address = targetAddress; + externReloc.size = m_addressSize; + externReloc.pcRelative = false; + externReloc.external = true; + header.externalRelocations.emplace_back(externReloc, entry.name); } else { diff --git a/view/macho/machoview.h b/view/macho/machoview.h index 8dd5328d..240dcc54 100644 --- a/view/macho/machoview.h +++ b/view/macho/machoview.h @@ -1238,6 +1238,8 @@ namespace BinaryNinja std::vector> entryPoints; std::vector m_entryPoints; //list of entrypoints + std::vector> externalRelocations; + symtab_command symtab; dysymtab_command dysymtab; dyld_info_command dyldInfo; @@ -1345,7 +1347,7 @@ namespace BinaryNinja BNSymbolBinding binding); bool GetSectionPermissions(MachOHeader& header, uint64_t address, uint32_t &flags); bool GetSegmentPermissions(MachOHeader& header, uint64_t address, uint32_t &flags); - void ParseChainedFixups(linkedit_data_command chainedFixups); + void ParseChainedFixups(MachOHeader& header, linkedit_data_command chainedFixups); virtual uint64_t PerformGetEntryPoint() const override; -- cgit v1.3.1