从HeaderLessPE到扩展实现HideVNC下Gui攻击技术
2023-9-18 18:13:50 Author: M01N Team(查看原文) 阅读量:17 收藏

概述

HeaderLessPE是一种移除了大多数字段的PE结构,由icedid木马所使用,本文通过对该技术的研究,扩展了该技术在HVNC下的攻击方式,使的通过远程注入后的HeaderLessPE可不受限制的运行图形化黑客工具。

01 HeaderLessPE 技术原理

HeaderLessPE最初由Icedid木马使用,该木马的多阶段内存加载和远程注入中都作为主要的技术手段。

如图所示,一个HeaderLessPE的结构定义如下:

typedef struct _HeaderLessSection {  DWORD  VA;             // 内存虚拟地址偏移  DWORD  VirtualSize;    // 内存加载大小  DWORD  RawOffset;      // 数据偏移  DWORD  RawSize;        // 数据大小  BYTE  Access;         // 内存属性}HeaderLessSection, * PHeaderLessSection;
typedef struct _HeaderLessPE{  PVOID  ImageBase;      // 映像基址  DWORD  ImageSize;      // 映像大小  DWORD  ImageEntryPoint;    // 入口函数  DWORD  ImportTableVA;      // 导入表  DWORD  RelocTableVA;       // 重定位表  DWORD  RelocTableSize;     // 重定位表大小  DWORD  SectionCount;       // 节区数量  HeaderLessSection Section[1];}HeaderLessPE, * PHeaderLessPE;

与Memdll等内存加载技术实现一致,加载HeaderLessPE时都需要自行编写loader代码分别将节区拷贝到内存、修复重定向与导入表,设置内存权限并调用入口函数。


HeaderLessPE的加载过程如下:

1. 申请内存并拷贝节区

申请地址时我们可以先申请ImageBase映像基址,如果失败再申请随机地址。

PBYTE image = (PBYTE)VirtualAlloc(pe->ImageBase, pe->ImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);if (image == 0){    image = (PBYTE)VirtualAlloc(NULL, pe->ImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);}

2. 修复重定位

如果申请地址与ImageBase不一致,就需要修复重定位数据,如果是注入到远程进程,需要计算与远程地址的偏移。

DWORD delta = (DWORD)((LPBYTE)image - (LPBYTE)pe->ImageBase);  //   0x40000 - 0x1400,0000 计算申请地址与基址的偏移

3. 修复导入表

4. 更改节区内存权限、并调用入口函数

entry = (pfnWinMain)((PBYTE)image + pe->ImageEntryPoint);entry(0,0, 0, 0);

相比MemDll等内存PE加载技术,HeaderLessPE有两个优点:

  1. 避免包含传统PE的DOS头、PE头特征:DOS头和PE头经常是被内存扫描的照顾重点特征,在使用Cobalt Strike的时候常需要设置Profile文件将加载完成的Beacon头抹掉。使用HeaderLessPE就不需要担心这个问题。

  2. 支持数据段和重定位表,能方便的将传统EXE文件转换为HeaderLessPE:只要是支持重定位,不包含如:Tls、delay import等结构都能够转换为HeaderLessPE, 这样不仅可以用来做木马内存模块,还可以将一些黑客工具方便的转换为HeaderLessPE进行内存加载运行,扩展可使用的攻击工具。

02 技术扩展,实现在HidenVNC下无文件运行GUI程序

HidenVNC又称HVNC,是一种远程桌面控制技术,多用于银行木马,  可以在受害者不知情的情况下,隐蔽的访问系统,浏览文件、查看凭证、启动程序、登录网银等。为了达到这一目的,HVNC会使用了一些鲜为人知Windows功能,实用CreateDesktop来创建一个新的虚拟桌面,隔绝了与用户操作互相影响。关于HVNC的介绍,看雪的这篇讲的比较全面https://bbs.kanxue.com/thread-264956.htm。总之,HVNC是一种高级的远程控制技术,提供了一种隐蔽的图形化控制手段。

单纯的利用HVNC只能运行一些受害者机器上已安装的应用程序,可执行的程序受限。假如我们能够执行一些如BrowsingHistoryView或者是ADExplorer之类的图形化工具,又避免在目标机器安装,我们就能扩展可执行程序的范围,例如NisSoft和微软的SysinternalsSuite都提供大量可以被用来攻击的管理用具。


在程序绘制GUI时,首先会查找相对应的资源,并将其加载至内存。程序资源是指程序或应用程序使用的各种非代码元素,这些元素可以描述图像、音频、文本、图标、位图、对话框框架、字符串等等。编程时,加载菜单资源的关键代码如下:

HMODULE hModule = GetModuleHandle(NULL);HRSRC hResInfo = FindResource(hModule, MAKEINTRESOURCE(IDR_MYMENU), RT_RCDATA);DWORD dwSize = SizeofResource(hModule, hResInfo);HGLOBAL hResData = LoadResource(hModule, hResInfo);LPVOID lpRes = LockResource(hResData);

在使用GetModuleHandle指明包含资源的模块后,使用FindResource在PE文件格式中查找资源信息,成功后通过SizeofResource和LoadResource获取资源的大小,加载资源。

在PE文件格式中,资源可以通过可选头数据目录表的第3个成员IMAGE_DIRECTORY_ENTRY_RESOURCE访问,IMAGE_DIRECTORY_ENTRY_RESOURCE指向了PE资源的根目录,之后资源按照资源类型->资源标识符->资源页的多层目录结构来组织的,只有通过层层索引才能够进入相应的子目录找到正确的资源。其中 IMAGE_RESOURCE_DIRECTORY 中会指明后面数组的成员个数,IMAGE_RESOURCE_DIRECTORY_ENTRY 指向具体的下一层目录结构。


其中资源的类型可以是图标(Icon)、位图(Bitmap)、对话框(Dialog Box)、菜单(Menu)等。找到相应类型之后,再匹配具体资源标识符。如:

理解了资源的加载过程,我们扩充HeaderLessPE包含的结构,增加一个ResourceTableVA指向资源根目录。

typedef struct _HeaderLessPE{  PVOID  ImageBase;      // 镜像基址  DWORD  ImageSize;      // 镜像大小  DWORD  ImageEntryPoint;    // 入口函数  DWORD  ImportTableVA;      // 导入表  DWORD  RelocTableVA;       // 重定位表  DWORD  RelocTableSize;     // 重定位表大小  DWORD   ResourceTableVA     // 资源表  DWORD   ResourceTableSize   // 资源表大小  DWORD  SectionCount;       // 节区数量  HeaderLessSection Section[1];}HeaderLessPE, * PHeaderLessPE;

劫持所有涉及资源的API如GetModuleHandleW、FindResourceExW等,将进程的模块地址返回成HeaderLessPE的ImageBase基址,当需要FindResources的时候,再通过层级目录从查找HeaderLessPE的空间内查找资源,返回

HMODULE GetModuleHandleW( [in, optional] LPCWSTR lpModuleName );

参数传入为空时为获取当前进程句柄(基址),返回当前基址返回为HeaderLessPE的基址能让我们后续判断是否查找HeaderLessPE的资源

HRSRC FindResourceExW( [in, optional] HMODULE hModule, [in] LPCWSTR lpType, [in] LPCWSTR lpName, [in] WORD wLanguage );

第一个参数是模块基址,当地址匹配我们的HeaderLessPE基址时,我们通过HeaderLessPE结构成员ResourceTable获取资源的根目录,再根据lpType(类型)和lpName(名称)通过名称或ID查找具体的资源,找到后返回资源句柄,实际就是PIMAGE_RESOURCE_DATA_ENTRY, 

DWORD SizeofResource( [in, optional] HMODULE hModule, [in] HRSRC hResInfo );

SizeofResource通过资源句柄获取指定的资源大小,资源大小存储在PIMAGE_RESOURCE_DATA_ENTRY的的Size字段

HGLOBAL LoadResource( [in, optional] HMODULE hModule, [in] HRSRC hResInfo );

LoadResource通过资源句柄获取资源数据地址, 资源数据地址通过获取PIMAGE_RESOURCE_DATA_ENTRY的OffsetToData计算基地址而来。

实际要完成一个FileLess图形化程序还需要使用到注入技术,同时为了避免出现导入表依赖,需要先注入一个没有依赖的loader, loader程序再加载真正要运行的GUI程序。过程如下:

我们需要准备两个HeaderLessPE分别为loader和BrowsingHistoryView程序:

  1. 挂起启动c:\windows\system32\mspaint.exe,申请远程进程内存。

  2. 根据申请的地址,在本地修复loader程序的重定位和导入表。

  3. 写入mspaint.exe内存,修改权限,修改RIP指向loader的入口函数,恢复mspaint.exe主线程,完成远程注入HeaderLessPE。

  4. loader再次申请内存,加载BrowsingHistoryView程序的HeaderLessPE。

实现效果如下:

附录 项目开源链接

https://github.com/M01N-Team/HeaderLessPE

附录 参考文献

[1] https://github.com/strivexjun/MemoryModulePP.git

[2] https://doxygen.reactos.org/

[3] https://github.com/hasherezade/pe-sieve.git

[4] https://bbs.kanxue.com/thread-264956.htm

绿盟科技天元实验室专注于新型实战化攻防对抗技术研究。

研究目标包括:漏洞利用技术、防御绕过技术、攻击隐匿技术、攻击持久化技术等蓝军技术,以及攻击技战术、攻击框架的研究。涵盖Web安全、终端安全、AD安全、云安全等多个技术领域的攻击技术研究,以及工业互联网、车联网等业务场景的攻击技术研究。通过研究攻击对抗技术,从攻击视角提供识别风险的方法和手段,为威胁对抗提供决策支撑。

M01N Team公众号

聚焦高级攻防对抗热点技术

绿盟科技蓝军技术研究战队

官方攻防交流群

网络安全一手资讯

攻防技术答疑解惑

扫码加好友即可拉群


文章来源: http://mp.weixin.qq.com/s?__biz=MzkyMTI0NjA3OA==&mid=2247492342&idx=1&sn=f3e7bd34d73946e294756cce75181c83&chksm=c18422e7f6f3abf168a3c11a48bee1778dc67a5e7f4e1a02fc0461af0bbe0f18476d7215194e&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh