DLL注入简介

DLL注入简介

DLL是Windows平台提供的一种模块共享和重用机制,本身不能执行,但可以被加载到其他进程进行执行。DLL注入技术利用了这种共享机制。它允许向正在运行的进程中注入一个动态链接库(DLL),被注入的DLL可以利用它所在的进程的权限执行一些特殊的任务,比如修改进程内存中的数据、劫持进程的执行流程、监控进程的行为等等。

应用

  • 软件调试:开发人员可以使用DLL注入技术来调试应用程序。它可以在目标进程中注入一个调试DLL,用于监视和分析应用程序的行为,以帮助发现和修复错误。
  • 病毒编写:恶意软件开发者可以利用DLL注入来实现恶意功能,如窃取用户信息、远程控制目标计算机等。这是一种常见的攻击技术,因此安全软件通常会检测和阻止恶意DLL注入。
  • 反病毒软件:一些反病毒软件利用DLL注入技术来监视和防止恶意软件的运行。它们在目标进程中注入一个监控DLL,以便检测和拦截恶意行为。
  • 游戏修改:一些玩家可能使用DLL注入技术来修改游戏的行为或增加额外的功能。这可能包括修改游戏内存中的数值、实现外挂功能等

相关API

注入方法

通常情况下,程序加载DLL的时机有以下三种情况:一是进程创建阶段加载输入表中的DLL,“静态输入”;二是通过调用LoadLibrary进行主动加载,”动态加载”;三是加载系统预设的一些基础服务模块,例如Shell扩展模块、网络服务接口模块等。

通过干预输入表处理过程加载目标DLL

当一个进程被创建后,不会直接到EXE本身的入口处执行,首先被执行的是ntdll.dll中的LdrInitializeTghunk(),该函数会调用LdrpInitializeProcess对进程的一些必要内容进行初始化,LdrpInitializeProcess会调用LdrpWalkImportDescriptor对输入表进行处理,即加载输入表中的模块,填充应用程序的IAT。所以,只要再输入表被处理之前进行干预,为输入表增加一个项目使其指向要加载的目标DLL,或者替换原有输入表中的DLL并对其进行调用进行转发,南无新进程的主线程再输入表初始化阶段就会主动加载目标DLL

静态修改PE输入法

这里编写个DLL注入到记事本程序中,使其启动时加载DLL。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
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <stdio.h>




DWORD WINAPI ThreadShow(LPVOID IpParameter)
{
char szPath[MAX_PATH] = { 0 };
char szBuf[1024] = { 0 };

//获取宿主进程的全部路径
GetModuleFileName(NULL, szPath, MAX_PATH);
sprintf(szBuf,"DLL已注入到进程%s[pid=%d]\n",szPath,GetCurrentProcessId());

//以Msgbox、控制台和调试器输出
MessageBox(NULL, szBuf, "DLL InJect", MB_OK);

printf("%s", szBuf);

OutputDebugString(szBuf);
return 0;

}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
CreateThread(NULL, 0, ThreadShow, NULL, 0, NULL);
}
return TRUE;
}

由于需要添加新的输入表,输入表是一个IID数组,那么将dll导入到程序中就需要考虑新写入的IID结构大小。假设原IID大小为old,那么只导入了一个函数,我们新的IID结构大小newIIDSize = Old+ sizeof(IMAGE_IMPORT_DESCRIPTOR)。

得到记事本的基本信息如下

当没有合适的节用来存放输入表数据时,有两种解决方法,一是扩展一个节,二是增加一个节。这里选用直接扩充最后一个节,为.rsrc节增加0x200字节。

文件偏移:0x8400+0x8000=0x10400

内存偏移:0xB000+0x8000=0x13000

原IID数组的文件偏移是0x7604-0x1000+0x400=0x6A04,到0x6AB4处

备份原IID结构

找到原始的输入表IID数组

将IID数组复制到增加的空白区域,偏移量为0x10400

在原IID区域构造新IID的OriginalFirstThunk、FirstThunk结构

由于前两个大小固定,比较容易对齐,所以我们可以先构造这两个Thunk,为了节省空间,我们将这些数据放在原IID的位置,当然放在新构造的200个字节里也是可以的。两个Thunk结构大小都是4字节+4字节全0结束标记,所以新填入的数据空间安排如下

1
2
3
4
5
6
7
8
+00h    OriginalFirstThunk
+04h 全0结束标记
+08h FirstThunk
+0ch 全0结束标记
+10h Name --"MsgDll.dll"
+1ah 全0字符串结束标记
+1ch IMPORT_BY_NAME-> hint
+1eh IMPORT_BY_NAME-> Name

在PE文件被加载前指向的都是IMPORT_BY_NAME数组,该结构

的RawOffset = 0x6a04 + 0x1c = 0x6a20

RVA = 0x6a20 - 0x400 + 0x1000 = 0x7614

所以我们填入的各个数据如下:

将其填充

接下来填充新输入表项的IID结构

OriginalFirstThunk RVA = RawOffset(0x6a04) - 0x400 + 0x1000 = 0x7604
Name RVA = RawOffset(0x6a14) - 0x400 + 0x1000 = 0x7614
FirstThunk RVA = RawOffset(0x6a0c) - 0x400 + 0x1000 = 0x760c
其余TimeDateStamp和FOrwarderChain字段填0即可,将以上数据填入得到:

修改PE文件头信息

修改PE文件头中指向输入表的位置为我们新构造的表的位置,另外因为PE在加载过程中FIrstThunk会被填充为真正的输入函数地址,所以该区段需要是可写的,原节属性为0x60000020,将其加上可写属性的0x80000000得到0xE0000020 。
修改PE头指向输入表的位置可以通过PE工具快速修改,值应改为我们新添加的节的RVA,该值等于0x10400 - 0x400 + 0x1000 * 3 =0x13000。

导入表如下

dll成功注入

  1. 备份原IID结构
  2. 在原IID区域构造新IID的OriginalFirstThunk、Name、FirstThunk结构
  3. 填充新输入表项的IID结构
  4. 修正PE文件头的信息

进程创建期修改PE输入表法

进程创建期修改PE输入表法修改映射后的PE内存,所需空隙大小不变,但可利用的节空隙由文件空隙变成了内存空隙。

  1. 以挂起方式创建目标进程
  2. 获取目标进程中的PE结构信息。
  3. 获取原IID大小,增加一项,搜索可用的节空隙
  4. 构造新的IID及与其相关的OriginalFirstThunk、Name、FirstThunk结构
  5. 修正PE映像头
  6. 更新目标进程的内存
  7. 继续运行主线程

输入表项DLL替换法(DLL劫持)

当输入表初始化时,会以递归的方式加载各个输入表项中Name所指定的DLL。当加载DLL时,系统优先从\KnownDLLs中查看,若找不到,则查找DLL的顺序:

  1. 加载DLL的进程的可执行目录
  2. 系统目录
  3. 加载DLL的进程的当前目录
  4. PATH环境变量中列出的目录

替换的DLL要有被替换的DLL的所有函数

改变程序运行流程使其主动加载目标DLL

改变程序流程是改变线程EIP、创建新线程或修改目标进程内的某些代码,使其指向LoadLibrary来加载目标DLL。

CreateRemoteThread法

在目标进程中申请一块内存并向其中写入DLL路径,调用CreateRemoteThread在目标进程中创建一个LoadLibraryA线程去调用DLL

RtlCreateUserThread法

QueueUserApc/NtQueueAPCThread APC注入法

SetThreadContext法

内核中通过Hook/Notify干预执行流程法

内核KeUserModeCallback法

纯WriteProcessMemory法

利用系统机制加载DLL

系统机制依赖一些基础服务模块实现,当进程主动或被动出发这些系统机制时,就会在适当的时间主动加载这些模块。因此,可以定制一个符合该规范的DLL,将其注册为系统服务模块,这样就可以“合法”地进入目标进程了。

SetwindowHookEx 消息钩子注入

AppInit_DLLs 注册表项注入

输入法注入

SPI网络过滤器注入

ShimEngine注入

Explorer Shell扩展注入

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2024 John Doe
  • 访问人数: | 浏览次数:

让我给大家分享喜悦吧!

微信