[Kernel] - Change OddObj to X_DISPATCH_HEADER
- Change OddObj to X_DISPATCH_HEADER - Add unknown X_KWAIT_REASON flag - Fixed InitializeGuestObject mistake - Replaces unknowns in kthread using nukernel as reference
This commit is contained in:
committed by
Radosław Gliński
parent
c2674b19d2
commit
dc4db67f9c
@@ -1527,15 +1527,17 @@ void KernelState::InitializeKernelGuestGlobals() {
|
||||
SetProcessTLSVars(system_process, 32, 0, 0);
|
||||
|
||||
uint32_t oddobject_offset =
|
||||
kernel_guest_globals_ + offsetof(KernelGuestGlobals, OddObj);
|
||||
kernel_guest_globals_ +
|
||||
offsetof(KernelGuestGlobals, XboxKernelDefaultObject);
|
||||
|
||||
// init unknown object
|
||||
|
||||
block->OddObj.field0 = 0x1000000;
|
||||
block->OddObj.field4 = 1;
|
||||
block->OddObj.points_to_self =
|
||||
oddobject_offset + offsetof(X_UNKNOWN_TYPE_REFED, points_to_self);
|
||||
block->OddObj.points_to_prior = block->OddObj.points_to_self;
|
||||
block->XboxKernelDefaultObject.type = DISPATCHER_AUTO_RESET_EVENT;
|
||||
block->XboxKernelDefaultObject.signal_state = 1;
|
||||
block->XboxKernelDefaultObject.wait_list.flink_ptr =
|
||||
oddobject_offset + offsetof(X_DISPATCH_HEADER, wait_list.flink_ptr);
|
||||
block->XboxKernelDefaultObject.wait_list.blink_ptr =
|
||||
block->XboxKernelDefaultObject.wait_list.flink_ptr;
|
||||
|
||||
// init thread object
|
||||
block->ExThreadObjectType.pool_tag = 0x65726854;
|
||||
|
||||
@@ -96,21 +96,13 @@ struct TerminateNotification {
|
||||
// a bit like the timers on KUSER_SHARED on normal win32
|
||||
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm
|
||||
struct X_TIME_STAMP_BUNDLE {
|
||||
// according to Nukernl these are BE
|
||||
uint64_t interrupt_time;
|
||||
// i assume system_time is in 100 ns intervals like on win32
|
||||
uint64_t system_time;
|
||||
uint32_t tick_count;
|
||||
uint32_t padding;
|
||||
};
|
||||
struct X_UNKNOWN_TYPE_REFED {
|
||||
xe::be<uint32_t> field0;
|
||||
xe::be<uint32_t> field4;
|
||||
// this is definitely a LIST_ENTRY?
|
||||
xe::be<uint32_t> points_to_self; // this field points to itself
|
||||
xe::be<uint32_t>
|
||||
points_to_prior; // points to the previous field, which points to itself
|
||||
};
|
||||
static_assert_size(X_UNKNOWN_TYPE_REFED, 16);
|
||||
|
||||
struct KernelGuestGlobals {
|
||||
X_OBJECT_TYPE ExThreadObjectType;
|
||||
@@ -125,7 +117,7 @@ struct KernelGuestGlobals {
|
||||
X_OBJECT_TYPE ObSymbolicLinkObjectType;
|
||||
// a constant buffer that some object types' "unknown_size_or_object" field
|
||||
// points to
|
||||
X_UNKNOWN_TYPE_REFED OddObj;
|
||||
X_DISPATCH_HEADER XboxKernelDefaultObject;
|
||||
X_KPROCESS idle_process; // X_PROCTYPE_IDLE. runs in interrupt contexts. is
|
||||
// also the context the kernel starts in?
|
||||
X_KPROCESS title_process; // X_PROCTYPE_TITLE
|
||||
|
||||
@@ -676,7 +676,7 @@ struct X_POOL_ALLOC_HEADER {
|
||||
};
|
||||
|
||||
uint32_t xeAllocatePoolTypeWithTag(PPCContext* context, uint32_t size,
|
||||
uint32_t tag, uint32_t zero) {
|
||||
uint32_t tag, uint32_t pool_selector) {
|
||||
if (size <= 0xFD8) {
|
||||
uint32_t adjusted_size = size + sizeof(X_POOL_ALLOC_HEADER);
|
||||
|
||||
@@ -694,9 +694,9 @@ uint32_t xeAllocatePoolTypeWithTag(PPCContext* context, uint32_t size,
|
||||
}
|
||||
|
||||
dword_result_t ExAllocatePoolTypeWithTag_entry(dword_t size, dword_t tag,
|
||||
dword_t zero,
|
||||
dword_t pool_selector,
|
||||
const ppc_context_t& context) {
|
||||
return xeAllocatePoolTypeWithTag(context, size, tag, zero);
|
||||
return xeAllocatePoolTypeWithTag(context, size, tag, pool_selector);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ExAllocatePoolTypeWithTag, kMemory, kImplemented);
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ uint32_t xeMmAllocatePhysicalMemoryEx(uint32_t flags, uint32_t region_size,
|
||||
dword_result_t xeMmQueryStatistics(
|
||||
pointer_t<X_MM_QUERY_STATISTICS_RESULT> stats_ptr);
|
||||
uint32_t xeAllocatePoolTypeWithTag(PPCContext* context, uint32_t size,
|
||||
uint32_t tag, uint32_t zero);
|
||||
uint32_t tag, uint32_t pool_selector);
|
||||
|
||||
void xeFreePool(PPCContext* context, uint32_t base_address);
|
||||
|
||||
|
||||
@@ -544,7 +544,7 @@ static_assert_size(X_RTL_CRITICAL_SECTION, 28);
|
||||
|
||||
void xeRtlInitializeCriticalSection(X_RTL_CRITICAL_SECTION* cs,
|
||||
uint32_t cs_ptr) {
|
||||
cs->header.type = 1; // EventSynchronizationObject (auto reset)
|
||||
cs->header.type = X_DISPATCHER_FLAGS::DISPATCHER_AUTO_RESET_EVENT;
|
||||
cs->header.absolute = 0; // spin count div 256
|
||||
cs->header.signal_state = 0;
|
||||
cs->lock_count = -1;
|
||||
@@ -567,7 +567,7 @@ X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(X_RTL_CRITICAL_SECTION* cs,
|
||||
spin_count_div_256 = 255;
|
||||
}
|
||||
|
||||
cs->header.type = 1; // EventSynchronizationObject (auto reset)
|
||||
cs->header.type = X_DISPATCHER_FLAGS::DISPATCHER_AUTO_RESET_EVENT;
|
||||
cs->header.absolute = spin_count_div_256;
|
||||
cs->header.signal_state = 0;
|
||||
cs->lock_count = -1;
|
||||
|
||||
@@ -692,12 +692,12 @@ DECLARE_XBOXKRNL_EXPORT2(NtClearEvent, kThreading, kImplemented,
|
||||
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff552150(v=vs.85).aspx
|
||||
void KeInitializeSemaphore_entry(pointer_t<X_KSEMAPHORE> semaphore_ptr,
|
||||
dword_t count, dword_t limit) {
|
||||
semaphore_ptr->header.type = 5; // SemaphoreObject
|
||||
semaphore_ptr->header.type = X_DISPATCHER_FLAGS::DISPATCHER_SEMAPHORE;
|
||||
semaphore_ptr->header.signal_state = (uint32_t)count;
|
||||
semaphore_ptr->limit = (uint32_t)limit;
|
||||
|
||||
auto sem = XObject::GetNativeObject<XSemaphore>(kernel_state(), semaphore_ptr,
|
||||
5 /* SemaphoreObject */);
|
||||
auto sem = XObject::GetNativeObject<XSemaphore>(
|
||||
kernel_state(), semaphore_ptr, X_DISPATCHER_FLAGS::DISPATCHER_SEMAPHORE);
|
||||
if (!sem) {
|
||||
assert_always();
|
||||
return;
|
||||
@@ -1014,7 +1014,7 @@ dword_result_t KeWaitForMultipleObjects_entry(
|
||||
dword_t count, lpdword_t objects_ptr, dword_t wait_type,
|
||||
dword_t wait_reason, dword_t processor_mode, dword_t alertable,
|
||||
lpqword_t timeout_ptr, lpvoid_t wait_block_array_ptr) {
|
||||
assert_true(wait_type <= 1);
|
||||
assert_true(wait_type <= X_KWAIT_REASON::WaitAny);
|
||||
|
||||
assert_true(count <= 64);
|
||||
object_ref<XObject> objects[64];
|
||||
@@ -1049,7 +1049,7 @@ uint32_t xeNtWaitForMultipleObjectsEx(uint32_t count, xe::be<uint32_t>* handles,
|
||||
uint32_t wait_type, uint32_t wait_mode,
|
||||
uint32_t alertable,
|
||||
uint64_t* timeout_ptr) {
|
||||
assert_true(wait_type <= 1);
|
||||
assert_true(wait_type <= X_KWAIT_REASON::WaitAny);
|
||||
|
||||
assert_true(count <= 64);
|
||||
object_ref<XObject> objects[64];
|
||||
@@ -1091,7 +1091,8 @@ dword_result_t NtWaitForMultipleObjectsEx_entry(
|
||||
dword_t count, lpdword_t handles, dword_t wait_type, dword_t wait_mode,
|
||||
dword_t alertable, lpqword_t timeout_ptr) {
|
||||
uint64_t timeout = timeout_ptr ? static_cast<uint64_t>(*timeout_ptr) : 0u;
|
||||
if (!count || count > 64 || (wait_type != 1 && wait_type)) {
|
||||
if (!count || count > 64 ||
|
||||
(wait_type != X_KWAIT_REASON::WaitAny && wait_type)) {
|
||||
return X_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
return xeNtWaitForMultipleObjectsEx(count, handles, wait_type, wait_mode,
|
||||
@@ -1871,7 +1872,7 @@ dword_result_t KeSetPriorityThread_entry(pointer_t<X_KTHREAD> thread_ptr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (thread_ptr->header.type != 6) {
|
||||
if (thread_ptr->header.type != X_DISPATCHER_FLAGS::DISPATCHER_THREAD) {
|
||||
XELOGW("{}: Invalid object type: {}", __func__, thread_ptr->header.type);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,10 +34,21 @@ class KernelState;
|
||||
template <typename T>
|
||||
class object_ref;
|
||||
|
||||
enum X_DISPATCHER_FLAGS : uint8_t {
|
||||
DISPATCHER_MANUAL_RESET_EVENT = 0,
|
||||
DISPATCHER_AUTO_RESET_EVENT = 1, // EventSynchronizationObject
|
||||
DISPATCHER_MUTANT = 2,
|
||||
DISPATCHER_QUEUE = 4,
|
||||
DISPATCHER_SEMAPHORE = 5, // SemaphoreObject
|
||||
DISPATCHER_THREAD = 6,
|
||||
DISPATCHER_MANUAL_RESET_TIMER = 8,
|
||||
DISPATCHER_AUTO_RESET_TIMER = 9,
|
||||
};
|
||||
|
||||
// https://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html
|
||||
typedef struct {
|
||||
struct {
|
||||
uint8_t type;
|
||||
uint8_t type; // X_DISPATCHER_FLAGS
|
||||
|
||||
union {
|
||||
uint8_t abandoned;
|
||||
|
||||
@@ -180,21 +180,25 @@ static uint8_t GetFakeCpuNumber(uint8_t proc_mask) {
|
||||
void XThread::InitializeGuestObject() {
|
||||
auto guest_thread = guest_object<X_KTHREAD>();
|
||||
auto thread_guest_ptr = guest_object();
|
||||
guest_thread->header.type = 6;
|
||||
guest_thread->header.type = X_DISPATCHER_FLAGS::DISPATCHER_THREAD;
|
||||
guest_thread->suspend_count =
|
||||
(creation_params_.creation_flags & X_CREATE_SUSPENDED) ? 1 : 0;
|
||||
|
||||
guest_thread->unk_10 = (thread_guest_ptr + 0x10);
|
||||
guest_thread->unk_14 = (thread_guest_ptr + 0x10);
|
||||
guest_thread->mutants_list.flink_ptr = (thread_guest_ptr + 0x10);
|
||||
guest_thread->mutants_list.blink_ptr = (thread_guest_ptr + 0x10);
|
||||
|
||||
auto timer_wait_header_list_entry = memory()->HostToGuestVirtual(
|
||||
&guest_thread->wait_timeout_timer.header.wait_list);
|
||||
guest_thread->wait_timeout_block.wait_list_entry.flink_ptr =
|
||||
thread_guest_ptr + 0x20;
|
||||
timer_wait_header_list_entry;
|
||||
guest_thread->wait_timeout_block.wait_list_entry.blink_ptr =
|
||||
thread_guest_ptr + 0x20;
|
||||
timer_wait_header_list_entry;
|
||||
guest_thread->wait_timeout_block.thread = thread_guest_ptr;
|
||||
uint32_t v6 = thread_guest_ptr + 0x18;
|
||||
guest_thread->wait_timeout_block.wait_result_xstatus = 0x0100;
|
||||
guest_thread->wait_timeout_block.wait_type = 0x0201;
|
||||
guest_thread->wait_timeout_block.object = v6;
|
||||
guest_thread->wait_timeout_block.object =
|
||||
memory()->HostToGuestVirtual(&guest_thread->wait_timeout_timer);
|
||||
guest_thread->wait_timeout_block.wait_result_xstatus = X_STATUS_TIMEOUT;
|
||||
guest_thread->wait_timeout_block.wait_type = X_KWAIT_REASON::WaitAny;
|
||||
|
||||
guest_thread->stack_base = (this->stack_base_);
|
||||
guest_thread->stack_limit = (this->stack_limit_);
|
||||
guest_thread->stack_kernel = (this->stack_base_ - 240);
|
||||
|
||||
@@ -48,17 +48,6 @@ enum IRQL_FLAGS : uint8_t {
|
||||
IRQL_HIGHEST = 124
|
||||
};
|
||||
|
||||
enum X_DISPATCHER_FLAGS {
|
||||
DISPATCHER_MANUAL_RESET_EVENT = 0,
|
||||
DISPATCHER_AUTO_RESET_EVENT = 1,
|
||||
DISPATCHER_MUTANT = 2,
|
||||
DISPATCHER_QUEUE = 4,
|
||||
DISPATCHER_SEMAPHORE = 5,
|
||||
DISPATCHER_THREAD = 6,
|
||||
DISPATCHER_MANUAL_RESET_TIMER = 8,
|
||||
DISPATCHER_AUTO_RESET_TIMER = 9,
|
||||
};
|
||||
|
||||
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/ntos/ke/kthread_state.htm
|
||||
enum X_KTHREAD_STATE_FLAGS : uint8_t {
|
||||
KTHREAD_STATE_INITIALIZED = 0,
|
||||
@@ -222,12 +211,22 @@ struct X_KPCR {
|
||||
uint8_t unk_2AC[0x2C]; // 0x2AC
|
||||
};
|
||||
|
||||
#ifdef WAIT_ANY
|
||||
#undef WAIT_ANY
|
||||
#endif
|
||||
enum : uint16_t {
|
||||
WAIT_ALL = 0,
|
||||
WAIT_ANY = 1,
|
||||
struct X_KMUTANT {
|
||||
X_DISPATCH_HEADER header; // 0x0
|
||||
X_LIST_ENTRY unk_list; // 0x10
|
||||
TypedGuestPointer<X_KTHREAD> owner; // 0x18
|
||||
bool abandoned; // 0x1C
|
||||
// these might just be padding
|
||||
uint8_t unk_1D; // 0x1D
|
||||
uint8_t unk_1E; // 0x1E
|
||||
uint8_t unk_1F; // 0x1F
|
||||
};
|
||||
static_assert_size(X_KMUTANT, 0x20);
|
||||
|
||||
enum X_KWAIT_REASON : uint16_t {
|
||||
WaitAll = 0,
|
||||
WaitAny = 1,
|
||||
WaitUnk3 = 3,
|
||||
};
|
||||
|
||||
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/ntos/ke_x/kwait_block.htm
|
||||
@@ -243,7 +242,7 @@ struct X_KWAIT_BLOCK {
|
||||
// is satisfied
|
||||
xe::be<uint16_t> wait_result_xstatus;
|
||||
// WAIT_ALL or WAIT_ANY
|
||||
xe::be<uint16_t> wait_type;
|
||||
xe::be<X_KWAIT_REASON> wait_type;
|
||||
};
|
||||
|
||||
static_assert_size(X_KWAIT_BLOCK, 0x18);
|
||||
@@ -258,9 +257,9 @@ struct X_KTIMER {
|
||||
static_assert_size(X_KTIMER, 0x28);
|
||||
|
||||
struct X_KTHREAD {
|
||||
X_DISPATCH_HEADER header; // 0x0
|
||||
xe::be<uint32_t> unk_10; // 0x10
|
||||
xe::be<uint32_t> unk_14; // 0x14
|
||||
X_DISPATCH_HEADER header; // 0x0
|
||||
util::X_TYPED_LIST<X_KMUTANT, offsetof(X_KMUTANT, unk_list)>
|
||||
mutants_list; // 0x10
|
||||
X_KTIMER wait_timeout_timer; // 0x18
|
||||
X_KWAIT_BLOCK wait_timeout_block; // 0x40
|
||||
uint8_t unk_58[0x4]; // 0x58
|
||||
@@ -295,7 +294,11 @@ struct X_KTHREAD {
|
||||
xe::be<uint32_t> msr_mask; // 0x9C
|
||||
xe::be<X_STATUS> wait_result; // 0xA0
|
||||
uint8_t wait_irql; // 0xA4
|
||||
uint8_t unk_A5[0xB]; // 0xA5
|
||||
uint8_t processor_mode; // 0xA5
|
||||
uint8_t wait_next; // 0xA6
|
||||
uint8_t wait_reason; // 0xA7
|
||||
TypedGuestPointer<X_KWAIT_BLOCK> wait_blocks; // 0xA8
|
||||
uint8_t unk_AC[4]; // 0xAC
|
||||
int32_t apc_disable_count; // 0xB0
|
||||
xe::be<int32_t> quantum; // 0xB4
|
||||
uint8_t saturation_increment; // 0xB8
|
||||
|
||||
Reference in New Issue
Block a user