DLL监控

3
有没有一款应用程序可以让我查看从一个进程发送到 DLL 的内容?
我有一个进程和一个 DLL,我想监视被发送到函数的参数,以便我自己使用该 DLL。
DLL 的导出为:
??0CCPCompressor@@AAE@XZ ??0CCPExpandor@@AAE@XZ ??1CCPCompressor@@AAE@XZ ??1CCPExpandor@@AAE@XZ ?Clear@CCPCompressor@@QAEHXZ ?Clear@CCPExpandor@@QAEHXZ ..Compress@CCPCompressor.. ..Delete@CCPCompressor.. ..Delete@CCPExpandor.. ..Expand@CCPExpandor.. ..Free@CCPCompressor.. ..Free@CCPExpandor.. ..Init@CCPCompressor.. ..Init@CCPExpandor.. ..New@CCPCompressor.. ..New@CCPExpandor..

3
可能是如何拦截DLL方法调用?的重复问题。 - Steve Townsend
查看您的DLL导出引发了严重的警示 - 您正在从DLL中导出C++修饰名称。这意味着您的DLL不会在不同的C++编译器之间进行互操作(它们都有自己的名称修饰算法),甚至在不同版本的C++编译器之间也不行(名称修饰算法会随版本变化而改变)。 - Larry Osterman
我相信这种技术是Sysinternal工具之一使用的,或者我看到过由Sysinternal的人员撰写关于这种注入方法的文章。记不清了。无论如何,编码愉快。 - user166390
一些帮助:监控工具 - lsalamon
4个回答

0
最简单的方法是将原始dll简单地重新定位,并创建一个新的dll,其中包含相同的导出项。这个dll会从备用位置LoadLibrary旧的dll。
但这并不适用于这里——dll正在导出c++类成员,这有两个后果:c++类必须静态加载,因为没有c++机制将c++函数指针(通过GetProcAddress获得)粘合到类实例中。
这意味着你的shim dll将不幸地处于既要导入又要导出相同一组符号的位置。
唯一的解决办法是将shim dll分为两部分:
Shim1:
一部分将获取原始dll的名称,并导出与原始dll相同的类定义。
Shim2:
第二部分将导入原始dll,并将其包装在一个类中,该类将公开所有原始dll的函数。
 class __decldpec(dllexport) CCPCompressor {
  ...

Depends可以破解名称修饰,或者Undname.exe与Visual Studio一起分发。

这部分将使用显式路径加载shimdll2.dll,该dll位于其他文件夹中,并与原始dll一起使用。需要使用GetProcAddress()导入由shimdll2.dll导出的函数。

Shim2:

另一个shim dll将位于尝试拦截的dll所在的文件夹中。该dll必须从原始压缩器dll中导入类:

class __declspec(dllimport) CCPCompressor {
  ...

您可以使用第一个dll创建的dll导入库来实际链接符号。 然后,只需从shim2.dll导出函数,每当调用CCPCompressor方法时,shim1.dll将调用这些函数。

NB. 其他事项:您的CCPCompressor类版本至少需要有一个大型虚拟数组,因为您无法从dll导出中知道应用程序期望该类的大小(除非您恰好有描述该类的实际头文件)。


为了分解导出的名称以构建类定义: 从开始菜单 > 程序 > Visual Studio 20XX -> 工具菜单中打开Visual Studio 20XX命令提示符。

c:\...\VC>undname ?Clear@CCPCompressor@@QAEHXZ
Microsoft (R) C++ Name Undecorator

Undecoration of :- "?Clear@CCPCompressor@@QAEHXZ"
is :- "public: int __thiscall CCPCompressor:Clear(void)"

c:\...\VC>_

对于从原始dll导出的每个函数执行此操作(undname接受某种文本文件以加快此过程),以找出如何声明匹配的类定义。


我该如何找到与原始dll导出的相同类定义? - None__
如果你没有它,那么你需要发明它:使用depends.exe来映射每个函数原型,并将它们全部添加到你自己的类声明中。 - Chris Becke
我已经组合了以下内容,但是 ::New 我不确定。class __decldpec(dllexport) CCPCompressor<BR>{<BR>private:<BR>CCPCompressor(void);<BR>~CCPCompressor(void);<BR>public:<BR>int Clear(void);<BR>unsigned short Compress(unsigned char* const, unsigned short, unsigned char* const, unsigned short, int);<BR>void Delete(void);<BR>void Free(void);<BR>int Init(void);<BR>}<BR>static class CCPCompressor * __cdecl CCPCompressor::New(void);<BR><BR>你有哪些值得阅读的与此相关的非常好的URL吗? - None__
那个类定义看起来适合于类 shi m dll。不幸的是,我想不出任何好的网站涵盖这个主题,坦白地说,在此帖子之前,我从未考虑过如何从 dll 钩取 c++ 类。 - Chris Becke

0
一般来说,这是一个不好的想法。即使您有一些捕获的参数集,如果没有对DLL代码进行深入分析,您就不知道如何处理这些参数以及某些方法接受哪些参数范围。例如:如果我调用一个方法DoMathOperation(Add, 1, 2),您可以模仿此调用,但您将无法执行DoMathOperation(Multiply, 2, 2),因为您不知道这是可能的。

0

使用detours是否符合您的要求?

来自该网站:

概述

创新的系统研究取决于轻松地对现有操作系统和应用程序功能进行仪器化和扩展的能力。如果可以访问适当的源代码,则通过重新构建操作系统或应用程序,插入新的仪器化或扩展通常是微不足道的。然而,在今天的世界上,系统研究人员很少能够访问所有相关的源代码。

Detours是一个库,用于在x86、x64和IA64机器上仪器化任意Win32函数。Detours通过重写目标函数的内存中的代码来拦截Win32函数。Detours包还包含实用程序,用于将任意DLL和数据段(称为有效载荷)附加到任何Win32二进制文件。

Detours保留未经仪器化的目标函数(可通过跳板调用)作为仪器化使用的子例程。我们的跳板设计使得现有二进制软件的大类创新扩展成为可能。

我们已经使用Detours创建了一个自动分布式分区系统,对DCOM协议栈进行了仪器化和分析,并为基于COM的操作系统API创建了一个thunking层。Detours在Microsoft内部和行业内广泛使用。


我可以尝试一下,但从其他帖子中得知似乎不能用于监视具有类的DLL。如果您能告诉我如何做到,我会尝试一下。谢谢。 - None__
C++类方法指针没有定义应用程序二进制接口。结果是,由于它们的大小可能会大相径庭,因此无法通过void*传递方法指针。Detours需要具有匹配调用约定的函数地址来挂钩被挂钩函数,我无法看到如何提供这个地址。 - Chris Becke
嗯,类只是一组方法,从您的角度来看 - 如果捕获方法并记录其调用和参数,您将获得一些东西。 - Daniel Mošmondor
@Chris:他没有提到他想要监视对象实例?也许如果他只想要参数,并忽略'this',那么这可能是可行的? - Daniel Mošmondor
  1. 他想使用dll,所以无论如何都需要反向工程类定义。
  2. 当拦截现有exe对dll的调用时,不清楚如何使用代码将Detours注入进程中。
  3. 即使跨越了这个障碍,注入之前进行的调用也会被忽略。
  4. 我可以想到两种潜在的使用Detours的方法:1. 创建一个本地shim类,并尝试将类方法指针转换为普通内存地址以传递给DetourAttach,2. Detour到c方法,使用一些自定义asm来处理__fastcall参数打包。
- Chris Becke

0
唯一可靠的方法是调试你的程序(使用任何调试器,如 OllyDBG),并在所需的导出函数上设置断点。然后您可以简单地跟踪发送到调用函数的堆栈参数。这只是开始,您需要完全分析调试器或反汇编器中的函数指令,以查看每个参数正在执行的操作及其类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接