12. 隐蔽的恶意代码启动
12.1 启动器(Launcher)
启动器要加载的恶意代码(可执行文件或DLL)包含在资源节中。
如果资源节被压缩或加密,恶意代码必须在加载前进行资源节提取操作,调用 FindResource
、 LoadResource
、 SizeofResource
等.
12.2 进程注入
最流行的隐藏启动技术。将代码注入到另一个正在运行的进程。
某些Windows API被用来执行进程注入。VirtualAllocEx
用来在另一个进程中分配内存空间;WriteProcessMemory
向分配的地址空间写数据。
12.2.1 DLL注入
强迫一个远程进程加载恶意DLL程序。DLL注入将代码注入到一个远程进程,并让远程进程调用LoadLibrary
,从而强制远程进程加载一个DLL程序到他的进程上下文。
一旦被感染进程加载了恶意DLL程序,OS会自动调用DllMain
函数,DllMain
与被注入进程有相同的系统访问权限,并且任意操作类似于被感染的进程。
为了注入DLL,首先获取目标进程的句柄。最常用的是使用CreateToolhelp32Snapshot
、 Process32First
和Process32Next
, 查找进程列表中的进程,一旦发现目标,启动器会提取目标进程的PID,然后用PID调用 OpenProcess
, 以获取目标进程的句柄(hProcess
)。
如果提供句柄,VirtualAllocEx
将在远程进程中分配内存空间;WriteProcessMemory
向分配的地址空间写入恶意DLL程序的名字字符串。
DLL注入使用CreateRemoteThread
,这个函数让启动器恶意代码在远程进程中创建并运行一个新的线程。
CreateRemoteThread
三个重要参数:
- 进程句柄
hProcess
,OpenProcess
获得 - 注入线程的入口点
lpStartAddress
, 可以设置为LoadLibrary
函数地址,并且恶意DLL名字作为参数。 - 线程的参数
hpParameter
12.2.2 直接注入
大多注入shellcode。
常用函数:VirtualAllocEx
, WriteProcessMemory
和CreateRemoteThread
。通常会有两次VirtualAllocEx
, WriteProcessMemory
调用,第一次分配空间写入数据,第二次写入代码。CreateRemoteThread
调用包含远程线程位置lpStartAddress
和数据lpParameter
。
12.3 进程替换
关键是以挂起状态创建一个进程。调用CreateProcess
, 并传递CREATE_SUSPENED(0x4)
作为dwCreationFlags
参数,来得到进程的挂起状态。
接下来用恶意可执行文件替换受害进程的内存空间,使用ZwUnmapViewOfSection
来释放有参数执行的所有内存。解除内存映射后,执行VirtualAllocEx
为恶意代码分配新的内存,WriteProcessMemory
将恶意代码写入内存空间。
最后,恢复受害进程环境,调用SetThreadContext
,让入口点指向恶意代码;调用ResumeThread
,初始化恶意代码并执行。
12.4 钩子(Hook)注入
- 保证无论何时拦截到特殊消息,恶意代码都会被运行。
- 保证一个特殊的DLL被载入到受害进程的内存空间。
12.4.1 本地和远程钩子(Hook)
- 本地钩子,观察和操纵发往进程内部的消息。
- 远程钩子,观察和操纵发往一个远程进程(系统中的另一个进程)的消息。
- 上层:是DLL程序的一个到处函数。被OS映射到被挂钩线程或所有线程的进程地址空间。
- 底层:被保护在安装钩子的进程中。在OS获得处理事件的机会前被通知。
12.4.2 使用钩子的击键记录器
WH_KEYBOARD
和WH_KEYBOARD_LL
来注册上层和底层的钩子。截获击键,在传递到进程或系统之前,进行记录或修改。
11.4.3 使用SetWindowsHookEx
是远程Windows挂钩的主要函数,拥有如下参数:
- idHook 指定安装钩子例程的类型
- lpfn 钩子例程指针
- hMod 对于上层钩子,标识包含lpfn定义的钩子例程的DLL句柄。对于底层钩子,标识包含lpfn例程的本地例程句柄。
- dwThreadId 与钩子例程关联的线程标识
钩子例程可以处理消息,也可以什么都不做。但必须调用CallNextHookEx
,保证调用链下一个钩子例程能得到消息,并保证系统正常运行。
12.4.4 目标线程
载入到所有线程会降低系统的运行速度,触发IPS,因此注入单个线程更隐蔽。
挂钩经常使用的WIndows消息,很有可能触发IPS,通常挂钩不常用的消息,如WH_CBT(一个用于计算机训练的消息)。
12.5 Detours
微软研究院开发的代码库,使二进制程序修改变得简单。
恶意代码作者使用Detours库,添加新的DLL到硬盘上的二进制文件。
12.6 APC注入
CreateRemoteThread
创建线程,来使用远程进程中的一个函数,需要系统开销。所以调用现有线程会更加高效,Windows的异步过程调用(APC)可以满足这种要求。
APC可以让一个线程在它正常执行路径运行之前执行一些其他的代码。比如调用WaitForSingleObjectEx
、 WaitForMultipleObjectsEx
和SleepEx
等。
每一个线程都有过一个附加的APC队列,APC队列完成时,线程才继续沿着规定路径执行。
- 为系统或者驱动生成的APC,内核模式APC
- 为应用程序生成的APC,用户模式APC
12.6.1 用户模式APC
使用QueueUserAPC
排入让远程线程调用的函数,参数pfnAPC
、hThread
和dwData
,QueueUserAPC
要求句柄为hThread
的线程使用参数dwData
运行pfnAPC
定义的函数。
12.6.2 内核模式APC
通常由shellcode组成。
设备驱动利用两个主要函数使用APC: KeInitializeApc
和KeInsertQueueApc
。