summaryrefslogtreecommitdiff
path: root/kernel_call/kernel_memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel_call/kernel_memory.c')
-rwxr-xr-xkernel_call/kernel_memory.c129
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;
+}