- 将恶意代码混淆到正常的windows资源空间中
- 逃避检测:隐藏启动技术
12.1 启动器(加载器)
- 设置自身或另外一些恶意代码立即或将来隐蔽运行
- 对用户隐藏恶意的行为
- 通常包含恶意代码的加载
- 在自身的资源节中包含一个可执行文件或者DLL
- 正常资源节中的内容包含: 图标、图片、菜单、字符串
- 启动器通常在资源节存储恶意代码,启动器运行时,它在运行嵌入的可执行程序或dll程序之前,从资源节将恶意代码提取出来
- 启动器经常使用资源操作API函数:FindResource、LoadResource、SizeofResource…
- 识别启动器的另一种思路:有提权代码存在(一般管理员权限才能操作资源节)
12.2 进程注入
- 将代码注入到另外一个正在运行的进程中,被注入的进程会不知不觉运行注入的代码
- 作用:隐藏代码行为、绕过基于主机的防火墙和针对进程的安全机制(进程白名单)
- 进程注入常用API:VirtualAllocEx-在另外一个进程分配一块内存空间,WriteProcessMemory-再分配的内存空间中写数据
- DLL注入
- 强迫一个进程远程加载恶意DLL程序到它的进程上下文(LoadLibrary)
- 恶意dll拥有被注入进程访问系统的相同权限
- 实例:恶意代码通过注入浏览器访问网络
- 为了将恶意dll注入主机进程,启动器恶意代码必须获取受害进程的句柄,常用方法使用CreateTollhelp32Snapshot、Process32First、Process32Next查找进程列表中的目标进程,一旦发现启动器就提取目标进程的PID,然后调用OpenProcess获得目标进程句柄
- dll注入使用CreateRemoteThread:让启动器在远程进程中创建并运行一个新的线程,参数包括
- 进程句柄hProcess,受害进程句柄(OpenProcess获得)
- 入口点lpStartAddress (如:LoadLibrary)
- 参数lpParameter (如:恶意DLL的名称)
- 例如:线程入口点设置为Loadlibrary函数地址,恶意dll名字作为它的参数,出发后会将恶意dll加载到受害进程中
- VirtualAllocEx:为恶意动态库的名字字符串在远程进程中创建内存空间
- WriteProcessMemory:将恶意dll程序的名字字符串写入VirtualAllocEx分配的内存空间
- 启动器不会调用恶意函数,当操作系统将dll加载到内存中时会自动调用
- 识别DLL的注入的最简单方式,就是在启动器恶意代码的反汇编代码中找 到这些Windows API调用的标志模式
- 一旦在反汇编代码中看到DLL注入行为,就应该查找 包含恶意DLL名字和受害进程名字的字符串。(从createremote向上找,查看字符串比较函数,比对的特殊进程名为要注入的目标)
- 启动器在确定受害进程的PID时,通常能在函数 strncmp(或者等同的函数)中发现受害进程的名字。
- 可以在动态调试过程中看到
- 直接注入
- 和dll注入的区别:不用单独编写一个dll并且强制远程进程载入它,而是直接将恶意代码注入到远程进程中
- 主要是注入shellcode
- 特征API:VirtualAllocEx、WriteProcessMemory、CreateRemoteThread
- 第一次调用VirtualAllocEx、WriteProcessMemory:分配内存空间、写入远程线程使用的数据(如shellcode)
- 第二次调用VirtualAllocEx、WriteProcessMemory:分配内存空间、写入远程线程代码(如执行shellcode)
- CreateRemoteThread:参数包含远程线程代码位置(lpStartAddress)和数据(lpParameter)
12.3 进程替换
- 将一个可执行文件重写到一个运行进程的内存空间
- 当恶意代码编写者想要将恶意代码伪装成一个合法进程, 并且不会产生DLL注入让进程崩溃的危险时,他们会使用进程替换技术
- 可以让恶意代码获取到其所替换进程的权限
- 技术关键:以挂起状态创建一个进程(通常替换svchost.exe),在挂起状态,进程被加载到内存但主线程被挂起,因此恶意代码能够在其运行前重写该进程的代码,恢复主线程后,进程才开始执行
- 调用CreateProcess,并且设置dwCreationFlags参 数为CREATE_SUSPENDED
- ZwUnmapViewOfSection:释放节的内存映射
- VirtualAllocEx:分配新内存
- WriteProcessMemory 将恶意代码的每个段写入受害 进程内存
- SetThreadContext:恢复被注入线程上下文,让入口点指向恶意代码
- ResumeThread:初始化恶意代码并进行执行
- 查看进程名称、进程路径时,都是已知和有效的二进制程序
12.4 钩子(Hook)注入
- 利用Windows钩子加载恶意代码,恶意代码用它拦截发往某个应用程序的消息
- 目的:
- 保证无论任何时候拦截到一个特殊消息,恶意代码都会被运行
- 保证一个特殊的DLL被载入到受害进程的内存空间
- 本地和远程钩子
- 本地钩子:观察和操控发往进程内部的消息
- 远程钩子:观察和操控发往一个远程进程的消息(系统中另一个进程),有两种形式
- 上层钩子:钩子例程是DLL的一个导出函数,它被操作系统映射到被挂钩线程或系统所有线程的进程地址空间(调用另外的dll安装)
- 底层钩子:要求钩子例程被包含在安装钩子的进程中(当前进程安装)
- 使用钩子的击键记录器
- 分别使用WH_KEYBOARD和WH_KEYBOARD_LL例程,来注册上层和底层钩子
- 使用SetWindowsHookEx
- idHook:要安装钩子例程类型
- lpfn:钩子例程指针
- hMod:DLL句柄,或标识包含lpfn例程的本地模块句柄
- dwThreadId:钩子例程关联的线程标识。0代表所有线程
- 钩子例程必须调用CallNextHookEx将消息传给下一个钩子例程因此系统能够继续正常运行
- 注入到目标线程
- 定制dwThreadId决定是载入到dw某个系统线程还是载入到所有线程
- 若目的是拦截消息(键盘记录器)应载入到所有线程,但是会降低系统运行速度,可能触发IPS
- 指定单线程为目标,要求查找进程列表中的目标进程,如果碰到目标进程没有运行,恶意代码要先启动它(已知PID的情况下)
- 通常以不常使用的Windows消息作为目标,如 WH_CBT (一个用于计算机训练的消息),一旦该消息出现,恶意程序就知道是触发它的消息
- 实例:
- 加载恶意dll(hook.dll)
- 获取恶意钩子例程(MlwareProc)的地址,钩子例程对notepad.exe中的一个线程调用SetWindowsHookEx函数, 对其他线程仅仅调用 CallNextHookEx函数
- 针对notepad.exe的一个线程(GetNotepadThreadId)调用SetWindowsHookEx函数,向notepad.exe进程发送WH_CBT消息,强制notepad.exe加载hook.dll,并让hook.dll在notepad.exe的进程空间运行
- 一旦hook.dll被注入,就可以运行 DLLMain中的代码,且伪装成 notepad.exe进程
- 定制dwThreadId决定是载入到dw某个系统线程还是载入到所有线程