注入技术
0x01 DLL注入方法
通常情况下,程序加载DLL的实际主要有以下3个:
- 进程创建阶段加载输入表中的DLL,即俗称“静态输入”;
- 通过调用LoadLibray主动加载,称“动态加载”;
- 由于系统机制的要求,必须加载系统预设的一些基础服务模块,如Shell扩展模块,网络服务模块等。
1.1 通过干预输入表处理过程加载目标DLL
当一个进程被创建后,不会直接到EXE本身的入口执行,首先被执行的时ntdll.dll的LdrInitializeThunk函数(ntdll在进程创建的时候就被映射到新进程中了)。LdrInitializeThunk会调用LdrpInitializeProcess对进程进行一些必要内容的初始化,LdrpInitializeProcess会继续调用LdrpWalkImportDescriptor对输入表进行处理,即加载输入表中的模块,并填充应用程序的IAT。所以在输入表被处理前,在输入表中添加一项,使其指向要加载的目标DLL,或者替换原输入表中的DLL并对调用进行转发,那么新进程的主线程在输入表初始化阶段就会主动加载目标DLL。
1.1.1 静态修改PE输入表法
参考实验
1.1.2 进程创建期修改PE输入表法
参考实验
1.1.3 输入表项DLL替换法(DLL劫持法)
参考实验
1.2 改变程序运行流程使其主动加载目标DLL
程序运行的容器是i进程,真正活动的是其中的线程。因此,改变程序流程的通常做法是改变线程的EIP,创建新线程或修改目标进程内的某些代码,使其执行LoadLibrary(Ex)来加载目标DLL。
1.2.1 CreateRemoteThread法
其基本思路实在目标进程中申请一块内存并向其中写入DLL路径,然后调用CreateRemoteThread,在目标进程中创建一个线程。线程函数的地址就是LoadLibraryA,参数就是存放DLL路径的内存指针。
1.2.2 RtlCreateUserThread法
RtlCreateUserThread函数是ntdll中Rtl执行体的一部分,与CreateRemoteThread类似,最终都要调用NtCreateThreadEx来创建线程实体。但是,他一般只用来创建一些特殊的线程(如Native程序smss.exe用它来创建监听线程,以及调试器附加到进程时创建DbgUiRemoteBreakin线程),所以不需要经过CSRSS的验证登记。与CreateRemoteThread不同的是,RtlCreateUserThread需要自己结束自己。造成创建线程的起始地址实际上是kernel32!BaseTrheadStart或kernel32!BaseThreadInitThunk,线程函数由它们执行,执行后会调用ExitThread或RtlExitUserThread结束线程自身。使用RtlCreateUserThread需要我们自己完成这些操作。
具体做法为使用它执行一个shellcode,shellcode再使用TreadPro,相当于远程创建了ThreadProc,最后再使用ZwTerminateThread函数终止线程。
1.2.3 QueueUserApc/NtQueueAPCThread APC注入法
“APC”是“Asynchronous Procedure Call”(异步过程调用的缩写)。它是一种软中断基址,当一个线程从等待状态中苏醒时,它会检测有没有APC交付给自己。如果由,它就执行这些APC过程。APC有两种形式,由系统产生的APC被称为内核APC,由应用程序产生的APC被称为用户模式APC。在用户层,我们可以像创建远程线程已有,使用QueueUserAPC把APC过程添加到目标线程的APC队列里,等这个线程恢复时,就会执行我们插入的APC过程。
在添加用户模式APC后,线程不会直接调用APC函数,只有当线程被唤醒时才会调用。为了增加调用机会,应向所有线程插入APC。
1.2.4 SetThreadContext法
正在执行的线程开源被SuspendThread函数暂停执行。然后,系统就会把此时的线程上下文环境保存下来。当使用ResumeThread恢复线程的执行时,系统会把之前保存到上下文环境恢复,使线程从之前保存的eip出开始执行。在注入DLL时,可以将目标进程中的线程暂停,然后想起向其shellcode,把线程CONTEXT的eip设置为shellcode的地址,这样线程恢复执行时就会先执行我们的shellcode。再shellcode中加载目标DLL,然后跳回原始的eip执行。
具体如下:
- 枚举目标进程中的线程,获取线程ID。
- 打开进程和线程,暂停线程。
- 获取线程的CONTEXT,保存eip。
- 申请内存,准备shellcode并将其写入。
- 设置新的CONTEXT并恢复线程的执行。
1.2.5 内核中通过Hook/Notify干预执行流程法
1.2.6 内核KeUserModeCallback法
Windows系统在加载全局钩子DLL时,是由Win32k.sys调用KeUserCallBack回调user32.dll中的函数并最终通过LoadLibraryExW实现的,所以,也可以用同样的方法注入DLL。
文章评论