首页
论坛
课程
招聘
使用SetWindowsHookExA对特定进程注入DLL时,使用MessageBox出错
2021-2-28 11:52 1247

使用SetWindowsHookExA对特定进程注入DLL时,使用MessageBox出错

2021-2-28 11:52
1247

在使用 SetWindowsHookExA 对特定进程进行Dll注入时,发现在DLL的回调函数中不能使用 MessageBox 。一旦调用该函数,就会造成被注入的目标进程崩溃!
希望解答一下!

 

DLL函数部分的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <windows.h>
#include <TlHelp32.h>
#include <stdio.h>
 
#pragma data_seg(".shared")
CHAR szBuff[100] = {0};
HHOOK g_hHook = NULL;
#pragma data_seg()
#pragma comment(linker,"/section:.shared,rws")
 
// 钩子回调函数
LRESULT MessageProc(
    int nCode,
    WPARAM wParam,
    LPARAM lParam);
 
DWORD GetWindowThreadID(LPSTR lpszWindowName)
{
    // 初始化
    HANDLE hProcess;
    HANDLE hThreadSnap = NULL;    // 模块快照
    DWORD th32ThreadID = 0;
    DWORD dwPid = 0x00;
    THREADENTRY32 thread32 = { 0 };
    BOOL bMoreOfThread;
 
    //获取进程句柄
    HWND hwnd = FindWindow(NULL, lpszWindowName);
    if (!hwnd)
    {
        return FALSE;
    }
 
 
    GetWindowThreadProcessId(hwnd, &dwPid);
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
 
    //获取线程ID
    thread32.dwSize = sizeof(thread32);
 
    hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (hThreadSnap == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    }
 
    bMoreOfThread = Thread32First(hThreadSnap, &thread32);
    while (bMoreOfThread)
    {
        if (thread32.th32OwnerProcessID == dwPid)
        {
            th32ThreadID = thread32.th32ThreadID;
            break;
        }
        bMoreOfThread = Thread32Next(hThreadSnap, &thread32);
    }
 
    CloseHandle(hThreadSnap);
 
    return th32ThreadID;
}
 
// 设置全局钩子
BOOL SetGlobalHook(int idHook, LPSTR lpszWindowName)
{
    DWORD threadID = GetWindowThreadID(lpszWindowName);
    if (!threadID)
    {
        return FALSE;
    }
    g_hHook = SetWindowsHookEx(idHook, (HOOKPROC)MessageProc, GetModuleHandle("TestDll"), threadID);
    if (NULL == g_hHook)
    {
        return FALSE;
    }
    return TRUE;
}
 
 
// 卸载钩子
BOOL UnsetGlobalHook()
{
    if (g_hHook)
    {
        UnhookWindowsHookEx(g_hHook);
        return TRUE;
    }
    else
        return FALSE;
}
 
// 钩子回调函数
LRESULT MessageProc(
    int nCode,
    WPARAM wParam,
    LPARAM lParam)
{
    if (nCode == HC_ACTION)
    {
        PCWPSTRUCT pcw = (PCWPSTRUCT)lParam;
        if(pcw->message == WM_USER+1)
        {
            MessageBox(0,0,0,0);
        }
 
    }
    return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}

测试函数部分代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
typedef BOOL(*typedef_SetGlobalHook)(int idHook, LPSTR lpszWindowName);
typedef BOOL(*typedef_UnsetGlobalHook)();
LPSTR lpszWindowName = "test";
 
HMODULE hModule = LoadLibrary("C:\\vc6++\\MyProjects\\TestDll\\Debug\\TestDll.dll");
 
    //获取进程句柄
    HWND hwnd = FindWindow(NULL, lpszWindowName);
    if (!hwnd)
    {
        printf("获取进程句柄失败!\n");
        return FALSE;
    }
 
    typedef_SetGlobalHook SetGlobalHook = (typedef_SetGlobalHook)GetProcAddress(hModule, "SetGlobalHook");
    BOOL bRet = SetGlobalHook(WH_CALLWNDPROC, lpszWindowName);
    SendMessage(hwnd, WM_USER+1, 12345678, 12341234);
 
    typedef_UnsetGlobalHook UnsetGlobalHook = (typedef_UnsetGlobalHook)GetProcAddress(hModule, "UnsetGlobalHook");
    UnsetGlobalHook();

调试图如下:
图片描述
当调用 MessageBox 时,并没有立刻弹出对话框,而是 EIP 在回调函数中一直循环。当我放开断点执行时,才弹出对话框,点完确定后,程序崩溃,提示 USER32.dll 中出现访存错误。

 

图片描述


 

经过测试发现,只要是使用SetGlobalHook 函数挂钩子,DLL中的MessageBox 都会引发程序崩溃。


[看雪官方培训] Unicorn Trace还原Ollvm算法!《安卓高级研修班》2021年6月班开始招生!!

最后于 2021-2-28 13:49 被ALwalker编辑 ,原因: 错别字
收藏
点赞0
打赏
分享
最新回复 (5)
雪    币: 0
活跃值: 活跃值 (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ALwalker 活跃值 2021-3-1 12:08
2
0

已解决! 

回到函数原型: 

LRESULT CALLBACK GetMsgProc(
  _In_ int    code,
  _In_ WPARAM wParam,
  _In_ LPARAM lParam
);


我当初使用回调函数时,把 `CALLBACK` 给落下啦。。。

雪    币: 229
活跃值: 活跃值 (949)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Mxixihaha 活跃值 2021-3-1 12:21
3
0
你那个  获取线程ID纯属多此一举

//获取线程ID
GetWindowThreadProcessId(hwnd, &dwPid);

这个函数的返回值就是返回的主线程的ID

DWORD ThreadID = GetWindowThreadProcessId(hwnd, &dwPid);
获取的就是主线程ID
雪    币: 0
活跃值: 活跃值 (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ALwalker 活跃值 2021-3-2 11:10
4
0
Mxixihaha 你那个 获取线程ID纯属多此一举 //获取线程ID GetWindowThreadProcessId(hwnd, &dwPid); 这个函数的返回值就是返回的主线程的ID ...
这个是获取进程PID的吧。
雪    币: 229
活跃值: 活跃值 (949)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Mxixihaha 活跃值 2021-3-3 10:31
5
0
ALwalker 这个是获取进程PID的吧。

不要忽略返回值.   

函数名字上就是  获取窗口线程进程ID 


 参数二 返回的是进程ID 

 函数返回值 是线程ID 


 编程不看MSDN的吗?

DWORD GetWindowThreadProcessId(
  HWND hWnd, 
  LPDWORD lpdwProcessId );
  
Parameters
hWnd [in] Handle to the window.

lpdwProcessId [out] Pointer to a 32-bit value that receives the process identifier. 
If this parameter is not NULL, GetWindowThreadProcessId copies the identifier of the process to the 32-bit value; otherwise, it does not.

Return Values

The return value is the identifier of the thread that created the window.
雪    币: 0
活跃值: 活跃值 (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ALwalker 活跃值 2021-3-3 11:16
6
0
Mxixihaha 不要忽略返回值. &nbsp;&nbsp;函数名字上就是 &nbsp;获取窗口线程进程ID&nbsp;&nbsp;参数二 返回的是进程ID&nbsp;& ...
谢谢,之前用的多了,都没注意返回值,谢谢指教了
游客
登录 | 注册 方可回帖
返回