如何拦截对已知 DLL 中具有已知名称的函数的调用

逆向工程 视窗 C++ C dll
2021-07-02 13:52:50

首先,直到现在我还不太喜欢倒车,所以如果我的问题很愚蠢,请原谅。

我有一个很可能是用 Visual C++ 制作的 Windows DLL。它是在 1998 年开发的,并且随附了 Mfc42.dll (4.21.7022) 和 mfc42u.dll 以及 msvcirt.dll (5.00.7022)。

我设法看到了 DLL 导出的函数名称(这很容易),但当然看不到它们的参数。这些函数不是由任何应用程序直接调用的,但我知道它们是间接调用的。我认为它们正在被其他一些 API 调用,但我不知道该链。

我的问题是:是否可以提取函数签名(函数参数和返回值),编写某种绑定(应该是可能的)并最终自己调用它们?

最后一个补充是有问题的 DLL 具有 DllRegisterServer 和 DllUnregisterServer 函数。

更新

我正在谈论的 DLL 来自旧的语音合成器 L&H TTS3000。我想研究它更多的是为了好玩而不是为了一些真实的东西,因为它非常老而且已经退休,不应该遇到任何麻烦。因此,如果有人想复制这些 DLL,您可以浏览到此页面:http : //www.v3mail.com/download/ttsengines.htm 并下载任何额外的声音。它们不可用(文件被删除)但可以使用 web.archive.org 下载。所以这里是英语语音 DLL 之一的转储示例

dumpbin Engvf160.dll /exports
...
File Type: DLL

  Section contains the following exports for ENGVF160.dl

           0 characteristics
    373160B4 time date stamp Thu May 06 13:28:20 1999
        0.00 version
           1 ordinal base
          99 number of functions
          18 number of names

    ordinal hint RVA      name

         97    0 0000E23A DllRegisterServer
         98    1 0000E25B DllUnregisterServer
         99    2 000099A0 TtsEgGetCodeInfo
          1    3 0000E280 vfClose
          2    4 0000E308 vfGenPcm
          3    5 0000E389 vfGetCaps
          4    6 0000EE61 vfGetSil
          5    7 0000EEA3 vfGetSpkr
          6    8 0000EF11 vfGetVersion
          7    9 0000F63D vfGetVol
          8    A 0000EF4E vfOpen
          9    B 0000F16D vfP2Tic
         10    C 0000F479 vfSetSegDb
         11    D 0000F482 vfSetSil
         12    E 0000F4D6 vfSetSpkr
         13    F 0000F550 vfSetSynthRange
         14   10 0000F67F vfSetVol
         15   11 0000F6D3 vfTuneSpkr

  Summary

        7000 .data
       7B000 .rdata
        3000 .reloc
        1000 .rsrc
        F000 .text

进口:

... Section contains the following imports:

   KERNEL32.dll
             63470020 Import Address Table
             634EA1C0 Import Name Table
                    0 time date stamp
                    0 Index of first forwarder reference

                308  lstrlenA
                1F5  OutputDebugStringA
                2FF  lstrcmpiA
                17D  GetWindowsDirectoryA
                2F9  lstrcatA
                302  lstrcpyA
                 5D  DisableThreadLibraryCalls

   ADVAPI32.dll
             63470000 Import Address Table
             634EA1A0 Import Name Table
                    0 time date stamp
                    0 Index of first forwarder reference

                176  RegQueryInfoKeyA
                162  RegDeleteKeyA
                15B  RegCloseKey
                172  RegOpenKeyExA
                15F  RegCreateKeyExA
                186  RegSetValueExA
                164  RegDeleteValueA

   MSVCRT.dll
             63470040 Import Address Table
             634EA1E0 Import Name Table
                    0 time date stamp
                    0 Index of first forwarder reference

                291  malloc
                 F1  _ftol
                2B3  sqrt
                18E  _pctype
                115  _isctype
                 61  __mb_cur_max
                2C1  strncpy
                2B0  sin
                258  fprintf
                113  _iob
                2B2  sprintf
                2BA  strcpy
                25E  free
                299  memset
                10F  _initterm
                 9D  _adjust_fdiv
                297  memcpy
1个回答

坏消息

DllRegisterServerDllUnregisterServer是将 COM 服务器 DLL 注册到系统中所涉及的两个函数。因此,它们的导出很好地表明您正在处理 COM 服务器 DLL。COM 服务器因其许多间接调用而臭名昭著,主要是因为 DLL 服务器从其自身公开了旨在供其他可执行文件和 DLL 使用的对象。您可能不得不处理不同可执行文件之间的许多间接调用。

好消息

现在,好消息是,因为 COM 以这种自由方式定义函数和对象,它还鼓励创建类型库文件 (*.tlb)。这些文件具有机器可读的格式,用于详细定义类、方法和接口。如果您可以找到 DLL 的类型库文件,则可以直接从这些文件中提取所有函数参数(包括名称!)、函数返回类型等。

类型库文件可能位于应用程序的目录中,与其他应用程序资源一起或作为 PE 文件本身的一部分。几个类型库文件阅读器,以及 python 实现(pythoncom.LoadTypeLib来自win32 包)。

文档有点稀缺,但拥有类型库将使整个逆向工程更容易。

如果一切都失败了

在不幸的情况下,您找不到类型库文件,您必须对您感兴趣的函数进行逆向工程拦截,并从函数本身中提取参数的含义(以及类型和大小)。与同时拥有调用者和被调用者相比,这通常有点棘手,但非常可行。对于进程内 COM 服务器,您甚至可以非常轻松地调试对 COM 服务器的调用(通过调试加载 DLL/com 服务器的可执行文件、COM 客户端,并在COM 服务器的方法上放置断点) .

最后一件事,有一些自动化工具会尝试自动生成 DLL 代理,这是一个.