模拟 Windows 菜单项激活

逆向工程 视窗 dll注入
2021-06-16 13:53:21

我试图将调用快捷方式调用到单击菜单项时激活的过程。

我在使用菜单栏创建此窗口的进程中注入了一个 DLL。

我使用 VisualStudio 中的 Spy++ 来获取此特定项目的菜单标识符(wid:40003)。现在我打电话

CallWindowProcW(wndproc, hwnd, WM_COMMAND, 40003, 0);

但是,不会触发项目过程。 我不能直接调用该过程,因为我不知道它是什么。我只知道当我点击这个菜单时它会激活它。

我已经获得windprochwnd在我的 DLL 中执行以下操作:

 void Init()
 {
     DWORD procID = GetProcessId(GetCurrentProcess());
     EnumWindows(myCallback, procID);
 }

 BOOL CALLBACK myCallback(HWND hWnd, LPARAM lParam)
 {
     DWORD wndId;

     GetWindowThreadProcessId(hWnd, &wndId);
     if(wndId == (DWORD)lParam) //Found the right window handle
     {
         WNDPROC windowFunc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
         LRESULT result = CallWindowProcW(windowFunc, hWnd, WM_COMMAND, 40003, 0);
         return FALSE;
     }
     return TRUE;
  }

编辑:也尝试过 SendMessageA、PostMessageA 和 DispatchMessageA 并且失败了

EDIT2:有关工作 PostMessageA,请参阅下面的答案。

2个回答

我已经确定了问题所在。它分为两个步骤:

1. 使用 PostMessageA 而不是 CallWindowProc

PostMessageA(hWnd, WM_COMMAND, 40003, 0) 完成繁重的工作并在所需的窗口上调用 WindowProc。

2.确保窗口是顶级的

我之前忽略了这一点,因为应用程序窗口是可见的,我认为它是顶级的。

但是,由于我正在执行注入的 dllEnumWindowsInit过程,因此我的启动器进程仍在运行并且该窗口是我的启动器的子窗口。

我不得不等待启动器退出,然后调用EnumWindowsPostMessage

我想对此发表评论,但没有足够的积分来这样做,因此这将是对答案的评论。

简单地说,windows 环境中最顶层的窗口接收 RawInputThread (RIT)。RIT 自动接收鼠标和键盘消息并将它们发送到位于 Z 顺序顶部的那个窗口。在遥远的过去做了很多这样的事情,如果你需要完全控制,可以做的一个技巧是实现一个覆盖整个屏幕的最顶部窗口(z 顺序)窗口,RIT 将提供一切消息,然后您可以对它们执行任何操作。

回到我做这件事的时候,几乎没有关于 RIT 的文档,但现在你可以找到很多文档。我在MSDN Raw Input上找到了这个,但看起来他们使它比实际需要的更复杂。多年来,微软一直在做一些事情,他们隐藏一个话题,然后澄清,然后把话题重新隐藏起来。Duckduckgo 显示了大量点击 并产生了一个不错的宝石,谷歌在其第一页上没有找到。