初探进程注入

十种进程注入技术研究


翻译自:https://www.endgame.com/blog/technical-blog/ten-process-injection-techniques-technical-survey-common-and-trending-process


简介

进程注入是一类各种恶意软件广泛使用的反检测技术,主要功能是在另一个进程的地址空间内运行自定义的代码。进程注入技术提高了恶意代码的隐蔽性,并且也有助于其持久化潜伏。虽然世面上有很多进程注入的技术,但是在这个博客中,我只呈现了十个最具代表的进程注入例子。


1. 传统DLL注入(DLL Injection)

这是最普通的注入技术之一,通常被用于注入恶意软件到另一个进程中。恶意软件将一个恶意DLL的地址写入一个目标进程的虚拟空间中,然后当恶意软件调用API为此DLL创建一个线程时,恶意代码就被运行了。
Classic Dll Injection

恶意软件首先确定一个准备注入的目标进程(例如svchost.exe)。然后通过以下三个API搜索目标进程:CreateToolhelp32Snapshot,Process32First和Process32Next。 CreateToolhelp32Snapshot用于枚举指定进程或所有进程的堆或模块状态,并返回一个Snapshot(进程信息集合)。 首先使用Process32First获取Snapshot中第一个进程的信息,然后用Process32Next循环遍历每一个进程的信息。找到目标进程后,恶意软件通过调用OpenProcess获取目标进程的句柄。

Rebhip

上图为Rebhip蠕虫病毒的代码,它首先调用VirtualAllocEx在目标进程申请一片内存空间,然后调用WriteProcessMemory来将恶意DLL的路径写入这个内存片中,最后,为了能让目标进程中的恶意代码执行,恶意软件会调用CreateRemoteThread、NtCreateThreadEx或RtlCreateUserThread,后两个函数目前没有官方记载。CreateRemoteThread可以在指定的进程上创建线程,如上图关键参数有hProcess、lpStartAddress、lpParameter,调用时hProcess填目标进程的句柄,lpStartAddress填LoadLibrary()的地址(PS:LoadLibrary的地址在每个进程中都是相同的,可以通过当前进程获取),lpParameter填之前创建的存放恶意DLL路径的内存地址,这样,就可以让目标进程创建一个线程,此线程调用LoadLibrary()加载恶意DLL,从而达到执行恶意代码的效果。大致代码如下:
DLL Injection exp
CreateRemoteThread现在已经被很多杀软标记了。因为恶意DLL在硬盘上很容易被发现,所以攻击者现在一般不使用这种方法了。


2. PE注入(PE Injection)

此方法不使用Loadlibrary,而是直接将恶意代码(整个PE文件)复制到目标进程中并运行(使用shellcode或者CreateRemoteThread)。PE注入的好处是,不用释放DLL到磁盘上。跟上一种方法相似,恶意软件首先在目标进程空间中申请内存(如使用VirtualAllocEx),不同的是,恶意软件直接使用WriteProcessMemory将恶意PE写入这片内存中(而不是写入DLL路径)。然而,这时会遇到一个问题,当恶意PE被插入到目标进程时,它的基址会发生变化,这个基址是无法预知的,所以我们只能在执行恶意软件的时实时地候获取目标进程的基址,然后遍历恶意PE的reloc表的每一个reloc描述符并对其进行修改。
PE Injection
这种技术与反射DLL式注入和内存模块式注入等其他技术相似,因为它们都不会释放文件到磁盘上。但是,反射DLL式注入和内存模块式注入更加难以检测。它们不会调用敏感的Windows API(例如,CreateRemoteThread或LoadLibrary)。反射式DLL注入是通过创建一个在执行时可以将自己映射到内存中的DLL来实现的,而不是依靠Window的加载器(LoadLibrary)。内存模块式注入类似于反射DLL式注入,但这种方法是使用加载器将目标DLL映射到内存而不是DLL映射本身。在之前的博客文章中,这两种内存方法已经被广泛讨论。

PE Injection
PE注入的恶意代码有个特点,就是在调用CreateRemoteThread之前,通常会有一个循环(通常是两个“for”循环,一个嵌套在另一个中)。这种技术在加密型恶意软件中非常流行。在图2中,恶意代码使用两个for循环来定位及修改reloc表。 “and 0x0fff”指令也是一个很好的指纹标记,表明eax是reloc表的绝对地址,and运算后得到的就是绝对地址。现在恶意软件已经重新计算了reloc表的地址,接下来只需将其起始地址传递给CreateRemoteThread并执行。


3.进程替换(Process Hollowing)

进程替换式注入跟DLL式注入截然不同,恶意软件首先目标进程的合法代码给unmap掉,然后将自己的恶意代码写入这片内存。
Process Hollowing

Process Hollowing
如上图,恶意软件首先通过CreateProcess来创建一个新的进程,调用时设置进程标志为CREATE_SUSPENDED(0x00000004)。这样当进程创建成功时,主线程就会是一个挂起状态,直到调用ResumeThread才会开始运行。接下来,恶意软件需要将其中的合法内容替换成恶意代码,通过调用ZwUnmapViewOfSection或NtUnmapViewOfSection来unmap掉指定Section的内存,然后使用VirtualAllocEx申请新的内存,接着调用WriteProcessMemory将恶意软件的每个section写入这片内存中。关键的一步,恶意软件调用SetThreadContext将程序入口点指向刚写入的恶意代码处。最后,调用ResumeThread恢复目标线程的执行,开始执行恶意代码。

4.线程执行流劫持(Thread Execution Hijacking)

这种注入技术跟前面讲的Process Hollowing很相似。但跟后者不同的是,Thread Execution Hijacking是操作一个进程中已存在的一个线程,这样可以避免在进程和线程的创建过程中出现差错。所以在分析中,你可能会看到OpenThread之后会有CreateToolhelp32Snapshot和Thread32First的调用。
Thread Execution Hijacking
拿到目标线程的句柄之后,恶意软件调用SuspendThread来挂起目标线程,接下来就是熟悉的调用VirtualAllocEx和WriteProcessMemory来写入恶意代码。
Thread Execution Hijacking
上图是一个使用了此技术的木马代码。为了劫持线程的执行流,恶意软件需要调用SetThreadContext来修改EIP寄存器的值,最后便是恢复线程来执行恶意代码。但是,攻击者发现,在线程进行系统调用的中途对其进行suspend和resume容易引起系统崩溃,所以为了防止这种情况发生,更高级的恶意软件会在EIP不属于NTDLL.dll范围内的时候再执行suspend和resume。


5.Hook注入(Hook Injection)

Hooking是一种监听函数调用的技术。恶意软件可以通过Hook使得目标线程触发一个事件时运行恶意DLL。具体是调用SetWindowsHookEx函数来安装Hook到Hook链中。SetWindowsHookEx需要4个参数,第一个参数是事件类型(event),第二个参数一个是指向事件处理函数的指针,第三个参数是包含此函数的module。因此,在恶意代码调用SetWindowsHookEx之前我们很可能会看到LoadLibrary和GetProcAddress的调用。最后一个参数就是要绑定的线程的ID,这个参数如果设置成0,那么Hook将会监听所有线程,然而,恶意软件一般都只会指定一个线程,以避免发生其他异常,所以,为了寻找特定的线程,恶意代码也会出现CreateToolhelp32Snapshot函数和Thread32Next函数。
Hook Injection


6.注册表式注入(Injection and presistence via registry modification)

Appinit_DLL,AppCertDlls和IFEO(Image File Execution Options)都是恶意软件用于injection和presistence的关键注册表键,它们一般处于以下位置:

   HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows\Appinit_Dlls

   HKLM\Software\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\Appinit_Dlls

   HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls

   HKLM\Software\Microsoft\Windows NT\currentversion\image file execution options

AppInit_DLLs
恶意软件通过在Appinit_Dlls注册表项下插入其恶意library的路径,使得其他进程在运行时会加载其恶意library。该键下的所有library在所有进程调用User32.dll时都会被调用,而User32.dll又是几乎所有进程都会调用的图形库,所以当恶意软件修改此键值时时,大多数进程都将会加载恶意library。下图显示了一个使用这种方法进行injection和presistence的木马。它通过调用RegCreateKeyEx打开Appinit_Dlls注册表项,然后调用RegSetValueEx来修改其值来达到注入的目的。

AppCertDlls
此方法与AppInit_DLLs方法非常相似,只不过被注入的函数是所有Win32 API函数如CreateProcess,CreateProcessAsUser,CreateProcessWithLogonW,CreateProcessWithTokenW和WinExec。

IFEO(Image File Execution Options)
IFEO本来是作调试程序用的,开发人员可以在此注册表项下设置“Debugger Value”,然后就可以将软件attach到一个要调试的程序上了。因此,只要一启动软件,被attach的程序也会一起启动。使用这种方式,恶意软件可以修改此注册键值以将自身注入到目标软件中中,这样,只要目标软件一启动,被注入的恶意代码也会一起运行。
Reigster Injection


7.APC式注入和Atombombing(apc injection and atombombing)

恶意软件可以通过APC(Asynchronous Procedure Calls–异步进程调用 )来强制目标线程执行恶意代码(通过将自己添加到目标线程的APC队列中)。每个线程都有一队等待执行的APC,一旦目标进程进入alterable状态,就会被触发。当线程调用SleepEx,SignalObjectAndWait,MsgWaitForMultipleObjectsEx,WaitForMultipleObjectsEx或WaitForSingleObjectEx函数时,就会进入alterable状态。恶意软件通常会寻找那些处在alterable状态的线程,然后调用OpenThread和QueueUserAPC来将一个APC插入到此线程的APC队列中。QueueUserAPC需要三个参数:1.目标线程的句柄 2.指向要调用的恶意函数的指针 3.恶意函数的参数。
APC Injection
如上图,Amanahe病毒首先调用OpenThread获得目标线程的句柄,然后将LoadLibraryA作为参数传入QueueUserAPC并运行,这样就能注入恶意DLL到目标线程了。
AtomBombing是由enSilo research提出的一种注入技术,它也后来Dridex V4病毒使用。它也是一种基于APC式注入的技术,我们在之前的文章中有详细介绍,它通过操作atom表来进行注入。


8.EWM式注入(extra window memory injection (EWMI) via SetWindowLong)

EWMI的原理是将恶意代码注入到资源管理器(Explorer)窗口的额外窗口内存(extra window memory)中,Gapz和PowerLoader这两个恶意软件家族就使用过这种技术。当我们注册一个window类时,应用程序可以申请一小部分的额外内存空间(EWM)。然而,EWM并没有多大的空间,所以恶意软件一般将恶意代码写入属于一段explorer.exe的shared section中,然后通过调用SetWindowLong和SendNotifyMessage来调用这段代码。

对于将恶意代码写入shared section,恶意软件有两种选择。第一种选择是创建一个新的shared section并将其同时映射至自身和目标进程(如explorer.exe)上;第二种选择是直接使用一个已存在的shared section上。前者会创建一段堆空间以及调用NTMapViewOfSection等API,这些都会产生额外的开销,所以后者更为大家所喜欢。恶意软件将恶意代码写入shared section后,接着就是调用GetWindowLong和SetWindowLong来修改”Shell_TrayWnd”的EWM。GetWindowLong的功能是获取一个window类的EWM的指定偏移地址的32位值,而SetWindowLong是用来修改此值的,这样,通过这两个API,恶意软件就可以修改window类中存放函数指针的值,将此值修改为我们恶意代码的地址。

接下来,恶意软件需要触发它写入的恶意代码,我们上面提到的几种技术一般使用诸如CreateRemoteThread,QueueUserAPC,SetThreadContext等API,而此技术则使用SendNotifyMessage,调用此函数后,Shell_TrayWnd将会把控制流转交给我们刚写入的恶意代码。下图是使用了此技术的PowerLoader病毒。
EWMI


9.SHIMS式注入(INJECTION USING SHIMS)

微软为程序员提供了Shims,Shims可以让程序员重写代码就能为之前应用程序打补丁。通过Shims,程序员可以告诉操作系统如何处理他们的应用程序。 Shims本质上就是一种Hook技术。Windows在加载二进制文件时会运行Shims引擎来查询shimming数据库以应用对应的补丁。

恶意软件一般会使用一些安全相关的补丁(如DisableNX,DisableSEH,InjectDLL等),恶意软件有许多方法来安装一个shimming数据库。比如,最简单的就是运行sdbinst.exe,然后让其引用恶意的sdb文件。下图是一个广告软件,它使用一个InjectDLL的shim来致使Chrome加载vc32loader.dll。当然也有许多工具可以用来分析sdb文件,我使用的是python-sdb
Shims


10.IAT Hooking和内联Hooking(IAT HOOKING AND INLINE HOOKING(A.K.A USERLAND ROOTKITS))

IAT Hooking和内联Hooking通常被称为用户层的rootkit。 IAT Hooking是恶意软件用来修改IAT的技术,原理是修改合法软件中API的地址,将其替换为恶意代码的地址。相比之下,内联Hooing是直接修改API函数本身。下图,是恶意软件FinFisher通过IAT Hooking来劫持CreateWindowEx的地址
IAT Hooking


结论

注入技术日新月异,我们也需要不断地学习,来与之抗衡!!!

Conclusion

猜你喜欢

转载自blog.csdn.net/m0_37552052/article/details/79198070