Last active
January 5, 2023 11:23
-
-
Save SeeFlowerX/236168a420b8b239e62638a49a0c6473 to your computer and use it in GitHub Desktop.
获取libc导入函数的plt地址
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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