rizin/librz/bin/format/xnu/scripts/machtraps.py
2020-10-05 21:39:56 +08:00

89 lines
2.5 KiB
Python

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
Example usage to regenerate traps.json:
- open the dyld cache in rizin like this:
RZ_DYLDCACHE_FILTER=libsystem_kernel rizin -e bin.usextr=false ~/Library/Developer/Xcode/iOS\ DeviceSupport/12.1.2\ \(16C101\)\ arm64e/Symbols/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e
- run the script with this command:
#!pipe python2 /path/to/this/script.py > traps.json
"""
import rzpipe, json, re
r = rzpipe.open('#!pipe')
def walk_back_until (addr, pattern, min_addr):
cursor = addr
while cursor >= min_addr:
op = r.cmdj('aoj@' + str(cursor))[0]['opcode']
if re.search(pattern, op) != None:
return cursor + 4
if re.search(r'^ret', op) != None:
return cursor + 4
if re.search(r'^b ', op) != None:
return cursor + 4
cursor -= 4
return min_addr
def carve_trap_num (addr, flag):
saved_seek = r.cmd('?v $$')
r.cmd('e io.cache=true')
r.cmd('e emu.write=true')
r.cmd('aei')
r.cmd('aeim')
min_addr = int(r.cmd('?v ' + flag), 0)
emu_start = walk_back_until(addr - 4, r'^b|^ret|^invalid', min_addr)
r.cmd('s ' + str(emu_start))
obj = r.cmd('aefa 0x%08x~[0]:0' % addr)
r.cmd('s ' + saved_seek)
val = r.cmdj('pv4j@%s+0x14' % obj)['value']
if val == 0:
val = r.cmdj('pv4j@%s+0x18' % obj)['value']
return val
def beautify_name (name):
return re.sub(r'^_', '', name)
def carve_traps ():
msgs = r.cmdj('axtj sym._mach_msg')
if len(msgs) == 0:
r.cmd('s sym._mach_msg')
r.cmd('aae $SS @ $S')
r.cmd('s-')
msgs = r.cmdj('axtj sym._mach_msg')
if len(msgs) == 0:
print 'Cannot find refs to mach_msg!'
return
traps = {}
for ref in msgs:
if ref['type'] != 'CALL' or 'realname' not in ref:
continue
name = ref['realname']
if re.search(r'^_mach_msg', name) != None:
continue
addr = ref['from']
traps[addr] = {
'name': name
}
result = []
for addr in traps:
trap = traps[addr]
flag = 'sym.%s' % trap['name']
trap['name'] = beautify_name(trap['name'])
trap['num'] = carve_trap_num(addr, flag)
if trap['num'] != None:
result.append(trap)
result.sort(key=lambda x: x['num'])
return result
if __name__ == '__main__':
traps = carve_traps()
print json.dumps(traps, indent=4)