[笔记]Windows核心编程《二十二》注入DLL和拦截API(二)

简介: [笔记]Windows核心编程《二十二》注入DLL和拦截API(二)

PostThreadMessage函数

将一个队列消息放入(寄送)到指定线程的消息队列里,不等待线程处理消息就返回。

BOOLPostThreadMessage(
  DWORDidThread,
  UINTMsg,
  WPARAMwParam,
  LPARAMIParam
);

idThread:其消息将被寄送的线程的线程标识符。如果线程没有消息队列,此函数将失败。当线程第一次调用一个Win 32 USER或GDI函数时,系统创建线程的消息队列。要得到更多的信息,参见备注。

Msg:指定将被寄送的消息的类型。

wParam:指定附加的消息特定信息。

IParam:指定附加的消息特定信息。

返回值:返回线程号。

GetMessage函数

从调用线程的消息队列里取得一个消息并将其放于指定的结构。此函数可取得与指定窗口联系的消息和由PostThreadMessage寄送的线程消息。此函数接收一定范围的消息值。GetMessage不接收属于其他线程或应用程序的消息。获取消息成功后,线程将从消息队列中删除该消息。函数会一直等待直到有消息到来才有返回值。

GetMessage(
  LPMSG lpMsg,
  HWND hWnd,
  UINT wMsgFilterMin,
  UINT wMsgFilterMax
)

lpMsg:指向MSG结构的指针,该结构从线程的消息队列里接收消息信息。

hWnd:取得其消息的窗口的句柄。当其值取NULL时,GetMessage为任何属于调用线程的窗口检索消息,线程消息通过PostThreadMessage寄送给调用线程。

wMsgFilterMin:指定被检索的最小消息值的整数。

wMsgFilterMax:指定被检索的最大消息值的整数。

返回值:如果函数取得WM_QUIT之外的其他消息,返回非零值。如果函数取得WM_QUIT消息,返回值是零。如果出现了错误,返回值是-1。例如,当hWnd是无效的窗口句柄或lpMsg是无效的指针时。若想获得更多的错误信息,请调用GetLastError函数。

SendMessage函数

将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。

LRESULT SendMessage(
    HWND hWnd,
    UINT Msg,
    WPARAM wParam,
    LPARAM IParam
)

hWnd:指定要接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。

Msg:指定被发送的消息。

wParam:指定附加的消息特定信息。

IParam:指定附加的消息特定信息。

返回值:返回值指定消息处理的结果,依赖于所发送的消息。

GetFirstChild宏

GetFirstChild()函数其实是一个宏定义:

#define GetFirstChild(hwnd) GetTopWindow(hwnd)\

GetTopWindow函数

GetTopWindow函数检查与特定父窗口相联的子窗口z序,并返回在z序顶部的子窗口的句柄。

HWND GetTopWindow(HWND hWnd);

hWnd:被查序的父窗口的句柄。如果该参数为NULL,函数返回Z序顶部的窗口句柄。

返回值;如果函数成功,返回值为在Z序顶部的子窗口句柄。如果指定的窗口无子窗口,返回值为NULL。

FindWindow函数

FindWindow这个函数检索处理顶级窗口的类名和窗口名称匹配指定的字符串。这个函数不搜索子窗口。

HWND FindWindow(LPCSTR lpClassName,LPCSTR lpWindowName);

lpClassName:指向一个以NULL字符结尾的、用来指定类名的字符串或一个可以确定类名字符串的原子。如果这个参数是一个原子,那么它必须是一个在调用此函数前已经通过GlobalAddAtom函数创建好的全局原子。这个原子(一个16bit的值),必须被放置在lpClassName的低位字节中,lpClassName的高位字节置零。如果该参数为null时,将会寻找任何与lpWindowName参数匹配的窗口。

lpWindowName:指向一个以NULL字符结尾的、用来指定窗口名(即窗口标题)的字符串。如果此参数为NULL,则匹配所有窗口名。

返回值

如果函数执行成功,则返回值是拥有指定窗口类名或窗口名的窗口的句柄。

如果函数执行失败,则返回值为 NULL 。

挂载调用

HHO0K hHook = SetWindowsHookEx(
        WH_GETMESSAGE,
        GetMsgProc,
        hinstDll,
        0
       );
  1. 进程B中的一个线程准备将一条消息发送到一个窗口。
  2. 系统查看该线程上是否已经安装了WH_GETMESSAGE挂钩。
  3. 系统查看包含GetMsgProc函数的DLL是否被映射到进程B的地址空间中。
  4. 如果该DLL尚未被映射,系统将强制该 DLL映射到进程B的地址空间,并且将进程 B中 的DLL映像的自动跟踪计数递增1。
  5. 当D L L的hinstDll用于进程B时,系统查看该函数,并检查该 D L L的hinstDll是否与它用于进程A时所处的位置相同。
  6. 系统将进程B中的D L L映像的自动跟踪计数递增1。
  7. 系统调用进程B的地址空间中的GetMsgProc函数。
  8. 当GetMsgProc函数返回时,系统将进程B中的D L L映像的自动跟踪计数递减1。

3.1 桌面项目位置保存器实用程序 DIPS

桌面项目位置保存器实用程序 DIPS。

当你将 S 作为命令行参数传递给 DIPS时,它就创建下面这个注册表子

关键字,并且给桌面窗口上的每个项目添加一个值:

HKEY_CURRENT_USER\Software\Richter\Desktop Item Position Saver

每个项目都有一个与它一起保存的位置值。当改变屏幕分辨率以便玩游戏之前,运行 DIPS的S。当玩完游戏后,将屏幕的分辨率改为原来的状态,并且运行 DIPS R。这使得DIPS打开注册表子关键字,对于桌面上与注册表中保存的项目相匹配的每个项目来说,当运行 DIPS S时,项目的位置将被重新设置为原来的值。

原理

DIPS应用程序使用窗口挂钩将一个DIPSLib.dll插入Explorer.exe的地址空间。

Explorer.exe进程用于管理Windows的图形界面,包括开始菜单、任务栏、桌面和文件管理,如果结束这个该程序会导致Windows图形界面无法使用,就是电脑只会剩下一张壁纸,其他的东西统统消失。所以这个Explorer.exe进程的正常运行对系统的稳定性有很大的帮助。如果用户发现任务管理器中有两个或多个Explorer.exe进程,那么就要检查是否中了远控了,最好用木马专杀工具扫扫。

windows下使用Hook实现对远程进程注入DLL技术,通过共用操作系统下同一份DLL,实现对目标进程的特定消息传输,甚至达到控制的技术。

DIPS功能

DIPS主要调用DIPSLib,DIPSLib主要实现Hook以及保存屏幕信息至注册表。

DIPS主要功能:

  • 界面显示 save、resave等
  • 获取ProgMan的线程ID
  • 调用SetDPISHook和UnHook
  • 作为客户端像DIPSLib发送WM_APP消息

ProgMan是显示出来的总桌面,也是总程序,如果你向Progman窗口发送一个WM_CLOSE消息,Windows就会提醒你是否要关机。

参考 编写Windows动态壁纸(关于Windows10桌面的了解)(一)

参考 Windows动态桌面原理

可以通过spy++ 查看

DIPSLib功能

DIPSLib主要功能:

  • 导出SetDIPSHook接口用来Hook线程
  • 保存DIPS信息到注册表。(SaveListViewItemPositions/RestoreListViewItemPositions)
  • 共享数据段g_hHook、g_dwThreadIdDIPS
#pragma data_seg("Shared")
HHOOK g_hHook = NULL;
DWORD g_dwThreadIdDIPS = 0;
#pragma data_seg()
  • 作为服务端 接受处理WM_APP消息

过程

  1. 首先通过ProgMan进程,得到桌面的ListView控件的窗口句柄
HWND hWndLV = GetFirstChild(GetFirstChild(
      FindWindow(TEXT("ProgMan"), NULL)));
  1. 通过调用GetWindowThreadProcessId函数,就能够确定创建窗口的线程的ID。将这个ID传递给 SetDIPSHook函数(在DIPSLib.cpp中实现)。SetDIPSHook负责在该线程上安装一个WH_GETMESSAGE挂钩,然后调用PostThreadMessage函数,以强制Windows Explorer的线程醒来。
// Install the hook on the specified thread
     g_hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInstDll, dwThreadId);
     bOk = (g_hHook != NULL);
     if (bOk) {
        // The hook was installed successfully; force a benign message to 
        // the thread's queue so that the hook function gets called.
        bOk = PostThreadMessage(dwThreadId, WM_NULL, 0, 0);
     }
  1. 由于已经在该线程上安装了一个 WH_GETMESSAGE挂钩,因此操作系统能够自动将DIPSLib. dll 文件插入Explorer.exe的地址空间,并且调用GetMsgProc函数。该函数首先查看它是否是初次被调用,如果是,那么它就创建一个隐藏的窗口,其标题是Wintellect DIPS,请记住,Explorer的线程正在创建这个隐藏窗口。
// The DLL just got injected.
 bFirstTime = FALSE;
 // Uncomment the line below to invoke the debugger 
 // on the process that just got the injected DLL.
 // ForceDebugBreak();
 // Create the DIPS Server window to handle the client request.
 CreateDialog(g_hInstDll, MAKEINTRESOURCE(IDD_DIPS), NULL, Dlg_Proc);
 // Tell the DIPS application that the server is up 
 // and ready to handle requests.
 PostThreadMessage(g_dwThreadIdDIPS, WM_NULL, 0, 0);
  1. 调用GetMessage函数,这次函数调用将使线程进入睡眠状态,直到队列中显示一条消息为止。
  2. 服务端DIPS.dll隐藏窗口Wintellect DIPS创建完成后,客户端DIPS.exe 通过FindWindow其标题Wintellect DIPS获得其句柄,向其发送消息WM_APP,让服务端 DIPS.dll 此时处理S、R操作。
  3. 客户端DIPS.exe 发送消息WM_CLOSE
  4. SetDIPSHook(0),卸载挂钩,Explorer的地址空间中卸载DIPSLib.dll。
相关文章
|
5月前
|
XML C# 数据格式
掌握了在Windows平台上查看DLL依赖的方法
掌握了在Windows平台上查看DLL依赖的方法
647 4
|
6月前
|
网络协议 API Windows
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
|
6月前
|
Windows
[原创]用MASM32编程获取windows类型
[原创]用MASM32编程获取windows类型
|
6月前
|
JavaScript 前端开发 API
MASM32编程通过WMI获取Windows计划任务
MASM32编程通过WMI获取Windows计划任务
|
6月前
|
API Windows
MASM32编程获取Windows当前桌面主题名
MASM32编程获取Windows当前桌面主题名
|
7月前
|
数据库 Windows
超详细步骤解析:从零开始,手把手教你使用 Visual Studio 打造你的第一个 Windows Forms 应用程序,菜鸟也能轻松上手的编程入门指南来了!
【8月更文挑战第31天】创建你的第一个Windows Forms (WinForms) 应用程序是一个激动人心的过程,尤其适合编程新手。本指南将带你逐步完成一个简单WinForms 应用的开发。首先,在Visual Studio 中创建一个“Windows Forms App (.NET)”项目,命名为“我的第一个WinForms 应用”。接着,在空白窗体中添加一个按钮和一个标签控件,并设置按钮文本为“点击我”。然后,为按钮添加点击事件处理程序`button1_Click`,实现点击按钮后更新标签文本为“你好,你刚刚点击了按钮!”。
632 0
|
API Windows 编解码
29、Windows API GDI(1)
GDI是Graphics Device Interface(图形设备接口)的简称,当Windows应用程序需要显示点、线、图像、文字等内容,在显示器或打印输入这些内容时,就需要使用到GDI。图形设备接口是Windows图形界面的基础。
1238 0
|
API Windows
30、Windows API GDI(2)
一、GDI的几个示例与概念 1、笔和话刷的基本操作 示例 画笔示例 **************************************//* 头文件 */#include /* 函数声明 */void GdiOut(HDC hdc);// WinMainint WI...
935 0
|
API Windows
31、Windows API GDI(3)
一、绘制图形     GDI所能绘制形状有很多种,可区分为标准形状和非标准形状。标准形状使用几个简单、确定的属性就可以确定的形状,比如矩形(左上角点位置和长度)、椭圆(使用外切矩形)、圆角矩形(一个矩形加圆角半径)、弓形、扇形。
818 0
|
API Windows
32、Windows API GDI(4)
区域(Regions)、路径(Paths)与修剪(Clip)操作 一、区域[2]     区域是一种对象,具有形状、位置、大小,用于进行填充、绘制、反转、边沿勾勒等操作,或用于限制DC的输出范围(修剪)。
761 0