Skip to content

Commit

Permalink
Code
Browse files Browse the repository at this point in the history
  • Loading branch information
sipo-x committed Nov 9, 2024
1 parent 74698d6 commit a074aa0
Show file tree
Hide file tree
Showing 5 changed files with 463 additions and 0 deletions.
187 changes: 187 additions & 0 deletions main.cpp
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;
}
18 changes: 18 additions & 0 deletions structs.h
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;
31 changes: 31 additions & 0 deletions syscall.asm
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
113 changes: 113 additions & 0 deletions syscall.h
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)
}
Loading

0 comments on commit a074aa0

Please sign in to comment.