-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #104 from RadWolfie/impl-object-types-test
Implement object type tests
- Loading branch information
Showing
16 changed files
with
356 additions
and
73 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,73 @@ | ||
#include <xboxkrnl/xboxkrnl.h> | ||
|
||
#include "util/output.h" | ||
#include "defines.h" | ||
|
||
static BOOL assert_object_type_ex(POBJECT_TYPE object_type, | ||
ULONG pool_tag, | ||
BOOL has_close, | ||
BOOL has_delete, | ||
BOOL has_parse, | ||
int func_line) | ||
{ | ||
ASSERT_HEADER; | ||
|
||
BOOLEAN is_address_valid; | ||
GEN_CHECK_EX(object_type->AllocateProcedure, ExAllocatePoolWithTag, ".AllocateProcedure", func_line); | ||
GEN_CHECK_EX(object_type->FreeProcedure, ExFreePool, ".FreeProcedure", func_line); | ||
// NOTE: Some object type has Close/Delete/Parse functions assigned. | ||
GEN_CHECK_EX(object_type->CloseProcedure != NULL, has_close, ".CloseProcedure", func_line); | ||
if (has_close) { | ||
is_address_valid = MmIsAddressValid(object_type->CloseProcedure); | ||
GEN_CHECK_EX(is_address_valid, TRUE, ".CloseProcedure valid", func_line); | ||
} | ||
GEN_CHECK_EX(object_type->DeleteProcedure != NULL, has_delete, ".DeleteProcedure", func_line); | ||
if (has_delete) { | ||
is_address_valid = MmIsAddressValid(object_type->DeleteProcedure); | ||
GEN_CHECK_EX(is_address_valid, TRUE, ".DeleteProcedure valid", func_line); | ||
} | ||
GEN_CHECK_EX(object_type->ParseProcedure != NULL, has_parse, ".ParseProcedure", func_line); | ||
if (has_parse) { | ||
is_address_valid = MmIsAddressValid(object_type->ParseProcedure); | ||
GEN_CHECK_EX(is_address_valid, TRUE, ".ParseProcedure valid", func_line); | ||
} | ||
// 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 (either within kernel executable | ||
// or allocated by ObCreateObject) is not exposed through kernel APIs. | ||
// We can only verify if the absolute address is valid with a call to the | ||
// 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__) |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
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,77 @@ | ||
#include <xboxkrnl/xboxkrnl.h> | ||
#include <synchapi.h> | ||
#include <handleapi.h> | ||
|
||
#include "util/output.h" | ||
#include "assertions/object_type.h" | ||
|
||
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(); | ||
} | ||
|
||
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(); | ||
} | ||
|
||
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(); | ||
} | ||
|
||
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(); | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
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,82 @@ | ||
#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(); | ||
} | ||
|
||
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(); | ||
} | ||
|
||
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(); | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
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,49 @@ | ||
#include <xboxkrnl/xboxkrnl.h> | ||
#include <nxdk/mount.h> | ||
#include <handleapi.h> | ||
|
||
#include "util/output.h" | ||
#include "assertions/object_type.h" | ||
|
||
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(); | ||
} | ||
|
||
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(); | ||
} |
Oops, something went wrong.