[笔记]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月前
|
Web App开发 人工智能 JSON
Windows版来啦!Qwen3+MCPs,用AI自动发布小红书图文/视频笔记!
上一篇用 Qwen3+MCPs实现AI自动发小红书的最佳实践 有超多小伙伴关注,同时也排队在蹲Windows版本的教程。
721 1
|
7月前
|
机器学习/深度学习 设计模式 API
Python 高级编程与实战:构建 RESTful API
本文深入探讨了使用 Python 构建 RESTful API 的方法,涵盖 Flask、Django REST Framework 和 FastAPI 三个主流框架。通过实战项目示例,详细讲解了如何处理 GET、POST 请求,并返回相应数据。学习这些技术将帮助你掌握构建高效、可靠的 Web API。
|
7月前
|
机器学习/深度学习 开发框架 API
Python 高级编程与实战:深入理解 Web 开发与 API 设计
在前几篇文章中,我们探讨了 Python 的基础语法、面向对象编程、函数式编程、元编程、性能优化、调试技巧以及数据科学和机器学习。本文将深入探讨 Python 在 Web 开发和 API 设计中的应用,并通过实战项目帮助你掌握这些技术。
|
安全 Java API
告别繁琐编码,拥抱Java 8新特性:Stream API与Optional类助你高效编程,成就卓越开发者!
【8月更文挑战第29天】Java 8为开发者引入了多项新特性,其中Stream API和Optional类尤其值得关注。Stream API对集合操作进行了高级抽象,支持声明式的数据处理,避免了显式循环代码的编写;而Optional类则作为非空值的容器,有效减少了空指针异常的风险。通过几个实战示例,我们展示了如何利用Stream API进行过滤与转换操作,以及如何借助Optional类安全地处理可能为null的数据,从而使代码更加简洁和健壮。
371 0
|
12月前
|
监控 Ubuntu Linux
视频监控笔记(五):Ubuntu和windows时区同步问题-your clock is behind
这篇文章介绍了如何在Ubuntu和Windows系统中通过设置相同的时区并使用ntp服务来解决时间同步问题。
246 4
视频监控笔记(五):Ubuntu和windows时区同步问题-your clock is behind
|
网络协议 API Windows
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
|
12月前
|
IDE API 定位技术
Python--API编程:IP地址翻译成实际的物理地址
Python--API编程:IP地址翻译成实际的物理地址
192 0
|
Linux Apache C++
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
该文介绍了如何在Windows环境下为FFmpeg集成SRT协议支持库libsrt。首先,需要安装Perl和Nasm,然后编译OpenSSL。接着,下载libsrt源码并使用CMake配置,生成VS工程并编译生成srt.dll和srt.lib。最后,将编译出的库文件和头文件按照特定目录结构放置,并更新环境变量,重新配置启用libsrt的FFmpeg并进行编译安装。该过程有助于优化直播推流的性能,减少卡顿问题。
345 2
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
|
JavaScript API 开发者
RESTful API 设计的传奇征程:突破常规,拥抱最佳实践,铸就编程巅峰!
【8月更文挑战第7天】希望通过以上的探讨,能让您对 RESTful API 设计有更深入的理解和认识。
105 5
|
存储 安全 数据安全/隐私保护
Windows 32 汇编笔记(一):基础知识
Windows 32 汇编笔记(一):基础知识