检测的方法
Github项目 参考项目内的描述 大部分”免杀“基于各
种加密例如XOR AES来混淆shellcode使AV静态扫描失效 但这些加载器本质都是基于VirtualAlloc函数
申请内存 且在VirtualAllowc区域内执行代码 于是对此区域线程堆栈回溯(StackWalkEx函数)RWX
- 检查原理 内存区段是否存在M.Z标志 //private区域的内存并且是excute权限的code在加载dll
- 线程是否指向一个NOIMAGE内存
- 检测是否存在过期签名 过期证书 WinVerifyTrust API
Windows OS architecture
程序员通常不会重复发明轮子 所以基本函数都是从现有库中导入 例如
pintf()
使C语言 stdio.h
库中导入的 Windows开发人员一般会使用Win32 Api
,Api也可以导入程序中. win32 Api
具有文档记录 由几个库文件(DLL文件)组成 ,这些文件位于 C:\windows\system32\
文件夹中例如
kernel32.DLL
User32.DLL
Ntdll不是Win32 Api的一部分 也没有正式文档
kernel32.dll和user32.dll这种的底层函数就被包含在ntdll.dll中
ntdll.dll中的函数成对出现,分别以“Nt”和“Zw”开头,这种函数叫做Native API
User-Mode / Kernel-Mode
windows操作系统分为两种特权级别 R3 R0 特权分级是为了保护系统免受应用程序导致崩溃
windows系统上的所有应用程序均在R3 用户模式运行 内核和设备驱动程序以R0 内核模式运行
AV/EDR一般会在用户层直接hook关键的api 例如
virtualalloc
creatprocess
对调用此函数的应用进行jmp头部插入dll进行扫描用户模式下应用无法访问操作内核下的内存部分 内核补丁保护 且减少系统崩溃 AV/EDR一般会选择以R3用户模式下监视应用程序行为
用户模式最后一个调用实例为WindowsApi函数 一旦调用 会传参NTDLL到内核模式 AV/EDR就无法再继续监控 NTDLL单个功能成为Syscalls。
说白了利用从ntdll中读取到的系统调用号进行系统直接调用来绕过敏感API函数的hook。
Why should i care?
模拟攻击者 我们如何需要win32 api?
例如我们写入shellcode到进程 可以使用代码从文件kernel32.dll导入WriteProcessMemory 例子
[DLLImport("kernel32.dll",SetLastError = true)] static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
但大多数人常用PE-Loaders 我们希望尽长时间保留注入内存 避免磁盘留下痕迹 就不出现AVEvasion因此 有很多项目 都大量使用Windows API函数作为他们的模块 CreatRemoteThread GetProcAddress CreatTuread 在 kernel32.dll中
C# PE-Loader
Invoke-ReflectivePEInjection
不过Win32 Api函数包含的功能(kernel32.dll user32.dll)并没有直接转换为机器码 而是通过本地的NTDLL.dll映射到其他功能 例如
kernel32.dll→WriteProcessMemory→NTDLL.dll→NtProtectVirtualMemory→NtWriteVirtualMemory→NtProtectVirtualMemory
第一个
syscall
NtProtectVirtualMemory
目的是设置新的可写入进程权限第二个
NtWriteVirtualMemory
实际上时写入字节 第三个再次调用
NtProtectVirtualMemory
目的是恢复该进程旧的权限综上所述本机API
NTDLL.dll
是系统内核前最后一个实例。