内网渗透之令牌窃取

原文链接: https://mp.weixin.qq.com/s?__biz=MzkwODc1NTgyMg==&mid=2247487314&idx=1&sn=ce3f14deb4e79dd84f77a86601024a63

内网渗透之令牌窃取

hangchuanin 蓝云Sec 2025-07-11 16:01

原文链接:
https://xz.aliyun.com/news/11427

0x00

在内网渗透中令牌窃取通常用于从Administrator权限提升到System权限或者用于获取trustedinstaller等权限,令牌窃取通过Metasploit框架提供的载荷很容易实现,在学习了Windows访问控制的内容之后,可以自己实现一个令牌窃取的工具,比如 JCTokenUtil、SharpToken、incognito,这篇文章是笔者学习令牌窃取的原理和实现的产出。

0x01 令牌列举

令牌列举就是列举本地计算机上所有的访问令牌,

NtQuerySystemInformation

API是用来检索指定的系统信息的,

NtQuerySystemInformation

API的原型如下

__kernel_entryNTSTATUSNtQuerySystemInformation([in]SYSTEM_INFORMATION_CLASSSystemInformationClass,[in,out]PVOIDSystemInformation,[in]ULONGSystemInformationLength,[out,optional]PULONGReturnLength);
SystemInformationClass

参数标识要检索的系统信息,它是

SYSTEM_INFORMATION_CLASS

中枚举的值之一。

SYSTEM_INFORMATION_CLASS

的原型如下

typedefenum_SYSTEM_INFORMATION_CLASS{SystemBasicInformation,SystemProcessorInformation,SystemPerformanceInformation,SystemTimeOfDayInformation,SystemPathInformation,SystemProcessInformation,SystemCallCountInformation,SystemDeviceInformation,SystemProcessorPerformanceInformation,SystemFlagsInformation,SystemCallTimeInformation,SystemModuleInformation,SystemLocksInformation,SystemStackTraceInformation,SystemPagedPoolInformation,SystemNonPagedPoolInformation,SystemHandleInformation,SystemObjectInformation,SystemPageFileInformation,SystemVdmInstemulInformation,SystemVdmBopInformation,SystemFileCacheInformation,SystemPoolTagInformation,SystemInterruptInformation,SystemDpcBehaviorInformation,SystemFullMemoryInformation,SystemLoadGdiDriverInformation,SystemUnloadGdiDriverInformation,SystemTimeAdjustmentInformation,SystemSummaryMemoryInformation,SystemNextEventIdInformation,SystemEventIdsInformation,SystemCrashDumpInformation,SystemExceptionInformation,SystemCrashDumpStateInformation,SystemKernelDebuggerInformation,SystemContextSwitchInformation,SystemRegistryQuotaInformation,SystemExtendServiceTableInformation,SystemPrioritySeperation,SystemPlugPlayBusInformation,SystemDockInformation,SystemPowerInformation,SystemProcessorSpeedInformation,SystemCurrentTimeZoneInformation,SystemLookasideInformation}SYSTEM_INFORMATION_CLASS,*PSYSTEM_INFORMATION_CLASS;

当枚举值为

SystemProcessInformation

时标识要检索计算机上的所有进程信息,这时

SystemInformation

参数指向检索结果的第一个进程的

SYSTEM_PROCESS_INFORMATION

结构,

SYSTEM_PROCESS_INFORMATION

的原型如下

typedefstruct_SYSTEM_PROCESS_INFORMATION{ULONGNextEntryOffset;ULONGNumberOfThreads;BYTEReserved1[48];UNICODE_STRINGImageName;KPRIORITYBasePriority;HANDLEUniqueProcessId;PVOIDReserved2;ULONGHandleCount;ULONGSessionId;PVOIDReserved3;SIZE_TPeakVirtualSize;SIZE_TVirtualSize;ULONGReserved4;SIZE_TPeakWorkingSetSize;SIZE_TWorkingSetSize;PVOIDReserved5;SIZE_TQuotaPagedPoolUsage;PVOIDReserved6;SIZE_TQuotaNonPagedPoolUsage;SIZE_TPagefileUsage;SIZE_TPeakPagefileUsage;SIZE_TPrivatePageCount;LARGE_INTEGERReserved7[6];}SYSTEM_PROCESS_INFORMATION;
NumberOfThreads

成员指示进程拥有的线程数,

UniqueProcessId

成员指示进程的唯一进程ID,

HandleCount

成员指示进程拥有的句柄数,

NextEntryOffset

指示下一个

SYSTEM_PROCESS_INFORMATION

结构距离当前结构的偏移,最后一个

SYSTEM_PROCESS_INFORMATION

结构的

NextEntryOffset

成员值为0。

SYSTEM_PROCESS_INFORMATION

结构后紧跟若干个

SYSTEM_THREAD_INFORMATION

结构表示此进程的若干个线程。

通过

NtQuerySystemInformation

API获取到计算机上所有的进程后,可以通过

DuplicateHandle

函数获取每个进程拥有的所有句柄,然后用

NtQueryObject

函数来检索句柄对应的对象类型。

NtQueryObject

函数原型如下

__kernel_entryNTSYSCALLAPINTSTATUSNtQueryObject([in,optional]HANDLEHandle,//要检索的句柄[in]OBJECT_INFORMATION_CLASSObjectInformationClass,[out,optional]PVOIDObjectInformation,[in]ULONGObjectInformationLength,[out,optional]PULONGReturnLength);
OBJECT_INFORMATION_CLASS

是一个枚举类型,原型如下

typedefenum_OBJECT_INFORMATION_CLASS{ObjectBasicInformation,ObjectTypeInformation}OBJECT_INFORMATION_CLASS;

当指定

ObjectInformationClass

成员为

ObjectTypeInformation

枚举值时,

ObjectInformation

参数返回

PUBLIC_OBJECT_TYPE_INFORMATION

结构,

PUBLIC_OBJECT_TYPE_INFORMATION

结构原型如下

typedefstruct__PUBLIC_OBJECT_TYPE_INFORMATION{UNICODE_STRINGTypeName;ULONGReserved[22];// reserved for internal use}PUBLIC_OBJECT_TYPE_INFORMATION,*PPUBLIC_OBJECT_TYPE_INFORMATION;
TypeName

成员表示对象的类型字符串,当对象是访问令牌时该值为

Token

,通过控制该值为

Token

就可以过滤出所有访问令牌的句柄。

注意的是,工具获取的是访问令牌模拟级别大于

SecurityImpersonation

模拟级别的访问令牌,通过

GetTokenInformation

函数获取访问令牌的

TokenImpersonationLevel

成员来确定访问令牌的模拟级别。

内网渗透之令牌窃取

通过上面的步骤就可以获取到每个进程拥有的访问令牌句柄,但是上面检索的访问令牌不包括每个进程本身的访问令牌,所以需要再通过

OpenProcessToken

函数来获取进程本身的令牌句柄。

0x02 窃取令牌来执行命令

比如我们想窃取NT AUTHORITY\SYSTEM账户的令牌来执行命令,我们需要先找到NT AUTHORITY\SYSTEM账户的令牌。这个很简单,通过

GetTokenInformation

函数获取到令牌的用户SID,然后用

LookupAccountSidA

函数将SID转换为对应的账户名即可。

找到NT AUTHORITY\SYSTEM账户的令牌后,需要把令牌的

TokenSessionId

改为当前进程令牌的

TokenSessionId

,调用

SetTokenInformation

函数来设置即可。注意更改令牌的

TokenSessionId

需要SeTcbPrivilege特权。

内网渗透之令牌窃取

最后调用

CreateProcessAsUserA

函数来执行命令,

CreateProcessAsUserA

函数的原型如下

BOOLCreateProcessAsUserA([in,optional]HANDLEhToken,[in,optional]LPCSTRlpApplicationName,[in,out,optional]LPSTRlpCommandLine,[in,optional]LPSECURITY_ATTRIBUTESlpProcessAttributes,[in,optional]LPSECURITY_ATTRIBUTESlpThreadAttributes,[in]BOOLbInheritHandles,[in]DWORDdwCreationFlags,[in,optional]LPVOIDlpEnvironment,[in,optional]LPCSTRlpCurrentDirectory,[in]LPSTARTUPINFOAlpStartupInfo,[out]LPPROCESS_INFORMATIONlpProcessInformation);
lpCommandLine

参数传递要执行的命令,

hToken

参数传递NT AUTHORITY\SYSTEM账户的令牌。

由于更改令牌的

TokenSessionId

值需要SeTcbPrivilege特权,

CreateProcessAsUserA

函数的调用需要SE_ASSIGNPRIMARYTOKEN_NAME特权。而NT AUTHORITY\SYSTEM账户拥有这两个特权,所以在更改令牌的

TokenSessionId

值和调用

CreateProcessAsUserA

函数之前先调用

ImpersonateLoggedOnUser

函数模拟NT AUTHORITY\SYSTEM账户。

内网渗透之令牌窃取

0x03 为什么低权限用户无法窃取令牌

熟悉令牌窃取的应该都知道一般普通用户是无法窃取令牌来执行命令的,这就导致令牌窃取只能用来从

Administrator

权限提升到

System

权限或

System

权限到

trustedinstaller

权限等。

出现这种情况的原因之一是普通用户无法获取到

System

Administrator

等账户的令牌,管理员账户获取到的令牌有730个

内网渗透之令牌窃取

而普通账户获取到的令牌只有345个

内网渗透之令牌窃取

我把普通账户获取到的令牌都down下来后发现此普通账户获取到的令牌用户都是其本身,没有其它账户存在。

账户能获取到多少令牌,取决于令牌的安全描述符和完整性级别是否允许账户对令牌的请求。

蓝云Sec公众号公开交流群,欢迎大家加入!

图片