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

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

四、使用远程线程来插入DLL

插入DLL的第三种方法是使用远程线程。这种方法具有更大的灵活性。

原理

特点

基本操作步骤

执行的操作步骤:

  1. 使用VirtualAllocEx函数,分配远程进程的地址空间中的内存。
  2. 使用WriteProcessMemory函数,将D L L的路径名拷贝到第一个步骤中已经分配的内存中。
  3. 使用GetProcAddress函数,获取 LoadLibraryA或LoadLibraryW函数的实地址(在Kernel32.dll中)。
  4. 使用CreateRemoteThread函数,在远程进程中创建一个线程,它调用正确的 LoadLibrary函数,为它传递第一个步骤中分配的内存的地址。这时, DLL已经被插入远程进程的地址空间中,同时 DLL的DllMain函数接收到一个DLL_PROCESS_ATTACH通知,并且能够执行需要的代码。当 DllMain函数返回时,远程线程从它对LoadLibrary的调用返回到 BaseThreadStart函数(第 6章中已经介绍)。然后BaseThreadStart调用ExitThread,使远程线程终止运行。现在远程进程拥有第一个步骤中分配的内存块,而 DLL则仍然保留在它的地址空间中。若要将它删除,需要在远程线程退出后执行下面的步骤:
  5. 使用VirtualFreeEx函数,释放第一个步骤中分配的内存。
  6. 使用GetProcAddress函数,获得FreeLibrary函数的实地址(在Kernel32.dll中)。
  7. 使用CreateRemoteThread函数,在远程进程中创建一个线程,它调用 FreeLibrary函数,传递远程DLL的HINSTANCE。

OpenProcess函数

OpenProcess 函数用来打开一个已存在的进程对象,并返回进程的句柄。

HANDLE OpenProcess(
  DWORD dwDesiredAccess, //渴望得到的访问权限(标志)
  BOOL bInheritHandle, // 是否继承句柄
  DWORD dwProcessId// 进程标示符
);

dwDesiredAccess:获取的权限,可分为以下几种

PROCESS_ALL_ACCESS:获取所有权限

PROCESS_CREATE_PROCESS:创建进程

PROCESS_CREATE_THREAD:创建线程

PROCESS_DUP_HANDLE:使用DuplicateHandle()函数复制一个新句柄

PROCESS_QUERY_INFORMATION:获取进程的令牌、退出码和优先级等信息

PROCESS_QUERY_LIMITED_INFORMATION:获取进程特定的某个信息

PROCESS_SET_INFORMATION:设置进程的某种信息

PROCESS_SET_QUOTA:使用SetProcessWorkingSetSize函数设置内存限制

PROCESS_SUSPEND_RESUME:暂停或者恢复一个进程

PROCESS_TERMINATE:使用Terminate函数终止进程

PROCESS_VM_OPERATION:在进程的地址空间执行操作

PROCESS_VM_READ:使用ReadProcessMemory函数在进程中读取内存

PROCESS_VM_WRITE:使用WriteProcessMemory函数在进程中写入内存

SYNCHRONIZE:使用wait函数等待进程终止

bInheritHandle:TRUE或者FALSE

dwProcessId:pid

VirtualAllocEx函数

分配远程进程的地址空间中的内存

WriteProcessMemory函数

GetProcAddress函数

获取 LoadLibraryA或LoadLibraryW函数的实地址(在Kernel32.dll中)

CreateRemoteThread函数

能够创建一个在其它进程地址空间中运行的线程(也称为创建远程线程)。

HANDLE CreateRemoteThread(
     HANDLE hProcess,
     LPSECURITY_ATTRIBUTES lpThreadAttributes,
     SIZE_T dwStackSize,
     LPTHREAD_START_ROUTINE lpStartAddress,
     LPVOID lpParameter,
     DWORD dwCreationFlags,
     LPDWORD lpThreadId
);

hProcess:进程句柄

lpThreadAttributes : 线程安全描述字,指向SECURITY_ATTRIBUTES结构的指针

dwStackSize:线程栈大小,以字节表示

lpStartAddress: 一个LPTHREAD_START_ROUTINE类型的指针,指向在远程进程中执行的函数地址

lpParameter: 传入参数

dwCreationFlags:创建线程的其它标志

lpThreadId:[输出] 线程身份标志,如果为NULL,则不返回

返回值:成功返回新线程句柄,失败返回NULL,并且可调用GetLastError获得错误值。

4.1 Inject Library示例应用程序

使用任务管理获取进程的I D。使用这个I D,该程序将设法通过调用 OpenProcess函数来打开正在运行的进程的句柄,申请相应的访问权。

原理

InjLib.exe应用程序使用CreateRemoteThread函数来插入ImgWalk.DLL

过程

  1. 使用界面输入的ProcesssId,然后获取ImgWalk.dll文件位置。
  2. 调用InjectLib:InjectLib内部调用OpenProcess获得ProcessId的句柄hProcess
  3. 通过进程句柄hProcess,
    调用VirtualAllocEx,分配远程进程的地址空间中的内存
  4. 使用WriteProcessMemory函数,将D L L的路径名拷贝到第一个步骤中已经分配的内存中。
  5. 调用GetProcAddress
    获取 LoadLibraryA或LoadLibraryW函数的实地址(在Kernel32.dll中)
  6. CreateRemoteThread,创建远程线程。
  7. 结束InjectLib后释放句柄hProcess,线程hThread,内存。
  8. 注入成功后,调用EjectLib,同InjectLib,只不过获得FreeLibrary地址,然后通过CreateRemoteThread调用FreeLibrary。

4.2 Image Walk DLL

ImgWalk.dll 是个D L L,一旦它被插入进程的地址空间,就能够报告该进程正在使用的所有 DLL。

原理

ImgWalk遍历进程的地址空间,查找已经映射的文件映像,反复调用 Virtual Query函数,填入一个MEMORY_BASIC_ INFORMATION结构中。运用循环的每个重复操作, ImgWalk找出一个文件路径名,并与一个字符串相连接。该字符串显示在消息框中。

五、使用特洛伊DLL来插入DLL

原理

利用自己伪造的同名DLL取代软件内的将要加载的Xyz.DLL。

特点

  • 在你的Xyz.dll中,输出的全部符号必须与原始的Xyz.dll输出的符号相同

实现方法 :

  1. 使用函数转发器

注意:

虽然函数转发器使你能够非常容易地挂接某些函数,你应该避免使用这种方法,因为它不具备版本升级能力。例如,如果你取代了一个系统 D L L, 而M i c r o s o f t在将来增加了一些新函数,那么你的 D L L将不具备它们的函数转发器。引用这些新函数的应用程序将无法加载和执行。

  1. 改变应用程序的.exe模块的输入节

注意:。

输入节只包含模块需要的 D L L的名字。你可以仔细搜索文件中的这个输入节,并且将它改变,使加载程序加载你自己的 D L L。这种方法相当不错,但是必须要非常熟悉. e x e和D L L文件的格式。

六、将DLL作为调试程序来插入

原理

调试程序能够对被调试的进程执行特殊的操作。

当被调试进程加载时,在被调试进程的地址空间已经作好准备,但是被调试进程的主线程尚未执行任何代码之前,系统将自动将这个情况通知调试程序时,调试程序可以强制将某些代码插入被调试进程的地址空间中(比如使用WriteProcessMemory函数来插入),然后使被调试进程的主线程执行该代码。

特点

  • 这种方法要求你对被调试线程的 CONTEXT结构进行操作,意味着必须编写特定 CPU的代码。必须修改你的源代码,使之能够在不同的 C P U平台上正确地运行。另外,必须对你想让被调试进程执行的机器语言指令进行硬编码。而且调试程序与它的被调试程序之间必须存在固定的关系。
  • 如果调试程序终止运行,Windows将自动撤消被调试进程。而你则无法阻止它。

七、用Windows 98上的内存映射文件插入代码

原理

在Windows 98上插入你自己的代码是非常简单的。在 Windows 98上运行的所有 3 2位 Wi n d o w s应用程序均共享同样的最上面的2 GB地址空间。如果你分配这里面的某些存储器,那么该存储器在每个进程的地址空间中均可使用。若要分配 2 GB以上的存储器,只要使用内存映射文件(第 1 7章已经介绍)。可以创建一个内存映射文件,然后调用 MapViewOfFile函数,使它显示出来。然后将数据填入你的地址空间区域(这是所有进程地址空间中的相同区域)。

特点

  • 必须使用硬编码的机器语言来进行填入数据到地址空间区域,很难移植到别的CPU平台。
  • 必须让其他进程中的线程来执行内存映射文件中的代码。要做到这一点,需要某种方法来控制远程进程中的线程。CreateRemoteThread函数能够很好地执行这个任务,可惜Windows 98不支持该函数的运行。

八、用CreateProcess插入代码

原理

通过当前进程来生成目标进程,在目标进程作为子进程启动之前先将其挂起。同时会得到其主线程的句柄。通过这个句柄可以对线程执行的代码进行修改。

方法

参考

让一个进程对其子进程的主线程进行控制的一种方法:

  1. 让进程生成一个被挂起的子进程
  2. 从exe模块的文件头中得到主线程的起始内存地址
  3. 将位于该内存地址处的机器指令保存起来
  4. 强制将一些手动编写的机器指令写入到该内存地址处。这些指令应该调用一个LoadLibrary来载入一个DLL
  5. 让子进程的主线程恢复运行,从而让这些指令得到执行。
  6. 把保存起来的原始指令恢复到起始地址处
  7. 让进程从起始地址继续执行,就好像什么都没发生一样。

特点

优点:

  • 它在应用程序执行之前就能得到地址空间
  • 它既能在Windows 98上使用,也能在Windows 2000上使用
  • 由于你不是调试者,因此能够很容易使用插入的D L L来调试应用程序
  • 这种方法可以同时用于控制台和 G U I应用程序。

缺点:

  • 只有当你的代码在父进程时,才能插入 DLL。
  • 不能跨越不同的C P U来运行,必须对不同的C P U平台进行相应的修改。

九、拦截API的一个示例

9.1 通过改写代码来拦截API

原理

用汇编代码JUMP覆盖需要拦截目标函数。

步骤

拦截ExitProcess的一个方案是用代码覆盖来拦截。

工作方式如下:

  1. 在内存中,对想要拦截的函数(假设是Kernel32.dll中的ExitProcess)进行定位,从而得到它的内存地址。
  2. 把这个函数起始的几个字节保存到自己的内存中
  3. 用CPU的一条JUMP指令来覆盖这个函数的起始几个字节,这条JUMP指令用来跳转到我们替代函数的内存地址。所有替代函数的签名必须要与拦截函数的签名完全相同:所有参数必须相同,返回值必须相同,调用约定也必须相同。
  4. 当线程调用被拦截函数(hooked function)的时候,跳转指令实际上会跳转到我们的替代函数。这是可以执行自己想要执行的代码。
  5. 为了撤销对该函数的拦截,必须把步骤2)中保存下来的直接放回被拦截函数的起始字节。
  6. 我们调用被拦截函数,让该函数正常处理
  7. 当原来的函数返回时,再次执行步骤2和步骤3,这样我们的代替函数将来还好被调用到。

特点

  • 它对cpu有依赖性x86, x64, ia-64其他cpu的JUMP指令各不相同,为了让这种方法工作必须手工编写机器指令。
  • 其次,这种方法在抢占式,多线程环境下根本不能工作。一个线程覆盖一个函数起始位置的代码是需要时间的,这个过程如果另一个线程试图调用同一个函数,结果是灾难性的。(除非保证任何时候只有一个线程会调用该函数)

9.2 通过操作模块的输入节来拦截API

一个模块的导入段包含一组DLL,为了让模块能够运行,这些DLL是必须的。此外导入段还包含一个符号表,列出了该模块从各DLL中导入的符号。当该模块调用一个导入函数的时候,实际上是先从该模块的导入表中得到相应的导入函数的地址,然后再跳转到那个地址。

原理

修改特点函数在模块的输入节(导入段)中的地址。

特点

  • 完全不存在对cpu的依赖性。
  • 而且并不需要修改函数的代码,
  • 也不用担心线程同步问题。

9.3 LastMsgBoxInfo示例应用程序

该例子拦截了所有对MessageBox(位于User32.dll中)的调用,为了在所有进程中拦截这个函数,应用程序使用了Windows挂钩技术来注入DLL。

总结

1. 第三节 使用Windows挂钩来插入DLL 发现隐藏窗口Wintellect DIPS为NULL

使用64位运行

相关文章
|
2天前
|
数据采集 JSON API
Python 实战:用 API 接口批量抓取小红书笔记评论,解锁数据采集新姿势
小红书作为社交电商的重要平台,其笔记评论蕴含丰富市场洞察与用户反馈。本文介绍的小红书笔记评论API,可获取指定笔记的评论详情(如内容、点赞数等),支持分页与身份认证。开发者可通过HTTP请求提取数据,以JSON格式返回。附Python调用示例代码,帮助快速上手分析用户互动数据,优化品牌策略与用户体验。
|
2月前
|
数据采集 搜索推荐 API
小红书笔记详情 API 接口的开发、应用与收益
小红书(RED)作为国内领先的生活方式分享平台,汇聚了大量用户生成内容(UGC),尤其是“种草”笔记。小红书笔记详情API接口为开发者提供了获取笔记详细信息的强大工具,包括标题、内容、图片、点赞数等。通过注册开放平台账号、申请API权限并调用接口,开发者可以构建内容分析工具、笔记推荐系统、数据爬虫等应用,提升用户体验和运营效率,创造新的商业模式。本文详细介绍API的开发流程、应用场景及潜在收益,并附上Python代码示例。
335 62
|
3天前
|
数据采集 JSON API
Python 实战!利用 API 接口获取小红书笔记详情的完整攻略
小红书笔记详情API接口帮助商家和数据分析人员获取笔记的详细信息,如标题、内容、作者信息、点赞数等,支持市场趋势与用户反馈分析。接口通过HTTP GET/POST方式请求,需提供`note_id`和`access_token`参数,返回JSON格式数据。以下是Python示例代码,展示如何调用该接口获取数据。使用时请遵守平台规范与法律法规。
|
1月前
|
数据采集 API 开发工具
从 0 到 1 掌握鸿蒙 AudioRenderer 音频渲染:我的自学笔记与踩坑实录(API 14)
本文详细介绍了在 HarmonyOS 中使用 AudioRenderer 开发音频播放功能的完整流程。从环境准备(SDK 5.0.3、DevEco Studio 5.0.7)到核心概念(状态机模型、异步回调),再到开发步骤(实例创建、数据回调、状态控制),结合代码示例与常见问题解决方法,帮助开发者掌握 AudioRenderer 的底层控制与定制化能力。同时,文章还提供了性能优化建议(多线程处理、缓冲管理)及学习路径,附带官方文档和示例代码资源,助你快速上手并避开常见坑点。
167 7
|
1月前
|
机器学习/深度学习 设计模式 API
Python 高级编程与实战:构建 RESTful API
本文深入探讨了使用 Python 构建 RESTful API 的方法,涵盖 Flask、Django REST Framework 和 FastAPI 三个主流框架。通过实战项目示例,详细讲解了如何处理 GET、POST 请求,并返回相应数据。学习这些技术将帮助你掌握构建高效、可靠的 Web API。
|
1月前
|
机器学习/深度学习 开发框架 API
Python 高级编程与实战:深入理解 Web 开发与 API 设计
在前几篇文章中,我们探讨了 Python 的基础语法、面向对象编程、函数式编程、元编程、性能优化、调试技巧以及数据科学和机器学习。本文将深入探讨 Python 在 Web 开发和 API 设计中的应用,并通过实战项目帮助你掌握这些技术。
|
2月前
|
存储 JSON API
小红书笔记评论数据接口(小红书 API 系列)
小红书凭借庞大的用户群体和丰富的内容生态,成为重要的数据来源。其笔记评论数据对企业了解市场需求、优化产品策略等具有极高价值。为高效、合法获取数据,可使用小红书笔记评论数据接口。该接口通过HTTP请求获取指定笔记的评论内容、时间、昵称等信息,返回JSON格式数据。开发者可利用Python的requests库发送GET请求并处理响应,实现批量收集评论数据,支持舆情监测、竞品分析等业务场景。
|
2月前
|
数据采集 JSON API
小红书笔记详情 API 接口(小红书 API 系列)
小红书作为热门生活方式平台,拥有海量用户生成内容。通过其笔记详情接口,开发者可获取指定笔记的完整内容、作者信息及互动数据(点赞、评论、收藏数等),助力内容分析与市场调研。接口采用HTTP GET请求,需提供笔记ID,响应数据为JSON格式。注意小红书有严格反爬虫机制,建议使用代理IP并控制请求频率。
|
2月前
|
数据采集 搜索推荐 API
小红书笔记详情 API 接口:获取、应用与收益全解析
小红书(RED)是国内领先的生活方式分享平台,汇聚大量用户生成内容(UGC),尤以“种草”笔记闻名。小红书笔记详情API接口为开发者提供了获取笔记详细信息的强大工具,包括标题、内容、图片、点赞数等。通过注册开放平台账号、申请API权限并调用接口,开发者可构建内容分析工具、笔记推荐系统、数据爬虫等应用,提升用户体验和运营效率,创造新的商业模式。本文将详细介绍该API的获取、应用及潜在收益,并附上代码示例。
468 13
|
3月前
|
存储 JSON API
小红书获取笔记详情API接口的开发、应用与收益。
小红书笔记详情API采用Python与Django框架开发,使用MySQL数据库存储数据。接口通过HTTP GET请求获取笔记详情,返回JSON格式数据,包含笔记内容、作者信息、图片链接等。该API应用于小红书APP内笔记展示和互动功能,并支持第三方平台的内容整合与数据分析,提升用户体验与活跃度,促进品牌合作推广,优化平台运营效率,为平台带来显著收益。
287 1
下一篇
oss创建bucket