idapython修复全局变量段未识别指针
idapython修复全局变量段未识别指针
在逆向的过程中,经常会遇到虚表或者指针数组的实现,这种时候在回溯一些危险函数调用的时候,经常找不到交叉引用,这里记录一下,下次就不去翻idapython的文档了。
这是一个IoT设备的cgi,这部分的逻辑是根据不同的路由名称,调用不同的函数指针进行http请求的处理。这个action_table
是一个结构体数组,这个结构体里面有函数指针和字符串指针,在ida
中定位到action_table
处,发现在全局变量段,没有正确识别变量类型,本来指针应该识别为dword
类型的变量,但是识别成byte
类型。也没有把整型识别成指针,这就导致大量的函数找不到交叉引用,非常影响后续分析。
当然这种情况,可以手动一个一个去恢复,但是遗憾的是,今天遇到的这个结构体数组出奇得大,手动确实太笨拙了,所以我们需要idapython来自动化实现这个过程。
import idc,idaapi
for seg in idautils.Segments():
if(idc.get_segm_name(seg)) == ".data":
data_start_addr = idc.get_segm_start(seg)
data_end_addr = idc.get_segm_end(seg)
print("data segment start address: %s"%hex(data_start_addr))
print("data segment end address: %s"%hex(data_end_addr))
# 识别变量类型的api: ida_bytes.create_*(),这里先识别为dword类型
# mark a global variable as an offset using IDAPython: idc_offset.op_offset(ea,0,idc.REF_OFF32)
ea = data_start_addr
while ea != data_end_addr:
ida_bytes.create_dword(ea,4)
value = idaapi.get_dword(ea)
if value > 0xff: # 结构体的字段中,存在非指针的整型变量,这里做个区分,避免ida里面出现非法地址引用了
ida_offset.op_offset(ea,0,idc.REF_OFF32)
ea += 4
修复一下,就可以正常进行后续分析了,不用担心找不到交叉引用了。
结构体中一个成员变量是路由名称的字符串指针,这个用来调用不同结构体中的函数指针,一个结构体中有两个函数指针,一个是post请求会调用的,一个是get请求会调用的,然后还有一个成员变量用来判断是否是post请求,最后完善一下脚本。
import idc,idaapi,idautils
callaction_struct_size = 24
callaction_start_addr = 0x0097468
data_start_addr,data_end_addr = 0,0
end_addr = 0x00098444
def search_data_base():
global data_start_addr,data_end_addr
for seg in idautils.Segments():
if(idc.get_segm_name(seg)) == ".data":
data_start_addr = idc.get_segm_start(seg)
data_end_addr = idc.get_segm_end(seg)
print("data segment start address: %s"%hex(data_start_addr))
print("data segment end address: %s"%hex(data_end_addr))
def fix_dataSeg_funcptr():
ea,sz = data_start_addr,0
data_end_addr = end_addr
print(hex(ea))
while ea <= data_end_addr:
ida_bytes.create_dword(ea,4)
value = idaapi.get_dword(ea)
if value > 0xff: # 结构体的字段中,存在非指针的整型变量,这里做个区分,避免ida里面出现非法地址引用了
ida_offset.op_offset(ea,0,idc.REF_OFF32)
if(ea >= callaction_start_addr):
if(sz % callaction_struct_size == 0):
action_name = idc.get_strlit_contents(idaapi.get_dword(ea)).decode()
post_func_addr = idaapi.get_dword(ea + 4)
get_func_addr = idaapi.get_dword(ea + 8)
#idc.SetType(ea,"callaction")
print("action name: %s"%action_name)
if post_func_addr != 0:
idc.set_name(post_func_addr,(action_name + "_post"))
if get_func_addr != 0:
idc.set_name(get_func_addr,(action_name + "_get"))
sz += 4
ea += 4
def main():
search_data_base()
fix_dataSeg_funcptr()
if __name__ == "__main__":
main()
恢复结果如下。如果全局变量段将变量类型设置成结构体的话,反而会找不到交叉引用,所以我只重命名了函数,把设置结构体那一行注释掉了。