-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
463 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
#include <windows.h> | ||
#include <ntstatus.h> | ||
#include <winternl.h> | ||
#include <tchar.h> | ||
#include <cstdio> | ||
|
||
#include "syscall.h" | ||
#include "structs.h" | ||
|
||
bool get_maximum_privileges(); | ||
bool unauthorized_access(ACCESS_MASK access_mask); | ||
|
||
int main() | ||
{ | ||
if (!get_maximum_privileges()) | ||
return 1; | ||
|
||
SIZE_T bufferSize = 0x10000; | ||
PVOID pHandleInfo = nullptr; | ||
SIZE_T zero = 0; | ||
|
||
NTSTATUS status = syscalls::nt_allocate_virtual_memory( | ||
GetCurrentProcess(), | ||
&pHandleInfo, | ||
0, | ||
(PULONG)&bufferSize, | ||
MEM_COMMIT | MEM_RESERVE, | ||
PAGE_READWRITE | ||
); | ||
|
||
if (!NT_SUCCESS(status) || !pHandleInfo) { | ||
return 1; | ||
} | ||
|
||
while (true) { | ||
NTSTATUS status; | ||
do { | ||
status = syscalls::nt_query_system_information(16, pHandleInfo, bufferSize, nullptr); | ||
if (status == STATUS_INFO_LENGTH_MISMATCH) { | ||
bufferSize *= 2; | ||
|
||
LPVOID newHandleInfo = nullptr; | ||
|
||
NTSTATUS status = syscalls::nt_allocate_virtual_memory( | ||
GetCurrentProcess(), | ||
&newHandleInfo, | ||
0, | ||
(PULONG)&bufferSize, | ||
MEM_COMMIT | MEM_RESERVE, | ||
PAGE_READWRITE | ||
); | ||
|
||
syscalls::nt_free_virtual_memory( | ||
GetCurrentProcess(), | ||
&pHandleInfo, | ||
&zero, | ||
MEM_RELEASE | ||
); | ||
|
||
if (!NT_SUCCESS(status) || !newHandleInfo) { | ||
return 1; | ||
} | ||
|
||
pHandleInfo = newHandleInfo; | ||
} | ||
} while (status == STATUS_INFO_LENGTH_MISMATCH); | ||
|
||
if (!NT_SUCCESS(status)) | ||
{ | ||
syscalls::nt_free_virtual_memory( | ||
GetCurrentProcess(), | ||
&pHandleInfo, | ||
&zero, | ||
MEM_RELEASE | ||
); | ||
return 1; | ||
} | ||
|
||
const auto handleInfo = reinterpret_cast<PSYSTEM_HANDLE_INFORMATION>(pHandleInfo); | ||
const ULONG currentProcessId = GetCurrentProcessId(); | ||
|
||
for (ULONG i = 0; i < handleInfo->HandleCount; ++i) { | ||
const SYSTEM_HANDLE& handle = handleInfo->Handles[i]; | ||
if (handle.ProcessId == currentProcessId || !unauthorized_access(handle.GrantedAccess)) continue; | ||
|
||
const HANDLE hProcess = syscalls::nt_open_process(PROCESS_DUP_HANDLE | PROCESS_QUERY_LIMITED_INFORMATION, | ||
handle.ProcessId | ||
); | ||
if (!hProcess || hProcess == INVALID_HANDLE_VALUE) continue; | ||
|
||
HANDLE hDupHandle = nullptr; | ||
if (NT_SUCCESS(syscalls::nt_duplicate_object( | ||
hProcess, | ||
reinterpret_cast<HANDLE>(handle.Handle), | ||
GetCurrentProcess(), | ||
&hDupHandle, | ||
PROCESS_QUERY_LIMITED_INFORMATION, | ||
FALSE, | ||
0))) | ||
{ | ||
if (GetProcessId(hDupHandle) == currentProcessId) | ||
{ | ||
TCHAR image_name[MAX_PATH]; | ||
DWORD nameLength = MAX_PATH; | ||
if (!QueryFullProcessImageName(hProcess, 0, image_name, &nameLength)) | ||
{ | ||
_tcscpy_s(image_name, MAX_PATH, _T("UNKNOWN IMAGE NAME")); | ||
} | ||
|
||
if (NT_SUCCESS(syscalls::nt_duplicate_object( | ||
hProcess, | ||
reinterpret_cast<HANDLE>(handle.Handle), | ||
GetCurrentProcess(), | ||
&hDupHandle, | ||
0, | ||
FALSE, | ||
DUPLICATE_CLOSE_SOURCE))) | ||
{ | ||
if (NT_SUCCESS(syscalls::nt_close(hDupHandle))) | ||
{ | ||
printf("[closed handle] %s | ACCESS_MASK 0x%0X%\n", image_name, handle.GrantedAccess); | ||
} | ||
else { | ||
return 1; | ||
} | ||
} | ||
else { | ||
syscalls::nt_close(hDupHandle); | ||
} | ||
} | ||
else { | ||
syscalls::nt_close(hDupHandle); | ||
} | ||
} | ||
|
||
syscalls::nt_close(hProcess); | ||
} | ||
} | ||
|
||
syscalls::nt_free_virtual_memory( | ||
GetCurrentProcess(), | ||
&pHandleInfo, | ||
&zero, | ||
MEM_RELEASE | ||
); | ||
|
||
return 0; | ||
} | ||
|
||
bool unauthorized_access(const ACCESS_MASK access_mask) | ||
{ | ||
constexpr ACCESS_MASK UNAUTHORIZED_FLAGS = PROCESS_VM_WRITE | | ||
PROCESS_VM_READ | | ||
PROCESS_ALL_ACCESS | | ||
PROCESS_VM_OPERATION | | ||
PROCESS_DUP_HANDLE | | ||
PROCESS_SET_INFORMATION | | ||
PROCESS_SUSPEND_RESUME; | ||
|
||
return (access_mask & UNAUTHORIZED_FLAGS) != 0; | ||
} | ||
|
||
bool get_maximum_privileges() | ||
{ | ||
HANDLE h_Process = GetCurrentProcess(); | ||
HANDLE h_Token; | ||
DWORD dw_TokenLength; | ||
if (NT_SUCCESS(syscalls::nt_open_process_token(h_Process, TOKEN_READ | TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &h_Token))) | ||
{ | ||
TOKEN_PRIVILEGES* privilages = new TOKEN_PRIVILEGES[100]; | ||
if (GetTokenInformation(h_Token, TokenPrivileges, privilages, sizeof(TOKEN_PRIVILEGES) * 100, &dw_TokenLength)) | ||
{ | ||
for (int i = 0; i < privilages->PrivilegeCount; i++) | ||
{ | ||
privilages->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED; | ||
} | ||
|
||
if (AdjustTokenPrivileges(h_Token, false, privilages, sizeof(TOKEN_PRIVILEGES) * 100, NULL, NULL)) | ||
{ | ||
delete[] privilages; | ||
return true; | ||
} | ||
} | ||
delete[] privilages; | ||
} | ||
return false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#pragma once | ||
#include <windows.h> | ||
|
||
typedef struct _SYSTEM_HANDLE | ||
{ | ||
ULONG ProcessId; | ||
UCHAR ObjectTypeNumber; | ||
UCHAR Flags; | ||
USHORT Handle; | ||
PVOID Object; | ||
ACCESS_MASK GrantedAccess; | ||
} SYSTEM_HANDLE, * PSYSTEM_HANDLE; | ||
|
||
typedef struct _SYSTEM_HANDLE_INFORMATION | ||
{ | ||
ULONG HandleCount; | ||
SYSTEM_HANDLE Handles[1]; | ||
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
.code | ||
syscall_stub proc | ||
mov eax, ecx | ||
|
||
; validate number of arguments | ||
cmp edx, 1 | ||
jl skip | ||
|
||
mov r10, r8 | ||
cmp edx, 2 | ||
jl skip | ||
|
||
xchg rdx, r9 | ||
cmp r9d, 3 | ||
jl skip | ||
|
||
mov r8, [rsp + 28h] | ||
cmp r9d, 4 | ||
jl skip | ||
|
||
mov r9, [rsp + 30h] | ||
|
||
skip: | ||
add rsp, 10h ; skip first 2 args | ||
syscall | ||
sub rsp, 10h | ||
ret | ||
syscall_stub endp | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
#pragma once | ||
#ifndef WIN32_LEAN_AND_MEAN | ||
#define WIN32_LEAN_AND_MEAN | ||
#endif | ||
|
||
#include <windows.h> | ||
#include <winternl.h> | ||
#include <winioctl.h> | ||
#include <TlHelp32.h> | ||
#include <Shlwapi.h> | ||
|
||
#pragma warning(push) | ||
#pragma warning(disable : 4005) | ||
#include <ntstatus.h> | ||
#pragma warning(pop) | ||
|
||
#include <type_traits> | ||
#include <cstdint> | ||
|
||
extern "C" void* syscall_stub(); | ||
|
||
namespace syscalls | ||
{ | ||
NTSTATUS nt_close(HANDLE handle); | ||
HANDLE nt_open_process(ACCESS_MASK access, | ||
DWORD pid); | ||
NTSTATUS nt_open_process_token(HANDLE ProcessHandle, ACCESS_MASK access, PHANDLE TokenHandle); | ||
NTSTATUS nt_query_system_information( | ||
ULONG SystemInformationClass, | ||
PVOID SystemInformation, | ||
ULONG SystemInformationLength, | ||
PULONG ReturnLength); | ||
NTSTATUS nt_duplicate_object(HANDLE SourceProcessHandle, | ||
HANDLE SourceHandle, | ||
HANDLE TargetProcessHandle, | ||
PHANDLE TargetHandle, | ||
ACCESS_MASK DesiredAccess, | ||
ULONG Attributes, | ||
ULONG Options); | ||
NTSTATUS nt_allocate_virtual_memory( | ||
_In_ HANDLE ProcessHandle, | ||
_Inout_ PVOID BaseAddress, | ||
_In_ ULONG ZeroBits, | ||
_Inout_ PULONG RegionSize, | ||
_In_ ULONG AllocationType, | ||
_In_ ULONG Protect); | ||
NTSTATUS nt_free_virtual_memory( | ||
HANDLE ProcessHandle, | ||
PVOID* BaseAddress, | ||
PSIZE_T RegionSize, | ||
ULONG FreeType); | ||
} | ||
|
||
namespace syscall | ||
{ | ||
template<typename T> | ||
using to_int64 = std::conditional_t < sizeof(T) < sizeof(int64_t), int64_t, T > ; | ||
|
||
#pragma warning(push) | ||
#pragma warning(disable : 4100) | ||
|
||
template<typename R, typename... Args> | ||
R syscall(int index, Args... args) | ||
{ | ||
auto error = [](NTSTATUS status) | ||
{ | ||
if constexpr (std::is_same_v<R, NTSTATUS>) | ||
return status; | ||
else | ||
return R(); | ||
}; | ||
|
||
#ifdef USE32 | ||
return error(STATUS_NOT_SUPPORTED); | ||
#else | ||
static_assert(sizeof(R) <= sizeof(void*), "Return types larger than void* aren't supported"); | ||
if (index == -1) | ||
return error(STATUS_INVALID_PARAMETER_1); | ||
|
||
// Cast types that otherwise will be only half-initialized | ||
auto pfn = reinterpret_cast<R(*)(int, size_t, to_int64<Args>...)>(syscall_stub); | ||
return pfn(index, sizeof...(Args), to_int64<Args>(args)...); | ||
#endif | ||
} | ||
|
||
inline int get_index(const wchar_t* modName, const char* func) | ||
{ | ||
#ifdef USE32 | ||
// Doesn't work for x86 | ||
return -1; | ||
#else | ||
const auto pfn = reinterpret_cast<const uint8_t*>(GetProcAddress( | ||
GetModuleHandleW(modName), | ||
func | ||
)); | ||
|
||
return pfn ? *reinterpret_cast<const int*>(pfn + 4) : -1; | ||
#endif | ||
} | ||
|
||
inline int get_index(const char* func) | ||
{ | ||
return get_index(L"ntdll.dll", func); | ||
} | ||
|
||
template<typename T, typename... Args> | ||
T syscall(const char* fn, Args&&... args) | ||
{ | ||
return syscall<T>(get_index(fn), std::forward<Args>(args)...); | ||
} | ||
|
||
#pragma warning(pop) | ||
} |
Oops, something went wrong.