导语:mavinject.exe是一个合法的Windows组件,它可能被恶意滥用,而不仅仅局限于DLL注入。

一、前言

一直以来,攻击者都滥用mavinject.exe进行DLL注入。我第一次是从这个tweet中听说mavinject,后来当Casey Smith开始在tweet上发表实际滥用案例时,我的兴趣再度被激发。然而,我一度失去了兴趣,因为mavinject不允许执行任意未签名的代码(强制执行应用程序白名单)。最近,我写了一些脚本,用于识别与通常恶意软件使用相同API(CreateRemoteThread,VirtualAllocEx等)的已签名应用程序,mavinject.exe脱颖而出(因为它使用这些API中的每一个)。这重新激起了我对mavinject的兴趣,尽管我无法完全滥用mavinject来实现任意代码执行,但我希望这篇文章能够对其他人的进一步研究有一定的参考价值。除此之外,我想提供一些基本的mavinject检测建议。

在我扫描的可疑API中,mavinject使用了恶意软件通常使用的与注入相关的函数:

· VirtualProtectEx

· CreateRemoteThread

· VirtualAllocEx

· WriteProcessMemory

尽管mavinject.exe不是恶意软件,但我想调查它是否可被恶意滥用,而不仅仅局限于DLL注入。

二、背景知识

Mavinject是一个合法的Windows组件,可以在任何正在运行的进程中执行任意代码注入。由于这是Windows上的一个常见组件,因此可以利用它来执行living-off-the-land攻击。

可在系统中多个不同的位置上找到Mavinject:

"C:\Program Files\Common Files\microsoft shared\ClickToRun\MavInject32.exe"

System32 

SysWOW64

该应用程序是Microsoft Application Virtualization(App-V)的一部分。其文件描述为:

FileDescription:  Microsoft Application Virtualization Injector

常见的使用方式为:

mavinject <PID> /INJECTRUNNING

使用此命令行运行的可执行文件查询以下注册表项:

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\AppV\Subsystem

其相应的值是:

ValueName: Modules - ValueData: C:\Windows\System32\AppVEntSubsystems32.dllValueName: Modules64 - ValueData: C:\Windows\System32\AppVEntSubsystems64.dll

根据目标进程体系结构(32位或64位),它会注入其中一个DLL。

经过进一步分析,通过以下方式滥用相同的机制,可以在任意运行的进程中注入dll:

MavInject.exe <PID> /INJECTRUNNING <PATH DLL>

三、mavinject执行DLL注入

通常滥用mavinject的方式如下所示:

mavinject.exe PROCESSID /INJECTRUNNING Path\To\Payload.dll

当用于DLL注入时,mavinject执行以下操作:

1.调用OpenProcess获取目标进程的句柄。它请求以下访问:0x10043A(SYNCHRONIZE | PROCESS_QUERY_INFORMATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD)。从检测的角度来看,对于那些熟悉Sysmon的人来说,构建ProcessAccess规则很合理,但请注意请求的访问与GrantedAccess字段并不是一定匹配。此外,我不了解此进程访问的唯一性,但通过让Sysmon持续捕获ProcessAccess事件,就可以很容易的发现。

2.调用VirtualAllocEx和WriteProcessMemory将DLL路径写入目标进程。该字符串将用作LoadLibraryW的参数。

3.调用CreateRemoteThread获取目标进程,使用在步骤#2中写入的路径为参数调用LoadLibraryW。

这是一个很熟悉的过程,因为这种注入技术已经存在并且被广泛使用(documented)。

四、mavinject执行Import Descriptor注入

在IDA中逆向mavinject,发现命令行参数/HMODULE=0x非常显眼,因为在任何地方都没有记录。最终我发现它使用Detours UpdateImports32/64函数的一个变体预先导入了一个导入表(IMAGE_IMPORT_DESCRIPTOR结构)以及所选择的DLL名称和序号。/HMODULE= 0参数使用方法如下所示:

mavinject.exe 4964 /HMODULE=0x013C0000 foo.dll 4

在本例中,32位的mavinject注入一个导入表,它将foo.dll中序号为4的函数“导出”为32位进程(PID 4964),并将其导入基址为0x013C0000(powershell.exe基地址)的模块中。值得一提的是是,foo.dll没有导出一个序号为4的函数。这只是一个虚构的例子,强调了可以注入任意字符串和序号。注入导入表添加后,可以使用WinDbg来验证:

0:009> !dh -i 013C0000
  _IMAGE_IMPORT_DESCRIPTOR 04860000
    foo.dll
              048600D0 Import Address Table
              048600C8 Import Name Table
                     0 time date stamp
                     0 Index of first forwarder reference
80000004      Ordinal     4

在上面的输出中,80000004中的8表示IMAGE_ORDINAL_FLAG32,它告诉Windows Loader通过序号而不是名称导入函数。有关导入表的更多信息,请阅读这篇文章this amazing article

我发现这个功能非常有趣,因为理想情况下,能够以某种方式重定向导入地址表(IAT)。在实践中,我无法实现这一目标,我不相信使用mavinject自己可以用来实现任意导入表钩子。可能存在一些滥用混合导入表或者其他AppV相关DLL的注入,比如AppVEntSubsystems [32 | 64] .dll,但我没有深入研究。

但是,我确实发现了一个有趣的bug,即mavinject如何将IMAGE_ORDINAL_FLAG32用于命令行提供的序号。正常情况下,IMAGE_ORDINAL_FLAG32应该“与”(即掩码)序号,而不是“加”。mavinject在命令行接受一个DWORD值作为序号。然后代码将IMAGE_ORDINAL_FLAG32(0x8000000)加到指定的值中,这就会导致溢出。如果发生溢出,那么读取导入表的代码将按名称而不是序号来导入。为了突出显示溢出,使用导入表导入This program cannot be run in DOS mode(用于突出显示该bug的伪造“导入”)——PE头的偏移0x4E(0x80000000 + 0x4E == 2147483726 ,这将导致溢出并返回到0x4E):

mavinject.exe 4964 /HMODULE=0x013C0000 foobar.dll 2147483726在执行导入表格添加时,WinDbg确认导入列表的溢出导致的冲突:

0:009> !dh -i 013C0000
  _IMAGE_IMPORT_DESCRIPTOR 04870000
    foobar.dll
              048700F8 Import Address Table
              048700F0 Import Name Table
                     0 time date stamp
                     0 Index of first forwarder reference
0000004E 6854 is program cannot be run in DOS mode.

我还没有找到一种有效的方式来滥用这一bug,但我认为它很有趣。此外,UpdateImports32/64函数的一个显著副作用是将导入表模块的PE校验和设置为零。这是值得注意的,因为Cobalt Strike Beacon等恶意软件和工具可以清除/更新/修改PE校验和。

另一个mavinject.exe支持的命令行如下:

mavinject.exe PROCESSID DLL_FULL_PATH_OR_FILENAME

该选项类似于/HMODULE =0x,但是它将指定DLL中序号#1的导出导入到主进程模块。一个副作用是此方法从Microsoft Detours库中调用DetourCopyPayloadToProcess,并将主模块中PE头保存在内存的.detours节中。This article解释了.detours部分的用途。不过,似乎没有办法只使用mavinject从自定义钩子函数引入.detourssection。

最后,我还是无法将导入表注入作为有趣的(除了任意数据注入之外的)利用方法。尽管如此,我还在研究这一功能,希望它能激励一些人。为识别使用Detours库的已签名代码(因为库静态链接到代码中),需要获取所有模块的符号,然后在PDB文件中搜索Detours functions

五、mavinject滥用检测建议

· 捕获命令行日志,查找“INJECTRUNNING”。攻击者可以重命名可滥用的应用程序来逃避检测,因此不要将检测仅限于“mavinject.exe”。mavinject在执行DLL注入时需要使用“INJECTRUNNING”,因此这是很好的DLL注入检测的基础。

· 通常,要检测mavinject.exe,请不要忽略攻击者会重命名它。应当根据Version Info资源中的属性,而不是Description或OrginalFileName来构建检测。但是,攻击者可以修改这些字段,但如果这样做的话签名将失效。

· 以下是一组用于检测mavinject使用的Sysmon规则示例:

<ProcessCreate onmatch="include">
    <!-- Catch mavinject DLL injection -->
    <CommandLine condition="contains">INJECTRUNNING</CommandLine>
    <!-- Catch mavinject regardless of its filename and command line usage -->
    <!-- Note: an attacker can modify this field in the binary. It will render its signature invalid but it will also evade this rule. -->
    <Description condition="is">Microsoft Application Virtualization Injector</Description>
</ProcessCreate>
<CreateRemoteThread onmatch="include">
    <!-- Catch mavinject DLL injection or any other DLL injection where LoadLibraryW was called. May be FP prone. -->
    <StartFunction condition="is">LoadLibraryW</StartFunction>
</CreateRemoteThread>

六、总结

在撰写本文时,我希望能达到以下任一目的:

· 如果阅读本文前也对/HMODULE=0x命令行开关感兴趣,现在你已经无需自己去逆向此功能。

· 受到启发,可以利用mavinject和AppV函数调查Detours滥用行为,目前我对此一无所知,但我相信将来会有大量的滥用。

· 希望考虑一下写博客来介绍你的研究成果和方法,即便最终没有成功,也没有关系,毕竟,失败会产生灵感,直至最后的胜利。

源链接

Hacking more

...