#include <mach/mach.h> // Where all the good things are. #include <mach/mach_port.h> #include <stdio.h> #include <bootstrap.h> #include <unistd.h> #include <stdlib.h> // because I can extern mach_port_t bootstrap_port; int main (int argc, char **argv){ if (argc < 2 ) { fprintf(stderr,"Usage: %s _name_\n", argv[0]); exit(1);} pid_t myVictim = 0; kern_return_t kr = KERN_SUCCESS; printf("I just woke up in this dark room and all I see is - the BSP: 0x%x\n", bootstrap_port); int rc = sscanf(argv[1], "%d" , &myVictim); if (rc == 1) { // myVictim holds a PID. } else { printf("I will now lookup %s\n", argv[1]); mach_port_t thePort; kr = bootstrap_look_up(bootstrap_port, // bootstrap_port_t argv[1], // service_name_t &thePort); // mach_port_t * if (KERN_SUCCESS == kr) { printf("Success!!! %s is at 0x%x\n", argv[1], thePort); } else printf("Nope\n"); } // end lookup // The ports reside within a mach_task_t which is ITSELF a port. // A task (i.e. process) can access its own port (namely, get // a send right to its representation in kernel) by calling // mach_task_self() printf ("I, myself, am : 0x%x\n", mach_task_self()); ipc_info_space_t space_info; ipc_info_name_array_t table_info; mach_msg_type_number_t table_info_cnt; ipc_info_tree_name_array_t tree_info; mach_msg_type_number_t tree_info_cnt; mach_port_t victim_task_port = mach_task_self(); if (myVictim) { if (getuid() != 0){ fprintf(stderr, "Go away, little man! TFP is for r00t only\n"); exit(1); } kr = task_for_pid (mach_task_self(), myVictim, &victim_task_port); } kr = mach_port_space_info ( victim_task_port, // ipc_space_t &space_info, // ipc_space_info_t &table_info, // ipc_info_name_array_t &table_info_cnt, // ... &tree_info, &tree_info_cnt); if (kr == KERN_SUCCESS) { int p = 0; for (p = 0; p < table_info_cnt; p++) { printf("Port 0x%x (obj 0x%x) is of type: 0x%x\n", table_info[p].iin_name, table_info[p].iin_object, table_info[p].iin_type); } } sleep(60); }