22.1 注入的一个例子(跨进程子类化窗口)

  ①子类化窗口可以改变窗口的行为,让发往该窗口的消息重新发到我们指定的过程来处理。但这种行为只能在本进程中(如A),对于从一个进程(如B)去子类化另一个进程(如A)时,会遇到无法跨越进程地址空间的边界问题。

  ②上图,进程B试图调用SetWindowLongPtr将进程A中的hWnd窗口过程,重新指定为MySubClassProc来处理(注意,MySubClassProc在进程B的地址空间中),而不是hWnd窗口的标准窗口处理过程。但因该行为是跨进程的,如果被允许的话,当系统要执行进程A的hWnd窗口过程时,就会试图调用进程A地址空间中另一个地址(该地址的值与进程B中的地址相同),原因是不同进程的地址空间是相互隔离的,所以会出现内存访问违规的错误。因此,为了避免这种错误,微软不允许SetWindowLongPrt修改别的进程的窗口过程

  ③要实现跨进程子类化窗口,须用到“DLL注入”技术,将DLL注入到进程的地址空间中。

22.2 使用注册表来注入DLL

(1)注册表项的使用

  ①AppInit_Dlls键可能会包含一个或一组Dll的文件名(用空格或逗号分隔,第一个Dll的文件名可包含路径,但其他Dll包含的路径会被忽略)。为了让系统使用这个注册表项,还须将LoadAppInit_Dlls的值设为1。

  ②因为路径可能会被忽略,所以最好将自己的Dll放到Windows的系统目录中,这样就不必指定路径了。

(2)User32.dll的映射

  ①当User32.dll被映射到一个新的进程时,该进程会收到DLL_PROCESS_ATTACH通知。User32.dll对它进行处理的时候,会取得上述注册表键的值,并调用LoadLibrary来载入这个字符串中指定的每个DLL。

  ②当系统载入每个DLL时,会调用它们的DllMain函数,并将参数fdwReason设为DLL_PROCESS_ATTACH,这样每个DLL就能够对自己进行初始化。

  ③由于被注入的DLL是在进程生命期的早期被载入,所以调用Kernel32.dll中的函数是没问题的,但其他DLL中的函数可能会导致问题。

(3)注册表注入DLL的缺点

  ①基于GUI的应用程序都使用了User32.dll,但大多数基于CUI的应用程序不会使用它。因此想要将DLL注入到编译器或链接器,这种方法是行不通的。

  ②DLL会被映射进每个基于GUI的应用程序中,导致这些进程的线程都在运行我们的代码,如果我们的代码进入无限循环或错误地访问了内存,那么会影响到“容器”进程(即其他基于GUI的所有进程)的行为和健壮性

  ③我们的DLL被映射到每个基于GUI应用程序中,其生命期会直到应用程序终止(因为进程终止时,才会发送DLL_PROCESS_DETACH通知给User32.dll,在这里会卸载到我们的DLL)。而理想的情况下,DLL应注入到我们需要的进程中,并且映射的时间越短越好。

22.3 使用Windows钩子来注入DLL

22.3.1 钩子的类型

(1)按作用范围

  ①局部钩子:仅钩挂属于自身进程的事件

  ②远程钩子:可钩挂自身进程,还可以钩挂其他进程中发生的事件。又分为基于线程和系统范围的。

(2)按监视消息的类型分类

钩子名称

监视消息的类型和时机

WH_CALLWNDPROC

每当调用SendMessage函数时,函数将消息发送给目标窗口前首先调用钩子函数

WH_CALLWNDPROCRET

每当调用SendMessage函数时,函数将消息发送给目标窗口过程后再调用钩子函数

WH_GETMESSAGE

每当调用GetMessage或PeekMessage函数时,函数从程序的消息队列中获取一个消息后调用钩子函数

WH_KEYBOARD

每当调用GetMessage或PeekMessage函数时,如果从消息队列中得到的是WM_KEYUP或WM_KEYDOWN消息时,则调用钩子函数

WH_MOUSE

每当调用GetMessage或PeekMessage函数时,如果从消息队列中得到的是鼠标消息,则调用钩子函数

WH_HARDWARE

每当调用GetMessage或PeekMessage函数时,如果从消息队列中得到的是非鼠标和键盘消息时,则调用钩子函数

WH_MSGFILTER

当用户对对话框、菜单和滚动条有所操作时,系统在发送对应的消息之前调用钩子函数,这种钩子只能是局部的

WH_SYSMSGFILTER

同WH_MSGFILTER,不过是系统范围的

WH_SHELL

当Windows shell程序准备接收一些通知事件前调用钩子函数,如shell被激活或重绘等。外壳应用程序是不接受WH_SHELL消息的,要使应用程序能够接收WH_SHELL,必须调用SystemParametersInfo函数注册该消息。WM_SHELL共有5种情况:

①TaskBar需要重绘某个按钮时

②当系统地要显示关于Taskbar的一个程序的最小化形式

③当目前的键盘布局状态改变。

④当按Ctrl+Esc去执行TaskManager(或相等级别的程序)时。

⑤只要有个top-level、unowned窗口被创建、起作用或被摧毁

WH_DEBUG

用来给其他钩子函数除错

WH_CBT

当基于计算机的训练(CBT)事件发生时调用钩子函数

WH_JOURNALRECORD

日志记录钩子,用来记录发送给系统消息队列的所有消息

WH_JOURNALPLAYBACK

日志回放钩子,用来回放日志记录钩子记录的系统事件

WH_FOREGROUNDIDLE

系统空闲钩子,当系统空闲的时候调用钩子函数,这样就可以在这里安排一些低优先级的任务

22.3.2 钩子程序的结构:

(1)主要的3个功能模块

模块

作用

①主程序

用来实现界面或者其他功能

②钩子回调函数

用来接收系统发过来的消息

①对于局部钩子,这些模块可在同一个EXE文件中

②对于远程钩子这个回调函数必须在一个DLL中

③钩子的安装和卸载模块

调用SetWindowsHookEx和UnhookWindowsHookEx函数。

①这部分虽然没有要求,但一般也放在DLL中,因为钩子创建以后会得到一个钩子句柄,这个句柄要在钩子回调函数中,以及卸载钩子的时候用到。

②如果把这部分代码放在主程序中的话,还需要创建一个函数将它传回给动态链接库,所以不如直接放在库中

(2)钩子的安装:SetWindowsHookEx

参数

说明

int idHook

要安装的钩子的类型

HOOKPROC lpfn

钩子回调函数(在我们的地址空间或某个DLL)

HINSTANCE hInstDll

标识一个DLL,这个DLL包含了钩子回调函数。

如果是局部钩子这里须为NULL。

DWORD dwThreadId

给哪个线程安装钩子。如果为0,表示给系统中所有的GUI线程安装钩子。

(3)举例说明钩子的工作过程——以WM_GETMESSAGE为例(进程A监视进程B的窗口消息,设钩子回调函数为GetMsgProc)

  ①当进程B的一个线程准备GetMessage一条窗口消息时。系统会检查该线程是否安装了WH_GETMESSAGE钩子。

  ②系统检查GetMsgProc所在的DLL是否己被映射进程B的地址空中。

  ③如果DLL尚未被映射,那么系统会强制将该DLL映射到进程B的地址空间中,并将进程B中该DLL的锁计数器递增

  ④由于安装钩子时参数hInstDll和回调函数的地址都是进程A地址空间中的值。当被映射到进程B时,系统会检查该DLL被映射的基地址是否与进程A中的位置相同。

    Ⅰ如果相同,那么在两个进程的地址空间中,GetMsgProc函数位于相同的位置,在这情况下,系统可以直接在进程B(课本这里写A,是否是错误?)的地址空间中调用GetMsgProc。

    Ⅱ如果不同,则得通过GetMsgProcB = hInstDllB + (GetMsgProcA - hInstDllA)公式计算GetMsgProc在进程B中的虚拟地址。

  ⑤系统在进程B中递增该DLL的锁计数器,这是因为调用GetMsgProc函数时须先锁定,以防止该DLL被别的线程卸载掉。当GetMsgProc返回后,系统递减该DLL在进程B中的锁计数器。

(4)钩子的卸载:BOOL UnhookWindowsHookEx(HHOOK hHook)

  ①当一个线程调用UnhookWindowsHookEx时,系统会遍历其内部维护的一个进程列表,该列表记录着那些己经注入过该DLL的进程。

  ②并将这些进程中该DLL的锁计数递减(注意每个进程都有各自对该DLL的锁计数器)。当某个进程的锁计数器减到0时,系统会自动从该进程的地址空间中撤消对该DLL的映射。

22.3.3 钩子链

(1)钩子链

  ①每一个钩子都有一个与之相关联的指针列表,称之为钩子链表,由系统来维护。这个列表的指针指向由应用程序定义的、后面由钩子调用的回调函数,也就是该钩子的各个处理子程。

  ②多个程序可以同时安装同一种钩子(如WH_GETMESSAGE),这些钩子组成一个钩子链,最近加入的钩子放在链表的头部,Windows负责为每种钩子维护一个钩子链。

  ③当一个事件发生的时候,Windows调用最后安装的钩子,然后由这个钩子的回调函数发起调用下一个钩子的动作,Windows收到这个动作后,再从链表中取出下一个钩子的地址并将调用传递下去。

(2)CallNextHookEx函数:调用下一个钩子回调函数的函数。

【Desktop Item Position Saver(DIPS)工具】——用来保存/恢复桌面图标的位置

(1)可能遇到的几个问题

  ①获得桌面的ListView控件窗口句柄的方法

  A、XP下

  //桌面的ListView控件是ProgMan窗口的孙子窗口

  hWndLV = GetFirstChild(GetFirstChild(FindWindow(TEXT("ProgMan"),NULL)));

  B、Win8下

HWND GetDestopListViewHandle(){
HWND hWnd = NULL,hWndItem;
HWND hWndParent = FindWindowEx(,,TEXT("WorkerW"),NULL);
while (hWndParent && (!hWnd)){ hWndItem = FindWindowEx(hWndParent, , TEXT("SHELLDLL_DefView"), NULL);
if (hWndItem){
hWnd = FindWindowEx(hWndItem, , TEXT("SysListView32"), TEXT("FolderView"));
break;
}
hWndParent = FindWindowEx(, hWndParent, TEXT("WorkerW"), NULL);
}
return hWnd;
}

  ②获取创建窗口的线程ID:dwThreadID = GetWindowThreadProcessID(hwnd,NULL)

  ③为Windows资源管理器创建一个“隐藏窗口”用于与DIPS.exe通信(利用窗口消息)

  ④卸载钩子时,须先销毁“隐藏窗口”这个对话框,再清除钩子。否则当对话框收到一下条消息时会导致Windows资源管理器的线程引发访问违规。

(2)实例源码

【动态链接库】

/************************************************************************
Module: DIPSLib.h
Notices: Copyright(c) 2008 Jeffrey Richter & Christophe Nasarre
************************************************************************/
#pragma once
#include <windows.h> #if !defined(DIPSLIBAPI)
#define DIPSLIBAPI __declspec(dllimport)
#endif ////////////////////////////////////////////////////////////////////////// //导出的外部函数原型
DIPSLIBAPI BOOL WINAPI SetDIPSHook(DWORD dwThreadId); //////////////////////////////////////////////////////////////////////////

//DIPSLib.cpp

/************************************************************************
Module: DIPSLib.cpp
Notices: Copyright(c) 2008 Jeffrey Richter & Christophe Nasarre
************************************************************************/ #include "../../CommonFiles/CmnHdr.h" #define DIPSLIBAPI __declspec(dllexport)
#include "DIPSLib.h"
#include "resource.h" //////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
//这个函数会强制调试器被调用
void ForceDebugBreak(){
__try{ DebugBreak();}
__except (UnhandledExceptionFilter(GetExceptionInformation())){}
}
#else
#define ForceDebugBreak()
#endif //////////////////////////////////////////////////////////////////////////
//前置声明
LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam); INT_PTR WINAPI Dlg_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); //////////////////////////////////////////////////////////////////////////
//通知编译器将g_hHook变量放在共享数据段中,以便让不同进程共享
#pragma data_seg("Shared")
HHOOK g_hHook = NULL;
DWORD g_dwThreadIdDIPS = ; //安装钩子的线程(这里是DIPS.exe中一个线程)
#pragma data_seg() #pragma comment(linker,"/section:Shared,rws") //可读可读、可共享 ////////////////////////////////////////////////////////////////////////// HINSTANCE g_hInstDll = NULL; //////////////////////////////////////////////////////////////////////////
BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, PVOID fImpLoad){
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
g_hInstDll = hInstDll;
break; case DLL_THREAD_ATTACH:
break; case DLL_THREAD_DETACH:
break; case DLL_PROCESS_DETACH:
break;
}
return (TRUE);
} //////////////////////////////////////////////////////////////////////////
BOOL WINAPI SetDIPSHook(DWORD dwThreadId){
BOOL bOk = FALSE; if (dwThreadId != ){
chASSERT(g_hHook == NULL);//断言钩子还未被安装 //保存我们的线程ID,以便在GetMsgProc函数里可以通过客户程序(DIPS.exe)与
//服务程序(Windows资源管理器)间进行通信
g_dwThreadIdDIPS = GetCurrentThreadId(); //为指定的线程安装WH_GETMESSAGE钩子
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInstDll, dwThreadId); bOk = (g_hHook != NULL);
if (bOk){
//钩子安装成功,发送一条消息到Windows资源管理器的消息队列里,这时资源管理器
//会检测到一条消息,并调用GetMessage,于是钩子函数就开始工作。
bOk = PostThreadMessage(dwThreadId, WM_NULL, , );
} } else{
//当传入dwThreadId为0时,表示要卸载钩子
chASSERT(g_hHook != NULL);//断言钩子己被安装,
bOk = UnhookWindowsHookEx(g_hHook);
g_hHook = NULL;
} return (bOk);
} //////////////////////////////////////////////////////////////////////////
LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam){
static BOOL bFirstTime = TRUE; if (bFirstTime){
//Dll刚被注入
bFirstTime = FALSE; //当调试被注入DLL的进程时,要取消注释
//ForceDebugBreak(); //创建DIPS服务窗口,以处理客户请求
CreateDialog(g_hInstDll, MAKEINTRESOURCE(IDD_DIPS), NULL, Dlg_Proc); //通知DIPS应用程序服务窗口己创建完毕,可以接收请求了
PostThreadMessage(g_dwThreadIdDIPS, WM_NULL, , );
}
return (CallNextHookEx(g_hHook, nCode, wParam, lParam));
} //////////////////////////////////////////////////////////////////////////
void Dlg_OnClose(HWND hWnd){
DestroyWindow(hWnd);
} //////////////////////////////////////////////////////////////////////////
static const TCHAR g_szRegSubKey[] =
TEXT("Software\\Wintellect\\Desktop Item Position Saver"); //////////////////////////////////////////////////////////////////////////
void SaveListViewItemPositions(HWND hWndLV){
int nMaxItems = ListView_GetItemCount(hWndLV); //删除先前的旧信息
LONG lRet = RegDeleteKey(HKEY_CURRENT_USER, g_szRegSubKey); //创建新的注册表项
HKEY hKey;
lRet = RegCreateKeyEx(HKEY_CURRENT_USER, g_szRegSubKey, , NULL, REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE, NULL, &hKey, NULL); chASSERT(lRet == ERROR_SUCCESS); for (int nItem = ; nItem < nMaxItems;nItem++){ //获取ListItem项的名称及位置
TCHAR szName[MAX_PATH];
ListView_GetItemText(hWndLV, nItem, , szName, _countof(szName)); POINT pt;
ListView_GetItemPosition(hWndLV, nItem, &pt); //保存名称及位置
lRet = RegSetValueEx(hKey, szName, , REG_BINARY, (PBYTE)&pt, sizeof(pt)); chASSERT(lRet == ERROR_SUCCESS);
} RegCloseKey(hKey);
} //////////////////////////////////////////////////////////////////////////
void RestoreListViewItemPosition(HWND hWndLV){
HKEY hKey;
LONG lRet = RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegSubKey, , KEY_QUERY_VALUE, &hKey); if (lRet != ERROR_SUCCESS)
return; //如果ListView打开了自动排列属性,则暂时关闭
DWORD dwStyle = GetWindowStyle(hWndLV);
if (dwStyle & LVS_AUTOARRANGE)
SetWindowLong(hWndLV, GWL_STYLE, dwStyle & ~LVS_AUTOARRANGE); lRet = NO_ERROR;
for (int nIndex = ; lRet != ERROR_NO_MORE_ITEMS; nIndex++){
TCHAR szName[MAX_PATH];
DWORD cbValueName = _countof(szName);//必须要在循环体内重新设置该值,因为每次会被RegEnumValue改变,用来接受下一个szName POINT pt;
DWORD cbData = sizeof(pt), nItem;//必须要在循环体内重新设置cbData,因为每次会被RegEnumValue改变 //从注册表中读取名称及位置信息
DWORD dwType; lRet = RegEnumValue(hKey, nIndex, szName, &cbValueName, NULL, &dwType, (PBYTE)&pt, &cbData); if (lRet == ERROR_NO_MORE_ITEMS)
continue; if ((dwType == REG_BINARY) && (cbData = sizeof(pt))){
//查找ListView控件相应的项目
LV_FINDINFO lvfi;
lvfi.flags = LVFI_STRING;
lvfi.psz = szName;
nItem = ListView_FindItem(hWndLV, -, &lvfi);
if (nItem != -){
ListView_SetItemPosition(hWndLV, nItem, pt.x, pt.y);
}
}
}
//将自动排列属性恢复为原来的值
SetWindowLong(hWndLV, GWL_STYLE, dwStyle);
RegCloseKey(hKey);
} //////////////////////////////////////////////////////////////////////////
INT_PTR WINAPI Dlg_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
switch (uMsg)
{
chHANDLE_DLGMSG(hWnd, WM_CLOSE, Dlg_OnClose); //隐藏服务窗口
case WM_APP:
//当调试被注入DLL的进程时,要取消注释
//ForceDebugBreak(); //lParam:表示保存或恢复操作。wParam:桌面ListView的句柄
if (lParam)
SaveListViewItemPositions((HWND)wParam);
else
RestoreListViewItemPosition((HWND)wParam);
break;
}
return (FALSE);
}

//resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 22_DipsLib.rc 使用
//
#define IDD_DIPS 101 // Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

//rc文件

// Microsoft Visual C++ generated resource script.
//
#include "resource.h" #define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h" /////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS /////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED #ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
// TEXTINCLUDE
BEGIN
"resource.h\0"
END TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END #endif // APSTUDIO_INVOKED /////////////////////////////////////////////////////////////////////////////
//
// Dialog
// IDD_DIPS DIALOG DISCARDABLE , , ,
STYLE WS_CAPTION
CAPTION "Wintellect DIPS"
FONT , "MS Shell Dlg"
BEGIN
END /////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
// #ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN,
RIGHTMARGIN,
TOPMARGIN,
BOTTOMMARGIN,
END
END
#endif // APSTUDIO_INVOKED #endif // 中文(简体,中国) resources
///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
// /////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

【DIPS工具源码】

/************************************************************************
Module: DIPS.cpp
Notices: Copyright(c) 2008 Jeffrey Richter & Christophe Nasarre
************************************************************************/ #include "../../CommonFiles/CmnHdr.h"
#include <tchar.h>
#include "resource.h"
#include "../22_DipsLib/DIPSLib.h" #pragma comment(lib,"../../Debug/22_DIPSLib.lib")
//////////////////////////////////////////////////////////////////////////
BOOL Dlg_OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam){
chSETDLGICONS(hWnd, IDI_DIPS);
return (TRUE);
} //////////////////////////////////////////////////////////////////////////
void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtrl, UINT codeNotity){
switch (id)
{
case IDC_SAVE:
case IDC_RESTORE:
case IDCANCEL:
EndDialog(hwnd, id);
break;
}
} //////////////////////////////////////////////////////////////////////////
INT_PTR WINAPI Dlg_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
switch (uMsg){
chHANDLE_DLGMSG(hWnd, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hWnd, WM_COMMAND, Dlg_OnCommand);
} return (FALSE);
} HWND GetDestopListViewHandle(){
HWND hWnd = NULL,hWndItem;
HWND hWndParent = FindWindowEx(,,TEXT("WorkerW"),NULL);
while (hWndParent && (!hWnd)){ hWndItem = FindWindowEx(hWndParent, , TEXT("SHELLDLL_DefView"), NULL);
if (hWndItem){
hWnd = FindWindowEx(hWndItem, , TEXT("SysListView32"), TEXT("FolderView"));
break;
}
hWndParent = FindWindowEx(, hWndParent, TEXT("WorkerW"), NULL);
}
return hWnd;
} //////////////////////////////////////////////////////////////////////////
int WINAPI _tWinMain(HINSTANCE hInstExe, HINSTANCE, PTSTR pszCmdLine, int){
//将命令行转为大写字符串
CharUpperBuff(pszCmdLine, );
TCHAR cWhatToDo = pszCmdLine[]; if ((cWhatToDo !=TEXT('S')) && (cWhatToDo != TEXT('R'))){
cWhatToDo = ; //无效的命令行参数
} //如果是从GUI界面启动本程序,而不是命令行启动
if (cWhatToDo == ){
//无命令行参数时,显示对话框以让用户相应的选择
switch (DialogBox(hInstExe, MAKEINTRESOURCE(IDD_DIPS), NULL, Dlg_Proc)){
case IDC_SAVE:
cWhatToDo = TEXT('S');
break;
case IDC_RESTORE:
cWhatToDo = TEXT('R');
break;
}
} //表示用户什么也不做
if (cWhatToDo == ){
return ();
} //获取桌面listView的窗口句柄,他是 HWND hWndLV = GetDestopListViewHandle();
chASSERT(IsWindow(hWndLV)); //安装钩子到Explorer进程的地址空间。当安装完成后,Explorer里会创建一个“隐藏”
//的窗口,我们可以向这个窗口发送消息,以便告诉他我们要想做的事情
chASSERT(SetDIPSHook(GetWindowThreadProcessId(hWndLV, NULL))); //阻塞等待DIPS服务器窗口创建完毕,当创建完毕后,这里GetMessage会收到通知,线程被唤醒
MSG msg;
GetMessage(&msg, NULL, , );//阻塞等待 //查找服务端这个被隐藏的窗口
HWND hWndDIPS = FindWindow(NULL, TEXT("Wintellect DIPS")); chASSERT(IsWindow(hWndDIPS)); //断言窗口是存在的 //告诉服务端的窗口进行保存或恢复桌面图标操作
BOOL bSave = (cWhatToDo == TEXT('S'));
SendMessage(hWndDIPS, WM_APP, (WPARAM)hWndLV, bSave); //销毁隐形窗口,使用SendMessage可以保证在函数返回后,窗口己这被销毁
SendMessage(hWndDIPS, WM_CLOSE, , ); chASSERT(!IsWindow(hWndDIPS)); //断言窗口己被销毁 //卸载钩子
SetDIPSHook();
return ();
}

//resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 22_DIPS.rc 使用
//
#define IDC_RESTORE 3
#define IDI_DIPS 101
#define IDD_DIPS 102
#define IDC_SAVE 1000 // Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

//rc文件

// Microsoft Visual C++ generated resource script.
//
#include "resource.h" #define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h" /////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS /////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED /////////////////////////////////////////////////////////////////////////////
//
// Icon
// // Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_DIPS ICON "DIPS.ico" #ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
// TEXTINCLUDE
BEGIN
"resource.h\0"
END TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END #endif // APSTUDIO_INVOKED /////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DIPS DIALOGEX , , ,
STYLE DS_SETFONT | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU
CAPTION "桌面图标位置保存工具"
FONT , "MS Shell Dlg", , , 0x1
BEGIN
CTEXT "DIPS: 桌面图标位置保存工具\n版权所有 (c) 2016 by 浅墨浓香.", IDC_STATIC, , , , , SS_SUNKEN, WS_EX_DLGMODALFRAME | WS_EX_STATICEDGE
LTEXT "这个工具可以保存或恢复桌面图标的位置.\n\n保存位置: DIPS S\n恢复位置: DIPS R", IDC_STATIC, , , ,
DEFPUSHBUTTON "&保存", IDC_SAVE, , , ,
PUSHBUTTON "&恢复", IDC_RESTORE, , , ,
PUSHBUTTON "取消", IDCANCEL, , , ,
END /////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
// #ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN,
RIGHTMARGIN,
TOPMARGIN,
BOTTOMMARGIN,
END
END
#endif // APSTUDIO_INVOKED #endif // 中文(简体,中国) resources
///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
// /////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

第22章 DLL注入和API拦截(1)的更多相关文章

  1. 第22章 DLL注入和API拦截(3)

    22.6 API拦截的一个例子 22.6.1 通过覆盖代码来拦截API (1)实现过程 ①在内存中对要拦截的函数(假设是Kernel32.dll中的ExitProcess)进行定位,从而得到它的内存地 ...

  2. 第22章 DLL注入和API拦截(2)

    22.4 使用远程线程来注入DLL 22.4.1 概述 (1)远程线程注入是指一个进程在另一个进程中创建线程,然后载入我们编写的DLL,并执行该DLL代码的技术.其基本思路是通过CreateRemot ...

  3. DLL注入_拦截技术之Hook方式

    后卫大师教你进程注入 首先提一下,由于文章完全是我手写,所以打不了太多,请包含,由于我已经提供了源代码,所以我在这里详细讲一下理论,至于想看代码的下载代码就可以了.代码中关于注入的部分做了详细的注释. ...

  4. Win32环境下代码注入与API钩子的实现(转)

    本文详细的介绍了在Visual Studio(以下简称VS)下实现API钩子的编程方法,阅读本文需要基础:有操作系统的基本知识(进程管理,内存管理),会在VS下编写和调试Win32应用程序和动态链接库 ...

  5. Win32环境下代码注入与API钩子的实现

    本文详细的介绍了在Visual Studio(以下简称VS)下实现API钩子的编程方法,阅读本文需要基础:有操作系统的基本知识(进程管理,内存管理),会在VS下编写和调试Win32应用程序和动态链接库 ...

  6. 20145319 《网络渗透》免考—API拦截技术

    20145319 <网络渗透>免考-API拦截技术 概述 本次实验在window环境下进行,主要通过编写hook代码和注入程序,将我们的hook代码通过dll文件的形式注入到目标中,拦截其 ...

  7. <ReversingEngineering>关于windows32位系统下的dll注入技术经验汇

    上个学期把自己闷在图书馆一直在看关于逆向工程技术方面的书,从入门到初级,现在也敢说自己一条腿已经迈进了这片知识的大门里,因为该博客刚开通先将一些经验记录下来,也是留给自己一方面做个参照. <逆向 ...

  8. DLL注入新姿势:反射式DLL注入研究

    在分析koadic渗透利器时,发现它有一个注入模块,其DLL注入实现方式和一般的注入方式不一样.搜索了一下发现是由HarmanySecurity的Stephen Fewer提出的ReflectiveD ...

  9. Dll注入技术之消息钩子

    转自:黑客反病毒 DLL注入技术之消息钩子注入 消息钩子注入原理是利用Windows 系统中SetWindowsHookEx()这个API,他可以拦截目标进程的消息到指定的DLL中导出的函数,利用这个 ...

随机推荐

  1. C# WM_NCMOUSELEAVE 消息触发

    public static extern bool TrackMouseEvent([In, Out] TRACKMOUSEEVENT lpEventTrack); [DllImport(" ...

  2. virtualenv and virtualenvwrapper on Ubuntu 14.04

    In this post I’ll go over my attempt to setup virtual environments for Python development. Most Pyth ...

  3. FEE Development Essentials

    FEE Development Essentials JS Basic function call() and apply() func1.bind(thisObj,arg1...argn) Cust ...

  4. ArcObject10.1降级至10.0

    最开始接触ArcGIS版本是9.3,为了需要也安装了9.2进行开发:因为自己的电脑配置较低,所以跑不起10.0中文版:毕业工作后,行业内用10.1居多(虽然10.3已出):现在10.4都要出来了:由于 ...

  5. CRM 2013 系统设置新功能一:界面自动保存 及 SDK 中 Xrm.Page.data.entity.save

    CRM 2013 界面会自动保存了..在系统设置中默认“是”,如果不需要可以调整. CRM实体记录在新建时会有出现“保存”按钮,非新建状态下,没有“保存”按钮只有“新建”按钮,系统将会自动为你保存最后 ...

  6. Oracle计算时间差函数

    两个Date类型字段:START_DATE,END_DATE,计算这两个日期的时间差(分别以天,小时,分钟,秒,毫秒): 天: ROUND(TO_NUMBER(END_DATE - START_DAT ...

  7. Android NDK

    1.Android之NDK开发 http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html

  8. [leetcode] Number of Islands

    Number of Islands Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. ...

  9. Android 6.0权限管理

    Android 6.0权限管理 关于权限管理 Android6.0 发布之后,Android 的权限系统被重新设计.在 23 之前 App 的权限只会在用户安装的时候询问一次,App一旦安装后就可以使 ...

  10. 【读书笔记】iOS-本地文件和数据安全注意事项

    一,程序文件的安全. 可通过将JavaScript源码时行混淆和加密,防止黑客轻易地阅读和篡改相关的逻辑,也可以防止自己的Web端与Native端的通讯协议泄露. 二,本地数据安全. 对于本地的重要数 ...