由于某种原因,Ghidra SRE 无法确定某些进口

逆向工程 吉德拉 进口改造
2021-06-22 14:25:51

将 Windows PE 可执行文件加载到 Ghidra SRE 后,从 MFC90U.DLL Ghidra 导入的某些函数未检测到:

                DAT_00aea270                   FUN_004ae180:004ae1ee, 
                                               FUN_004b0f40:004b1b84, 
                                               FUN_004bb2b0:004bb475, 
                                               FUN_0067a2f0:0067a332, [more]
        00aea270 af            ??         AFh     XREF[892]:
        00aea271 09            ??         09h
        00aea272 00            ??         00h
        00aea273 80            ??         80h

我确切地知道这是 CStringT :: Find 的一个函数。同样,Ghidra 也未定义 CStringT :: Replace 函数。

如果我强制地址 0x00AEA270 处的字节为指针类型,那么我将光标悬停在 DAT_800009af 变量上,Ghidra 会抱怨“地址:ram:800009af,地址不在内存中”:

                PTR_DAT_00aea270               FUN_004ae180:004ae1ee, 
                                               FUN_004b0f40:004b1b84, 
                                               FUN_004bb2b0:004bb475, 
                                               FUN_0067a2f0:0067a332, [more]
        00aea270 af 09 00 80   addr       DAT_800009af     XREF[892]:
                                               +----------------------+
                                               |Address: ram: 800009af|
                                               |Address not in memory |
                                               +----------------------+

同时,正确检测到来自同一个 MFC90U.DLL 的其他函数:

             **************************************************************
             *                POINTER to EXTERNAL FUNCTION                *
             **************************************************************
                 CStringT<wchar_t,class_StrTraitMFC_DLL<wchar_t,class_ATL
             CStringT<wchar    EAX:4          <RETURN>
             CStringT<wchar    ECX:4 (auto)   this
             CStringT<wchar    Stack[0x4]:4   param_1
                811  Ordinal_811  <<not bound>>
                PTR_operator=_00aea26c         FUN_004cdbe0:004ce2e5,
                                               FUN_00911be0:00914605, [more]
        00aea26c 2b 03 00 80   addr       MFC90U.DLL::ATL::CStringT<wchar_t,class_StrTra   XREF[4517]:

             **************************************************************
             *                POINTER to EXTERNAL FUNCTION                *
             **************************************************************
                 int __thiscall ShowWindow(CWnd * this, int param_1)
             int               EAX:4          <RETURN>
             CWnd *            ECX:4 (auto)   this
             int               Stack[0x4]:4   param_1
                 6604  Ordinal_6604  <<not bound>>
                 PTR_ShowWindow_00aea278                         ShowWindow:00947004  
        00aea278 cc 19 00 80    addr       MFC90U.DLL::CWnd::ShowWindow                     XREF[1]:

此外,Ghidra 未检测到的函数地址(0x800009af 是 CStringT::Find 和 0x80001723 是 CStringT::Replace)位于地址 0x8000032b 和 0x800019cc 之间,即 Ghidra SRE 检测到的那些函数的地址之间。也就是说,这些地址无论如何都不能是“地址不在内存中”!

结果,在列表窗口中:

    006c88a2 68 8c 98           PUSH       u_</HeaderData>_00b6988c
             b6 00
    006c88a7 8d 8d 34           LEA        ECX=>local_26d0,[EBP + 0xffffd934]
             d9 ff ff
                              -> DAT_800009af
    006c88ad ff 15 70           CALL       dword ptr [PTR_DAT_00aea270]
             a2 ae 00
    006c88b3 85 c0              TEST       EAX,EAX
    006c88b5 7c 13              JL         LAB_006c88ca

并在反编译器窗口中:

    iVar4 = (*(code *)&DAT_800009af)(L"</HeaderData>",0);
    if (-1 < iVar4) {

我只看到来自间接未知地址的未知调用。

但 IDA Pro 正确检测到相同的导入。这是从 IDA Pro 导入相同的导入窗口:

.idata:00AEA26C ; public: class ATL::CStringT<wchar_t, class StrTraitMFC_DLL<wchar_t, class ATL::ChTraitsCRT<wchar_t>>> & __thiscall ATL::CStringT<wchar_t, class StrTraitMFC_DLL<wchar_t, class ATL::ChTraitsCRT<wchar_t>>>::operator=(class ATL::CStringT<wchar_t, class StrTraitMFC_DLL<wchar_t, class ATL::ChTraitsCRT<wchar_t>>> const &)
.idata:00AEA26C                 extrn ??4?$CStringT@_WV?$StrTraitMFC_DLL@_WV?$ChTraitsCRT@_W@ATL@@@@@ATL@@QAEAAV01@ABV01@@Z:dword
.idata:00AEA26C                                         ; CODE XREF: sub_4016D0+15E↑p
.idata:00AEA26C                                         ; sub_402E30+30↑p ...
.idata:00AEA270 ; public: int __thiscall ATL::CStringT<wchar_t, class StrTraitMFC_DLL<wchar_t, class ATL::ChTraitsCRT<wchar_t>>>::Find(wchar_t const *, int)const
.idata:00AEA270                 extrn ?Find@?$CStringT@_WV?$StrTraitMFC_DLL@_WV?$ChTraitsCRT@_W@ATL@@@@@ATL@@QBEHPB_WH@Z:dword
.idata:00AEA270                                         ; CODE XREF: sub_401680+1A↑p
.idata:00AEA270                                         ; sub_403210+8B↑p ...
.idata:00AEA274 ; public: int __thiscall ATL::CStringT<wchar_t, class StrTraitMFC_DLL<wchar_t, class ATL::ChTraitsCRT<wchar_t>>>::Replace(wchar_t const *, wchar_t const *)
.idata:00AEA274                 extrn ?Replace@?$CStringT@_WV?$StrTraitMFC_DLL@_WV?$ChTraitsCRT@_W@ATL@@@@@ATL@@QAEHPB_W0@Z:dword
.idata:00AEA274                                         ; CODE XREF: sub_4011C0+269↑p
.idata:00AEA274                                         ; sub_41A3F0+D7↑p ...
.idata:00AEA278 ; __declspec(dllimport) public: int __thiscall CWnd::ShowWindow(int)
.idata:00AEA278                 extrn __imp_?ShowWindow@CWnd@@QAEHH@Z:dword
.idata:00AEA278                                         ; DATA XREF: CWnd::ShowWindow(int)↑r

这是 IDA Pro 列表窗口,显示了可执行文件中的相同位置:

.text:006C88A2                 push    offset aHeaderdata ; "</HeaderData>"
.text:006C88A7                 lea     ecx, [ebp+var_26CC]
.text:006C88AD                 call    ds:?Find@?$CStringT@_WV?$StrTraitMFC_DLL@_WV?$ChTraitsCRT@_W@ATL@@@@@ATL@@QBEHPB_WH@Z ; ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::Find(wchar_t const *,int)
.text:006C88B3                 test    eax, eax
.text:006C88B5                 jl      short loc_6C88CA

调用此函数的 Hex-Rays 反编译器窗口也位于可执行文件内的同一位置:

    v18 = ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::Find(&v39, L"</HeaderData>", 0);
    if ( v18 >= 0 )
    {

但是,与 Hex-Rays 反编译器相比,我更喜欢 Ghidra 反编译器的结果,因此我希望至少对这个特定的可执行文件使用 Ghidra。

如何使用 Ghidra 实现正确导入?我应该怎么做才能修复它?我怎么能告诉 Ghidra 这些是位于可执行进程内正常地址的正常导入函数?

是的,文件中有 CStringT::Find 和 CStringT::Replace 的描述~/ghidra_9.1.2_PUBLIC/Ghidra/Features/Base/data/symbols/win32/mfc90u.exports

[...]

<EXPORT ORDINAL="2479" NAME="?Find@?$CStringT@_WV?$StrTraitMFC_DLL@_WV?$ChTraitsCRT@_W@ATL@@@@@ATL@@QBEHPB_WH@Z" PURGE="-1" COMMENT="" />

[...]

所以 Ghidra SRE 知道这些函数是否存在以及如何正确命名它们,但由于某种原因,它没有像从 MFC90U.DLL 导入的那样正确检测和定义它们。为什么?

我运行 Ghidra 9.1.2 public release 2020 年 2 月 12 日 1149 EST 和 IDA Pro 版本 7.1.180227。

0个回答
没有发现任何回复~