从用户模式win32应用程序

时间:2015-05-25 13:12:22

标签: c++ windows

我正在编写一个应用程序,它可以从系统上的任何用户模式进程捕获stdout / stderr和调试消息,并将其打印到其控制台。有几种情况我过去一直在编写程序,并且由于程序的性质,无论是GUI,Windows服务等......;无法简单地看到控制台输出,因为没有控制台。显而易见的解决方法是更改​​print语句以调试OutputDebugString()之类的打印语句,然后附加调试器并查看输出。有时,特别是在内核模式调试中,设置调试器并查看所需的输出可能很棘手。

理想情况下,我正在编写的这个应用程序将允许您指定一个PID(并最终将处理驱动程序,现在不用担心) - 并且不作为调试器附加到应用程序,它将显示所有输出目的地调试器,stdout或stderr。

为此,我创建了一个将DLL注入系统上任何进程的应用程序。从DLL中我将一个trampoline挂钩插入到_write()过程中,以便从cout,cerr,wcout,wcerr,printf和fprintf中捕获发往stdout和stderr的数据。我现在的问题是_write()过程的地址在目标应用程序的每次运行中都会发生变化。目前我正在windbg中运行目标应用程序并执行x program!_write来查找地址,对其进行硬编码并测试我的钩子。

TLDR

当我运行_write()命令时,Windbg如何找到x program!_write的地址?如何从没有符号的注入到目标进程的DLL中执行相同的操作?

非常感谢任何帮助。可以在此处找到我当前进度的源代码:https://github.com/vix597/StJude

此外,如果有更好的方法从注入DLL的目标进程重定向stdout / stderr,我会全力以赴。我尝试了freopen但是唯一被重定向的输出是从注入的DLL本身输出而不是注入DLL的应用程序。我的工作是假设我无法控制目标应用程序源代码。我还没有验证在没有控制台时调用_write()

更新

在提出这个问题之前,我的测试程序是在静态库中使用MFC编译的。使用标准Windows库时,Windbg会在_write()中找到MSVCR120。对于那些试图回答这个问题的人来说,这可能会引起一些混淆,因此更加明确:

无论编译目标应用程序中的C ++运行时的方式如何,无论使用何种版本的C ++运行时环境,我如何找到_write()方法的地址?

我基本上想要这样的东西:

LPVOID fnWrite = GetProcAddress(GetModuleHandle(L"<module_name>"),"_write");

然而,这不起作用。

1 个答案:

答案 0 :(得分:1)

关于Windbg如何做的问题,它使用Windows的调试API。有了它,您可以使用方法来插入断点等。具体来说,要在程序中使用函数的地址,请使用dbghelp DLL(您需要使用PDB才能使用它)。

但是如果应用程序将运行时作为DLL使用,那么对于使用你有一个更简单的解决方案:在该入口点上放置一个钩子。看看This page in CodeProject