windows核心编程之DLL注入
来源:互联网 发布:锐捷交换机查mac 编辑:程序博客网 时间:2024/06/05 07:02
一.前言
DLL注入的酷炫之处在于无需目标程序的源码,就可向目的程序注入代码。
要理解DLL注入要先理解好进程的虚拟地址空间,每个进程都有自己独立的虚拟地址空间,一般来说,两个进程的虚拟地址空间是互相隔绝的,进程A不能访问到进程B的虚拟地址空间,进程A的虚拟地址空间被破坏也不会影响到其他进程的虚拟地址空间。
windows核心编程中用一个例子来说明DLL注入的使用:一个进程想从另一个进程创建的窗口实例来派生一个子类窗口。
windows中,要派生子类窗口,必须调用SetWindowLongPtr接口让父窗口的窗口过程指向新的子类窗口的窗口过程(WndProc)。如果用下面的代码调用SetWindowLongPtr来从一个窗口派生子类窗口,那所有发到或者发往hWnd窗口的消息,应用由MySubclassProc来处理,而不是由该窗口的标准窗口过程来处理:
SetWindowLongPtr(hWnd , GWLP_WNDPROC,MySubclassProc) ;
换句话说,当系统需要向指定的WndProc派送消息的时候,会先查看窗口过程的地址,然后通过该地址来调用WndProc,在前面的例子中,由于系统发现与该窗口相关联的窗口过程地址是MySubclassProc,因此会直接调用MySublassProc。
现在一个进程要向另一个进程的窗口派生子类窗口的问题是,两个进程的地址空间时隔离的,子类窗口的窗口过程并不能被父窗口调用。这里就是DLL注入的使用场景了,我们可以将MySubclassProc放在一个Dll中实现,然后将该DLL注入到父窗口所在的进程中,这时子类窗口的窗口过程就进入了父窗口的进程地址空间中了,这时就能在父窗口进程中通过调用SetWindowLongPtr中派生一个子类窗口了。
Windows中几种常用的方式来注入DLL:
(1)使用注册表来注入DLL
(2)使用Windows挂钩来注入DLL
(3)使用远程线程来注入DLL
(4)使用木马DLL来注入DLL
(5)把DLL作为调试器来注入
(6)对子进程进行DLL注入
其中(2)和(3)是比较通用的方法,本篇文章只对这两种方式进行详细讲解。
二.使用Windows挂钩来注入DLL
首先看一下windows挂钩的使用方法:
进程A调用了挂钩安装函数:
HHOOK hHook = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hInstDll,0);
其中第一个参数表示安装的挂钩类型,这里安装的是WH_GETMESSAGE挂钩,该挂钩是一个windows窗口消息挂钩。如果一个窗口安装了该挂钩,在该窗口处理一条消息时,系统应该调用挂钩过滤函数。挂钩过滤函数即为第二个参数GetMsgProc。第三个参数标识了一个DLL,即GetMsgProc所在的DLL,在windows中,hInstDll的值是进程地址空间中DLL被映射的虚拟内存地址。最后一个参数表示要给哪个线程安装挂钩,如果该参数为0,表示要给系统中的所有GUI线程安装挂钩。
假设进程A给进程B的某个线程安装了WH_GETMESSAGE挂钩,则该挂钩的工作过程如下:
(1)进程B中的一个线程准备向一个窗口派送一条消息;
(2)系统检测到该线程已经安装了WH_GETMESSAGE挂钩,所以会先调用一次挂钩过滤程序;
(3)应该挂钩过滤程序所在的DLL还没载入到进程B的地址空间中,所以系统会强制将该DLL注入到进程B的地址空间中。(这里就是DLL注入的发生时机)
(4)当DLL被注入到进程B的地址空间时,也会得到一个hInstDll,即DLL在进程B中的虚拟地址空间,系统会对它进行检查,看是否与该DLL在进程A中的位置相同(在前面进程A给进程B安装挂钩时传的hInstDLL)。如果相同,则在两个进程地址空间中,GetMsgProc的地址是一样的,否则的话,系统可以根据下面的公式推导出GetMsgProc函数在进程B的虚拟地址空间中的位置:
GetMsgProc B = GetMsgProcA + (hInstDll B - hInstDll A) ;
(5)系统在进程B的地址空间中调用挂钩过滤函数GetMsgProc() ;
理解了windows挂钩的使用和工作工程后,现在来看看如何用windows挂钩解决前面的问题:在其他进程的窗口实例中派生一个子类窗口:
我们可以先给创建窗口的线程设置一个WH_GETMESSAGE的挂钩,然后当挂钩过滤函数GetMsgProc被调用时,我们就可以在GetMsgProc函数内调用SetWindowLongPtr来派生子类窗口。当然,子类窗口的窗口过程必须和GetMsgProc在同一个Dll中。
当我们不需要该挂钩和DLL的时候,可以调用下面的windows接口来撤销挂钩和DLL的映射:
BOOL UnhookWindowsHookEx(HHOOK hHook);
最后,如果想了解windows挂钩的详细信息,可看看MSDN中的相关介绍:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms632589(v=vs.85).aspx
三.使用远程线程来注入DLL
使用远程线程来注入DLL是最灵活的一种方式。从根本上来说,DLL注入要求目标进程中的一个线程调用LoadLibrary来载入我们想要的DLL。在理解远程线程DLL注入的原理之前,我们必须先明白一点:
大多数windows接口只允许调用进程操作自己的进程空间,这可以防止一个进程破坏另一个进程。但是windows也提供了一些函数来让一个进程对另一个进程进行操作,这些接口都有一个共同的参数Handle hProcess,用来指定要操作的进程。例如:
CreateRemoteThread(HANDLE hProcess,...); //在一个指定的进程中创建一个新的线程。 VirtualAllocEx(HANDLE hProcess,...); //在一个指定的进程的虚拟地址空间中分配一块内存 VirtualFreeEx(HANDLE hProcess,...) ; //在一个指定的进程的虚拟地址空间中释放内存 ReadProcessMemory(HANDLE hProcess,...);//对指定的进程的地址空间进行读 WriteProcessMemory(HANDLE hProcess,...);//对指定的进程的地址空间进行写
远程线程注入DLL就是靠上面的几个接口来实现的。其原理就是我们在自己的进程中为其他进程创建一个新的线程,并把该线程的起始函数设为LoadLibrary,线程的参数为DLL的路径。假设在进程A中,需要对进程B进行MyLib.dll注入,进程B的HANDLE为hProcessB,这在进程A中的代码类似于:
PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("kernel 32")),"LoadLibraryW");HANDLE hThread = CreateRemoteThread(hProcessB,NULL,0,pfnThreadRtn,L"C:\\MyLig.dll",0,NULL);
当新线程在进程B中被创建的时候,会立即调用LoadLibraryW(),并传入DLL路径名的地址,这时DLL的注入就完成了,在DLLMain()函数里面我们就得到了线程的运行控制权。
但是,上面的代码有一个问题,我们在进程A中调用的CreateRemoteThread()函数,其中把DLL的路径用字符串地址传进去,但是这个字符串地址是在进程A的地址空间的,当创建的线程在进程B的地址空间运行时,其按这个地址去取DLL的路径,实际上是不能取到字符串的,因为这时是在进程B中的地址空间中,我们并没有玩进程B的地址空间中该位置写入字符串,所以这个访问可以导致访问违规异常,进程B被终止。
为了避免这种情况,我们需要先向进程B的地址空间的某个地址写入DLL的路径,然后在调用CreateRemoteThread的时候传入该地址。上面介绍的几个接口可以实现这个需求:
先调用VirtualAllocEx()在进程B中分配一个虚拟内存,再用WriteProcessMemory()向该地址写入DLL的路径。当不需要该块内存时,可以用VirtualFreeEx来释放内存。
最后,当我们不再需要该DLL的时候,我们同样通过创建一个线程,并让线程调用FreeLibrary()函数来释放DLL。
《windows核心编程》中对这两种DLL注入方式还有对应的程序例子,会在下一篇文章<windows核心编程之DLL注入例子分析> 进行讲解。
- Windows 核心编程之Dll注入
- windows核心编程之DLL注入
- Windows核心编程Dll注入之远程线程
- 《Windows核心编程》之“DLL注入”(一)
- 《Windows核心编程》之”DLL注入“(二)
- 《Windows核心编程》之22远程线程注入DLL
- windows核心编程之DLL注入例子分析
- 基于visual c++之windows核心编程代码分析(54)实现Winlogon注入dll
- 基于visual c++之windows核心编程代码分析(54)实现Winlogon注入dll
- Windows核心编程:DLL注入和API拦截
- Windows核心编程(二十一)远程线程注入DLL
- 【Windows核心编程学习笔记】远程注入DLL
- windows核心编程---DLL注入和API拦截
- Windows 核心编程之Dll 延时加载
- Windows核心编程之DLL基础
- 基于visual c++之windows核心编程代码分析(53)在C++中嵌入汇编实现DLL注入源代码
- Windows核心编程:DLL基础
- Windows核心编程 DLL基础
- Anniversary Party(树形dp)
- Go语言学习笔记 --- 关键字、注释、结构、包相关和可见性规则
- eclipse打jar包、解决nosuchmethoderror 问题
- 求二叉树镜像
- GeoServer安装过程
- windows核心编程之DLL注入
- 太坑了,EASYUI的tree图标显示竟然与CSS引入顺序有关系
- Apache开启GZIP压缩
- SQL编程--类型属性unsigned
- Remmina – 功能丰富的用于Linux的远程桌面共享工具
- hdu2040 亲和数(C语言)
- snmp4j 实现 trap监听
- 随便乱写的感想
- 关于数据标准化,归一化,正则化