├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── ktrw_gdb_stub ├── Makefile ├── kernel_symbols │ ├── iPhone10,1_17B102.txt │ ├── iPhone10,1_17C54.txt │ └── iPhone10,1_17F75.txt └── source │ ├── debug.c │ ├── debug.h │ ├── devicetree.c │ ├── devicetree.h │ ├── gdb_stub │ ├── gdb_cpu.c │ ├── gdb_cpu.h │ ├── gdb_internal.c │ ├── gdb_internal.h │ ├── gdb_packets.c │ ├── gdb_packets.h │ ├── gdb_platform.c │ ├── gdb_platform.h │ ├── gdb_rsp.c │ ├── gdb_rsp.h │ ├── gdb_state.h │ ├── gdb_stub.c │ └── gdb_stub.h │ ├── if_value.h │ ├── jit_heap.c │ ├── jit_heap.h │ ├── kernel_extern.h │ ├── ktrw.c │ ├── page_table.c │ ├── page_table.h │ ├── primitives.c │ ├── primitives.h │ ├── third_party │ ├── boot_args.h │ └── kmod.h │ ├── usb │ ├── synopsys_otg.c │ ├── synopsys_otg_regs.h │ └── usb.h │ ├── watchdog.c │ └── watchdog.h ├── ktrw_kext_loader ├── Makefile ├── app │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── headers │ ├── IOKitLib.h │ └── mach_vm.h ├── kernel │ ├── kernel_memory.c │ ├── kernel_memory.h │ ├── kernel_parameters.c │ ├── kernel_parameters.h │ ├── kernel_slide.c │ ├── kernel_slide.h │ ├── kernel_tasks.c │ └── kernel_tasks.h ├── kernel_call │ ├── kernel_call.c │ ├── kernel_call.h │ ├── kernel_call_7_a11.c │ ├── kernel_call_7_a11.h │ ├── kernel_call_parameters.c │ └── kernel_call_parameters.h ├── kernel_patches │ ├── kernel_patches.c │ └── kernel_patches.h ├── kernel_symbols │ ├── iPhone10,1_16C101.txt │ ├── iPhone10,1_16G77.txt │ └── iPhone10,6_16E227.txt ├── kext_load │ ├── kext_load.c │ ├── kext_load.h │ ├── resolve_symbol.c │ └── resolve_symbol.h ├── ktrr │ ├── ktrr_bypass.c │ ├── ktrr_bypass.h │ ├── ktrr_bypass_parameters.c │ └── ktrr_bypass_parameters.h ├── ktrw_kext_loader.entitlements ├── ktrw_kext_loader.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── ktrw_kext_loader.xcscheme ├── main.c └── system │ ├── bundle_path.c │ ├── bundle_path.h │ ├── log.c │ ├── log.h │ ├── map_file.c │ ├── map_file.h │ ├── parameters.h │ ├── platform.c │ ├── platform.h │ ├── platform_match.c │ └── platform_match.h ├── ktrw_usb_proxy ├── Makefile └── source │ └── ktrw_usb_proxy.c ├── misc └── dbg_xnu.cfg.patch ├── pongo_kext_loader ├── Makefile └── source │ └── pongo_kext_loader.c └── pongo_kextload ├── Makefile └── source ├── pongo_kextload.c └── third_party └── pongo.h /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows [Google's Open Source Community 28 | Guidelines](https://opensource.google.com/conduct/). 29 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARGET_DIRECTORIES = pongo_kext_loader pongo_kextload ktrw_gdb_stub ktrw_usb_proxy 2 | 3 | all: $(TARGET_DIRECTORIES) 4 | 5 | .PHONY: all $(TARGET_DIRECTORIES) 6 | 7 | $(TARGET_DIRECTORIES): 8 | $(MAKE) -C $@ 9 | 10 | CLEAN_TARGET_DIRECTORIES = $(TARGET_DIRECTORIES:%=clean-%) 11 | 12 | clean: $(CLEAN_TARGET_DIRECTORIES) 13 | 14 | .PHONY: clean $(CLEAN_TARGET_DIRECTORIES) 15 | 16 | $(CLEAN_TARGET_DIRECTORIES): 17 | $(MAKE) -C $(@:clean-%=%) clean 18 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = ktrw_gdb_stub.ikext 2 | 3 | ARCH = arm64 4 | SDK = iphoneos 5 | KTRW_VERSION = 0.1.0 6 | ACTIVATION_DELAY = 30 7 | 8 | SYSROOT := $(shell xcrun --sdk $(SDK) --show-sdk-path) 9 | ifeq ($(SYSROOT),) 10 | $(error Could not find SDK $(SDK)) 11 | endif 12 | CLANG := $(shell xcrun --sdk $(SDK) --find clang) 13 | CC := $(CLANG) -isysroot $(SYSROOT) -arch $(ARCH) 14 | 15 | CFLAGS = -fno-builtin -fno-common -mkernel 16 | CFLAGS += -Isource 17 | CFLAGS += -O2 18 | CFLAGS += -Wall -Werror -Wpedantic -Wno-gnu -Wno-language-extension-token 19 | # TODO: -Wconversion 20 | 21 | DEFINES = -DKTRW_VERSION='"$(KTRW_VERSION)"' \ 22 | -DKTRW_GDB_STUB_ACTIVATION_DELAY='$(ACTIVATION_DELAY)' 23 | 24 | LDFLAGS = -Xlinker -kext -nostdlib -Xlinker -fatal_warnings 25 | 26 | SOURCES = source/gdb_stub/gdb_cpu.c \ 27 | source/gdb_stub/gdb_internal.c \ 28 | source/gdb_stub/gdb_packets.c \ 29 | source/gdb_stub/gdb_platform.c \ 30 | source/gdb_stub/gdb_rsp.c \ 31 | source/gdb_stub/gdb_stub.c \ 32 | source/usb/synopsys_otg.c \ 33 | source/debug.c \ 34 | source/devicetree.c \ 35 | source/jit_heap.c \ 36 | source/ktrw.c \ 37 | source/page_table.c \ 38 | source/primitives.c \ 39 | source/watchdog.c 40 | 41 | HEADERS = source/gdb_stub/gdb_cpu.h \ 42 | source/gdb_stub/gdb_internal.h \ 43 | source/gdb_stub/gdb_packets.h \ 44 | source/gdb_stub/gdb_platform.h \ 45 | source/gdb_stub/gdb_rsp.h \ 46 | source/gdb_stub/gdb_state.h \ 47 | source/gdb_stub/gdb_stub.h \ 48 | source/third_party/boot_args.h \ 49 | source/usb/synopsys_otg_regs.h \ 50 | source/usb/usb.h \ 51 | source/debug.h \ 52 | source/devicetree.h \ 53 | source/if_value.h \ 54 | source/jit_heap.h \ 55 | source/kernel_extern.h \ 56 | source/page_table.h \ 57 | source/primitives.h \ 58 | source/watchdog.h 59 | 60 | $(TARGET): $(SOURCES) $(HEADERS) 61 | $(CC) $(CFLAGS) $(DEFINES) $(LDFLAGS) -o $@ $(SOURCES) 62 | 63 | symbols: $(TARGET) 64 | @nm -u $(TARGET) 65 | 66 | clean: 67 | rm -rf -- $(TARGET).$(ARCH).ld 68 | rm -f -- $(TARGET) 69 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/kernel_symbols/iPhone10,1_17B102.txt: -------------------------------------------------------------------------------- 1 | KERNELCACHE UUID: 6D59B3A0-4546-32CD-A399-FA9F24D99ED2 2 | DEVICE: iPhone10,1 17B102 3 | DEVICE: iPhone10,4 17B102 4 | 5 | __disable_preemption 0xFFFFFFF007CD06E4 6 | __enable_preemption 0xFFFFFFF007CD0710 7 | __mh_execute_header 0xFFFFFFF007004000 8 | _const_boot_args 0xFFFFFFF007906870 9 | _IOSleep 0xFFFFFFF0080F568C 10 | _kernel_map 0xFFFFFFF007905658 11 | _kernel_memory_allocate 0xFFFFFFF007C50AF4 12 | _kernel_thread_start 0xFFFFFFF007BFAC54 13 | _ml_nofault_copy 0xFFFFFFF007CD6CF8 14 | _panic 0xFFFFFFF0090329E4 15 | _paniclog_append_noflush 0xFFFFFFF007BD5698 16 | _thread_deallocate 0xFFFFFFF007BF93A0 17 | _vsnprintf 0xFFFFFFF007FE60E4 18 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/kernel_symbols/iPhone10,1_17C54.txt: -------------------------------------------------------------------------------- 1 | KERNELCACHE UUID: EB3BF781-4235-3F5E-8E77-B4C836D5F71F 2 | DEVICE: iPhone10,1 17C54 3 | DEVICE: iPhone10,4 17C54 4 | 5 | __disable_preemption 0xFFFFFFF007CD8BC4 6 | __enable_preemption 0xFFFFFFF007CD8BF0 7 | __mh_execute_header 0xFFFFFFF007004000 8 | _const_boot_args 0xFFFFFFF00790A870 9 | _IOSleep 0xFFFFFFF0080FC218 10 | _kernel_map 0xFFFFFFF007909658 11 | _kernel_memory_allocate 0xFFFFFFF007C58B6C 12 | _kernel_thread_start 0xFFFFFFF007C02C8C 13 | _ml_nofault_copy 0xFFFFFFF007CDF1D8 14 | _panic 0xFFFFFFF00903A9E4 15 | _paniclog_append_noflush 0xFFFFFFF007BDD6D0 16 | _thread_deallocate 0xFFFFFFF007C013D8 17 | _vsnprintf 0xFFFFFFF007FECB98 18 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/kernel_symbols/iPhone10,1_17F75.txt: -------------------------------------------------------------------------------- 1 | KERNELCACHE UUID: 15576917-FD0D-3A15-B52E-72D55A37D8E8 2 | DEVICE: iPhone10,1 17F75 3 | DEVICE: iPhone10,4 17F75 4 | 5 | __disable_preemption 0xFFFFFFF007D08CF0 6 | __enable_preemption 0xFFFFFFF007D08D20 7 | __mh_execute_header 0xFFFFFFF007004000 8 | _const_boot_args 0xFFFFFFF0079328C0 9 | _IOSleep 0xFFFFFFF008131198 10 | _kernel_map 0xFFFFFFF0079316a8 11 | _kernel_memory_allocate 0xFFFFFFF007C88CE0 12 | _kernel_thread_start 0xFFFFFFF007C33608 13 | _ml_nofault_copy 0xFFFFFFF007D0F574 14 | _panic 0xFFFFFFF00909EA08 15 | _paniclog_append_noflush 0xFFFFFFF007C0E170 16 | _thread_deallocate 0xFFFFFFF007C010AC 17 | _vsnprintf 0xFFFFFFF0080204E0 18 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/debug.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "debug.h" 21 | 22 | #include "page_table.h" 23 | 24 | // ---- Mapping the debug registers --------------------------------------------------------------- 25 | 26 | // 0x208010000, 0x208110000, 0x208210000, 0x208310000, 0x208410000, 0x208510000 27 | uint64_t cpu_register_base[MAX_CPU_COUNT]; 28 | 29 | uint64_t external_debug_registers[MAX_CPU_COUNT]; 30 | uint64_t dbgwrap_registers[MAX_CPU_COUNT]; 31 | 32 | void 33 | map_debug_registers() { 34 | for (uint32_t cpu_id = 0; cpu_id < MAX_CPU_COUNT; cpu_id++) { 35 | if (external_debug_registers[cpu_id] != 0 || cpu_register_base[cpu_id] == 0) { 36 | continue; 37 | } 38 | external_debug_registers[cpu_id] = (uint64_t) 39 | ttbr0_map_io(cpu_register_base[cpu_id] + 0x00000, 0x1000); 40 | dbgwrap_registers[cpu_id] = (uint64_t) 41 | ttbr0_map_io(cpu_register_base[cpu_id] + 0x30000, 0x1000); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/debug.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef DEBUG__H_ 21 | #define DEBUG__H_ 22 | 23 | #include 24 | 25 | // The maximum number of CPUs. 26 | #define MAX_CPU_COUNT 6 27 | 28 | // The physical base address of the CPU registers. This should be initialized prior to mapping the 29 | // debug registers. 30 | extern uint64_t cpu_register_base[]; 31 | 32 | // The memory-mapped CoreSight External Debug registers, per CPU. 33 | extern uint64_t external_debug_registers[]; 34 | 35 | // The memory-mapped DBGWRAP registers, per CPU. 36 | extern uint64_t dbgwrap_registers[]; 37 | 38 | #define rEDECR(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0x024) 39 | #define rEDWAR_lo(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0x030) 40 | #define rEDWAR_hi(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0x034) 41 | #define rDBGDTRRX(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0x080) 42 | #define rEDITR(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0x084) 43 | #define rEDSCR(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0x088) 44 | #define rDBGDTRTX(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0x08c) 45 | #define rEDRCR(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0x090) 46 | #define rOSLAR(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0x300) 47 | #define rEDPRSR(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0x314) 48 | #define rDBGBVR(cpu, n) *(volatile uint64_t *)(external_debug_registers[(cpu)] + 0x400 + 16 * n) 49 | #define rDBGBCR(cpu, n) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0x408 + 16 * n) 50 | #define rDBGWVR(cpu, n) *(volatile uint64_t *)(external_debug_registers[(cpu)] + 0x800 + 16 * n) 51 | #define rDBGWCR(cpu, n) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0x808 + 16 * n) 52 | #define rEDDFR_lo(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0xd28) 53 | #define rEDDFR_hi(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0xd2c) 54 | #define rEDLAR(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0xfb0) 55 | #define rEDLSR(cpu) *(volatile uint32_t *)(external_debug_registers[(cpu)] + 0xfb4) 56 | 57 | #define rDBGWRAP(cpu) *(volatile uint64_t *)(dbgwrap_registers[(cpu)] + 0x000) 58 | 59 | #define EDECR_SS (1 << 2) 60 | 61 | #define EDSCR_ITE (1 << 24) 62 | #define EDSCR_INTdis(b) (((b) & 0x3) << 22) 63 | #define EDSCR_TDA (1 << 21) 64 | #define EDSCR_HDE (1 << 14) 65 | #define EDSCR_ERR (1 << 6) 66 | #define EDSCR_STATUS (0x3f) 67 | 68 | #define EDRCR_CSE (1 << 2) 69 | 70 | #define EDPRSR_SDR (1 << 11) 71 | #define EDPRSR_HALTED (1 << 4) 72 | 73 | #define EDLSR_SLI (1 << 0) 74 | #define EDLSR_SLK (1 << 1) 75 | 76 | #define DBGWRAP_Halt (1uL << 31) 77 | #define DBGWRAP_Restart (1uL << 30) 78 | #define DBGWRAP_HaltAfterReset (1uL << 29) // EDECR.RCE ? 79 | #define DBGWRAP_CpuIsHalted (1uL << 28) 80 | #define DBGWRAP_DisableReset (1uL << 26) // EDPRCR.CORENPDRQ ? 81 | 82 | /* 83 | * map_debug_registers 84 | * 85 | * Description: 86 | * Map the debug registers. 87 | */ 88 | void map_debug_registers(void); 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/devicetree.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "devicetree.h" 21 | 22 | #include 23 | 24 | #include "primitives.h" 25 | 26 | // The format of a device tree node header. 27 | struct _devicetree_node { 28 | uint32_t n_properties; 29 | uint32_t n_children; 30 | }; 31 | 32 | // The format of a device tree property header. 33 | struct _devicetree_property { 34 | char name[32]; 35 | uint32_t size; 36 | uint8_t data[0]; 37 | }; 38 | 39 | // Parse a property and perform basic validation. 40 | static const struct _devicetree_property * 41 | parse_property(const uint8_t **p, const uint8_t *end) { 42 | // Parse the property header. 43 | const struct _devicetree_property *prop = (void *)*p; 44 | *p += sizeof(*prop); 45 | if (*p > end) { 46 | return NULL; 47 | } 48 | // Make sure the property name is null terminated. 49 | if (prop->name[sizeof(prop->name) - 1] != 0) { 50 | return NULL; 51 | } 52 | // Properties are padded to a multiple of 4 bytes. 53 | size_t padded_size = (prop->size + 0x3) & ~0x3; 54 | *p += padded_size; 55 | if (*p > end) { 56 | if (*p - padded_size + prop->size == end) { 57 | // If the very last property does not have the requisite 58 | // padding, that's okay. 59 | *p = end; 60 | } else { 61 | return NULL; 62 | } 63 | } 64 | return prop; 65 | } 66 | 67 | struct devicetree_node 68 | devicetree_find_node_by_property(struct devicetree devicetree, 69 | const char *key, const char *value) { 70 | const uint8_t *p = (const uint8_t *)devicetree.data; 71 | const uint8_t *end = p + devicetree.size; 72 | // We will do a "flat" scan of the devicetree, ignoring the hierarchy. 73 | size_t remaining_nodes = 1; 74 | for (;;) { 75 | // If we run out of data or believe there should be no more nodes left in the tree, 76 | // then we're done. 77 | if (p >= end || remaining_nodes == 0) { 78 | goto done; 79 | } 80 | // Parse the node header. 81 | const struct _devicetree_node *node = (void *)p; 82 | p += sizeof(*node); 83 | if (p > end) { 84 | goto done; 85 | } 86 | // We will linearly scan this node's children in subsequent loops. 87 | remaining_nodes += node->n_children; 88 | // Scan this node's properties, searching for a match. 89 | uint32_t n_properties = node->n_properties; 90 | for (uint32_t i = 0; i < n_properties; i++) { 91 | // Parse the property. 92 | const struct _devicetree_property *prop = parse_property(&p, end); 93 | if (prop == NULL) { 94 | goto done; 95 | } 96 | // Check if we have a property match. Both the property name and the 97 | // property value must match. 98 | int key_cmp = strcmp(prop->name, key); 99 | if (key_cmp == 0) { 100 | int value_cmp = strncmp((char *)prop->data, value, prop->size); 101 | if (value_cmp == 0) { 102 | return (struct devicetree_node) { node, end }; 103 | } 104 | } 105 | } 106 | // Done with this node. 107 | remaining_nodes -= 1; 108 | } 109 | done: 110 | return (struct devicetree_node) { NULL, NULL }; 111 | } 112 | 113 | struct devicetree_property 114 | devicetree_node_get_property(struct devicetree_node node0, const char *key) { 115 | const uint8_t *p = (void *)node0.data; 116 | const uint8_t *end = (void *)node0.end; 117 | // Parse the node header. 118 | const struct _devicetree_node *node = (void *)p; 119 | p += sizeof(*node); 120 | if (p > end) { 121 | goto done; 122 | } 123 | // Scan this node's properties, searching for a match. 124 | uint32_t n_properties = node->n_properties; 125 | for (uint32_t i = 0; i < n_properties; i++) { 126 | // Parse the property. 127 | const struct _devicetree_property *prop = parse_property(&p, end); 128 | if (prop == NULL) { 129 | goto done; 130 | } 131 | // Check if we have a property match. 132 | int key_cmp = strcmp(prop->name, key); 133 | if (key_cmp == 0) { 134 | return (struct devicetree_property) { prop->data, prop->size }; 135 | } 136 | } 137 | done: 138 | return (struct devicetree_property) { NULL, 0 }; 139 | } 140 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/devicetree.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef DEVICETREE__H_ 21 | #define DEVICETREE__H_ 22 | 23 | #include 24 | #include 25 | 26 | // A flattened device tree. 27 | struct devicetree { 28 | const void *data; 29 | size_t size; 30 | }; 31 | 32 | // A device tree node header. Treat this type as opaque. 33 | struct devicetree_node { 34 | const void *data; 35 | const void *end; 36 | }; 37 | 38 | // A device tree property's data. 39 | struct devicetree_property { 40 | const void *data; 41 | size_t size; 42 | }; 43 | 44 | /* 45 | * devicetree_find_node_by_property 46 | * 47 | * Description: 48 | * Find a device tree node with a property with the specified property name and string value. 49 | */ 50 | struct devicetree_node devicetree_find_node_by_property(struct devicetree devicetree, 51 | const char *key, const char *value); 52 | 53 | /* 54 | * devicetree_node_valid 55 | * 56 | * Description: 57 | * Checks whether a returned devicetree_node represents a valid node. 58 | */ 59 | static inline bool 60 | devicetree_node_valid(struct devicetree_node node) { 61 | return node.data != NULL; 62 | } 63 | 64 | /* 65 | * devicetree_node_get_property 66 | * 67 | * Description: 68 | * Get the value of the specified property of a device tree node. 69 | */ 70 | struct devicetree_property devicetree_node_get_property(struct devicetree_node node, 71 | const char *key); 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/gdb_stub/gdb_cpu.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "gdb_cpu.h" 21 | 22 | #include "gdb_state.h" 23 | 24 | // ---- Checking CPU state ------------------------------------------------------------------------ 25 | 26 | bool 27 | valid_cpu_id(int cpu_id) { 28 | return (0 <= cpu_id && cpu_id < CPU_COUNT && ((1 << cpu_id) & gdb.cpu_mask)); 29 | } 30 | 31 | bool 32 | cpu_is_halted(int cpu_id) { 33 | // The cpu_id must be between 0 and CPU_COUNT - 1. 34 | uint32_t cpu_bit = 1 << cpu_id; 35 | return ((gdb.halted & cpu_bit) && (gdb.cpu_mask & cpu_bit)); 36 | } 37 | 38 | bool 39 | cpu_is_running(int cpu_id) { 40 | // The cpu_id must be between 0 and CPU_COUNT - 1. 41 | uint32_t cpu_bit = 1 << cpu_id; 42 | return (!(gdb.halted & cpu_bit) && (gdb.cpu_mask & cpu_bit)); 43 | } 44 | 45 | // ---- Interrupting and resuming CPUs ------------------------------------------------------------ 46 | 47 | // Call this function just after resuming a CPU to update internal state. 48 | static void 49 | gdb_cpu_resumed(int cpu_id) { 50 | gdb.halted &= ~(1 << cpu_id); 51 | gdb.cpu_debug[cpu_id].halted_watchpoint = INVALID_ADDRESS; 52 | gdb.cpu_debug[cpu_id].state = CPU_STATE_RUNNING; 53 | } 54 | 55 | void 56 | gdb_interrupt_cpu(int cpu_id) { 57 | if (cpu_is_running(cpu_id)) { 58 | gdb_stub_interrupt_cpu(cpu_id); 59 | } 60 | } 61 | 62 | void 63 | gdb_resume_cpu(int cpu_id) { 64 | if (cpu_is_halted(cpu_id)) { 65 | gdb_stub_resume_cpu(cpu_id); 66 | gdb_cpu_resumed(cpu_id); 67 | } 68 | } 69 | 70 | void 71 | gdb_interrupt() { 72 | for (int cpu_id = 0; cpu_id < CPU_COUNT; cpu_id++) { 73 | if (valid_cpu_id(cpu_id)) { 74 | gdb_interrupt_cpu(cpu_id); // Only if running. 75 | } 76 | } 77 | } 78 | 79 | void 80 | gdb_resume() { 81 | for (int cpu_id = 0; cpu_id < CPU_COUNT; cpu_id++) { 82 | if (valid_cpu_id(cpu_id)) { 83 | gdb_resume_cpu(cpu_id); // Only if halted. 84 | } 85 | } 86 | } 87 | 88 | void 89 | gdb_step_cpu(int cpu_id) { 90 | if (cpu_is_halted(cpu_id)) { 91 | gdb_stub_step_cpu(cpu_id); 92 | gdb_cpu_resumed(cpu_id); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/gdb_stub/gdb_cpu.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef GDB_CPU__H_ 21 | #define GDB_CPU__H_ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | // ---- Checking CPU state ------------------------------------------------------------------------ 28 | 29 | /* 30 | * valid_cpu_id 31 | * 32 | * Description: 33 | * Returns true if the CPU ID is valid. 34 | */ 35 | bool valid_cpu_id(int cpu_id); 36 | 37 | /* 38 | * cpu_is_halted 39 | * 40 | * Description: 41 | * Returns true if the specified CPU is halted. 42 | */ 43 | bool cpu_is_halted(int cpu_id); 44 | 45 | /* 46 | * cpu_is_running 47 | * 48 | * Description: 49 | * Returns true if the specified CPU is running. 50 | */ 51 | bool cpu_is_running(int cpu_id); 52 | 53 | // ---- Interrupting and resuming CPUs ------------------------------------------------------------ 54 | 55 | /* 56 | * gdb_interrupt_cpu 57 | * 58 | * Description: 59 | * Asynchronously interrupt a CPU, if it is running. 60 | */ 61 | void gdb_interrupt_cpu(int cpu_id); 62 | 63 | /* 64 | * gdb_resume_cpu 65 | * 66 | * Description: 67 | * Asynchronously resume a CPU, if it is halted. 68 | */ 69 | void gdb_resume_cpu(int cpu_id); 70 | 71 | /* 72 | * gdb_interrupt 73 | * 74 | * Description: 75 | * Asynchronously interrupt all running CPUs. 76 | */ 77 | void gdb_interrupt(void); 78 | 79 | /* 80 | * gdb_resume 81 | * 82 | * Description: 83 | * Asynchronously resume all halted CPUs. 84 | */ 85 | void gdb_resume(void); 86 | 87 | /* 88 | * gdb_step_cpu 89 | * 90 | * Description: 91 | * Asynchronously single-step a CPU, if it is halted. 92 | */ 93 | void gdb_step_cpu(int cpu_id); 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/gdb_stub/gdb_internal.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "gdb_internal.h" 21 | 22 | #include 23 | 24 | #include "gdb_rsp.h" 25 | #include "kernel_extern.h" 26 | 27 | // ---- Kernel symbols ---------------------------------------------------------------------------- 28 | 29 | KERNEL_EXTERN int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap); 30 | 31 | // ---- Formatting functions ---------------------------------------------------------------------- 32 | 33 | int 34 | hex_digit(char ch) { 35 | if ('0' <= ch && ch <= '9') { 36 | return ch - '0'; 37 | } else if ('a' <= ch && ch <= 'f') { 38 | return ch - 'a' + 0xa; 39 | } else if ('A' <= ch && ch <= 'F') { 40 | return ch - 'A' + 0xa; 41 | } 42 | return -1; 43 | } 44 | 45 | const char hex_char[16] = "0123456789abcdef"; 46 | 47 | void 48 | vsnprintf_cat(char *buffer, size_t size, char **cursor, const char *format, va_list ap) { 49 | // Write the formatted data to a stack buffer. This allows us to skip the whole 50 | // null-terminator deal altogether. 51 | char src_buffer[GDB_RSP_MAX_PACKET_SIZE + 1]; 52 | int len = vsnprintf(src_buffer, sizeof(src_buffer), format, ap); 53 | size_t written = len; 54 | // TODO: Ensure that no single print atom takes too much space! The vsnprintf() function 55 | // doesn't give us this flexibility, so we'll just silently drop characters :( In this 56 | // hack, if a single atom is larger than the source buffer size, we pretend that the atom 57 | // exactly filled the source buffer. Doing it this way (rather than only truncating if the 58 | // atom actually shows up in the output buffer) allows for consistency when windowing a 59 | // generated output string. 60 | if (written > sizeof(src_buffer)) { 61 | written = sizeof(src_buffer); 62 | } 63 | // Get copy parameters. 64 | char *dst = *cursor; 65 | char *src = src_buffer; 66 | size_t src_size = written; 67 | // Handle the case where the cursor is before the buffer so we need to discard some 68 | // characters from the source. 69 | if (dst < buffer) { 70 | size_t skip = buffer - dst; 71 | // Only skip up to the size of the source. 72 | if (skip >= src_size) { 73 | skip = src_size; 74 | } 75 | dst += skip; 76 | src += skip; 77 | src_size -= skip; 78 | } 79 | // Copy into dst as long as we're within the bounds of the output buffer and up to the size 80 | // of the source. 81 | if (buffer <= dst && dst < buffer + size) { 82 | size_t dst_size = buffer + size - dst; 83 | size_t copy_size = (dst_size < src_size ? dst_size : src_size); 84 | for (size_t i = 0; i < copy_size; i++) { 85 | dst[i] = src[i]; 86 | } 87 | } 88 | // Update the cursor. Even if we exited the copy loop early, we update the cursor past the 89 | // ends of the buffer as if the whole source were copied. 90 | *cursor = dst + src_size; 91 | } 92 | 93 | void 94 | snprintf_cat(char *buffer, size_t size, char **cursor, const char *format, ...) { 95 | va_list ap; 96 | va_start(ap, format); 97 | vsnprintf_cat(buffer, size, cursor, format, ap); 98 | va_end(ap); 99 | } 100 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/gdb_stub/gdb_internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef GDB_INTERNAL__H_ 21 | #define GDB_INTERNAL__H_ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | /* 28 | * hex_digit 29 | * 30 | * Description: 31 | * Convert a character representing a hexadecimal digit to its numeric value or -1. 32 | */ 33 | int hex_digit(char ch); 34 | 35 | /* 36 | * hex_char 37 | * 38 | * Description: 39 | * A table converting an integer between 0 and 15 to the corresponding hexadecimal digit. 40 | */ 41 | extern const char hex_char[16]; 42 | 43 | /* 44 | * snprintf_cat 45 | * 46 | * Description: 47 | * Print a formatted string to a buffer without null-terminating. The cursor specifies where 48 | * in or before the buffer printing should start. On return, cursor is updated to point to 49 | * where in or before the buffer printing would have ended if the buffer were infinite in both 50 | * directions. Only formatted data that actually falls within the true bounds of the buffer 51 | * will actually be written. 52 | * 53 | * Due to the current implementation of this function, correct behavior is only guaranteed if 54 | * at most 1024 characters are printed in a single call. 55 | */ 56 | void snprintf_cat(char *buffer, size_t size, char **cursor, const char *format, ...); 57 | 58 | /* 59 | * vsnprintf_cat 60 | * 61 | * Description: 62 | * See snprintf_cat(). 63 | */ 64 | void vsnprintf_cat(char *buffer, size_t size, char **cursor, const char *format, va_list ap); 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/gdb_stub/gdb_packets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef GDB_PACKETS__H_ 21 | #define GDB_PACKETS__H_ 22 | 23 | #include 24 | #include 25 | 26 | /* 27 | * gdb_process_packet 28 | * 29 | * Description: 30 | * Handle a GDB RSP packet and send any replies. The supplied data buffer is used both for 31 | * parsing the request and building the reply, so it must be of capacity 32 | * GDB_RSP_MAX_PACKET_SIZE. 33 | */ 34 | void gdb_process_packet(void *data, size_t size); 35 | 36 | /* 37 | * gdb_process_cpu_halts 38 | * 39 | * Description: 40 | * Handle any CPU halts and send any replies. 41 | */ 42 | void gdb_process_cpu_halts(uint32_t halted_mask); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/gdb_stub/gdb_platform.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef GDB_PLATFORM__H_ 21 | #define GDB_PLATFORM__H_ 22 | 23 | #include 24 | 25 | // The maximum number of supported CPUs. The actual number of CPUs may be less than this. 26 | #define CPU_COUNT 6 27 | 28 | // The packed register definitions. This is the struct used to transfer registers between GDB and 29 | // the stub. 30 | struct __attribute__((packed)) gdb_registers { 31 | union { 32 | uint64_t x; 33 | uint32_t w; 34 | } x[31]; 35 | uint64_t sp; 36 | uint64_t pc; 37 | uint32_t cpsr; 38 | union { 39 | uint64_t q[2]; 40 | double d; 41 | float s; 42 | } v[32]; 43 | uint32_t fpsr; 44 | uint32_t fpcr; 45 | }; 46 | 47 | // A type for register IDs. 48 | typedef uint16_t reg_id_t; 49 | 50 | // An invalid register ID. 51 | #define INVALID_REG_ID ((reg_id_t)(-1)) 52 | 53 | // Information describing a register to GDB. 54 | struct gdb_register_info { 55 | const char *name; // The register's name. 56 | const char *altname; // An alternative name for the register. 57 | uint8_t generic; // The GDB generic name of this register. 58 | uint8_t type; // The GDB type of this register. 59 | uint8_t encoding; // The GDB encoding of this register. 60 | uint8_t format; // The GDB format of this register. 61 | uint8_t group; // The GDB group of this register. 62 | uint8_t set; // The register set to which this register belongs. 63 | uint16_t offset; // The offset in the struct gdb_registers. 64 | uint16_t bitsize; // The size of this register in bits. 65 | reg_id_t ehframe_reg; // The exception handler frame register number. 66 | reg_id_t dwarf_reg; // The DWARF register number. 67 | reg_id_t value_regs[4]; // A list of registers that contain this register. 68 | reg_id_t invalidate_regs[4]; // A list of registers to invalidate if this one is set. 69 | }; 70 | 71 | // The list of gdb_register_info structs. 72 | extern const struct gdb_register_info gdb_register_info[]; 73 | extern const unsigned gdb_register_count; 74 | 75 | // Lookup tables for the string values of the generic, type, encoding, format, and group fields. 76 | extern const char *const gdb_register_generic_name[]; 77 | extern const char *const gdb_register_type_name[]; 78 | extern const char *const gdb_register_encoding_name[]; 79 | extern const char *const gdb_register_format_name[]; 80 | extern const char *const gdb_register_group_name[]; 81 | 82 | // Information describing a register set to GDB. 83 | struct gdb_register_set_info { 84 | const char *description; 85 | }; 86 | 87 | // The list of register sets. 88 | extern const struct gdb_register_set_info gdb_register_set_info[]; 89 | extern const unsigned gdb_register_set_count; 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/gdb_stub/gdb_rsp.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef GDB_RSP__H_ 21 | #define GDB_RSP__H_ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | // The maximum size of the data in a packet. This is calculated such that it is big enough to hold 28 | // the "g" packet (788 bytes of register data hex-encoded to a 0x628 byte packet) but small enough 29 | // that it is guaranteed that the RSP ACK and RSP-encoded packet will still fit within the 30 | // 0x1000 byte USB transport buffer. 31 | #define GDB_RSP_MAX_PACKET_SIZE 0x700 32 | 33 | /* 34 | * gdb_rsp_send_packet 35 | * 36 | * Description: 37 | * Send a packet to GDB. 38 | */ 39 | void gdb_rsp_send_packet(const void *data, size_t size); 40 | 41 | /* 42 | * gdb_rsp_send_notification 43 | * 44 | * Description: 45 | * Send a notification packet to GDB. 46 | */ 47 | void gdb_rsp_send_notification(const void *data, size_t size); 48 | 49 | /* 50 | * gdb_rsp_receive_packet 51 | * 52 | * Description: 53 | * Receive a packet from GDB. 54 | */ 55 | bool gdb_rsp_receive_packet(void *data, size_t *size); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/gdb_stub/gdb_state.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef GDB_STATE__H_ 21 | #define GDB_STATE__H_ 22 | 23 | #include 24 | 25 | #include "gdb_stub.h" 26 | 27 | // ---- Definitions ------------------------------------------------------------------------------- 28 | 29 | // An identifier for an invalid CPU. -1 is reserved to mean "all CPUs" or "unknown". 30 | #define INVALID_CPU (-2) 31 | 32 | // An invalid address. 33 | #define INVALID_ADDRESS ((uint64_t)(-1)) 34 | 35 | // The possible CPU states. 36 | enum { 37 | CPU_STATE_RUNNING, 38 | CPU_STATE_HALTED, 39 | CPU_STATE_HALTED_HARDWARE_BREAKPOINT, 40 | CPU_STATE_HALTED_HARDWARE_WATCHPOINT, 41 | CPU_STATE_HALTED_SINGLE_STEP, 42 | }; 43 | 44 | // A struct holding the GDB stub's state. 45 | struct gdb_stub_state { 46 | // The mask of available CPUs being debugged. 47 | uint32_t cpu_mask; 48 | // The mask of CPUs currently halted. 49 | uint32_t halted; 50 | // The current CPU. 51 | int current_cpu; 52 | // CPU debug state. 53 | struct { 54 | // The current CPU state. This indicates why the CPU is halted. 55 | int state; 56 | // The watchpoint address for which this CPU has halted. If INVALID_ADDRESS, then 57 | // the CPU is not currently halted because of a watchpoint. 58 | uint64_t halted_watchpoint; 59 | } cpu_debug[6]; 60 | // The mask of CPUs that have just halted and need processing. 61 | uint32_t process_halted; 62 | // State for all-stop mode. 63 | struct { 64 | // True if GDB sent us a packet that requires we send a stop-reply, but we've 65 | // deferred sending the reply waiting for the appropriate stop to occur. 66 | bool stop_reply_deferred; 67 | // The first CPU that generated an "interesting" stop event (breakpoint or 68 | // watchpoint). This is what we'll try to report to LLDB, since reporting a stop 69 | // event for the current CPU when nothing is happening there seems to confuse LLDB 70 | // and make it loop single-stepping. 71 | int first_stop; 72 | } all_stop; 73 | // State for non-stop mode. 74 | struct { 75 | // Whether non-stop mode is currently enabled. 76 | bool enabled; 77 | // The mask of CPUs that GDB has confirmed it knows are halted. 78 | uint32_t stopped; 79 | // A mask of CPUs still left to report in non-stop mode. 80 | uint32_t queue; 81 | // A mask for the CPU for which there is an outstanding stop notification/packet 82 | // that has not yet been confirmed by a "vStopped" packet. This will be OR'd into 83 | // stopped once GDB ack's the packet. 84 | uint32_t pending; 85 | } non_stop; 86 | // Whether to send error strings with error packets. Controlled by QEnableErrorStrings. 87 | bool error_strings; 88 | // Whether to include a list of threads in stop reply packets. Controlled by 89 | // QListThreadsInStopReply. 90 | bool list_threads_in_stop_reply; 91 | // The main executable (kernel) Mach-O. 92 | const struct mach_header_64 *mach_header; 93 | // The number of available hardware watchpoints. We only need this for the 94 | // qWatchpointSupportInfo packet, which in turn is only needed so LLDB will respect 95 | // watchpoint_exceptions_received:before, which is needed so that LLDB will correctly 96 | // handle watchpoints. 97 | unsigned hardware_watchpoint_count; 98 | }; 99 | 100 | // The GDB state. 101 | extern struct gdb_stub_state gdb; 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/gdb_stub/gdb_stub.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "gdb_stub.h" 21 | 22 | #include 23 | 24 | #include "gdb_internal.h" 25 | #include "gdb_packets.h" 26 | #include "gdb_rsp.h" 27 | #include "gdb_state.h" 28 | 29 | // Define the main GDB state. 30 | struct gdb_stub_state gdb; 31 | 32 | void 33 | gdb_stub_init(uint32_t cpu_mask, uint32_t halted_mask) { 34 | halted_mask &= cpu_mask; 35 | gdb.cpu_mask = cpu_mask; 36 | gdb.halted = halted_mask; 37 | gdb.current_cpu = -1; // No current CPU. 38 | for (int cpu_id = 0; cpu_id < CPU_COUNT; cpu_id++) { 39 | gdb.cpu_debug[cpu_id].halted_watchpoint = INVALID_ADDRESS; 40 | int state = CPU_STATE_RUNNING; 41 | if (halted_mask & (1 << cpu_id)) { 42 | state = CPU_STATE_HALTED; 43 | } 44 | gdb.cpu_debug[cpu_id].state = state; 45 | } 46 | gdb.process_halted = 0; 47 | gdb.all_stop.stop_reply_deferred = false; 48 | gdb.all_stop.first_stop = INVALID_CPU; 49 | gdb.non_stop.enabled = false; 50 | gdb.non_stop.stopped = 0; 51 | gdb.non_stop.queue = 0; 52 | gdb.non_stop.pending = 0; 53 | gdb.error_strings = false; 54 | gdb.list_threads_in_stop_reply = false; 55 | gdb.mach_header = NULL; 56 | gdb.hardware_watchpoint_count = 0; 57 | } 58 | 59 | void 60 | gdb_stub_set_mach_header(const struct mach_header_64 *mach_header) { 61 | gdb.mach_header = mach_header; 62 | } 63 | 64 | void 65 | gdb_stub_set_hardware_watchpoint_count(unsigned hardware_watchpoint_count) { 66 | gdb.hardware_watchpoint_count = hardware_watchpoint_count; 67 | } 68 | 69 | // Record that a halt has taken place. 70 | static void 71 | gdb_stub_record_halt(int cpu_id) { 72 | gdb.halted |= (1 << cpu_id); 73 | gdb.process_halted |= (1 << cpu_id); 74 | // If we are in all-stop mode, and we have a deferred stop reply, and this is the first 75 | // stop we've observed, record it and switch to this CPU. 76 | if (!gdb.non_stop.enabled 77 | && gdb.all_stop.stop_reply_deferred 78 | && gdb.all_stop.first_stop == INVALID_CPU) { 79 | gdb.all_stop.first_stop = cpu_id; 80 | gdb.current_cpu = cpu_id; 81 | } 82 | } 83 | 84 | void 85 | gdb_stub_hit_hardware_breakpoint(int cpu_id) { 86 | gdb_stub_record_halt(cpu_id); 87 | gdb.cpu_debug[cpu_id].state = CPU_STATE_HALTED_HARDWARE_BREAKPOINT; 88 | } 89 | 90 | void 91 | gdb_stub_hit_hardware_watchpoint(int cpu_id, uint64_t address) { 92 | gdb_stub_record_halt(cpu_id); 93 | gdb.cpu_debug[cpu_id].halted_watchpoint = address; 94 | gdb.cpu_debug[cpu_id].state = CPU_STATE_HALTED_HARDWARE_WATCHPOINT; 95 | } 96 | 97 | void 98 | gdb_stub_did_step(int cpu_id) { 99 | gdb_stub_record_halt(cpu_id); 100 | gdb.cpu_debug[cpu_id].state = CPU_STATE_HALTED_SINGLE_STEP; 101 | } 102 | 103 | void 104 | gdb_stub_did_halt(int cpu_id) { 105 | gdb_stub_record_halt(cpu_id); 106 | gdb.cpu_debug[cpu_id].state = CPU_STATE_HALTED; 107 | } 108 | 109 | void 110 | gdb_stub_process_halts(uint32_t halted_mask) { 111 | if (halted_mask != gdb.halted) { 112 | // If we ever get out-of-sync, send a debugging message. This will likely break the 113 | // connection with the debugger. 114 | gdb_stub_log("%s: halted_mask(%x) != gdb.halted(%x)", 115 | __func__, halted_mask, gdb.halted); 116 | } 117 | if (gdb.process_halted != 0) { 118 | gdb_process_cpu_halts(gdb.process_halted); 119 | gdb.process_halted = 0; 120 | } 121 | } 122 | 123 | void 124 | gdb_stub_packet() { 125 | char packet[GDB_RSP_MAX_PACKET_SIZE]; 126 | size_t size; 127 | // Try to receive the packet. 128 | bool ok = gdb_rsp_receive_packet(packet, &size); 129 | if (!ok) { 130 | return; 131 | } 132 | // Dispatch the packet to the appropriate handler. 133 | gdb_process_packet(packet, size); 134 | } 135 | 136 | void 137 | gdb_stub_log(const char *message, ...) { 138 | char buffer[GDB_RSP_MAX_PACKET_SIZE]; 139 | char *p = buffer; 140 | va_list ap; 141 | va_start(ap, message); 142 | vsnprintf_cat(buffer, sizeof(buffer), &p, message, ap); 143 | va_end(ap); 144 | gdb_stub_serial_write(buffer, p - buffer); 145 | } 146 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/gdb_stub/gdb_stub.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef GDB_STUB__H_ 21 | #define GDB_STUB__H_ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | // ---- Platform configuration -------------------------------------------------------------------- 29 | 30 | #include "gdb_platform.h" 31 | 32 | // ---- Functions needed by the GDB stub ---------------------------------------------------------- 33 | 34 | // Reset state to prepare for a new connection. 35 | void gdb_stub_reset_state(void); 36 | 37 | // Read any pending data sent from GDB to the GDB stub. 38 | size_t gdb_stub_serial_read(void *data, size_t size); 39 | 40 | // Write data generated by the GDB stub out to GDB. 41 | size_t gdb_stub_serial_write(const void *data, size_t size); 42 | 43 | // Called when the GDB stub wants to set or clear a hardware breakpoint. 44 | bool gdb_stub_set_hardware_breakpoint(uint64_t address); 45 | bool gdb_stub_clear_hardware_breakpoint(uint64_t address); 46 | 47 | // Called when the GDB stub wants to set or clear a hardware watchpoint. The type parameter 48 | // specifies the type of watchpoint: 'r' for read, 'w' for write, or 'a' for access. 49 | bool gdb_stub_set_hardware_watchpoint(uint64_t address, size_t size, char type); 50 | bool gdb_stub_clear_hardware_watchpoint(uint64_t address, size_t size, char type); 51 | 52 | // Called when the GDB stub wants to interrupt the specified CPU. The function should not wait for 53 | // the CPU to halt. 54 | void gdb_stub_interrupt_cpu(int cpu_id); 55 | 56 | // Called when the GDB stub wants to resume the specified CPU. The function should not wait for the 57 | // CPU to resume. 58 | void gdb_stub_resume_cpu(int cpu_id); 59 | 60 | // Called when the GDB stub wants to single-step the specified CPU. The function should not wait 61 | // for the CPU to resume or to halt. 62 | void gdb_stub_step_cpu(int cpu_id); 63 | 64 | // Called when the GDB stub wants to read the PC register on a specific CPU. 65 | uint64_t gdb_stub_cpu_pc(int cpu_id); 66 | 67 | // Called when the GDB stub wants to read the registers on a specific CPU. 68 | void gdb_stub_read_registers(int cpu_id, struct gdb_registers *registers); 69 | 70 | // Called when the GDB stub wants to write the registers on a specific CPU. 71 | void gdb_stub_write_registers(int cpu_id, const struct gdb_registers *registers); 72 | 73 | // Called when the GDB stub wants to read memory from a specific CPU. 74 | size_t gdb_stub_read_memory(int cpu_id, uint64_t address, void *data, size_t length); 75 | 76 | // Called when the GDB stub wants to write memory from a specific CPU. 77 | size_t gdb_stub_write_memory(int cpu_id, uint64_t address, const void *data, size_t length); 78 | 79 | // Called when the GDB stub wants to allocate memory with the specified permissions. 80 | uint64_t gdb_stub_allocate_jit_memory(size_t size, int perm); 81 | 82 | // Called when the GDB stub wants to deallocate memory previously allocated with 83 | // gdb_stub_allocate_jit_memory(). 84 | bool gdb_stub_deallocate_jit_memory(uint64_t address); 85 | 86 | // ---- The GDB stub entry points ----------------------------------------------------------------- 87 | 88 | // Call this once at the beginning to initialize the GDB stub state. 89 | void gdb_stub_init(uint32_t cpu_mask, uint32_t halted_mask); 90 | 91 | // Call this once to initialize the Mach-O header of the main kernel. 92 | void gdb_stub_set_mach_header(const struct mach_header_64 *mach_header); 93 | 94 | // Call this once to set the number of available hardware watchpoints. 95 | void gdb_stub_set_hardware_watchpoint_count(unsigned hardware_watchpoint_count); 96 | 97 | // Call this when a CPU halts due to a hardware breakpoint. This function simply records the 98 | // breakpoint information in the GDB stub, it does not begin processing the event. 99 | void gdb_stub_hit_hardware_breakpoint(int cpu_id); 100 | 101 | // Call this when a CPU halts due to a hardware watchpoint. This function simply records the 102 | // watchpoint information in the GDB stub, it does not begin processing the event. 103 | void gdb_stub_hit_hardware_watchpoint(int cpu_id, uint64_t address); 104 | 105 | // Call this function when a CPU halts because it completed a single-step operation. This function 106 | // simply records the step information in the GDB stub, it does not begin processing the event. 107 | void gdb_stub_did_step(int cpu_id); 108 | 109 | // Call this function when a CPU halts because it was interrupted. This function simply records the 110 | // halt information in the GDB stub, it does not begin processing the event. 111 | void gdb_stub_did_halt(int cpu_id); 112 | 113 | // Call this when information about all current halts has been recorded with the 114 | // gdb_stub_hit_hardware_breakpoint(), ..., gdb_stub_did_halt() functions and the GDB stub should 115 | // now process that information and act accordingly. 116 | // The halted_mask argument is a mask of the CPUs that are halted. This is a debugging check for 117 | // the GDB stub that it is managing state correctly. 118 | void gdb_stub_process_halts(uint32_t halted_mask); 119 | 120 | // Call this when a packet becomes available over serial. 121 | void gdb_stub_packet(void); 122 | 123 | // This function can be called to log a critical event over serial. It may interfere with the 124 | // normal operation of the debugger, so only do so for debugging critical issues. 125 | void gdb_stub_log(const char *message, ...); 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/if_value.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef IF_VALUE 21 | 22 | /* 23 | * IF_VALUE(_x_)(_y_)(_z_) 24 | * 25 | * Description: 26 | * If _x_ is not empty, produces _y_, else produces _z_. Do not use or redefine macros 27 | * beginning with _IF_VALUE_. 28 | */ 29 | 30 | // _IF_VALUE__SECOND() returns the second argument. 31 | #define _IF_VALUE__SECOND(_a, _b, ...) _b 32 | // _IF_VALUE__SECOND_2() does the same as _IF_VALUE__SECOND() after an additional round of 33 | // parameter expansion. 34 | #define _IF_VALUE__SECOND_2(_a, _b, ...) _IF_VALUE__SECOND(_a, _b, __VA_ARGS__) 35 | // _IF_VALUE__CHECK__IF_VALUE__IS_EMPTY() is used by _IF_VALUE__CHECK to test whether the argument 36 | // is _IF_VALUE__IS_EMPTY and return _IF_VALUE__IS_EMPTY if so. 37 | #define _IF_VALUE__CHECK__IF_VALUE__IS_EMPTY() ~, _IF_VALUE__IS_EMPTY 38 | // _IF_VALUE__CHECK() produces _IF_VALUE__IS_EMPTY if _first is _IF_VALUE__IS_EMPTY and 39 | // _IF_VALUE__NOT_EMPTY otherwise. 40 | #define _IF_VALUE__CHECK(_first, ...) _IF_VALUE__SECOND_2(_IF_VALUE__CHECK_ ## _first (), _IF_VALUE__NOT_EMPTY, ~) 41 | // _IF_VALUE__CHECK_2() does the same as _IF_VALUE__CHECK() after an additional round of parameter 42 | // expansion. 43 | #define _IF_VALUE__CHECK_2(_first, ...) _IF_VALUE__CHECK(_first, __VA_ARGS__) 44 | // _IF_VALUE__IS_EMPTY takes 2 groups of parentheses and returns the unwrapped value of the first 45 | // group. 46 | #define _IF_VALUE__IS_EMPTY(...) _IF_VALUE__IS_EMPTY_1 47 | #define _IF_VALUE__IS_EMPTY_1(...) __VA_ARGS__ 48 | // _IF_VALUE__NOT_EMPTY takes 2 groups of parentheses and returns the unwrapped value of the second 49 | // group. 50 | #define _IF_VALUE__NOT_EMPTY(...) __VA_ARGS__ _IF_VALUE__NOT_EMPTY_1 51 | #define _IF_VALUE__NOT_EMPTY_1(...) /* nothing */ 52 | // IF_VALUE() produces _IF_VALUE__IS_EMPTY if _maybe_empty is empty and _IF_VALUE__NOT_EMPTY 53 | // otherwise. 54 | #define IF_VALUE(_maybe_empty) _IF_VALUE__CHECK_2(_IF_VALUE__CHECK _maybe_empty (_IF_VALUE__IS_EMPTY, ~), ~) 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/jit_heap.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "jit_heap.h" 21 | 22 | #include "page_table.h" 23 | #include "primitives.h" 24 | 25 | // ---- JIT heap internals ------------------------------------------------------------------------ 26 | 27 | #define PAGE_SIZE 0x4000 28 | 29 | #define JIT_HEAP_PAGES (JIT_HEAP_SIZE / PAGE_SIZE) 30 | 31 | // The JIT heap. Since we will be setting permissions on individual allocations, the allocation 32 | // granularity is a single page. This means that the jit heap itself must be page-aligned. 33 | static uint8_t *jit_heap; 34 | 35 | _Static_assert(JIT_HEAP_PAGES < (1uL << (sizeof(uint8_t) * 8)), 36 | "struct jit_heap_page: The number of JIT heap pages must fit in a uint8_t"); 37 | 38 | // For each page in the JIT heap, we have a small structure describing the allocation to which that 39 | // page belongs. 40 | struct jit_heap_page { 41 | // The index of the first page of this allocation. 42 | uint8_t alloc_index; 43 | // The number of allocated pages in this allocation. 44 | uint8_t alloc_count; 45 | // The VM permissions of the page (rwx). 46 | uint8_t vm_permissions; 47 | }; 48 | 49 | // The information for each heap page. 50 | static struct jit_heap_page jit_heap_pages[JIT_HEAP_PAGES] = {}; 51 | 52 | // Verifies that the specified address is part of the JIT heap. 53 | static bool 54 | verify_jit_heap_address(void *address) { 55 | uint8_t *p = address; 56 | return (jit_heap <= p && p < jit_heap + JIT_HEAP_SIZE); 57 | } 58 | 59 | // Set the alloc_index and alloc_count fields of the pages in the allocation. 60 | static void 61 | claim_jit_heap_allocation(size_t alloc_index, size_t alloc_count) { 62 | struct jit_heap_page *page = &jit_heap_pages[alloc_index]; 63 | for (size_t i = 0; i < alloc_count; i++) { 64 | page->alloc_index = alloc_index; 65 | page->alloc_count = alloc_count; 66 | page++; 67 | } 68 | } 69 | 70 | // Find a region in the heap large enough for the specified allocation. The jit_heap_page structs 71 | // for all pages in the allocation have the alloc_index and alloc_count fields initialized. The 72 | // jit_heap_page struct for the first page is returned. 73 | struct jit_heap_page * 74 | reserve_jit_heap_allocation(size_t page_count) { 75 | // Find a stretch of unallocated pages of the requisite size. 76 | size_t alloc_index = 0; 77 | size_t alloc_count = 0; 78 | for (size_t page_index = 0; page_index < JIT_HEAP_PAGES; page_index++) { 79 | if (jit_heap_pages[page_index].alloc_count == 0) { 80 | // This one is free. Bump the alloc_count. 81 | if (alloc_count == 0) { 82 | alloc_index = page_index; 83 | } 84 | alloc_count++; 85 | if (alloc_count >= page_count) { 86 | claim_jit_heap_allocation(alloc_index, alloc_count); 87 | return &jit_heap_pages[alloc_index]; 88 | } 89 | } else { 90 | // This one is allocated. Reset our count. 91 | alloc_count = 0; 92 | } 93 | } 94 | return NULL; 95 | } 96 | 97 | // Get the address of the start of the allocation containing this page. 98 | static void * 99 | jit_heap_allocation_address(size_t alloc_index) { 100 | return &jit_heap[alloc_index * PAGE_SIZE]; 101 | } 102 | 103 | // Find the JIT heap allocation starting at this address. 104 | struct jit_heap_page * 105 | find_jit_heap_allocation(void *address) { 106 | if (!verify_jit_heap_address(address)) { 107 | return NULL; 108 | } 109 | if ((((uintptr_t) address) & (PAGE_SIZE - 1)) != 0) { 110 | return NULL; 111 | } 112 | size_t page_index = ((uint8_t *) address - jit_heap) / PAGE_SIZE; 113 | struct jit_heap_page *page = &jit_heap_pages[page_index]; 114 | if (page->alloc_index != page_index) { 115 | return NULL; 116 | } 117 | if (page->alloc_count == 0) { 118 | return NULL; 119 | } 120 | return page; 121 | } 122 | 123 | static void 124 | clear_jit_heap_page(struct jit_heap_page *page) { 125 | page->alloc_index = 0; 126 | page->alloc_count = 0; 127 | page->vm_permissions = 0; 128 | } 129 | 130 | static void 131 | clear_jit_heap_allocation(struct jit_heap_page *page) { 132 | size_t alloc_index = page->alloc_index; 133 | size_t alloc_count = page->alloc_count; 134 | bzero(&jit_heap[alloc_index], alloc_count * PAGE_SIZE); 135 | for (size_t i = 0; i < alloc_count; i++) { 136 | clear_jit_heap_page(page); 137 | page++; 138 | } 139 | } 140 | 141 | // ---- JIT heap API ------------------------------------------------------------------------------ 142 | 143 | void 144 | jit_heap_init(void *heap) { 145 | jit_heap = heap; 146 | jit_heap_reset(); 147 | } 148 | 149 | void 150 | jit_heap_reset() { 151 | for (size_t i = 0; i < JIT_HEAP_PAGES; i++) { 152 | clear_jit_heap_page(&jit_heap_pages[i]); 153 | } 154 | } 155 | 156 | void * 157 | jit_heap_allocate(size_t size, int vm_prot) { 158 | size_t page_count = (size + PAGE_SIZE - 1) / PAGE_SIZE; 159 | struct jit_heap_page *page = reserve_jit_heap_allocation(page_count); 160 | if (page == NULL) { 161 | return NULL; 162 | } 163 | size_t alloc_index = page->alloc_index; 164 | size_t alloc_count = page->alloc_count; 165 | page_table_sync(); 166 | for (size_t i = 0; i < alloc_count; i++) { 167 | void *heap_page = jit_heap_allocation_address(alloc_index + i); 168 | // We'll set the page for maximum permissions, regardless of what the user asked 169 | // for. 170 | ttbr1_page_table_set_page_attributes(heap_page, 1, 0, SH_OUTER, AP_RWNA, 171 | ATTR_Normal_WriteBack); 172 | } 173 | page_table_sync(); 174 | return jit_heap_allocation_address(alloc_index); 175 | } 176 | 177 | bool 178 | jit_heap_deallocate(void *address) { 179 | struct jit_heap_page *page = find_jit_heap_allocation(address); 180 | if (page == NULL) { 181 | return false; 182 | } 183 | clear_jit_heap_allocation(page); 184 | return true; 185 | } 186 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/jit_heap.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef JIT_HEAP__H_ 21 | #define JIT_HEAP__H_ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | // The size of the JIT heap. 28 | #define JIT_HEAP_SIZE (64 * 0x4000) 29 | 30 | /* 31 | * jit_heap_init 32 | * 33 | * Description: 34 | * Initialize the JIT heap to use the specified allocation. 35 | */ 36 | void jit_heap_init(void *heap); 37 | 38 | /* 39 | * jit_heap_reset 40 | * 41 | * Description: 42 | * Reset the JIT heap, freeing all outstanding allocations. 43 | */ 44 | void jit_heap_reset(void); 45 | 46 | /* 47 | * jit_heap_allocate 48 | * 49 | * Description: 50 | * Allocate memory from the JIT heap with the specified permissions. 51 | */ 52 | void *jit_heap_allocate(size_t size, int vm_prot); 53 | 54 | /* 55 | * jit_heap_deallocate 56 | * 57 | * Description: 58 | * Deallocate the specified JIT heap allocation. 59 | */ 60 | bool jit_heap_deallocate(void *address); 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/kernel_extern.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef KERNEL_EXTERN__H_ 21 | #define KERNEL_EXTERN__H_ 22 | 23 | // Declare any kernel variables as KERNEL_EXTERN and include the static addresses in the symbols 24 | // files. 25 | #define KERNEL_EXTERN extern __attribute__((weak_import)) 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/page_table.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef PAGE_TABLE__H_ 21 | #define PAGE_TABLE__H_ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | // ---- Kernel virtual to physical translation ---------------------------------------------------- 28 | 29 | /* 30 | * kernel_virtual_to_physical 31 | * 32 | * Description: 33 | * Translate the specified kernel virtual address into the corresponding physical address. The 34 | * kernel's shared TTBR1_EL1 is used for translation. 35 | */ 36 | uint64_t kernel_virtual_to_physical(uint64_t kvaddr); 37 | 38 | // ---- Cacheing ---------------------------------------------------------------------------------- 39 | 40 | /* 41 | * cache_invalidate 42 | * 43 | * Description: 44 | * Invalidate cache lines for the specified virtual address range. 45 | */ 46 | void cache_invalidate(void *address, size_t size); 47 | 48 | /* 49 | * cache_clean_and_invalidate 50 | * 51 | * Description: 52 | * Clean and invalidate cache lines for the specified virtual address range. 53 | */ 54 | void cache_clean_and_invalidate(void *address, size_t size); 55 | 56 | // ---- Memory mapping via TTBR0_EL1 -------------------------------------------------------------- 57 | 58 | /* 59 | * ttbr0_page_tables_init 60 | * 61 | * Description: 62 | * Set up TTBR0_EL1 for mapping physical memory. This mapping is only present on this CPU 63 | * core, and thus will not be accessible to the rest of the kernel. 64 | * 65 | * This function should only be called once this thread has been pinned to the CPU, since if 66 | * we move to another CPU core then the TTBR0_EL1 register will no longer point to our page 67 | * tables. 68 | */ 69 | void ttbr0_page_tables_init(void); 70 | 71 | #define SH_NONE 0x0 72 | #define SH_OUTER 0x2 73 | #define SH_INNER 0x3 74 | 75 | #define AP_RWNA 0x0 76 | #define AP_RWRW 0x1 77 | #define AP_RONA 0x2 78 | #define AP_RORO 0x3 79 | 80 | #define ATTR_Normal_WriteBack 0 81 | #define ATTR_Normal_NonCacheable 1 82 | #define ATTR_Normal_WriteThrough 2 83 | #define ATTR_Device_nGnRnE 3 84 | #define ATTR_Device_nGnRE 5 85 | 86 | /* 87 | * ttbr0_map 88 | * 89 | * Description: 90 | * Map the specified physical address range. The page is mapped for all access and with the 91 | * specified attributes. 92 | * 93 | * Due to how the mapping is implemented, a maximum of 4095 pages can be mapped 94 | * simultaneously. 95 | */ 96 | void *ttbr0_map(uint64_t paddr, size_t size, unsigned attr); 97 | 98 | /* 99 | * ttbr0_map_io 100 | * 101 | * Description: 102 | * A convenience wrapper around ttbr0_map() for mapping device memory suitable for MMIO. 103 | */ 104 | static inline void * 105 | ttbr0_map_io(uint64_t paddr, size_t size) { 106 | return ttbr0_map(paddr, size, ATTR_Device_nGnRnE); 107 | } 108 | 109 | /* 110 | * ttbr0_unmap 111 | * 112 | * Description: 113 | * Unmap a mapping established via ttbr0_map(). 114 | */ 115 | void ttbr0_unmap(void *address, size_t size); 116 | 117 | // ---- Accessing physical memory ----------------------------------------------------------------- 118 | 119 | /* 120 | * physical_read_64 121 | * 122 | * Description: 123 | * Read a 64-bit value from physical memory. 124 | */ 125 | uint64_t physical_read_64(uint64_t paddr); 126 | 127 | /* 128 | * physical_write_64 129 | * 130 | * Description: 131 | * Write a 64-bit value to physical memory. 132 | */ 133 | void physical_write_64(uint64_t paddr, uint64_t value); 134 | 135 | // ---- Modifying page tables --------------------------------------------------------------------- 136 | 137 | /* 138 | * ttbr1_page_table_set_page_attributes 139 | * 140 | * Description: 141 | * Set attributes on the TTBR1_EL1 translation table entry mapping the specified page. 142 | */ 143 | bool ttbr1_page_table_set_page_attributes(void *page, 144 | unsigned uxn, unsigned pxn, unsigned sh, unsigned ap, unsigned attr); 145 | 146 | /* 147 | * ttbr1_page_table_swap_physical_page 148 | * 149 | * Description: 150 | * Modify the TTBR1_EL1 page tables so that all virtual mappings of the specified physical 151 | * page instead refer to another physical page. 152 | */ 153 | size_t ttbr1_page_table_swap_physical_page(uint64_t paddr_old, uint64_t paddr_new); 154 | 155 | /* 156 | * page_table_sync() 157 | * 158 | * Description: 159 | * Ensure that changes to the page table become visible. 160 | */ 161 | void page_table_sync(void); 162 | 163 | #endif 164 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/primitives.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | 21 | #include 22 | #include 23 | 24 | // These functions and globals are used in compiler-generated code. We'd prefer not to use the 25 | // kernel's versions, since calling kernel functions and reading kernel variables could interfere 26 | // with the operation of the debugger. (When using per-core hardware breakpoints and watchpoints 27 | // this will obviously be fine, but it could be problematic if the debugger rewrites kernel 28 | // memory.) 29 | 30 | uint64_t __stack_chk_guard = 0x1122334455667788; 31 | 32 | void 33 | __stack_chk_fail() { 34 | for (;;) {} 35 | } 36 | 37 | void 38 | bzero(void *s, size_t n) { 39 | uint8_t *p = s; 40 | for (size_t i = 0; i < n; i++) { 41 | p[i] = 0; 42 | } 43 | } 44 | 45 | // These functions are not necessarily used automatically by the compiler but they are useful to 46 | // have. 47 | 48 | void 49 | memcpy(void *restrict dst, const void *restrict src, size_t n) { 50 | for (size_t i = 0; i < n; i++) { 51 | ((uint8_t *)dst)[i] = ((uint8_t *)src)[i]; 52 | } 53 | } 54 | 55 | void 56 | memmove(void *dst, const void *src, size_t n) { 57 | uint8_t *d = dst; 58 | const uint8_t *s = src; 59 | if (d < s) { 60 | for (size_t i = 0; i < n; i++) { 61 | d[i] = s[i]; 62 | } 63 | } else if (s < d) { 64 | size_t i = n; 65 | while (i > 0) { 66 | i--; 67 | d[i] = s[i]; 68 | } 69 | } 70 | } 71 | 72 | size_t 73 | strlen(const char *str) { 74 | const char *end = str; 75 | for (;;) { 76 | if (*end == 0) { 77 | return (end - str); 78 | } 79 | end++; 80 | } 81 | } 82 | 83 | int 84 | strcmp(const char *s1, const char *s2) { 85 | for (;;) { 86 | unsigned char c1 = (unsigned char) *s1; 87 | unsigned char c2 = (unsigned char) *s2; 88 | int diff = c1 - c2; 89 | if (diff != 0) { 90 | return diff; 91 | } 92 | if (c1 == 0) { 93 | return 0; 94 | } 95 | s1++; 96 | s2++; 97 | } 98 | } 99 | 100 | int 101 | strncmp(const char *s1, const char *s2, size_t n) { 102 | while (n > 0) { 103 | unsigned char c1 = (unsigned char) *s1; 104 | unsigned char c2 = (unsigned char) *s2; 105 | int diff = c1 - c2; 106 | if (diff != 0) { 107 | return diff; 108 | } 109 | if (c1 == 0) { 110 | return 0; 111 | } 112 | s1++; 113 | s2++; 114 | n--; 115 | } 116 | return 0; 117 | } 118 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/primitives.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef PRIMITIVES__H_ 21 | #define PRIMITIVES__H_ 22 | 23 | #include 24 | 25 | void bzero(void *s, size_t n); 26 | 27 | void memcpy(void *restrict dst, const void *restrict src, size_t n); 28 | 29 | void memmove(void *dst, const void *src, size_t n); 30 | 31 | int strcmp(const char *s1, const char *s2); 32 | 33 | size_t strlen(const char *str); 34 | 35 | int strncmp(const char *s1, const char *s2, size_t n); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/third_party/boot_args.h: -------------------------------------------------------------------------------- 1 | // This file is from XNU-4903.221.2, pexpert/pexpert/arm64/boot.h, available at 2 | // https://opensource.apple.com/tarballs/xnu/xnu-4903.221.2.tar.gz. It has been modified for 3 | // inclusion in this project. 4 | /* 5 | * Copyright (c) 2007-2009 Apple Inc. All rights reserved. 6 | * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. 7 | */ 8 | /* 9 | * @OSF_COPYRIGHT@ 10 | */ 11 | 12 | #ifndef _PEXPERT_ARM64_BOOT_H_ 13 | #define _PEXPERT_ARM64_BOOT_H_ 14 | 15 | #define BOOT_LINE_LENGTH 256 16 | 17 | /* 18 | * Video information.. 19 | */ 20 | 21 | struct Boot_Video { 22 | unsigned long v_baseAddr; /* Base address of video memory */ 23 | unsigned long v_display; /* Display Code (if Applicable */ 24 | unsigned long v_rowBytes; /* Number of bytes per pixel row */ 25 | unsigned long v_width; /* Width */ 26 | unsigned long v_height; /* Height */ 27 | unsigned long v_depth; /* Pixel Depth and other parameters */ 28 | }; 29 | 30 | typedef struct Boot_Video Boot_Video; 31 | 32 | /* Boot argument structure - passed into Mach kernel at boot time. 33 | */ 34 | #define kBootArgsRevision 1 35 | #define kBootArgsRevision2 2 /* added boot_args.bootFlags */ 36 | #define kBootArgsVersion1 1 37 | #define kBootArgsVersion2 2 38 | 39 | typedef struct boot_args { 40 | uint16_t Revision; /* Revision of boot_args structure */ 41 | uint16_t Version; /* Version of boot_args structure */ 42 | uint64_t virtBase; /* Virtual base of memory */ 43 | uint64_t physBase; /* Physical base of memory */ 44 | uint64_t memSize; /* Size of memory */ 45 | uint64_t topOfKernelData; /* Highest physical address used in kernel data area */ 46 | Boot_Video Video; /* Video Information */ 47 | uint32_t machineType; /* Machine Type */ 48 | void *deviceTreeP; /* Base of flattened device tree */ 49 | uint32_t deviceTreeLength; /* Length of flattened tree */ 50 | char CommandLine[BOOT_LINE_LENGTH]; /* Passed in command line */ 51 | uint64_t bootFlags; /* Additional flags specified by the bootloader */ 52 | uint64_t memSizeActual; /* Actual size of memory */ 53 | } boot_args; 54 | 55 | #endif /* _PEXPERT_ARM64_BOOT_H_ */ 56 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/third_party/kmod.h: -------------------------------------------------------------------------------- 1 | // This file is from Xcode 11.2.1 (11B500), at the path 2 | // Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/mach/kmod.h. 3 | // It has been modified for inclusion in this project. 4 | /* 5 | * Copyright (c) 2000-2007 Apple Inc. All rights reserved. 6 | * 7 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 8 | * 9 | * This file contains Original Code and/or Modifications of Original Code 10 | * as defined in and that are subject to the Apple Public Source License 11 | * Version 2.0 (the 'License'). You may not use this file except in 12 | * compliance with the License. The rights granted to you under the License 13 | * may not be used to create, or enable the creation or redistribution of, 14 | * unlawful or unlicensed copies of an Apple operating system, or to 15 | * circumvent, violate, or enable the circumvention or violation of, any 16 | * terms of an Apple operating system software license agreement. 17 | * 18 | * Please obtain a copy of the License at 19 | * http://www.opensource.apple.com/apsl/ and read it before using this file. 20 | * 21 | * The Original Code and all software distributed under the License are 22 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 23 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 24 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 25 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 26 | * Please see the License for the specific language governing rights and 27 | * limitations under the License. 28 | * 29 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 30 | */ 31 | /* 32 | * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce 33 | * support for mandatory and extensible security protections. This notice 34 | * is included in support of clause 2.2 (b) of the Apple Public License, 35 | * Version 2.0. 36 | */ 37 | 38 | #ifndef _MACH_KMOD_H_ 39 | #define _MACH_KMOD_H_ 40 | 41 | #include 42 | 43 | #if PRAGMA_MARK 44 | #pragma mark Basic macros & typedefs 45 | #endif 46 | /*********************************************************************** 47 | * Basic macros & typedefs 48 | ***********************************************************************/ 49 | #define KMOD_MAX_NAME 64 50 | 51 | struct kmod_info; 52 | typedef int kmod_start_func_t(struct kmod_info * ki, void * data); 53 | typedef int kmod_stop_func_t(struct kmod_info * ki, void * data); 54 | 55 | #if PRAGMA_MARK 56 | #pragma mark Structure definitions 57 | #endif 58 | /*********************************************************************** 59 | * Structure definitions 60 | * 61 | * All structures must be #pragma pack(4). 62 | ***********************************************************************/ 63 | #pragma pack(push, 4) 64 | 65 | /* Run-time struct only; never saved to a file */ 66 | typedef struct kmod_reference { 67 | struct kmod_reference * next; 68 | struct kmod_info * info; 69 | } kmod_reference_t; 70 | 71 | /*********************************************************************** 72 | * Warning: Any changes to the kmod_info structure affect the 73 | * KMOD_..._DECL macros below. 74 | ***********************************************************************/ 75 | 76 | /* The kmod_info_t structure is only safe to use inside the running 77 | * kernel. If you need to work with a kmod_info_t structure outside 78 | * the kernel, please use the compatibility definitions below. 79 | */ 80 | typedef struct kmod_info { 81 | struct kmod_info * next; 82 | int32_t info_version; // version of this structure 83 | uint32_t id; 84 | char name[KMOD_MAX_NAME]; 85 | char version[KMOD_MAX_NAME]; 86 | int32_t reference_count; // # linkage refs to this 87 | kmod_reference_t * reference_list; // who this refs (links on) 88 | uint64_t address; // starting address 89 | uint64_t size; // total size 90 | uint64_t hdr_size; // unwired hdr size 91 | kmod_start_func_t * start; 92 | kmod_stop_func_t * stop; 93 | } kmod_info_t; 94 | 95 | /* A compatibility definition of kmod_info_t for 32-bit kexts. 96 | */ 97 | typedef struct kmod_info_32_v1 { 98 | uint32_t next_addr; 99 | int32_t info_version; 100 | uint32_t id; 101 | uint8_t name[KMOD_MAX_NAME]; 102 | uint8_t version[KMOD_MAX_NAME]; 103 | int32_t reference_count; 104 | uint32_t reference_list_addr; 105 | uint32_t address; 106 | uint32_t size; 107 | uint32_t hdr_size; 108 | uint32_t start_addr; 109 | uint32_t stop_addr; 110 | } kmod_info_32_v1_t; 111 | 112 | /* A compatibility definition of kmod_info_t for 64-bit kexts. 113 | */ 114 | typedef struct kmod_info_64_v1 { 115 | uint64_t next_addr; 116 | int32_t info_version; 117 | uint32_t id; 118 | uint8_t name[KMOD_MAX_NAME]; 119 | uint8_t version[KMOD_MAX_NAME]; 120 | int32_t reference_count; 121 | uint64_t reference_list_addr; 122 | uint64_t address; 123 | uint64_t size; 124 | uint64_t hdr_size; 125 | uint64_t start_addr; 126 | uint64_t stop_addr; 127 | } kmod_info_64_v1_t; 128 | 129 | #pragma pack(pop) 130 | 131 | #if PRAGMA_MARK 132 | #pragma mark Kmod structure declaration macros 133 | #endif 134 | /*********************************************************************** 135 | * Kmod structure declaration macros 136 | ***********************************************************************/ 137 | #define KMOD_INFO_NAME kmod_info 138 | #define KMOD_INFO_VERSION 1 139 | 140 | #define KMOD_DECL(name, version) \ 141 | static kmod_start_func_t name ## _module_start; \ 142 | static kmod_stop_func_t name ## _module_stop; \ 143 | kmod_info_t KMOD_INFO_NAME = { 0, KMOD_INFO_VERSION, -1U, \ 144 | { #name }, { version }, -1, 0, 0, 0, 0, \ 145 | name ## _module_start, \ 146 | name ## _module_stop }; 147 | 148 | #define KMOD_EXPLICIT_DECL(name, version, start, stop) \ 149 | kmod_info_t KMOD_INFO_NAME = { 0, KMOD_INFO_VERSION, -1U, \ 150 | { #name }, { version }, -1, 0, 0, 0, 0, \ 151 | start, stop }; 152 | 153 | #endif /* _MACH_KMOD_H_ */ 154 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/usb/synopsys_otg_regs.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef SYNOPSYS_OTG_REGS__H_ 21 | #define SYNOPSYS_OTG_REGS__H_ 22 | 23 | #ifndef SYNOPSYS_OTG_REGISTER 24 | #define SYNOPSYS_OTG_REGISTER(_x) (_x) 25 | #endif 26 | 27 | #define rGOTGCTL (SYNOPSYS_OTG_REGISTER(0x000)) 28 | #define rGOTGINT (SYNOPSYS_OTG_REGISTER(0x004)) 29 | #define rGAHBCFG (SYNOPSYS_OTG_REGISTER(0x008)) 30 | #define rGUSBCFG (SYNOPSYS_OTG_REGISTER(0x00c)) 31 | #define rGRSTCTL (SYNOPSYS_OTG_REGISTER(0x010)) 32 | #define rGINTSTS (SYNOPSYS_OTG_REGISTER(0x014)) 33 | #define rGINTMSK (SYNOPSYS_OTG_REGISTER(0x018)) 34 | #define rGRXSTSR (SYNOPSYS_OTG_REGISTER(0x01c)) 35 | #define rGRXSTSP (SYNOPSYS_OTG_REGISTER(0x020)) 36 | #define rGRXFSIZ (SYNOPSYS_OTG_REGISTER(0x024)) 37 | #define rGNPTXFSIZ (SYNOPSYS_OTG_REGISTER(0x028)) 38 | #define rGNPTXSTS (SYNOPSYS_OTG_REGISTER(0x02c)) 39 | #define rGI2CCTL (SYNOPSYS_OTG_REGISTER(0x030)) 40 | #define rGPVNDCTL (SYNOPSYS_OTG_REGISTER(0x034)) 41 | #define rGGPIO (SYNOPSYS_OTG_REGISTER(0x038)) 42 | #define rGUID (SYNOPSYS_OTG_REGISTER(0x03c)) 43 | #define rGSNPSID (SYNOPSYS_OTG_REGISTER(0x040)) 44 | #define rGHWCFG1 (SYNOPSYS_OTG_REGISTER(0x044)) 45 | #define rGHWCFG2 (SYNOPSYS_OTG_REGISTER(0x048)) 46 | #define rGHWCFG3 (SYNOPSYS_OTG_REGISTER(0x04c)) 47 | #define rGHWCFG4 (SYNOPSYS_OTG_REGISTER(0x050)) 48 | #define rGLPMCFG (SYNOPSYS_OTG_REGISTER(0x054)) 49 | #define rGPWRDN (SYNOPSYS_OTG_REGISTER(0x058)) 50 | #define rGDFIFOCFG (SYNOPSYS_OTG_REGISTER(0x05c)) 51 | #define rADPCTL (SYNOPSYS_OTG_REGISTER(0x060)) 52 | 53 | #define rHPTXFSIZ (SYNOPSYS_OTG_REGISTER(0x100)) 54 | #define rDTXFSIZ(n) (SYNOPSYS_OTG_REGISTER(0x104 + 0x4 * (n - 1))) 55 | 56 | #define rHPTXSIZ (SYNOPSYS_OTG_REGISTER(0x400)) 57 | 58 | #define rHPRT0 (SYNOPSYS_OTG_REGISTER(0x440)) 59 | 60 | #define rDCFG (SYNOPSYS_OTG_REGISTER(0x800)) 61 | #define rDCTL (SYNOPSYS_OTG_REGISTER(0x804)) 62 | #define rDSTS (SYNOPSYS_OTG_REGISTER(0x808)) 63 | #define rDIEPMSK (SYNOPSYS_OTG_REGISTER(0x810)) 64 | #define rDOEPMSK (SYNOPSYS_OTG_REGISTER(0x814)) 65 | #define rDAINT (SYNOPSYS_OTG_REGISTER(0x818)) 66 | #define rDAINTMSK (SYNOPSYS_OTG_REGISTER(0x81c)) 67 | 68 | #define rDIEPCTL(ep) (SYNOPSYS_OTG_REGISTER(0x900 + 0x20 * ep)) 69 | #define rDIEPINT(ep) (SYNOPSYS_OTG_REGISTER(0x908 + 0x20 * ep)) 70 | #define rDIEPTSIZ(ep) (SYNOPSYS_OTG_REGISTER(0x910 + 0x20 * ep)) 71 | #define rDIEPDMA(ep) (SYNOPSYS_OTG_REGISTER(0x914 + 0x20 * ep)) 72 | #define rDTXFSTS(ep) (SYNOPSYS_OTG_REGISTER(0x918 + 0x20 * ep)) 73 | #define rDIEPDMAB(ep) (SYNOPSYS_OTG_REGISTER(0x91c + 0x20 * ep)) 74 | 75 | #define rDOEPCTL(ep) (SYNOPSYS_OTG_REGISTER(0xb00 + 0x20 * ep)) 76 | #define rDOEPINT(ep) (SYNOPSYS_OTG_REGISTER(0xb08 + 0x20 * ep)) 77 | #define rDOEPTSIZ(ep) (SYNOPSYS_OTG_REGISTER(0xb10 + 0x20 * ep)) 78 | #define rDOEPDMA(ep) (SYNOPSYS_OTG_REGISTER(0xb14 + 0x20 * ep)) 79 | #define rDOEPDMAB(ep) (SYNOPSYS_OTG_REGISTER(0xb1c + 0x20 * ep)) 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/usb/usb.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef USB__H_ 21 | #define USB__H_ 22 | 23 | #include 24 | #include 25 | 26 | // The amount of memory needed for the USB stack. 27 | #define USB_STACK_MEMORY_SIZE 0x4000 28 | 29 | /* 30 | * usb_init 31 | * 32 | * Description: 33 | * Initialize state for the USB stack. This does not interact with the USB hardware so it may 34 | * be called before preemption is disabled. 35 | * 36 | * dma should be a pointer to a page with a low physical address suitable for use by the USB 37 | * controller's DMA engine. 38 | * 39 | * memory should be a pointer to a page-aligned allocation of size USB_STACK_MEMORY_SIZE for 40 | * internal use by the USB stack. 41 | */ 42 | void usb_init(void *dma, void *memory); 43 | 44 | /* 45 | * usb_start 46 | * 47 | * Description: 48 | * Start the USB stack for communication with the host. 49 | * 50 | * This should only be called once the system is stopped and with interrupts disabled. 51 | */ 52 | void usb_start(void); 53 | 54 | /* 55 | * usb_process 56 | * 57 | * Description: 58 | * Perform a single round of USB processing. This should be called after usb_read() and 59 | * usb_write(), and at every USB interrupt. A simple implementation would be to call this 60 | * function on every iteration of the debugger main loop. 61 | */ 62 | void usb_process(void); 63 | 64 | /* 65 | * usb_read 66 | * 67 | * Description: 68 | * Read data sent over USB. 69 | * 70 | * Up to 0x1000 bytes of data will be buffered. 71 | */ 72 | size_t usb_read(void *buffer, size_t size); 73 | 74 | /* 75 | * usb_write 76 | * 77 | * Description: 78 | * Write data out over USB. No actual data is sent until a call to usb_write_commit(). 79 | * 80 | * The maximum packet size is 0x1000. However, it is possible that less than 0x1000 bytes can 81 | * be written if the buffer is already partially full from the last write. 82 | */ 83 | size_t usb_write(const void *buffer, size_t size); 84 | 85 | /* 86 | * usb_write_commit 87 | * 88 | * Description: 89 | * Send any data written via usb_write() over USB to the host. 90 | */ 91 | void usb_write_commit(void); 92 | 93 | // ---- Transfer API ------------------------------------------------------------------------------ 94 | 95 | /* 96 | * usb_in_transfer 97 | * 98 | * Description: 99 | * Perform an IN transfer on the specified endpoint. 100 | * 101 | * The data buffer must remain alive until the completion callback is invoked. 102 | */ 103 | void usb_in_transfer(uint8_t ep_addr, const void *data, uint32_t size, void (*callback)(void)); 104 | 105 | /* 106 | * usb_out_transfer 107 | * 108 | * Description: 109 | * Perform an OUT transfer on the specified endpoint. 110 | */ 111 | void usb_out_transfer(uint8_t ep_addr, void *data, uint32_t size, 112 | void (*callback)(void *data, uint32_t size, uint32_t transferred)); 113 | 114 | /* 115 | * usb_out_transfer_dma 116 | * 117 | * Description: 118 | * Perform an OUT transfer on the specified endpoint, optimized for when the data buffer is 119 | * suitable for DMA. 120 | */ 121 | void usb_out_transfer_dma(uint8_t ep_addr, void *data, uint32_t dma, uint32_t size, 122 | void (*callback)(void *data, uint32_t size, uint32_t transferred)); 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/watchdog.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "watchdog.h" 21 | 22 | #include "page_table.h" 23 | 24 | // ---- WatchDog Timer ---------------------------------------------------------------------------- 25 | 26 | uint64_t watchdog_timer_register_base = 0x2352b0000; 27 | 28 | // The memory-mapped WatchDog Timer registers. 29 | static uint64_t watchdog_registers; 30 | 31 | // Map the WatchDog Timer registers. 32 | static void 33 | map_watchdog_registers() { 34 | if (watchdog_registers == 0) { 35 | watchdog_registers = (uint64_t) ttbr0_map_io(watchdog_timer_register_base, 0x1000); 36 | } 37 | } 38 | 39 | void 40 | disable_watchdog_timer() { 41 | map_watchdog_registers(); 42 | *(volatile uint32_t *)(watchdog_registers + 0x0c) = 0; 43 | *(volatile uint32_t *)(watchdog_registers + 0x1c) = 0; 44 | } 45 | -------------------------------------------------------------------------------- /ktrw_gdb_stub/source/watchdog.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef WATCHDOG__H_ 21 | #define WATCHDOG__H_ 22 | 23 | #include 24 | 25 | // The physical address of the WatchDog Timer registers. This should be initialized prior to 26 | // calling disable_watchdog_timer(). 27 | extern uint64_t watchdog_timer_register_base; 28 | 29 | /* 30 | * disable_watchdog_timer 31 | * 32 | * Description: 33 | * Disables the WatchDog Timer. 34 | */ 35 | void disable_watchdog_timer(void); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /ktrw_kext_loader/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = ktrw_kext_loader 2 | 3 | ARCH = arm64 4 | SDK = iphoneos 5 | DEBUG = 0 6 | 7 | SYSROOT := $(shell xcrun --sdk $(SDK) --show-sdk-path) 8 | ifeq ($(SYSROOT),) 9 | $(error Could not find SDK $(SDK)) 10 | endif 11 | CLANG := $(shell xcrun --sdk $(SDK) --find clang) 12 | CC := $(CLANG) -isysroot $(SYSROOT) -arch $(ARCH) 13 | 14 | CFLAGS = -Iheaders -Ikernel -Ikernel_call -Ikernel_patches -Ikext_load -Iktrr -Isystem 15 | CFLAGS += -O2 16 | CFLAGS += -Wall -Werror -Wpedantic -Wno-gnu -Wno-language-extension-token 17 | CFLAGS += -Wno-keyword-macro 18 | 19 | ifneq ($(DEBUG),0) 20 | CFLAGS += -DDEBUG=$(DEBUG) 21 | endif 22 | 23 | LDFLAGS = -framework CoreFoundation -framework IOKit 24 | 25 | SOURCES = kernel/kernel_memory.c \ 26 | kernel/kernel_parameters.c \ 27 | kernel/kernel_slide.c \ 28 | kernel/kernel_tasks.c \ 29 | kernel_call/kernel_call.c \ 30 | kernel_call/kernel_call_7_a11.c \ 31 | kernel_call/kernel_call_parameters.c \ 32 | kernel_patches/kernel_patches.c \ 33 | kext_load/kext_load.c \ 34 | kext_load/resolve_symbol.c \ 35 | ktrr/ktrr_bypass.c \ 36 | ktrr/ktrr_bypass_parameters.c \ 37 | system/log.c \ 38 | system/map_file.c \ 39 | system/platform.c \ 40 | system/platform_match.c \ 41 | main.c 42 | 43 | HEADERS = headers/IOKitLib.h \ 44 | headers/mach_vm.h \ 45 | kernel/kernel_memory.h \ 46 | kernel/kernel_parameters.h \ 47 | kernel/kernel_slide.h \ 48 | kernel/kernel_tasks.h \ 49 | kernel_call/kernel_call.h \ 50 | kernel_call/kernel_call_7_a11.h \ 51 | kernel_call/kernel_call_parameters.h \ 52 | kernel_patches/kernel_patches.h \ 53 | kext_load/kext_load.h \ 54 | kext_load/resolve_symbol.h \ 55 | ktrr/ktrr_bypass.h \ 56 | ktrr/ktrr_bypass_parameters.h \ 57 | system/log.h \ 58 | system/map_file.h \ 59 | system/parameters.h \ 60 | system/platform.h \ 61 | system/platform_match.h 62 | 63 | $(TARGET): $(SOURCES) $(HEADERS) 64 | $(CC) $(CFLAGS) $(DEFINES) $(LDFLAGS) -o $@ $(SOURCES) 65 | 66 | clean: 67 | rm -f -- $(TARGET) 68 | -------------------------------------------------------------------------------- /ktrw_kext_loader/app/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import 21 | 22 | @interface AppDelegate : UIResponder 23 | 24 | @property (strong, nonatomic) UIWindow *window; 25 | 26 | 27 | @end 28 | 29 | -------------------------------------------------------------------------------- /ktrw_kext_loader/app/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import "AppDelegate.h" 21 | 22 | #import "bundle_path.h" 23 | #import "kernel_call.h" 24 | #import "kernel_memory.h" 25 | #import "kernel_patches.h" 26 | #import "kext_load.h" 27 | #import "ktrr_bypass.h" 28 | #import "log.h" 29 | 30 | 31 | @interface AppDelegate () 32 | 33 | @end 34 | 35 | @implementation AppDelegate 36 | 37 | 38 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 39 | // Get the bundle path. 40 | char bundle_path[1024]; 41 | get_bundle_path(bundle_path, sizeof(bundle_path)); 42 | // Load the kernel symbol database. 43 | char kernel_symbol_database[1024]; 44 | snprintf(kernel_symbol_database, sizeof(kernel_symbol_database), "%s/%s", bundle_path, 45 | "kernel_symbols"); 46 | bool ok = kext_load_set_kernel_symbol_database(kernel_symbol_database); 47 | if (!ok) { 48 | ERROR("Could not load kernel symbol database"); 49 | goto done_0; 50 | } 51 | // Try to get the kernel task port using task_for_pid(). If this works, then KTRR has 52 | // already been bypassed and the kext has already been loaded. 53 | kernel_task_port = MACH_PORT_NULL; 54 | task_for_pid(mach_task_self(), 0, &kernel_task_port); 55 | if (kernel_task_port != MACH_PORT_NULL) { 56 | INFO("task_for_pid(0) = 0x%x", kernel_task_port); 57 | INFO("KTRR already bypassed"); 58 | goto done_0; 59 | } 60 | // Try to get the kernel task port using host_get_special_port(4). If this works, then an 61 | // exploit has already run but we still need to bypass KTRR. 62 | if (kernel_task_port == MACH_PORT_NULL) { 63 | mach_port_t host = mach_host_self(); 64 | host_get_special_port(host, 0, 4, &kernel_task_port); 65 | mach_port_deallocate(mach_task_self(), host); 66 | if (kernel_task_port != MACH_PORT_NULL) { 67 | INFO("host_get_special_port(4) = 0x%x", kernel_task_port); 68 | } 69 | } 70 | // If we still don't have a kernel task port, then abort. 71 | if (kernel_task_port == MACH_PORT_NULL) { 72 | ERROR("Could not get kernel task port"); 73 | goto done_0; 74 | } 75 | // Initialize our kernel function calling capability. 76 | ok = kernel_call_init(); 77 | if (!ok) { 78 | ERROR("Could not initialize kernel_call subsystem"); 79 | goto done_0; 80 | } 81 | // Bypass KTRR and remap the kernel as read/write. 82 | ok = have_ktrr_bypass(); 83 | if (!ok) { 84 | ERROR("No KTRR bypass is available for this platform"); 85 | goto done_1; 86 | } 87 | ktrr_bypass(); 88 | // Apply kernel patches. 89 | apply_kernel_patches(); 90 | // Check that we can call task_for_pid(0). 91 | mach_port_t tfp0 = MACH_PORT_NULL; 92 | task_for_pid(mach_task_self(), 0, &tfp0); 93 | INFO("task_for_pid(0) = 0x%x", tfp0); 94 | // Load the kernel extension. 95 | const char *kext_name = "ktrw_gdb_stub.ikext"; 96 | char kext_path[1024]; 97 | snprintf(kext_path, sizeof(kext_path), "%s/kexts/%s", bundle_path, kext_name); 98 | uint64_t kext_address = kext_load(kext_path, 0); 99 | INFO("Kext %s loaded at address 0x%016llx", kext_name, kext_address); 100 | done_1: 101 | // De-initialize our kernel function calling primitive. 102 | kernel_call_deinit(); 103 | done_0: 104 | usleep(100000); 105 | exit(1); 106 | return YES; 107 | } 108 | 109 | 110 | - (void)applicationWillResignActive:(UIApplication *)application { 111 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 112 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 113 | } 114 | 115 | 116 | - (void)applicationDidEnterBackground:(UIApplication *)application { 117 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 118 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 119 | } 120 | 121 | 122 | - (void)applicationWillEnterForeground:(UIApplication *)application { 123 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 124 | } 125 | 126 | 127 | - (void)applicationDidBecomeActive:(UIApplication *)application { 128 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 129 | } 130 | 131 | 132 | - (void)applicationWillTerminate:(UIApplication *)application { 133 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 134 | } 135 | 136 | 137 | @end 138 | -------------------------------------------------------------------------------- /ktrw_kext_loader/app/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /ktrw_kext_loader/app/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ktrw_kext_loader/app/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ktrw_kext_loader/app/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ktrw_kext_loader/app/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ktrw_kext_loader/app/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import 21 | 22 | @interface ViewController : UIViewController 23 | 24 | 25 | @end 26 | 27 | -------------------------------------------------------------------------------- /ktrw_kext_loader/app/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import "ViewController.h" 21 | 22 | @interface ViewController () 23 | 24 | @end 25 | 26 | @implementation ViewController 27 | 28 | - (void)viewDidLoad { 29 | [super viewDidLoad]; 30 | // Do any additional setup after loading the view, typically from a nib. 31 | } 32 | 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /ktrw_kext_loader/app/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import 21 | #import "AppDelegate.h" 22 | 23 | int main(int argc, char * argv[]) { 24 | @autoreleasepool { 25 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ktrw_kext_loader/headers/IOKitLib.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef IOKITLIB__H_ 21 | #define IOKITLIB__H_ 22 | 23 | #include 24 | #include 25 | 26 | typedef mach_port_t io_object_t; 27 | typedef io_object_t io_connect_t; 28 | typedef io_object_t io_iterator_t; 29 | typedef io_object_t io_service_t; 30 | 31 | extern const mach_port_t kIOMasterPortDefault; 32 | 33 | kern_return_t 34 | IOObjectRelease( 35 | io_object_t object ); 36 | 37 | io_object_t 38 | IOIteratorNext( 39 | io_iterator_t iterator ); 40 | 41 | io_service_t 42 | IOServiceGetMatchingService( 43 | mach_port_t masterPort, 44 | CFDictionaryRef matching CF_RELEASES_ARGUMENT); 45 | 46 | kern_return_t 47 | IOServiceGetMatchingServices( 48 | mach_port_t masterPort, 49 | CFDictionaryRef matching CF_RELEASES_ARGUMENT, 50 | io_iterator_t * existing ); 51 | 52 | kern_return_t 53 | IOServiceOpen( 54 | io_service_t service, 55 | task_port_t owningTask, 56 | uint32_t type, 57 | io_connect_t * connect ); 58 | 59 | kern_return_t 60 | IOServiceClose( 61 | io_connect_t connect ); 62 | 63 | kern_return_t 64 | IOConnectCallMethod( 65 | mach_port_t connection, // In 66 | uint32_t selector, // In 67 | const uint64_t *input, // In 68 | uint32_t inputCnt, // In 69 | const void *inputStruct, // In 70 | size_t inputStructCnt, // In 71 | uint64_t *output, // Out 72 | uint32_t *outputCnt, // In/Out 73 | void *outputStruct, // Out 74 | size_t *outputStructCnt) // In/Out 75 | AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; 76 | 77 | kern_return_t 78 | IOConnectTrap6(io_connect_t connect, 79 | uint32_t index, 80 | uintptr_t p1, 81 | uintptr_t p2, 82 | uintptr_t p3, 83 | uintptr_t p4, 84 | uintptr_t p5, 85 | uintptr_t p6); 86 | 87 | CFMutableDictionaryRef 88 | IOServiceMatching( 89 | const char * name ) CF_RETURNS_RETAINED; 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /ktrw_kext_loader/headers/mach_vm.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef MACH_VM__H_ 21 | #define MACH_VM__H_ 22 | 23 | #include 24 | 25 | extern 26 | kern_return_t mach_vm_allocate 27 | ( 28 | vm_map_t target, 29 | mach_vm_address_t *address, 30 | mach_vm_size_t size, 31 | int flags 32 | ); 33 | 34 | extern 35 | kern_return_t mach_vm_deallocate 36 | ( 37 | vm_map_t target, 38 | mach_vm_address_t address, 39 | mach_vm_size_t size 40 | ); 41 | 42 | extern 43 | kern_return_t mach_vm_protect 44 | ( 45 | vm_map_t target_task, 46 | mach_vm_address_t address, 47 | mach_vm_size_t size, 48 | boolean_t set_maximum, 49 | vm_prot_t new_protection 50 | ); 51 | 52 | extern 53 | kern_return_t mach_vm_write 54 | ( 55 | vm_map_t target_task, 56 | mach_vm_address_t address, 57 | vm_offset_t data, 58 | mach_msg_type_number_t dataCnt 59 | ); 60 | 61 | extern 62 | kern_return_t mach_vm_read_overwrite 63 | ( 64 | vm_map_t target_task, 65 | mach_vm_address_t address, 66 | mach_vm_size_t size, 67 | mach_vm_address_t data, 68 | mach_vm_size_t *outsize 69 | ); 70 | 71 | extern 72 | kern_return_t mach_vm_remap 73 | ( 74 | vm_map_t target_task, 75 | mach_vm_address_t *target_address, 76 | mach_vm_size_t size, 77 | mach_vm_offset_t mask, 78 | int flags, 79 | vm_map_t src_task, 80 | mach_vm_address_t src_address, 81 | boolean_t copy, 82 | vm_prot_t *cur_protection, 83 | vm_prot_t *max_protection, 84 | vm_inherit_t inheritance 85 | ); 86 | 87 | extern 88 | kern_return_t mach_vm_region_recurse 89 | ( 90 | vm_map_t target_task, 91 | mach_vm_address_t *address, 92 | mach_vm_size_t *size, 93 | natural_t *nesting_depth, 94 | vm_region_recurse_info_t info, 95 | mach_msg_type_number_t *infoCnt 96 | ); 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel/kernel_memory.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #define KERNEL_MEMORY_EXTERN 21 | #include "kernel_memory.h" 22 | 23 | #include 24 | 25 | #include "log.h" 26 | #include "mach_vm.h" 27 | #include "platform.h" 28 | 29 | // ---- Kernel memory functions ------------------------------------------------------------------- 30 | 31 | uint64_t 32 | kernel_vm_allocate(size_t size) { 33 | mach_vm_address_t address = 0; 34 | kern_return_t kr = mach_vm_allocate(kernel_task_port, &address, size, VM_FLAGS_ANYWHERE); 35 | if (kr != KERN_SUCCESS) { 36 | ERROR("%s returned %d: %s", "mach_vm_allocate", kr, mach_error_string(kr)); 37 | address = -1; 38 | } else { 39 | // Fault in each page. 40 | for (size_t offset = 0; offset < size; offset += page_size) { 41 | kernel_read64(address + offset); 42 | } 43 | } 44 | return address; 45 | } 46 | 47 | void 48 | kernel_vm_deallocate(uint64_t address, size_t size) { 49 | kern_return_t kr = mach_vm_deallocate(kernel_task_port, address, size); 50 | if (kr != KERN_SUCCESS) { 51 | WARNING("%s returned %d: %s", "mach_vm_deallocate", kr, mach_error_string(kr)); 52 | } 53 | } 54 | 55 | bool 56 | kernel_vm_protect(uint64_t address, size_t size, vm_prot_t prot) { 57 | kern_return_t kr = mach_vm_protect(kernel_task_port, address, size, FALSE, prot); 58 | if (kr != KERN_SUCCESS) { 59 | ERROR("%s returned %d: %s", "mach_vm_protect", kr, mach_error_string(kr)); 60 | return false; 61 | } 62 | return true; 63 | } 64 | 65 | void * 66 | kernel_vm_remap(uint64_t address, size_t size) { 67 | assert((address & (page_size - 1)) == 0); 68 | assert((size & (page_size - 1)) == 0); 69 | mach_vm_address_t target_address = 0; 70 | vm_prot_t cur_prot, max_prot; 71 | kern_return_t kr = mach_vm_remap( 72 | mach_task_self(), 73 | &target_address, 74 | size, 75 | 0, 76 | VM_FLAGS_ANYWHERE, 77 | kernel_task_port, 78 | address, 79 | FALSE, 80 | &cur_prot, 81 | &max_prot, 82 | VM_INHERIT_NONE); 83 | if (kr != KERN_SUCCESS) { 84 | ERROR("%s returned %d: %s", "mach_vm_remap", kr, mach_error_string(kr)); 85 | return NULL; 86 | } 87 | return (void *)target_address; 88 | } 89 | 90 | bool 91 | kernel_read(uint64_t address, void *data, size_t size) { 92 | mach_vm_size_t size_out; 93 | kern_return_t kr = mach_vm_read_overwrite(kernel_task_port, address, 94 | size, (mach_vm_address_t) data, &size_out); 95 | if (kr != KERN_SUCCESS) { 96 | ERROR("%s returned %d: %s", "mach_vm_read_overwrite", kr, mach_error_string(kr)); 97 | ERROR("could not %s address 0x%016llx", "read", address); 98 | return false; 99 | } 100 | if (size_out != size) { 101 | ERROR("partial read of address 0x%016llx: %llu of %zu bytes", 102 | address, size_out, size); 103 | return false; 104 | } 105 | return true; 106 | } 107 | 108 | bool 109 | kernel_write(uint64_t address, const void *data, size_t size) { 110 | const uint8_t *write_data = data; 111 | while (size > 0) { 112 | size_t write_size = size; 113 | if (write_size > page_size) { 114 | write_size = page_size; 115 | } 116 | kern_return_t kr = mach_vm_write(kernel_task_port, address, 117 | (mach_vm_address_t) write_data, (mach_msg_size_t) write_size); 118 | if (kr != KERN_SUCCESS) { 119 | ERROR("%s returned %d: %s", "mach_vm_write", kr, mach_error_string(kr)); 120 | ERROR("could not %s address 0x%016llx", "write", address); 121 | return false; 122 | } 123 | address += write_size; 124 | write_data += write_size; 125 | size -= write_size; 126 | } 127 | return true; 128 | } 129 | 130 | uint8_t 131 | kernel_read8(uint64_t address) { 132 | uint8_t value; 133 | bool ok = kernel_read(address, &value, sizeof(value)); 134 | if (!ok) { 135 | return -1; 136 | } 137 | return value; 138 | } 139 | 140 | uint16_t 141 | kernel_read16(uint64_t address) { 142 | uint16_t value; 143 | bool ok = kernel_read(address, &value, sizeof(value)); 144 | if (!ok) { 145 | return -1; 146 | } 147 | return value; 148 | } 149 | 150 | uint32_t 151 | kernel_read32(uint64_t address) { 152 | uint32_t value; 153 | bool ok = kernel_read(address, &value, sizeof(value)); 154 | if (!ok) { 155 | return -1; 156 | } 157 | return value; 158 | } 159 | 160 | uint64_t 161 | kernel_read64(uint64_t address) { 162 | uint64_t value; 163 | bool ok = kernel_read(address, &value, sizeof(value)); 164 | if (!ok) { 165 | return -1; 166 | } 167 | return value; 168 | } 169 | 170 | bool 171 | kernel_write8(uint64_t address, uint8_t value) { 172 | return kernel_write(address, &value, sizeof(value)); 173 | } 174 | 175 | bool 176 | kernel_write16(uint64_t address, uint16_t value) { 177 | return kernel_write(address, &value, sizeof(value)); 178 | } 179 | 180 | bool 181 | kernel_write32(uint64_t address, uint32_t value) { 182 | return kernel_write(address, &value, sizeof(value)); 183 | } 184 | 185 | bool 186 | kernel_write64(uint64_t address, uint64_t value) { 187 | return kernel_write(address, &value, sizeof(value)); 188 | } 189 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel/kernel_memory.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef KERNEL_MEMORY__H_ 21 | #define KERNEL_MEMORY__H_ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #ifdef KERNEL_MEMORY_EXTERN 29 | #define extern KERNEL_MEMORY_EXTERN 30 | #endif 31 | 32 | /* 33 | * kernel_task_port 34 | * 35 | * Description: 36 | * The kernel task port. 37 | */ 38 | extern mach_port_t kernel_task_port; 39 | 40 | /* 41 | * kernel_vm_allocate 42 | * 43 | * Description: 44 | * Allocate kernel virtual memory with mach_vm_allocate(). 45 | */ 46 | uint64_t kernel_vm_allocate(size_t size); 47 | 48 | /* 49 | * kernel_vm_deallocate 50 | * 51 | * Description: 52 | * Deallocate kernel virtual memory with mach_vm_deallocate(). 53 | */ 54 | void kernel_vm_deallocate(uint64_t address, size_t size); 55 | 56 | /* 57 | * kernel_vm_protect 58 | * 59 | * Description: 60 | * Set permissions on kernel virtual memory with mach_vm_protect(). 61 | */ 62 | bool kernel_vm_protect(uint64_t address, size_t size, vm_prot_t prot); 63 | 64 | /* 65 | * kernel_vm_remap 66 | * 67 | * Description: 68 | * Remap kernel memory into userspace. The address and size must be page-aligned. 69 | */ 70 | void *kernel_vm_remap(uint64_t address, size_t size); 71 | 72 | /* 73 | * kernel_read 74 | * 75 | * Description: 76 | * Read data from kernel memory. 77 | */ 78 | bool kernel_read(uint64_t address, void *data, size_t size); 79 | 80 | /* 81 | * kernel_write 82 | * 83 | * Description: 84 | * Write data to kernel memory. 85 | */ 86 | bool kernel_write(uint64_t address, const void *data, size_t size); 87 | 88 | /* 89 | * kernel_read8 90 | * 91 | * Description: 92 | * Read a single byte from kernel memory. If the read fails, -1 is returned. 93 | */ 94 | uint8_t kernel_read8(uint64_t address); 95 | 96 | /* 97 | * kernel_read16 98 | * 99 | * Description: 100 | * Read a 16-bit value from kernel memory. If the read fails, -1 is returned. 101 | */ 102 | uint16_t kernel_read16(uint64_t address); 103 | 104 | /* 105 | * kernel_read32 106 | * 107 | * Description: 108 | * Read a 32-bit value from kernel memory. If the read fails, -1 is returned. 109 | */ 110 | uint32_t kernel_read32(uint64_t address); 111 | 112 | /* 113 | * kernel_read64 114 | * 115 | * Description: 116 | * Read a 64-bit value from kernel memory. If the read fails, -1 is returned. 117 | */ 118 | uint64_t kernel_read64(uint64_t address); 119 | 120 | /* 121 | * kernel_write8 122 | * 123 | * Description: 124 | * Write a single byte to kernel memory. 125 | */ 126 | bool kernel_write8(uint64_t address, uint8_t value); 127 | 128 | /* 129 | * kernel_write16 130 | * 131 | * Description: 132 | * Write a 16-bit value to kernel memory. 133 | */ 134 | bool kernel_write16(uint64_t address, uint16_t value); 135 | 136 | /* 137 | * kernel_write32 138 | * 139 | * Description: 140 | * Write a 32-bit value to kernel memory. 141 | */ 142 | bool kernel_write32(uint64_t address, uint32_t value); 143 | 144 | /* 145 | * kernel_write64 146 | * 147 | * Description: 148 | * Write a 64-bit value to kernel memory. 149 | */ 150 | bool kernel_write64(uint64_t address, uint64_t value); 151 | 152 | /* 153 | * kernel_ipc_port_lookup 154 | * 155 | * Description: 156 | * Get the address of the ipc_port and ipc_entry for a Mach port name. 157 | */ 158 | bool kernel_ipc_port_lookup(uint64_t task, mach_port_name_t port_name, 159 | uint64_t *ipc_port, uint64_t *ipc_entry); 160 | 161 | #undef extern 162 | 163 | #endif 164 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel/kernel_parameters.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #define KERNEL_PARAMETERS_EXTERN PARAMETER_SHARED 21 | #include "kernel_parameters.h" 22 | 23 | #include "kernel_slide.h" 24 | #include "log.h" 25 | #include "platform_match.h" 26 | 27 | // ---- Offset initialization --------------------------------------------------------------------- 28 | 29 | static void 30 | offsets__iphone10_1__16C101() { 31 | kernel_slide_step = 0x4000; 32 | SIZE(ipc_entry) = 0x18; 33 | OFFSET(ipc_entry, ie_object) = 0; 34 | OFFSET(ipc_space, is_table_size) = 0x14; 35 | OFFSET(ipc_space, is_table) = 0x20; 36 | OFFSET(proc, p_list_next) = 0; 37 | OFFSET(proc, task) = 0x10; 38 | OFFSET(proc, p_pid) = 0x60; 39 | OFFSET(task, itk_space) = 0x300; 40 | OFFSET(task, bsd_info) = 0x358; 41 | STATIC_ADDRESS(kernel_base) = 0xFFFFFFF007004000; 42 | } 43 | 44 | static void 45 | offsets__iphone10_1__17B102() { 46 | kernel_slide_step = 0x4000; 47 | SIZE(ipc_entry) = 0x18; 48 | OFFSET(ipc_entry, ie_object) = 0; 49 | OFFSET(ipc_space, is_table_size) = 0x14; 50 | OFFSET(ipc_space, is_table) = 0x20; 51 | OFFSET(proc, p_list_next) = 0; 52 | OFFSET(proc, task) = 0x10; 53 | OFFSET(proc, p_pid) = 0x68; 54 | OFFSET(task, itk_space) = 0x320; 55 | OFFSET(task, bsd_info) = 0x380; 56 | STATIC_ADDRESS(kernel_base) = 0xFFFFFFF007004000; 57 | } 58 | 59 | static struct platform_initialization offsets[] = { 60 | { "iPhone10,1", "16C101-16G77", offsets__iphone10_1__16C101 }, 61 | { "iPhone10,6", "16E227", offsets__iphone10_1__16C101 }, 62 | { "iPhone10,1|iPhone10,4", "17B102-17C54", offsets__iphone10_1__17B102 }, 63 | }; 64 | 65 | // ---- Address initialization -------------------------------------------------------------------- 66 | 67 | static void 68 | addresses__iphone10_1__16C101() { 69 | STATIC_ADDRESS(allproc) = 0xFFFFFFF0076D2B28; 70 | } 71 | 72 | static void 73 | addresses__iphone10_6__16E227() { 74 | STATIC_ADDRESS(allproc) = 0xFFFFFFF0076CF918; 75 | } 76 | 77 | static void 78 | addresses__iphone10_1__16G77() { 79 | STATIC_ADDRESS(allproc) = 0xFFFFFFF0076CF958; 80 | } 81 | 82 | static void 83 | addresses__iphone10_1__17B102() { 84 | STATIC_ADDRESS(allproc) = 0xFFFFFFF0091E6C50; 85 | } 86 | 87 | static void 88 | addresses__iphone10_1__17C54() { 89 | STATIC_ADDRESS(allproc) = 0xFFFFFFF0091EEC30; 90 | } 91 | 92 | static struct platform_initialization addresses[] = { 93 | { "iPhone10,1", "16C101", addresses__iphone10_1__16C101 }, 94 | { "iPhone10,6", "16E227", addresses__iphone10_6__16E227 }, 95 | { "iPhone10,1", "16G77", addresses__iphone10_1__16G77 }, 96 | { "iPhone10,1|iPhone10,4", "17B102", addresses__iphone10_1__17B102 }, 97 | { "iPhone10,1|iPhone10,4", "17C54", addresses__iphone10_1__17C54 }, 98 | }; 99 | 100 | // ---- Public API -------------------------------------------------------------------------------- 101 | 102 | #define ARRAY_COUNT(x) (sizeof(x) / sizeof((x)[0])) 103 | 104 | bool 105 | kernel_parameters_init() { 106 | // Only run once. 107 | static bool initialized = false; 108 | if (initialized) { 109 | return true; 110 | } 111 | // Get general platform info. 112 | platform_init(); 113 | // Initialize offsets. 114 | size_t count = run_platform_initializations(offsets, ARRAY_COUNT(offsets)); 115 | if (count < 1) { 116 | ERROR("No kernel %s for %s %s", "offsets", platform.machine, platform.osversion); 117 | return false; 118 | } 119 | // Initialize addresses. 120 | count = run_platform_initializations(addresses, ARRAY_COUNT(addresses)); 121 | if (count < 1) { 122 | ERROR("No kernel %s for %s %s", "addresses", platform.machine, platform.osversion); 123 | return false; 124 | } 125 | initialized = true; 126 | return true; 127 | } 128 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel/kernel_parameters.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef KERNEL_PARAMETERS__H_ 21 | #define KERNEL_PARAMETERS__H_ 22 | 23 | #include "parameters.h" 24 | 25 | #ifdef KERNEL_PARAMETERS_EXTERN 26 | #define extern KERNEL_PARAMETERS_EXTERN 27 | #endif 28 | 29 | // The static base address of the kernel. 30 | extern uint64_t STATIC_ADDRESS(kernel_base); 31 | 32 | // The kernel_slide granularity. 33 | extern uint64_t kernel_slide_step; 34 | 35 | // Parameters for struct ipc_entry. 36 | extern size_t SIZE(ipc_entry); 37 | extern size_t OFFSET(ipc_entry, ie_object); 38 | 39 | // Parameters for struct ipc_port. 40 | extern size_t OFFSET(ipc_port, ip_kobject); 41 | 42 | // Parameters for struct ipc_space. 43 | extern size_t OFFSET(ipc_space, is_table_size); 44 | extern size_t OFFSET(ipc_space, is_table); 45 | 46 | // Parameters for struct proc. 47 | extern size_t OFFSET(proc, p_list_next); 48 | extern size_t OFFSET(proc, task); 49 | extern size_t OFFSET(proc, p_pid); 50 | 51 | // Parameters for struct task. 52 | extern size_t OFFSET(task, itk_space); 53 | extern size_t OFFSET(task, bsd_info); 54 | 55 | // The static address of the allproc variable. 56 | extern uint64_t STATIC_ADDRESS(allproc); 57 | 58 | /* 59 | * kernel_parameters_init 60 | * 61 | * Description: 62 | * Initialize the parameters used in the kernel subsystem. 63 | */ 64 | bool kernel_parameters_init(void); 65 | 66 | #undef extern 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel/kernel_slide.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #define KERNEL_SLIDE_EXTERN 21 | #include "kernel_slide.h" 22 | 23 | #include 24 | #include 25 | 26 | #include "kernel_memory.h" 27 | #include "kernel_parameters.h" 28 | #include "kernel_tasks.h" 29 | #include "log.h" 30 | #include "mach_vm.h" 31 | 32 | // Check if the given address is the kernel base. 33 | static bool 34 | is_kernel_base(uint64_t base) { 35 | // Read the data at the base address as a Mach-O header. 36 | struct mach_header_64 header = {}; 37 | bool ok = kernel_read(base, &header, sizeof(header)); 38 | if (!ok) { 39 | return false; 40 | } 41 | // Validate that this looks like the kernel base. We don't check the CPU subtype since it 42 | // may not exactly match the current platform's CPU subtype (e.g. on iPhone10,1, 43 | // header.cpusubtype is CPU_SUBTYPE_ARM64_ALL while platform.cpu_subtype is 44 | // CPU_SUBTYPE_ARM64_V8). 45 | if (!(header.magic == MH_MAGIC_64 46 | && header.cputype == platform.cpu_type 47 | && header.filetype == MH_EXECUTE 48 | && header.ncmds > 2)) { 49 | return false; 50 | } 51 | return true; 52 | } 53 | 54 | // Call this once the kernel slide has been set up. 55 | static void 56 | did_set_kernel_slide() { 57 | INFO("KASLR slide is 0x%llx", kernel_slide); 58 | } 59 | 60 | // Some jailbreaks stash information about the kernel base in task_info(TASK_DYLD_INFO). Check to 61 | // see if this information is populated for the kernel_task_port. 62 | static bool 63 | check_task_dyld_info() { 64 | struct task_dyld_info info; 65 | mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; 66 | kern_return_t kr = task_info(kernel_task_port, 67 | TASK_DYLD_INFO, (task_info_t) &info, &count); 68 | if (kr != KERN_SUCCESS) { 69 | return false; 70 | } 71 | uint64_t kernel_base = info.all_image_info_addr; 72 | if (is_kernel_base(kernel_base)) { 73 | kernel_slide = info.all_image_info_addr - STATIC_ADDRESS(kernel_base); 74 | goto found_kernel_slide; 75 | } 76 | kernel_base = STATIC_ADDRESS(kernel_base) + info.all_image_info_size; 77 | if (is_kernel_base(kernel_base)) { 78 | kernel_slide = info.all_image_info_size; 79 | goto found_kernel_slide; 80 | } 81 | return false; 82 | found_kernel_slide: 83 | did_set_kernel_slide(); 84 | return true; 85 | } 86 | 87 | // Try to initialize the kernel slide from an address inside the kernel image (and after the kernel 88 | // Mach-O header). 89 | static bool 90 | init_with_kernel_image_address(uint64_t address) { 91 | // Find the highest possible kernel base address that could still correspond to the given 92 | // kernel image address. 93 | uint64_t base = STATIC_ADDRESS(kernel_base); 94 | assert(address > base); 95 | base = base + ((address - base) / kernel_slide_step) * kernel_slide_step; 96 | // Now walk backwards from that kernel base one kernel slide at a time until we find the 97 | // real kernel base. 98 | while (base >= STATIC_ADDRESS(kernel_base)) { 99 | bool found = is_kernel_base(base); 100 | if (found) { 101 | kernel_slide = base - STATIC_ADDRESS(kernel_base); 102 | did_set_kernel_slide(); 103 | return true; 104 | } 105 | base -= kernel_slide_step; 106 | } 107 | return false; 108 | } 109 | 110 | // If we have current_task, then we can find the kernel slide easily by looking up the host port. 111 | static bool 112 | init_with_current_task() { 113 | // Get the address of the host port. 114 | mach_port_t host = mach_host_self(); 115 | assert(MACH_PORT_VALID(host)); 116 | uint64_t host_port; 117 | bool ok = kernel_ipc_port_lookup(current_task, host, &host_port, NULL); 118 | mach_port_deallocate(mach_task_self(), host); 119 | if (!ok) { 120 | return false; 121 | } 122 | // Get the address of realhost. 123 | uint64_t realhost = kernel_read64(host_port + OFFSET(ipc_port, ip_kobject)); 124 | // Initialize with that address. 125 | return init_with_kernel_image_address(realhost); 126 | } 127 | 128 | // Try to find the kernel base using an unsafe heap scan to sample kernel pointers. As suggested by 129 | // the function name, this method is UNSAFE and may panic the device. It should only be used in the 130 | // absence of better options! 131 | static bool 132 | init_with_unsafe_heap_scan() { 133 | WARNING("Could not find the kernel base address"); 134 | WARNING("Trying to find the kernel base address using an unsafe heap scan!"); 135 | uint64_t kernel_region_base = 0xfffffff000000000; 136 | uint64_t kernel_region_end = 0xfffffffbffffc000; 137 | // Try and find a pointer in the kernel heap to data in the kernel image. We'll take the 138 | // smallest such pointer. 139 | uint64_t kernel_ptr = (uint64_t)(-1); 140 | mach_vm_address_t address = 0; 141 | for (;;) { 142 | // Get the next memory region. 143 | mach_vm_size_t size = 0; 144 | uint32_t depth = 2; 145 | struct vm_region_submap_info_64 info; 146 | mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64; 147 | kern_return_t kr = mach_vm_region_recurse(kernel_task_port, &address, &size, 148 | &depth, (vm_region_recurse_info_t) &info, &count); 149 | if (kr != KERN_SUCCESS) { 150 | break; 151 | } 152 | // Skip any region that is not on the heap, not in a submap, not readable and 153 | // writable, or not fully mapped. 154 | int prot = VM_PROT_READ | VM_PROT_WRITE; 155 | if (info.user_tag != 12 156 | || depth != 1 157 | || (info.protection & prot) != prot 158 | || info.pages_resident * 0x4000 != size) { 159 | goto next; 160 | } 161 | // Read the first word of each page in this region. 162 | for (size_t offset = 0; offset < size; offset += 0x4000) { 163 | uint64_t value = 0; 164 | bool ok = kernel_read(address + offset, &value, sizeof(value)); 165 | if (ok 166 | && kernel_region_base <= value 167 | && value < kernel_region_end 168 | && value < kernel_ptr) { 169 | kernel_ptr = value; 170 | } 171 | } 172 | next: 173 | address += size; 174 | } 175 | // If we didn't find any such pointer, abort. 176 | if (kernel_ptr == (uint64_t)(-1)) { 177 | return false; 178 | } 179 | DEBUG_TRACE(1, "Found kernel pointer %p", (void *)kernel_ptr); 180 | // Now that we have a pointer, we want to scan pages until we reach the kernel's Mach-O 181 | // header. Unfortunately, the layout of the kernel differs on different iOS versions. iOS 182 | // 12.4 uses the old kernelcache format; on these kernelcaches, kernel_ptr will usually 183 | // point into one of the __PRELINK sections that lies before the Mach-O header in __TEXT. 184 | // On the other hand, iOS 13 uses the newer kernelcache format in which the __PRELINK 185 | // sections are empty and __TEXT is mapped first, and hence kernel_ptr lies after the 186 | // Mach-O header. We'll program for the newer kernelcache format. 187 | uint64_t page = kernel_ptr & ~0x3fff; 188 | for (;;) { 189 | bool found = is_kernel_base(page); 190 | if (found) { 191 | kernel_slide = page - STATIC_ADDRESS(kernel_base); 192 | did_set_kernel_slide(); 193 | return true; 194 | } 195 | page -= 0x4000; 196 | } 197 | return false; 198 | } 199 | 200 | bool 201 | kernel_slide_init() { 202 | if (kernel_slide != 0) { 203 | return true; 204 | } 205 | // Initialize the parameters. 206 | bool ok = kernel_parameters_init(); 207 | if (!ok) { 208 | return false; 209 | } 210 | // Check if the kernel base is stashed in task_info(TASK_DYLD_INFO). 211 | ok = check_task_dyld_info(); 212 | if (ok) { 213 | return true; 214 | } 215 | // If we have current_task, then we can init with the address of the host port. 216 | if (current_task != 0) { 217 | ok = init_with_current_task(); 218 | if (ok) { 219 | return true; 220 | } 221 | } 222 | // Try an unsafe heap scan. This is a last resort! 223 | ok = init_with_unsafe_heap_scan(); 224 | if (ok) { 225 | return true; 226 | } 227 | // No available method. 228 | ERROR("Could not determine the kernel slide"); 229 | return false; 230 | } 231 | 232 | bool 233 | kernel_slide_init_with_kernel_image_address(uint64_t address) { 234 | if (kernel_slide != 0) { 235 | return true; 236 | } 237 | bool ok = kernel_parameters_init(); 238 | if (!ok) { 239 | return false; 240 | } 241 | ok = init_with_kernel_image_address(address); 242 | if (ok) { 243 | return true; 244 | } 245 | ERROR("Could not determine the kernel slide"); 246 | return false; 247 | } 248 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel/kernel_slide.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef KERNEL_SLIDE__H_ 21 | #define KERNEL_SLIDE__H_ 22 | 23 | #include 24 | #include 25 | 26 | #ifdef KERNEL_SLIDE_EXTERN 27 | #define extern KERNEL_SLIDE_EXTERN 28 | #endif 29 | 30 | /* 31 | * kernel_slide 32 | * 33 | * Description: 34 | * The kASLR slide. 35 | */ 36 | extern uint64_t kernel_slide; 37 | 38 | /* 39 | * kernel_slide_init 40 | * 41 | * Description: 42 | * Find the value of the kernel slide using task_info(TASK_DYLD_INFO) or current_task. 43 | */ 44 | bool kernel_slide_init(void); 45 | 46 | /* 47 | * kernel_slide_init_with_kernel_image_address 48 | * 49 | * Description: 50 | * Find the value of the kernel slide using kernel_read(), starting with an address that is 51 | * known to reside within the kernel image. 52 | */ 53 | bool kernel_slide_init_with_kernel_image_address(uint64_t address); 54 | 55 | #undef extern 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel/kernel_tasks.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #define KERNEL_TASKS_EXTERN 21 | #include "kernel_tasks.h" 22 | 23 | #include 24 | #include 25 | 26 | #include "kernel_memory.h" 27 | #include "kernel_parameters.h" 28 | #include "kernel_slide.h" 29 | #include "log.h" 30 | 31 | // ---- Kernel task functions --------------------------------------------------------------------- 32 | 33 | bool 34 | kernel_ipc_port_lookup(uint64_t task, mach_port_name_t port_name, 35 | uint64_t *ipc_port, uint64_t *ipc_entry) { 36 | // Get the task's ipc_space. 37 | uint64_t itk_space = kernel_read64(task + OFFSET(task, itk_space)); 38 | // Get the size of the table. 39 | uint32_t is_table_size = kernel_read32(itk_space + OFFSET(ipc_space, is_table_size)); 40 | // Get the index of the port and check that it is in-bounds. 41 | uint32_t port_index = MACH_PORT_INDEX(port_name); 42 | if (port_index >= is_table_size) { 43 | return false; 44 | } 45 | // Get the space's is_table and compute the address of this port's entry. 46 | uint64_t is_table = kernel_read64(itk_space + OFFSET(ipc_space, is_table)); 47 | uint64_t entry = is_table + port_index * SIZE(ipc_entry); 48 | if (ipc_entry != NULL) { 49 | *ipc_entry = entry; 50 | } 51 | // Get the address of the port if requested. 52 | if (ipc_port != NULL) { 53 | *ipc_port = kernel_read64(entry + OFFSET(ipc_entry, ie_object)); 54 | } 55 | return true; 56 | } 57 | 58 | // ---- Initialization ---------------------------------------------------------------------------- 59 | 60 | // Try to initialize kernel_task and current_task by walking the allproc list. 61 | static bool 62 | find_kernel_task_and_current_task() { 63 | if (STATIC_ADDRESS(allproc) == 0) { 64 | ERROR("Need allproc address to initialize tasks"); 65 | return false; 66 | } 67 | uint64_t allproc = kernel_read64(STATIC_ADDRESS(allproc) + kernel_slide); 68 | uint64_t kernproc = 0; 69 | uint64_t current_proc = 0; 70 | int current_pid = getpid(); 71 | uint64_t proc = allproc; 72 | for (;;) { 73 | if (proc == 0 || proc == -1) { 74 | break; 75 | } 76 | uint32_t pid = kernel_read32(proc + OFFSET(proc, p_pid)); 77 | if (pid == 0) { 78 | kernproc = proc; 79 | } else if (pid == current_pid) { 80 | current_proc = proc; 81 | } 82 | proc = kernel_read64(proc + OFFSET(proc, p_list_next)); 83 | if (proc == allproc) { 84 | break; 85 | } 86 | } 87 | if (kernproc != 0) { 88 | kernel_task = kernel_read64(kernproc + OFFSET(proc, task)); 89 | } 90 | if (current_proc != 0) { 91 | current_task = kernel_read64(current_proc + OFFSET(proc, task)); 92 | } 93 | return (kernel_task != 0 && current_task != 0); 94 | } 95 | 96 | bool 97 | kernel_tasks_init() { 98 | static bool initialized = false; 99 | if (initialized) { 100 | return true; 101 | } 102 | bool ok = kernel_parameters_init(); 103 | if (!ok) { 104 | return false; 105 | } 106 | ok = find_kernel_task_and_current_task(); 107 | if (!ok) { 108 | return false; 109 | } 110 | initialized = true; 111 | return true; 112 | } 113 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel/kernel_tasks.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef KERNEL_TASKS__H_ 21 | #define KERNEL_TASKS__H_ 22 | 23 | #include 24 | #include 25 | 26 | #ifdef KERNEL_TASKS_EXTERN 27 | #define extern KERNEL_TASKS_EXTERN 28 | #endif 29 | 30 | /* 31 | * kernel_task 32 | * 33 | * Description: 34 | * The address of the kernel_task in kernel memory. 35 | */ 36 | extern uint64_t kernel_task; 37 | 38 | /* 39 | * current_task 40 | * 41 | * Description: 42 | * The address of the current task in kernel memory. 43 | */ 44 | extern uint64_t current_task; 45 | 46 | /* 47 | * kernel_tasks_init 48 | * 49 | * Description: 50 | * Initialize kernel_task and current_task. kernel_slide must already be initialized. 51 | */ 52 | bool kernel_tasks_init(void); 53 | 54 | #undef extern 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel_call/kernel_call.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "kernel_call.h" 21 | 22 | #include 23 | #include 24 | 25 | #include "kernel_call_7_a11.h" 26 | 27 | // ---- Public API -------------------------------------------------------------------------------- 28 | 29 | bool 30 | kernel_call_init() { 31 | bool ok = kernel_call_7_a11_init(); 32 | if (!ok) { 33 | kernel_call_7_a11_deinit(); 34 | } 35 | return ok; 36 | } 37 | 38 | void 39 | kernel_call_deinit() { 40 | kernel_call_7_a11_deinit(); 41 | } 42 | 43 | uint32_t 44 | kernel_call_7(uint64_t function, size_t argument_count, ...) { 45 | assert(argument_count <= 7); 46 | uint64_t arguments[7]; 47 | va_list ap; 48 | va_start(ap, argument_count); 49 | for (size_t i = 0; i < argument_count && i < 7; i++) { 50 | arguments[i] = va_arg(ap, uint64_t); 51 | } 52 | va_end(ap); 53 | return kernel_call_7v(function, argument_count, arguments); 54 | } 55 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel_call/kernel_call.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef KERNEL_CALL__H_ 21 | #define KERNEL_CALL__H_ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | /* 28 | * kernel_call_init 29 | * 30 | * Description: 31 | * Initialize kernel_call functions. 32 | */ 33 | bool kernel_call_init(void); 34 | 35 | /* 36 | * kernel_call_deinit 37 | * 38 | * Description: 39 | * Deinitialize the kernel call subsystem and restore the kernel to a safe state. 40 | */ 41 | void kernel_call_deinit(void); 42 | 43 | /* 44 | * kernel_call_7 45 | * 46 | * Description: 47 | * Call a kernel function with the specified arguments. 48 | * 49 | * Restrictions: 50 | * See kernel_call_7v(). 51 | */ 52 | uint32_t kernel_call_7(uint64_t function, size_t argument_count, ...); 53 | 54 | /* 55 | * kernel_call_7v 56 | * 57 | * Description: 58 | * Call a kernel function with the specified arguments. 59 | * 60 | * Restrictions: 61 | * At most 7 arguments can be passed. 62 | * arguments[0] must be nonzero. 63 | * The return value is truncated to 32 bits. 64 | */ 65 | uint32_t kernel_call_7v(uint64_t function, size_t argument_count, const uint64_t arguments[]); 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel_call/kernel_call_7_a11.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef KERNEL_CALL_7_A11__H_ 21 | #define KERNEL_CALL_7_A11__H_ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | /* 28 | * kernel_call_7_a11_init 29 | * 30 | * Description: 31 | * Initialize kernel_call_7 on A11 (non-PAC) devices. If this fails, still call 32 | * kernel_call_7_a11_deinit(). 33 | * 34 | * Initializes: 35 | * kernel_call_parameters_init() 36 | * kernel_call_7v() 37 | */ 38 | bool kernel_call_7_a11_init(void); 39 | 40 | /* 41 | * kernel_call_7_a11_deinit 42 | * 43 | * Description: 44 | * Deinitialize kernel_call_7 on A11 devices. 45 | */ 46 | void kernel_call_7_a11_deinit(void); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel_call/kernel_call_parameters.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #define KERNEL_CALL_PARAMETERS_EXTERN PARAMETER_SHARED 21 | #include "kernel_call_parameters.h" 22 | 23 | #include "kernel_slide.h" 24 | #include "log.h" 25 | #include "platform_match.h" 26 | 27 | // ---- Offset initialization --------------------------------------------------------------------- 28 | 29 | static void 30 | offsets__iphone10_1__16C101() { 31 | OFFSET(ipc_port, ip_kobject) = 104; 32 | OFFSET(proc, p_ucred) = 0xf8; 33 | OFFSET(task, bsd_info) = 0x358; 34 | SIZE(IOExternalTrap) = 24; 35 | OFFSET(IOExternalTrap, object) = 0; 36 | OFFSET(IOExternalTrap, function) = 8; 37 | OFFSET(IOExternalTrap, offset) = 16; 38 | OFFSET(IORegistryEntry, reserved) = 16; 39 | OFFSET(IORegistryEntry__ExpansionData, fRegistryEntryID) = 8; 40 | VTABLE_INDEX(IOUserClient, getExternalTrapForIndex) = 0x5b8 / 8; 41 | VTABLE_INDEX(IOUserClient, getTargetAndTrapForIndex) = 0x5c0 / 8; 42 | } 43 | 44 | static void 45 | offsets__iphone10_1__17B102() { 46 | OFFSET(ipc_port, ip_kobject) = 104; 47 | OFFSET(proc, p_ucred) = 0x100; 48 | OFFSET(task, bsd_info) = 0x380; 49 | SIZE(IOExternalTrap) = 24; 50 | OFFSET(IOExternalTrap, object) = 0; 51 | OFFSET(IOExternalTrap, function) = 8; 52 | OFFSET(IOExternalTrap, offset) = 16; 53 | OFFSET(IORegistryEntry, reserved) = 16; 54 | OFFSET(IORegistryEntry__ExpansionData, fRegistryEntryID) = 8; 55 | VTABLE_INDEX(IOUserClient, getExternalTrapForIndex) = 0x5c0 / 8; 56 | VTABLE_INDEX(IOUserClient, getTargetAndTrapForIndex) = 0x5c8 / 8; 57 | } 58 | 59 | static struct platform_initialization offsets[] = { 60 | { "iPhone10,1", "16C101-16G77", offsets__iphone10_1__16C101 }, 61 | { "iPhone10,6", "16E227", offsets__iphone10_1__16C101 }, 62 | { "iPhone10,1|iPhone10,4", "17B102-17C54", offsets__iphone10_1__17B102 }, 63 | }; 64 | 65 | // ---- Address initialization -------------------------------------------------------------------- 66 | 67 | #define SLIDE(address) (address == 0 ? 0 : address + kernel_slide) 68 | 69 | static void 70 | addresses__iphone10_1__16C101() { 71 | ADDRESS(mov_x0_x4__br_x5) = SLIDE(0xFFFFFFF006580164); 72 | ADDRESS(IOUserClient__vtable) = SLIDE(0xFFFFFFF0070CC648); 73 | ADDRESS(IORegistryEntry__getRegistryEntryID) = SLIDE(0xFFFFFFF00759424C); 74 | } 75 | 76 | static void 77 | addresses__iphone10_6__16E227() { 78 | ADDRESS(mov_x0_x4__br_x5) = SLIDE(0xFFFFFFF00659E068); 79 | ADDRESS(IOUserClient__vtable) = SLIDE(0xFFFFFFF0070CC818); 80 | ADDRESS(IORegistryEntry__getRegistryEntryID) = SLIDE(0xFFFFFFF0075931F4); 81 | } 82 | 83 | static void 84 | addresses__iphone10_1__16G77() { 85 | ADDRESS(mov_x0_x4__br_x5) = SLIDE(0xFFFFFFF00658D30C); 86 | ADDRESS(IOUserClient__vtable) = SLIDE(0xFFFFFFF0070CC780); 87 | ADDRESS(IORegistryEntry__getRegistryEntryID) = SLIDE(0xFFFFFFF007594320); 88 | } 89 | 90 | static void 91 | addresses__iphone10_1__17B102() { 92 | ADDRESS(IOUserClient__vtable) = SLIDE(0xFFFFFFF00791CCD8); 93 | ADDRESS(IORegistryEntry__getRegistryEntryID) = SLIDE(0xFFFFFFF0080FFDE0); 94 | } 95 | 96 | static void 97 | addresses__iphone10_1__17C54() { 98 | ADDRESS(IOUserClient__vtable) = SLIDE(0xFFFFFFF007920CD8); 99 | ADDRESS(IORegistryEntry__getRegistryEntryID) = SLIDE(0xFFFFFFF00810696C); 100 | } 101 | 102 | static struct platform_initialization addresses[] = { 103 | { "iPhone10,1", "16C101", addresses__iphone10_1__16C101 }, 104 | { "iPhone10,6", "16E227", addresses__iphone10_6__16E227 }, 105 | { "iPhone10,1", "16G77", addresses__iphone10_1__16G77 }, 106 | { "iPhone10,1|iPhone10,4", "17B102", addresses__iphone10_1__17B102 }, 107 | { "iPhone10,1|iPhone10,4", "17C54", addresses__iphone10_1__17C54 }, 108 | }; 109 | 110 | // ---- Public API -------------------------------------------------------------------------------- 111 | 112 | #define ARRAY_COUNT(x) (sizeof(x) / sizeof((x)[0])) 113 | 114 | bool 115 | kernel_call_parameters_init() { 116 | bool ok = kernel_slide_init(); 117 | if (!ok) { 118 | return false; 119 | } 120 | size_t count = run_platform_initializations(offsets, ARRAY_COUNT(offsets)); 121 | if (count < 1) { 122 | ERROR("No kernel_call %s for %s %s", "offsets", 123 | platform.machine, platform.osversion); 124 | return false; 125 | } 126 | count = run_platform_initializations(addresses, ARRAY_COUNT(addresses)); 127 | if (count < 1) { 128 | ERROR("No kernel_call %s for %s %s", "addresses", 129 | platform.machine, platform.osversion); 130 | return false; 131 | } 132 | return true; 133 | } 134 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel_call/kernel_call_parameters.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef KERNEL_CALL_PARAMETERS__H_ 21 | #define KERNEL_CALL_PARAMETERS__H_ 22 | 23 | #include "parameters.h" 24 | 25 | #ifdef KERNEL_CALL_PARAMETERS_EXTERN 26 | #define extern KERNEL_CALL_PARAMETERS_EXTERN 27 | #endif 28 | 29 | extern uint64_t ADDRESS(mov_x0_x4__br_x5); 30 | extern uint64_t ADDRESS(IOUserClient__vtable); 31 | extern uint64_t ADDRESS(IORegistryEntry__getRegistryEntryID); 32 | 33 | // Parameters for struct ipc_port. 34 | extern size_t OFFSET(ipc_port, ip_kobject); 35 | 36 | // Parameters for struct proc. 37 | extern size_t OFFSET(proc, p_ucred); 38 | 39 | // Parameters for struct task. 40 | extern size_t OFFSET(task, bsd_info); 41 | 42 | // Parameters for IOExternalTrap. 43 | extern size_t SIZE(IOExternalTrap); 44 | extern size_t OFFSET(IOExternalTrap, object); 45 | extern size_t OFFSET(IOExternalTrap, function); 46 | extern size_t OFFSET(IOExternalTrap, offset); 47 | 48 | // Parameters for IORegistryEntry. 49 | extern size_t OFFSET(IORegistryEntry, reserved); 50 | extern size_t OFFSET(IORegistryEntry__ExpansionData, fRegistryEntryID); 51 | 52 | // Parameters for IOUserClient. 53 | extern uint32_t VTABLE_INDEX(IOUserClient, getExternalTrapForIndex); 54 | extern uint32_t VTABLE_INDEX(IOUserClient, getTargetAndTrapForIndex); 55 | 56 | /* 57 | * kernel_call_parameters_init 58 | * 59 | * Description: 60 | * Initialize the addresses used in the kernel_call subsystem. 61 | */ 62 | bool kernel_call_parameters_init(void); 63 | 64 | #undef extern 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel_patches/kernel_patches.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "kernel_patches.h" 21 | 22 | #include "kernel_memory.h" 23 | #include "kernel_slide.h" 24 | #include "log.h" 25 | #include "platform_match.h" 26 | 27 | // A structure to describe a patch consisting of a single instruction substitution. 28 | struct instruction_substitution { 29 | uint64_t address; 30 | uint32_t instruction; 31 | }; 32 | 33 | // A helper macro to get the number of elements in a static array. 34 | #define ARRAY_COUNT(x) (sizeof(x) / sizeof((x)[0])) 35 | 36 | // ---- Kernel patches ---------------------------------------------------------------------------- 37 | 38 | // A helper to define a branch instruction. This only works for short ranges! 39 | #define BRANCH(source, target) (0x14000000 | (0x03FFFFFF & (uint32_t)(((int64_t)target - (int64_t)source) / 4))) 40 | 41 | static void 42 | task_for_pid_0__iPhone10_1__16C101() { 43 | INFO("Patching task_for_pid(0)"); 44 | const struct instruction_substitution code_patches[] = { 45 | // task_for_pid(): 46 | // "if (pid == 0)" -> NOP 47 | { 0xFFFFFFF007500F20, 0xD503201F }, 48 | // task_for_pid(): 49 | // "task_for_pid_posix_check(p)" -> NOP 50 | { 0xFFFFFFF007500F44, 0xD503201F }, 51 | // task_for_pid(): 52 | // Skip the inlined code of mac_proc_check_get_task(). 53 | // ADRP X23, #mac_policy_list@PAGE -> B 0xFFFFFFF0075010F8 54 | { 0xFFFFFFF007500F5C, BRANCH(0xFFFFFFF007500F5C, 0xFFFFFFF0075010F8) }, 55 | // convert_port_to_locked_task(): 56 | // "if (caller == victim)" -> "if (caller == caller)" 57 | // CMP X24, X23 -> CMP X24, X24 58 | { 0xFFFFFFF007119530, 0xEB18031F }, 59 | // convert_port_to_task_with_exec_token(): 60 | // "if (caller == victim)" -> "if (caller == caller)" 61 | // CMP X8, X21 -> CMP X8, X8 62 | { 0xFFFFFFF007119730, 0xEB08011F }, 63 | }; 64 | for (size_t i = 0; i < ARRAY_COUNT(code_patches); i++) { 65 | uint64_t address = code_patches[i].address + kernel_slide; 66 | kernel_write32(address, code_patches[i].instruction); 67 | } 68 | } 69 | 70 | static void 71 | i_can_has_debugger__iPhone10_1__16C101() { 72 | INFO("Enabling PE_i_can_has_debugger()"); 73 | uint64_t debug_enabled = 0xFFFFFFF00702D430 + kernel_slide; 74 | kernel_write32(debug_enabled, 1); 75 | } 76 | 77 | // A list of kernel patches to apply by platform. 78 | static struct platform_initialization kernel_patches[] = { 79 | { "iPhone10,1", "16C101", task_for_pid_0__iPhone10_1__16C101 }, 80 | { "iPhone10,1", "16C101", i_can_has_debugger__iPhone10_1__16C101 }, 81 | }; 82 | 83 | // ---- API --------------------------------------------------------------------------------------- 84 | 85 | void 86 | apply_kernel_patches() { 87 | run_platform_initializations(kernel_patches, ARRAY_COUNT(kernel_patches)); 88 | } 89 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel_patches/kernel_patches.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef KERNEL_PATCHES__H_ 21 | #define KERNEL_PATCHES__H_ 22 | 23 | /* 24 | * apply_kernel_patches 25 | * 26 | * Description: 27 | * Apply the kernel patches. 28 | */ 29 | void apply_kernel_patches(void); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel_symbols/iPhone10,1_16C101.txt: -------------------------------------------------------------------------------- 1 | __disable_preemption 0xFFFFFFF00720424C 2 | __enable_preemption 0xFFFFFFF007204260 3 | __mh_execute_header 0xFFFFFFF007004000 4 | _const_boot_args 0xFFFFFFF0070B9548 5 | _IOSleep 0xFFFFFFF007588B4C 6 | _kernel_map 0xFFFFFFF007666080 7 | _kernel_memory_allocate 0xFFFFFFF007197F4C 8 | _kernel_thread_start 0xFFFFFFF0071435EC 9 | _ml_nofault_copy 0xFFFFFFF00720A5B0 10 | _panic 0xFFFFFFF007112278 11 | _paniclog_append_noflush 0xFFFFFFF007120568 12 | _thread_deallocate 0xFFFFFFF007140FFC 13 | _vsnprintf 0xFFFFFFF0074A1ED8 14 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel_symbols/iPhone10,1_16G77.txt: -------------------------------------------------------------------------------- 1 | __disable_preemption 0xFFFFFFF007203050 2 | __enable_preemption 0xFFFFFFF007203064 3 | __mh_execute_header 0xFFFFFFF007004000 4 | _const_boot_args 0xFFFFFFF0070B9558 5 | _IOSleep 0xFFFFFFF007589040 6 | _kernel_map 0xFFFFFFF007663080 7 | _kernel_memory_allocate 0xFFFFFFF0071995FC 8 | _kernel_thread_start 0xFFFFFFF007143F58 9 | _ml_nofault_copy 0xFFFFFFF007209324 10 | _panic 0xFFFFFFF00711207C 11 | _paniclog_append_noflush 0xFFFFFFF0071209B0 12 | _thread_deallocate 0xFFFFFFF0071419B4 13 | _vsnprintf 0xFFFFFFF0074A2384 14 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kernel_symbols/iPhone10,6_16E227.txt: -------------------------------------------------------------------------------- 1 | __disable_preemption 0xFFFFFFF007202A84 2 | __enable_preemption 0xFFFFFFF007202A98 3 | __mh_execute_header 0xFFFFFFF007004000 4 | _const_boot_args 0xFFFFFFF0070B9558 5 | _IOSleep 0xFFFFFFF007587F14 6 | _kernel_map 0xFFFFFFF007663080 7 | _kernel_memory_allocate 0xFFFFFFF007198050 8 | _kernel_thread_start 0xFFFFFFF007143B3C 9 | _ml_nofault_copy 0xFFFFFFF007208D4C 10 | _panic 0xFFFFFFF007111E7C 11 | _paniclog_append_noflush 0xFFFFFFF00712059C 12 | _thread_deallocate 0xFFFFFFF00714159C 13 | _vsnprintf 0xFFFFFFF0074A1138 14 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kext_load/kext_load.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef KEXT_LOAD__H_ 21 | #define KEXT_LOAD__H_ 22 | 23 | #include 24 | #include 25 | 26 | /* 27 | * kext_load_set_kernel_symbol_database 28 | * 29 | * Description: 30 | * Set the path to the kernel symbols database. 31 | */ 32 | bool kext_load_set_kernel_symbol_database(const char *path); 33 | 34 | /* 35 | * kext_load 36 | * 37 | * Description: 38 | * Dynamically load a Mach-O file into the kernel and call its entry point function. The 39 | * address of the kernel extension in kernel memory is returned. 40 | * 41 | * The "kext" file isn't a true kext in the sense of a macOS kernel extension. Rather, it's a 42 | * binary that conforms to certain formatting standards that allow us to map it into kernel 43 | * memory and resolve its symbols from a kernel image symbol database. 44 | * 45 | * Compiling the kext: 46 | * In order to be loadable, the Mach-O must be compiled as position-independent arm64. Use the 47 | * following CFLAGS: 48 | * 49 | * -arch arm64 -fno-builtin -fno-common -mkernel 50 | * 51 | * For linking you'll want the following LDFLAGS: 52 | * 53 | * -Xlinker -kext -nostdlib -Xlinker -fatal_warnings 54 | * 55 | * In the source of the kext, mark any kernel symbols that need to be resolved at link time 56 | * with: 57 | * 58 | * extern __attribute__((weak_import)) 59 | * 60 | * The entry point should be a function _kext_start() with the following prototype: 61 | * 62 | * uint32_t _kext_start(uint64_t argument) 63 | * 64 | * Linking the kext: 65 | * Symbols in the kext are resolved to their runtime values by consulting the appropriate 66 | * symbol database for the device and OS version located in the kernel_symbols/ directory. 67 | * 68 | * In the kext, you can dynamically check whether the external symbol was resolved by testing 69 | * its address: if the address of the symbol is 0, then it is unresolved and should not be 70 | * used. 71 | * 72 | * Loading the kext: 73 | * The kext is loaded into kernel memory and then virtual memory protections are set according 74 | * to the protections in each segment command. The _kext_start() function is then called from 75 | * userspace using kernel_call_7(). _kext_start() will be supplied the 64-bit argument value 76 | * given to kext_load(). 77 | * 78 | * Unloading the kext: 79 | * TODO: Not yet supported. 80 | */ 81 | uint64_t kext_load(const char *file, uint64_t argument); 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kext_load/resolve_symbol.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "resolve_symbol.h" 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "bundle_path.h" 28 | #include "log.h" 29 | #include "map_file.h" 30 | #include "platform.h" 31 | 32 | 33 | // ---- Internal functions ------------------------------------------------------------------------ 34 | 35 | // The mapped database file. 36 | static void *symbol_database = NULL; 37 | static size_t symbol_database_size = 0; 38 | 39 | /* 40 | * lookup_symbol 41 | * 42 | * Description: 43 | * Parses the memory-mapped database file line-by-line looking for the matching symbol. 44 | */ 45 | static uint64_t 46 | lookup_symbol(const char *name) { 47 | const char *str = symbol_database; 48 | const char *const end = str + symbol_database_size; 49 | // Each iteration of this loop starts at the beginning of a line. 50 | for (;;) { 51 | char ch; 52 | // At the start of the line. Skip any leading whitespace. 53 | for (;;) { 54 | if (str >= end) { 55 | return 0; 56 | } 57 | ch = *str; 58 | if (ch != ' ' && ch != '\t') { 59 | break; 60 | } 61 | str++; 62 | } 63 | // At the symbol name. 64 | const char *p = name; 65 | for (;;) { 66 | if (*p == 0) { 67 | break; 68 | } 69 | if (*p != ch) { 70 | goto next_line; 71 | } 72 | p++; 73 | str++; 74 | if (str >= end) { 75 | return 0; 76 | } 77 | ch = *str; 78 | } 79 | // Matched the name. Consume some whitespace. 80 | if (ch != ' ' && ch != '\t') { 81 | // Not a match. 82 | goto next_line; 83 | } 84 | for (;;) { 85 | str++; 86 | if (str >= end) { 87 | return 0; 88 | } 89 | ch = *str; 90 | if (ch != ' ' && ch != '\t') { 91 | break; 92 | } 93 | } 94 | // Matched the name plus whitespace. Extract the value. 95 | uint64_t value = 0; 96 | if (str + 2 + 16 > end) { 97 | goto next_line; 98 | } 99 | if (ch != '0') { 100 | goto next_line; 101 | } 102 | str++; 103 | ch = *str; 104 | if (ch != 'x') { 105 | goto next_line; 106 | } 107 | str++; 108 | ch = *str; 109 | for (size_t i = 0;;) { 110 | uint64_t digit; 111 | if ('0' <= ch && ch <= '9') { 112 | digit = ch - '0'; 113 | } else if ('a' <= ch && ch <= 'f') { 114 | digit = ch - 'a' + 0xa; 115 | } else if ('A' <= ch && ch <= 'F') { 116 | digit = ch - 'A' + 0xa; 117 | } else { 118 | goto next_line; 119 | } 120 | value = (value << 4) | digit; 121 | i++; 122 | str++; 123 | if (i >= 16) { 124 | break; 125 | } 126 | if (str >= end) { 127 | return 0; 128 | } 129 | ch = *str; 130 | } 131 | // Alright, we have a value! Make sure that we don't have more. 132 | if (str >= end) { 133 | return value; 134 | } 135 | ch = *str; 136 | if (ch != ' ' && ch != '\t' && ch != '\n') { 137 | WARNING("Invalid value for symbol %s", name); 138 | return 0; 139 | } 140 | // Correctly formatted value! 141 | return value; 142 | // Find the next newline character and then skip it to start the next line. 143 | next_line: 144 | for (;;) { 145 | if (str >= end) { 146 | return 0; 147 | } 148 | if (ch == '\n') { 149 | break; 150 | } 151 | str++; 152 | ch = *str; 153 | } 154 | str++; 155 | } 156 | } 157 | 158 | // ---- Public API -------------------------------------------------------------------------------- 159 | 160 | bool 161 | load_symbol_database(const char *database_path) { 162 | if (symbol_database != NULL) { 163 | return true; 164 | } 165 | platform_init(); 166 | char symbol_file_path[1024]; 167 | snprintf(symbol_file_path, sizeof(symbol_file_path), "%s/%s_%s.txt", 168 | database_path, platform.machine, platform.osversion); 169 | symbol_database = map_file(symbol_file_path, &symbol_database_size); 170 | if (symbol_database == NULL) { 171 | WARNING("No kernel symbol database for %s %s", platform.machine, platform.osversion); 172 | return false; 173 | } 174 | return true; 175 | } 176 | 177 | uint64_t 178 | resolve_symbol(const char *symbol) { 179 | return lookup_symbol(symbol); 180 | } 181 | -------------------------------------------------------------------------------- /ktrw_kext_loader/kext_load/resolve_symbol.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef RESOLVE_SYMBOL__H_ 21 | #define RESOLVE_SYMBOL__H_ 22 | 23 | #include 24 | #include 25 | 26 | /* 27 | * load_symbol_database 28 | * 29 | * Description: 30 | * Tries to load the symbol database for this platform. 31 | */ 32 | bool load_symbol_database(const char *database_path); 33 | 34 | /* 35 | * resolve_symbol 36 | * 37 | * Description: 38 | * Resolves a symbol in the kernel image to its static (unslid) address. 39 | * 40 | * The appropriate database must be loaded first with load_symbol_database(). 41 | */ 42 | uint64_t resolve_symbol(const char *symbol); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /ktrw_kext_loader/ktrr/ktrr_bypass.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef KTRR_BYPASS__H_ 21 | #define KTRR_BYPASS__H_ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | /* 28 | * have_ktrr_bypass 29 | * 30 | * Description: 31 | * Checks whether a KTRR bypass is available for this platform. Only A11 devices are confirmed 32 | * to have the necessary debug registers accessible. 33 | */ 34 | bool have_ktrr_bypass(void); 35 | 36 | /* 37 | * ktrr_bypass 38 | * 39 | * Description: 40 | * Disables KTRR and remaps the RoRgn to be writable. 41 | * 42 | * Implementation: 43 | * KTRR is disabled using the CoreSight External Debug registers along with a proprietary 44 | * register called DBGWRAP. These registers allow placing a CPU core into a debug state in 45 | * which register values can be inspected and modified and execution can be single-stepped. By 46 | * single-stepping through execution of the reset vector after a core resets, we can subvert 47 | * initialization of KTRR and specify a custom page table base to be written to TTBR1_EL1, 48 | * allowing the kernel to be remapped to new physical pages outside of the AMCC-protected 49 | * RoRgn. 50 | * 51 | * Limitations: 52 | * Note that these changes only persist while the device is plugged in and active; changes may 53 | * be lost (leaking memory and possibly leaving the system unstable) anytime after sleeping. 54 | * In particular, once the debug power domain is switched off, the debug registers will reset, 55 | * losing state which prevents the CPU cores from resetting. It is possible to work around 56 | * this restriction for a fully persistent KTRR bypass, but I have not implemented that here. 57 | */ 58 | void ktrr_bypass(void); 59 | 60 | /* 61 | * ktrr_vm_protect 62 | * 63 | * Description: 64 | * Set virtual memory protection on an address range. 65 | * 66 | * This is stronger than kernel_vm_protect() since it can be used to make memory executable. 67 | */ 68 | void ktrr_vm_protect(uint64_t address, size_t size, int prot); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /ktrw_kext_loader/ktrr/ktrr_bypass_parameters.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #define KTRR_BYPASS_PARAMETERS_EXTERN PARAMETER_SHARED 21 | #include "ktrr_bypass_parameters.h" 22 | 23 | #include 24 | 25 | #include "kernel_memory.h" 26 | #include "kernel_slide.h" 27 | #include "log.h" 28 | #include "platform_match.h" 29 | 30 | // ---- Offset initialization --------------------------------------------------------------------- 31 | 32 | static void 33 | offsets__iphone10_1__16C101() { 34 | SIZE(cpu_data_entry) = 16; 35 | OFFSET(cpu_data_entry, cpu_data_vaddr) = 8; 36 | OFFSET(cpu_data, cpu_regmap_paddr) = 61 * 8; 37 | OFFSET(cpu_data, ed_mmio) = 57 * 8; 38 | OFFSET(cpu_data, utt_mmio) = 60 * 8; 39 | } 40 | 41 | static void 42 | offsets__iphone10_1__17B102() { 43 | SIZE(cpu_data_entry) = 16; 44 | OFFSET(cpu_data_entry, cpu_data_vaddr) = 8; 45 | OFFSET(cpu_data, cpu_regmap_paddr) = 63 * 8; 46 | OFFSET(cpu_data, ed_mmio) = 59 * 8; 47 | OFFSET(cpu_data, utt_mmio) = 62 * 8; 48 | } 49 | 50 | static struct platform_initialization offsets[] = { 51 | { "iPhone10,1", "16C101-16G77", offsets__iphone10_1__16C101 }, 52 | { "iPhone10,6", "16E227", offsets__iphone10_1__16C101 }, 53 | { "iPhone10,1|iPhone10,4", "17B102-17C54", offsets__iphone10_1__17B102 }, 54 | }; 55 | 56 | // ---- KTRR parameter initialization ------------------------------------------------------------- 57 | 58 | #define SLIDE(address) (address == 0 ? 0 : address + kernel_slide) 59 | 60 | static void 61 | parameters__iphone10_1__16C101() { 62 | gPhysBase = kernel_read64(SLIDE(0xFFFFFFF0070B96D8)); 63 | gVirtBase = kernel_read64(SLIDE(0xFFFFFFF0070B96E0)); 64 | rorgn_begin = kernel_read64(SLIDE(0xFFFFFFF0070B99B8)); 65 | rorgn_end = kernel_read64(SLIDE(0xFFFFFFF0070B99C0)); 66 | cpu_ttep = kernel_read64(SLIDE(0xFFFFFFF0070B9488)); 67 | kernel_pmap = kernel_read64(SLIDE(0xFFFFFFF0070B9468)); 68 | ADDRESS(pmap_find_phys) = SLIDE(0xFFFFFFF0071F88AC); 69 | ADDRESS(ml_phys_read_data) = SLIDE(0xFFFFFFF007203CAC); 70 | ADDRESS(ml_phys_write_data) = SLIDE(0xFFFFFFF007203F14); 71 | ADDRESS(ml_io_map) = SLIDE(0xFFFFFFF0072095CC); 72 | ADDRESS(ldr_w0_x0__ret) = SLIDE(0xFFFFFFF00711EE60); 73 | ADDRESS(str_w1_x0__ret) = SLIDE(0xFFFFFFF0061DF26C); 74 | ADDRESS(CpuDataEntries) = SLIDE(0xFFFFFFF007634000); 75 | } 76 | 77 | static void 78 | parameters__iphone10_6__16E227() { 79 | gPhysBase = kernel_read64(SLIDE(0xFFFFFFF0070B96E8)); 80 | gVirtBase = kernel_read64(SLIDE(0xFFFFFFF0070B96F0)); 81 | rorgn_begin = kernel_read64(SLIDE(0xFFFFFFF0070B99C8)); 82 | rorgn_end = kernel_read64(SLIDE(0xFFFFFFF0070B99D0)); 83 | cpu_ttep = kernel_read64(SLIDE(0xFFFFFFF0070B9498)); 84 | kernel_pmap = kernel_read64(SLIDE(0xFFFFFFF0070B9478)); 85 | ADDRESS(pmap_find_phys) = SLIDE(0xFFFFFFF0071F74A4); 86 | ADDRESS(ml_phys_read_data) = SLIDE(0xFFFFFFF0072024F4); 87 | ADDRESS(ml_phys_write_data) = SLIDE(0xFFFFFFF007202754); 88 | ADDRESS(ml_io_map) = SLIDE(0xFFFFFFF007207EE0); 89 | ADDRESS(ldr_w0_x0__ret) = SLIDE(0xFFFFFFF00711EE6C); 90 | ADDRESS(str_w1_x0__ret) = SLIDE(0xFFFFFFF0061C600C); 91 | ADDRESS(CpuDataEntries) = SLIDE(0xFFFFFFF0076ACD38); 92 | } 93 | 94 | static void 95 | parameters__iphone10_1__16G77() { 96 | gPhysBase = kernel_read64(SLIDE(0xFFFFFFF0070B96E8)); 97 | gVirtBase = kernel_read64(SLIDE(0xFFFFFFF0070B96F0)); 98 | rorgn_begin = kernel_read64(SLIDE(0xFFFFFFF0070B99C8)); 99 | rorgn_end = kernel_read64(SLIDE(0xFFFFFFF0070B99D0)); 100 | cpu_ttep = kernel_read64(SLIDE(0xFFFFFFF0070B9498)); 101 | kernel_pmap = kernel_read64(SLIDE(0xFFFFFFF0070B9478)); 102 | ADDRESS(pmap_find_phys) = SLIDE(0xFFFFFFF0071F75D4); 103 | ADDRESS(ml_phys_read_data) = SLIDE(0xFFFFFFF007202AC0); 104 | ADDRESS(ml_phys_write_data) = SLIDE(0xFFFFFFF007202D20); 105 | ADDRESS(ml_io_map) = SLIDE(0xFFFFFFF0072084AC); 106 | ADDRESS(ldr_w0_x0__ret) = SLIDE(0xFFFFFFF00711F1D4); 107 | ADDRESS(str_w1_x0__ret) = SLIDE(0xFFFFFFF00711F280); 108 | ADDRESS(CpuDataEntries) = SLIDE(0xFFFFFFF0076ACD48); 109 | } 110 | 111 | static void 112 | parameters__iphone10_1__17B102() { 113 | gPhysBase = kernel_read64(SLIDE(0xFFFFFFF007906B68)); 114 | gVirtBase = kernel_read64(SLIDE(0xFFFFFFF007906B70)); 115 | rorgn_begin = kernel_read64(SLIDE(0xFFFFFFF007906E58)); 116 | rorgn_end = kernel_read64(SLIDE(0xFFFFFFF007906E60)); 117 | cpu_ttep = kernel_read64(SLIDE(0xFFFFFFF0079067C0)); 118 | kernel_pmap = kernel_read64(SLIDE(0xFFFFFFF0079067A0)); 119 | ADDRESS(pmap_find_phys) = SLIDE(0xFFFFFFF007CC39CC); 120 | ADDRESS(ml_phys_read_data) = SLIDE(0xFFFFFFF007CCFF0C); 121 | ADDRESS(ml_phys_write_data) = SLIDE(0xFFFFFFF007CD01B0); 122 | ADDRESS(ml_io_map) = SLIDE(0xFFFFFFF007CD5864); 123 | ADDRESS(ldr_w0_x0__ret) = SLIDE(0xFFFFFFF007BD2EFC); 124 | ADDRESS(str_w1_x0__ret) = SLIDE(0xFFFFFFF007BD2F80); 125 | ADDRESS(CpuDataEntries) = SLIDE(0xFFFFFFF0091CACB8); 126 | } 127 | 128 | static void 129 | parameters__iphone10_1__17C54() { 130 | gPhysBase = kernel_read64(SLIDE(0xFFFFFFF00790AB68)); 131 | gVirtBase = kernel_read64(SLIDE(0xFFFFFFF00790AB70)); 132 | rorgn_begin = kernel_read64(SLIDE(0xFFFFFFF00790AE58)); 133 | rorgn_end = kernel_read64(SLIDE(0xFFFFFFF00790AE60)); 134 | cpu_ttep = kernel_read64(SLIDE(0xFFFFFFF00790A7C0)); 135 | kernel_pmap = kernel_read64(SLIDE(0xFFFFFFF00790A7A0)); 136 | ADDRESS(pmap_find_phys) = SLIDE(0xFFFFFFF007CCBDAC); 137 | ADDRESS(ml_phys_read_data) = SLIDE(0xFFFFFFF007CD83EC); 138 | ADDRESS(ml_phys_write_data) = SLIDE(0xFFFFFFF007CD8690); 139 | ADDRESS(ml_io_map) = SLIDE(0xFFFFFFF007CDDD44); 140 | ADDRESS(ldr_w0_x0__ret) = SLIDE(0xFFFFFFF007BDAF34); 141 | ADDRESS(str_w1_x0__ret) = SLIDE(0xFFFFFFF007BDAFB8); 142 | ADDRESS(CpuDataEntries) = SLIDE(0xFFFFFFF0091D2C98); 143 | } 144 | 145 | static struct platform_initialization parameters[] = { 146 | { "iPhone10,1", "16C101", parameters__iphone10_1__16C101 }, 147 | { "iPhone10,6", "16E227", parameters__iphone10_6__16E227 }, 148 | { "iPhone10,1", "16G77", parameters__iphone10_1__16G77 }, 149 | { "iPhone10,1|iPhone10,4", "17B102", parameters__iphone10_1__17B102 }, 150 | { "iPhone10,1|iPhone10,4", "17C54", parameters__iphone10_1__17C54 }, 151 | }; 152 | 153 | // ---- Public API -------------------------------------------------------------------------------- 154 | 155 | #define ARRAY_COUNT(x) (sizeof(x) / sizeof((x)[0])) 156 | 157 | bool 158 | ktrr_bypass_parameters_init() { 159 | static bool initialized = false; 160 | if (initialized) { 161 | return true; 162 | } 163 | assert(kernel_slide != 0); 164 | size_t count = run_platform_initializations(offsets, ARRAY_COUNT(offsets)); 165 | if (count < 1) { 166 | ERROR("No KTRR bypass %s for %s %s", "offests", 167 | platform.machine, platform.osversion); 168 | return false; 169 | } 170 | count = run_platform_initializations(parameters, ARRAY_COUNT(parameters)); 171 | if (count < 1) { 172 | ERROR("No KTRR bypass %s for %s %s", "parameters", 173 | platform.machine, platform.osversion); 174 | return false; 175 | } 176 | initialized = true; 177 | return true; 178 | } 179 | -------------------------------------------------------------------------------- /ktrw_kext_loader/ktrr/ktrr_bypass_parameters.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef KTRR_BYPASS_PARAMETERS__H_ 21 | #define KTRR_BYPASS_PARAMETERS__H_ 22 | 23 | #include "log.h" 24 | #include "parameters.h" 25 | 26 | #ifdef KTRR_BYPASS_PARAMETERS_EXTERN 27 | #define extern KTRR_BYPASS_PARAMETERS_EXTERN 28 | #endif 29 | 30 | extern uint64_t gPhysBase; 31 | extern uint64_t gVirtBase; 32 | extern uint64_t rorgn_begin; 33 | extern uint64_t rorgn_end; 34 | extern uint64_t cpu_ttep; 35 | extern uint64_t kernel_pmap; 36 | extern uint64_t ADDRESS(pmap_find_phys); 37 | extern uint64_t ADDRESS(ml_phys_read_data); 38 | extern uint64_t ADDRESS(ml_phys_write_data); 39 | extern uint64_t ADDRESS(ml_io_map); 40 | extern uint64_t ADDRESS(ldr_w0_x0__ret); 41 | extern uint64_t ADDRESS(str_w1_x0__ret); 42 | extern uint64_t ADDRESS(CpuDataEntries); 43 | extern size_t SIZE(cpu_data_entry); 44 | extern size_t OFFSET(cpu_data_entry, cpu_data_vaddr); 45 | extern size_t OFFSET(cpu_data, cpu_regmap_paddr); 46 | extern size_t OFFSET(cpu_data, ed_mmio); 47 | extern size_t OFFSET(cpu_data, utt_mmio); 48 | 49 | /* 50 | * ktrr_bypass_parameters_init 51 | * 52 | * Description: 53 | * Initialize the parameters used in the KTRR bypass. 54 | */ 55 | bool ktrr_bypass_parameters_init(void); 56 | 57 | #undef extern 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /ktrw_kext_loader/ktrw_kext_loader.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | get-task-allow 6 | 7 | task_for_pid-allow 8 | 9 | platform-application 10 | 11 | com.apple.private.security.container-required 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ktrw_kext_loader/ktrw_kext_loader.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ktrw_kext_loader/ktrw_kext_loader.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ktrw_kext_loader/ktrw_kext_loader.xcodeproj/xcshareddata/xcschemes/ktrw_kext_loader.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ktrw_kext_loader/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "kernel_call.h" 4 | #include "kernel_memory.h" 5 | #include "kernel_patches.h" 6 | #include "kext_load.h" 7 | #include "ktrr_bypass.h" 8 | #include "log.h" 9 | 10 | int main(int argc, const char *argv[]) { 11 | int ret = 1; 12 | // Parse arguments. 13 | if (argc != 2) { 14 | printf("usage: %s \n", argv[0]); 15 | goto done_0; 16 | } 17 | const char *kext_path = argv[1]; 18 | // Load the kernel symbol database. 19 | bool ok = kext_load_set_kernel_symbol_database("kernel_symbols"); 20 | if (!ok) { 21 | ERROR("Could not load kernel symbol database"); 22 | goto done_0; 23 | } 24 | // Try to get the kernel task port using task_for_pid(). 25 | kernel_task_port = MACH_PORT_NULL; 26 | task_for_pid(mach_task_self(), 0, &kernel_task_port); 27 | if (kernel_task_port == MACH_PORT_NULL) { 28 | ERROR("Could not get kernel task port"); 29 | goto done_0; 30 | } 31 | INFO("task_for_pid(0) = 0x%x", kernel_task_port); 32 | // Initialize our kernel function calling capability. 33 | ok = kernel_call_init(); 34 | if (!ok) { 35 | ERROR("Could not initialize kernel_call subsystem"); 36 | goto done_0; 37 | } 38 | // TODO: Check if we've already bypassed KTRR. 39 | // Ensure that we have a KTRR bypass. 40 | ok = have_ktrr_bypass(); 41 | if (!ok) { 42 | ERROR("No KTRR bypass is available for this platform"); 43 | goto done_1; 44 | } 45 | // Bypass KTRR and remap the kernel as read/write. 46 | ktrr_bypass(); 47 | // Apply kernel patches. 48 | apply_kernel_patches(); 49 | // Load the kernel extension. 50 | uint64_t kext_address = kext_load(kext_path, 171); 51 | if (kext_address == 0) { 52 | ERROR("Could not load kext %s", kext_path); 53 | goto done_1; 54 | } 55 | INFO("Kext %s loaded at address 0x%016llx", kext_path, kext_address); 56 | ret = 0; 57 | done_1: 58 | // De-initialize our kernel function calling primitive. 59 | kernel_call_deinit(); 60 | done_0: 61 | return ret; 62 | } 63 | -------------------------------------------------------------------------------- /ktrw_kext_loader/system/bundle_path.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "bundle_path.h" 21 | 22 | #include 23 | 24 | void 25 | get_bundle_path(char *buffer, size_t size) { 26 | CFBundleRef bundle = CFBundleGetMainBundle(); 27 | CFURLRef url = CFBundleCopyBundleURL(bundle); 28 | CFURLGetFileSystemRepresentation(url, true, (UInt8 *)buffer, size); 29 | CFRelease(url); 30 | } 31 | -------------------------------------------------------------------------------- /ktrw_kext_loader/system/bundle_path.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef BUNDLE_PATH__H_ 21 | #define BUNDLE_PATH__H_ 22 | 23 | #include 24 | 25 | /* 26 | * get_bundle_path 27 | * 28 | * Description: 29 | * Copy the absolute path to the bundle directory (without the trailing slash) into the 30 | * specified buffer. 31 | */ 32 | void get_bundle_path(char *buffer, size_t size); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /ktrw_kext_loader/system/log.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "log.h" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | void 27 | log_internal(char type, const char *format, ...) { 28 | if (log_implementation != NULL) { 29 | va_list ap; 30 | va_start(ap, format); 31 | log_implementation(type, format, ap); 32 | va_end(ap); 33 | } 34 | } 35 | 36 | // The default logging implementation prints to stderr with a nice hacker prefix. 37 | static void 38 | log_stderr(char type, const char *format, va_list ap) { 39 | char *message = NULL; 40 | vasprintf(&message, format, ap); 41 | assert(message != NULL); 42 | switch (type) { 43 | case 'D': type = 'D'; break; 44 | case 'I': type = '+'; break; 45 | case 'W': type = '!'; break; 46 | case 'E': type = '-'; break; 47 | } 48 | fprintf(stderr, "[%c] %s\n", type, message); 49 | free(message); 50 | } 51 | 52 | void (*log_implementation)(char type, const char *format, va_list ap) = log_stderr; 53 | -------------------------------------------------------------------------------- /ktrw_kext_loader/system/log.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef LOG__H_ 21 | #define LOG__H_ 22 | 23 | #include 24 | #include 25 | 26 | /* 27 | * log_implementation 28 | * 29 | * Description: 30 | * This is the log handler that will be executed when code wants to log a message. The default 31 | * implementation logs the message to stderr. Setting this value to NULL will disable all 32 | * logging. Specify a custom log handler to process log messages in another way. 33 | * 34 | * Parameters: 35 | * type A character representing the type of message that is being 36 | * logged. 37 | * format A printf-style format string describing the error message. 38 | * ap The variadic argument list for the format string. 39 | * 40 | * Log Type: 41 | * The type parameter is one of: 42 | * - D: Debug: Used for debugging messages. Set the DEBUG build variable to control debug 43 | * verbosity. 44 | * - I: Info: Used to convey general information about the exploit or its progress. 45 | * - W: Warning: Used to indicate that an unusual but possibly recoverable condition was 46 | * encountered. 47 | * - E: Error: Used to indicate that an unrecoverable error was encountered. The code 48 | * might continue running after an error was encountered, but it probably will 49 | * not succeed. 50 | */ 51 | extern void (*log_implementation)(char type, const char *format, va_list ap); 52 | 53 | #define DEBUG_LEVEL(level) (DEBUG && level <= DEBUG) 54 | 55 | #if DEBUG 56 | #define DEBUG_TRACE(level, fmt, ...) \ 57 | do { \ 58 | if (DEBUG_LEVEL(level)) { \ 59 | log_internal('D', fmt, ##__VA_ARGS__); \ 60 | } \ 61 | } while (0) 62 | #else 63 | #define DEBUG_TRACE(level, fmt, ...) do {} while (0) 64 | #endif 65 | #define INFO(fmt, ...) log_internal('I', fmt, ##__VA_ARGS__) 66 | #define WARNING(fmt, ...) log_internal('W', fmt, ##__VA_ARGS__) 67 | #define ERROR(fmt, ...) log_internal('E', fmt, ##__VA_ARGS__) 68 | 69 | // A function to call the logging implementation. 70 | void log_internal(char type, const char *format, ...) __printflike(2, 3); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /ktrw_kext_loader/system/map_file.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "map_file.h" 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "log.h" 31 | 32 | 33 | void * 34 | map_file(const char *path, size_t *size) { 35 | int fd = open(path, O_RDONLY); 36 | if (fd < 0) { 37 | ERROR("Could not open file \"%s\": %s", path, strerror(errno)); 38 | return NULL; 39 | } 40 | struct stat st; 41 | int err = fstat(fd, &st); 42 | if (err != 0) { 43 | ERROR("Could not stat file \"%s\": %s", path, strerror(errno)); 44 | close(fd); 45 | return NULL; 46 | } 47 | size_t file_size = st.st_size; 48 | void *data = mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 49 | close(fd); 50 | if (data == MAP_FAILED) { 51 | ERROR("Could not map file \"%s\": %s", path, strerror(errno)); 52 | return NULL; 53 | } 54 | *size = file_size; 55 | return data; 56 | } 57 | 58 | void 59 | unmap_file(void *data, size_t size) { 60 | munmap(data, size); 61 | } 62 | -------------------------------------------------------------------------------- /ktrw_kext_loader/system/map_file.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef MAP_FILE__H_ 21 | #define MAP_FILE__H_ 22 | 23 | #include 24 | 25 | /* 26 | * map_file 27 | * 28 | * Description: 29 | * Maps the specified file into memory. Returns the address and size of the mapping. 30 | */ 31 | void *map_file(const char *path, size_t *size); 32 | 33 | /* 34 | * unmap_file 35 | * 36 | * Description: 37 | * Unmap a file mapped with map_file(). 38 | */ 39 | void unmap_file(void *data, size_t size); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /ktrw_kext_loader/system/parameters.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef PARAMETERS__H_ 21 | #define PARAMETERS__H_ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "platform.h" 28 | 29 | // Marks a parameter as a weak symbol, allowing multiple non-conflicting definitions. 30 | #define PARAMETER_SHARED __attribute__((weak)) 31 | 32 | // Generate the name for an offset. 33 | #define OFFSET(base_, object_) _##base_##__##object_##__offset_ 34 | 35 | // Generate the name for the size of an object. 36 | #define SIZE(object_) _##object_##__size_ 37 | 38 | // Generate the name for the address of an object. 39 | #define ADDRESS(object_) _##object_##__address_ 40 | 41 | // Generate the name for the static (unslid) address of an object. 42 | #define STATIC_ADDRESS(object_) _##object_##__static_address_ 43 | 44 | // A structure describing the PAC codes used as part of the context for signing and verifying 45 | // virtual method pointers in a vtable. 46 | struct vtable_pac_codes { 47 | size_t count; 48 | const uint16_t *codes; 49 | }; 50 | 51 | // Generate the name for an offset in a virtual method table. 52 | #define VTABLE_INDEX(class_, method_) _##class_##_##method_##__vtable_index_ 53 | 54 | // Generate the name for a list of vtable PAC codes. 55 | #define VTABLE_PAC_CODES(class_) _##class_##__vtable_pac_codes_ 56 | 57 | // A helper macro for INIT_VTABLE_PAC_CODES(). 58 | #define VTABLE_PAC_CODES_DATA(class_) _##class_##__vtable_pac_codes_data_ 59 | 60 | // Initialize a list of vtable PAC codes. In order to store the PAC code array in constant memory, 61 | // we place it in a static variable. Consequently, this macro will produce name conflicts if used 62 | // outside a function. 63 | #define INIT_VTABLE_PAC_CODES(class_, ...) \ 64 | static const uint16_t VTABLE_PAC_CODES_DATA(class_)[] = { __VA_ARGS__ }; \ 65 | VTABLE_PAC_CODES(class_) = (struct vtable_pac_codes) { \ 66 | .count = sizeof(VTABLE_PAC_CODES_DATA(class_)) / sizeof(uint16_t), \ 67 | .codes = (const uint16_t *) VTABLE_PAC_CODES_DATA(class_), \ 68 | } 69 | 70 | // A convenience macro for accessing a field of a structure. 71 | #define FIELD(object_, struct_, field_, type_) \ 72 | ( *(type_ *) ( ((uint8_t *) object_) + OFFSET(struct_, field_) ) ) 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /ktrw_kext_loader/system/platform.c: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #define PLATFORM_EXTERN 21 | #include "platform.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "log.h" 29 | 30 | // ---- Initialization ---------------------------------------------------------------------------- 31 | 32 | void 33 | platform_init() { 34 | // Only initialize once. 35 | static bool initialized = false; 36 | if (initialized) { 37 | return; 38 | } 39 | initialized = true; 40 | // Set the page size. 41 | platform.page_size = vm_kernel_page_size; 42 | page_size = platform.page_size; 43 | // Get the machine name (e.g. iPhone11,8). 44 | struct utsname u = {}; 45 | int error = uname(&u); 46 | assert(error == 0); 47 | strncpy((char *)platform.machine, u.machine, sizeof(platform.machine)); 48 | // Get the build (e.g. 16C50). 49 | size_t osversion_size = sizeof(platform.osversion); 50 | error = sysctlbyname("kern.osversion", 51 | (void *)platform.osversion, &osversion_size, NULL, 0); 52 | assert(error == 0); 53 | // Get basic host info. 54 | mach_port_t host = mach_host_self(); 55 | assert(MACH_PORT_VALID(host)); 56 | host_basic_info_data_t basic_info; 57 | mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; 58 | kern_return_t kr = host_info(host, HOST_BASIC_INFO, (host_info_t) &basic_info, &count); 59 | assert(kr == KERN_SUCCESS); 60 | platform.cpu_type = basic_info.cpu_type; 61 | platform.cpu_subtype = basic_info.cpu_subtype; 62 | platform.physical_cpu = basic_info.physical_cpu; 63 | platform.logical_cpu = basic_info.logical_cpu; 64 | platform.memory_size = basic_info.max_mem; 65 | mach_port_deallocate(mach_task_self(), host); 66 | // Log basic platform info. 67 | INFO("Platform: %s %s", platform.machine, platform.osversion); 68 | } 69 | -------------------------------------------------------------------------------- /ktrw_kext_loader/system/platform.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef PLATFORM__H_ 21 | #define PLATFORM__H_ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef PLATFORM_EXTERN 28 | #define extern PLATFORM_EXTERN 29 | #endif 30 | 31 | /* 32 | * platform 33 | * 34 | * Description: 35 | * Basic information about the platform. 36 | */ 37 | struct platform { 38 | // The name of the platform, e.g. iPhone11,8. 39 | const char machine[32]; 40 | // The version of the OS build, e.g. 16C50. 41 | const char osversion[32]; 42 | // The platform CPU type. 43 | cpu_type_t cpu_type; 44 | // The platform CPU subtype. 45 | cpu_subtype_t cpu_subtype; 46 | // The number of physical CPU cores. 47 | unsigned physical_cpu; 48 | // The number of logical CPU cores. 49 | unsigned logical_cpu; 50 | // The kernel page size. 51 | size_t page_size; 52 | // The size of physical memory on the device. 53 | size_t memory_size; 54 | }; 55 | extern struct platform platform; 56 | 57 | /* 58 | * page_size 59 | * 60 | * Description: 61 | * The kernel page size on this platform, made available globally for convenience. 62 | */ 63 | extern size_t page_size; 64 | 65 | /* 66 | * platform_init 67 | * 68 | * Description: 69 | * Initialize the platform. 70 | */ 71 | void platform_init(void); 72 | 73 | #undef extern 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /ktrw_kext_loader/system/platform_match.h: -------------------------------------------------------------------------------- 1 | // 2 | // Project: KTRW 3 | // Author: Brandon Azad 4 | // 5 | // Copyright 2019 Google LLC 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef PLATFORM_MATCH__H_ 21 | #define PLATFORM_MATCH__H_ 22 | 23 | #include 24 | #include 25 | 26 | /* 27 | * platform_matches_device 28 | * 29 | * Description: 30 | * Check whether the current platform matches the specified device or range of devices. 31 | * 32 | * Match format: 33 | * The match string may either specify a single device glob or a range of device globs. For 34 | * example: 35 | * 36 | * "iPhone11,8" Matches only iPhone11,8 37 | * "iPhone11,*" Matches all iPhone11 devices, including e.g. iPhone11,4. 38 | * "iPhone*,*" Matches all iPhone devices. 39 | * "iPhone11,4-iPhone11,8" Matches all iPhone devices between 11,4 and 11,8, inclusive. 40 | * "iPhone10,*-11,*" Matches all iPhone10 and iPhone11 devices. 41 | * "iPhon10,1|iPhone10,6" Matches iPhone10,1 and iPhone10,6. 42 | * "*", NULL Matches all devices. 43 | */ 44 | bool platform_matches_device(const char *device_range); 45 | 46 | /* 47 | * platform_matches_build 48 | * 49 | * Description: 50 | * Check whether the current platform matches the specified build version or range of build 51 | * versions. 52 | * 53 | * Match format: 54 | * The match string may either specify a single build version or a range of build versions. 55 | * For example: 56 | * 57 | * "16C50" Matches only build 16C50. 58 | * "16B92-16C50" Matches all builds between 16B92 and 16C50, inclusive. 59 | * 60 | * As a special case, either build version may be replaced with "*" to indicate a lack of 61 | * lower or upper bound: 62 | * 63 | * "*-16B92" Matches all builds up to and including 16B92. 64 | * "16C50-*" Matches build 16C50 and later. 65 | * "*", NULL Matches all build versions. 66 | */ 67 | bool platform_matches_build(const char *build_range); 68 | 69 | /* 70 | * platform_matches 71 | * 72 | * Description: 73 | * A convenience function that combines platform_matches_device() and 74 | * platform_matches_build(). 75 | */ 76 | bool platform_matches(const char *device_range, const char *build_range); 77 | 78 | // A struct describing an initialization for a particular set of devices and builds. 79 | struct platform_initialization { 80 | const char *devices; 81 | const char *builds; 82 | void (*init)(void); 83 | }; 84 | 85 | /* 86 | * run_platform_initializations 87 | * 88 | * Description: 89 | * Run each of the platform initializations that match the current device and build. 90 | * 91 | * Returns the number of initializations that ran. 92 | */ 93 | size_t run_platform_initializations(struct platform_initialization *inits, size_t count); 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /ktrw_usb_proxy/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = ktrw_usb_proxy 2 | 3 | DEBUG ?= 0 4 | 5 | CFLAGS = -O2 -Wall -Werror 6 | 7 | ifneq ($(DEBUG),0) 8 | CFLAGS += -DDEBUG=$(DEBUG) 9 | endif 10 | 11 | SOURCES = source/ktrw_usb_proxy.c 12 | 13 | HEADERS = 14 | 15 | FRAMEWORKS = -framework IOKit -framework CoreFoundation 16 | 17 | $(TARGET): $(SOURCES) $(HEADERS) 18 | $(CC) $(CFLAGS) $(DEFINES) $(LDFLAGS) $(FRAMEWORKS) -o $@ $(SOURCES) 19 | 20 | clean: 21 | rm -f -- $(TARGET) 22 | -------------------------------------------------------------------------------- /misc/dbg_xnu.cfg.patch: -------------------------------------------------------------------------------- 1 | --- dbg_xnu.cfg.orig 2 | +++ dbg_xnu.cfg 3 | @@ -270,6 +270,66 @@ 4 | "com.corellium.gdb.arm64.state": 5 | { 6 | "title": "FP/Exception State Registers" 7 | + }, 8 | + "com.apple.debugserver.arm64.general": 9 | + { 10 | + "title": "General Registers", 11 | + "rename": 12 | + { 13 | + "cpsr": "psr", 14 | + "fp": "x29", 15 | + "lr": "x30" 16 | + }, 17 | + "stack_ptr": "sp", 18 | + "code_ptr": "pc", 19 | + "frame_ptr": "x29", 20 | + "data_ptr": 21 | + [ 22 | + "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 23 | + "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 24 | + "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 25 | + "x24", "x25", "x26", "x27", "x28", "x29", "x30" 26 | + ], 27 | + "bitfields": 28 | + { 29 | + "psr": 30 | + { 31 | + "M": [ 0, 4 ], 32 | + "F": [ 6, 6 ], 33 | + "I": [ 7, 7 ], 34 | + "A": [ 8, 8 ], 35 | + "D": [ 9, 9 ], 36 | + "IL": [ 20, 20 ], 37 | + "SS": [ 21, 21 ], 38 | + "PAN": [ 22, 22 ], 39 | + "UAO": [ 23, 23 ], 40 | + "DIT": [ 24, 24 ], 41 | + "V": [ 28, 28 ], 42 | + "C": [ 29, 29 ], 43 | + "Z": [ 30, 30 ], 44 | + "N": [ 31, 31 ] 45 | + } 46 | + } 47 | + }, 48 | + "com.apple.debugserver.arm64.low": 49 | + { 50 | + "title": "General Registers (32-bit)" 51 | + }, 52 | + "com.apple.debugserver.arm64.single": 53 | + { 54 | + "title": "Floating Point Registers (Single Precision)" 55 | + }, 56 | + "com.apple.debugserver.arm64.double": 57 | + { 58 | + "title": "Floating Point Registers (Double Precision)" 59 | + }, 60 | + "com.apple.debugserver.arm64.neon": 61 | + { 62 | + "title": "NEON Registers" 63 | + }, 64 | + "com.apple.debugserver.arm64.state": 65 | + { 66 | + "title": "FP/Exception State Registers" 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /pongo_kext_loader/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = pongo_kext_loader 2 | 3 | DEBUG ?= 0 4 | 5 | CFLAGS = -O2 -Wall -Werror 6 | 7 | ifneq ($(DEBUG),0) 8 | CFLAGS += -DDEBUG=$(DEBUG) 9 | endif 10 | 11 | SOURCES = source/pongo_kext_loader.c 12 | 13 | HEADERS = 14 | 15 | FRAMEWORKS = -framework IOKit -framework CoreFoundation 16 | 17 | $(TARGET): $(SOURCES) $(HEADERS) 18 | $(CC) $(CFLAGS) $(DEFINES) $(LDFLAGS) $(FRAMEWORKS) -o $@ $(SOURCES) 19 | 20 | clean: 21 | rm -f -- $(TARGET) 22 | -------------------------------------------------------------------------------- /pongo_kextload/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = kextload.pongo-module 2 | 3 | ARCH = arm64 4 | SDK = iphoneos 5 | ABI = aapcs 6 | 7 | SYSROOT := $(shell xcrun --sdk $(SDK) --show-sdk-path) 8 | ifeq ($(SYSROOT),) 9 | $(error Could not find SDK $(SDK)) 10 | endif 11 | CLANG := $(shell xcrun --sdk $(SDK) --find clang) 12 | CC := $(CLANG) -isysroot $(SYSROOT) -arch $(ARCH) 13 | 14 | CFLAGS = -mabi=$(ABI) -fno-builtin -fno-common -mkernel 15 | CFLAGS += -Isource/third_party 16 | CFLAGS += -O2 17 | CFLAGS += -Wall -Werror -Wpedantic -Wno-gnu -Wno-language-extension-token -Wconversion 18 | 19 | LDFLAGS = -Xlinker -kext -nostdlib -Xlinker -fatal_warnings 20 | 21 | SOURCES = source/pongo_kextload.c 22 | 23 | HEADERS = source/third_party/pongo.h 24 | 25 | $(TARGET): $(SOURCES) $(HEADERS) 26 | $(CC) $(CFLAGS) $(DEFINES) $(LDFLAGS) -o $@ $(SOURCES) 27 | 28 | symbols: $(TARGET) 29 | @nm -u $(TARGET) 30 | 31 | clean: 32 | rm -rf -- $(TARGET).$(ARCH).ld 33 | rm -f -- $(TARGET) 34 | --------------------------------------------------------------------------------