From deb48db7d9e4b6e9c02700b65eabc4438530e47d Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Fri, 19 Apr 2024 16:11:53 +0900 Subject: [PATCH 1/7] Also explore symbols defined in self image (For compiling with the `-Xlinker -interposable` option added.) --- IOSSecuritySuite/FishHookChecker.swift | 37 +++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/IOSSecuritySuite/FishHookChecker.swift b/IOSSecuritySuite/FishHookChecker.swift index e521113..ba414fb 100644 --- a/IOSSecuritySuite/FishHookChecker.swift +++ b/IOSSecuritySuite/FishHookChecker.swift @@ -184,7 +184,7 @@ internal class SymbolFound { let lazyBindSize = Int(dyldInfoCmd.pointee.lazy_bind_size) if (lazyBindSize > 0) { if let lazyBindInfoCmd = UnsafeMutablePointer(bitPattern: UInt(linkeditBase + UInt64(dyldInfoCmd.pointee.lazy_bind_off))), - lookLazyBindSymbol(symbol, symbolAddr: &symbolAddress, lazyBindInfoCmd: lazyBindInfoCmd, lazyBindInfoSize: lazyBindSize, allLoadDylds: allLoadDylds) { + lookLazyBindSymbol(symbol, symbolAddr: &symbolAddress, lazyBindInfoCmd: lazyBindInfoCmd, lazyBindInfoSize: lazyBindSize, imageSlide: slide, allLoadDylds: allLoadDylds) { return true } } @@ -193,7 +193,7 @@ internal class SymbolFound { let bindSize = Int(dyldInfoCmd.pointee.bind_size) if (bindSize > 0) { if let bindCmd = UnsafeMutablePointer(bitPattern: UInt(linkeditBase + UInt64(dyldInfoCmd.pointee.bind_off))), - lookBindSymbol(symbol, symbolAddr: &symbolAddress, bindInfoCmd: bindCmd, bindInfoSize: bindSize, allLoadDylds: allLoadDylds) { + lookBindSymbol(symbol, symbolAddr: &symbolAddress, bindInfoCmd: bindCmd, bindInfoSize: bindSize, imageSlide: slide, allLoadDylds: allLoadDylds) { return true } } @@ -203,7 +203,7 @@ internal class SymbolFound { // LazySymbolBindInfo @inline(__always) - private static func lookLazyBindSymbol(_ symbol: String, symbolAddr: inout UnsafeMutableRawPointer?, lazyBindInfoCmd: UnsafeMutablePointer, lazyBindInfoSize: Int, allLoadDylds: [String]) -> Bool { + private static func lookLazyBindSymbol(_ symbol: String, symbolAddr: inout UnsafeMutableRawPointer?, lazyBindInfoCmd: UnsafeMutablePointer, lazyBindInfoSize: Int, imageSlide slide: Int, allLoadDylds: [String]) -> Bool { var ptr = lazyBindInfoCmd let lazyBindingInfoEnd = lazyBindInfoCmd.advanced(by: Int(lazyBindInfoSize)) var ordinal: Int = -1 @@ -265,7 +265,15 @@ internal class SymbolFound { assert(ordinal <= allLoadDylds.count) if (foundSymbol && ordinal >= 0 && allLoadDylds.count > 0), ordinal <= allLoadDylds.count, type != BindTypeThreadedRebase { - let imageName = allLoadDylds[ordinal-1] + let imageName: String + if ordinal == SELF_LIBRARY_ORDINAL { + guard let selfImageName = Self.imageName(for: slide) else { + fatalError() + } + imageName = selfImageName + } else { + imageName = allLoadDylds[ordinal-1] + } var tmpSymbolAddress: UnsafeMutableRawPointer? if lookExportedSymbol(symbol, exportImageName: imageName, symbolAddress: &tmpSymbolAddress), let symbolPointer = tmpSymbolAddress { symbolAddr = symbolPointer + addend @@ -278,7 +286,7 @@ internal class SymbolFound { // NonLazySymbolBindInfo @inline(__always) - private static func lookBindSymbol(_ symbol: String, symbolAddr: inout UnsafeMutableRawPointer?, bindInfoCmd: UnsafeMutablePointer, bindInfoSize: Int, allLoadDylds: [String]) -> Bool { + private static func lookBindSymbol(_ symbol: String, symbolAddr: inout UnsafeMutableRawPointer?, bindInfoCmd: UnsafeMutablePointer, bindInfoSize: Int, imageSlide slide: Int, allLoadDylds: [String]) -> Bool { var ptr = bindInfoCmd let bindingInfoEnd = bindInfoCmd.advanced(by: Int(bindInfoSize)) var ordinal: Int = -1 @@ -365,7 +373,15 @@ internal class SymbolFound { assert(ordinal <= allLoadDylds.count) if (foundSymbol && ordinal >= 0 && allLoadDylds.count > 0), ordinal <= allLoadDylds.count, type != BindTypeThreadedRebase { - let imageName = allLoadDylds[ordinal-1] + let imageName: String + if ordinal == SELF_LIBRARY_ORDINAL { + guard let selfImageName = Self.imageName(for: slide) else { + fatalError() + } + imageName = selfImageName + } else { + imageName = allLoadDylds[ordinal-1] + } var tmpSymbolAddress: UnsafeMutableRawPointer? if lookExportedSymbol(symbol, exportImageName: imageName, symbolAddress: &tmpSymbolAddress), let symbolPointer = tmpSymbolAddress { symbolAddr = symbolPointer + addend @@ -566,6 +582,15 @@ internal class SymbolFound { } return nil } + + static private func imageName(for slide: Int) -> String? { + for index in 0..<_dyld_image_count() { + if _dyld_get_image_vmaddr_slide(index) == slide { + return String(cString: _dyld_get_image_name(index)) + } + } + return nil + } } // MARK: - FishHook From 204eaeccee9c370d52c4969fcdeed1b52d08f6f0 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Fri, 19 Apr 2024 16:16:41 +0900 Subject: [PATCH 2/7] Name of the exported symbol will always start with "_". --- IOSSecuritySuite/FishHookChecker.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IOSSecuritySuite/FishHookChecker.swift b/IOSSecuritySuite/FishHookChecker.swift index ba414fb..2ae8595 100644 --- a/IOSSecuritySuite/FishHookChecker.swift +++ b/IOSSecuritySuite/FishHookChecker.swift @@ -542,7 +542,7 @@ internal class SymbolFound { terminalSize = readUleb128(ptr: &ptr, end: end) } if terminalSize != 0 { - return currentSymbol == targetSymbol ? ptr : nil + return currentSymbol == "_" + targetSymbol ? ptr : nil } // children @@ -568,7 +568,7 @@ internal class SymbolFound { // node if let nodeSymbol = String(cString: nodeLabel, encoding: .utf8) { let tmpCurrentSymbol = currentSymbol + nodeSymbol - if !targetSymbol.contains(tmpCurrentSymbol) { + if !("_" + targetSymbol).contains(tmpCurrentSymbol) { continue } if nodeOffset != 0 && (start + nodeOffset <= end) { From 12d1dfe109fc782833c3963860e78aa471680d70 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Fri, 19 Apr 2024 16:50:59 +0900 Subject: [PATCH 3/7] Search binding symbols via dyld_chained_fixups --- IOSSecuritySuite/FishHookChecker.swift | 199 ++++++++++++++++++++++--- 1 file changed, 182 insertions(+), 17 deletions(-) diff --git a/IOSSecuritySuite/FishHookChecker.swift b/IOSSecuritySuite/FishHookChecker.swift index 2ae8595..704f49b 100644 --- a/IOSSecuritySuite/FishHookChecker.swift +++ b/IOSSecuritySuite/FishHookChecker.swift @@ -146,6 +146,7 @@ internal class SymbolFound { // target cmd var linkeditCmd: UnsafeMutablePointer! var dyldInfoCmd: UnsafeMutablePointer! + var dyldChainedFixUpsCmd: UnsafeMutablePointer! var allLoadDylds = [String]() guard var curCmdPointer = UnsafeMutableRawPointer(bitPattern: UInt(bitPattern: image)+UInt(MemoryLayout.size)) else { @@ -164,6 +165,8 @@ internal class SymbolFound { } case LC_DYLD_INFO_ONLY, UInt32(LC_DYLD_INFO): dyldInfoCmd = curCmdPointer.assumingMemoryBound(to: dyld_info_command.self) + case LC_DYLD_CHAINED_FIXUPS: + dyldChainedFixUpsCmd = curCmdPointer.assumingMemoryBound(to: linkedit_data_command.self) case UInt32(LC_LOAD_DYLIB), LC_LOAD_WEAK_DYLIB, LC_LOAD_UPWARD_DYLIB, LC_REEXPORT_DYLIB: let loadDyldCmd = curCmdPointer.assumingMemoryBound(to: dylib_command.self) let loadDyldNameOffset = Int(loadDyldCmd.pointee.dylib.name.offset) @@ -177,27 +180,37 @@ internal class SymbolFound { curCmdPointer += Int(curCmd.pointee.cmdsize) } - if linkeditCmd == nil || dyldInfoCmd == nil { return false } + if linkeditCmd == nil || (dyldInfoCmd == nil && dyldChainedFixUpsCmd == nil) { return false } let linkeditBase = UInt64(slide + Int(linkeditCmd.pointee.vmaddr) - Int(linkeditCmd.pointee.fileoff)) - // look by LazyBindInfo - let lazyBindSize = Int(dyldInfoCmd.pointee.lazy_bind_size) - if (lazyBindSize > 0) { - if let lazyBindInfoCmd = UnsafeMutablePointer(bitPattern: UInt(linkeditBase + UInt64(dyldInfoCmd.pointee.lazy_bind_off))), - lookLazyBindSymbol(symbol, symbolAddr: &symbolAddress, lazyBindInfoCmd: lazyBindInfoCmd, lazyBindInfoSize: lazyBindSize, imageSlide: slide, allLoadDylds: allLoadDylds) { - return true - } + let chainedFixUpsSize = Int(dyldChainedFixUpsCmd?.pointee.datasize ?? 0) + if let dyldChainedFixUpsCmd, + chainedFixUpsSize > 0, + let dataStart = UnsafeMutablePointer(bitPattern: UInt(linkeditBase + UInt64(dyldChainedFixUpsCmd.pointee.dataoff))), + lookDyldChainedFixUps(symbol, symbolAddr: &symbolAddress, chainedFixUpsCmd: dataStart, chainedFixUpsSize: chainedFixUpsSize, imageSlide: slide, allLoadDylds: allLoadDylds) { + return true } - - // look by NonLazyBindInfo - let bindSize = Int(dyldInfoCmd.pointee.bind_size) - if (bindSize > 0) { - if let bindCmd = UnsafeMutablePointer(bitPattern: UInt(linkeditBase + UInt64(dyldInfoCmd.pointee.bind_off))), - lookBindSymbol(symbol, symbolAddr: &symbolAddress, bindInfoCmd: bindCmd, bindInfoSize: bindSize, imageSlide: slide, allLoadDylds: allLoadDylds) { - return true + + if let dyldInfoCmd { + // look by LazyBindInfo + let lazyBindSize = Int(dyldInfoCmd.pointee.lazy_bind_size) + if (lazyBindSize > 0) { + if let lazyBindInfoCmd = UnsafeMutablePointer(bitPattern: UInt(linkeditBase + UInt64(dyldInfoCmd.pointee.lazy_bind_off))), + lookLazyBindSymbol(symbol, symbolAddr: &symbolAddress, lazyBindInfoCmd: lazyBindInfoCmd, lazyBindInfoSize: lazyBindSize, imageSlide: slide, allLoadDylds: allLoadDylds) { + return true + } + } + + // look by NonLazyBindInfo + let bindSize = Int(dyldInfoCmd.pointee.bind_size) + if (bindSize > 0) { + if let bindCmd = UnsafeMutablePointer(bitPattern: UInt(linkeditBase + UInt64(dyldInfoCmd.pointee.bind_off))), + lookBindSymbol(symbol, symbolAddr: &symbolAddress, bindInfoCmd: bindCmd, bindInfoSize: bindSize, imageSlide: slide, allLoadDylds: allLoadDylds) { + return true + } } } - + return false } @@ -391,7 +404,69 @@ internal class SymbolFound { return false } - + + // DyldChainedFixUps + @inline(__always) + private static func lookDyldChainedFixUps(_ symbol: String, symbolAddr: inout UnsafeMutableRawPointer?, chainedFixUpsCmd: UnsafeMutablePointer, chainedFixUpsSize: Int, imageSlide slide: Int, allLoadDylds: [String]) -> Bool { + let header = UnsafeRawPointer(chainedFixUpsCmd) + .assumingMemoryBound(to: DyldChainedFixupsHeader.self) + .pointee + let importsOffset: Int = numericCast(header.imports_offset) + let importsCount: Int = numericCast(header.imports_count) + + let importsStart = UnsafeRawPointer(chainedFixUpsCmd).advanced(by: importsOffset) + + let imports: [any DyldChainedImportProtocol] + switch header.importsFormat { + case .general: + imports = UnsafeBufferPointer( + start: importsStart + .assumingMemoryBound(to: DyldChainedImportGeneral.self), + count: importsCount + ).map { $0 } + case .addend: + imports = UnsafeBufferPointer( + start: importsStart + .assumingMemoryBound(to: DyldChainedImportAddend.self), + count: importsCount + ).map { $0 } + case .addend64: + imports = UnsafeBufferPointer( + start: importsStart + .assumingMemoryBound(to: DyldChainedImportAddend64.self), + count: importsCount + ).map { $0 } + } + + for `import` in imports { + let namePtr = UnsafeRawPointer(chainedFixUpsCmd) + .advanced(by: numericCast(header.symbols_offset)) + .advanced(by: `import`.nameOffset) + .assumingMemoryBound(to: CChar.self) + let name = String(cString: namePtr + 1) + print(`import`.libraryOrdinal, name) + if name == symbol { + let ordinal = `import`.libraryOrdinal + assert(ordinal <= allLoadDylds.count) + if (ordinal >= 0 && allLoadDylds.count > 0), ordinal <= allLoadDylds.count { + var s: String? + for index in 0..<_dyld_image_count() { + if _dyld_get_image_vmaddr_slide(index) == slide { + s = String(cString: _dyld_get_image_name(index)) + } + } + let imageName = ordinal == 0 ? s!: allLoadDylds[ordinal-1] + var tmpSymbolAddress: UnsafeMutableRawPointer? + if lookExportedSymbol(symbol, exportImageName: imageName, symbolAddress: &tmpSymbolAddress), let symbolPointer = tmpSymbolAddress { + symbolAddr = symbolPointer + `import`.symbolAddend + return true + } + } + } + } + return false + } + // ExportSymbol @inline(__always) private static func lookExportedSymbol(_ symbol: String, exportImageName: String, symbolAddress: inout UnsafeMutableRawPointer?) -> Bool { @@ -713,5 +788,95 @@ private class FishHook { } } } + +// https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/EXTERNAL_HEADERS/mach-o/fixup-chains.h +struct DyldChainedFixupsHeader { + let fixups_version: UInt32 // 0 + let starts_offset: UInt32 // offset of dyld_chained_starts_in_image in chain_data + let imports_offset: UInt32 // offset of imports table in chain_data + let symbols_offset: UInt32 // offset of symbol strings in chain_data + let imports_count: UInt32 // number of imported symbol names + let imports_format: UInt32 // DYLD_CHAINED_IMPORT* + let symbols_format: UInt32 // 0 => uncompressed, 1 => zlib compressed +} + +extension DyldChainedFixupsHeader { + var importsFormat: DyldChainedImportFormat { + .init(rawValue: imports_format)! + } +} + +public enum DyldChainedImportFormat: UInt32 { + /// DYLD_CHAINED_IMPORT + case general = 1 + /// DYLD_CHAINED_IMPORT_ADDEND + case addend + /// DYLD_CHAINED_IMPORT_ADDEND64 + case addend64 +} + +protocol DyldChainedImportProtocol { + var libraryOrdinal: Int { get } + var isWeakImport: Bool { get } + var nameOffset: Int { get } + var symbolAddend: Int { get } +} + +struct DyldChainedImportGeneral: DyldChainedImportProtocol { + let rawValue: UInt32 + + var libraryOrdinal: Int { + numericCast(rawValue & 0xFF) + } + + var isWeakImport: Bool { + (rawValue & 0x100) != 0 + } + + var nameOffset: Int { + numericCast((rawValue >> 9) & 0x7FFFFF) + } + + var symbolAddend: Int { 0 } +} + +struct DyldChainedImportAddend: DyldChainedImportProtocol { + var addend: Int32 + var rawValue: UInt32 + + var libraryOrdinal: Int { + numericCast(rawValue & 0xFF) + } + + var isWeakImport: Bool { + (rawValue & 0x100) != 0 + } + + var nameOffset: Int { + numericCast((rawValue >> 9) & 0x7FFFFF) + } + + var symbolAddend: Int { numericCast(addend) } +} + +struct DyldChainedImportAddend64: DyldChainedImportProtocol { + var addend: UInt64 + var rawValue: UInt64 + + var libraryOrdinal: Int { + numericCast(rawValue & 0xFFFF) + } + + var isWeakImport: Bool { + (rawValue & 0x10000) != 0 + } + + var nameOffset: Int { + numericCast((rawValue >> 17) & 0xFFFFFFFF) + } + + var symbolAddend: Int { numericCast(addend) } +} + #endif // swiftlint:enable all From 7191de55687374924e08b58475bc7db9ba2ba1e1 Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Fri, 19 Apr 2024 16:52:22 +0900 Subject: [PATCH 4/7] Fix to replace symbol pointer in `__DATA_CONST` segment correctly --- IOSSecuritySuite/FishHookChecker.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IOSSecuritySuite/FishHookChecker.swift b/IOSSecuritySuite/FishHookChecker.swift index 704f49b..49d6499 100644 --- a/IOSSecuritySuite/FishHookChecker.swift +++ b/IOSSecuritySuite/FishHookChecker.swift @@ -734,7 +734,7 @@ private class FishHook { for segment in [dataCmd, dataConstCmd] { guard let segment else { continue } for tmp in 0...size + MemoryLayout.size*Int(tmp)).assumingMemoryBound(to: section_64.self) + let curSection = UnsafeMutableRawPointer(segment).advanced(by: MemoryLayout.size + MemoryLayout.size*Int(tmp)).assumingMemoryBound(to: section_64.self) // symbol_pointers sections if curSection.pointee.flags == S_LAZY_SYMBOL_POINTERS { From 9c65ebcf4b8c31fe729d0c4dfcc27852c8e8355a Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Fri, 19 Apr 2024 16:54:36 +0900 Subject: [PATCH 5/7] Fix condition for checking if indirect symbol is local or absolute --- IOSSecuritySuite/FishHookChecker.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IOSSecuritySuite/FishHookChecker.swift b/IOSSecuritySuite/FishHookChecker.swift index 49d6499..108ed41 100644 --- a/IOSSecuritySuite/FishHookChecker.swift +++ b/IOSSecuritySuite/FishHookChecker.swift @@ -765,7 +765,7 @@ private class FishHook { for tmp in 0...size { let curIndirectSym = indirectSymVmAddr.advanced(by: tmp) - if curIndirectSym.pointee == INDIRECT_SYMBOL_ABS || curIndirectSym.pointee == INDIRECT_SYMBOL_LOCAL { + if curIndirectSym.pointee & UInt32(INDIRECT_SYMBOL_ABS) != 0 || curIndirectSym.pointee & ~UInt32(INDIRECT_SYMBOL_ABS) == INDIRECT_SYMBOL_LOCAL { continue } let curStrTabOff = symtab.advanced(by: Int(curIndirectSym.pointee)).pointee.n_un.n_strx From b9e02b85847c973123cd612724c5a5fa0059ccef Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Fri, 19 Apr 2024 17:03:32 +0900 Subject: [PATCH 6/7] remove unnecessary print --- IOSSecuritySuite/FishHookChecker.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/IOSSecuritySuite/FishHookChecker.swift b/IOSSecuritySuite/FishHookChecker.swift index 108ed41..5f36ea0 100644 --- a/IOSSecuritySuite/FishHookChecker.swift +++ b/IOSSecuritySuite/FishHookChecker.swift @@ -444,7 +444,6 @@ internal class SymbolFound { .advanced(by: `import`.nameOffset) .assumingMemoryBound(to: CChar.self) let name = String(cString: namePtr + 1) - print(`import`.libraryOrdinal, name) if name == symbol { let ordinal = `import`.libraryOrdinal assert(ordinal <= allLoadDylds.count) From 22b0f3e22a8eaa6eafbedcf303c3c673f8af382e Mon Sep 17 00:00:00 2001 From: p-x9 <50244599+p-x9@users.noreply.github.com> Date: Fri, 19 Apr 2024 17:17:06 +0900 Subject: [PATCH 7/7] Fix FishHook in the app as well. --- FrameworkClientApp/FishHook.swift | 45 +++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/FrameworkClientApp/FishHook.swift b/FrameworkClientApp/FishHook.swift index 1e8439d..6d2dffd 100644 --- a/FrameworkClientApp/FishHook.swift +++ b/FrameworkClientApp/FishHook.swift @@ -44,6 +44,7 @@ private func replaceSymbolAtImage( ) { var linkeditCmd: UnsafeMutablePointer! var dataCmd: UnsafeMutablePointer! + var dataConstCmd: UnsafeMutablePointer! var symtabCmd: UnsafeMutablePointer! var dynamicSymtabCmd: UnsafeMutablePointer! @@ -56,10 +57,14 @@ private func replaceSymbolAtImage( let curCmdNameOffset = MemoryLayout.size(ofValue: curCmd.pointee.cmd) + MemoryLayout.size(ofValue: curCmd.pointee.cmdsize) let curCmdNamePointer = curCmdPointer.advanced(by: curCmdNameOffset).assumingMemoryBound(to: Int8.self) let curCmdName = String(cString: curCmdNamePointer) - if (curCmdName == SEG_LINKEDIT) { + switch curCmdName { + case SEG_LINKEDIT: linkeditCmd = curCmd - } else if (curCmdName == SEG_DATA) { + case SEG_DATA: dataCmd = curCmd + case "__DATA_CONST": + dataConstCmd = curCmd + default: break } } else if curCmd.pointee.cmd == LC_SYMTAB { symtabCmd = UnsafeMutablePointer(OpaquePointer(curCmd)) @@ -70,7 +75,7 @@ private func replaceSymbolAtImage( curCmdPointer += Int(curCmd.pointee.cmdsize) } - if linkeditCmd == nil || symtabCmd == nil || dynamicSymtabCmd == nil || dataCmd == nil { + if linkeditCmd == nil || symtabCmd == nil || dynamicSymtabCmd == nil || (dataCmd == nil && dataConstCmd == nil) { return } @@ -83,15 +88,18 @@ private func replaceSymbolAtImage( return } - for tmp in 0...size + MemoryLayout.size*Int(tmp)).assumingMemoryBound(to: section_64.self) - - // symbol_pointers sections - if curSection.pointee.flags == S_LAZY_SYMBOL_POINTERS { - replaceSymbolPointerAtSection(curSection, symtab: symtab!, strtab: strtab!, indirectsym: indirectsym!, slide: slide, symbolName: symbol, newMethod: newMethod, oldMethod: &oldMethod) - } - if curSection.pointee.flags == S_NON_LAZY_SYMBOL_POINTERS { - replaceSymbolPointerAtSection(curSection, symtab: symtab!, strtab: strtab!, indirectsym: indirectsym!, slide: slide, symbolName: symbol, newMethod: newMethod, oldMethod: &oldMethod) + for segment in [dataCmd, dataConstCmd] { + guard let segment else { continue } + for tmp in 0...size + MemoryLayout.size*Int(tmp)).assumingMemoryBound(to: section_64.self) + + // symbol_pointers sections + if curSection.pointee.flags == S_LAZY_SYMBOL_POINTERS { + replaceSymbolPointerAtSection(curSection, symtab: symtab!, strtab: strtab!, indirectsym: indirectsym!, slide: slide, symbolName: symbol, newMethod: newMethod, oldMethod: &oldMethod) + } + if curSection.pointee.flags == S_NON_LAZY_SYMBOL_POINTERS { + replaceSymbolPointerAtSection(curSection, symtab: symtab!, strtab: strtab!, indirectsym: indirectsym!, slide: slide, symbolName: symbol, newMethod: newMethod, oldMethod: &oldMethod) + } } } } @@ -116,14 +124,23 @@ private func replaceSymbolPointerAtSection( for tmp in 0...size { let curIndirectSym = indirectSymVmAddr.advanced(by: tmp) - if curIndirectSym.pointee == INDIRECT_SYMBOL_ABS || curIndirectSym.pointee == INDIRECT_SYMBOL_LOCAL { + if curIndirectSym.pointee & UInt32(INDIRECT_SYMBOL_ABS) != 0 || curIndirectSym.pointee & ~UInt32(INDIRECT_SYMBOL_ABS) == INDIRECT_SYMBOL_LOCAL { continue } let curStrTabOff = symtab.advanced(by: Int(curIndirectSym.pointee)).pointee.n_un.n_strx let curSymbolName = strtab.advanced(by: Int(curStrTabOff+1)) if String(cString: curSymbolName) == symbolName { oldMethod = sectionVmAddr!.advanced(by: tmp).pointee - sectionVmAddr!.advanced(by: tmp).initialize(to: newMethod) + let err = vm_protect( + mach_task_self_, + .init(bitPattern: sectionVmAddr), + numericCast(section.pointee.size), + 0, + VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY + ) + if err == KERN_SUCCESS { + sectionVmAddr!.advanced(by: tmp).initialize(to: newMethod) + } break } }