diff --git a/Compiled/NtCall64.exe b/Compiled/NtCall64.exe index c444a1f..85e2a0a 100644 Binary files a/Compiled/NtCall64.exe and b/Compiled/NtCall64.exe differ diff --git a/Compiled/badcalls.ini b/Compiled/badcalls.ini index e4ce0bd..ac194ce 100644 --- a/Compiled/badcalls.ini +++ b/Compiled/badcalls.ini @@ -1,5 +1,6 @@ [ntos] NtClose +NtInitiatePowerAction NtRaiseHardError NtReleaseKeyedEvent NtPropagationComplete diff --git a/LICENSE.md b/LICENSE.md index 3e1525a..a089817 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) 2016 - 2022, NtCall64 Project +Copyright (c) 2016 - 2023, NtCall64 Project Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/NtCall64.sha256 b/NtCall64.sha256 index d5f4c6b..b250db9 100644 --- a/NtCall64.sha256 +++ b/NtCall64.sha256 @@ -1,45 +1,2 @@ -ddc4a319b3ce482f7e57cd8291994045c41ad62fbcb5a26b03b69a713bea2e4a *Compiled\badcalls.ini -723e1dee6c66b9cbce5dfb87e489ebb70b41e607971393f391b8dba53e6b8734 *Compiled\NtCall64.exe -9c41705a8efa0c845867b4b7d6f9771f2172c15d55e1f00f5de6ef3e4509693b *Source\NtCall64.sln -fad664ec0d0c25531e5564889edeadfca4d47efe763d6536afeaf2d2eedd64d6 *Source\NtCall64\blacklist.c -b48096900363f68a5eb0b395c9b86b133497f1a5725bf481dbe230d39802c906 *Source\NtCall64\blacklist.h -dd32fab74b8aa7a2ac673ee4a6c76e4e852ee0bf9e1a6e0f31ca5f443a87557a *Source\NtCall64\fuzz.c -9d985200820ae2fb844af24010a3addf38492d2d04c760716ed97494b620b847 *Source\NtCall64\fuzz.h -e19447618ecf1721c7f7c94df27ebe78662c0966f0bb86af7399bbbfb7c493c4 *Source\NtCall64\global.h -648ac51015c09a80c88aa4ffe1cc51d8dd08109a5d8ba06473e6ee68a751a475 *Source\NtCall64\log.c -c1f0eb28ee9abc0c371c0ba6a1208b3d5821b20eace4a5a61aab821dbacb9a33 *Source\NtCall64\log.h -5c2b48a253a178a79af61e713e16faeff3cab99f705ac92b57614556960fcdd8 *Source\NtCall64\main.c -0078fbdb03efa638ecf840f776afd4fc4f69e0e96c6bd48363a51350f4321266 *Source\NtCall64\ntos.h -d1130a87d31c6f62387dcfd5ce1449a68c8dad2bc62674d1cc887804758615ae *Source\NtCall64\resource.h -dc8498bc0d0bd32ae2afe115bc5e5a4f885e0aa3608f28693d423fddff151789 *Source\NtCall64\resource.rc -3957bcebe3741c99439bbcd0a4a56643ae5e5dae7139a25e2fea2f0c27ba784d *Source\NtCall64\syscall.asm -062ac9e7119cb058554ec698e9f025e2976dae1a8a838bd5fbd443bdde763148 *Source\NtCall64\tables.h -8b6fb6ce675dd79d355ab39bfe05cb4d9ca08c5ffe9268c838be7b37982e2f76 *Source\NtCall64\util.c -86726b76f7e3456e4a827d43f3db5fce751e571c5969c6902607d5b95dd5e168 *Source\NtCall64\util.h -6461b2932f106c395720cdcaaa834dc181bb1672646ce50984b318c719f50541 *Source\NtCall64\wfuzzer.vcxproj -80f43d7f81eec7648ef4dde1dc4c39b2635becdf64c359441a35512f4bcf5c95 *Source\NtCall64\wfuzzer.vcxproj.filters -5bb622e3b2e91f8ccc320d1cac51113009a3845c05d3de39c3a28b62f627c1f5 *Source\NtCall64\wfuzzer.vcxproj.user -53a7ce27591e040b63880a3dd326b8ba8c97a0fa34d5e2d32aba89a0147434f6 *Source\NtCall64\hde\hde64.c -e99aa4997bda14b534c614c3d8cb78a72c4aca91a1212c8b03ec605d1d75e36e *Source\NtCall64\hde\hde64.h -f8e6a0be357726bee35c7247b57408b54bb38d94e8324a6bb84b91c462b2be30 *Source\NtCall64\hde\pstdint.h -b774446d2f110ce954fb0a710f4693c5562ddbd8d56fe84106f2ee80db8b50a2 *Source\NtCall64\hde\table64.h -893b90b942372928009bad64f166c7018701497e4f7cd1753cdc44f76da06707 *Source\NtCall64\minirtl\cmdline.c -bd6fe82852c4fcdfab559defa33ea394b752a4e4a5ac0653ae20c4a94b0175ed *Source\NtCall64\minirtl\cmdline.h -2a08385892845104b4f07d693ca395eba3a09e4aa89ad791be3807919316ed67 *Source\NtCall64\minirtl\minirtl.h -d7fbfd69df3840022dab1f8f2d529ce04abac8cee0234448bfd0a67feb6aea22 *Source\NtCall64\minirtl\rtltypes.h -0320808115d42f04f63a382e8f386aa9bc77ba879892f5ccc94c40378b5131c8 *Source\NtCall64\minirtl\strtou64.c -f4763588a79859ba8a84e3be35fa1e4b0b8bf95f547a4fee5ae4612978c0787b *Source\NtCall64\minirtl\strtoul.c -e56e67b10a67f0d5ef4128c7ab0c6cb9ba9966916720525edfa6abf3101dfe13 *Source\NtCall64\minirtl\u64tohex.c -4d15af5a22467795c5367c3956746d01424795784f62ca3f30e4619c063338a5 *Source\NtCall64\minirtl\u64tostr.c -f81c975acd016c97776dd3a8e3218e148682b0336ff3fcd77fad6d9b86ddf107 *Source\NtCall64\minirtl\ultohex.c -9cbedf9b92abaef3ea28de28dd523ac44079592178ef727c7003c339a5a54712 *Source\NtCall64\minirtl\ultostr.c -c1405b280bacc7566ccd041a74461de3f8496128fd71e39368905cf8d95268f6 *Source\NtCall64\minirtl\_filename.c -9e3f1386bfb64dbaa3cbb12fd3bf51c734872c2fdf15cf1aaeca52a515767519 *Source\NtCall64\minirtl\_filename.h -83772aa217508279294d91af5cfabec9b5e00b836a2e2f5fe37cf1ebc2905a52 *Source\NtCall64\minirtl\_strcat.c -2a67c7690ec6df8e233207116b0e4fe76c02ae43595d9e606e123572b6ac88a1 *Source\NtCall64\minirtl\_strcmp.c -ef1b18997ea473ac8d516ef60efc64b9175418b8f078e088d783fdaef2544969 *Source\NtCall64\minirtl\_strcmpi.c -969b35213fa23ff50a169e5498a97f28bc6f5820b447b78ec9dc6910dd8cc3e8 *Source\NtCall64\minirtl\_strcpy.c -27159b8ff67d3f8e6c7fdb4b57b9f57f899bdfedf92cf10276269245c6f4e066 *Source\NtCall64\minirtl\_strend.c -60f19c6b805801e13824c4d9d44748da8245cd936971411d3d36b873121888eb *Source\NtCall64\minirtl\_strlen.c -97e0720ed22d2d99e8148aab7ab2cb2cc3df278225669828b2d8d4d9ef856d94 *Source\NtCall64\minirtl\_strncmp.c -0434d69daa20fbf87d829ffc17e43dcc2db3386aff434af888011fdec2f645a4 *Source\NtCall64\minirtl\_strncpy.c +83a3c4632f0f685a56a5c0c54531eba10f32533c74590a011efe439c8a13d83e *Compiled\badcalls.ini +aec6ca2f29b1c474ea1aa8e9a620a557be4391aa951ce35fcc98f45788cf8182 *Compiled\NtCall64.exe diff --git a/README.md b/README.md index bb45ef7..709e228 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ NTCALL64 -help[-win32k][-log][-call Id][-pc Value][-wt Value][-s] * -call Id - fuzz syscall by supplied id (id can be from any table ntos/win32k); * -pc Value - set pass count for each syscall (maximum value is limited to ULONG64 max value), default value 65536; * -wt Value - set wait timeout for calling threads in seconds (except single syscall fuzzing), default value is 30; +* -start Id - Fuzz syscall table starting from given syscall id, mutual exclusive with -call; * -s - Attempt to run program from LocalSystem account. @@ -62,6 +63,7 @@ Example of badcalls.ini (default config shipped with program)
[ntos] NtClose +NtInitiatePowerAction NtRaiseHardError NtReleaseKeyedEvent NtPropagationComplete @@ -98,6 +100,7 @@ This program may crash the operation system, affect it stability, which may resu * [win32k!NtUserCreateActivationObject](https://gist.githubusercontent.com/hfiref0x/23a2331588e7765664f50cac26cf0637/raw/49457ef5e30049b6b4ca392e489aaceaafe2b280/NtUserCreateActivationObject.cpp) * [win32k!NtUserOpenDesktop](https://gist.githubusercontent.com/hfiref0x/6e726b352da7642fc5b84bf6ebce0007/raw/8df05220f194da4980f401e15a0efdb7694deb26/NtUserOpenDesktop.c) * [win32k!NtUserSetWindowsHookEx](https://gist.github.com/hfiref0x/8ecfbcc0a7afcc9917cef093ef3a18b2) +* [win32k!NtUserInitialize -> win32kbase!Win32kBaseUserInitialize] (https://gist.github.com/hfiref0x/f731e690e6155c6763b801ce0e497db7) * [nt!NtLoadEnclaveData](https://gist.githubusercontent.com/hfiref0x/1ac328a8e73d053012e02955d38e36a8/raw/b26174f8b7b68506d62308ce4327dfc573b8aa26/main.c) * [nt!NtCreateIoRing](https://gist.github.com/hfiref0x/bd6365a7cfa881da0e9c9e7a917a051b) * [nt!NtQueryInformationCpuPartition](https://gist.github.com/hfiref0x/48bdc12241d0a981a6da473e979c8aff) @@ -106,13 +109,11 @@ This program may crash the operation system, affect it stability, which may resu # Build NTCALL64 comes with full source code written in C with tiny assembler usage. -In order to build from source you need Microsoft Visual Studio 2015 and later versions. +In order to build from source you need Microsoft Visual Studio 2017 and later versions. ## Instructions * Select Platform ToolSet first for project in solution you want to build (Project->Properties->General): - * v120 for Visual Studio 2013; - * v140 for Visual Studio 2015; * v141 for Visual Studio 2017; * v142 for Visual Studio 2019; * v143 for Visual Studio 2022. @@ -123,6 +124,6 @@ In order to build from source you need Microsoft Visual Studio 2015 and later ve # Authors -(c) 2016 - 2022 NTCALL64 Project +(c) 2016 - 2023 NTCALL64 Project Original NtCall by Peter Kosyh aka Gloomy (c) 2001, http://gl00my.chat.ru/ diff --git a/Source/NtCall64/fuzz.c b/Source/NtCall64/fuzz.c index 39dd314..9b83687 100644 --- a/Source/NtCall64/fuzz.c +++ b/Source/NtCall64/fuzz.c @@ -1,12 +1,12 @@ /******************************************************************************* * -* (C) COPYRIGHT AUTHORS, 2016 - 2021 +* (C) COPYRIGHT AUTHORS, 2016 - 2023 * * TITLE: FUZZ.C * -* VERSION: 1.35 +* VERSION: 1.37 * -* DATE: 21 Feb 2021 +* DATE: 04 Aug 2023 * * Fuzzing routines. * @@ -23,11 +23,20 @@ #ifdef __cplusplus extern "C" { #endif - NTSTATUS ntSyscallGate(ULONG ServiceId, ULONG ArgumentCount, ULONG_PTR *Arguments); + NTSTATUS ntSyscallGate(ULONG ServiceId, ULONG ArgumentCount, ULONG_PTR* Arguments); #ifdef __cplusplus } #endif +#define FUZZDATA_COUNT 13 +const ULONG_PTR FuzzData[FUZZDATA_COUNT] = { + 0x0000000000000000, 0x000000000000ffff, 0x000000000000fffe, 0x00007ffffffeffff, + 0x00007ffffffefffe, 0x00007fffffffffff, 0x00007ffffffffffe, 0x0000800000000000, + 0x8000000000000000, 0xffff080000000000, 0xfffff80000000000, 0xffff800000000000, + 0xffff800000000001 +}; + + /* * FuzzEnumWin32uServices * @@ -36,69 +45,62 @@ extern "C" { * Enumerate win32u module services to the table. * */ -_Success_(return != 0) ULONG FuzzEnumWin32uServices( _In_ HANDLE HeapHandle, - _In_ LPVOID Module, - _Out_ PWIN32_SHADOWTABLE * Table + _In_ LPVOID ModuleBase, + _Inout_ PWIN32_SHADOWTABLE* Table ) { - PIMAGE_NT_HEADERS NtHeaders; - PIMAGE_EXPORT_DIRECTORY exp; - PDWORD FnPtrTable, NameTable; - PWORD NameOrdTable; - ULONG_PTR fnptr, exprva, expsize; - ULONG c, n, result; - PWIN32_SHADOWTABLE NewEntry; + ULONG i, j, result = 0, exportSize; + PBYTE fnptr; + PDWORD funcTable, nameTableBase; + PWORD nameOrdinalTableBase; + PWIN32_SHADOWTABLE w32kTableEntry; + PIMAGE_EXPORT_DIRECTORY pImageExportDirectory; - NtHeaders = RtlImageNtHeader(Module); - if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_EXPORT) - return 0; + pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(ModuleBase, + TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize); - exprva = NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; - if (exprva == 0) - return 0; + if (pImageExportDirectory) { - expsize = NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; + nameTableBase = (PDWORD)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfNames); + nameOrdinalTableBase = (PUSHORT)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfNameOrdinals); + funcTable = (PDWORD)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfFunctions); - exp = (PIMAGE_EXPORT_DIRECTORY)((ULONG_PTR)Module + exprva); - FnPtrTable = (PDWORD)((ULONG_PTR)Module + exp->AddressOfFunctions); - NameTable = (PDWORD)((ULONG_PTR)Module + exp->AddressOfNames); - NameOrdTable = (PWORD)((ULONG_PTR)Module + exp->AddressOfNameOrdinals); + result = 0; - result = 0; + for (i = 0; i < pImageExportDirectory->NumberOfFunctions; ++i) { - for (c = 0; c < exp->NumberOfFunctions; ++c) - { - fnptr = (ULONG_PTR)Module + FnPtrTable[c]; - if (*(PDWORD)fnptr != 0xb8d18b4c) //mov r10, rcx; mov eax - continue; + fnptr = (PBYTE)RtlOffsetToPointer(ModuleBase, funcTable[nameOrdinalTableBase[i]]); + if (*(PDWORD)fnptr != 0xb8d18b4c) //mov r10, rcx; mov eax + continue; - NewEntry = (PWIN32_SHADOWTABLE)HeapAlloc(HeapHandle, - HEAP_ZERO_MEMORY, sizeof(WIN32_SHADOWTABLE)); + w32kTableEntry = (PWIN32_SHADOWTABLE)HeapAlloc(HeapHandle, + HEAP_ZERO_MEMORY, sizeof(WIN32_SHADOWTABLE)); - if (NewEntry == NULL) - break; + if (w32kTableEntry == NULL) + break; - NewEntry->Index = *(PDWORD)(fnptr + 4); + w32kTableEntry->Index = *(PDWORD)(fnptr + 4); - for (n = 0; n < exp->NumberOfNames; ++n) - { - if (NameOrdTable[n] == c) + for (j = 0; j < pImageExportDirectory->NumberOfNames; ++j) { - _strncpy_a(&NewEntry->Name[0], - sizeof(NewEntry->Name), - (LPCSTR)((ULONG_PTR)Module + NameTable[n]), - sizeof(NewEntry->Name)); + if (nameOrdinalTableBase[j] == i) + { + _strncpy_a(&w32kTableEntry->Name[0], + sizeof(w32kTableEntry->Name), + (LPCSTR)RtlOffsetToPointer(ModuleBase, nameTableBase[j]), + sizeof(w32kTableEntry->Name)); - break; + break; + } } - } - ++result; + ++result; - *Table = NewEntry; - Table = &NewEntry->NextService; + *Table = w32kTableEntry; + Table = &w32kTableEntry->NextService; + } } return result; @@ -138,17 +140,18 @@ PCHAR FuzzResolveW32kServiceNameById( * Locate KiServiceTable in mapped ntoskrnl copy. * */ -BOOL FuzzFindKiServiceTable( - _In_ ULONG_PTR MappedImageBase, +BOOLEAN FuzzFindKiServiceTable( + _In_ PVOID MappedImageBase, _In_ PRAW_SERVICE_TABLE ServiceTable ) { - ULONG_PTR SectionPtr = 0; - IMAGE_NT_HEADERS* NtHeaders = RtlImageNtHeader((PVOID)MappedImageBase); + ULONG_PTR SectionPtr = 0; + PBYTE ptrCode = (PBYTE)MappedImageBase; + IMAGE_NT_HEADERS* NtHeaders = RtlImageNtHeader(MappedImageBase); IMAGE_SECTION_HEADER* SectionTableEntry; - ULONG c, p, SectionSize = 0, SectionVA = 0; + ULONG c, p, SectionSize = 0, SectionVA = 0; - const BYTE KiSystemServiceStartPattern[] = { 0x45, 0x33, 0xC9, 0x44, 0x8B, 0x05 }; + const BYTE KiSystemServiceStartPattern[] = { 0x45, 0x33, 0xC9, 0x44, 0x8B, 0x05 }; SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeaders + sizeof(ULONG) + @@ -164,7 +167,7 @@ BOOL FuzzFindKiServiceTable( { SectionVA = SectionTableEntry->VirtualAddress; - SectionPtr = (ULONG_PTR)(MappedImageBase + SectionVA); + SectionPtr = (ULONG_PTR)RtlOffsetToPointer(MappedImageBase, SectionVA); SectionSize = SectionTableEntry->Misc.VirtualSize; break; } @@ -191,14 +194,14 @@ BOOL FuzzFindKiServiceTable( return FALSE; p += 3; - c = *((PULONG)(MappedImageBase + p + 3)) + 7 + p; - ServiceTable->CountOfEntries = *((PULONG)(MappedImageBase + c)); + c = *((PULONG)(ptrCode + p + 3)) + 7 + p; + ServiceTable->CountOfEntries = *((PULONG)(ptrCode + c)); p += 7; - c = *((PULONG)(MappedImageBase + p + 3)) + 7 + p; - ServiceTable->StackArgumentTable = (PBYTE)MappedImageBase + c; + c = *((PULONG)(ptrCode + p + 3)) + 7 + p; + ServiceTable->StackArgumentTable = (PBYTE)ptrCode + c; p += 7; - c = *((PULONG)(MappedImageBase + p + 3)) + 7 + p; - ServiceTable->ServiceTable = (LPVOID*)(MappedImageBase + c); + c = *((PULONG)(ptrCode + p + 3)) + 7 + p; + ServiceTable->ServiceTable = (LPVOID*)(ptrCode + c); return TRUE; } @@ -211,23 +214,23 @@ BOOL FuzzFindKiServiceTable( * Locate shadow table info in mapped win32k copy. * */ -BOOL FuzzFindW32pServiceTable( - _In_ HMODULE MappedImageBase, +BOOLEAN FuzzFindW32pServiceTable( + _In_ PVOID MappedImageBase, _In_ PRAW_SERVICE_TABLE ServiceTable ) { PULONG ServiceLimit; - ServiceLimit = (ULONG*)GetProcAddress(MappedImageBase, "W32pServiceLimit"); + ServiceLimit = (ULONG*)supLdrGetProcAddressEx(MappedImageBase, "W32pServiceLimit"); if (ServiceLimit == NULL) return FALSE; ServiceTable->CountOfEntries = *ServiceLimit; - ServiceTable->StackArgumentTable = (PBYTE)GetProcAddress(MappedImageBase, "W32pArgumentTable"); + ServiceTable->StackArgumentTable = (PBYTE)supLdrGetProcAddressEx(MappedImageBase, "W32pArgumentTable"); if (ServiceTable->StackArgumentTable == NULL) return FALSE; - ServiceTable->ServiceTable = (LPVOID*)GetProcAddress(MappedImageBase, "W32pServiceTable"); + ServiceTable->ServiceTable = (LPVOID*)supLdrGetProcAddressEx(MappedImageBase, "W32pServiceTable"); if (ServiceTable->ServiceTable == NULL) return FALSE; @@ -242,23 +245,21 @@ BOOL FuzzFindW32pServiceTable( * Fuzzing procedure, building parameters list and using syscall gate. * */ -void DoSystemCall( +VOID DoSystemCall( _In_ ULONG ServiceId, _In_ ULONG ParametersInStack, _In_ PVOID LogParams ) { - ULONG c; - ULONG_PTR Arguments[MAX_PARAMETERS]; - ULONG64 u_rand; + ULONG c; + ULONG_PTR args[MAX_PARAMETERS]; - RtlSecureZeroMemory(Arguments, sizeof(Arguments)); + RtlSecureZeroMemory(args, sizeof(args)); ParametersInStack /= 4; for (c = 0; c < ParametersInStack + 4; c++) { - u_rand = __rdtsc(); - Arguments[c] = fuzzdata[u_rand % SIZEOF_FUZZDATA]; + args[c] = FuzzData[__rdtsc() % FUZZDATA_COUNT]; } if (g_ctx.LogEnabled) { @@ -266,12 +267,11 @@ void DoSystemCall( FuzzLogCallParameters((PNTCALL_LOG_PARAMS)LogParams, ServiceId, ParametersInStack + 4, - (ULONG_PTR*)&Arguments); + (ULONG_PTR*)&args); } - ntSyscallGate(ServiceId, ParametersInStack + 4, Arguments); - + ntSyscallGate(ServiceId, ParametersInStack + 4, args); } /* @@ -282,57 +282,56 @@ void DoSystemCall( * Build shadow table service names list. * */ -BOOL FuzzLookupWin32kNames( - _In_ LPWSTR ModuleName, - _Inout_ NTCALL_CONTEXT *Context +BOOLEAN FuzzLookupWin32kNames( + _Inout_ NTCALL_CONTEXT* Context ) { - ULONG BuildNumber = 0, i; - ULONG_PTR MappedImageBase = Context->SystemImageBase; - PIMAGE_NT_HEADERS NtHeaders = RtlImageNtHeader((PVOID)MappedImageBase); - PRAW_SERVICE_TABLE ServiceTable = &Context->ServiceTable; - ULONG_PTR Address; - CHAR **lpServiceNames; + ULONG dwBuildNumber = 0, i; + PVOID MappedImageBase = Context->SystemModuleBase; + PIMAGE_NT_HEADERS NtHeaders = RtlImageNtHeader((PVOID)MappedImageBase); + PRAW_SERVICE_TABLE ServiceTable = &Context->ServiceTable; + ULONG_PTR Address; + PCHAR* lpServiceNames; - DWORD64 *pW32pServiceTable = NULL; - CHAR **Names = NULL; - PCHAR pfn; + DWORD64* pW32pServiceTable = NULL; + PCHAR* pszNames = NULL; + PCHAR pfn; - IMAGE_IMPORT_BY_NAME *ImportEntry; + IMAGE_IMPORT_BY_NAME* ImportEntry; HMODULE win32u = NULL; ULONG win32uLimit; PWIN32_SHADOWTABLE ShadowTable = NULL; - PCHAR ServiceName; + PCHAR lpServiceName; hde64s hs; - if (!GetImageVersionInfo(ModuleName, NULL, NULL, &BuildNumber, NULL)) { - ConsoleShowMessage("[!] Failed to query win32k.sys version information.\r\n", - FOREGROUND_RED | FOREGROUND_INTENSITY); - return FALSE; - } +#ifdef _DEBUG + dwBuildNumber = g_ctx.OsVersion.dwBuildNumber; +#else + dwBuildNumber = g_ctx.OsVersion.dwBuildNumber; +#endif - switch (BuildNumber) { + switch (dwBuildNumber) { - case 7600: - case 7601: + case NT_WIN7_RTM: + case NT_WIN7_SP1: if (ServiceTable->CountOfEntries != W32pServiceTableLimit_7601) return FALSE; - Names = (CHAR**)W32pServiceTableNames_7601; + pszNames = (CHAR**)W32pServiceTableNames_7601; break; - case 9200: + case NT_WIN8_RTM: if (ServiceTable->CountOfEntries != W32pServiceTableLimit_9200) return FALSE; - Names = (CHAR**)W32pServiceTableNames_9200; + pszNames = (CHAR**)W32pServiceTableNames_9200; break; - case 9600: + case NT_WIN8_BLUE: if (ServiceTable->CountOfEntries != W32pServiceTableLimit_9600) return FALSE; - Names = (CHAR**)W32pServiceTableNames_9600; + pszNames = (CHAR**)W32pServiceTableNames_9600; break; default: @@ -341,9 +340,7 @@ BOOL FuzzLookupWin32kNames( break; } - lpServiceNames = (CHAR**)HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - ServiceTable->CountOfEntries * sizeof(PCHAR)); + lpServiceNames = (CHAR**)supHeapAlloc(ServiceTable->CountOfEntries * sizeof(PCHAR)); if (lpServiceNames == NULL) return FALSE; @@ -357,24 +354,21 @@ BOOL FuzzLookupWin32kNames( // If win32k version below 10240 copy them from predefined array. // Otherwise lookup them dynamically. // - if (BuildNumber < 10240) { - if (Names == NULL) + if (dwBuildNumber < NT_WIN10_THRESHOLD1) { + if (pszNames == NULL) return FALSE; for (i = 0; i < ServiceTable->CountOfEntries; i++) { - lpServiceNames[i] = Names[i]; + lpServiceNames[i] = pszNames[i]; } } else { - // - // - // - if (BuildNumber >= 14393) { + if (dwBuildNumber >= NT_WIN10_REDSTONE1) { - win32u = LoadLibraryEx(TEXT("win32u.dll"), NULL, 0); + win32u = GetModuleHandle(TEXT("win32u.dll")); if (win32u == NULL) { - ConsoleShowMessage("[!] Failed to load win32u.dll.\r\n", + ConsoleShowMessage("[!] Failed to reference win32u.dll.\r\n", FOREGROUND_RED | FOREGROUND_INTENSITY); return FALSE; } @@ -391,10 +385,10 @@ BOOL FuzzLookupWin32kNames( for (i = 0; i < ServiceTable->CountOfEntries; i++) { - ServiceName = "UnknownName"; + lpServiceName = "UnknownName"; - if (BuildNumber <= 10586) { - pfn = (PCHAR)(pW32pServiceTable[i] - NtHeaders->OptionalHeader.ImageBase + MappedImageBase); + if (dwBuildNumber <= NT_WIN10_THRESHOLD2) { + pfn = (PCHAR)(pW32pServiceTable[i] - NtHeaders->OptionalHeader.ImageBase + (ULONG_PTR)MappedImageBase); hde64_disasm((void*)pfn, &hs); if (hs.flags & F_ERROR) { @@ -403,24 +397,23 @@ BOOL FuzzLookupWin32kNames( break; } - Address = MappedImageBase + *(ULONG_PTR*)(pfn + hs.len + *(DWORD*)(pfn + (hs.len - 4))); + Address = (ULONG_PTR)MappedImageBase + *(ULONG_PTR*)(pfn + hs.len + *(DWORD*)(pfn + (hs.len - 4))); if (Address) { - ImportEntry = (IMAGE_IMPORT_BY_NAME *)Address; - ServiceName = ImportEntry->Name; + ImportEntry = (IMAGE_IMPORT_BY_NAME*)Address; + lpServiceName = ImportEntry->Name; } } - else if (BuildNumber >= 14393) { + else if (dwBuildNumber >= NT_WIN10_REDSTONE1) { - ServiceName = FuzzResolveW32kServiceNameById(i + 0x1000, ShadowTable); - if (ServiceName == NULL) ServiceName = "UnknownName"; + lpServiceName = FuzzResolveW32kServiceNameById(i + W32SYSCALLSTART, ShadowTable); + if (lpServiceName == NULL) + lpServiceName = "UnknownName"; } - lpServiceNames[i] = ServiceName; + lpServiceNames[i] = lpServiceName; } } - if (win32u) FreeLibrary(win32u); - return TRUE; } @@ -438,7 +431,7 @@ DWORD WINAPI FuzzThreadProc( { ULONG64 i, c; HMODULE hUser32 = NULL; - CALL_PARAM *Context = (CALL_PARAM*)Parameter; + CALL_PARAM* Context = (CALL_PARAM*)Parameter; if (Context->Syscall >= W32SYSCALLSTART) hUser32 = LoadLibrary(TEXT("user32.dll")); @@ -469,7 +462,7 @@ void PrintServiceInformation( _In_opt_ LPCSTR ServiceName, _In_ BOOL BlackListed) { - CHAR *pLog; + CHAR* pLog; CHAR szConsoleText[4096]; WORD wColor = 0; @@ -507,7 +500,7 @@ void PrintServiceInformation( * */ VOID FuzzRunThreadWithWait( - _In_ CALL_PARAM *CallParams + _In_ CALL_PARAM* CallParams ) { HANDLE hThread; @@ -541,18 +534,18 @@ VOID FuzzRunThreadWithWait( * */ VOID FuzzRun( - _In_ NTCALL_CONTEXT *Context + _In_ NTCALL_CONTEXT* Context ) { BOOL probeWin32k = Context->ProbeWin32k, bSkip = FALSE; - BLACKLIST *BlackList = &Context->BlackList; - ULONG_PTR hNtdll = Context->hNtdll; + BLACKLIST* BlackList = &Context->BlackList; + PVOID ntdllBase = Context->NtdllBase; PRAW_SERVICE_TABLE ServiceTable = &Context->ServiceTable; ULONG c, sid; CALL_PARAM CallParams; - PCHAR ServiceName, pLog; + PCHAR lpServiceName, pLog; CHAR szOut[MAX_PATH * 2]; @@ -568,22 +561,22 @@ VOID FuzzRun( // Query service name. // if (probeWin32k) { - sid = Context->SingleSyscallId - W32SYSCALLSTART; - ServiceName = Context->Win32pServiceTableNames[sid]; + sid = Context->u1.SingleSyscallId - W32SYSCALLSTART; + lpServiceName = Context->Win32pServiceTableNames[sid]; } else { - sid = Context->SingleSyscallId; - ServiceName = (PCHAR)PELoaderGetProcNameBySDTIndex(hNtdll, sid); + sid = Context->u1.SingleSyscallId; + lpServiceName = supLdrGetProcNameBySDTIndex(ntdllBase, sid); } // // Output service information to console. // _strcpy_a(szOut, "\tProbing #"); - ultostr_a(Context->SingleSyscallId, _strend_a(szOut)); + ultostr_a(Context->u1.SingleSyscallId, _strend_a(szOut)); pLog = _strcat_a(szOut, "\t"); - if (ServiceName) { - _strncpy_a(pLog, MAX_PATH, ServiceName, MAX_PATH); + if (lpServiceName) { + _strncpy_a(pLog, MAX_PATH, lpServiceName, MAX_PATH); } else { _strcpy_a(pLog, "Unknown"); @@ -595,7 +588,7 @@ VOID FuzzRun( // Setup service call parameters and call it in separate thread. // CallParams.ParametersInStack = Context->ServiceTable.StackArgumentTable[sid]; - CallParams.Syscall = Context->SingleSyscallId; + CallParams.Syscall = Context->u1.SingleSyscallId; CallParams.ThreadTimeout = INFINITE; CallParams.NumberOfPassesForCall = Context->SyscallPassCount; CallParams.LogParams = &g_Log; @@ -604,22 +597,30 @@ VOID FuzzRun( } else { - for (c = 0; c < ServiceTable->CountOfEntries; c++) { + c = 0; + if (Context->ProbeFromSyscallId) { + if (Context->ProbeWin32k) + c = Context->u1.StartingSyscallId - W32SYSCALLSTART; + else + c = Context->u1.StartingSyscallId; + } + + for (; c < ServiceTable->CountOfEntries; c++) { // // Query service name. // if (probeWin32k) { - ServiceName = Context->Win32pServiceTableNames[c]; + lpServiceName = Context->Win32pServiceTableNames[c]; sid = W32SYSCALLSTART + c; } else { - ServiceName = (PCHAR)PELoaderGetProcNameBySDTIndex(hNtdll, c); + lpServiceName = supLdrGetProcNameBySDTIndex(ntdllBase, c); sid = c; } - if (ServiceName) { - bSkip = BlackListEntryPresent(BlackList, (LPCSTR)ServiceName); + if (lpServiceName) { + bSkip = BlackListEntryPresent(BlackList, (LPCSTR)lpServiceName); } // @@ -627,7 +628,7 @@ VOID FuzzRun( // PrintServiceInformation(ServiceTable->StackArgumentTable[c] / 4, sid, - ServiceName, + lpServiceName, bSkip); if (bSkip) { diff --git a/Source/NtCall64/fuzz.h b/Source/NtCall64/fuzz.h index 0b0a74f..2f10f02 100644 --- a/Source/NtCall64/fuzz.h +++ b/Source/NtCall64/fuzz.h @@ -1,12 +1,12 @@ /******************************************************************************* * -* (C) COPYRIGHT AUTHORS, 2016 - 2021 +* (C) COPYRIGHT AUTHORS, 2016 - 2023 * * TITLE: FUZZ.H * -* VERSION: 1.35 +* VERSION: 1.37 * -* DATE: 21 Feb 2021 +* DATE: 04 Aug 2023 * * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED @@ -17,30 +17,21 @@ #pragma once #define W32SYSCALLSTART 0x1000 -#define MAX_PARAMETERS 32 -#define SIZEOF_FUZZDATA 13 +#define MAX_PARAMETERS 32 #define FUZZ_THREAD_TIMEOUT_SEC (30) #define FUZZ_PASS_COUNT (64) * (1024) -static const ULONG_PTR fuzzdata[SIZEOF_FUZZDATA] = { - 0x0000000000000000, 0x000000000000ffff, 0x000000000000fffe, 0x00007ffffffeffff, - 0x00007ffffffefffe, 0x00007fffffffffff, 0x00007ffffffffffe, 0x0000800000000000, - 0x8000000000000000, 0xffff080000000000, 0xfffff80000000000, 0xffff800000000000, - 0xffff800000000001 -}; - VOID FuzzRun( _In_ NTCALL_CONTEXT *Context); -BOOL FuzzLookupWin32kNames( - _In_ LPWSTR ModuleName, +BOOLEAN FuzzLookupWin32kNames( _Inout_ NTCALL_CONTEXT *Context); -BOOL FuzzFindW32pServiceTable( - _In_ HMODULE MappedImageBase, +BOOLEAN FuzzFindW32pServiceTable( + _In_ PVOID MappedImageBase, _In_ PRAW_SERVICE_TABLE ServiceTable); -BOOL FuzzFindKiServiceTable( - _In_ ULONG_PTR MappedImageBase, +BOOLEAN FuzzFindKiServiceTable( + _In_ PVOID MappedImageBase, _In_ PRAW_SERVICE_TABLE ServiceTable); diff --git a/Source/NtCall64/global.h b/Source/NtCall64/global.h index 9bb2365..2bae109 100644 --- a/Source/NtCall64/global.h +++ b/Source/NtCall64/global.h @@ -1,12 +1,12 @@ /******************************************************************************* * -* (C) COPYRIGHT AUTHORS, 2016 - 2021 +* (C) COPYRIGHT AUTHORS, 2016 - 2023 * * TITLE: GLOBAL.H * -* VERSION: 1.35 +* VERSION: 1.37 * -* DATE: 21 Feb 2021 +* DATE: 04 Aug 2023 * * Global definitions. * @@ -41,12 +41,13 @@ #include#include #include "ntos.h" +#include "ntbuilds.h" #include "hde\hde64.h" #include "minirtl\minirtl.h" #include "minirtl\_filename.h" #include "minirtl\cmdline.h" #include "blacklist.h" -#include "util.h" +#include "sup.h" #include "log.h" #pragma comment(lib, "Version.lib") @@ -66,29 +67,37 @@ typedef struct _CALL_PARAM { } CALL_PARAM, *PCALL_PARAM; typedef struct _NTCALL_CONTEXT { - BOOL LogEnabled; - BOOL ProbeWin32k; - BOOL ProbeSingleSyscall; - BOOL IsUserInAdminGroup; - BOOL IsLocalSystem; - BOOL IsElevated; - ULONG SingleSyscallId; + BOOLEAN LogEnabled; + BOOLEAN ProbeWin32k; + BOOLEAN ProbeSingleSyscall; + BOOLEAN ProbeFromSyscallId; + BOOLEAN IsUserFullAdmin; + BOOLEAN IsLocalSystem; + BOOLEAN IsElevated; + union { + ULONG SingleSyscallId; + ULONG StartingSyscallId; + } u1; ULONG ThreadWaitTimeout; ULONG64 SyscallPassCount; - ULONG_PTR hNtdll; - ULONG_PTR SystemImageBase; - CHAR **Win32pServiceTableNames; + PVOID NtdllBase; + PVOID SystemModuleBase; + PCHAR *Win32pServiceTableNames; RAW_SERVICE_TABLE ServiceTable; BLACKLIST BlackList; - WCHAR szSystemDirectory[MAX_PATH + 1]; + RTL_OSVERSIONINFOW OsVersion; } NTCALL_CONTEXT, *PNTCALL_CONTEXT; typedef struct _NTCALL_FUZZ_PARAMS { - BOOL EnableLog; - BOOL LogToFile; - BOOL ProbeWin32k; - BOOL ProbeSingleSyscall; - ULONG SingleSyscallId; + BOOLEAN LogEnabled; + BOOLEAN LogToFile; + BOOLEAN ProbeWin32k; + BOOLEAN ProbeSingleSyscall; + BOOLEAN ProbeFromSyscallId; + union { + ULONG SingleSyscallId; + ULONG StartingSyscallId; + } u1; ULONG ThreadWaitTimeout; ULONG64 SyscallPassCount; WCHAR szLogDeviceOrFile[MAX_PATH + 1]; diff --git a/Source/NtCall64/log.c b/Source/NtCall64/log.c index d61dbdf..dec2f63 100644 --- a/Source/NtCall64/log.c +++ b/Source/NtCall64/log.c @@ -27,15 +27,15 @@ * Open port/file for logging. * */ -BOOL FuzzOpenLog( +BOOLEAN FuzzOpenLog( _In_ LPWSTR LogDeviceFileName, _In_ PNTCALL_LOG_PARAMS LogParams ) { - HANDLE hFile; - CHAR szWelcome[128]; - DWORD bytesIO; - DWORD openFlags = OPEN_EXISTING; + HANDLE hFile; + CHAR szWelcome[128]; + DWORD bytesIO; + DWORD openFlags = OPEN_EXISTING; if (LogParams->LogToFile) openFlags = CREATE_ALWAYS; //always overwrite existing log file. diff --git a/Source/NtCall64/log.h b/Source/NtCall64/log.h index ad35a93..ae70cad 100644 --- a/Source/NtCall64/log.h +++ b/Source/NtCall64/log.h @@ -1,12 +1,12 @@ /******************************************************************************* * -* (C) COPYRIGHT AUTHORS, 2016 - 2021 +* (C) COPYRIGHT AUTHORS, 2016 - 2023 * * TITLE: LOG.H * -* VERSION: 1.35 +* VERSION: 1.37 * -* DATE: 21 Feb 2021 +* DATE: 04 Aug 2023 * * Log support header file. * @@ -24,7 +24,7 @@ typedef struct _NTCALL_LOG_PARAMS { HANDLE LogHandle; } NTCALL_LOG_PARAMS, * PNTCALL_LOG_PARAMS; -BOOL FuzzOpenLog( +BOOLEAN FuzzOpenLog( _In_ LPWSTR LogDeviceFileName, _In_ PNTCALL_LOG_PARAMS LogParams); diff --git a/Source/NtCall64/main.c b/Source/NtCall64/main.c index 6ac75d7..9999a2e 100644 --- a/Source/NtCall64/main.c +++ b/Source/NtCall64/main.c @@ -1,12 +1,12 @@ /******************************************************************************* * -* (C) COPYRIGHT AUTHORS, 2016 - 2022 +* (C) COPYRIGHT AUTHORS, 2016 - 2023 * * TITLE: MAIN.C * -* VERSION: 1.36 +* VERSION: 1.37 * -* DATE: 04 Sep 2022 +* DATE: 04 Aug 2023 * * Program entry point. * @@ -28,25 +28,27 @@ #define PARAM_WAITTIMEOUT TEXT("-wt") #define PARAM_HELP TEXT("-help") #define PARAM_LOCALSYSTEM TEXT("-s") +#define PARAM_SYSCALL_START TEXT("-start") #define DEFAULT_LOG_PORT TEXT("COM1") #define DEFAULT_LOG_FILE TEXT("ntcall64.log") #define WELCOME_BANNER "NtCall64, Windows NT x64 syscall fuzzer, based on NtCall by Peter Kosyh.\r\n" -#define VERSION_BANNER "Version 1.3.6 from 04 Sep 2022\r\n\n" +#define VERSION_BANNER "Version 1.3.7 from 04 Aug 2023\r\n\n" // // Help output. // #define T_HELP "Usage: -help [-win32k][-log [-pname][-ofile]][-call Id][-pc Value][-wt Value][-s]\r\n\ -help - Show this help information;\r\n\ - -log - Enable logging to file last call parameters;\r\n\ + -log - Enable logging to file last call parameters, use -ofile to specify file otherwise COM port will be used;\r\n\ -pname - Port name for logging, default COM1 (-log enabled required, mutual exclusive with -ofile);\r\n\ -ofile - File name for logging, default ntcall64.log (-log enabled required, mutual exclusive with -pname);\r\n\ -win32k - Fuzz win32k graphical subsystem table, otherwise fuzz ntos table;\r\n\ -call Id - Fuzz syscall by supplied numeric (can be from any table). All blacklists are ignored;\r\n\ -pc Value - Set number of passes for each service to , default value 65536;\r\n\ -wt Value - Set wait timeout for calling threads in seconds (except single syscall fuzzing), default value is 30;\r\n\ + -start Id - Fuzz syscall table starting from given syscall id, mutual exclusive with -call;\r\n\ -s - Attempt to run program from LocalSystem account.\r\n\n\ Example: ntcall64.exe -win32k -log" @@ -133,36 +135,40 @@ void FuzzInitPhase2( BOOL probeWin32k = Context->ProbeWin32k; ULONG d; + NTSTATUS ntStatus; + UNICODE_STRING usModule; + WCHAR szBuffer[MAX_PATH * 2]; ConsoleShowMessage("[+] Entering FuzzInitPhase2()\r\n", FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); - _strcpy(szBuffer, Context->szSystemDirectory); + _strcpy(szBuffer, L"\\systemroot\\system32\\"); if (probeWin32k) { - _strcat(szBuffer, TEXT("\\win32k.sys")); + _strcat(szBuffer, TEXT("win32k.sys")); } else { - _strcat(szBuffer, TEXT("\\ntoskrnl.exe")); + _strcat(szBuffer, TEXT("ntoskrnl.exe")); } - Context->SystemImageBase = (ULONG_PTR)LoadLibraryEx(szBuffer, NULL, 0); + RtlInitUnicodeString(&usModule, szBuffer); + + ntStatus = supMapImageNoExecute(&usModule, &Context->SystemModuleBase); - if (Context->SystemImageBase == 0) { - ConsoleShowMessage("[!] Could not preload system image, abort!\r\n", - FOREGROUND_RED | FOREGROUND_INTENSITY); + if (!NT_SUCCESS(ntStatus) || (Context->SystemModuleBase == NULL)) { + supShowNtStatus("[!] Could not preload system image, abort!\r\n", ntStatus); return; } if (probeWin32k) { - if (!FuzzFindW32pServiceTable((HMODULE)Context->SystemImageBase, &Context->ServiceTable)) { + if (!FuzzFindW32pServiceTable(Context->SystemModuleBase, &Context->ServiceTable)) { ConsoleShowMessage("[!] Could not find W32pServiceTable, abort!\r\n", FOREGROUND_RED | FOREGROUND_INTENSITY); return; } - if (!FuzzLookupWin32kNames(szBuffer, Context)) { + if (!FuzzLookupWin32kNames(Context)) { ConsoleShowMessage("[!] Win32k names query error, abort!\r\n", FOREGROUND_RED | FOREGROUND_INTENSITY); return; @@ -170,14 +176,14 @@ void FuzzInitPhase2( } else { - Context->hNtdll = (ULONG_PTR)GetModuleHandle(TEXT("ntdll.dll")); - if (Context->hNtdll == 0) { - ConsoleShowMessage("[!] Ntdll not found, abort!\r\n", + Context->NtdllBase = (PVOID)GetModuleHandle(TEXT("ntdll.dll")); + if (Context->NtdllBase == NULL) { + ConsoleShowMessage("[!] NTDLL not found, abort!\r\n", FOREGROUND_RED | FOREGROUND_INTENSITY); return; } - if (!FuzzFindKiServiceTable(Context->SystemImageBase, &Context->ServiceTable)) { + if (!FuzzFindKiServiceTable(Context->SystemModuleBase, &Context->ServiceTable)) { ConsoleShowMessage("[!] KiServiceTable not found, abort!\r\n", FOREGROUND_RED | FOREGROUND_INTENSITY); return; @@ -189,7 +195,7 @@ void FuzzInitPhase2( // if (Context->ProbeSingleSyscall) { - d = Context->SingleSyscallId; + d = Context->u1.SingleSyscallId; if (Context->ProbeWin32k) { d -= W32SYSCALLSTART; @@ -207,7 +213,7 @@ void FuzzInitPhase2( FuzzRun(Context); - FreeLibrary((HMODULE)Context->SystemImageBase); + NtUnmapViewOfSection(NtCurrentProcess(), Context->SystemModuleBase); ConsoleShowMessage("[-] Leaving FuzzInitPhase2()\r\n", FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); @@ -225,14 +231,12 @@ VOID FuzzInitPhase1( _In_ NTCALL_FUZZ_PARAMS* FuzzParams ) { + BOOLEAN LogEnabled = FALSE; BOOLEAN bWasEnabled = FALSE; WORD wColor = 0; UINT i; - BOOL LogEnabled = FALSE; CHAR szOut[MAX_PATH * 2]; - RTL_OSVERSIONINFOW osver; - ConsoleShowMessage("[+] Entering FuzzInitPhase1()\r\n", FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); @@ -242,8 +246,8 @@ VOID FuzzInitPhase1( if (g_ctx.IsLocalSystem) ConsoleShowMessage("[+] LocalSystem account\r\n", 0); - if (g_ctx.IsUserInAdminGroup) { - ConsoleShowMessage("[+] User is admin\r\n", 0); + if (g_ctx.IsUserFullAdmin) { + ConsoleShowMessage("[+] User is with admin privileges\r\n", 0); if (g_ctx.IsElevated) { ConsoleShowMessage("[+] NtCall64 runs elevated.\r\n", 0); @@ -253,13 +257,6 @@ VOID FuzzInitPhase1( } } - RtlSecureZeroMemory(g_ctx.szSystemDirectory, sizeof(g_ctx.szSystemDirectory)); - if (!GetSystemDirectory(g_ctx.szSystemDirectory, MAX_PATH)) { - ConsoleShowMessage("[!] Could not query system directory, abort!\r\n", - FOREGROUND_RED | FOREGROUND_INTENSITY); - return; - } - // // Show current directory. // @@ -279,17 +276,17 @@ VOID FuzzInitPhase1( // // Show version logo if possible. // - osver.dwOSVersionInfoSize = sizeof(osver); - RtlGetVersion(&osver); + g_ctx.OsVersion.dwOSVersionInfoSize = sizeof(g_ctx.OsVersion); + RtlGetVersion(&g_ctx.OsVersion); _strcpy_a(szOut, "[~] Windows version: "); - ultostr_a(osver.dwMajorVersion, _strend_a(szOut)); - ultostr_a(osver.dwMinorVersion, _strcat_a(szOut, ".")); - ultostr_a(osver.dwBuildNumber, _strcat_a(szOut, ".")); + ultostr_a(g_ctx.OsVersion.dwMajorVersion, _strend_a(szOut)); + ultostr_a(g_ctx.OsVersion.dwMinorVersion, _strcat_a(szOut, ".")); + ultostr_a(g_ctx.OsVersion.dwBuildNumber, _strcat_a(szOut, ".")); _strcat_a(szOut, "\r\n"); ConsoleShowMessage(szOut, 0); - if (FuzzParams->EnableLog) { + if (FuzzParams->LogEnabled) { g_Log.LogHandle = INVALID_HANDLE_VALUE; g_Log.LogToFile = FuzzParams->LogToFile; @@ -304,9 +301,17 @@ VOID FuzzInitPhase1( ConsoleShowMessage(szOut, FOREGROUND_RED | FOREGROUND_INTENSITY); } - else - ConsoleShowMessage("[+] Logging is enabled\r\n", + else { + _strcpy_a(szOut, "[+] Logging is enabled, output will be written to "); + + WideCharToMultiByte(CP_ACP, 0, FuzzParams->szLogDeviceOrFile, -1, + _strend_a(szOut), MAX_PATH, NULL, NULL); + + _strcat_a(szOut, "\r\n"); + + ConsoleShowMessage(szOut, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); + } g_ctx.LogEnabled = LogEnabled; @@ -319,9 +324,9 @@ VOID FuzzInitPhase1( // Handle single system call. // if (FuzzParams->ProbeSingleSyscall) { - g_ctx.ProbeWin32k = (FuzzParams->SingleSyscallId >= W32SYSCALLSTART); + g_ctx.ProbeWin32k = (FuzzParams->u1.SingleSyscallId >= W32SYSCALLSTART); g_ctx.ProbeSingleSyscall = TRUE; - g_ctx.SingleSyscallId = FuzzParams->SingleSyscallId; + g_ctx.u1.SingleSyscallId = FuzzParams->u1.SingleSyscallId; } else { g_ctx.ProbeWin32k = FuzzParams->ProbeWin32k; @@ -344,6 +349,18 @@ VOID FuzzInitPhase1( _strcat_a(szOut, "\r\n"); ConsoleShowMessage(szOut, 0); + // + // Show probe from syscall id. + // + g_ctx.ProbeFromSyscallId = FuzzParams->ProbeFromSyscallId; + g_ctx.u1.StartingSyscallId = FuzzParams->u1.StartingSyscallId; + if (g_ctx.ProbeFromSyscallId) { + _strcpy_a(szOut, "[+] Starting syscall id "); + ultostr_a(g_ctx.u1.StartingSyscallId, _strend_a(szOut)); + _strcat_a(szOut, "\r\n"); + ConsoleShowMessage(szOut, 0); + } + // // Assign much possible privileges if can. // @@ -393,7 +410,7 @@ VOID FuzzInitPhase1( } if (g_ctx.Win32pServiceTableNames) - HeapFree(GetProcessHeap(), 0, g_ctx.Win32pServiceTableNames); + supHeapFree(g_ctx.Win32pServiceTableNames); ConsoleShowMessage("[-] Leaving FuzzInitPhase1()\r\n", FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); @@ -413,8 +430,10 @@ VOID FuzzInitPhase0( { ULONG rLen; NTCALL_FUZZ_PARAMS fuzzParams; + HANDLE hToken; + NTSTATUS ntStatus; - TCHAR szTextBuf[MAX_PATH + 1]; + WCHAR szTextBuf[MAX_PATH + 1]; do { @@ -426,22 +445,42 @@ VOID FuzzInitPhase0( fuzzParams.SyscallPassCount = FUZZ_PASS_COUNT; RtlSecureZeroMemory(&g_ctx, sizeof(g_ctx)); - g_ctx.IsLocalSystem = IsLocalSystem(); - if (g_ctx.IsLocalSystem) { - g_ctx.IsElevated = TRUE; - g_ctx.IsUserInAdminGroup = TRUE; + + ntStatus = NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &hToken); + if (NT_SUCCESS(ntStatus)) { + + ntStatus = supIsLocalSystem(hToken, &g_ctx.IsLocalSystem); + if (NT_SUCCESS(ntStatus)) { + if (g_ctx.IsLocalSystem) { + g_ctx.IsElevated = TRUE; + g_ctx.IsUserFullAdmin = TRUE; + } + else { + g_ctx.IsUserFullAdmin = supUserIsFullAdmin(hToken); + if (g_ctx.IsUserFullAdmin) { + g_ctx.IsElevated = supIsClientElevated(NtCurrentProcess()); + } + } + } + else { + supShowNtStatus("[!] Failed to query process token information\r\n", ntStatus); + return; + } + + NtClose(hToken); } else { - g_ctx.IsUserInAdminGroup = IsUserInAdminGroup(); - if (g_ctx.IsUserInAdminGroup) { - g_ctx.IsElevated = IsElevated(NULL); - } + supShowNtStatus("[!] Failed to open self process token\r\n", ntStatus); + return; } - if (GetCommandLineOption(PARAM_LOCALSYSTEM, FALSE, NULL, 0, NULL)) { + // + // -s (System) param. + // + if (supGetCommandLineOption(PARAM_LOCALSYSTEM, FALSE, NULL, 0, NULL)) { if (g_ctx.IsLocalSystem == FALSE) { - if (g_ctx.IsUserInAdminGroup == FALSE) { - ConsoleShowMessage("[~] Administrative privileges reqruied for this operation\r\n", 0); + if (g_ctx.IsUserFullAdmin == FALSE) { + ConsoleShowMessage("[~] Administrative privileges are required for this operation\r\n", 0); break; } if (g_ctx.IsElevated == FALSE) { @@ -449,7 +488,7 @@ VOID FuzzInitPhase0( break; } ConsoleShowMessage("[~] Restarting as LocalSystem\r\n", 0); - RunAsLocalSystem(); + supRunAsLocalSystem(); break; } // @@ -457,19 +496,31 @@ VOID FuzzInitPhase0( // } - fuzzParams.ProbeWin32k = GetCommandLineOption(PARAM_WIN32K, FALSE, NULL, 0, NULL); - fuzzParams.EnableLog = GetCommandLineOption(PARAM_LOG, FALSE, NULL, 0, NULL); - if (fuzzParams.EnableLog) { + // + // -win32k param. + // + fuzzParams.ProbeWin32k = supGetCommandLineOption(PARAM_WIN32K, FALSE, NULL, 0, NULL); + + // + // -log param. + // + fuzzParams.LogEnabled = supGetCommandLineOption(PARAM_LOG, FALSE, NULL, 0, NULL); + if (fuzzParams.LogEnabled) { _strcpy(fuzzParams.szLogDeviceOrFile, DEFAULT_LOG_PORT); fuzzParams.LogToFile = FALSE; // - // Check log port name. + // Check log port name (-pname). // rLen = 0; RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf)); - if (GetCommandLineOption(PARAM_LOGPORT, TRUE, szTextBuf, sizeof(szTextBuf) / sizeof(TCHAR), &rLen)) { + if (supGetCommandLineOption(PARAM_LOGPORT, + TRUE, + szTextBuf, + RTL_NUMBER_OF(szTextBuf), + &rLen)) + { if (rLen) { _strcpy(fuzzParams.szLogDeviceOrFile, szTextBuf); } @@ -477,11 +528,16 @@ VOID FuzzInitPhase0( else { // - // Check log file name. + // Check log file name (-ofile). // rLen = 0; RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf)); - if (GetCommandLineOption(PARAM_LOGFILE, TRUE, szTextBuf, sizeof(szTextBuf) / sizeof(TCHAR), &rLen)) { + if (supGetCommandLineOption(PARAM_LOGFILE, + TRUE, + szTextBuf, + RTL_NUMBER_OF(szTextBuf), + &rLen)) + { if (rLen) { _strcpy(fuzzParams.szLogDeviceOrFile, szTextBuf); } @@ -494,15 +550,45 @@ VOID FuzzInitPhase0( } } + // + // -call (SyscallId) param. + // RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf)); - if (GetCommandLineOption(PARAM_SYSCALL, TRUE, szTextBuf, sizeof(szTextBuf) / sizeof(TCHAR), NULL)) + if (supGetCommandLineOption(PARAM_SYSCALL, + TRUE, + szTextBuf, + RTL_NUMBER_OF(szTextBuf), + NULL)) { fuzzParams.ProbeSingleSyscall = TRUE; - fuzzParams.SingleSyscallId = _strtoul(szTextBuf); + fuzzParams.u1.SingleSyscallId = _strtoul(szTextBuf); + } + + if (fuzzParams.ProbeSingleSyscall == FALSE) { + // + // -start (SyscallId) param. + // + RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf)); + if (supGetCommandLineOption(PARAM_SYSCALL_START, + TRUE, + szTextBuf, + RTL_NUMBER_OF(szTextBuf), + NULL)) + { + fuzzParams.ProbeFromSyscallId = TRUE; + fuzzParams.u1.StartingSyscallId = _strtoul(szTextBuf); + } } + // + // -pc (PassCount) param. + // RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf)); - if (GetCommandLineOption(PARAM_PASSCOUNT, TRUE, szTextBuf, sizeof(szTextBuf) / sizeof(TCHAR), NULL)) + if (supGetCommandLineOption(PARAM_PASSCOUNT, + TRUE, + szTextBuf, + RTL_NUMBER_OF(szTextBuf), + NULL)) { fuzzParams.SyscallPassCount = strtou64(szTextBuf); } @@ -515,8 +601,15 @@ VOID FuzzInitPhase0( break; } + // + // -wt (WaitTimeout) param. + // RtlSecureZeroMemory(szTextBuf, sizeof(szTextBuf)); - if (GetCommandLineOption(PARAM_WAITTIMEOUT, TRUE, szTextBuf, sizeof(szTextBuf) / sizeof(TCHAR), NULL)) + if (supGetCommandLineOption(PARAM_WAITTIMEOUT, + TRUE, + szTextBuf, + RTL_NUMBER_OF(szTextBuf), + NULL)) { fuzzParams.ThreadWaitTimeout = _strtoul(szTextBuf); } @@ -554,7 +647,7 @@ UINT NtCall64Main() do { - if (GetCommandLineOption(PARAM_HELP, FALSE, NULL, 0, NULL)) { + if (supGetCommandLineOption(PARAM_HELP, FALSE, NULL, 0, NULL)) { ConsoleShowMessage(T_HELP, 0); break; } diff --git a/Source/NtCall64/minirtl/strtou64.c b/Source/NtCall64/minirtl/strtou64.c index 1ec829c..fad5eb3 100644 --- a/Source/NtCall64/minirtl/strtou64.c +++ b/Source/NtCall64/minirtl/strtou64.c @@ -11,7 +11,7 @@ unsigned long long strtou64_a(char *s) while (*s != 0) { c = *s; if (_isdigit_w(c)) - a = (a*10)+(c-'0'); + a = (a*10)+((unsigned long long)c-'0'); else break; s++; @@ -30,7 +30,7 @@ unsigned long long strtou64_w(wchar_t *s) while (*s != 0) { c = *s; if (_isdigit_w(c)) - a = (a*10)+(c-L'0'); + a = (a*10)+((unsigned long long)c-L'0'); else break; s++; diff --git a/Source/NtCall64/minirtl/strtoul.c b/Source/NtCall64/minirtl/strtoul.c index 3250d74..4fcd0bb 100644 --- a/Source/NtCall64/minirtl/strtoul.c +++ b/Source/NtCall64/minirtl/strtoul.c @@ -1,49 +1,39 @@ #include "rtltypes.h" -#define ULONG_MAX_VALUE 0xffffffffUL - unsigned long strtoul_a(char *s) { - unsigned long long a = 0; - char c; - - if (s == 0) - return 0; - - while (*s != 0) { - c = *s; - if (_isdigit_a(c)) - a = (a*10)+(c-'0'); - else - break; - - if (a > ULONG_MAX_VALUE) - return ULONG_MAX_VALUE; - - s++; - } - return (unsigned long)a; + unsigned long a = 0; + char c; + + if (s == 0) + return 0; + + while (*s != 0) { + c = *s; + if (_isdigit_a(c)) + a = (a*10)+(c-'0'); + else + break; + s++; + } + return a; } unsigned long strtoul_w(wchar_t *s) { - unsigned long long a = 0; - wchar_t c; - - if (s == 0) - return 0; - - while (*s != 0) { - c = *s; - if (_isdigit_w(c)) - a = (a * 10) + (c - L'0'); - else - break; - - if (a > ULONG_MAX_VALUE) - return ULONG_MAX_VALUE; - - s++; - } - return (unsigned long)a; + unsigned long a = 0; + wchar_t c; + + if (s == 0) + return 0; + + while (*s != 0) { + c = *s; + if (_isdigit_w(c)) + a = (a*10)+(c-L'0'); + else + break; + s++; + } + return a; } diff --git a/Source/NtCall64/ntbuilds.h b/Source/NtCall64/ntbuilds.h new file mode 100644 index 0000000..f92204d --- /dev/null +++ b/Source/NtCall64/ntbuilds.h @@ -0,0 +1,90 @@ +/******************************************************************************* +* +* (C) COPYRIGHT AUTHORS, 2021 - 2023 +* +* TITLE: NTBUILDS.H +* +* VERSION: 1.18 +* +* DATE: 21 Jul 2023 +* +* Windows NT builds definition file. +* +* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED +* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +* PARTICULAR PURPOSE. +* +*******************************************************************************/ +#pragma once + +// +// Defines for Major Windows NT release builds +// + +// Windows 7 RTM +#define NT_WIN7_RTM 7600 + +// Windows 7 SP1 +#define NT_WIN7_SP1 7601 + +// Windows 8 RTM +#define NT_WIN8_RTM 9200 + +// Windows 8.1 +#define NT_WIN8_BLUE 9600 + +// Windows 10 TH1 +#define NT_WIN10_THRESHOLD1 10240 + +// Windows 10 TH2 +#define NT_WIN10_THRESHOLD2 10586 + +// Windows 10 RS1 +#define NT_WIN10_REDSTONE1 14393 + +// Windows 10 RS2 +#define NT_WIN10_REDSTONE2 15063 + +// Windows 10 RS3 +#define NT_WIN10_REDSTONE3 16299 + +// Windows 10 RS4 +#define NT_WIN10_REDSTONE4 17134 + +// Windows 10 RS5 +#define NT_WIN10_REDSTONE5 17763 + +// Windows 10 19H1 +#define NT_WIN10_19H1 18362 + +// Windows 10 19H2 +#define NT_WIN10_19H2 18363 + +// Windows 10 20H1 +#define NT_WIN10_20H1 19041 + +// Windows 10 20H2 +#define NT_WIN10_20H2 19042 + +// Windows 10 21H1 +#define NT_WIN10_21H1 19043 + +// Windows 10 21H2 +#define NT_WIN10_21H2 19044 + +// Windows 10 22H2 +#define NT_WIN10_22H2 19045 + +// Windows Server 2022 +#define NT_WINSRV_21H1 20348 + +// Windows 11 21H2 +#define NT_WIN11_21H2 22000 + +// Windows 11 22H2 +#define NT_WIN11_22H2 22621 + +// Windows 11 Active Develepment Branch +#define NT_WIN11_23H2 22631 +#define NT_WIN11_24H2 25905 //canary (24H2) diff --git a/Source/NtCall64/resource.rc b/Source/NtCall64/resource.rc index fe710be..594a216 100644 Binary files a/Source/NtCall64/resource.rc and b/Source/NtCall64/resource.rc differ diff --git a/Source/NtCall64/util.c b/Source/NtCall64/sup.c similarity index 68% rename from Source/NtCall64/util.c rename to Source/NtCall64/sup.c index 2100606..d7e46c3 100644 --- a/Source/NtCall64/util.c +++ b/Source/NtCall64/sup.c @@ -1,12 +1,12 @@ /******************************************************************************* * -* (C) COPYRIGHT AUTHORS, 2016 - 2022 +* (C) COPYRIGHT AUTHORS, 2016 - 2023 * -* TITLE: UTIL.C +* TITLE: SUP.C * -* VERSION: 1.36 +* VERSION: 1.37 * -* DATE: 04 Sep 2022 +* DATE: 04 Aug 2023 * * Support routines. * @@ -19,64 +19,6 @@ #include "global.h" -/* -* GetImageVersionInfo -* -* Purpose: -* -* Return version numbers from version info. -* -*/ -BOOL GetImageVersionInfo( - _In_ LPWSTR lpFileName, - _Out_opt_ ULONG *MajorVersion, - _Out_opt_ ULONG *MinorVersion, - _Out_opt_ ULONG *Build, - _Out_opt_ ULONG *Revision -) -{ - BOOL bResult = FALSE; - DWORD dwHandle, dwSize; - PVOID vinfo = NULL; - UINT Length; - VS_FIXEDFILEINFO *pFileInfo; - - // - // Assume failure. - // - if (MajorVersion) - *MajorVersion = 0; - if (MinorVersion) - *MinorVersion = 0; - if (Build) - *Build = 0; - if (Revision) - *Revision = 0; - - dwHandle = 0; - dwSize = GetFileVersionInfoSize(lpFileName, &dwHandle); - if (dwSize) { - vinfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); - if (vinfo) { - if (GetFileVersionInfo(lpFileName, 0, dwSize, vinfo)) { - bResult = VerQueryValue(vinfo, TEXT("\\"), (LPVOID *)&pFileInfo, (PUINT)&Length); - if (bResult) { - if (MajorVersion) - *MajorVersion = HIWORD(pFileInfo->dwFileVersionMS); - if (MinorVersion) - *MinorVersion = LOWORD(pFileInfo->dwFileVersionMS); - if (Build) - *Build = HIWORD(pFileInfo->dwFileVersionLS); - if (Revision) - *Revision = LOWORD(pFileInfo->dwFileVersionLS); - } - } - HeapFree(GetProcessHeap(), 0, vinfo); - } - } - return bResult; -} - VOID ConsoleInit( VOID) { @@ -153,40 +95,44 @@ VOID ConsoleShowMessage( } /* -* GetCommandLineOption +* supGetCommandLineOption * * Purpose: * * Parse command line options. * */ -BOOL GetCommandLineOption( - _In_ LPCTSTR OptionName, - _In_ BOOL IsParametric, - _Out_writes_opt_z_(ValueSize) LPTSTR OptionValue, +BOOLEAN supGetCommandLineOption( + _In_ LPCWSTR OptionName, + _In_ BOOLEAN IsParametric, + _Out_writes_opt_z_(ValueSize) LPWSTR OptionValue, _In_ ULONG ValueSize, _Out_opt_ PULONG ParamLength ) { - BOOL bResult; - LPTSTR cmdline = GetCommandLine(); - TCHAR Param[MAX_PATH + 1]; - ULONG rlen; - int i = 0; + BOOLEAN bResult; + LPWSTR cmdline = GetCommandLine(); + WCHAR szParam[MAX_PATH + 1]; + ULONG rlen; + INT i = 0; if (ParamLength) *ParamLength = 0; - RtlSecureZeroMemory(Param, sizeof(Param)); - while (GetCommandLineParam(cmdline, i, Param, MAX_PATH, &rlen)) + RtlSecureZeroMemory(szParam, sizeof(szParam)); + while (GetCommandLineParam( + cmdline, + i, + szParam, + MAX_PATH, + &rlen)) { if (rlen == 0) break; - if (_strcmp(Param, OptionName) == 0) - { + if (_strcmp(szParam, OptionName) == 0) { if (IsParametric) { - bResult = GetCommandLineParam(cmdline, i + 1, OptionValue, ValueSize, &rlen); + bResult = (BOOLEAN)GetCommandLineParam(cmdline, i + 1, OptionValue, ValueSize, &rlen); if (ParamLength) *ParamLength = rlen; return bResult; @@ -200,83 +146,85 @@ BOOL GetCommandLineOption( return FALSE; } - /* -* IsUserInAdminGroup +* supUserIsFullAdmin * * Purpose: * -* Returns TRUE if current user is in admin group. +* Tests if the current user is admin with full access token. * */ -BOOLEAN IsUserInAdminGroup( - VOID +BOOLEAN supUserIsFullAdmin( + _In_ HANDLE hToken ) { BOOLEAN bResult = FALSE; - HANDLE hToken; + NTSTATUS status; + DWORD i, Attributes; + ULONG ReturnLength = 0; + + PTOKEN_GROUPS pTkGroups; + + SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY; + PSID adminGroup = NULL; + + do { + if (!NT_SUCCESS(RtlAllocateAndInitializeSid( + &ntAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &adminGroup))) + { + break; + } - ULONG returnLength, i; - - PSID pSid = NULL; - - PTOKEN_GROUPS ptg = NULL; - - SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; - - if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { - - GetTokenInformation(hToken, TokenGroups, NULL, 0, &returnLength); - - ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (SIZE_T)returnLength); - if (ptg) { - - if (GetTokenInformation(hToken, - TokenGroups, - ptg, - returnLength, - &returnLength)) - { - if (AllocateAndInitializeSid(&NtAuthority, - 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, - 0, - 0, - 0, - 0, - 0, - &pSid)) - { - for (i = 0; i < ptg->GroupCount; i++) { - if (EqualSid(pSid, ptg->Groups[i].Sid)) { + status = NtQueryInformationToken(hToken, TokenGroups, NULL, 0, &ReturnLength); + if (status != STATUS_BUFFER_TOO_SMALL) + break; + + pTkGroups = (PTOKEN_GROUPS)supHeapAlloc((SIZE_T)ReturnLength); + if (pTkGroups == NULL) + break; + + status = NtQueryInformationToken(hToken, TokenGroups, pTkGroups, ReturnLength, &ReturnLength); + if (NT_SUCCESS(status)) { + if (pTkGroups->GroupCount > 0) + for (i = 0; i < pTkGroups->GroupCount; i++) { + Attributes = pTkGroups->Groups[i].Attributes; + if (RtlEqualSid(adminGroup, pTkGroups->Groups[i].Sid)) + if ( + (Attributes & SE_GROUP_ENABLED) && + (!(Attributes & SE_GROUP_USE_FOR_DENY_ONLY)) + ) + { bResult = TRUE; break; } - } - - FreeSid(pSid); } - } - - HeapFree(GetProcessHeap(), 0, ptg); } - CloseHandle(hToken); + supHeapFree(pTkGroups); + + } while (FALSE); + + if (adminGroup != NULL) { + RtlFreeSid(adminGroup); } + return bResult; } /* -* IsElevated +* supIsClientElevated * * Purpose: * * Returns TRUE if process runs elevated. * */ -BOOL IsElevated( - _In_opt_ HANDLE ProcessHandle +BOOLEAN supIsClientElevated( + _In_ HANDLE ProcessHandle ) { HANDLE hToken = NULL, processHandle = ProcessHandle; @@ -284,10 +232,6 @@ BOOL IsElevated( ULONG BytesRead = 0; TOKEN_ELEVATION te; - if (ProcessHandle == NULL) { - processHandle = GetCurrentProcess(); - } - te.TokenIsElevated = 0; Status = NtOpenProcessToken(processHandle, TOKEN_QUERY, &hToken); @@ -303,78 +247,46 @@ BOOL IsElevated( } /* -* PELoaderGetProcNameBySDTIndex +* supLdrGetProcNameBySDTIndex * * Purpose: * * Return name of service from ntdll by given syscall id. * */ -PCHAR PELoaderGetProcNameBySDTIndex( - _In_ ULONG_PTR MappedImageBase, +PCHAR supLdrGetProcNameBySDTIndex( + _In_ PVOID ModuleBase, _In_ ULONG SDTIndex ) { + PIMAGE_EXPORT_DIRECTORY pImageExportDirectory; + PULONG nameTableBase; + PUSHORT nameOrdinalTableBase; + PULONG funcTable; + PBYTE pfn; + ULONG c, exportSize; + + pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(ModuleBase, + TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize); + + if (pImageExportDirectory) { + + nameTableBase = (PDWORD)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfNames); + nameOrdinalTableBase = (PUSHORT)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfNameOrdinals); + funcTable = (PDWORD)RtlOffsetToPointer(ModuleBase, pImageExportDirectory->AddressOfFunctions); + + for (c = 0; c < pImageExportDirectory->NumberOfNames; c++) { + pfn = (PBYTE)RtlOffsetToPointer(ModuleBase, funcTable[nameOrdinalTableBase[c]]); + if (*((PULONG)pfn) == 0xb8d18b4c) + if (*((PULONG)(pfn + 4)) == SDTIndex) + return (PCHAR)RtlOffsetToPointer(ModuleBase, nameTableBase[c]); + } - PIMAGE_NT_HEADERS nthdr = RtlImageNtHeader((PVOID)MappedImageBase); - PIMAGE_EXPORT_DIRECTORY ExportDirectory; - - ULONG_PTR ExportDirectoryOffset; - PULONG NameTableBase; - PUSHORT NameOrdinalTableBase; - PULONG Addr; - PBYTE pfn; - ULONG c; - - ExportDirectoryOffset = - nthdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; - - if (ExportDirectoryOffset == 0) - return NULL; - - ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(MappedImageBase + ExportDirectoryOffset); - NameTableBase = (PULONG)(MappedImageBase + (ULONG)ExportDirectory->AddressOfNames); - NameOrdinalTableBase = (PUSHORT)(MappedImageBase + (ULONG)ExportDirectory->AddressOfNameOrdinals); - Addr = (PULONG)(MappedImageBase + (ULONG)ExportDirectory->AddressOfFunctions); - - for (c = 0; c < ExportDirectory->NumberOfNames; c++) { - pfn = (PBYTE)(MappedImageBase + Addr[NameOrdinalTableBase[c]]); - if (*((PULONG)pfn) == 0xb8d18b4c) - if (*((PULONG)(pfn + 4)) == SDTIndex) - return (PCHAR)(MappedImageBase + NameTableBase[c]); } return NULL; } -/* -* supHeapAlloc -* -* Purpose: -* -* Wrapper for RtlAllocateHeap. -* -*/ -FORCEINLINE PVOID supHeapAlloc( - _In_ SIZE_T Size) -{ - return RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, HEAP_ZERO_MEMORY, Size); -} - -/* -* supHeapFree -* -* Purpose: -* -* Wrapper for RtlFreeHeap. -* -*/ -FORCEINLINE BOOL supHeapFree( - _In_ PVOID Memory) -{ - return RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, Memory); -} - /* * supPrivilegeEnabled * @@ -495,9 +407,9 @@ NTSTATUS supIsLocalSystem( _In_ HANDLE hToken, _Out_ PBOOLEAN pbResult) { - BOOLEAN bResult = FALSE; - NTSTATUS status = STATUS_UNSUCCESSFUL; - PSID SystemSid = NULL, TokenSid = NULL; + BOOLEAN bResult = FALSE; + NTSTATUS status = STATUS_UNSUCCESSFUL; + PSID SystemSid = NULL, TokenSid = NULL; SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY; TokenSid = supQueryTokenUserSid(hToken); @@ -701,7 +613,7 @@ PVOID supGetSystemInfo( &returnedLength)) == STATUS_INFO_LENGTH_MISMATCH) { supHeapFree(buffer); - bufferSize *= 2; + bufferSize <<= 1; if (bufferSize > SI_MAX_BUFFER_LENGTH) return NULL; @@ -734,11 +646,10 @@ BOOL supEnablePrivilege( _In_ BOOL fEnable ) { - BOOL bResult = FALSE; - NTSTATUS status; - ULONG dummy; - HANDLE hToken; - TOKEN_PRIVILEGES TokenPrivileges; + NTSTATUS status; + ULONG dummy; + HANDLE hToken; + TOKEN_PRIVILEGES tkPrivs; status = NtOpenProcessToken( NtCurrentProcess(), @@ -746,25 +657,24 @@ BOOL supEnablePrivilege( &hToken); if (!NT_SUCCESS(status)) { - return bResult; + return FALSE; } - TokenPrivileges.PrivilegeCount = 1; - TokenPrivileges.Privileges[0].Luid.LowPart = PrivilegeName; - TokenPrivileges.Privileges[0].Luid.HighPart = 0; - TokenPrivileges.Privileges[0].Attributes = (fEnable) ? SE_PRIVILEGE_ENABLED : 0; - status = NtAdjustPrivilegesToken(hToken, FALSE, &TokenPrivileges, + tkPrivs.PrivilegeCount = 1; + tkPrivs.Privileges[0].Luid.LowPart = PrivilegeName; + tkPrivs.Privileges[0].Luid.HighPart = 0; + tkPrivs.Privileges[0].Attributes = (fEnable) ? SE_PRIVILEGE_ENABLED : 0; + status = NtAdjustPrivilegesToken(hToken, FALSE, &tkPrivs, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PULONG)&dummy); if (status == STATUS_NOT_ALL_ASSIGNED) { status = STATUS_PRIVILEGE_NOT_HELD; } - bResult = NT_SUCCESS(status); NtClose(hToken); - return bResult; + return NT_SUCCESS(status); } /* -* RunAsLocalSystem +* supRunAsLocalSystem * * Purpose: * @@ -773,7 +683,7 @@ BOOL supEnablePrivilege( * Note: Elevated instance required. * */ -VOID RunAsLocalSystem( +VOID supRunAsLocalSystem( VOID ) { @@ -1011,25 +921,168 @@ HANDLE supGetCurrentProcessToken( } /* -* IsLocalSystem +* supMapImageNoExecute * * Purpose: * -* Returns TRUE if current user is LocalSystem. +* Map image with SEC_IMAGE_NO_EXECUTE. * */ -BOOLEAN IsLocalSystem( - VOID +NTSTATUS supMapImageNoExecute( + _In_ PUNICODE_STRING ImagePath, + _Out_ PVOID* BaseAddress ) { - BOOLEAN bResult = FALSE; - HANDLE hToken; + NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; + SIZE_T fileSize = 0; + HANDLE hFile = NULL, hSection = NULL; + OBJECT_ATTRIBUTES obja; + IO_STATUS_BLOCK iost; + LARGE_INTEGER li; - hToken = supGetCurrentProcessToken(); - if (hToken) { - supIsLocalSystem(hToken, &bResult); - NtClose(hToken); + *BaseAddress = NULL; + + do { + + InitializeObjectAttributes(&obja, ImagePath, + OBJ_CASE_INSENSITIVE, NULL, NULL); + + RtlSecureZeroMemory(&iost, sizeof(iost)); + ntStatus = NtCreateFile(&hFile, + SYNCHRONIZE | FILE_READ_DATA, + &obja, + &iost, + NULL, + 0, + FILE_SHARE_READ, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, + NULL, + 0); + + if (!NT_SUCCESS(ntStatus)) + break; + + obja.ObjectName = NULL; + + ntStatus = NtCreateSection(&hSection, + SECTION_MAP_READ, + &obja, + NULL, + PAGE_READONLY, + SEC_IMAGE_NO_EXECUTE, + hFile); + + if (!NT_SUCCESS(ntStatus)) + break; + + li.QuadPart = 0; + + ntStatus = NtMapViewOfSection(hSection, + NtCurrentProcess(), + BaseAddress, + 0, + 0, + &li, + &fileSize, + ViewShare, + 0, + PAGE_READONLY); + + if (!NT_SUCCESS(ntStatus)) + break; + + } while (FALSE); + + if (hFile) NtClose(hFile); + if (hSection) NtClose(hSection); + return ntStatus; +} + +/* +* supLdrGetProcAddressEx +* +* Purpose: +* +* Simplified GetProcAddress reimplementation. +* +*/ +LPVOID supLdrGetProcAddressEx( + _In_ LPVOID ImageBase, + _In_ LPCSTR RoutineName +) +{ + PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; + USHORT OrdinalNumber; + PULONG NameTableBase; + PUSHORT NameOrdinalTableBase; + PULONG Addr; + LONG Result; + ULONG High, Low, Middle = 0; + + union { + PIMAGE_NT_HEADERS64 nt64; + PIMAGE_NT_HEADERS32 nt32; + PIMAGE_NT_HEADERS nt; + } NtHeaders; + + if (!NT_SUCCESS(RtlImageNtHeaderEx(RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK, + ImageBase, 0, &NtHeaders.nt))) + { + return NULL; } - return bResult; + if (NtHeaders.nt == NULL) { + return NULL; + } + + if (NtHeaders.nt->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) { + + ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlOffsetToPointer(ImageBase, + NtHeaders.nt64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); + + } + else if (NtHeaders.nt->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) { + + ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlOffsetToPointer(ImageBase, + NtHeaders.nt32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); + } + else + { + return NULL; + } + + NameTableBase = (PULONG)RtlOffsetToPointer(ImageBase, (ULONG)ExportDirectory->AddressOfNames); + NameOrdinalTableBase = (PUSHORT)RtlOffsetToPointer(ImageBase, (ULONG)ExportDirectory->AddressOfNameOrdinals); + Low = 0; + High = ExportDirectory->NumberOfNames - 1; + while (High >= Low) { + + Middle = (Low + High) >> 1; + + Result = _strcmp_a( + RoutineName, + (char*)RtlOffsetToPointer(ImageBase, NameTableBase[Middle])); + + if (Result < 0) { + High = Middle - 1; + } + else { + if (Result > 0) { + Low = Middle + 1; + } + else { + break; + } + } + } + if (High < Low) + return NULL; + + OrdinalNumber = NameOrdinalTableBase[Middle]; + if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions) + return NULL; + + Addr = (PULONG)RtlOffsetToPointer(ImageBase, (ULONG)ExportDirectory->AddressOfFunctions); + return (LPVOID)RtlOffsetToPointer(ImageBase, Addr[OrdinalNumber]); } diff --git a/Source/NtCall64/sup.h b/Source/NtCall64/sup.h new file mode 100644 index 0000000..ae3b645 --- /dev/null +++ b/Source/NtCall64/sup.h @@ -0,0 +1,68 @@ +/******************************************************************************* +* +* (C) COPYRIGHT AUTHORS, 2016 - 2023 +* +* TITLE: SUP.H +* +* VERSION: 1.37 +* +* DATE: 04 Aug 2023 +* +* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED +* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +* PARTICULAR PURPOSE. +* +*******************************************************************************/ +#pragma once + +typedef struct _WIN32_SHADOWTABLE { + ULONG Index; + CHAR Name[256]; + struct _WIN32_SHADOWTABLE *NextService; +} WIN32_SHADOWTABLE, *PWIN32_SHADOWTABLE; + +#define supHeapAlloc(Size) RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, HEAP_ZERO_MEMORY, Size) +#define supHeapFree(Memory) RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, Memory) + +VOID supShowNtStatus( + _In_ LPCSTR lpText, + _In_ NTSTATUS Status); + +VOID ConsoleInit( + VOID); + +VOID ConsoleShowMessage( + _In_ LPCSTR lpMessage, + _In_opt_ WORD wColor); + +BOOLEAN supGetCommandLineOption( + _In_ LPCWSTR OptionName, + _In_ BOOLEAN IsParametric, + _Out_writes_opt_z_(ValueSize) LPWSTR OptionValue, + _In_ ULONG ValueSize, + _Out_opt_ PULONG ParamLength); + +NTSTATUS supIsLocalSystem( + _In_ HANDLE hToken, + _Out_ PBOOLEAN pbResult); + +BOOLEAN supUserIsFullAdmin( + _In_ HANDLE hToken); + +VOID supRunAsLocalSystem(VOID); + +BOOLEAN supIsClientElevated( + _In_ HANDLE ProcessHandle); + +PCHAR supLdrGetProcNameBySDTIndex( + _In_ PVOID MappedImageBase, + _In_ ULONG SDTIndex); + +NTSTATUS supMapImageNoExecute( + _In_ PUNICODE_STRING ImagePath, + _Out_ PVOID* BaseAddress); + +LPVOID supLdrGetProcAddressEx( + _In_ LPVOID ImageBase, + _In_ LPCSTR RoutineName); diff --git a/Source/NtCall64/util.h b/Source/NtCall64/util.h deleted file mode 100644 index 055be88..0000000 --- a/Source/NtCall64/util.h +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************* -* -* (C) COPYRIGHT AUTHORS, 2016 - 2022 -* -* TITLE: UTIL.H -* -* VERSION: 1.36 -* -* DATE: 04 Sep 2022 -* -* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED -* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -* PARTICULAR PURPOSE. -* -*******************************************************************************/ -#pragma once - -typedef struct _WIN32_SHADOWTABLE { - ULONG Index; - CHAR Name[256]; - struct _WIN32_SHADOWTABLE *NextService; -} WIN32_SHADOWTABLE, *PWIN32_SHADOWTABLE; - -BOOL GetImageVersionInfo( - _In_ LPWSTR lpFileName, - _Out_opt_ ULONG *MajorVersion, - _Out_opt_ ULONG *MinorVersion, - _Out_opt_ ULONG *Build, - _Out_opt_ ULONG *Revision); - -VOID ConsoleInit( - VOID); - -VOID ConsoleShowMessage( - _In_ LPCSTR lpMessage, - _In_opt_ WORD wColor); - -BOOL GetCommandLineOption( - _In_ LPCTSTR OptionName, - _In_ BOOL IsParametric, - _Out_writes_opt_z_(ValueSize) LPTSTR OptionValue, - _In_ ULONG ValueSize, - _Out_opt_ PULONG ParamLength); - -BOOLEAN IsLocalSystem(VOID); -BOOLEAN IsUserInAdminGroup(VOID); -VOID RunAsLocalSystem(VOID); - -BOOL IsElevated( - _In_opt_ HANDLE ProcessHandle); - -PCHAR PELoaderGetProcNameBySDTIndex( - _In_ ULONG_PTR MappedImageBase, - _In_ ULONG SDTIndex); diff --git a/Source/NtCall64/wfuzzer.vcxproj b/Source/NtCall64/wfuzzer.vcxproj index 30dd8dd..3f139eb 100644 --- a/Source/NtCall64/wfuzzer.vcxproj +++ b/Source/NtCall64/wfuzzer.vcxproj @@ -158,7 +158,7 @@ - + @@ -172,10 +172,11 @@ + - + diff --git a/Source/NtCall64/wfuzzer.vcxproj.filters b/Source/NtCall64/wfuzzer.vcxproj.filters index 72f5d0b..4d0fc1f 100644 --- a/Source/NtCall64/wfuzzer.vcxproj.filters +++ b/Source/NtCall64/wfuzzer.vcxproj.filters @@ -24,7 +24,7 @@ - Source Files + Source Files @@ -95,7 +95,7 @@ - Header Files + Header Files @@ -134,6 +134,9 @@ + Header Files + Header Files +diff --git a/Source/NtCall64/wfuzzer.vcxproj.user b/Source/NtCall64/wfuzzer.vcxproj.user index 4967d14..66da31c 100644 --- a/Source/NtCall64/wfuzzer.vcxproj.user +++ b/Source/NtCall64/wfuzzer.vcxproj.user @@ -1,7 +1,7 @@ - -win32k +-win32k -start 4993 WindowsLocalDebugger