kmem.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #import "../kern_utils.h"
  2. #import "patchfinder64.h"
  3. #import "kmem.h"
  4. #define MAX_CHUNK_SIZE 0xFFF
  5. size_t kread(uint64_t where, void *p, size_t size) {
  6. int rv;
  7. size_t offset = 0;
  8. while (offset < size) {
  9. mach_vm_size_t sz, chunk = MAX_CHUNK_SIZE;
  10. if (chunk > size - offset) {
  11. chunk = size - offset;
  12. }
  13. rv = mach_vm_read_overwrite(tfpzero, where + offset, chunk, (mach_vm_address_t)p + offset, &sz);
  14. if (rv || sz == 0) {
  15. fprintf(stderr, "[e] error reading kernel @%p\n", (void *)(offset + where));
  16. break;
  17. }
  18. offset += sz;
  19. }
  20. return offset;
  21. }
  22. size_t kwrite(uint64_t where, const void *p, size_t size) {
  23. int rv;
  24. size_t offset = 0;
  25. while (offset < size) {
  26. size_t chunk = MAX_CHUNK_SIZE;
  27. if (chunk > size - offset) {
  28. chunk = size - offset;
  29. }
  30. rv = mach_vm_write(tfpzero, where + offset, (mach_vm_offset_t)p + offset, chunk);
  31. if (rv) {
  32. fprintf(stderr, "[e] error writing kernel @%p\n", (void *)(offset + where));
  33. break;
  34. }
  35. offset += chunk;
  36. }
  37. return offset;
  38. }
  39. uint64_t kalloc(vm_size_t size){
  40. mach_vm_address_t address = 0;
  41. mach_vm_allocate(tfpzero, (mach_vm_address_t *)&address, size, VM_FLAGS_ANYWHERE);
  42. return address;
  43. }
  44. void kfree(mach_vm_address_t address, vm_size_t size){
  45. mach_vm_deallocate(tfpzero, address, size);
  46. }
  47. uint32_t rk32(uint64_t kaddr) {
  48. uint32_t val = 0;
  49. kread(kaddr, &val, sizeof(val));
  50. return val;
  51. }
  52. uint64_t rk64(uint64_t kaddr) {
  53. uint64_t val = 0;
  54. kread(kaddr, &val, sizeof(val));
  55. return val;
  56. }
  57. void wk32(uint64_t kaddr, uint32_t val) {
  58. kwrite(kaddr, &val, sizeof(val));
  59. }
  60. void wk64(uint64_t kaddr, uint64_t val) {
  61. kwrite(kaddr, &val, sizeof(val));
  62. }
  63. // thx Siguza
  64. typedef struct {
  65. uint64_t prev;
  66. uint64_t next;
  67. uint64_t start;
  68. uint64_t end;
  69. } kmap_hdr_t;
  70. uint64_t zm_fix_addr(uint64_t addr) {
  71. static kmap_hdr_t zm_hdr = {0, 0, 0, 0};
  72. if (zm_hdr.start == 0) {
  73. // xxx rk64(0) ?!
  74. // uint64_t zone_map_ref = find_zone_map_ref();
  75. fprintf(stderr, "offset_zonemap = %llx \n", offset_zonemap);
  76. fprintf(stderr, "zone_map_ref: %llx \n", offset_zonemap + kernel_slide);
  77. uint64_t zone_map = rk64(offset_zonemap + kernel_slide);
  78. fprintf(stderr, "zone_map: %llx \n", zone_map);
  79. // hdr is at offset 0x10, mutexes at start
  80. size_t r = kread(zone_map + 0x10, &zm_hdr, sizeof(zm_hdr));
  81. 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));
  82. if (r != sizeof(zm_hdr) || zm_hdr.start == 0 || zm_hdr.end == 0) {
  83. fprintf(stderr, "kread of zone_map failed!\n");
  84. exit(1);
  85. }
  86. if (zm_hdr.end - zm_hdr.start > 0x100000000) {
  87. fprintf(stderr, "zone_map is too big, sorry.\n");
  88. exit(1);
  89. }
  90. }
  91. uint64_t zm_tmp = (zm_hdr.start & 0xffffffff00000000) | ((addr) & 0xffffffff);
  92. return zm_tmp < zm_hdr.start ? zm_tmp + 0x100000000 : zm_tmp;
  93. }
  94. int kstrcmp(uint64_t kstr, const char* str) {
  95. // XXX be safer, dont just assume you wont cause any
  96. // page faults by this
  97. size_t len = strlen(str) + 1;
  98. char *local = malloc(len + 1);
  99. local[len] = '\0';
  100. int ret = 1;
  101. if (kread(kstr, local, len) == len) {
  102. ret = strcmp(local, str);
  103. }
  104. free(local);
  105. return ret;
  106. }