立即系统软件调用(Direct System Call)早已是现阶段流行的绕过Ring3层AVEDR沙盒的常见方式,为了解把握该技术性,小编近期对其开展了科学研究学习培训,文中融合近期看的各种各样blog及其碰到难题,小结梳理出一种相对性较为友善且通用性的Syscall方式。
请参照[汉语翻译]蓝队战略:融合立即系统软件调用和sRDI来绕过AV / EDR
AV/EDR/Sandbox等一般根据Hook ntdll.dll(inline hook)的重要函数,做到对程序流程调用链的监管。在 Windows NT后,客户态API最终根据syscall命令调用到核心态。
依据ntdll.dll 反汇编能够获知,其ntdll.dll的各种各样NT/ZW类函数完成汇编指令以下
比如根据SYSCALL方式卸载掉HOOK完成绕过安全软件开展LSASS过程dump的Dumpert新项目中,其syscall.asm界定为
提早依据表,融合RtlGetVersion函数,大批量生产汇编代码,实际能够参照
该专用工具在github上面有贴近600的Star,最终转化成的选编实例以下:
根据搜集系统结构的调用号,融合系统版本,开展标准分辨,最终实行syscall
该方式优势:
可以绕过关键函数监管,应该是最开始的一代Direct System Call
该方式缺陷
转化成编码比较松垮;
因为系统软件号所有写死,不可以适用后边公布的全新Windows系统软件
全文参照
总体基本原理是载入ntdll.dll镜像系统,根据PE文档载入到导出来函数的代码段,随后利用VirtualAlloc将代码段置放在运行内存中,最终开展函数表针调用。
该方式优势:
根据载入ntdll.dll的具体编码方式,将ntdll的真正编码开展调用,防止ntdll.dll已被HOOK;
其他的函数还可以参照,非常好的一种绕过HOOK的方式。
该方式缺陷:
编码中仍然必须VirtualAlloc等函数开展运行内存的可写应写可实行申请办理,这些函数早已被AV/EDR监管。
该方式实质是以硬盘上载入真正的系统软件函数完成,利用SHELLCODE载入的方式,开展真正函数调用,该方式也是绕过Ring3 Hook较为合理的方式(后边还有机会会专业共享一下客户态的Hook绕过,期待大伙儿不断关心Cloud-Penetrating Arrow Lab)。
融合所述二种方式,能够试着根据方式二从ntdll.dll中载入真正的函数完成,利用SYSCALL独有的特点,寻找系统软件版本信息,随后根据将系统软件版本信息传送到准备充分很大SYSCALL编码中,以完成动态性的SYSCALL调用。
根据NTDLL.DLL中获得导出来函数代码段,具体步骤有二种方式
方式一:根据PEB的方式载入早已载入函数详细地址,其编码以下:
方式二:根据读取文件,开展PE格式文件变换,载入到回应的函数详细地址。
根据syscall选编调用特点,从函数底单处逐渐载入到系统软件调用号。因为当今系统软件上早已存有AV/EDR,从PEB载入的方式函数早已被HOOK,小编因为应用vm虚拟机(Parallels Desktop)的原因,其NtQuerySystemTime早已被vm虚拟机Agent给Hook了,其函数代码段运行内存如下图:
一般HOOK编码均是在函数起止地区添加调节命令,因而能够简易的试着运行内存配对特点,获取到系统软件调用号。
#define NOT_FOUND_SYSCALL_ID -1
#define IS_NOT_FUND(x) (x == NOT_FOUND_SYSCALL_ID)
unsigned char SYS_CALL_START_MAGIC[]={
0x4c, 0x9a, 0xd1, 0xb8
};
#define SYS_CALL_START_MAGIC_LENGTH 4
#define MAX_SEARCH_LENGTH 24
DWORD MatchSyscallId(BYTE* pData)
{
// 根据运行内存检索的方式绕过HOOK
// HOOK一般会在函数逐渐处插进调节命令,根据运行内存检索的方式搜索到真正的函数部位,并获取SyscallId
DWORD syscallId = NOT_FOUND_SYSCALL_ID;
for (int item = 0; item < MAX_SEARCH_LENGTH; item ){
if (memcmp((pData item), &SYS_CALL_START_MAGIC, SYS_CALL_START_MAGIC_LENGTH) == 0){
memcpy(&syscallId, (pData item 4), sizeof(DWORD));
break;
}
}
return syscallId;
}
界定proc.asm选编调用
界定2个函数和一个自变量,SetSyscallId函数系统对调用号开展取值,DynamicSyscall函数出示统一的Syscall调用。
界定asm文档中依靠的外界自变量及其引进DynamicSyscall函数
extern "C"
{
VOID SetSyscallId(DWORD syscallId);
NTSTATUS WINAPI DynamicSyscall();
}
从ntdll.dll中依据函数名字动态性获得syscalId
试着应用NtCreateFile的方式创建文件,编码调用以下
该方式根据选编 自变量设定 动态性载入NTDLL中系统软件版本信息完成动态性系统软件立即调用。
有以下优势:
兼容模式强,不用将系统软件调用号写死,兼容模式能够有确保;
根据asm完成代码段,根据更改值开展函数调用;
从早已载入的DLL中获得系统软件号,而且考虑到了早已被简易HOOK的情景。
待提升点:
因为汇编指令中静态变量,现阶段进程不安全,中后期能够根据引进外界函数的方式开展上锁或是客户态自主完成;
函数名字的方式可应用函数Hash的方式,假如自身搞专用工具,能够自定一套FastHash优化算法。