Guest User

Untitled

a guest
Jun 22nd, 2018
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.22 KB | None | 0 0
  1. #
  2. # ios-12-kernelcache-tagged-pointers.py
  3. # Brandon Azad
  4. #
  5. # An idapython script that shows how to work with the new tagged pointers in the iOS 12
  6. # kernelcache.
  7. #
  8.  
  9. import idc
  10. import idaapi
  11. import idautils
  12.  
  13. import random
  14. from collections import defaultdict, Counter
  15.  
  16. def untag_pointer(tp):
  17. return tp | 0xffff000000000000
  18.  
  19. def tagged_pointer_tag(tp):
  20. return (tp >> 48) & 0xffff
  21.  
  22. def is_tagged_pointer_format(pointer):
  23. return (pointer & 0x0000FFFFf0000000) == 0x0000FFF000000000
  24.  
  25. def is_valid_tagged_pointer(pointer):
  26. return is_tagged_pointer_format(pointer) and idaapi.getseg(untag_pointer(pointer))
  27.  
  28. def tagged_pointer_tag_to_span(tag):
  29. return (tag >> 1) & ~0x3
  30.  
  31. def tagged_pointer_span(tp):
  32. return tagged_pointer_tag_to_span(tagged_pointer_tag(tp))
  33.  
  34. def tagged_pointers():
  35. if tagged_pointers.eas_and_tps is None:
  36. eas_and_tps = []
  37. for seg in idautils.Segments():
  38. start = idc.SegStart(seg)
  39. end = idc.SegEnd(seg)
  40. for ea in range(start, end, 4):
  41. value = idc.Qword(ea)
  42. if is_valid_tagged_pointer(value):
  43. eas_and_tps.append((ea, value))
  44. tagged_pointers.eas_and_tps = eas_and_tps
  45. return tagged_pointers
  46.  
  47. tagged_pointers.eas_and_tps = None
  48.  
  49. def print_tagged_pointer_counts_per_section():
  50. seg_to_tag_count = Counter()
  51. for ea, tp in tagged_pointers().eas_and_tps:
  52. if tagged_pointer_tag(tp) == 0xffff:
  53. continue
  54. seg = idc.SegStart(ea)
  55. seg_to_tag_count[seg] += 1
  56. segs = list(seg_to_tag_count.keys())
  57. segs.sort()
  58. for seg in segs:
  59. print '{:32s} {:8d}'.format(idc.SegName(seg), seg_to_tag_count[seg])
  60.  
  61. def print_untagged_pointer_counts_per_section():
  62. seg_to_tag_count = Counter()
  63. for ea, tp in tagged_pointers().eas_and_tps:
  64. if tagged_pointer_tag(tp) != 0xffff:
  65. continue
  66. seg = idc.SegStart(ea)
  67. seg_to_tag_count[seg] += 1
  68. segs = list(seg_to_tag_count.keys())
  69. segs.sort()
  70. for seg in segs:
  71. print '{:32s} {:8d}'.format(idc.SegName(seg), seg_to_tag_count[seg])
  72.  
  73. def print_tagged_pointer_counts_by_tag_per_section():
  74. seg_to_tag_counts = defaultdict(Counter)
  75. for ea, tp in tagged_pointers().eas_and_tps:
  76. seg = idc.SegStart(ea)
  77. tag = tagged_pointer_tag(tp)
  78. seg_to_tag_counts[seg][tag] += 1
  79. segs = list(seg_to_tag_counts.keys())
  80. segs.sort()
  81. for seg in segs:
  82. tag_counts = seg_to_tag_counts[seg]
  83. tags = list(tag_counts.keys())
  84. tags.sort()
  85. print '{:32s} {}'.format(idc.SegName(seg),
  86. ', '.join('{:04x} ({})'.format(tag, tag_counts[tag]) for tag in tags))
  87.  
  88. def print_references_for_tagged_pointers():
  89. tag_to_eas_and_tps = defaultdict(list)
  90. for ea, tp in tagged_pointers().eas_and_tps:
  91. tag_to_eas_and_tps[tagged_pointer_tag(tp)].append((ea, tp))
  92. tags = list(tag_to_eas_and_tps.keys())
  93. tags.sort()
  94. for tag in tags:
  95. eas_and_tps = tag_to_eas_and_tps[tag]
  96. ea, tp = random.choice(eas_and_tps)
  97. kp = untag_pointer(tp)
  98. print '{:04x} {:8d} {:016x} {:32s} -> {:016x} {:s}'.format(
  99. tag, len(eas_and_tps), ea, idc.SegName(ea), kp, idc.SegName(kp))
  100.  
  101. def find_tagged_pointers_to_address(address):
  102. tag_to_eas = defaultdict(list)
  103. for ea, tp in tagged_pointers().eas_and_tps:
  104. if untag_pointer(tp) == address:
  105. tag_to_eas[tagged_pointer_tag(tp)].append(ea)
  106. return dict(tag_to_eas)
  107.  
  108. def print_tagged_pointers_to_address(address):
  109. tag_to_eas = find_tagged_pointers_to_address(address)
  110. tags = list(tag_to_eas.keys())
  111. tags.sort()
  112. for tag in tags:
  113. eas = tag_to_eas[tag]
  114. print '{:04x} {:8d} {}'.format(
  115. tag, len(eas), ', '.join('{:016x}'.format(ea) for ea in eas))
  116.  
  117. def check_pointer_tags_as_links():
  118. last_seg, last_ea, last_tp = None, None, None
  119. correct, warnings, errors, skipped = 0, 0, 0, 0
  120. for ea, tp in tagged_pointers().eas_and_tps:
  121. if tagged_pointer_tag(tp) == 0xffff:
  122. skipped += 1
  123. continue
  124. seg = idc.SegStart(ea)
  125. if seg == last_seg:
  126. span = tagged_pointer_span(last_tp)
  127. if span == 0:
  128. real_span = ea - last_ea
  129. print 'WARNING: ZERO SPAN LINK: ea={:016x}, tp={:016x}, last_ea={:016x}, last_tp={:016x}, span={:04x}'.format(
  130. ea, tp, last_ea, last_tp, real_span)
  131. warnings += 1
  132. elif ea != last_ea + span:
  133. print 'ERROR: BAD LINK: ea={:016x}, tp={:016x}, last_ea={:016x}, last_tp={:016x}'.format(
  134. ea, tp, last_ea, last_tp)
  135. errors += 1
  136. break
  137. else:
  138. correct += 1
  139. elif last_ea:
  140. span = tagged_pointer_span(last_tp)
  141. if span == 0:
  142. correct += 1
  143. else:
  144. print 'WARNING: NON-ZERO SPAN LINK AT END OF SEGMENT: ea={:016x}, tp={:016x}, last_ea={:016x}, last_tp={:016x}, seg={:016x}'.format(
  145. ea, tp, last_ea, last_tp, seg)
  146. warnings += 1
  147. last_seg, last_ea, last_tp = seg, ea, tp
  148. print '{} correct, {} warnings, {} errors, {} skipped'.format(
  149. correct, warnings, errors, skipped)
Add Comment
Please, Sign In to add comment