Skip to content

Instantly share code, notes, and snippets.

@lab313ru
Created April 5, 2023 21:42
Show Gist options
  • Save lab313ru/36972ba4d4ded3ef1de3ef4a35de538a to your computer and use it in GitHub Desktop.
Save lab313ru/36972ba4d4ded3ef1de3ef4a35de538a to your computer and use it in GitHub Desktop.
Applies sym file information to idb
import re
import idc
import ida_nalt
import ida_kernwin
import ida_name
MODULE = re.compile(r'^MODULE \w+ \w+ \w+ .+$')
INFO = re.compile(r'^INFO CODE_ID \w+ .+$')
FILE = re.compile(r'^FILE (\d+) (.+)$')
FUNC = re.compile(r'^FUNC (\w+) (\w+) (\w+) (.+)$')
LINE = re.compile(r'^([0-9a-f]+) (\w+) (\d+) (\d+)$')
PUBLIC = re.compile(r'^PUBLIC (\w+) (\w+) (.+)$')
STACK = re.compile(r'^STACK CFI .+$')
def is_module(line):
return MODULE.match(line)
def parse_module(res):
return None
def is_info(line):
return INFO.match(line)
def parse_info(res):
return None
def is_file(line):
return FILE.match(line)
def parse_file(res):
fnum = int(res.group(1))
name = res.group(2)
return fnum, name
def is_func(line):
return FUNC.match(line)
def parse_func(res):
addr = int(res.group(1), 16)
size = int(res.group(2), 16)
psize = int(res.group(3), 16)
name = res.group(4)
return addr, size, name
def is_line(line):
return LINE.match(line)
def parse_line(res):
addr = int(res.group(1), 16)
size = int(res.group(2), 16)
line = int(res.group(3))
fnum = int(res.group(4))
return addr, size, line, fnum
def is_public(line):
return PUBLIC.match(line)
def parse_public(res):
addr = int(res.group(1), 16)
psize = int(res.group(2), 16)
name = res.group(3)
return addr, name
def is_stack(line):
return STACK.match(line)
def parse_stack(res):
return None
def parse_lines(line):
res = is_module(line)
if res:
return 'md', parse_module(res)
res = is_info(line)
if res:
return 'in', parse_info(res)
res = is_file(line)
if res:
return 'fl', parse_file(res)
res = is_func(line)
if res:
return 'fn', parse_func(res)
res = is_line(line)
if res:
return 'ln', parse_line(res)
res = is_public(line)
if res:
return 'pb', parse_public(res)
res = is_stack(line)
if res:
return 'st', parse_stack(res)
return 'nn', None
def use_files(files, funcs, lines, pubs):
base = ida_nalt.get_imagebase()
ida_kernwin.show_wait_box('Apply funcs')
sz = len(funcs)
for i, addr in enumerate(funcs.keys()):
size, name = funcs[addr]
name = ida_name.validate_name(name, ida_name.VNT_IDENT)
idc.set_name(base + addr, name, idc.SN_NOWARN)
ida_kernwin.replace_wait_box('%d/%d, 0x%X' % (i, sz, base + addr))
ida_kernwin.hide_wait_box()
ida_kernwin.show_wait_box('Apply pubs')
sz = len(pubs)
for i, addr in enumerate(pubs.keys()):
name = pubs[addr]
name = ida_name.validate_name(name, ida_name.VNT_IDENT)
idc.set_name(base + addr, name, idc.SN_NOWARN)
ida_kernwin.replace_wait_box('%d/%d, 0x%X' % (i, sz, base + addr))
ida_kernwin.hide_wait_box()
ida_kernwin.show_wait_box('Apply files')
sz1 = len(files)
for i, fnum in enumerate(files.keys()):
fname = files[fnum]
if fnum not in lines:
continue
addrs = lines[fnum]
sz2 = len(addrs)
for j, addr in enumerate(addrs.keys()):
size, line = addrs[addr]
idc.add_sourcefile(base + addr, base + addr + size, fname)
idc.set_source_linnum(base + addr, line)
ida_kernwin.replace_wait_box('%d/%d - %d/%d, 0x%X (0x%x)' % (i, sz1, j, sz2, base + addr, size))
ida_kernwin.hide_wait_box()
def main(path):
files = dict()
funcs = dict()
lines = dict()
pubs = dict()
with open(path) as f:
for line in f.readlines():
line = line.rstrip()
t, args = parse_lines(line)
if t in ['md', 'in', 'st']:
continue
elif t == 'fl':
fnum, name = args
files[fnum] = name
elif t == 'fn':
addr, size, name = args
funcs[addr] = size, name
elif t == 'ln':
addr, size, line, fnum = args
if fnum not in lines:
lines[fnum] = dict()
lines[fnum][addr] = size, line
elif t == 'pb':
addr, name = args
pubs[addr] = name
else:
print('wrong')
print('total:\nfiles = %d, funcs = %d, lines = %d, pubs = %d' % (len(files), len(funcs), len(lines), len(pubs)))
use_files(files, funcs, lines, pubs)
main('nw.dll.sym')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment