Skip to content

Instantly share code, notes, and snippets.

@zznop
Created July 13, 2019 21:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zznop/4fbdd86529d144d7df5955c7cb10f5b8 to your computer and use it in GitHub Desktop.
Save zznop/4fbdd86529d144d7df5955c7cb10f5b8 to your computer and use it in GitHub Desktop.
import ida_segment
import ida_bytes
import idautils
import idaapi
import idc
import re
__author__ = 'zznop'
__copyright__ = 'Copyright 2019, zznop'
__email__ = 'zznop0x90@gmail.com'
def get_call_table_instrs():
'''Return all jsr instructions with pc in the operand
'''
instrs = []
# Iterate instructions in functions
for funcea in idautils.Functions():
for (startea, endea) in idautils.Chunks(funcea):
for head in idautils.Heads(startea, endea):
instr = idc.GetDisasm(head).split()
if instr[0] == 'jsr' or instr[0] == 'jmp':
if 'pc' in instr[1]:
instrs.append(instr)
# Iterate instructions not in a function
addr = idaapi.find_not_func(0, 1)
while addr != idc.BADADDR:
instr = idc.GetDisasm(addr).split()
if instr[0] == 'jsr' or instr[0] == 'jmp':
if 'pc' in instr[1]:
instrs.append(instr)
addr = idaapi.find_not_func(addr, 1)
return instrs
def get_call_table_addrs_from_instrs(instrs):
'''Get the base addr of the call tables from the instrs
'''
call_table_addrs = []
for mnem, opnd in instrs:
print(opnd)
match = re.match(r"^.*_(.*)\(pc,.*\)$", opnd)
if match:
addr = int(match.group(1), 16)
call_table_addrs.append(addr)
return call_table_addrs
def disas_call_tables(base_table_addrs):
for base_addr in base_table_addrs:
i = base_addr
while True:
instr_dword = ida_bytes.get_32bit(i)
if not ((instr_dword >> 24) == 0x60):
break
idc.MakeCode(i)
i += 4
def main():
'''
'''
call_table_instrs = get_call_table_instrs()
if call_table_instrs is []:
print("Failed to find JSR instructions that modify PC")
return
call_table_addrs = get_call_table_addrs_from_instrs(call_table_instrs)
if call_table_addrs is []:
print("Failed to enumerate call table base addresses from instructions")
return
disas_call_tables(call_table_addrs)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment