Skip to content

Commit

Permalink
add __ObjectType tests for relative call check
Browse files Browse the repository at this point in the history
  • Loading branch information
RadWolfie committed Feb 26, 2024
1 parent 6001cdf commit a2a9715
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 1 deletion.
34 changes: 33 additions & 1 deletion src/assertions/object_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,42 @@ static BOOL assert_object_type_ex(POBJECT_TYPE object_type,
is_address_valid = MmIsAddressValid(object_type->ParseProcedure);
GEN_CHECK_EX(is_address_valid, TRUE, ".ParseProcedure valid", func_line);
}
// TODO: DefaultObject field require check against the object's address for some object types.
// NOTE: DefaultObject check has been moved to assert_object_header_type_ex function. Because it needs the object's address.
GEN_CHECK_EX(object_type->PoolTag, pool_tag, ".PoolTag", func_line);

return test_passed;
}
#define assert_object_type(object_type, pool_tag, has_close, has_delete, has_parse) \
assert_object_type_ex(object_type, pool_tag, has_close, has_delete, has_parse, __LINE__)

static BOOL assert_object_header_type_ex(POBJECT_TYPE object_type,
HANDLE object_handle,
int func_line)
{
ASSERT_HEADER;

PVOID type_object;
NTSTATUS status = ObReferenceObjectByHandle(object_handle, object_type, &type_object);
GEN_CHECK_EX(type_object != NULL, TRUE, "type_object", func_line);
if (NT_SUCCESS(status)) {
POBJECT_HEADER event_object_header = OBJECT_TO_OBJECT_HEADER(type_object);
// NOTE: DefaultObject's relative offset or address (above 0x80000000) are private.
// Since they are private, we can only verify if the address is valid by call
// MmIsAddressValid function.
BOOLEAN is_address_valid;
if ((LONG_PTR)object_type->DefaultObject >= 0) {
is_address_valid = MmIsAddressValid((PUCHAR)type_object + (LONG_PTR)object_type->DefaultObject);
}
else {
is_address_valid = MmIsAddressValid(type_object);
}
GEN_CHECK_EX(is_address_valid, TRUE, ".DefaultObject valid", func_line);

GEN_CHECK_EX(event_object_header->Type, object_type, "object_header->Type", func_line);
ObfDereferenceObject(type_object);
}

return test_passed;
}
#define assert_object_header_type(object_type, object_handle) \
assert_object_header_type_ex(object_type, object_handle, __LINE__)
37 changes: 37 additions & 0 deletions src/tests/ex/suite/object_type.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include <xboxkrnl/xboxkrnl.h>
#include <synchapi.h>
#include <handleapi.h>

#include "util/output.h"
#include "assertions/object_type.h"
Expand All @@ -8,6 +10,13 @@ TEST_FUNC(ExEventObjectType)
TEST_BEGIN();

test_passed &= assert_object_type(&ExEventObjectType, 'vevE', FALSE, FALSE, FALSE);
HANDLE event_handle = CreateEventA(NULL, TRUE, FALSE, "ExEventObjectType");
GEN_CHECK(event_handle != INVALID_HANDLE_VALUE, TRUE, "event_handle");
if (event_handle != INVALID_HANDLE_VALUE) {
test_passed &= assert_object_header_type(&ExEventObjectType, event_handle);
BOOL close = CloseHandle(event_handle);
GEN_CHECK(close, TRUE, "close handle");
}

TEST_END();
}
Expand All @@ -17,6 +26,13 @@ TEST_FUNC(ExMutantObjectType)
TEST_BEGIN();

test_passed &= assert_object_type(&ExMutantObjectType, 'atuM', FALSE, TRUE, FALSE);
HANDLE mutant_handle = CreateMutexA(NULL, TRUE, "ExMutantObjectType");
GEN_CHECK(mutant_handle != INVALID_HANDLE_VALUE, TRUE, "mutant_handle");
if (mutant_handle != INVALID_HANDLE_VALUE) {
test_passed &= assert_object_header_type(&ExMutantObjectType, mutant_handle);
BOOL close = CloseHandle(mutant_handle);
GEN_CHECK(close, TRUE, "close handle");
}

TEST_END();
}
Expand All @@ -26,6 +42,13 @@ TEST_FUNC(ExSemaphoreObjectType)
TEST_BEGIN();

test_passed &= assert_object_type(&ExSemaphoreObjectType, 'ameS', FALSE, FALSE, FALSE);
HANDLE semaphore_handle = CreateSemaphore(NULL, 0, 1, "ExSemaphoreObjectType");
GEN_CHECK(semaphore_handle != INVALID_HANDLE_VALUE, TRUE, "semaphore_handle");
if (semaphore_handle != INVALID_HANDLE_VALUE) {
test_passed &= assert_object_header_type(&ExSemaphoreObjectType, semaphore_handle);
BOOL close = CloseHandle(semaphore_handle);
GEN_CHECK(close, TRUE, "close handle");
}

TEST_END();
}
Expand All @@ -35,6 +58,20 @@ TEST_FUNC(ExTimerObjectType)
TEST_BEGIN();

test_passed &= assert_object_type(&ExTimerObjectType, 'emiT', FALSE, TRUE, FALSE);
// NOTE: There's no such thing as CreateTimer for Windows, it is done through SetTimer.
ANSI_STRING obj_name;
RtlInitAnsiString(&obj_name, "ExTimerObjectType");
OBJECT_ATTRIBUTES obj_attr;
InitializeObjectAttributes(&obj_attr, &obj_name, OBJ_OPENIF, ObWin32NamedObjectsDirectory(), NULL);
// --------
HANDLE timer_handle;
NTSTATUS status = NtCreateTimer(&timer_handle, &obj_attr, NotificationTimer);
GEN_CHECK(timer_handle != INVALID_HANDLE_VALUE, TRUE, "timer_handle");
if (timer_handle != INVALID_HANDLE_VALUE) {
test_passed &= assert_object_header_type(&ExTimerObjectType, timer_handle);
BOOL close = CloseHandle(timer_handle);
GEN_CHECK(close, TRUE, "close handle");
}

TEST_END();
}
51 changes: 51 additions & 0 deletions src/tests/io/suite/object_type.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
#include <xboxkrnl/xboxkrnl.h>
#include <synchapi.h>
#include <fileapi.h>
#include <handleapi.h>

#include "util/output.h"
#include "assertions/object_type.h"
#include "util/device_dummy.h"

TEST_FUNC(IoCompletionObjectType)
{
TEST_BEGIN();

test_passed &= assert_object_type(&IoCompletionObjectType, 'pmoC', FALSE, TRUE, FALSE);
HANDLE completion_handle;
NTSTATUS status = NtCreateIoCompletion(&completion_handle, STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3, NULL, 0);
GEN_CHECK(completion_handle != INVALID_HANDLE_VALUE, TRUE, "completion_handle");
if (completion_handle != INVALID_HANDLE_VALUE) {
test_passed &= assert_object_header_type(&IoCompletionObjectType, completion_handle);
PVOID key_context = NULL, apc_context = NULL;
IO_STATUS_BLOCK status_block = { 0 };
status = NtSetIoCompletion(completion_handle, &key_context, &apc_context, STATUS_SUCCESS, status_block.Information);
GEN_CHECK(status, STATUS_SUCCESS, "status return");
LARGE_INTEGER timeout = { .QuadPart = 0 };
status = NtRemoveIoCompletion(completion_handle, &key_context, &apc_context, &status_block, &timeout);
GEN_CHECK(status, STATUS_SUCCESS, "status return");
GEN_CHECK(status_block.Status, STATUS_SUCCESS, "status block");
}

TEST_END();
}
Expand All @@ -17,6 +35,25 @@ TEST_FUNC(IoDeviceObjectType)
TEST_BEGIN();

test_passed &= assert_object_type(&IoDeviceObjectType, 'iveD', FALSE, FALSE, TRUE);
ANSI_STRING obj_name;
RtlInitAnsiString(&obj_name, "\\Device\\IoDeviceObjectType");
NTSTATUS status = IoCreateDevice(&dummy_driver_object, 0, &obj_name, FILE_DEVICE_CD_ROM, FALSE, &dummy_device_object);
GEN_CHECK(status, STATUS_SUCCESS, "status return");
if (NT_SUCCESS(status)) {
OBJECT_ATTRIBUTES obj_attr;
InitializeObjectAttributes(&obj_attr, &obj_name, OBJ_OPENIF, NULL, NULL);
HANDLE device_handle;
status = ObOpenObjectByName(&obj_attr, NULL, NULL, &device_handle);
GEN_CHECK(status, STATUS_SUCCESS, "status return");
GEN_CHECK(device_handle != INVALID_HANDLE_VALUE, TRUE, "device_handle");
if (device_handle != INVALID_HANDLE_VALUE) {
test_passed &= assert_object_header_type(&IoDeviceObjectType, device_handle);
BOOL close = CloseHandle(device_handle);
GEN_CHECK(close, TRUE, "close handle");
}
IoDeleteDevice(dummy_device_object);
dummy_device_object = NULL;
}

TEST_END();
}
Expand All @@ -26,6 +63,20 @@ TEST_FUNC(IoFileObjectType)
TEST_BEGIN();

test_passed &= assert_object_type(&IoFileObjectType, 'eliF', TRUE, TRUE, TRUE);
HANDLE file_handle = CreateFileA("D:\\IoFileObjectType",
GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
GEN_CHECK(file_handle != INVALID_HANDLE_VALUE, TRUE, "file_handle");
if (file_handle != INVALID_HANDLE_VALUE) {
test_passed &= assert_object_header_type(&IoFileObjectType, file_handle);
BOOL close = CloseHandle(file_handle);
GEN_CHECK(close, TRUE, "close handle");
BOOL delete = DeleteFileA("D:\\IoFileObjectType");
GEN_CHECK(delete, TRUE, "delete file");
}

TEST_END();
}
27 changes: 27 additions & 0 deletions src/tests/ob/suite/object_type.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include <xboxkrnl/xboxkrnl.h>
#include <nxdk/mount.h>
#include <handleapi.h>

#include "util/output.h"
#include "assertions/object_type.h"
Expand All @@ -8,6 +10,15 @@ TEST_FUNC(ObDirectoryObjectType)
TEST_BEGIN();

test_passed &= assert_object_type(&ObDirectoryObjectType, 'eriD', FALSE, FALSE, FALSE);
OBJECT_ATTRIBUTES obj_attr;
InitializeObjectAttributes(&obj_attr, NULL, OBJ_CASE_INSENSITIVE, ObDosDevicesDirectory(), NULL);
HANDLE directory_handle;
NTSTATUS status = NtOpenDirectoryObject(&directory_handle, &obj_attr);
if (NT_SUCCESS(status)) {
test_passed &= assert_object_header_type(&ObDirectoryObjectType, directory_handle);
BOOL close = CloseHandle(directory_handle);
GEN_CHECK(close, TRUE, "close handle");
}

TEST_END();
}
Expand All @@ -17,6 +28,22 @@ TEST_FUNC(ObSymbolicLinkObjectType)
TEST_BEGIN();

test_passed &= assert_object_type(&ObSymbolicLinkObjectType, 'bmyS', FALSE, TRUE, FALSE);
ANSI_STRING obj_name;
RtlInitAnsiString(&obj_name, "\\??\\A:");
bool is_mount = nxMountDrive(obj_name.Buffer[4], "\\Device\\CdRom0");
GEN_CHECK(is_mount, TRUE, "is_mount");
OBJECT_ATTRIBUTES obj_attr;
InitializeObjectAttributes(&obj_attr, &obj_name, OBJ_CASE_INSENSITIVE, NULL, NULL);
HANDLE symlink_handle;
NTSTATUS status = NtOpenSymbolicLinkObject(&symlink_handle, &obj_attr);
if (NT_SUCCESS(status)) {
test_passed &= assert_object_header_type(&ObSymbolicLinkObjectType, symlink_handle);
BOOL close = CloseHandle(symlink_handle);
GEN_CHECK(close, TRUE, "close handle");
}
if (is_mount) {
nxUnmountDrive(obj_name.Buffer[4]);
}

TEST_END();
}
26 changes: 26 additions & 0 deletions src/tests/ps/PsThreadObjectType.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,39 @@
#include <xboxkrnl/xboxkrnl.h>
#include <processthreadsapi.h>
#include <synchapi.h>
#include <handleapi.h>

#include "util/output.h"
#include "assertions/object_type.h"

DWORD NTAPI dummy_thread(
IN PVOID context
)
{
return 0;
}

TEST_FUNC(PsThreadObjectType)
{
TEST_BEGIN();

test_passed &= assert_object_type(&PsThreadObjectType, 'erhT', FALSE, FALSE, FALSE);
HANDLE thread_handle = CreateThread(NULL, 0, dummy_thread, NULL, 0, NULL);
GEN_CHECK(thread_handle != INVALID_HANDLE_VALUE, TRUE, "thread_handle");
if (thread_handle != INVALID_HANDLE_VALUE) {
test_passed &= assert_object_header_type(&PsThreadObjectType, thread_handle);
do {
DWORD ExitCode = 0;
GetExitCodeThread(thread_handle, &ExitCode);
if (ExitCode != STILL_ACTIVE) {
break;
}
Sleep(10);
}
while(1);
BOOL close = CloseHandle(thread_handle);
GEN_CHECK(close, TRUE, "close handle");
}

TEST_END();
}
33 changes: 33 additions & 0 deletions src/util/device_dummy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <xboxkrnl/xboxkrnl.h>

static void NTAPI dummy_start_io(
IN DEVICE_OBJECT *DeviceObject,
IN IRP *Irp
)
{
// Don't need to initialize anything
}

PDEVICE_OBJECT dummy_device_object = NULL;

DRIVER_OBJECT dummy_driver_object = {
.DriverStartIo = dummy_start_io,
.DriverDeleteDevice = NULL,
.DriverDismountVolume = NULL,
.MajorFunction = {
IoInvalidDeviceRequest, // IRP_MJ_CREATE
IoInvalidDeviceRequest, // IRP_MJ_CLOSE
IoInvalidDeviceRequest, // IRP_MJ_READ
IoInvalidDeviceRequest, // IRP_MJ_WRITE
IoInvalidDeviceRequest, // IRP_MJ_QUERY_INFORMATION
IoInvalidDeviceRequest, // IRP_MJ_SET_INFORMATION
IoInvalidDeviceRequest, // IRP_MJ_FLUSH_BUFFERS
IoInvalidDeviceRequest, // IRP_MJ_QUERY_VOLUME_INFORMATION
IoInvalidDeviceRequest, // IRP_MJ_DIRECTORY_CONTROL
IoInvalidDeviceRequest, // IRP_MJ_FILE_SYSTEM_CONTROL
IoInvalidDeviceRequest, // IRP_MJ_DEVICE_CONTROL
IoInvalidDeviceRequest, // IRP_MJ_INTERNAL_DEVICE_CONTROL
IoInvalidDeviceRequest, // IRP_MJ_SHUTDOWN
IoInvalidDeviceRequest // IRP_MJ_CLEANUP
}
};
10 changes: 10 additions & 0 deletions src/util/device_dummy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#include <xboxkrnl/xboxkrnl.h>

#ifndef FILE_DEVICE_CD_ROM
#define FILE_DEVICE_CD_ROM 2
#endif

extern PDEVICE_OBJECT dummy_device_object;
extern DRIVER_OBJECT dummy_driver_object;

0 comments on commit a2a9715

Please sign in to comment.