【问题标题】:Can I call a Win32 API from the Visual Studio Immediate Window?我可以从 Visual Studio 即时窗口调用 Win32 API 吗?
【发布时间】:2010-11-21 16:11:33
【问题描述】:

我正在调试一个 C++ Win32 应用程序,我想从该进程的上下文中调用任意 Win32 API,就好像程序已经运行了这行代码:

DestroyWindow(0x00021c0e);

但是将它输入到即时窗口会给出:

CXX0017: Error: symbol "DestroyWindow" not found

编辑:使用函数的全名{,,user32.dll}_NtUserDestroyWindow@4,我可以得到即时窗口来了解我指的是哪个函数并显示函数的地址:

{,,user32.dll}_NtUserDestroyWindow@4
0x76600454 _NtUserDestroyWindow@4

但是当我尝试调用它时,会发生这种情况:

{,,user32.dll}_NtUserDestroyWindow@4(0x00021c0e);
CXX0004: Error: syntax error

是否有可能像这样从即时窗口调用 C 函数,还是我找错了树?

【问题讨论】:

    标签: c++ c visual-studio debugging winapi


    【解决方案1】:

    我认为问题在于 C++ EE 在解析 DestroyWindow 的上下文时遇到了问题。试试下面的

    {,,user32}DestroyWindow(0x00021c0e);
    

    我不确定方法调用语法是否支持这种限定风格(过去仅用于强制转换)。但值得一试。

    编辑您可能需要也可能不需要添加 !结束后}。自从我使用这种语法已经有一段时间了,我经常将它与等效的 windbg 混淆。

    【讨论】:

    • 感谢您的建议,但我已经尝试过了,但它不起作用。我也尝试将其装饰为_DestroyWindow@4 等,一直到完全合格的{,,user32.dll}_DestroyWindow@4,但没有任何乐趣。
    • @JaredPar:+1 帮助改善这种情况 - 请参阅我编辑的问题。我现在可以让它理解我指的是哪个函数,但我仍然无法让它调用它。
    • @Richie,谢谢!也为您的答案 +1。哇,顺便说一句。
    • @JaredPar:谢谢...我有点尴尬,因为我今年早些时候写了一篇关于这个问题的博客文章:entrian.com/blog/… 8-)
    【解决方案2】:

    我想出了一个解决方法,但我仍然希望让即时窗口工作。

    解决方法是:

    • 获取函数的地址,如题中所示
    • 使用反汇编窗口转到该地址,并在此处放置断点
    • 对应用程序做一些事情让它调用DestroyWindow
    • 将调用堆栈退回到DestroyWindow的调用者,如下所示:

      6D096A9D 推送 ecx
      6D096A9E 调用 dword ptr ds:[6D0BB4B8h]

    • push ecx指令上放一个断点,并清除DestroyWindow上的断点

    • 点击继续,然后再次对应用程序执行某些操作以使其调用该代码
    • 记下ecx的值
    • 将调试器中ecx 的值更改为所需的值并跳过push/call
    • 恢复ecx的值并使用Set Next Statement返回push,然后继续

    它很冗长,但它确实有效。它假定您可以让应用程序随意调用相应的 API。

    【讨论】:

      【解决方案3】:

      一旦你有了函数地址(正如你在更新的问题中所做的那样),你可以尝试将它转换为函数指针并调用它:

      (*(BOOL (*)(HWND))0x76600454)((HWND)0x00021c0e)
      

      第一部分将地址转换为BOOL (*)(HWND),它是一个指向函数的指针,该函数采用HWND 参数并返回BOOL。然后,函数指针被取消引用并被调用。确保参数正确,否则会发生不好的事情。在 64 位系统上,HWND 可能是 64 位,因此您可能无法将参数作为 int 传递。

      编辑:请参阅 cmets 了解完整内容。

      【讨论】:

      • 感谢您的想法,但是...这给了我CXX0004: Error: syntax error。将 Windows 类型(BOOLHWND)替换为原始类型(在这两种情况下为int)会有所改善,但我会得到CXX0014: Error: missing operand。 (顺便说一句,我在一个 32 位进程中。)
      • 显然,VS 调试器不擅长解析函数指针类型。尝试为它创建一个 typedef。将typedef BOOL (*DESTROYWINDOW)(HWND); 放入代码中,然后在调试器中写入(*(DESTROYWINDOW)0x76600454)((void*)0x00021c0e)
      • @Adam:耶! (但一个合格的)。通过将typedef 添加到我的代码中,并且实际上在代码中使用typedef,这样编译器就不会丢弃定义,并且会中断执行在我使用typedef 的编译单元内的进程中,我现在可以从即时窗口调用 DestroyWindow。谢谢!不得不跳过这些障碍来做到这一点很可惜,但至少这是可能的。
      • 这绝对是可怕的。我只是有同样的经历。这是一个巨大的 Visual Studio 失败。
      • 有人知道如何在 NTSD 中使用 .call 吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-13
      • 2020-03-22
      • 2021-10-23
      • 2021-09-10
      • 2011-05-31
      相关资源
      最近更新 更多