Skip to content

Instantly share code, notes, and snippets.

@SeeFlowerX
Last active January 5, 2023 11:23
Show Gist options
  • Save SeeFlowerX/236168a420b8b239e62638a49a0c6473 to your computer and use it in GitHub Desktop.
Save SeeFlowerX/236168a420b8b239e62638a49a0c6473 to your computer and use it in GitHub Desktop.
获取libc导入函数的plt地址
import json
from pathlib import Path
import idautils
import ida_nalt
def get_libc_import():
info = {}
nimps = ida_nalt.get_import_module_qty()
print("Found %d import(s)..." % nimps)
for i in range(nimps):
name = ida_nalt.get_import_module_name(i)
if not name:
print("Failed to get import module name for #%d" % i)
name = "<unnamed>"
print("Walking imports for module %s" % name)
def imp_cb(ea, name: str, ordinal: int):
if not name:
# print("%08x: ordinal #%d" % (ea, ordinal))
pass
else:
if name.endswith('@@LIBC'):
import_symbol = name.split('@@')[0]
import_addr = ea
# print('[+]', import_symbol, hex(import_addr))
info[import_symbol] = import_addr
else:
pass
# print("%08x: %s (ordinal #%d)" % (ea, name, ordinal))
# True -> Continue enumeration
# False -> Stop enumeration
return True
ida_nalt.enum_import_names(i, imp_cb)
return info
def main():
print('<------------start------------>')
result = []
info = get_libc_import()
for import_symbol, extern_addr in info.items():
got_offset, plt_offset = get_import_func_plt_addr(extern_addr)
result.append({
'symbol': import_symbol,
'extern_addr': extern_addr,
'got_offset': got_offset,
'plt_offset': plt_offset,
})
print('[+]', hex(plt_offset), import_symbol)
text = json.dumps(result, ensure_ascii=False, indent=4)
fullpath = Path(ida_nalt.get_input_file_path())
dump_path = fullpath.parent / (fullpath.stem + '_libc_plt.json')
dump_path.write_text(text, encoding='utf-8')
print('libc import plt info dump to =>', dump_path)
def get_import_func_plt_addr(extern_addr: int):
# https://psyduck0409.github.io/2021/03/01/2021/idapython%E7%AC%94%E8%AE%B0/
# 先根据符号拿到 extern 地址
# extern_addr = idc.get_name_ea_simple("memcpy")
# print('[+]', hex(extern_addr), idc.GetDisasm(extern_addr))
# CodeRefsTo 似乎只能取到引用函数的结尾 ?
# for addr in idautils.CodeRefsTo(extern_addr, 0):
# print('--', hex(addr), idc.GetDisasm(addr))
got_offset = -1
plt_offset = -1
# XrefsTo 遍历
# - ida_xref.XREF_ALL 0
# - ida_xref.XREF_FAR 1
# - ida_xref.XREF_DATA 2
for xref in idautils.XrefsTo(extern_addr, ida_xref.XREF_FAR):
# 取 xref.type 为 Data_Offset 类型的
if idautils.XrefTypeName(xref.type) != 'Data_Offset':
continue
# print('[+]', xref.type, idautils.XrefTypeName(xref.type), hex(xref.frm), hex(xref.to), xref.iscode)
got_offset = xref.frm
# print('[+] got offset', hex(xref.frm))
# 这个时候 xref.frm 就是 got 表地址了 再次交叉引用
for xref2 in idautils.XrefsTo(xref.frm, 1):
# 还是取 xref.type 为 Data_Offset 类型的
if idautils.XrefTypeName(xref2.type) != 'Data_Offset':
continue
# 这里对应的就是 xxx_ptr
# print('[*]', xref2.type, idautils.XrefTypeName(xref2.type), hex(xref2.frm), hex(xref2.to), xref2.iscode)
# print('[+] plt offset', hex(xref2.frm))
plt_offset = xref2.frm
# 取第一个即可 因为 plt 函数里面一般是几个 xxx_ptr
# Data_Offset 类型的有两个 第一个往往就是函数起始地址 那么直接跳出即可
break
break
return [got_offset, plt_offset]
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment