|
// vim:set ts=4 sw=4:
//
// This program demonstrates how to write directly to hardware ports
// from user mode. To do this, the account that this program is
// running under must have SeTcbPrivilege available, but not
// necessarily active. The SYSTEM account has this privilege enabled
// and active. Administrators do not normally have this privilege
// available. To enable SeTcbPrivilege, use the "Local Computer
// Policy" in the MMC and grant the "Act as part of the operating
// system" to your user via:
//
// Local Computer Policy
// Computer Configuration
// Windows Settings
// Security Settings
// Local Policies
// User Rights Management
//
// You will need to log out and back in again so your login token has
// this privilege granted (but disabled). You could also assign
// this privilege programatically to the account. A relogin is still
// required. This program will then enable SeTcbPrivilege then attempt
// to change the IOPL of this process to allow direct port access and
// "effective" kernel mode abilities.
//
// As a demo, we will write directly to the reset port of the keyboard
// controller. The keyboard controller has a direct line to the RESET
// pin of the CPU and the machine will hard reboot with no questions
// asked and without OS intervention.
//
// This is something that is not normally allowed from user mode! ;-)
//
// To perform the reset, write to port 0x64 with command 0xFE. From
// kernel mode, we already have access to hardware ports and accomplish
// the same result via: WRITE_PORT_UCHAR(0x64, 0xFE).
//
// For a kernel mode driver version of this program, refer to
// "Reboot.c".
//
// Michael Wookey / August 2006
//
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>
BOOL
EnablePrivilege(
PTCHAR Privilege
)
{
BOOL rc = FALSE;
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tokenPrivilege;
//
// Open the current process' token.
//
rc = OpenProcessToken(
GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken);
if (rc)
{
rc = LookupPrivilegeValue(NULL, Privilege, &luid);
if (rc)
{
tokenPrivilege.PrivilegeCount = 1;
tokenPrivilege.Privileges[0].Luid = luid;
tokenPrivilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
//
// Assign the given privilege.
//
rc = AdjustTokenPrivileges(
hToken,
FALSE,
&tokenPrivilege,
sizeof(tokenPrivilege),
NULL,
NULL);
}
}
if (hToken)
{
CloseHandle(hToken);
}
return rc;
}
BOOL
EnableUserModeHardwareIO()
{
typedef ULONG (__stdcall* pfn_ZwSetInformationProcess)(
HANDLE,
ULONG,
PVOID,
ULONG);
BOOL rc = FALSE;
HMODULE hNtDll = NULL;
ULONG IOPL = 3;
INT ProcessUserModeIOPL = 16;
pfn_ZwSetInformationProcess ZwSetInformationProcess;
hNtDll = GetModuleHandle("ntdll.dll");
if (hNtDll)
{
ZwSetInformationProcess = (pfn_ZwSetInformationProcess)
GetProcAddress(hNtDll, "ZwSetInformationProcess");
if (ZwSetInformationProcess)
{
//
// Enable SeTcbPrivilege
//
rc = EnablePrivilege(SE_TCB_NAME);
if (rc)
{
//
// Grant user mode hardware IO access.
//
rc = ZwSetInformationProcess(
GetCurrentProcess(),
ProcessUserModeIOPL,
&IOPL,
sizeof(IOPL));
//
// An NTSTATUS is returned, so zero is success.
//
if (!rc)
{
rc = TRUE;
}
}
}
}
return rc;
}
int
__cdecl
main(
int argc,
char* argv[]
)
{
UNREFERENCED_PARAMETER(argc); // To compile cleanly at /W4
UNREFERENCED_PARAMETER(argv); // To compile cleanly at /W4
if (EnableUserModeHardwareIO())
{
//
// Hard boot the machine via writing directly to the keyboard
// controller...
//
__asm mov dx, 0x64
__asm mov al, 0xFE
__asm out dx, al
}
return 0;
}
/* EOF */
|