From 1b7da037bbc74b6a883b9d3c2844ff98dc996b01 Mon Sep 17 00:00:00 2001 From: nganhkhoa Date: Tue, 6 Jun 2023 13:15:31 +0700 Subject: [PATCH] remove all strings when remove imports --- .../internal/wrapper/action/remove_imports.go | 2 + macho-go/pkg/ios/macho/edit.go | 112 ++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/macho-go/internal/wrapper/action/remove_imports.go b/macho-go/internal/wrapper/action/remove_imports.go index dc50d13..d40beac 100644 --- a/macho-go/internal/wrapper/action/remove_imports.go +++ b/macho-go/internal/wrapper/action/remove_imports.go @@ -8,6 +8,8 @@ type removeImports struct{} func (action *removeImports) withMacho(mf *MachoFile) error { mf.Context().RemoveBindSymbols() + mf.Context().RemoveSymbolTable() + mf.Context().RemoveExportTrie() return nil } diff --git a/macho-go/pkg/ios/macho/edit.go b/macho-go/pkg/ios/macho/edit.go index 7022e14..3666296 100644 --- a/macho-go/pkg/ios/macho/edit.go +++ b/macho-go/pkg/ios/macho/edit.go @@ -320,6 +320,32 @@ func (mc *MachoContext) RemoveBindSymbols() { } func (mc *MachoContext) removeBindSymbolsModern() { + // we don't mess up the chain + // we clear the imports table, and the raw opcodes + // clearing imports table disables static analysis + // clearing opcodes forces runtime manual mapping + + // imports item are defined by mc.fixups.imports_format + // basic case is dyld_chained_import, 4 bytes + + start := mc.fixups.dataoff + size := mc.fixups.datasize + fixups := new(Fixups) + fixups.Deserialize(mc, mc.buf[start:start+size]) + + start = mc.fixups.dataoff + fixups.imports_offset + size = fixups.imports_count * 4 + fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size) + mc.file.WriteAt(make([]byte, size), int64(start)) + + // string reference are at the end of this section + start = mc.fixups.dataoff + fixups.symbols_offset + size = mc.fixups.Datasize() - fixups.symbols_offset + fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size) + mc.file.WriteAt(make([]byte, size), int64(start)) + + fixups.imports_count = 0 + mc.file.WriteAt(fixups.Serialize(mc), int64(mc.fixups.dataoff)) } func (mc *MachoContext) removeBindSymbolsLegacy() { @@ -329,3 +355,89 @@ func (mc *MachoContext) removeBindSymbolsLegacy() { // but no symbol state to bind mc.file.WriteAt(make([]byte, size), int64(start)) } + +func (mc *MachoContext) RemoveSymbolTable() { + // try to remove symtab and dysymtab + mc.removeSymtabCommand() + mc.removeDySymtabCommand() +} + +func (mc *MachoContext) removeSymtabCommand() { + ptr := int64(0) + if mc.Is64bit() { + ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart) + } else { + ptr, _ = mc.file.Seek(int64(Header_size), io.SeekStart) + } + + var symtab_fix *Symtab + for _, cmd := range mc.commands { + if cmd.Cmd() != LC_SYMTAB { + ptr += int64(cmd.Cmdsize()) + continue + } + var symtab = cmd.(*Symtab) + symtab_fix = symtab + + // erase strings referenced + start := int64(symtab_fix.stroff) + size := symtab_fix.strsize + fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size) + mc.file.WriteAt(make([]byte, size), start) + + // erase nlist64 symbol items + start = int64(symtab_fix.symoff) + size = symtab_fix.nsyms * 16 + fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size) + mc.file.WriteAt(make([]byte, size), start) + + symtab_fix.symoff = 0 + symtab_fix.nsyms = 0 + symtab_fix.stroff = 0 + symtab_fix.strsize = 0 + mc.file.Seek(ptr, io.SeekStart) + mc.file.Write(symtab_fix.Serialize(mc)) + break + } + mc.file.Seek(0, io.SeekStart) +} + +func (mc *MachoContext) removeDySymtabCommand() { + ptr := int64(0) + if mc.Is64bit() { + ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart) + } else { + ptr, _ = mc.file.Seek(int64(Header_size), io.SeekStart) + } + for _, cmd := range mc.commands { + if cmd.Cmd() != LC_DYSYMTAB { + ptr += int64(cmd.Cmdsize()) + continue + } + var dysymtab = cmd.(*DySymtab) + dysymtab_fix := dysymtab + dysymtab_fix.indirectsymoff = 0 + dysymtab_fix.nindirectsyms = 0 + mc.file.Seek(ptr, io.SeekStart) + mc.file.Write(dysymtab_fix.Serialize(mc)) + } +} + +func (mc *MachoContext) RemoveExportTrie() { + var start int64 + var size int + if mc.dyldinfo != nil { + // legacy export trie + start = int64(mc.dyldinfo.export_off) + size = int(mc.dyldinfo.export_size) + mc.file.WriteAt(make([]byte, size), start) + } else if mc.exports != nil { + // modern export trie + start = int64(mc.exports.dataoff) + size = int(mc.exports.datasize) + mc.file.WriteAt(make([]byte, size), start) + } else { + // no export trie (??) + // should never occur unless this binary is modified + } +}