IDA 逆 WDF 驅動時的函式識別外掛

窮到底發表於2023-04-02

快一年沒更新了,累,工作累,各種累,想換個工作,突然發現找不到合適的工作了,哎,自己往火坑裡跳,怪不得別人。

 

import idautils
import idaapi
import idc

print("new ------------------------------------------")

#ea = idc.get_curline()
#print(ea)

# 
def GetWdfVersionBindObject(addr):
    for x in XrefsTo(addr,flags=0):
        cur_addr = x.frm
        cur_asm = GetDisasm(cur_addr)
        if (cur_asm.startswith("call")):
            pass
        else:
            continue

        func_addr = idc.get_func_attr(cur_addr,FUNCATTR_START)
        
        pre_addr = cur_addr
        while True:
            if pre_addr <= func_addr:
                break
            pre_addr = idc.prev_head(pre_addr)
            pre_asm = GetDisasm(pre_addr)
            if (pre_asm.startswith("lea")):
                t = idc.get_operand_type(pre_addr, 0)
                # 暫存器
                if (t == 1):
                    pass
                else:
                    break
            
                data = idc.get_operand_value(pre_addr, 0)
                # r8
                if (data == 8):
                    t = idc.get_operand_type(pre_addr, 1)
                    data = idc.get_operand_value(pre_addr, 1)
                    return data
    return 0


# 從模組中找到對應符號地址
fpWdfVersionBind = idc.get_name_ea(0x140000000, "WdfVersionBind")
print('Address : WdfVersionBind : %#x'%fpWdfVersionBind)
# 根據對應符號地址,找到其第三個引數地址
pObject = GetWdfVersionBindObject(fpWdfVersionBind)
print('Address : Wdf Object : %#x'%pObject)
# 獲取的版本號
verBig = idaapi.get_dword(pObject + 0x10)
verMin = idaapi.get_dword(pObject + 0x14)
print("version :", verBig, verMin)


# 根據函式索引取函式名字
def GetNameByID(id):
    return ""


def MakeWdfFunctionInfo(addr):
    for x in XrefsTo(addr,flags=0):
        cur_addr = x.frm
        cur_asm = GetDisasm(cur_addr)
        if (cur_asm.startswith("mov")):
            pass
        else:
            continue
        #print("cur", cur_addr, cur_asm)
        
        pre_addr = idc.prev_head(cur_addr)
        pre_asm = GetDisasm(pre_addr)
        #print("pre", pre_addr, pre_asm)
        if (pre_asm.startswith("imul")):
            # 第 0 個引數型別是1,所以是暫存器
            type0 = idc.get_operand_type(pre_addr, 0)
            if (type0 == 1):
                pass
            else:
                break
            # 暫存器引數索引是 0,是rax
            data = idc.get_operand_value(pre_addr, 0)
            if (data == 0):
                pass
            else:
                break

            # 按理說應該是取運算元1,但是這裡1裡面沒值,所以取的是 2
            # 取出來的就是函式索引
            data = idc.get_operand_value(pre_addr, 2)
            
            # 根據函式索引
            func_name = GetNameByID(data)
            
            fun_addr = idc.get_func_attr(pre_addr,FUNCATTR_START)
            
            if (func_name != ""):
                ida_name.set_name(fun_addr, func_name)


# 尋找所有使用到的地方,並且修正對應函式名,程式設計索引對應函式名
MakeWdfFunctionInfo(get_qword(pObject + 0x20))

 

幾十行程式碼,有註釋,一些地方用的是硬編碼,需要改一改,但是目前至少能用了,還缺少一個東西,就是資料庫,

這個資料庫是根據不同版本的 WDF 函式資料庫

相關文章