diff options
Diffstat (limited to 'kernel_call/kernel_memory.c')
-rwxr-xr-x | kernel_call/kernel_memory.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/kernel_call/kernel_memory.c b/kernel_call/kernel_memory.c new file mode 100755 index 0000000..fba81b8 --- /dev/null +++ b/kernel_call/kernel_memory.c @@ -0,0 +1,129 @@ +/* + * kernel_memory.c + * Brandon Azad + */ +#define KERNEL_MEMORY_EXTERN +#include "kernel_memory.h" + +#include "log.h" +#include "mach_vm.h" +#include "parameters.h" + +// ---- Kernel memory functions ------------------------------------------------------------------- + +bool +kernel_read(uint64_t address, void *data, size_t size) { + mach_vm_size_t size_out; + kern_return_t kr = mach_vm_read_overwrite(kernel_task_port, address, + size, (mach_vm_address_t) data, &size_out); + if (kr != KERN_SUCCESS) { + ERROR("%s returned %d: %s", "mach_vm_read_overwrite", kr, mach_error_string(kr)); + ERROR("could not %s address 0x%016llx", "read", address); + return false; + } + if (size_out != size) { + ERROR("partial read of address 0x%016llx: %llu of %zu bytes", + address, size_out, size); + return false; + } + return true; +} + +bool +kernel_write(uint64_t address, const void *data, size_t size) { + kern_return_t kr = mach_vm_write(kernel_task_port, address, + (mach_vm_address_t) data, (mach_msg_size_t) size); + if (kr != KERN_SUCCESS) { + ERROR("%s returned %d: %s", "mach_vm_write", kr, mach_error_string(kr)); + ERROR("could not %s address 0x%016llx", "write", address); + return false; + } + return true; +} + +uint8_t +kernel_read8(uint64_t address) { + uint8_t value; + bool ok = kernel_read(address, &value, sizeof(value)); + if (!ok) { + return -1; + } + return value; +} + +uint16_t +kernel_read16(uint64_t address) { + uint16_t value; + bool ok = kernel_read(address, &value, sizeof(value)); + if (!ok) { + return -1; + } + return value; +} + +uint32_t +kernel_read32(uint64_t address) { + uint32_t value; + bool ok = kernel_read(address, &value, sizeof(value)); + if (!ok) { + return -1; + } + return value; +} + +uint64_t +kernel_read64(uint64_t address) { + uint64_t value; + bool ok = kernel_read(address, &value, sizeof(value)); + if (!ok) { + return -1; + } + return value; +} + +bool +kernel_write8(uint64_t address, uint8_t value) { + return kernel_write(address, &value, sizeof(value)); +} + +bool +kernel_write16(uint64_t address, uint16_t value) { + return kernel_write(address, &value, sizeof(value)); +} + +bool +kernel_write32(uint64_t address, uint32_t value) { + return kernel_write(address, &value, sizeof(value)); +} + +bool +kernel_write64(uint64_t address, uint64_t value) { + return kernel_write(address, &value, sizeof(value)); +} + +// ---- Kernel utility functions ------------------------------------------------------------------ + +bool +kernel_ipc_port_lookup(uint64_t task, mach_port_name_t port_name, + uint64_t *ipc_port, uint64_t *ipc_entry) { + // Get the task's ipc_space. + uint64_t itk_space = kernel_read64(task + OFFSET(task, itk_space)); + // Get the size of the table. + uint32_t is_table_size = kernel_read32(itk_space + OFFSET(ipc_space, is_table_size)); + // Get the index of the port and check that it is in-bounds. + uint32_t port_index = MACH_PORT_INDEX(port_name); + if (port_index >= is_table_size) { + return false; + } + // Get the space's is_table and compute the address of this port's entry. + uint64_t is_table = kernel_read64(itk_space + OFFSET(ipc_space, is_table)); + uint64_t entry = is_table + port_index * SIZE(ipc_entry); + if (ipc_entry != NULL) { + *ipc_entry = entry; + } + // Get the address of the port if requested. + if (ipc_port != NULL) { + *ipc_port = kernel_read64(entry + OFFSET(ipc_entry, ie_object)); + } + return true; +} |