Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions inc/usersim/ps.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,14 @@ void
usersime_invoke_process_creation_notify_routine(
_Inout_ PEPROCESS process, _In_ HANDLE process_id, _Inout_opt_ PPS_CREATE_NOTIFY_INFO create_info);

typedef PACCESS_TOKEN PEPROCESS_ACCESS_TOKEN;

USERSIM_API
PACCESS_TOKEN
PsReferencePrimaryToken(_In_ PEPROCESS process);

USERSIM_API
VOID
PsDereferencePrimaryToken(_In_ PACCESS_TOKEN token);

CXPLAT_EXTERN_C_END
15 changes: 15 additions & 0 deletions inc/usersim/se.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "..\src\platform.h"
#include "ke.h"
#include "rtl.h"

CXPLAT_EXTERN_C_BEGIN

Expand Down Expand Up @@ -180,6 +181,20 @@ USERSIM_API
NTSTATUS
SeQueryAuthenticationIdToken(_In_ PACCESS_TOKEN token, _Out_ PLUID authentication_id);

USERSIM_API
NTSTATUS
SeQueryInformationToken(_In_ PACCESS_TOKEN token, _In_ TOKEN_INFORMATION_CLASS token_information_class, _Out_ PVOID* token_information);

USERSIM_API
NTSTATUS
SecLookupAccountSid(
_In_ PSID Sid,
_Inout_ PULONG NameSize,
_Out_opt_ PUNICODE_STRING Name,
_Inout_ PULONG DomainSize,
_Out_opt_ PUNICODE_STRING Domain,
_Out_ PSID_NAME_USE SidNameUse);

void
usersim_initialize_se();

Expand Down
15 changes: 15 additions & 0 deletions src/ps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,19 @@ usersime_invoke_process_creation_notify_routine(
if (_usersim_process_creation_notify_routine != NULL) {
_usersim_process_creation_notify_routine(process, process_id, create_info);
}
}

PACCESS_TOKEN
PsReferencePrimaryToken(_In_ PEPROCESS process)
{
UNREFERENCED_PARAMETER(process);
// In user mode, return the current process token handle as a pseudo-token.
return (PACCESS_TOKEN)GetCurrentProcessToken();
}

VOID
PsDereferencePrimaryToken(_In_ PACCESS_TOKEN token)
{
UNREFERENCED_PARAMETER(token);
// No-op in user mode; GetCurrentProcessToken() returns a pseudo-handle.
}
129 changes: 129 additions & 0 deletions src/se.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,132 @@ SeQueryAuthenticationIdToken(_In_ PACCESS_TOKEN token, _Out_ PLUID authenticatio
usersim_convert_sid_to_luid(((PTOKEN_OWNER)token_owner_buffer)->Owner, authentication_id);
return STATUS_SUCCESS;
}

NTSTATUS
SeQueryInformationToken(_In_ PACCESS_TOKEN token, _In_ TOKEN_INFORMATION_CLASS token_information_class, _Out_ PVOID* token_information)
{
*token_information = nullptr;

if (cxplat_fault_injection_inject_fault()) {
return STATUS_UNSUCCESSFUL;
}

HANDLE token_handle = (HANDLE)token;
DWORD needed = 0;

// Get required buffer size.
(void)GetTokenInformation(token_handle, token_information_class, nullptr, 0, &needed);
DWORD error = GetLastError();
if (error != ERROR_INSUFFICIENT_BUFFER || needed == 0) {
return win32_error_to_usersim_error(error);
}

// Allocate buffer (caller frees with ExFreePool).
void* buffer = ExAllocatePoolUninitialized(NonPagedPoolNx, needed, USERSIM_TAG_TOKEN_ACCESS_INFORMATION);
if (buffer == nullptr) {
return STATUS_NO_MEMORY;
}

if (!GetTokenInformation(token_handle, token_information_class, buffer, needed, &needed)) {
ExFreePool(buffer);
return win32_error_to_usersim_error(GetLastError());
}

*token_information = buffer;
return STATUS_SUCCESS;
}

NTSTATUS
SecLookupAccountSid(
_In_ PSID Sid,
_Inout_ PULONG NameSize,
_Out_opt_ PUNICODE_STRING Name,
_Inout_ PULONG DomainSize,
_Out_opt_ PUNICODE_STRING Domain,
_Out_ PSID_NAME_USE SidNameUse)
{
if (cxplat_fault_injection_inject_fault()) {
return STATUS_UNSUCCESSFUL;
}

if (Sid == nullptr || NameSize == nullptr || DomainSize == nullptr || SidNameUse == nullptr) {
return STATUS_INVALID_PARAMETER;
}

// Use LookupAccountSidW to resolve the SID in user mode.
DWORD name_chars = 0;
DWORD domain_chars = 0;
SID_NAME_USE name_use;

// First call to get required buffer sizes (in characters including null terminator).
(void)LookupAccountSidW(nullptr, Sid, nullptr, &name_chars, nullptr, &domain_chars, &name_use);
DWORD error = GetLastError();
if (error != ERROR_INSUFFICIENT_BUFFER) {
return win32_error_to_usersim_error(error);
}

// If caller just wants sizes (Name and Domain are NULL), return sizes in bytes.
if (Name == nullptr && Domain == nullptr) {
// Return sizes as byte counts (without null terminator) to match kernel SecLookupAccountSid behavior.
*NameSize = (name_chars > 0) ? (ULONG)((name_chars - 1) * sizeof(WCHAR)) : 0;
*DomainSize = (domain_chars > 0) ? (ULONG)((domain_chars - 1) * sizeof(WCHAR)) : 0;
*SidNameUse = name_use;
return STATUS_BUFFER_TOO_SMALL;
}

// Allocate temporary buffers for the LookupAccountSidW call.
WCHAR* name_buf = nullptr;
WCHAR* domain_buf = nullptr;

if (name_chars > 0) {
name_buf = (WCHAR*)malloc(name_chars * sizeof(WCHAR));
if (name_buf == nullptr) {
return STATUS_NO_MEMORY;
}
}
if (domain_chars > 0) {
domain_buf = (WCHAR*)malloc(domain_chars * sizeof(WCHAR));
if (domain_buf == nullptr) {
free(name_buf);
return STATUS_NO_MEMORY;
}
}

if (!LookupAccountSidW(nullptr, Sid, name_buf, &name_chars, domain_buf, &domain_chars, &name_use)) {
free(name_buf);
free(domain_buf);
return win32_error_to_usersim_error(GetLastError());
}

// Copy results into caller-provided UNICODE_STRING buffers.
// The kernel SecLookupAccountSid returns Length in bytes (without null terminator).
if (Name != nullptr && Name->Buffer != nullptr && name_chars > 0) {
USHORT byte_len = (USHORT)((name_chars) * sizeof(WCHAR));
if (byte_len > Name->MaximumLength) {
byte_len = Name->MaximumLength;
}
memcpy(Name->Buffer, name_buf, byte_len);
Name->Length = byte_len;
*NameSize = byte_len;
} else {
*NameSize = 0;
}

if (Domain != nullptr && Domain->Buffer != nullptr && domain_chars > 0) {
USHORT byte_len = (USHORT)((domain_chars) * sizeof(WCHAR));
if (byte_len > Domain->MaximumLength) {
byte_len = Domain->MaximumLength;
}
memcpy(Domain->Buffer, domain_buf, byte_len);
Domain->Length = byte_len;
*DomainSize = byte_len;
} else {
*DomainSize = 0;
}

*SidNameUse = name_use;

free(name_buf);
free(domain_buf);
return STATUS_SUCCESS;
}
Loading