void TestSharedMemory( io_connect_t connect ) { kern_return_t kr; AppleSampleSharedMemory * shared; #if __LP64__ mach_vm_address_t addr; mach_vm_size_t size; #else vm_address_t addr; vm_size_t size; #endif kr = IOConnectMapMemory( connect, kAppleSamplePCIMemoryType1, mach_task_self(), &addr, &size, kIOMapAnywhere | kIOMapDefaultCache ); assert( KERN_SUCCESS == kr ); assert( size == sizeof( AppleSampleSharedMemory )); shared = (AppleSampleSharedMemory *) addr; printf("From AppleSampleSharedMemory: %08" PRIx32 ", %08" PRIx32 ", %08" PRIx32 ", \"%s\"\n", shared->field1, shared->field2, shared->field3, shared->string); strcpy( shared->string, "some other data" ); }
void printMsgBuffer(io_service_t service) { kern_return_t ret; io_connect_t connect = 0; #if __LP64__ mach_vm_address_t address; mach_vm_size_t size; #else vm_address_t address; vm_size_t size; #endif ret = IOServiceOpen(service, mach_task_self(), 0, &connect); if (ret != KERN_SUCCESS) { printf("error: IOServiceOpen returned 0x%08x\n", ret); goto failure; } ret = IOConnectMapMemory(connect, kVoodooHDAMemoryMessageBuffer, mach_task_self(), &address, &size, kIOMapAnywhere | kIOMapDefaultCache); if (ret != kIOReturnSuccess) { printf("error: IOConnectMapMemory returned 0x%08x\n", ret); goto failure; } printf("%s\n", (char *) address); failure: if (connect) { ret = IOServiceClose(connect); if (ret != KERN_SUCCESS) printf("warning: IOServiceClose returned 0x%08x\n", ret); } }
int main(){ // re map the null page rw vm_deallocate(mach_task_self(), 0x0, 0x1000); vm_address_t addr = 0; vm_allocate(mach_task_self(), &addr, 0x1000, 0); char* np = 0; for (int i = 0; i < 0x1000; i++){ np[i] = 'A'; } kern_return_t err; CFMutableDictionaryRef matching = IOServiceMatching("IntelAccelerator"); if (!matching){ printf("unable to create matching dictionary\n"); return 0; } io_service_t ia_service = IOServiceGetMatchingService(kIOMasterPortDefault, matching); if (ia_service == MACH_PORT_NULL){ printf("unable to get matching service\n"); return 0; } io_connect_t conn = MACH_PORT_NULL; err = IOServiceOpen(ia_service, mach_task_self(), 0x100, &conn); if (err != KERN_SUCCESS){ printf("unable to open user client\n"); return 0; } void* token_buf; size_t token_buf_size = 0; // kernel NULL deref here in IOAccelContext2::clientMemoryForType // mov rdi, [r12+1D8h] ; rdi := NULL // mov rax, [rdi] ; read vtable pointer from NULL // call qword ptr [rax+20h] ; controlled call err = IOConnectMapMemory(conn, 0, mach_task_self(), &token_buf, &token_buf_size, 1); if (err != KERN_SUCCESS){ printf("unable to map token buffer\n"); return 0; } printf("got token buffer: 0x%p size:0x%x\n", token_buf, token_buf_size); return 0; }
kern_return_t fake_IOConnectMapMemory( io_connect_t connect, uint32_t memoryType, task_port_t intoTask, vm_address_t *atAddress, vm_size_t *ofSize, IOOptionBits options ) { kern_return_t ret = IOConnectMapMemory(connect, memoryType, intoTask, atAddress, ofSize, options); if (memoryType == 0){ token_buf = *atAddress; } return ret; }
kern_return_t fake_IOConnectMapMemory( io_connect_t connect, uint32_t memoryType, task_port_t intoTask, vm_address_t *atAddress, vm_size_t *ofSize, IOOptionBits options ) { kern_return_t ret = IOConnectMapMemory(connect, memoryType, intoTask, atAddress, ofSize, options); // is this the mapping for the sideband buffer for the gpu tokens? if (memoryType == 0){ token_buf = *atAddress; } return ret; }
kern_return_t fake_IOConnectMapMemory( io_connect_t connect, uint32_t memoryType, task_port_t intoTask, vm_address_t *atAddress, vm_size_t *ofSize, IOOptionBits options ) { printf("IOConnectMapMemory(connect=%x, memoryType=0x%x, intoTask=%x, atAddress=%p, ofSize=%x, options=%x)\n", connect, memoryType, intoTask, atAddress, ofSize, options); kern_return_t ret = IOConnectMapMemory(connect, memoryType, intoTask, atAddress, ofSize, options); if (memoryType == 0 && connect == main_port){ token_buf = *atAddress; token_buf_size = *ofSize; printf(" this is the token buffer for IGAccelVideoContextMain\n"); } printf(" after: *atAddress: %p *ofSize = %x\n", *atAddress, *ofSize); return ret; }
void *map_physical(uint64_t phys_addr, size_t len) { kern_return_t err; #if __LP64__ mach_vm_address_t addr; mach_vm_size_t size; #else vm_address_t addr; vm_size_t size; #endif size_t dataInLen = sizeof(map_t); size_t dataOutLen = sizeof(map_t); map_t in, out; in.addr = phys_addr; in.size = len; #ifdef DEBUG printf("map_phys: phys %08lx, %08x\n", phys_addr, len); #endif #if !defined(__LP64__) && defined(WANT_OLD_API) /* Check if OSX 10.5 API is available */ if (IOConnectCallStructMethod != NULL) { #endif err = IOConnectCallStructMethod(connect, kPrepareMap, &in, dataInLen, &out, &dataOutLen); #if !defined(__LP64__) && defined(WANT_OLD_API) } else { /* Use old API */ err = IOConnectMethodStructureIStructureO(connect, kPrepareMap, dataInLen, &dataOutLen, &in, &out); } #endif if (err != KERN_SUCCESS) { printf("\nError(kPrepareMap): system 0x%x subsystem 0x%x code 0x%x ", err_get_system(err), err_get_sub(err), err_get_code(err)); printf("physical 0x%08"PRIx64"[0x%zx]\n", phys_addr, len); switch (err_get_code(err)) { case 0x2c2: printf("Invalid argument.\n"); errno = EINVAL; break; case 0x2cd: printf("Device not open.\n"); errno = ENOENT; break; } return MAP_FAILED; } err = IOConnectMapMemory(connect, 0, mach_task_self(), &addr, &size, kIOMapAnywhere | kIOMapInhibitCache); /* Now this is odd; The above connect seems to be unfinished at the * time the function returns. So wait a little bit, or the calling * program will just segfault. Bummer. Who knows a better solution? */ usleep(1000); if (err != KERN_SUCCESS) { printf("\nError(IOConnectMapMemory): system 0x%x subsystem 0x%x code 0x%x ", err_get_system(err), err_get_sub(err), err_get_code(err)); printf("physical 0x%08"PRIx64"[0x%zx]\n", phys_addr, len); switch (err_get_code(err)) { case 0x2c2: printf("Invalid argument.\n"); errno = EINVAL; break; case 0x2cd: printf("Device not open.\n"); errno = ENOENT; break; } return MAP_FAILED; } #ifdef DEBUG printf("map_phys: virt %08x, %08x\n", addr, size); #endif return (void *)addr; }
int main(){ kern_return_t err; CFMutableDictionaryRef matching = IOServiceMatching("IOBluetoothHCIController"); if(!matching){ printf("unable to create service matching dictionary\n"); return 0; } io_iterator_t iterator; err = IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator); if (err != KERN_SUCCESS){ printf("no matches\n"); return 0; } io_service_t service = IOIteratorNext(iterator); if (service == IO_OBJECT_NULL){ printf("unable to find service\n"); return 0; } printf("got service: %x\n", service); io_connect_t conn = MACH_PORT_NULL; err = IOServiceOpen(service, mach_task_self(), 1, &conn); if (err != KERN_SUCCESS){ printf("unable to get user client connection\n"); return 0; }else{ printf("got userclient connection: %x, type:%d\n", conn, 1); } printf("got userclient connection: %x\n", conn); mach_vm_address_t addr = 0x4100000000; mach_vm_size_t size = 0x1000; uint32_t* buf = 0; err = IOConnectMapMemory(conn, 0x1000, mach_task_self(), &addr, &size, 0); if (err != KERN_SUCCESS){ printf("IOConnectMapMemory failed:0x%x\n", err); return 0; } buf = (uint32_t*)addr; printf("mapped at: 0x%p size:0x%x\n", addr, size); for (int i = 0; i < 3; i++){ printf("0x%08x\n", buf[i]); } // overwrite the size field buf[0] = 0x12000; printf("probably crashing soon\n"); return 0; }
static IOReturn vnodeNotificationHandler(io_connect_t connection) { kern_return_t kr; VnodeWatcherData_t vdata; UInt32 dataSize; IODataQueueMemory *queueMappedMemory; vm_size_t queueMappedMemorySize; vm_address_t address = nil; vm_size_t size = 0; unsigned int msgType = 1; // family-defined port type (arbitrary) mach_port_t recvPort; // allocate a Mach port to receive notifications from the IODataQueue if (!(recvPort = IODataQueueAllocateNotificationPort())) { fprintf(stderr, "%s: failed to allocate notification port\n", PROGNAME); return kIOReturnError; } // this will call registerNotificationPort() inside our user client class kr = IOConnectSetNotificationPort(connection, msgType, recvPort, 0); if (kr != kIOReturnSuccess) { fprintf(stderr, "%s: failed to register notification port (%d)\n", PROGNAME, kr); mach_port_destroy(mach_task_self(), recvPort); return kr; } // this will call clientMemoryForType() inside our user client class kr = IOConnectMapMemory(connection, kIODefaultMemoryType, mach_task_self(), &address, &size, kIOMapAnywhere); if (kr != kIOReturnSuccess) { fprintf(stderr, "%s: failed to map memory (%d)\n", PROGNAME, kr); mach_port_destroy(mach_task_self(), recvPort); return kr; } queueMappedMemory = (IODataQueueMemory *)address; queueMappedMemorySize = size; while (IODataQueueWaitForAvailableData(queueMappedMemory, recvPort) == kIOReturnSuccess) { while (IODataQueueDataAvailable(queueMappedMemory)) { dataSize = sizeof(vdata); kr = IODataQueueDequeue(queueMappedMemory, &vdata, &dataSize); if (kr == kIOReturnSuccess) { if (*(UInt8 *)&vdata == kt_kStopListeningToMessages) goto exit; printf("\"%s\" %s %s %lu(%s) ", vdata.path, vtype_name(vdata.v_type), vtag_name(vdata.v_tag), vdata.pid, vdata.p_comm); action_print(vdata.action, (vdata.v_type & VDIR)); } else fprintf(stderr, "*** error in receiving data (%d)\n", kr); } } exit: kr = IOConnectUnmapMemory(connection, kIODefaultMemoryType, mach_task_self(), address); if (kr != kIOReturnSuccess) fprintf(stderr, "%s: failed to unmap memory (%d)\n", PROGNAME, kr); mach_port_destroy(mach_task_self(), recvPort); return kr; }
int main(int argc, char * argv[]) { kern_return_t kr; io_iterator_t iter; io_service_t framebuffer; io_string_t path; uint32_t index, maxIndex; io_connect_t connect; mach_timebase_info_data_t timebase; StdFBShmem_t * shmem[16]; vm_size_t shmemSize; CFNumberRef clk, count; vm_address_t mapAddr; kr = IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching( IOFRAMEBUFFER_CONFORMSTO), &iter); assert( KERN_SUCCESS == kr ); for ( index = 0; index++, (framebuffer = IOIteratorNext(iter)); IOObjectRelease(framebuffer)) { kr = IORegistryEntryGetPath(framebuffer, kIOServicePlane, path); assert( KERN_SUCCESS == kr ); printf("\n/* [%d] Using device: %s */\n", index, path); clk = IORegistryEntryCreateCFProperty(framebuffer, CFSTR(kIOFBCurrentPixelClockKey), kCFAllocatorDefault, kNilOptions); count = IORegistryEntryCreateCFProperty(framebuffer, CFSTR(kIOFBCurrentPixelCountKey), kCFAllocatorDefault, kNilOptions); if (clk && count) { float num, div; CFNumberGetValue(clk, kCFNumberFloatType, &num); CFNumberGetValue(count, kCFNumberFloatType, &div); printf("clock %.0f, count %.0f, rate %f Hz, period %f us\n", num, div, num / div, div * 1000 / num); } if (clk) CFRelease(clk); if (count) CFRelease(count); kr = mach_timebase_info(&timebase); assert(kIOReturnSuccess == kr); kr = IOServiceOpen(framebuffer, mach_task_self(), kIOFBSharedConnectType, &connect); if (kIOReturnSuccess != kr) { printf("IOServiceOpen(%x)\n", kr); continue; } kr = IOConnectMapMemory(connect, kIOFBCursorMemory, mach_task_self(), &mapAddr, &shmemSize, kIOMapAnywhere); if (kIOReturnSuccess != kr) { printf("IOConnectMapMemory(%x)\n", kr); continue; } shmem[index] = (StdFBShmem_t *) mapAddr; // bzero( shmem, shmemSize); // make sure its read only! printf("screenBounds (%d, %d), (%d, %d)\n", shmem[index]->screenBounds.minx, shmem[index]->screenBounds.miny, shmem[index]->screenBounds.maxx, shmem[index]->screenBounds.maxy); } maxIndex = index; while (true) { printf("\n"); for (index = 0; index < maxIndex; index++) { if (!shmem[index]) continue; uint64_t time = (((uint64_t) shmem[index]->vblTime.hi) << 32 | shmem[index]->vblTime.lo); uint64_t delta = (((uint64_t) shmem[index]->vblDelta.hi) << 32 | shmem[index]->vblDelta.lo); double usecs = delta * timebase.numer / timebase.denom / 1e6; if (!delta) continue; printf("[%d] time of last VBL 0x%qx, delta %qd (%f us), count %qd, measured delta %qd(%f%%), drift %qd(%qd%%)\n", index, time, delta, usecs, shmem[index]->vblCount, shmem[index]->vblDeltaMeasured, ((shmem[index]->vblDeltaMeasured * 100.0) / delta), shmem[index]->vblDrift, ((shmem[index]->vblDrift * 100) / delta)); } for (index = 0; index < maxIndex; index++) { if (!shmem[index]) continue; if ((shmem[index]->screenBounds.maxx - shmem[index]->screenBounds.minx) < 128) continue; printf("[%d] cursorShow %d, hw %d, frame %d, loc (%d, %d), hs (%d, %d), cursorRect (%d, %d), (%d, %d), saveRect (%d, %d), (%d, %d)\n", index, shmem[index]->cursorShow, shmem[index]->hardwareCursorActive, shmem[index]->frame, shmem[index]->cursorLoc.x, shmem[index]->cursorLoc.y, shmem[index]->hotSpot[0].x, shmem[index]->hotSpot[0].y, shmem[index]->cursorRect.minx, shmem[index]->cursorRect.miny, shmem[index]->cursorRect.maxx, shmem[index]->cursorRect.maxy, shmem[index]->saveRect.minx, shmem[index]->saveRect.miny, shmem[index]->saveRect.maxx, shmem[index]->saveRect.maxy); } sleep(1); } exit(0); return(0); }
IOReturn vnodeNotificationHandler(io_connect_t connection) { kern_return_t kr; DldDriverDataLog vdata; uint32_t dataSize; IODataQueueMemory *queueMappedMemory; vm_size_t queueMappedMemorySize; #if !__LP64__ || defined(IOCONNECT_MAPMEMORY_10_6) vm_address_t address = nil; vm_size_t size = 0; #else mach_vm_address_t address = NULL; mach_vm_size_t size = 0x0; #endif mach_port_t recvPort; // // allocate a Mach port to receive notifications from the IODataQueue // if (!(recvPort = IODataQueueAllocateNotificationPort())) { PRINT_ERROR(("failed to allocate notification port\n")); return kIOReturnError; } // // this will call registerNotificationPort() inside our user client class // kr = IOConnectSetNotificationPort(connection, kt_DldNotifyTypeLog, recvPort, 0); if (kr != kIOReturnSuccess) { PRINT_ERROR(("failed to register notification port (%d)\n", kr)); mach_port_destroy(mach_task_self(), recvPort); return kr; } // // this will call clientMemoryForType() inside our user client class // kr = IOConnectMapMemory( connection, kt_DldNotifyTypeLog, mach_task_self(), &address, &size, kIOMapAnywhere ); if (kr != kIOReturnSuccess) { PRINT_ERROR(("failed to map memory (%d)\n",kr)); mach_port_destroy(mach_task_self(), recvPort); return kr; } queueMappedMemory = (IODataQueueMemory *)address; queueMappedMemorySize = size; printf("before the while loop\n"); //bool first_iteration = true; while( kIOReturnSuccess == IODataQueueWaitForAvailableData(queueMappedMemory, recvPort) ) { //first_iteration = false; //printf("a buffer has been received\n"); while (IODataQueueDataAvailable(queueMappedMemory)) { dataSize = sizeof(vdata); kr = IODataQueueDequeue(queueMappedMemory, &vdata, &dataSize); if (kr == kIOReturnSuccess) { if (*(UInt32 *)&vdata == kt_DldStopListeningToMessages) goto exit; printf( "\"%s\" %s %i(%s) ", vdata.Fsd.path, vtype_name(vdata.Fsd.v_type), (int)vdata.Fsd.pid, vdata.Fsd.p_comm ); if( DLD_KAUTH_SCOPE_VNODE_ID == vdata.Fsd.scopeID ) vnode_action_print(vdata.Fsd.action, (vdata.Fsd.v_type & VDIR)); else fileop_action_print(vdata.Fsd.action, (vdata.Fsd.v_type & VDIR)); } else { PRINT_ERROR(("*** error in receiving data (%d)\n", kr)); } }// end while }// end while exit: kr = IOConnectUnmapMemory( connection, kt_DldNotifyTypeLog, mach_task_self(), address ); if (kr != kIOReturnSuccess){ PRINT_ERROR(("failed to unmap memory (%d)\n", kr)); } mach_port_destroy(mach_task_self(), recvPort); return kr; }