首页
社区
课程
招聘
[原创]一篇文章带你了解Dll注入
发表于: 2019-8-18 00:34 29685

[原创]一篇文章带你了解Dll注入

2019-8-18 00:34
29685

         这是<一篇文章带你...>系列的第四篇,主要会阐明DLL注入的基本原理和几种主流方式,虽然这些方法已经有点滞后了。但是DLL注入的基本原理是不会改变的。自己做的笔记帮助自己理解。准备匆忙。大佬们轻拍。

         DLL注入的主要原理就是强制进程自己将需要注入的dll文件注入到自身进程空间内,最好配合Hook技术。

         Dll注入可以从三个方向入手:第一:在进程创建初期按照导入表加载dll的时候。第二:进程运行时期利用LoadLibrary函数加载,第三:利用某些系统机制:例如windows消息机制等。

         此方法是最常见的dll注入的方法,原理是由于CreateRemoteThread的函数原型和CreateThread是一致的。所以模仿CreateThread创建线程的方式实现注入。

         由于创建的是远程线程,是需要将注入的参数(也就是Dll文件的路径)写入目标进程空间。所以基本步骤如下:

         打开目标进程句柄

         向目标进程中开辟空间并写入Dll文件路径

         获取LoadLibrary的地址

         利用CreateRemoteThread函数调用LoadLibrary加载dll

         RtlCreateUserThread是CreateRemoteThread的底层实现,所以使用RtlCreateUserThread的原理是和使用CreateRemoteThread的原理是一样的。唯一的区别是使用CreateRemoteThread写入目标进程的是Dll的路径,而RtlCreateUserThread写入的是一段shellcode。

         和CreateRemoteThread一样都是需要获取目标进程句柄,获取LoadLibrary地址,dll路径。

         接着我们需要获取RtlCreateUserThread地址,RtlCreateUserThread函数原型如下:

         如何构造shellcode?

         将shellcode写入进程内存中,然后调用RtlCreateUserThread执行shellcode。

         APC中文名称为异步过程调用, APC是一个链状的数据结构,可以让一个线程在其本应该的执行步骤前执行其他代码,每个线程都维护这一个APC链。当线程从等待状态苏醒后,会自动检测自己得APC队列中是否存在APC过程。

         所以只需要将目标进程的线程的APC队列里面添加APC过程,当然为了提高命中率可以向进程的所有线程中添加APC过程。然后促使线程从休眠中恢复就可以实现APC注入。

         首先依旧是将DLL文件路径写入进程。

         然后使用QueueUserAPC将APC例程添加到APC队列中,QueueUserAPC三个参数分别是APC例程,线程句柄,例程参数。所以还需要获取线程句柄

         当然,为了提高命中率,可以使用遍历所有线程,然后利用te32.th32OwnerProcessID是否等于目标进程PID的策略进行进程全局注入。

         使用傀儡进程:以挂起方式创建进程,然后向其中写入shellcode,利用shellcode执行LoadLibrary

         首先以挂起方式创建进程,CreateProcess的第6个参数可以设定进程创建的方式

         然后需要保存进程的上下文信息,主要是EIP的值。以便于Load完成后返回。

         接着需要构建我们替换执行的代码。这段代码的目的是Load我们的恶意的dll文件,所以至少需要做两个方面的准备,第一:需要知道LoadLibrary的地址。第二需要知道Dll的路径。为了让程序更好的运行还需要保存现场。最后利用ret方式返回。

         构造完这些之后将shellcode写入,由于内存本身就有执行属性,所以不需要修改内存属性。

         最后利用SetThreadContext将我们的EIP设置为shellcode起始地址。并调用ResumeThread重启线程

         为了提高命中率可以向目标进程的所有线程进行注入.利用CreateToolhelp32Snapshot等三个函数遍历线程。

         反射式dll注入不需要dll文件落地,减少被查杀的风险。首先将需要注入的dll写入进程内存,然后为该dll添加一个导出函数,利用这个导出函数让其自动的装载dll。注射器是将DLL文件写入目标进程内存。反射装载器实现的就是模拟dll装载器装载dll文件的操作。

         首先说一下注射器,注射器的目的是将Dll文件写入到目标进程空间,然后获取里面导出函数ReflectiveLoader。

         首先需要打开目标进程句柄

         向目标进程写入DLL数据

         利用导出表获取导出函数地址ReflectiveLoader。

         然后利用CreateRemoteThread跨线程调用ReflectiveLoader。

         接下来就是ReflectiveLoader的编程,ReflectiveLoader其实就是一个dll加载器。

         首先需要知道当前dll的基地址,而ReflectiveLoader肯定位于这个DLL中所以在此函数地址出逐次递减,然后判断是否存在MZ标志,MZ的地址就是DLL的基地址

         接着获取注射器所需要的API函数LoadLibrary,GetProcess,VirtualAlloc的地址。

         有了前面这几个API函数做支撑,可以将DLL文件载入到内存,这个是模拟装载器的载入,并不是单纯的读取。

         然后就是修正IAT和重定位表。修正OEP。和加壳很像!

         总结一下

         切换输入法时候,输入法管理器imm32.dll就会加载IME模块,这样就形成了输入法注入的充要条件。而由于这个Ime文件本质上只是个存放在C:\WINDOWS\system32目录下的特殊的DLL文件,因此我们可以利用这个特性,在Ime文件中使用LoadLibrary()函数待注入的DLL文件。

         首先就是编写ime文件,至少需要两个导出函数BOOL ImeClass_Register(HINSTANCE hinstDLL)BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo, LPTSTR lpszUIClass, LPCTSTR lpszOption)这两个是必须要实现的。剩下的导出函数可以选择不去实现。

         接着编写注射器。利用ImmInstallIME安装ime文件,当输入法切换的时候就可以注入dll了。

         我的理解是:windows维护着消息队列,应用程序会从队列中取出消息,不同的消息有着不同的编号,我们根据编号idHook,设置不同钩子。如何设置钩子?可以利用SetWindowsHookEx这个API函数,函数原型如下:第一个参数是消息编号,第二个参数为Hook函数

         具体操作如下:

         DLL劫持法(输入表DLL替换法),原理是利用搜索DLL路径存在先后顺序(exe程序目录>系统目录>当前目录>Path),当较高层存在一个同名的DLL文件的时候,就会直接加载较高层的DLL文件。常常用于病毒的白加黑。需要注意的是黑DLL路径优先级一定要高于原来的dll文件,第二,一定要具有源dll文件所有的导出函数。

         毕竟新创建的进程在加载User32.dll时,都会自动调用LoadLibrary去加载注册表中某个表项键值里写入的Dll路径

         在创建远程线程创建初期在DllMain中防御远程线程,此时尚未调用LoadLibrary。可以对线程的合法性判断
         LoadLibrary之前首先可以挂钩LoadLibrary函数,然后检查dll路径合法性
         LoadLibrary之后枚举可疑内存和模块

 
 
 
 
 
 
 
 

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 21
支持
分享
最新回复 (20)
雪    币: 2822
活跃值: (154)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
很详细,受教了,感谢大佬
2019-8-18 01:02
0
雪    币: 6535
活跃值: (4491)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
3
反射方式看起来很高端呀
2019-8-18 08:58
0
雪    币: 341
活跃值: (1005)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
学习学习.
2019-8-18 09:49
0
雪    币: 877
活跃值: (132)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
好文章 ,学习了~~
2019-9-7 07:22
0
雪    币: 120
活跃值: (1597)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
学习了·
2019-9-10 18:06
0
雪    币: 1
活跃值: (95)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
补充一种注入姿势。使用SetThreadContext,获取线程的上下文,修改Rip,跳到写入目标进程的shellcode,加载dll后跳回到原Rip继续执行。这个比较隐蔽吧,因为不会创建新的线程,只是在原有线程上动手脚。
2019-9-11 00:32
0
雪    币: 498
活跃值: (2314)
能力值: ( LV12,RANK:356 )
在线值:
发帖
回帖
粉丝
8
5ilent 补充一种注入姿势。使用SetThreadContext,获取线程的上下文,修改Rip,跳到写入目标进程的shellcode,加载dll后跳回到原Rip继续执行。这个比较隐蔽吧,因为不会创建新的线程,只 ...
这个有写,原理是一样的,您那个算是代码注入,更加隐蔽,结合Hook效果特棒
2019-9-11 23:09
0
雪    币: 1808
活跃值: (578)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
9
目标进程的内存中仍然有痕迹
2019-9-17 16:00
0
雪    币: 5317
活跃值: (3313)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
10
反射加载的那里,如果是通过导出函数ReflectiveLoader来加载自身,如果是想对代码加密解密,那么需要如何处理?
2020-2-29 14:04
0
雪    币: 1400
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
感谢大佬分享
2020-3-1 10:12
0
雪    币: 6
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
对于游戏类。可以注入到dx的EndScene中。很酸爽。
https://docs.microsoft.com/en-us/previous-versions/windows/desktop/bb324054(v=vs.85)?redirectedfrom=MSDN
最后于 2020-3-1 10:38 被uuzone编辑 ,原因:
2020-3-1 10:37
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
大佬大大,请问为什么我算的那个call的地址减去开始的地址是28b33f,是因为我的起始地址是在OD里最上面的那个?其实程序装入内存的时候前1000有别的用吗?求解,谢谢!
2020-3-19 11:50
0
雪    币:
活跃值: (421)
能力值: ( LV5,RANK:73 )
在线值:
发帖
回帖
粉丝
14
mark
2020-5-1 14:40
0
雪    币: 259
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
给力,再来点防护措施就完美了
2020-5-28 15:40
0
雪    币: 3
活跃值: (466)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
前排留名
2020-12-8 12:50
0
雪    币: 1245
活跃值: (2148)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
17
学习学习,增长知识
2020-12-8 15:15
0
雪    币: 0
活跃值: (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18

小白向大佬请教个问题,在"反射式DLL注入"->" 利用导出表获取导出函数地址ReflectiveLoader"这一步骤中导出表地址是如何拿到的呢?是不是根据载入内存的dll基址计算得来的?如果是的话ReflectiveLoader为什么还要在内部定位DLL载入基址而不是在"利用CreateRemoteThread跨线程调用ReflectiveLoader"这一步将dll基址作为参数传入呢。

最后于 2021-4-20 16:34 被xdxtu编辑 ,原因:
2021-4-20 16:33
0
雪    币: 1140
活跃值: (266)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
push dword ptr ds : [ebx]INJECT_DATA.lpParameter         
call dword ptr ds : [ebx]INJECT_DATA.lpThreadStartRoutine 
类似这样的汇编不是很明白, push call 指令还可以这样用么?求大神解惑
2021-4-26 16:49
0
雪    币: 6
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
21
createremotethread老是让目标进程崩溃怎么办
2021-12-17 23:44
0
游客
登录 | 注册 方可回帖
返回
//