### macOS Manual Setup for Tweaks Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Steps to manually set up ElleKit on macOS, including disabling SIP, copying dylibs, and enabling DYLD injection. This process requires administrator privileges. ```bash # 1. Disable SIP and enable arm64e preview ABI sudo nvram boot-args=-arm64e_preview_abi # reboot # 2. Copy tweaks into ~/.tweaks/ mkdir -p ~/.tweaks cp MyTweak.dylib ~/.tweaks/ # 3. Install runtime libraries sudo cp libinjector.dylib /usr/local/lib/ sudo cp libsubstrate.dylib /usr/local/lib/ # 4. Enable DYLD injection launchctl setenv DYLD_INSERT_LIBRARIES "/usr/local/lib/libinjector.dylib" # 5. (Optional) Reload Dock to inject immediately killall Dock ``` -------------------------------- ### `hook(_:_:)` without orig — Fire-and-Forget Hook Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Installs a hook when the original implementation is not needed. No trampoline is allocated, making this slightly cheaper. ```APIDOC ## `hook(_:_:)` without orig — Fire-and-Forget Hook ### Description Installs a hook when the original implementation is not needed. No trampoline is allocated, making this slightly cheaper. ### Method `hook(target: replacement:)` ### Parameters #### Path Parameters - **target** (`UnsafeMutableRawPointer`) - Required - The memory address of the function to hook. - **replacement** (`UnsafeMutableRawPointer`) - Required - The memory address of the replacement function. ### Request Example ```swift import ellekit typealias WriteType = @convention(c) (Int32, UnsafeRawPointer, Int) -> Int func blockedWrite(_ fd: Int32, _ buf: UnsafeRawPointer, _ count: Int) -> Int { if fd == STDOUT_FILENO { return count } return Darwin.write(fd, buf, count) } let writeSymbol = dlsym(RTLD_DEFAULT, "write")! hook(writeSymbol, unsafeBitCast(blockedWrite as WriteType, to: UnsafeMutableRawPointer.self)) ``` ### Response #### Success Response This method does not return a value. ``` -------------------------------- ### LHHookFunctions Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Installs multiple C function hooks in a single call using an array of `LHFunctionHook` structs. More efficient than calling `hook()` repeatedly because orig pages may be shared. Returns `LIBHOOKER_OK` (0) on success or a `LIBHOOKER_ERR` code on failure. ```APIDOC ## `LHHookFunctions` — Batch Function Hooks Installs multiple C function hooks in a single call using an array of `LHFunctionHook` structs. More efficient than calling `hook()` repeatedly because orig pages may be shared. Returns `LIBHOOKER_OK` (0) on success or a `LIBHOOKER_ERR` code on failure. ```swift import ellekit typealias MallocType = @convention(c) (Int) -> UnsafeMutableRawPointer? var origMalloc: UnsafeMutableRawPointer? = nil var origFree: UnsafeMutableRawPointer? = nil func fakeMalloc(_ size: Int) -> UnsafeMutableRawPointer? { print("malloc(\(size))") return unsafeBitCast(origMalloc!, to: MallocType.self)(size) } func fakeFree(_ ptr: UnsafeMutableRawPointer?) { print("free called") typealias FreeType = @convention(c) (UnsafeMutableRawPointer?) -> Void unsafeBitCast(origFree!, to: FreeType.self)(ptr) } var hooks: [LHFunctionHook] = [ LHFunctionHook(function: dlsym(RTLD_DEFAULT, "malloc"), replacement: unsafeBitCast(fakeMalloc as MallocType, to: UnsafeMutableRawPointer.self), oldptr: &origMalloc, options: nil), LHFunctionHook(function: dlsym(RTLD_DEFAULT, "free"), replacement: unsafeBitCast(fakeFree, to: UnsafeMutableRawPointer.self), oldptr: &origFree, options: nil), ] let result = LHHookFunctions(&hooks, hooks.count) if result == Int(LIBHOOKER_OK.rawValue) { print("All hooks installed") } else { print("Error:", String(cString: LHStrError(LIBHOOKER_ERR(rawValue: UInt32(result)))! .assumingMemoryBound(to: CChar.self))) } ``` ``` -------------------------------- ### ARM64 Instruction Builder DSL Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Provides a Swift result-builder DSL and ARM64 instruction classes for assembling machine code. Use `bytes()` to get the raw byte representation of instructions. ```swift import ellekit // Manually assemble a 64-bit absolute jump to an arbitrary address let targetAddr: UInt64 = 0x1_0000_1234 let jumpBytes: [UInt8] = { @InstructionBuilder var code: [UInt8] { // Load full 64-bit address into x16 via four movk movk(.x16, targetAddr % 65536) movk(.x16, (targetAddr / 65536) % 65536, lsl: 16) movk(.x16, ((targetAddr / 65536) / 65536) % 65536, lsl: 32) movk(.x16, ((targetAddr / 65536) / 65536) / 65536, lsl: 48) br(.x16) } return code }() print(jumpBytes.map { String(format: "%02X", $0) }.joined(separator: " ")) // e.g. → "90 24 80 D2 ..." // Assemble a conditional branch using b(cond:) let condBranch = b(8, cond: .EQ).bytes() // b.eq #32 // Assemble an SVC instruction (system call number 0x80) let syscall = svc(0x80).bytes() // Use assembleJump for a page-relative (ADRP) jump within 4 GB let pageJump = assembleJump( 0x1_ABCD_0000, pc: 0x1_0000_0000, link: false, page: true, jmpReg: .x17 ) ``` -------------------------------- ### Batch Function Hooks with LHHookFunctions Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Installs multiple C function hooks in a single call using an array of LHFunctionHook structs. More efficient than calling hook() repeatedly as original pages may be shared. Returns LIBHOOKER_OK (0) on success or a LIBHOOKER_ERR code on failure. ```swift import ellekit typealias MallocType = @convention(c) (Int) -> UnsafeMutableRawPointer? var origMalloc: UnsafeMutableRawPointer? = nil var origFree: UnsafeMutableRawPointer? = nil func fakeMalloc(_ size: Int) -> UnsafeMutableRawPointer? { print("malloc(\(size))") return unsafeBitCast(origMalloc!, to: MallocType.self)(size) } func fakeFree(_ ptr: UnsafeMutableRawPointer?) { print("free called") typealias FreeType = @convention(c) (UnsafeMutableRawPointer?) -> Void unsafeBitCast(origFree!, to: FreeType.self)(ptr) } var hooks: [LHFunctionHook] = [ LHFunctionHook(function: dlsym(RTLD_DEFAULT, "malloc"), replacement: unsafeBitCast(fakeMalloc as MallocType, to: UnsafeMutableRawPointer.self), oldptr: &origMalloc, options: nil), LHFunctionHook(function: dlsym(RTLD_DEFAULT, "free"), replacement: unsafeBitCast(fakeFree, to: UnsafeMutableRawPointer.self), oldptr: &origFree, options: nil), ] let result = LHHookFunctions(&hooks, hooks.count) if result == Int(LIBHOOKER_OK.rawValue) { print("All hooks installed") } else { print("Error:", String(cString: LHStrError(LIBHOOKER_ERR(rawValue: UInt32(result)))! .assumingMemoryBound(to: CChar.self))) } ``` -------------------------------- ### Kill Dock Process Source: https://github.com/tealbathingsuit/ellekit/blob/main/Installation.md This command forcefully terminates the Dock process. It is an optional step often used to ensure injection into the Dock takes effect immediately after setup. ```bash killall Dock ``` -------------------------------- ### Hook C Function without Trampoline (Swift) Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Installs a hook on a C function without needing the original implementation. This is slightly more efficient as no trampoline is allocated. ```swift import ellekit typealias WriteType = @convention(c) (Int32, UnsafeRawPointer, Int) -> Int func blockedWrite(_ fd: Int32, _ buf: UnsafeRawPointer, _ count: Int) -> Int { // Silently drop writes to stdout if fd == STDOUT_FILENO { return count } // Fall through: we don't have orig, so call the syscall directly return Darwin.write(fd, buf, count) } let writeSymbol = dlsym(RTLD_DEFAULT, "write")! hook(writeSymbol, unsafeBitCast(blockedWrite as WriteType, to: UnsafeMutableRawPointer.self)) ``` -------------------------------- ### LaunchDaemon for Automatic macOS Startup Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Configure a LaunchDaemon to automatically load ElleKit on macOS startup. This ensures your tweaks are injected every time the system boots. ```bash # Install the bundled plist for load-on-boot injection sudo cp launchd-plist/com.evln.ellekit.startup.plist \ /Library/LaunchDaemons/ sudo launchctl load -w \ /Library/LaunchDaemons/com.evln.ellekit.startup.plist # Verify sudo launchctl list | grep ellekit ``` -------------------------------- ### Enable ARM64e Preview ABI Source: https://github.com/tealbathingsuit/ellekit/blob/main/Installation.md This command modifies boot arguments to enable the ARM64e preview ABI. It requires administrator privileges and a system reboot to take effect. ```bash sudo nvram boot-args=-arm64e_preview_abi ``` -------------------------------- ### Assemble Original Function Implementation (arm64) Source: https://github.com/tealbathingsuit/ellekit/blob/main/README.md This code demonstrates how ElleKit assembles the original function implementation when hooking functions beyond 128mb of address space. It sets up registers to point to the target address, prepares for a jump, executes skipped instructions, and finally calls the target function. ```arm64 // Insert address to target function movk x16, target_addr % 65536) movk x16, (target_addr / 65536) % 65536 lsl: 16 movk x16, ((target_addr / 65536) / 65536) % 65536, lsl: 32 movk x16, ((target_addr / 65536) / 65536) / 65536, lsl: 48 // Jump first instruction (the branch to the replacement, aka what we patched) add x16, x16, 4 // Execute the skipped instruction [4 first unpatched bytes of the target function] // Call the target function br x16 ``` -------------------------------- ### Instruction Builder DSL Source: https://context7.com/tealbathingsuit/ellekit/llms.txt ElleKit provides a Swift result-builder DSL (`@InstructionBuilder`) and a full set of ARM64 instruction classes for assembling machine code. ```APIDOC ## Instruction Builder DSL ### Description ElleKit provides a Swift result-builder DSL (`@InstructionBuilder`) and a full set of ARM64 instruction classes (`b`, `bl`, `br`, `blr`, `movz`, `movk`, `ldr`, `str`, `add`, `sub`, `ret`, `nop`, `svc`, `csel`, `adr`, `adrp`, `cbz`, `cbnz`). Each class exposes a `bytes() -> [UInt8]` method and can be used standalone or within `patchFunction`. ### Usage Use the `@InstructionBuilder` attribute with a closure that returns `[UInt8]` to construct sequences of instructions. Individual instruction classes can be instantiated and their `bytes()` method called to get their raw byte representation. ### Request Example ```swift import ellekit // Manually assemble a 64-bit absolute jump to an arbitrary address let targetAddr: UInt64 = 0x1_0000_1234 let jumpBytes: [UInt8] = { @InstructionBuilder var code: [UInt8] { // Load full 64-bit address into x16 via four movk movk(.x16, targetAddr % 65536) movk(.x16, (targetAddr / 65536) % 65536, lsl: 16) movk(.x16, ((targetAddr / 65536) / 65536) % 65536, lsl: 32) movk(.x16, ((targetAddr / 65536) / 65536) / 65536, lsl: 48) br(.x16) } return code }() print(jumpBytes.map { String(format: "%02X", $0) }.joined(separator: " ")) // e.g. → "90 24 80 D2 ..." // Assemble a conditional branch using b(cond:) let condBranch = b(8, cond: .EQ).bytes() // b.eq #32 // Assemble an SVC instruction (system call number 0x80) let syscall = svc(0x80).bytes() // Use assembleJump for a page-relative (ADRP) jump within 4 GB let pageJump = assembleJump( 0x1_ABCD_0000, pc: 0x1_0000_0000, link: false, page: true, jmpReg: .x17 ) ``` ``` -------------------------------- ### Building Debian Package for iOS Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Commands to build a Debian package for iOS using ElleKit. The `MAC=1` flag is used for building for macOS. ```bash # Build for arm64 iOS make deb # Build for macOS (arm64) MAC=1 make deb ``` -------------------------------- ### Enable DYLD Injection Source: https://github.com/tealbathingsuit/ellekit/blob/main/Installation.md Sets the DYLD_INSERT_LIBRARIES environment variable to inject the libinjector.dylib library. This is a crucial step for enabling ElleKit's injection capabilities. ```bash launchctl setenv DYLD_INSERT_LIBRARIES "/usr/local/lib/libinjector.dylib" ``` -------------------------------- ### Register JIT-Less Hardware Hook Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Registers a hardware-breakpoint based hook that does not require JIT. Call EKLaunchExceptionHandler once at startup. The target function is patched with `brk #1`, and the exception handler redirects execution to the replacement function on invocation. ```swift import ellekit // Launch the exception handler (call once at startup) let exceptionPort = EKLaunchExceptionHandler() print("Exception port:", exceptionPort) // Register a hook manually in the JIT-less registry let target = dlsym(RTLD_DEFAULT, "_expensiveFunction")! let replacement = dlsym(RTLD_DEFAULT, "_myReplacement")! var orig: UnsafeMutableRawPointer? = nil hardwareHook(target, replacement, &orig) // The target is now patched with `brk #1`; the exception handler // will redirect execution to `replacement` on each invocation. ``` -------------------------------- ### Allocate Executable Memory with LHExecMemory Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Allocates a new VM page, copies machine code into it, marks it executable, and returns the pointer. Useful for injecting shellcode stubs. The returned pointer must be freed manually if not used. ```swift import ellekit // A minimal ARM64 stub that returns 0 var stub: [UInt8] = [ 0x00, 0x00, 0x80, 0xD2, // movz x0, #0 0xC0, 0x03, 0x5F, 0xD6 // ret ] var execPage: UnsafeMutableRawPointer? = nil let ok = stub.withUnsafeMutableBytes { buf in LHExecMemory(&execPage, buf.baseAddress!, stub.count) } if ok != 0, let page = execPage { typealias StubFn = @convention(c) () -> Int let fn = unsafeBitCast(page, to: StubFn.self) print(fn()) // → 0 } ``` -------------------------------- ### Swift Package Manager Integration Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Add ElleKit as a dependency in your Package.swift file to integrate it into your Swift project. ```swift // Package.swift let package = Package( name: "MyTweak", dependencies: [ .package(url: "https://github.com/evelyneee/ellekit", branch: "main") ], targets: [ .target(name: "MyTweak", dependencies: ["ellekit"]) ] ) ``` -------------------------------- ### `hookClassPair(_:_:_:)` — Objective-C Class Pair Hook (`MSHookClassPair`) Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Copies all methods from `hookClass` onto `targetClass`, exchanging implementations with those already defined on `baseClass`. This is the ElleKit equivalent of Substrate's `MSHookClassPair`. ```APIDOC ## `hookClassPair(_:_:_:)` — Objective-C Class Pair Hook (`MSHookClassPair`) ### Description Copies all methods from `hookClass` onto `targetClass`, exchanging implementations with those already defined on `baseClass`. This is the ElleKit equivalent of Substrate's `MSHookClassPair`. ### Method `hookClassPair(targetClass: hookClass: baseClass:) ### Parameters #### Path Parameters - **targetClass** (`AnyClass`) - Required - The class to modify. - **hookClass** (`AnyClass`) - Required - The class providing new implementations. - **baseClass** (`AnyClass`) - Required - The class used to resolve original implementations. ### Request Example ```swift import ellekit import ObjectiveC class MyHookView: UIView { override func layoutSubviews() { print("hooked layoutSubviews") super.layoutSubviews() } } hookClassPair( UIView.self, MyHookView.self, UIView.self ) ``` ### Response #### Success Response This method does not return a value. ``` -------------------------------- ### Hook C Function using Substrate API in Swift Source: https://github.com/tealbathingsuit/ellekit/blob/main/Usage.md Utilize the Substrate API (MSHookFunction) to hook C functions. This method also provides a pointer to the original function's implementation. ```swift let atoiC: @convention(c) (UnsafePointer?) -> Int32 = atoi let repC: @convention(c) () -> Int32 = Replacement let orig = UnsafeMutablePointer.allocate(capacity: 10) MSHookFunction( unsafeBitCast(atoiC, to: UnsafeMutableRawPointer.self), unsafeBitCast(repC, to: UnsafeMutableRawPointer.self), orig ) ``` -------------------------------- ### LHExecMemory — Allocate Executable Page Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Allocates a new VM page, copies `size` bytes of machine code into it, marks it `r-x`, and stores the resulting pointer. Useful for injecting hand-crafted shellcode stubs. ```APIDOC ## LHExecMemory — Allocate Executable Page ### Description Allocates a new VM page, copies `size` bytes of machine code into it, marks it `r-x`, and stores the resulting pointer. Useful for injecting hand-crafted shellcode stubs. ### Parameters #### Path Parameters - **execPage** (UnsafeMutableRawPointer?) - Output - A pointer to the newly allocated executable page. - **machineCode** (UnsafeRawPointer?) - Required - A pointer to the machine code to be copied into the page. - **size** (Int) - Required - The number of bytes of machine code to copy. ### Return Value - **Int** - 0 on success, non-zero on failure. ### Request Example ```swift import ellekit // A minimal ARM64 stub that returns 0 var stub: [UInt8] = [ 0x00, 0x00, 0x80, 0xD2, // movz x0, #0 0xC0, 0x03, 0x5F, 0xD6 // ret ] var execPage: UnsafeMutableRawPointer? = nil let ok = stub.withUnsafeMutableBytes { buf in LHExecMemory(&execPage, buf.baseAddress!, stub.count) } if ok != 0, let page = execPage { typealias StubFn = @convention(c) () -> Int let fn = unsafeBitCast(page, to: StubFn.self) print(fn()) // → 0 } ``` ``` -------------------------------- ### Substrate Objective-C Hook with MSHookMessageEx Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Hooks an Objective-C method by selector. Equivalent to messageHook; included for source compatibility with Substrate-based tweaks. ```objective-c // In a Substrate-style tweak (ObjC) #import static NSString *(*orig_description)(id self, SEL _cmd); static NSString *replaced_description(id self, SEL _cmd) { NSString *original = orig_description(self, _cmd); return [NSString stringWithFormat:@"[Hooked] %@", original]; } // C API — also callable from Swift via MSHookMessageEx MSHookMessageEx( objc_getClass("NSObject"), @selector(description), (IMP)replaced_description, (IMP *)&orig_description ); ``` -------------------------------- ### Image and Symbol Lookup with MSGetImageByName / MSFindSymbol Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Opens a loaded Mach-O image by path and resolves a symbol name to a function pointer, searching the symbol table and (on iOS 14+) the dyld shared cache. ```swift import ellekit // Find a private symbol inside SpringBoard (on iOS) if let image = MSGetImageByName("/System/Library/CoreServices/SpringBoard.app/SpringBoard") { if let sym = MSFindSymbol(image, "_SBApplicationIcon") { print("Found _SBApplicationIcon at:", sym) } } // Search across all loaded images (pass nil as image) if let sym = MSFindSymbol(nil, "_UIApplicationMain") { print("UIApplicationMain:", sym) } ``` -------------------------------- ### MSHookMessageEx Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Hooks an Objective-C method by selector. Equivalent to `messageHook`; included for source compatibility with Substrate-based tweaks. ```APIDOC ## `MSHookMessageEx` — Substrate Objective-C Hook Hooks an Objective-C method by selector. Equivalent to `messageHook`; included for source compatibility with Substrate-based tweaks. ```swift // In a Substrate-style tweak (ObjC) #import static NSString *(*orig_description)(id self, SEL _cmd); static NSString *replaced_description(id self, SEL _cmd) { NSString *original = orig_description(self, _cmd); return [NSString stringWithFormat:@"[Hooked] %@", original]; } // C API — also callable from Swift via MSHookMessageEx MSHookMessageEx( objc_getClass("NSObject"), @selector(description), (IMP)replaced_description, (IMP *)&orig_description ); ``` ``` -------------------------------- ### Substrate Function Hook with MSHookFunction Source: https://context7.com/tealbathingsuit/ellekit/llms.txt A drop-in replacement for Substrate's MSHookFunction. Hooks a symbol, redirecting calls to a replacement function. If result is non-nil, it receives a pointer to the original-function trampoline. ```swift import ellekit typealias OpenType = @convention(c) (UnsafePointer, Int32) -> Int32 var origOpen: UnsafeMutableRawPointer? = nil func replacementOpen(_ path: UnsafePointer, _ flags: Int32) -> Int32 { print("open intercepted:", String(cString: path)) // Call original return unsafeBitCast(origOpen!, to: OpenType.self)(path, flags) } MSHookFunction( dlsym(RTLD_DEFAULT, "open")!, unsafeBitCast(replacementOpen as OpenType, to: UnsafeMutableRawPointer.self), &origOpen ) ``` -------------------------------- ### patchFunction(_:_:) Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Overwrites the bytes of a function directly using the built-in ARM64 assembler DSL. Instructions are composed with the `@InstructionBuilder` result-builder and written atomically to the target page. ```APIDOC ## `patchFunction(_:_:)` — Raw Inline Patch with `@InstructionBuilder` Overwrites the bytes of a function directly using the built-in ARM64 assembler DSL. Instructions are composed with the `@InstructionBuilder` result-builder and written atomically to the target page. ```swift import ellekit // Replace the first 3 instructions of someFunction with a NOP sled + immediate return let target = dlsym(RTLD_DEFAULT, "_someFunction")! patchFunction(target) { nop() nop() ret() } ``` ``` -------------------------------- ### MSHookMemory Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Patches `size` bytes at `target` with the bytes pointed to by `code`, remapping the backing memory page as writable first. ```APIDOC ## `MSHookMemory` — Raw Memory Patch via Substrate API Patches `size` bytes at `target` with the bytes pointed to by `code`, remapping the backing memory page as writable first. ```swift import ellekit // Patch 4 bytes at an arbitrary address with a NOP instruction var nopBytes: [UInt8] = [0x1F, 0x20, 0x03, 0xD5] // NOP on ARM64 let target = dlsym(RTLD_DEFAULT, "_someSmallFunction")! nopBytes.withUnsafeBytes { MSHookMemory( UnsafeMutableRawPointer(mutating: target), $0.baseAddress!.assumingMemoryBound(to: UInt8.self), mach_vm_size_t(4) ) } ``` ``` -------------------------------- ### MSHookFunction Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Drop-in replacement for Substrate's `MSHookFunction`. Hooks `symbol`, redirecting calls to `replace`. If `result` is non-nil, it receives a pointer to the original-function trampoline. ```APIDOC ## `MSHookFunction` — Substrate Function Hook Drop-in replacement for Substrate's `MSHookFunction`. Hooks `symbol`, redirecting calls to `replace`. If `result` is non-nil, it receives a pointer to the original-function trampoline. ```swift import ellekit typealias OpenType = @convention(c) (UnsafePointer, Int32) -> Int32 var origOpen: UnsafeMutableRawPointer? = nil func replacementOpen(_ path: UnsafePointer, _ flags: Int32) -> Int32 { print("open intercepted:", String(cString: path)) // Call original return unsafeBitCast(origOpen!, to: OpenType.self)(path, flags) } MSHookFunction( dlsym(RTLD_DEFAULT, "open")!, unsafeBitCast(replacementOpen as OpenType, to: UnsafeMutableRawPointer.self), &origOpen ) ``` ``` -------------------------------- ### Batch Symbol Lookup with LHFindSymbols Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Resolves multiple symbol names from a Mach-O image efficiently. Returns true only if all requested symbols are found. Ensure the image path is valid and the header is correctly opened. ```swift import ellekit import MachO let imagePath = "/usr/lib/libobjc.A.dylib" guard let header = LHOpenImage(imagePath) else { fatalError("image not found") } defer { LHCloseImage(header) } var sym1: UnsafeRawPointer? = nil var sym2: UnsafeRawPointer? = nil let names = ["_objc_msgSend", "_objc_retain"] let cNames = names.map { strdup($0)! as UnsafePointer } var results = [UnsafeRawPointer?](repeating: nil, count: names.count) let found = LHFindSymbols( header.withMemoryRebound(to: mach_header_64.self, capacity: 1) { $0 }, cNames, &results, names.count ) if found { print("objc_msgSend:", results[0]!) print("objc_retain:", results[1]!) } ``` -------------------------------- ### Hook Objective-C Class Pair (Swift) Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Copies methods from a hook class to a target class, exchanging implementations with a base class. This is equivalent to Substrate's `MSHookClassPair`. ```swift import ellekit import ObjectiveC // Assume MyHookView declares overrides for UIView methods class MyHookView: UIView { override func layoutSubviews() { print("hooked layoutSubviews") super.layoutSubviews() } } // Redirect all UIView instances through MyHookView's overrides hookClassPair( UIView.self, // target — class to modify MyHookView.self, // hook — class providing new implementations UIView.self // base — class used to resolve originals ) ``` -------------------------------- ### Hook C Function with Original in Swift Source: https://github.com/tealbathingsuit/ellekit/blob/main/Usage.md Hook a C function and obtain a pointer to its original implementation. Ensure the target and replacement functions are correctly cast. ```swift let atoiC: @convention(c) (UnsafePointer?) -> Int32 = atoi let repC: @convention(c) () -> Int32 = Replacement let orig = hook( unsafeBitCast(atoiC, to: UnsafeMutableRawPointer.self), unsafeBitCast(repC, to: UnsafeMutableRawPointer.self) ) ``` -------------------------------- ### `hook(_:_:)` — C Function Hook Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Hooks a C function by patching the target address with a branch to the replacement. Returns a pointer to a trampoline that executes the original implementation. ```APIDOC ## `hook(_:_:)` — C Function Hook ### Description Hooks a C function by patching the target address with a branch to the replacement. Returns an `UnsafeMutableRawPointer?` pointing to a newly allocated trampoline page that executes the original first instruction(s) and then jumps back into the unpatched body of the target. ### Method `hook(target: replacement:)` ### Parameters #### Path Parameters - **target** (`UnsafeMutableRawPointer`) - Required - The memory address of the function to hook. - **replacement** (`UnsafeMutableRawPointer`) - Required - The memory address of the replacement function. ### Request Example ```swift import ellekit typealias AtoiType = @convention(c) (UnsafePointer?) -> Int32 typealias FakeType = @convention(c) () -> Int32 func FakeAtoi() -> Int32 { return 42 } let atoiC: AtoiType = atoi let fakeC: FakeType = FakeAtoi let origPtr = hook( unsafeBitCast(atoiC, to: UnsafeMutableRawPointer.self), unsafeBitCast(fakeC, to: UnsafeMutableRawPointer.self) ) if let origPtr { let origAtoi = unsafeBitCast(origPtr, to: AtoiType.self) print(origAtoi("123")) } print(atoi("123")) ``` ### Response #### Success Response - **origPtr** (`UnsafeMutableRawPointer?`) - A pointer to the trampoline executing the original function, or nil if hooking failed. ``` -------------------------------- ### MSGetImageByName / MSFindSymbol Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Opens a loaded Mach-O image by path and resolves a symbol name to a function pointer, searching the symbol table and (on iOS 14+) the dyld shared cache. ```APIDOC ## `MSGetImageByName` / `MSFindSymbol` — Image & Symbol Lookup Opens a loaded Mach-O image by path and resolves a symbol name to a function pointer, searching the symbol table and (on iOS 14+) the dyld shared cache. ```swift import ellekit // Find a private symbol inside SpringBoard (on iOS) if let image = MSGetImageByName("/System/Library/CoreServices/SpringBoard.app/SpringBoard") { if let sym = MSFindSymbol(image, "_SBApplicationIcon") { print("Found _SBApplicationIcon at:", sym) } } // Search across all loaded images (pass nil as image) if let sym = MSFindSymbol(nil, "_UIApplicationMain") { print("UIApplicationMain:", sym) } ``` ``` -------------------------------- ### Raw Memory Patch with MSHookMemory Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Patches a specified number of bytes at a target address with new code, remapping the backing memory page as writable first. Useful for small, direct memory modifications. ```swift import ellekit // Patch 4 bytes at an arbitrary address with a NOP instruction var nopBytes: [UInt8] = [0x1F, 0x20, 0x03, 0xD5] // NOP on ARM64 let target = dlsym(RTLD_DEFAULT, "_someSmallFunction")! nopBytes.withUnsafeBytes { MSHookMemory( UnsafeMutableRawPointer(mutating: target), $0.baseAddress!.assumingMemoryBound(to: UInt8.self), mach_vm_size_t(4) ) } ``` -------------------------------- ### Atomic Raw Memory Patching with LHPatchMemory Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Applies a list of raw byte patches atomically. Returns 0 on success. Ensure the target pointer and data are valid. ```swift import ellekit var patchBytes: [UInt8] = [0x1F, 0x20, 0x03, 0xD5] // NOP let target = dlsym(RTLD_DEFAULT, "_targetFunction")! var patches: [LHMemoryPatch] = [ LHMemoryPatch( destination: UnsafeMutableRawPointer(mutating: target), data: patchBytes.withUnsafeBytes { $0.baseAddress }, size: 4, options: nil ) ] let ret = LHPatchMemory(&patches, patches.count) print(ret == 0 ? "patched" : "failed") ``` -------------------------------- ### Raw Inline Patch with @InstructionBuilder Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Directly overwrites function bytes using the ARM64 assembler DSL. Instructions are composed with the @InstructionBuilder result-builder and written atomically to the target page. ```swift import ellekit // Replace the first 3 instructions of someFunction with a NOP sled + immediate return let target = dlsym(RTLD_DEFAULT, "_someFunction")! patchFunction(target) { nop() nop() ret() } ``` -------------------------------- ### LHPatchMemory — Batch Raw Memory Patches Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Applies a list of raw byte patches atomically using `LHMemoryPatch` structs. Returns 0 on success. ```APIDOC ## LHPatchMemory — Batch Raw Memory Patches ### Description Applies a list of raw byte patches atomically using `LHMemoryPatch` structs. Returns 0 on success. ### Parameters #### Path Parameters - **patches** (LHMemoryPatch?) - Required - An array of `LHMemoryPatch` structs defining the patches to apply. - **count** (Int) - Required - The number of patches in the `patches` array. ### Return Value - **Int** - 0 on success, non-zero on failure. ### Request Example ```swift import ellekit var patchBytes: [UInt8] = [0x1F, 0x20, 0x03, 0xD5] // NOP let target = dlsym(RTLD_DEFAULT, "_targetFunction")! var patches: [LHMemoryPatch] = [ LHMemoryPatch( destination: UnsafeMutableRawPointer(mutating: target), data: patchBytes.withUnsafeBytes { $0.baseAddress }, size: 4, options: nil ) ] let ret = LHPatchMemory(&patches, patches.count) print(ret == 0 ? "patched" : "failed") ``` ``` -------------------------------- ### Hook Objective-C Method (Swift) Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Replaces an Objective-C method implementation using `class_replaceMethod`. The original IMP is stored in a provided pointer, allowing the hook to call the original method. ```swift import ellekit import ObjectiveC // Hook -[NSString lowercaseString] to return uppercase instead var origLowercase: IMP? let replacement: @convention(block) (NSString) -> NSString = { self in return self.uppercased as NSString } let replacementIMP = imp_implementationWithBlock(replacement) var origPtr: UnsafeMutableRawPointer? = nil messageHook( NSString.self, #selector(NSString.lowercased), replacementIMP, &origPtr ) // origPtr now points to the original -lowercaseString IMP print(("Hello" as NSString).lowercased) // → "HELLO" ``` -------------------------------- ### LHFindSymbols — Batch Symbol Lookup Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Resolves multiple symbol names from a Mach-O image in one call. Returns `true` only if every requested symbol was found. ```APIDOC ## LHFindSymbols — Batch Symbol Lookup ### Description Resolves multiple symbol names from a Mach-O image in one call. Returns `true` only if every requested symbol was found. ### Parameters #### Path Parameters - **header** (mach_header_64) - Required - Pointer to the Mach-O header. - **cNames** (UnsafePointer?) - Required - An array of C strings representing the symbol names to look up. - **results** (UnsafeMutablePointer?) - Required - An array to store the pointers to the found symbols. - **count** (Int) - Required - The number of symbols to look up. ### Return Value - **Bool** - `true` if all symbols were found, `false` otherwise. ### Request Example ```swift import ellekit import MachO let imagePath = "/usr/lib/libobjc.A.dylib" guard let header = LHOpenImage(imagePath) else { fatalError("image not found") } defer { LHCloseImage(header) } var sym1: UnsafeRawPointer? = nil var sym2: UnsafeRawPointer? = nil let names = ["_objc_msgSend", "_objc_retain"] let cNames = names.map { strdup($0)! as UnsafePointer } var results = [UnsafeRawPointer?](repeating: nil, count: names.count) let found = LHFindSymbols( header.withMemoryRebound(to: mach_header_64.self, capacity: 1) { $0 }, cNames, &results, names.count ) if found { print("objc_msgSend:", results[0]!) print("objc_retain:", results[1]!) } ``` ``` -------------------------------- ### Toggle Thread Safety with EKEnableThreadSafety Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Controls whether ElleKit suspends all threads during memory patching. Enabled by default (1). Disable (0) for faster patching at load time if no other thread can execute the target concurrently. ```swift import ellekit // Disable thread suspension for faster hooking at load time EKEnableThreadSafety(0) // … install all hooks … // Re-enable for runtime safety EKEnableThreadSafety(1) ``` -------------------------------- ### Hook C Function with Trampoline (Swift) Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Hooks a C function and returns a trampoline to the original implementation. Ensure correct type casting for function pointers. ```swift import ellekit // Hook atoi so every call returns 42 typealias AtoiType = @convention(c) (UnsafePointer?) -> Int32 typealias FakeType = @convention(c) () -> Int32 func FakeAtoi() -> Int32 { return 42 } let atoiC: AtoiType = atoi let fakeC: FakeType = FakeAtoi // Cast to raw pointers, install hook, keep orig trampoline let origPtr = hook( unsafeBitCast(atoiC, to: UnsafeMutableRawPointer.self), unsafeBitCast(fakeC, to: UnsafeMutableRawPointer.self) ) // Call through the trampoline to reach the real atoi if let origPtr { let origAtoi = unsafeBitCast(origPtr, to: AtoiType.self) print(origAtoi("123")) // → 123 (original implementation) } print(atoi("123")) // → 42 (hooked) ``` -------------------------------- ### EKEnableThreadSafety — Thread Safety Toggle Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Controls whether ElleKit suspends all threads in the process before patching memory. Enabled by default (`true`). Disable only if you are certain no other thread could execute the target during patching (e.g., during `+load`). ```APIDOC ## EKEnableThreadSafety — Thread Safety Toggle ### Description Controls whether ElleKit suspends all threads in the process before patching memory. Enabled by default (`true`). Disable only if you are certain no other thread could execute the target during patching (e.g., during `+load`). ### Parameters #### Path Parameters - **enable** (Int) - Required - Set to `0` to disable thread safety, `1` to enable. ### Request Example ```swift import ellekit // Disable thread suspension for faster hooking at load time EKEnableThreadSafety(0) // … install all hooks … // Re-enable for runtime safety EKEnableThreadSafety(1) ``` ``` -------------------------------- ### `messageHook(_:_:_:_:)` — Objective-C Method Hook Source: https://context7.com/tealbathingsuit/ellekit/llms.txt Replaces the implementation of an Objective-C selector on a class using `class_replaceMethod`. Stores the previous IMP in the provided result pointer. ```APIDOC ## `messageHook(_:_:_:_:)` — Objective-C Method Hook ### Description Replaces the implementation of an Objective-C selector on a class using `class_replaceMethod`. Stores the previous `IMP` (or the superclass implementation) in the provided result pointer so the hook can call through. ### Method `messageHook(targetClass: selector: replacementIMP: originalIMP:) ### Parameters #### Path Parameters - **targetClass** (`AnyClass`) - Required - The class whose method implementation to replace. - **selector** (`Selector`) - Required - The selector of the method to replace. - **replacementIMP** (`IMP`) - Required - The new implementation for the method. - **originalIMP** (`UnsafeMutablePointer?`) - Optional - A pointer to store the original implementation. ### Request Example ```swift import ellekit import ObjectiveC var origLowercase: IMP? let replacement: @convention(block) (NSString) -> NSString = { self in return self.uppercased as NSString } let replacementIMP = imp_implementationWithBlock(replacement) var origPtr: UnsafeMutableRawPointer? = nil messageHook( NSString.self, #selector(NSString.lowercased), replacementIMP, &origPtr ) print(("Hello" as NSString).lowercased) ``` ### Response #### Success Response This method does not return a value, but the `originalIMP` parameter will be populated if provided. ``` -------------------------------- ### Hook C Function without Original in Swift Source: https://github.com/tealbathingsuit/ellekit/blob/main/Usage.md Hook a C function without preserving its original implementation. This is a simpler form of hooking when the original function is not needed. ```swift hook( target, replacement ) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.