224 lines
5.9 KiB
C
224 lines
5.9 KiB
C
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
#include <ntexapi.dbg>
|
||
|
|
||
|
DECLARE_API( gflag )
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function is called as an NTSD extension to dump or modify
|
||
|
the contents of the NtGlobalFlag variable in NTDLL
|
||
|
|
||
|
Called as:
|
||
|
|
||
|
!gflag [value]
|
||
|
|
||
|
If a value is not given then displays the current bits set in
|
||
|
NTDLL!NtGlobalFlag variable. Otherwise value can be one of the
|
||
|
following:
|
||
|
|
||
|
-? - displays a list of valid flag abbreviations
|
||
|
number - 32-bit number that becomes the new value stored into
|
||
|
NtGlobalFlag
|
||
|
+number - specifies one or more bits to set in NtGlobalFlag
|
||
|
+abbrev - specifies a single bit to set in NtGlobalFlag
|
||
|
-number - specifies one or more bits to clear in NtGlobalFlag
|
||
|
-abbrev - specifies a single bit to clear in NtGlobalFlag
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
ULONG gflagOffset;
|
||
|
ULONG64 pebAddress;
|
||
|
ULONG64 pNtGlobalFlag = 0;
|
||
|
ULONG ValidBits = FLG_USERMODE_VALID_BITS;
|
||
|
ULONG i;
|
||
|
ULONG OldGlobalFlags;
|
||
|
ULONG NewGlobalFlagsClear;
|
||
|
ULONG NewGlobalFlagsSet;
|
||
|
ULONG NewGlobalFlags;
|
||
|
LPSTR s, Arg;
|
||
|
|
||
|
pNtGlobalFlag = GetExpression("nt!NtGlobalFlag");
|
||
|
ValidBits = FLG_VALID_BITS;
|
||
|
|
||
|
//
|
||
|
// If we could not get the global variable from the kernel, try from the
|
||
|
// PEB for user mode
|
||
|
//
|
||
|
|
||
|
if (!pNtGlobalFlag)
|
||
|
{
|
||
|
GetPebAddress(0, &pebAddress);
|
||
|
|
||
|
if (pebAddress)
|
||
|
{
|
||
|
if (GetFieldOffset("nt!_PEB", "NtGlobalFlag", &gflagOffset))
|
||
|
{
|
||
|
dprintf("Could not find NtGlobalFlag in nt!_PEB\n");
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
pNtGlobalFlag = gflagOffset + pebAddress;
|
||
|
ValidBits = FLG_USERMODE_VALID_BITS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!pNtGlobalFlag)
|
||
|
{
|
||
|
dprintf( "Unable to get address of NtGlobalFlag variable" );
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
if (!ReadMemory(pNtGlobalFlag,
|
||
|
&OldGlobalFlags,
|
||
|
sizeof(OldGlobalFlags),
|
||
|
NULL))
|
||
|
{
|
||
|
dprintf( "Unable to read contents of NtGlobalFlag variable at %p\n", pNtGlobalFlag );
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
OldGlobalFlags &= ValidBits;
|
||
|
|
||
|
s = (LPSTR)args;
|
||
|
if (!s)
|
||
|
{
|
||
|
s = "";
|
||
|
}
|
||
|
|
||
|
NewGlobalFlagsClear = 0;
|
||
|
NewGlobalFlagsSet = 0;
|
||
|
while (*s)
|
||
|
{
|
||
|
while (*s && *s <= ' ')
|
||
|
{
|
||
|
s += 1;
|
||
|
}
|
||
|
|
||
|
Arg = s;
|
||
|
if (!*s)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
while (*s && *s > ' ')
|
||
|
{
|
||
|
s += 1;
|
||
|
}
|
||
|
|
||
|
if (*s)
|
||
|
{
|
||
|
*s++ = '\0';
|
||
|
}
|
||
|
|
||
|
if (!strcmp( Arg, "-?" ))
|
||
|
{
|
||
|
dprintf( "usage: !gflag [-? | flags]\n" );
|
||
|
dprintf( "Flags may either be a single hex number that specifies all\n" );
|
||
|
dprintf( "32-bits of the GlobalFlags value, or it can be one or more\n" );
|
||
|
dprintf( "arguments, each beginning with a + or -, where the + means\n" );
|
||
|
dprintf( "to set the corresponding bit(s) in the GlobalFlags and a -\n" );
|
||
|
dprintf( "means to clear the corresponding bit(s). After the + or -\n" );
|
||
|
dprintf( "may be either a hex number or a three letter abbreviation\n" );
|
||
|
dprintf( "for a GlobalFlag. Valid abbreviations are:\n" );
|
||
|
for (i=0; i<32; i++) {
|
||
|
if ((GlobalFlagInfo[i].Flag & ValidBits) &&
|
||
|
GlobalFlagInfo[i].Abbreviation != NULL)
|
||
|
{
|
||
|
dprintf( " %s - %s\n", GlobalFlagInfo[i].Abbreviation,
|
||
|
GlobalFlagInfo[i].Description
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
if (*Arg == '+' || *Arg == '-')
|
||
|
{
|
||
|
if (strlen(Arg+1) == 3)
|
||
|
{
|
||
|
for (i=0; i<32; i++)
|
||
|
{
|
||
|
if ((GlobalFlagInfo[i].Flag & ValidBits) &&
|
||
|
!_stricmp( GlobalFlagInfo[i].Abbreviation, Arg+1 ))
|
||
|
{
|
||
|
if (*Arg == '-')
|
||
|
{
|
||
|
NewGlobalFlagsClear |= GlobalFlagInfo[i].Flag;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
NewGlobalFlagsSet |= GlobalFlagInfo[i].Flag;
|
||
|
}
|
||
|
|
||
|
Arg += 4;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (*Arg != '\0')
|
||
|
{
|
||
|
dprintf( "Invalid flag abbreviation - '%s'\n", Arg );
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (*Arg != '\0')
|
||
|
{
|
||
|
if (*Arg++ == '-')
|
||
|
{
|
||
|
NewGlobalFlagsClear |= strtoul( Arg, &Arg, 16 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
NewGlobalFlagsSet |= strtoul( Arg, &Arg, 16 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
NewGlobalFlagsSet = strtoul( Arg, &Arg, 16 );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NewGlobalFlags = (OldGlobalFlags & ~NewGlobalFlagsClear) | NewGlobalFlagsSet;
|
||
|
NewGlobalFlags &= ValidBits;
|
||
|
if (NewGlobalFlags != OldGlobalFlags)
|
||
|
{
|
||
|
if (!WriteMemory( pNtGlobalFlag,
|
||
|
&NewGlobalFlags,
|
||
|
sizeof( NewGlobalFlags ),
|
||
|
NULL))
|
||
|
{
|
||
|
dprintf( "Unable to store new global flag settings.\n" );
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
dprintf( "New NtGlobalFlag contents: 0x%08x\n", NewGlobalFlags );
|
||
|
OldGlobalFlags = NewGlobalFlags;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
dprintf( "Current NtGlobalFlag contents: 0x%08x\n", OldGlobalFlags );
|
||
|
}
|
||
|
|
||
|
for (i=0; i<32; i++)
|
||
|
{
|
||
|
if (OldGlobalFlags & GlobalFlagInfo[i].Flag)
|
||
|
{
|
||
|
dprintf( " %s - %s\n", GlobalFlagInfo[i].Abbreviation, GlobalFlagInfo[i].Description );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|