kmem.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #import "../kern_utils.h"
  2. #import "kmem.h"
  3. #define MAX_CHUNK_SIZE 0xFFF
  4. void remote_read_overwrite(mach_port_t task_port,
  5. uint64_t remote_address,
  6. uint64_t local_address,
  7. uint64_t length) {
  8. kern_return_t err;
  9. mach_vm_size_t outsize = 0;
  10. err = mach_vm_read_overwrite(task_port, (mach_vm_address_t)remote_address, (mach_vm_size_t)length, (mach_vm_address_t)local_address, &outsize);
  11. if (err != KERN_SUCCESS){
  12. return;
  13. }
  14. if (outsize != length){
  15. return;
  16. }
  17. }
  18. void remote_write(mach_port_t remote_task_port,
  19. uint64_t remote_address,
  20. uint64_t local_address,
  21. uint64_t length) {
  22. kern_return_t err = mach_vm_write(remote_task_port,
  23. (mach_vm_address_t)remote_address,
  24. (vm_offset_t)local_address,
  25. (mach_msg_type_number_t)length);
  26. if (err != KERN_SUCCESS) {
  27. return;
  28. }
  29. }
  30. uint64_t binary_load_address() {
  31. kern_return_t err;
  32. mach_msg_type_number_t region_count = VM_REGION_BASIC_INFO_COUNT_64;
  33. memory_object_name_t object_name = MACH_PORT_NULL;
  34. mach_vm_size_t target_first_size = 0x1000;
  35. mach_vm_address_t target_first_addr = 0x0;
  36. struct vm_region_basic_info_64 region = {0};
  37. err = mach_vm_region(mach_task_self(), &target_first_addr, &target_first_size, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&region, &region_count, &object_name);
  38. if (err != KERN_SUCCESS) {
  39. return -1;
  40. }
  41. return target_first_addr;
  42. }
  43. size_t kread(uint64_t where, void *p, size_t size) {
  44. int rv;
  45. size_t offset = 0;
  46. while (offset < size) {
  47. mach_vm_size_t sz, chunk = MAX_CHUNK_SIZE;
  48. if (chunk > size - offset) {
  49. chunk = size - offset;
  50. }
  51. rv = mach_vm_read_overwrite(tfp0, where + offset, chunk, (mach_vm_address_t)p + offset, &sz);
  52. if (rv || sz == 0) {
  53. fprintf(stderr, "[e] error reading kernel @%p\n", (void *)(offset + where));
  54. break;
  55. }
  56. offset += sz;
  57. }
  58. return offset;
  59. }
  60. size_t kwrite(uint64_t where, const void *p, size_t size) {
  61. int rv;
  62. size_t offset = 0;
  63. while (offset < size) {
  64. size_t chunk = MAX_CHUNK_SIZE;
  65. if (chunk > size - offset) {
  66. chunk = size - offset;
  67. }
  68. rv = mach_vm_write(tfp0, where + offset, (mach_vm_offset_t)p + offset, chunk);
  69. if (rv) {
  70. fprintf(stderr, "[e] error writing kernel @%p\n", (void *)(offset + where));
  71. break;
  72. }
  73. offset += chunk;
  74. }
  75. return offset;
  76. }
  77. uint64_t kalloc(vm_size_t size){
  78. mach_vm_address_t address = 0;
  79. mach_vm_allocate(tfp0, (mach_vm_address_t *)&address, size, VM_FLAGS_ANYWHERE);
  80. return address;
  81. }
  82. void kfree(mach_vm_address_t address, vm_size_t size){
  83. mach_vm_deallocate(tfp0, address, size);
  84. }
  85. uint16_t rk16(uint64_t kaddr) {
  86. uint16_t val = 0;
  87. kread(kaddr, &val, sizeof(val));
  88. return val;
  89. }
  90. uint32_t rk32(uint64_t kaddr) {
  91. uint32_t val = 0;
  92. kread(kaddr, &val, sizeof(val));
  93. return val;
  94. }
  95. uint64_t rk64(uint64_t kaddr) {
  96. uint64_t val = 0;
  97. kread(kaddr, &val, sizeof(val));
  98. return val;
  99. }
  100. void wk16(uint64_t kaddr, uint16_t val) {
  101. kwrite(kaddr, &val, sizeof(val));
  102. }
  103. void wk32(uint64_t kaddr, uint32_t val) {
  104. kwrite(kaddr, &val, sizeof(val));
  105. }
  106. void wk64(uint64_t kaddr, uint64_t val) {
  107. kwrite(kaddr, &val, sizeof(val));
  108. }
  109. // thx Siguza
  110. typedef struct {
  111. uint64_t prev;
  112. uint64_t next;
  113. uint64_t start;
  114. uint64_t end;
  115. } kmap_hdr_t;
  116. uint64_t zm_fix_addr(uint64_t addr) {
  117. static kmap_hdr_t zm_hdr = {0, 0, 0, 0};
  118. if (zm_hdr.start == 0) {
  119. // xxx rk64(0) ?!
  120. uint64_t zone_map = rk64(offset_zonemap);
  121. fprintf(stderr, "zone_map: %llx \n", zone_map);
  122. // hdr is at offset 0x10, mutexes at start
  123. size_t r = kread(zone_map + 0x10, &zm_hdr, sizeof(zm_hdr));
  124. fprintf(stderr, "zm_range: 0x%llx - 0x%llx (read 0x%zx, exp 0x%zx)\n", zm_hdr.start, zm_hdr.end, r, sizeof(zm_hdr));
  125. if (r != sizeof(zm_hdr) || zm_hdr.start == 0 || zm_hdr.end == 0) {
  126. fprintf(stderr, "kread of zone_map failed!\n");
  127. exit(1);
  128. }
  129. if (zm_hdr.end - zm_hdr.start > 0x100000000) {
  130. fprintf(stderr, "zone_map is too big, sorry.\n");
  131. exit(1);
  132. }
  133. }
  134. uint64_t zm_tmp = (zm_hdr.start & 0xffffffff00000000) | ((addr) & 0xffffffff);
  135. return zm_tmp < zm_hdr.start ? zm_tmp + 0x100000000 : zm_tmp;
  136. }
  137. int kstrcmp(uint64_t kstr, const char* str) {
  138. // XXX be safer, dont just assume you wont cause any
  139. // page faults by this
  140. size_t len = strlen(str) + 1;
  141. char *local = (char *)malloc(len + 1);
  142. local[len] = '\0';
  143. int ret = 1;
  144. if (kread(kstr, local, len) == len) {
  145. ret = strcmp(local, str);
  146. }
  147. free(local);
  148. return ret;
  149. }