mirror of https://github.com/JKornev/hidden
271 lines
6.5 KiB
C
271 lines
6.5 KiB
C
#include "Helper.h"
|
|
|
|
#define HELPER_ALLOC_TAG 'rplH'
|
|
|
|
NTSTATUS QuerySystemInformation(SYSTEM_INFORMATION_CLASS Class, PVOID* InfoBuffer, PSIZE_T InfoSize)
|
|
{
|
|
PVOID info = NULL;
|
|
NTSTATUS status;
|
|
ULONG size = 0, written = 0;
|
|
|
|
// Query required size
|
|
status = ZwQuerySystemInformation(Class, 0, 0, &size);
|
|
if (status != STATUS_INFO_LENGTH_MISMATCH)
|
|
return status;
|
|
|
|
while (status == STATUS_INFO_LENGTH_MISMATCH)
|
|
{
|
|
size += written; // We should allocate little bit more space
|
|
|
|
if (info)
|
|
ExFreePoolWithTag(info, HELPER_ALLOC_TAG);
|
|
|
|
info = ExAllocatePoolWithTag(NonPagedPool, size, HELPER_ALLOC_TAG);
|
|
if (!info)
|
|
break;
|
|
|
|
status = ZwQuerySystemInformation(Class, info, size, &written);
|
|
}
|
|
|
|
if (!info)
|
|
return STATUS_ACCESS_DENIED;
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
ExFreePoolWithTag(info, HELPER_ALLOC_TAG);
|
|
return status;
|
|
}
|
|
|
|
*InfoBuffer = info;
|
|
*InfoSize = size;
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS QueryProcessInformation(PROCESSINFOCLASS Class, HANDLE Process, PVOID* InfoBuffer, PSIZE_T InfoSize)
|
|
{
|
|
PVOID info = NULL;
|
|
NTSTATUS status;
|
|
ULONG size = 0, written = 0;
|
|
|
|
// Query required size
|
|
status = ZwQueryInformationProcess(Process, Class, 0, 0, &size);
|
|
if (status != STATUS_INFO_LENGTH_MISMATCH)
|
|
return status;
|
|
|
|
while (status == STATUS_INFO_LENGTH_MISMATCH)
|
|
{
|
|
size += written; // We should allocate little bit more space
|
|
|
|
if (info)
|
|
ExFreePoolWithTag(info, HELPER_ALLOC_TAG);
|
|
|
|
info = ExAllocatePoolWithTag(NonPagedPool, size, HELPER_ALLOC_TAG);
|
|
if (!info)
|
|
break;
|
|
|
|
status = ZwQueryInformationProcess(Process, Class, info, size, &written);
|
|
}
|
|
|
|
if (!info)
|
|
return STATUS_ACCESS_DENIED;
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
ExFreePoolWithTag(info, HELPER_ALLOC_TAG);
|
|
return status;
|
|
}
|
|
|
|
*InfoBuffer = info;
|
|
*InfoSize = size;
|
|
|
|
return status;
|
|
}
|
|
|
|
VOID FreeInformation(PVOID Buffer)
|
|
{
|
|
ExFreePoolWithTag(Buffer, HELPER_ALLOC_TAG);
|
|
}
|
|
|
|
NTSTATUS ResolveSymbolicLink(PUNICODE_STRING Link, PUNICODE_STRING Resolved)
|
|
{
|
|
OBJECT_ATTRIBUTES attribs;
|
|
HANDLE hsymLink;
|
|
ULONG written;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
// Open symlink
|
|
|
|
InitializeObjectAttributes(&attribs, Link, OBJ_KERNEL_HANDLE, NULL, NULL);
|
|
|
|
status = ZwOpenSymbolicLinkObject(&hsymLink, GENERIC_READ, &attribs);
|
|
if (!NT_SUCCESS(status))
|
|
return status;
|
|
|
|
// Query original name
|
|
|
|
status = ZwQuerySymbolicLinkObject(hsymLink, Resolved, &written);
|
|
ZwClose(hsymLink);
|
|
if (!NT_SUCCESS(status))
|
|
return status;
|
|
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Convertion template:
|
|
// \\??\\C:\\Windows -> \\Device\\HarddiskVolume1\\Windows
|
|
//
|
|
NTSTATUS NormalizeDevicePath(PCUNICODE_STRING Path, PUNICODE_STRING Normalized)
|
|
{
|
|
UNICODE_STRING globalPrefix, dvcPrefix, sysrootPrefix;
|
|
NTSTATUS status;
|
|
|
|
RtlInitUnicodeString(&globalPrefix, L"\\??\\");
|
|
RtlInitUnicodeString(&dvcPrefix, L"\\Device\\");
|
|
RtlInitUnicodeString(&sysrootPrefix, L"\\SystemRoot\\");
|
|
|
|
if (RtlPrefixUnicodeString(&globalPrefix, Path, TRUE))
|
|
{
|
|
OBJECT_ATTRIBUTES attribs;
|
|
UNICODE_STRING subPath;
|
|
HANDLE hsymLink;
|
|
ULONG i, written, size;
|
|
|
|
subPath.Buffer = (PWCH)((PUCHAR)Path->Buffer + globalPrefix.Length);
|
|
subPath.Length = Path->Length - globalPrefix.Length;
|
|
|
|
for (i = 0; i < subPath.Length; i++)
|
|
{
|
|
if (subPath.Buffer[i] == L'\\')
|
|
{
|
|
subPath.Length = (USHORT)(i * sizeof(WCHAR));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (subPath.Length == 0)
|
|
return STATUS_INVALID_PARAMETER_1;
|
|
|
|
subPath.Buffer = Path->Buffer;
|
|
subPath.Length += globalPrefix.Length;
|
|
subPath.MaximumLength = subPath.Length;
|
|
|
|
// Open symlink
|
|
|
|
InitializeObjectAttributes(&attribs, &subPath, OBJ_KERNEL_HANDLE, NULL, NULL);
|
|
|
|
status = ZwOpenSymbolicLinkObject(&hsymLink, GENERIC_READ, &attribs);
|
|
if (!NT_SUCCESS(status))
|
|
return status;
|
|
|
|
// Query original name
|
|
|
|
status = ZwQuerySymbolicLinkObject(hsymLink, Normalized, &written);
|
|
ZwClose(hsymLink);
|
|
if (!NT_SUCCESS(status))
|
|
return status;
|
|
|
|
// Construct new variable
|
|
|
|
size = Path->Length - subPath.Length + Normalized->Length;
|
|
if (size > Normalized->MaximumLength)
|
|
return STATUS_BUFFER_OVERFLOW;
|
|
|
|
subPath.Buffer = (PWCH)((PUCHAR)Path->Buffer + subPath.Length);
|
|
subPath.Length = Path->Length - subPath.Length;
|
|
subPath.MaximumLength = subPath.Length;
|
|
|
|
status = RtlAppendUnicodeStringToString(Normalized, &subPath);
|
|
if (!NT_SUCCESS(status))
|
|
return status;
|
|
}
|
|
else if (RtlPrefixUnicodeString(&dvcPrefix, Path, TRUE))
|
|
{
|
|
Normalized->Length = 0;
|
|
status = RtlAppendUnicodeStringToString(Normalized, Path);
|
|
if (!NT_SUCCESS(status))
|
|
return status;
|
|
}
|
|
else if (RtlPrefixUnicodeString(&sysrootPrefix, Path, TRUE))
|
|
{
|
|
UNICODE_STRING subPath, resolvedLink, winDir;
|
|
WCHAR buffer[64];
|
|
SHORT i;
|
|
|
|
// Open symlink
|
|
|
|
subPath.Buffer = sysrootPrefix.Buffer;
|
|
subPath.MaximumLength = subPath.Length = sysrootPrefix.Length - sizeof(WCHAR);
|
|
|
|
resolvedLink.Buffer = buffer;
|
|
resolvedLink.Length = 0;
|
|
resolvedLink.MaximumLength = sizeof(buffer);
|
|
|
|
status = ResolveSymbolicLink(&subPath, &resolvedLink);
|
|
if (!NT_SUCCESS(status))
|
|
return status;
|
|
|
|
// \Device\Harddisk0\Partition0\Windows -> \Device\Harddisk0\Partition0
|
|
// Win10: \Device\BootDevice\Windows -> \Device\BootDevice
|
|
|
|
winDir.Length = 0;
|
|
for (i = (resolvedLink.Length - sizeof(WCHAR)) / sizeof(WCHAR); i >= 0; i--)
|
|
{
|
|
if (resolvedLink.Buffer[i] == L'\\')
|
|
{
|
|
winDir.Buffer = resolvedLink.Buffer + i;
|
|
winDir.Length = resolvedLink.Length - (i * sizeof(WCHAR));
|
|
winDir.MaximumLength = winDir.Length;
|
|
resolvedLink.Length = (i * sizeof(WCHAR));
|
|
break;
|
|
}
|
|
}
|
|
|
|
// \Device\Harddisk0\Partition0 -> \Device\HarddiskVolume1
|
|
// Win10: \Device\BootDevice -> \Device\HarddiskVolume2
|
|
|
|
status = ResolveSymbolicLink(&resolvedLink, Normalized);
|
|
if (!NT_SUCCESS(status))
|
|
return status;
|
|
|
|
// Construct new variable
|
|
|
|
subPath.Buffer = (PWCHAR)((PCHAR)Path->Buffer + sysrootPrefix.Length - sizeof(WCHAR));
|
|
subPath.MaximumLength = subPath.Length = Path->Length - sysrootPrefix.Length + sizeof(WCHAR);
|
|
|
|
status = RtlAppendUnicodeStringToString(Normalized, &winDir);
|
|
if (!NT_SUCCESS(status))
|
|
return status;
|
|
|
|
status = RtlAppendUnicodeStringToString(Normalized, &subPath);
|
|
if (!NT_SUCCESS(status))
|
|
return status;
|
|
}
|
|
else
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
BOOLEAN IsWin8OrAbove()
|
|
{//TODO: cache it
|
|
RTL_OSVERSIONINFOW version;
|
|
NTSTATUS status;
|
|
|
|
RtlZeroMemory(&version, sizeof(version));
|
|
|
|
status = RtlGetVersion(&version);
|
|
if (!NT_SUCCESS(status))
|
|
LogWarning("Can't get an OS version, status:%x", status);
|
|
|
|
if (version.dwMajorVersion < 6)
|
|
return FALSE;
|
|
|
|
if (version.dwMajorVersion == 6 && version.dwMinorVersion < 2) // NT 6.2 == Win8
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
} |