您的位置:首页 > 其它

replace ollydbg's WNDPROC on OD's plugin

2016-07-17 17:27 204 查看

前言

在ODBG_Pluginshortcut中处理F1, 发现在CPU窗口不来F1.

再试下, 替换OD的窗口处理函数,是否能在每个窗口都收到F1按下的消息.

实验结果:在CPU窗口按F1, 不会被主窗口的窗口处理过程捕获.

看起来像是, CPU窗口子类化过了, 有自己的窗口处理过程.

代码片段

// MyOdPlugin.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "MyOdPlugin.h"

#include "plugin.h"
#pragma comment(lib, "OLLYDBG.LIB")

// 测试位
#define TEST_BIT_00 0x00000001
#define TEST_BIT_01 0x00000002
#define TEST_BIT_02 0x00000004
#define TEST_BIT_03 0x00000008
#define TEST_BIT_04 0x00000010
#define TEST_BIT_05 0x00000020
#define TEST_BIT_06 0x00000040
#define TEST_BIT_07 0x00000080

#define TEST_BIT_08 0x00000100
#define TEST_BIT_09 0x00000200
#define TEST_BIT_10 0x00000400
#define TEST_BIT_11 0x00000800
#define TEST_BIT_12 0x00001000
#define TEST_BIT_13 0x00002000
#define TEST_BIT_14 0x00004000
#define TEST_BIT_15 0x00008000

#define TEST_BIT_16 0x00010000
#define TEST_BIT_17 0x00020000
#define TEST_BIT_18 0x00040000
#define TEST_BIT_19 0x00080000
#define TEST_BIT_20 0x00100000
#define TEST_BIT_21 0x00200000
#define TEST_BIT_22 0x00400000
#define TEST_BIT_23 0x00800000

#define TEST_BIT_24 0x01000000
#define TEST_BIT_25 0x02000000
#define TEST_BIT_26 0x04000000
#define TEST_BIT_27 0x08000000
#define TEST_BIT_28 0x10000000
#define TEST_BIT_29 0x20000000
#define TEST_BIT_30 0x40000000
#define TEST_BIT_31 0x80000000

// OD插件名字最长为31个字符
//                         0--------90--------90--------90
#define MY_OD_PLUGIN_NAME "MyOdPlugin1"

HWND g_hOdWnd = NULL; ///< OD 的窗口句柄
LONG_PTR g_OldWndProc = NULL; ///< 原始的窗口处理过程

LRESULT CALLBACK MyWindowProc(
HWND hwnd,      // handle to window
UINT uMsg,      // message identifier
WPARAM wParam,  // first message parameter
LPARAM lParam   // second message parameter
);

LRESULT CALLBACK OnWmKeyDown(
HWND hwnd,       // handle to window
UINT uMsg,       // WM_KEYDOWN
WPARAM wParam,   // virtual-key code
LPARAM lParam    // key data
);

LRESULT CALLBACK OnWmKeyDownF1(
HWND hwnd,       // handle to window
UINT uMsg,       // WM_KEYDOWN
WPARAM wParam,   // virtual-key code
LPARAM lParam    // key data
);

void ReplaceWndProc();
void RestoreWndProc();

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD  ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

// OD启动时,应该是检测了2个必须的插件函数都存在的DLL, 才会当插件来用
// 只实现2个必须函数函数之一时, 插件函数不会被调用

// 先调用 ODBG_Plugindata
int ODBG_Plugindata(char *shortname) {
if (NULL != shortname) {
strcpy(shortname, MY_OD_PLUGIN_NAME);
}

return PLUGIN_VERSION;
}

// 再调用 ODBG_Plugininit
int ODBG_Plugininit(int ollydbgversion,HWND hw,ulong *features) {
if (PLUGIN_VERSION != ollydbgversion) {
return -1;
}

g_hOdWnd = hw;
ReplaceWndProc();

return 0;
}

void ODBG_Plugindestroy(void) {
// OD关闭的时候, 会来这里
// IsWindow(g_hOdWnd) 已经无效了
// 只有OD未关闭, 只卸载插件的情况下, 才会恢复原始OD窗口过程
RestoreWndProc();
}

void ReplaceWndProc() {
if (NULL != g_hOdWnd) {
// OD的窗口过程是A版的
g_OldWndProc = SetWindowLongPtrA(g_hOdWnd, GWLP_WNDPROC, (LONG_PTR)MyWindowProc);
}
}

void RestoreWndProc() {
if ((NULL != g_hOdWnd)
&& (NULL != g_OldWndProc)) {

if (IsWindow(g_hOdWnd)) {
SetWindowLongPtrA(g_hOdWnd, GWLP_WNDPROC, g_OldWndProc);
g_OldWndProc = NULL;
}
}
}

LRESULT CALLBACK MyWindowProc(
HWND hwnd,      // handle to window
UINT uMsg,      // message identifier
WPARAM wParam,  // first message parameter
LPARAM lParam   // second message parameter
) {

if (WM_KEYDOWN == uMsg) {
if (S_OK == OnWmKeyDown(hwnd, uMsg, wParam, lParam)) {
return S_OK; // An application should return zero if it processes this message.
}
}

return CallWindowProc((WNDPROC)g_OldWndProc, hwnd, uMsg, wParam, lParam);
}

LRESULT CALLBACK OnWmKeyDown(
HWND hwnd,       // handle to window
UINT uMsg,       // WM_KEYDOWN
WPARAM wParam,   // virtual-key code
LPARAM lParam    // key data
) {
if (S_OK == OnWmKeyDownF1(hwnd, uMsg, wParam, lParam)) {
return S_OK;
}

return S_OK;
}

LRESULT CALLBACK OnWmKeyDownF1(
HWND hwnd,       // handle to window
UINT uMsg,       // WM_KEYDOWN
WPARAM wParam,   // virtual-key code
LPARAM lParam    // key data
) {
// wParam : Specifies the virtual-key code of the nonsystem key
if ((wParam != VK_F1) ///< the F1 key only
&& ((lParam & TEST_BIT_29) == 0) ///< when keydown, the prev key status is up, only process the first key down
) {
return S_FALSE;
}

// 在CPU窗口按F1, 被OD吃掉了, 不会来F1
// 其他子窗口中按下F1, 可以来
// 和 ODBG_Pluginshortcut 处理效果一样
// 好处是, 如果用自己的窗口处理过程, 可以处理的更细, 不止是键盘组合键

// 弹出帮助文件
if ((NULL != g_hOdWnd) && (::IsWindow(g_hOdWnd))) {
::PostMessage(
g_hOdWnd,
WM_COMMAND,
MAKEWPARAM(2504, 0),  // notification code and identifier
0); // handle to control (HWND)
}

return S_OK;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: