启动技术
Friday, February 7, 2020
5:15 PM
创建进程API
调用 Win32 API 创建新进程。微软在用户层提供 WinExec , ShellExecute 和 CreateProcess 等函数实现进程的创建。
WinExec,ShellExecute以及CreateProcess除了可以创建进程外,还能执行CMD命令等功能。
用户层,通常使用WMI或通过HOOK API来监控进程的创建。
EnumWindows函数可以枚举所有屏幕上的顶层窗口,包括隐藏窗口。
突破SESSION 0隔离创建用户进程
病毒或木马通常会把自己注入到系统服务进程或伪装为系统服务进程,并运行在SESSION 0中。
处于SESSION 0中的程序可以正常执行普通程序的大部分操作,但个别操作除外。如,处于SESSION 0中的系统服务进程
无法与普通用户进程通信,不能通过Windows消息机制进行通信,更不能创建普通用户进程。
在Windows XP,Windows Server 2003 ,以及更老版本的Windows操作系统中,服务和应用程序使用相同的会话session运行,而这个会话是由第一个登录到控制台的用户来启动的,该会话就称为session 0.将服务和用户应用程序一起在session0中运行会导致安全风险,因为服务会使用提升后的权限来运行,而应用程序使用用户特权(大部分是非管理员用户)运行,
这会使得恶意软件把某个服务作为攻击目标,通过“劫持”该服务以达到提升权限的目的。
从 Windows Vista开始,只有服务被托管到session 0中,用户应用程序和服务之间隔离。微软提供一系列以WTS
(Windows Terminal Service,Windows终端服务)开头的函数,从而完成服务层和应用层的交互。
突破session 0创建的用户桌面进程,可以是普通用户进程;可以是拥有系统权限的子进程(设置进程访问令牌的安全描述符实现继承系统权限)。
通过挂钩CreateProcessAsUser 函数监控进程创建。
内存直接加载运行
很多病毒或木马具有模拟PE加载器的功能,把DLL或EXE等PE文件直接从内存中直接加载到病毒或木马的内存中去执行,
不需要通过 LoadLibrary 等现成的API函数操作,以此躲过杀软的检测。
内存直接加载技术的核心就是模拟PE加载器加载PE文件的过程,即对导入表,导出表和重定位表的操作过程。
PE文件有两个对齐字段:映像对齐大小是PE文件加载到内存中所用的对齐大小。文件对齐大小是PE文件存储到本地磁盘所用的对齐大小。一般文件对齐大小会比映像对齐大小要小,这样文件会变小,以此节省磁盘空间。
成功映射内存数据后,在DLL程序中会存在硬编码数据,硬编码都是以默认的加载基地址作为基址计算的。由于DLL可以任意加载到其他进程空间中,所以DLL的加载基址并非固定不变。当改变加载基址时,硬编码也需要改变。
如何知道硬编码的位置?如何知道需要修改哪些硬编码?PE结构的重定位表,记录的是程序中所有需要修改的硬编码的相对偏移位置。
PE结构使用导入表记录PE程序中所有引用的函数及其函数地址。在DLL映射到内存后,需要根据导入表中的导入模块和函数名称来获取调用函数的地址。若想从导入模块中获取导出函数地址,最简单的方式是通过GetProcAddress函数获取。但为了避免调用敏感的WIN32 API 函数而被杀软拦截检测,直接遍历PE结构导出表的方式来获取导出函数地址。
实现步骤:
(1)在DLL文件中,根据PE结构获取其加载映像的大小 SizeofImage , 并在程序中申请可读,可写和可执行的内存。该地址地址即是DLL加载基址。
(2)根据DLL中的PE结构获取其映像对齐大小SectionAlignment,然后把DLL文件数据按照sectionAlignment复制到上述申请的可读,可写,可执行的内存中。
(3)根据PE结构的重定位表,重新对重定位表进行修正。
(4)根据PE结构的导入表,加载所需DLL,并获取导入函数地址并写入导入表。
(5)修改DLL加载基址 ImageBase
(6)根据PE结构获取DLL入口地址,然后构造并调用Dllmain函数,实现DLL加载。
对于exe文件而言,重定位表不是必须的,即使没有重定位表,exe亦可以正常运行。因为对于EXE进程而言,进程最早加载的模块是EXE模块,所以可以按照默认的加载基址加载到内存。对于那些没有重定位表的程序,只能把它们加载到默认的加载基址上。如果默认加载基址被占用,则直接内存加载运行会失败。