基础知识
反恶意软件扫描接口简称\\”AMSI\\”,它是微软在Windows中阻止危险脚本执行的解决方案,AMSI理论上是一个好的解决方案,它通过分析正在执行的脚本然后根据是否发现恶意内容来阻止或允许,然而正如我们稍后将讨论的那样,它有一些基本的实现缺陷,使得我们可以绕过检测
从下图中您可以看到AMSI阻止了字符串\\”Invoke-Mimikatz\\”,尽管该字符串不在恶意上下文中,但它仍然被检测到,那么这究竟是如何运作的呢?微软通过将amsi.dll加载到创建的每个进程中,这些进程会导出一些功能供防病毒和EDR使用,以及Windows Defender
查看amsi.dll中的导出结果发现一个看起来很有趣的函数AmsiScanBuffer,如果你要做更多和更加深入的研究可以查看MSDN官方关于AmsiScanBuffer 的介绍页面,其中包含许多关于AMSI和函数的有用信息
https://docs.microsoft.com/en-us/windows/win32/api/amsi/nf-amsi-amsiscanbuffer
在AmsiScanBuffer的最后一个参数中我们看到有一个指向名为result的枚举的指针,我们可以确定我们应该读取结果以获得AmsiScanBuffer的结果,无论结果包含什么都将决定我们的脚本执行是否是恶意的
理论上如果我们可以操纵结果是什么(即AMSI_RESULT_CLEAN),然后我们应该能够对蓝队和EDR隐藏恶意脚本执行
函数hook
函数hook是一种在函数被调用之前对其进行控制的方法,这使我们作为攻击者可以做多种事情,例如:记录参数、允许/阻止功能的执行、覆盖传入函数的参数、并决定要返回的值,考虑到这一点我们需要找出hook AmsiScanBuffer的最佳方法,微软提供了detours库,这是一个使用trampoline hook方法的函数hook库
Trampoline钩子的工作原理是存储一个目标函数的副本,然后用一个jmp指令覆盖目标函数的开始,这个跳转将我们发送到我们作为攻击者控制的函数,因此得名trampoline hook
#include <iostream>
#include <Windows.h>
#include <detours.h>
static int(WINAPI* OriginalMessageBox)(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) = MessageBox;
int WINAPI _MessageBox(HWND hWnd, LPCSTR lpText, LPCTSTR lpCaption, UINT uType) {
return OriginalMessageBox(NULL, L\\\"We\\\'ve used detours to hook MessageBox\\\", L\\\"Hooked Window\\\", 0);
}
int main() {
std::cout << \\\"[+] Hooking MessageBox\\\" << std::endl;
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)OriginalMessageBox, _MessageBox);
DetourTransactionCommit();
std::cout << \\\"[+] Message Box Hooked\\\" << std::endl;
MessageBox(NULL, L\\\"My Message\\\", L\\\"My Caption\\\", 0);
std::cout << \\\"[+] Unhooking MessageBox\\\" << std::endl;
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)OriginalMessageBox, _MessageBox);
DetourTransactionCommit();
std::cout << \\\"[+] Message Box Unhooked\\\" << std::endl;
}
上面的代码片段显示了如何使用detours库来挂钩MessageBox函数并覆盖用户参数,有了这些知识我们基本上能够控制AmsiScanBuffer函数的所有方面,因此现在我们需要设置一个基本项目,该项目接收一个字符串,然后使用AmsiScanBuffer扫描该字符串以查找恶意内容:
#include <iostream>
#include <Windows.h>
#include <amsi.h>
#include <system_error>
#pragma comment(lib, \\\"amsi.lib\\\")
#define EICAR \\\"X5O!P%@AP[4\\\\\\\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*\\\"
const char* GetResultDescription(HRESULT hRes) {
const char* description;
switch (hRes)
{
case AMSI_RESULT_CLEAN:
description = \\\"AMSI_RESULT_CLEAN\\\";
break;
case AMSI_RESULT_NOT_DETECTED:
description = \\\"AMSI_RESULT_NOT_DETECTED\\\";
break;
case AMSI_RESULT_BLOCKED_BY_ADMIN_START:
description = \\\"AMSI_RESULT_BLOCKED_BY_ADMIN_START\\\";
break;
case AMSI_RESULT_BLOCKED_BY_ADMIN_
原创文章,作者:七芒星实验室,如若转载,请注明出处:https://www.sudun.com/ask/34377.html