625 lines
18 KiB
C
625 lines
18 KiB
C
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include "gflags.h"
|
|
|
|
#define VALID_SYSTEM_REGISTRY_FLAGS FLG_VALID_BITS ^ FLG_STOP_ON_HUNG_GUI
|
|
|
|
#define VALID_KERNEL_MODE_FLAGS FLG_VALID_BITS ^ (FLG_DEBUG_INITIAL_COMMAND | \
|
|
FLG_KERNEL_STACK_TRACE_DB | \
|
|
FLG_MAINTAIN_OBJECT_TYPELIST | \
|
|
FLG_ENABLE_CSRDEBUG)
|
|
|
|
#define VALID_IMAGE_FILE_NAME_FLAGS FLG_USERMODE_VALID_BITS
|
|
|
|
LONG APIENTRY MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LONG lParam);
|
|
|
|
BOOLEAN
|
|
EnableDebugPrivilege( VOID );
|
|
|
|
HWND hwndMain;
|
|
HKEY hKey;
|
|
DWORD InitialSetFlags;
|
|
DWORD LastSetFlags;
|
|
|
|
DWORD
|
|
GetSystemRegistryFlags( VOID )
|
|
{
|
|
DWORD cbKey;
|
|
DWORD GFlags;
|
|
DWORD type;
|
|
|
|
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
"SYSTEM\\CurrentControlSet\\Control\\Session Manager",
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
&hKey
|
|
) != ERROR_SUCCESS
|
|
) {
|
|
MessageBox( hwndMain, "Open Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager", MB_OK );
|
|
ExitProcess( 0 );
|
|
}
|
|
|
|
cbKey = sizeof( GFlags );
|
|
if (RegQueryValueEx( hKey,
|
|
"GlobalFlag",
|
|
0,
|
|
&type,
|
|
(LPBYTE)&GFlags,
|
|
&cbKey
|
|
) != ERROR_SUCCESS ||
|
|
type != REG_DWORD
|
|
) {
|
|
MessageBox( hwndMain, "Value Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\GlobalFlag", MB_OK );
|
|
RegCloseKey( hKey );
|
|
ExitProcess( 0 );
|
|
}
|
|
|
|
|
|
return GFlags;
|
|
}
|
|
|
|
BOOLEAN
|
|
SetSystemRegistryFlags(
|
|
DWORD GFlags
|
|
)
|
|
{
|
|
if (RegSetValueEx( hKey,
|
|
"GlobalFlag",
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&GFlags,
|
|
sizeof( GFlags )
|
|
) != ERROR_SUCCESS
|
|
) {
|
|
MessageBox( hwndMain, "Value Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\GlobalFlag", MB_OK );
|
|
RegCloseKey( hKey );
|
|
ExitProcess( 0 );
|
|
}
|
|
|
|
LastSetFlags = GFlags;
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD
|
|
GetKernelModeFlags( VOID )
|
|
{
|
|
NTSTATUS Status;
|
|
SYSTEM_FLAGS_INFORMATION SystemInformation;
|
|
|
|
Status = NtQuerySystemInformation( SystemFlagsInformation,
|
|
&SystemInformation,
|
|
sizeof( SystemInformation ),
|
|
NULL
|
|
);
|
|
if (!NT_SUCCESS( Status )) {
|
|
MessageBox( hwndMain, "Value Error", "Kernel Mode Flags", MB_OK );
|
|
ExitProcess( 0 );
|
|
}
|
|
|
|
return SystemInformation.Flags;
|
|
}
|
|
|
|
BOOLEAN
|
|
SetKernelModeFlags(
|
|
DWORD GFlags
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
SYSTEM_FLAGS_INFORMATION SystemInformation;
|
|
|
|
if (!EnableDebugPrivilege()) {
|
|
MessageBox( hwndMain, "Access Denied", "Unable to enable debug privilege", MB_OK );
|
|
ExitProcess( 0 );
|
|
}
|
|
|
|
SystemInformation.Flags = GFlags;
|
|
Status = NtSetSystemInformation( SystemFlagsInformation,
|
|
&SystemInformation,
|
|
sizeof( SystemInformation )
|
|
);
|
|
if (!NT_SUCCESS( Status )) {
|
|
MessageBox( hwndMain, "Value Error", "Kernel Mode Flags", MB_OK );
|
|
ExitProcess( 0 );
|
|
}
|
|
|
|
LastSetFlags = GFlags;
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD
|
|
GetImageFileNameFlags(
|
|
PCHAR ImageFileName
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
CHAR Buffer[ MAX_PATH ];
|
|
CHAR RegKey[ MAX_PATH ];
|
|
DWORD Length = MAX_PATH;
|
|
DWORD GFlags;
|
|
HKEY hKey;
|
|
|
|
sprintf( Buffer, "0x%x", GetKernelModeFlags() ); // default if query fails
|
|
|
|
if ( strlen( ImageFileName ) != 0 ) {
|
|
|
|
sprintf( RegKey,
|
|
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
|
|
ImageFileName
|
|
);
|
|
|
|
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, RegKey, 0, KEY_READ, &hKey ) == ERROR_SUCCESS ) {
|
|
RegQueryValueEx( hKey, "GlobalFlag", NULL, NULL, Buffer, &Length );
|
|
RegCloseKey( hKey );
|
|
}
|
|
|
|
}
|
|
|
|
Status = RtlCharToInteger( Buffer, 0, &GFlags );
|
|
if (!NT_SUCCESS( Status )) {
|
|
MessageBox( hwndMain, "Value Error", ImageFileName, MB_OK );
|
|
ExitProcess( 0 );
|
|
}
|
|
|
|
return GFlags;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
SetImageFileNameFlags(
|
|
PCHAR ImageFileName,
|
|
DWORD GFlags
|
|
)
|
|
{
|
|
CHAR Buffer[ MAX_PATH ];
|
|
CHAR RegKey[ MAX_PATH ];
|
|
HKEY hKey;
|
|
DWORD Result;
|
|
DWORD Length;
|
|
DWORD Disposition;
|
|
|
|
if ( strlen( ImageFileName ) != 0 ) {
|
|
|
|
Length = ( sprintf( Buffer, "0x%08x", GFlags ) + 1 ) * sizeof( CHAR );
|
|
|
|
sprintf( RegKey,
|
|
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
|
|
ImageFileName
|
|
);
|
|
|
|
Result = RegCreateKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
RegKey,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hKey,
|
|
&Disposition
|
|
);
|
|
|
|
if ( Result == ERROR_SUCCESS ) {
|
|
|
|
Result = RegSetValueEx(
|
|
hKey,
|
|
"GlobalFlag",
|
|
0,
|
|
REG_SZ,
|
|
Buffer,
|
|
Length
|
|
);
|
|
|
|
RegCloseKey( hKey );
|
|
}
|
|
|
|
if ( Result != ERROR_SUCCESS ) {
|
|
|
|
MessageBox( hwndMain, "Failed to set registry value", ImageFileName, MB_OK );
|
|
return FALSE;
|
|
}
|
|
|
|
LastSetFlags = GFlags;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
int WinMain(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine,
|
|
INT nCmdShow)
|
|
{
|
|
MSG msg;
|
|
|
|
hwndMain = NULL;
|
|
CreateDialog( hInstance,
|
|
(LPSTR)DID_GFLAGS,
|
|
NULL,
|
|
MainWndProc
|
|
);
|
|
if (!hwndMain) {
|
|
MessageBox( hwndMain, "Main Error", "Cant create dialog", MB_OK );
|
|
ExitProcess( 0 );
|
|
}
|
|
|
|
while (GetMessage( &msg, 0, 0, 0 )) {
|
|
if (!IsDialogMessage( hwndMain, &msg )) {
|
|
DispatchMessage( &msg );
|
|
}
|
|
}
|
|
|
|
ExitProcess( 0 );
|
|
return 0;
|
|
}
|
|
|
|
|
|
VOID
|
|
SetCheckBoxesFromFlags(
|
|
DWORD GFlags,
|
|
DWORD ValidFlags
|
|
)
|
|
{
|
|
int iBit;
|
|
|
|
GFlags &= ValidFlags;
|
|
InitialSetFlags = GFlags;
|
|
LastSetFlags = 0;
|
|
for (iBit=0; iBit < 32; iBit++) {
|
|
CheckDlgButton( hwndMain,
|
|
ID_FLAG_1 + iBit,
|
|
(GFlags & (1 << iBit)) ? 1 : 0
|
|
);
|
|
|
|
ShowWindow( GetDlgItem( hwndMain, ID_FLAG_1 + iBit ),
|
|
(ValidFlags & (1 << iBit)) ? SW_SHOWNORMAL : SW_HIDE
|
|
);
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
GetFlagsFromCheckBoxes( VOID )
|
|
{
|
|
DWORD GFlags;
|
|
int iBit;
|
|
|
|
GFlags = 0;
|
|
for (iBit=0; iBit < 32; iBit++) {
|
|
if (IsDlgButtonChecked( hwndMain, ID_FLAG_1 + iBit )) {
|
|
GFlags |= (1 << iBit);
|
|
}
|
|
}
|
|
|
|
return GFlags;
|
|
}
|
|
|
|
VOID
|
|
DoLaunch(
|
|
PCHAR CommandLine
|
|
)
|
|
{
|
|
STARTUPINFO StartupInfo;
|
|
PROCESS_INFORMATION ProcessInformation;
|
|
NTSTATUS Status;
|
|
PROCESS_BASIC_INFORMATION BasicInformation;
|
|
BOOLEAN ReadImageFileExecOptions;
|
|
DWORD BytesWritten;
|
|
DWORD GFlags;
|
|
|
|
memset( &StartupInfo, 0, sizeof( StartupInfo ) );
|
|
StartupInfo.cb = sizeof( StartupInfo );
|
|
if (CreateProcess( NULL,
|
|
CommandLine,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
CREATE_SUSPENDED,
|
|
NULL,
|
|
NULL,
|
|
&StartupInfo,
|
|
&ProcessInformation
|
|
)
|
|
) {
|
|
Status = NtQueryInformationProcess( ProcessInformation.hProcess,
|
|
ProcessBasicInformation,
|
|
&BasicInformation,
|
|
sizeof( BasicInformation ),
|
|
NULL
|
|
);
|
|
if (NT_SUCCESS( Status )) {
|
|
ReadImageFileExecOptions = TRUE;
|
|
GFlags = GetFlagsFromCheckBoxes();
|
|
if (!WriteProcessMemory( ProcessInformation.hProcess,
|
|
&BasicInformation.PebBaseAddress->ReadImageFileExecOptions,
|
|
&ReadImageFileExecOptions,
|
|
sizeof( ReadImageFileExecOptions ),
|
|
&BytesWritten
|
|
) ||
|
|
!WriteProcessMemory( ProcessInformation.hProcess,
|
|
&BasicInformation.PebBaseAddress->NtGlobalFlag,
|
|
&GFlags,
|
|
sizeof( GFlags ),
|
|
&BytesWritten
|
|
)
|
|
) {
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
|
|
if (!NT_SUCCESS( Status )) {
|
|
MessageBox( hwndMain,
|
|
"Launch Command Line",
|
|
"Unable to pass flags to process - terminating",
|
|
MB_OK
|
|
);
|
|
TerminateProcess( ProcessInformation.hProcess, 1 );
|
|
}
|
|
|
|
ResumeThread( ProcessInformation.hThread );
|
|
CloseHandle( ProcessInformation.hThread );
|
|
MsgWaitForMultipleObjects( 1,
|
|
&ProcessInformation.hProcess,
|
|
FALSE,
|
|
NMPWAIT_WAIT_FOREVER,
|
|
QS_ALLINPUT
|
|
);
|
|
CloseHandle( ProcessInformation.hProcess );
|
|
}
|
|
else {
|
|
MessageBox( hwndMain, "Launch Command Line", "Unable to create process", MB_OK );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
DWORD LastRadioButtonId;
|
|
|
|
LONG
|
|
APIENTRY
|
|
MainWndProc(
|
|
HWND hwnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LONG lParam
|
|
)
|
|
{
|
|
CHAR ImageFileName[ MAX_PATH ];
|
|
CHAR CommandLine[ MAX_PATH ];
|
|
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
hwndMain = hwnd;
|
|
LastRadioButtonId = ID_SYSTEM_REGISTRY;
|
|
CheckRadioButton( hwnd,
|
|
ID_SYSTEM_REGISTRY,
|
|
ID_IMAGE_FILE_OPTIONS,
|
|
LastRadioButtonId
|
|
);
|
|
|
|
SetCheckBoxesFromFlags( GetSystemRegistryFlags(), VALID_SYSTEM_REGISTRY_FLAGS );
|
|
return(TRUE);
|
|
|
|
case WM_COMMAND:
|
|
switch( LOWORD(wParam) ) {
|
|
case ID_LAUNCH:
|
|
GetDlgItemText( hwnd, ID_COMMAND_LINE, CommandLine, sizeof( CommandLine ) );
|
|
if (strlen( ImageFileName ) == 0) {
|
|
MessageBox( hwndMain, "Launch Command Line", "Must fill in command line first", MB_OK );
|
|
SetFocus( GetDlgItem( hwnd, ID_COMMAND_LINE ) );
|
|
break;
|
|
}
|
|
|
|
// fall through
|
|
|
|
case ID_APPLY:
|
|
if (IsDlgButtonChecked( hwnd, ID_SYSTEM_REGISTRY )) {
|
|
SetSystemRegistryFlags( GetFlagsFromCheckBoxes() );
|
|
}
|
|
else
|
|
if (IsDlgButtonChecked( hwnd, ID_KERNEL_MODE )) {
|
|
SetKernelModeFlags( GetFlagsFromCheckBoxes() );
|
|
}
|
|
else
|
|
if (IsDlgButtonChecked( hwnd, ID_IMAGE_FILE_OPTIONS )) {
|
|
GetDlgItemText( hwnd, ID_IMAGE_FILE_NAME, ImageFileName, sizeof( ImageFileName ) );
|
|
if (strlen( ImageFileName ) == 0) {
|
|
MessageBox( hwnd, "Missing Image File Name", "Must set image file name", MB_OK );
|
|
SetFocus( GetDlgItem( hwnd, ID_IMAGE_FILE_NAME ) );
|
|
break;
|
|
}
|
|
|
|
SetImageFileNameFlags( ImageFileName, GetFlagsFromCheckBoxes() );
|
|
}
|
|
|
|
if (LOWORD(wParam) == ID_LAUNCH) {
|
|
DoLaunch( CommandLine );
|
|
}
|
|
break;
|
|
|
|
case IDOK:
|
|
if (GetFlagsFromCheckBoxes() != InitialSetFlags) {
|
|
if (GetFlagsFromCheckBoxes() != LastSetFlags) {
|
|
if (MessageBox( hwndMain,
|
|
"Did you want to exit without applying these settings?",
|
|
"Warning",
|
|
MB_OKCANCEL
|
|
) == IDCANCEL
|
|
) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// fall through
|
|
|
|
case IDCANCEL:
|
|
PostQuitMessage(0);
|
|
DestroyWindow( hwnd );
|
|
break;
|
|
|
|
case ID_SYSTEM_REGISTRY:
|
|
if (GetFlagsFromCheckBoxes() != InitialSetFlags) {
|
|
if (MessageBox( hwndMain,
|
|
"Did you want to discard current changes??",
|
|
"Warning",
|
|
MB_OKCANCEL
|
|
) == IDCANCEL
|
|
) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
LastRadioButtonId = ID_SYSTEM_REGISTRY;
|
|
SetCheckBoxesFromFlags( GetSystemRegistryFlags(), VALID_SYSTEM_REGISTRY_FLAGS );
|
|
break;
|
|
|
|
case ID_KERNEL_MODE:
|
|
if (GetFlagsFromCheckBoxes() != InitialSetFlags) {
|
|
if (MessageBox( hwndMain,
|
|
"Did you want to discard current changes??",
|
|
"Warning",
|
|
MB_OKCANCEL
|
|
) == IDCANCEL
|
|
) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
LastRadioButtonId = ID_KERNEL_MODE;
|
|
SetCheckBoxesFromFlags( GetKernelModeFlags(), VALID_KERNEL_MODE_FLAGS );
|
|
break;
|
|
|
|
case ID_IMAGE_FILE_OPTIONS:
|
|
if (GetFlagsFromCheckBoxes() != InitialSetFlags) {
|
|
if (MessageBox( hwndMain,
|
|
"Did you want to discard current changes??",
|
|
"Warning",
|
|
MB_OKCANCEL
|
|
) == IDCANCEL
|
|
) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
GetDlgItemText( hwnd, ID_IMAGE_FILE_NAME, ImageFileName, sizeof( ImageFileName ) );
|
|
if (strlen( ImageFileName ) == 0) {
|
|
MessageBox( hwndMain, "Image File Name Missing", "Must fill in image file name first", MB_OK );
|
|
CheckRadioButton( hwnd,
|
|
ID_SYSTEM_REGISTRY,
|
|
ID_IMAGE_FILE_OPTIONS,
|
|
LastRadioButtonId
|
|
);
|
|
SetCheckBoxesFromFlags( GetSystemRegistryFlags(), VALID_SYSTEM_REGISTRY_FLAGS );
|
|
SetFocus( GetDlgItem( hwnd, ID_IMAGE_FILE_NAME ) );
|
|
break;
|
|
}
|
|
else {
|
|
LastRadioButtonId = ID_IMAGE_FILE_NAME;
|
|
SetCheckBoxesFromFlags( GetImageFileNameFlags( ImageFileName ),
|
|
VALID_IMAGE_FILE_NAME_FLAGS
|
|
);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
PostQuitMessage(0);
|
|
DestroyWindow( hwnd );
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
EnableDebugPrivilege( VOID )
|
|
{
|
|
HANDLE Token;
|
|
PTOKEN_PRIVILEGES NewPrivileges;
|
|
BYTE OldPriv[ 1024 ];
|
|
PBYTE pbOldPriv;
|
|
ULONG cbNeeded;
|
|
BOOLEAN fRc;
|
|
LUID LuidPrivilege;
|
|
|
|
//
|
|
// Make sure we have access to adjust and to get the old token privileges
|
|
//
|
|
if (!OpenProcessToken( GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
|
&Token
|
|
)
|
|
) {
|
|
return FALSE;
|
|
}
|
|
|
|
cbNeeded = 0;
|
|
|
|
//
|
|
// Initialize the privilege adjustment structure
|
|
//
|
|
|
|
LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &LuidPrivilege );
|
|
NewPrivileges = (PTOKEN_PRIVILEGES)HeapAlloc( GetProcessHeap(), 0,
|
|
sizeof(TOKEN_PRIVILEGES) +
|
|
(1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES)
|
|
);
|
|
if (NewPrivileges == NULL) {
|
|
CloseHandle( Token );
|
|
return FALSE;
|
|
}
|
|
|
|
NewPrivileges->PrivilegeCount = 1;
|
|
NewPrivileges->Privileges[0].Luid = LuidPrivilege;
|
|
NewPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
//
|
|
// Enable the privilege
|
|
//
|
|
|
|
pbOldPriv = OldPriv;
|
|
fRc = AdjustTokenPrivileges( Token,
|
|
FALSE,
|
|
NewPrivileges,
|
|
sizeof( OldPriv ),
|
|
(PTOKEN_PRIVILEGES)pbOldPriv,
|
|
&cbNeeded
|
|
);
|
|
if (!fRc) {
|
|
//
|
|
// If the stack was too small to hold the privileges
|
|
// then allocate off the heap
|
|
//
|
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
|
pbOldPriv = (PBYTE)HeapAlloc( GetProcessHeap(), 0, cbNeeded );
|
|
if (pbOldPriv == NULL) {
|
|
CloseHandle( Token );
|
|
return FALSE;
|
|
}
|
|
|
|
fRc = AdjustTokenPrivileges( Token,
|
|
FALSE,
|
|
NewPrivileges,
|
|
cbNeeded,
|
|
(PTOKEN_PRIVILEGES)pbOldPriv,
|
|
&cbNeeded
|
|
);
|
|
}
|
|
}
|
|
|
|
return fRc;
|
|
}
|