仅依靠现有的操作系统文件就可以实现持久性。在 Windows 上,有很多 LOLBins(living off the land binaries),比如 Powershell。注册表可用于存储。从技术上讲,注册表存储在磁盘上,因此这是一种 II 类无文件攻击。
Payload.exe:本机可执行文件,显示 MessageBox。目标是让此可执行文件在启动时运行(持久性),并且永远不会将其写入文件系统。
此外,脚本或其他文件也不能写入文件系统。
第 1 阶段:安装程序
安装程序 (LivingOffTheLand.exe) 是本机可执行文件。它可以正常启动(双击 EXE 文件),也可以在内存中执行,即通过 RCE 漏洞执行。正常执行很可能会被发现,而内存执行更有可能逃避 AV 攻击。
安装人员的工作:
-
将 Injector.exe 写入注册表
-
将此内联powershell 脚本写入 HKCU...Run 以实现持久性
-
运行 powershell.exe 立即执行
mshta "javascript:close(new ActiveXObject('WScript.Shell').run('powershell "[Reflection.Assembly]::Load([Microsoft.Win32.Registry]::CurrentUser.OpenSubKey(\"Software\\Microsoft\\Internet Explorer\").GetValue($Null)).EntryPoint.Invoke(0,$Null)"',0))"
这是上面这一行的格式化版本:
mshta "
javascript:close(
new ActiveXObject('WScript.Shell')
.run('
powershell "
[Reflection.Assembly]::Load([Microsoft.Win32.Registry]::CurrentUser
.OpenSubKey(\"Software\\Microsoft\\Internet Explorer\")
.GetValue($Null))
.EntryPoint
.Invoke(0,$Null)
"
',0)
)
"
此启动命令写入 HKCU...Run 键。它可能只有 260 个字符(MAX_PATH)。Powershell.exe 从注册表加载 Injector.exe 并在内存中执行它。Injector.exe 必须用 C# 编写!由于 MAX_PATH 限制,这里只能执行简单的Assembly.Load().EntryPoint.Invoke()。
mshta.exe 不是必需的。但如果没有它,powershell 窗口会短暂可见。JavaScript 允许使用 SW_HIDE 启动 powershell。
因为 mshta 正在包装 powershell,而 powershell 又包装 C#,所以需要多层字符串转义
为了伪装注册表值,需要使用一个空嵌入字符。注册表值的名称以 NULL 字符开头,后跟实际名称。由于 WinAPI 使用以空字符结尾的字符串,因此该值的名称在技术上等于 NULL。但是,由于值的内容有效,因此脚本仍在启动时执行。注册表编辑器无法显示此值,使用 WinAPI 读取注册表的任何程序也无法显示此值。需要使用本机 API,它使用 UNICODE_STRING 允许读取和写入嵌入的 NULL 字符。
第 2 阶段:喷射器
Injector.exe 是一个存储在注册表值中的 C# 可执行文件。powershell 内联脚本通过 Assembly.Load() 加载此可执行文件并调用其主入口点。
然后,注入器继续从其自己的可执行资源加载实际的 Payload.exe。然后使用进程挖空技术 (RunPE) 注入有效载荷。此注入技术通过创建合法 Windows 二进制文件(例如 svchost.exe)的进程来工作。进程在挂起状态下创建,之后其进程内存被取消映射并替换为有效载荷文件。线程上下文设置为在有效载荷的入口点继续运行,然后恢复主线程。
第 3 阶段:有效载荷
因此,TaskMgr 中可以看到一个新进程
(C:WindowsSystem32svchost.exe),但它实际上是 Payload.exe。如果不付出很大努力,就无法将此进程与同一文件的合法实例区分开来。大多数 32 位 Windows 二进制文件可用于 32 位可执行文件的进程挖空。
原文始发于微信公众号(TtTeam):持久性无文件攻击
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论