In this example, I launched mspaint.exe from windbg.
C> windbg mspaint.exe
In the middle of the debugging, let's say I want to adjust one of privileges for the mspaint process.
To check current privileges status, !token command can be used.
0:008> !token -n Thread is not impersonating. Using process token... TS Session ID: 0x1 Privs: 00 0x000000005 SeIncreaseQuotaPrivilege Attributes - ...... 11 0x000000013 SeShutdownPrivilege Attributes - 12 0x000000014 SeDebugPrivilege Attributes - Enabled 13 0x000000016 SeSystemEnvironmentPrivilege Attributes - 14 0x000000017 SeChangeNotifyPrivilege Attributes - Enabled Default 15 0x000000018 SeRemoteShutdownPrivilege Attributes - 16 0x000000019 SeUndockPrivilege Attributes - 17 0x00000001c SeManageVolumePrivilege Attributes - 18 0x00000001d SeImpersonatePrivilege Attributes - Enabled Default 19 0x00000001e SeCreateGlobalPrivilege Attributes - Enabled Default Auth ID: 0:4d37b Impersonation Level: Anonymous TokenType: Primary Is restricted token: no.
Here, let's try to enable SeUndockPrivilege (0x19). To check current registers, r command is used. It is DbgBreak state at this point.
0:008> r eax=7ffd6000 ebx=00000000 ecx=00000000 edx=77add23d esi=00000000 edi=00000000 eip=77a73540 esp=026ef9ec ebp=026efa18 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 ntdll!DbgBreakPoint: 77a73540 cc int 3
Now in order to call RtlAdjustPrivilege() function in NTDLL.DLL, we first manipulate thread stack manually.
NTSTATUS RtlAdjustPrivilege ( ULONG Privilege, BOOLEAN Enable, BOOLEAN CurrentThread, PBOOLEAN Enabled )
Since RtlAdjustPrivilege() API has 4 parameters, 4 parameter values should be pushed into the stack from 4th parameter to 1st parameter (due to calling convention). ESP points to current stack location. 4th parameter is located at ESP-8 (since 4th parameter is output pointer type, it is pointing to another memory address; in this case, ESP-4 memory address), 3rd parameter is at ESP-C, and so on. Once 4 parameters are added into stack, return address should be added. Since we want to return back to current point, the example sets ESP-18 to . (which means current address).
0:008> ed esp-4 0 0:008> ed esp-8 @esp-4 0:008> ed esp-c 0 0:008> ed esp-10 1 0:008> ed esp-14 19 0:008> ed esp-18 . 0:008> resp=@esp-18 0:008> r $ip=ntdll!RtlAdjustPrivilege
Now I set stack pointer (esp) to ESP-18 and set instruction pointer to ntdll!RtlAdjustPrivilege function. So all registers are set to go. Since current execution pointer is set to ntdll!RtlAdjustPrivilege, if we use 'uf .' command, WinDBG will show the whole RtlAdjustPrivilege function in assembly language.
0:008> uf . ntdll!RtlAdjustPrivilege+0x9d: 77a45414 8b45e8 mov eax,dword ptr [ebp-18h] 77a45417 d1e8 shr eax,1 77a45419 2401 and al,1 77a4541b e9b45a0000 jmp ntdll!RtlAdjustPrivilege+0xa4 (77a4aed4) .....
Now, to execute the RtlAdjustPrivilege function, run 'gu' command. gu command runs until the current function is complete.
0:008> gu (16a0.ec0): Break instruction exception - code 80000003 (first chance) eax=00000000 ebx=00000000 ecx=5ef2406b edx=77a864f4 esi=00000000 edi=00000000 eip=77a73540 esp=026ef9e8 ebp=026efa18 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 ntdll!DbgBreakPoint: 77a73540 cc int 3 0:008> r esp=@esp+4 0:008> r eax=00000000 ebx=00000000 ecx=5ef2406b edx=77a864f4 esi=00000000 edi=00000000 eip=77a73540 esp=026ef9ec ebp=026efa18 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 ntdll!DbgBreakPoint: 77a73540 cc int 3
Once the function is successfully run, we can check new privilege list by using !token command again. But how do we know the run is successful? Return value (NTSTATUS for the function) can be checked by looking at EAX register. Since it is 0, we can figure out that the function execution was successful.
0:008> !token -n Thread is not impersonating. Using process token... TS Session ID: 0x1 ...... Privs: 00 0x000000005 SeIncreaseQuotaPrivilege Attributes - ....... 12 0x000000014 SeDebugPrivilege Attributes - Enabled 13 0x000000016 SeSystemEnvironmentPrivilege Attributes - 14 0x000000017 SeChangeNotifyPrivilege Attributes - Enabled Default 15 0x000000018 SeRemoteShutdownPrivilege Attributes - 16 0x000000019 SeUndockPrivilege Attributes - Enabled 17 0x00000001c SeManageVolumePrivilege Attributes - 18 0x00000001d SeImpersonatePrivilege Attributes - Enabled Default 19 0x00000001e SeCreateGlobalPrivilege Attributes - Enabled Default
As you can see, SeUndockPrivilege is now enabled...
NOTE: setting SeUndockPrivilege might not be useful in real world, but enabling some other privileges such as TCB privilege or DEBUG privilege in the debugger might be useful in some situations.
No comments:
Post a Comment