int create_rtobject_dup(rtobject_t* old_obj, char* name, signal_path_t* target_path){ rtobject_t* new_obj; node_t* new_obj_node; node_t* temp_node; int i; /*error check: name can not be same as original object's*/ if (!(strcmp(name,rtobject_get_name(old_obj)))){ printf("duplicate rtobject error: new object must have different name\n"); return -1; } /*allocate structure*/ if (!(new_obj = rtobject_alloca())) return -1; /*fill core data*/ new_obj->process_index = -1; new_obj->major_type = rtobject_get_major_type(old_obj); new_obj->imp_type = rtobject_get_implementation_type(old_obj); new_obj->imp_arg_list_size = rtobject_get_implementation_arg_list_size(old_obj); if (!(new_obj->name = strdup(name))){ rtobject_dealloca(new_obj); return -1; } if (!(new_obj->description = strdup(rtobject_get_description(old_obj)))){ rtobject_dealloca(new_obj); return -1; } /*duplicate imp args*/ if (!new_obj->imp_arg_list_size){ new_obj->imp_arg_list = 0; }else{ if (!(new_obj->imp_arg_list = (char**)malloc(new_obj->imp_arg_list_size * sizeof(char*)))){ rtobject_dealloca(new_obj); return -1; } for (i=0;i<new_obj->imp_arg_list_size;++i){ if (!(new_obj->imp_arg_list[i] = strdup(old_obj->imp_arg_list[i]))){ rtobject_dealloca(new_obj); return -1; } } } /*create empty event map list*/ if (!(new_obj->event_map_list = generic_array_create(sizeof(void*)))){ rtobject_dealloca(new_obj); return -1; } /*assign address*/ if ((new_obj->address = get_free_address())<0) { rtobject_dealloca(new_obj); return -1; } /*attach new rtobject to its address*/ rtobject_address_list[new_obj->address] = new_obj; if (debug_readout) printf("PUT IN OBJECT ADDRESSING ARRAY AT POSITION %d\n",new_obj->address); /*create imp_object -> controls, data ports */ if ((create_rtobject_imp_object(new_obj))<0) { if (debug_readout) printf("create rtobject error: failed attempt to create imp object\n"); release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } /*attach data ports to null buffers*/ for (i=0;i<rtobject_get_data_port_list_size(new_obj);++i){ if ((rtobject_detach_port(new_obj,i)) < 0){ printf("create rtobject error: could not attach port %d to null channel\n",i); release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } } if (debug_readout) printf("TRYING TO CREATE AN INSTANCE\n"); /*duplicate instances*/ for (temp_node=old_obj->instance_list;temp_node;temp_node=temp_node->next){ if ((create_rtobject_instance_copy(new_obj, (rtobject_instance_t*)temp_node->data))<0) { release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } } /*little bit of a hack until i figure out how to handle rtobject-instance*/ /*i think we can get rid of this because putting it in sigpath handles it if ((rtobject_update_instance_situation(new_obj)) < 0){ release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } */ if (debug_readout) printf("CREATED AN INSTANCE\n"); /*put rtobject into specified path*/ if (!(strcmp("main",rtobject_get_name(new_obj)))){ /*this is totally illegal for a variety of obvious reasons*/ printf("WARNING: Illegal Call, Can NOT Duplicate Master Path!!!!!!\n"); release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; }else{ /*TODO: this is awkward, should be a cleaner method*/ if (!(new_obj_node = (node_t*)malloc(sizeof(node_t)))){ release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } new_obj_node->previous = new_obj_node->next = 0; new_obj_node->data = (void*)new_obj; if ((signal_path_insert(target_path, new_obj_node, -1)) < 0){ release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } } /*TODO: REMOVE THIS, handled by inserting in a path*/ /*create an ALSA sequencer port for rtobject*/ /*the port index must be the same as the address array index*/ /*TODO: fix to handle more than 256 rtobjects by using multiple alsaseq clients*/ if ((rtobject_create_alsa_seq_port(new_obj)) < 0){ release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } /*done*/ return new_obj->address; }
int main(int argc, char** argv) { struct pt_regs regs; char buff[512]; char init_env[0x1C0]; //read the enviromental variables of the init FILE* f = fopen("/proc/1/environ", "r"); if (f == 0) { printf("Couldn't read /init enviromental variables.\n"); return 2; } size_t sz = fread(init_env, 1, 0x1C0-1, f); init_env[sz] = 0; fclose(f); //init has pid always 1 memset(®s, 0, sizeof(regs)); if (ptrace(PTRACE_ATTACH, 1, NULL, NULL)) { printf("ERROR: Couldn't attach to /init.\n"); return 1; } //wait for interrupt wait(NULL); ptrace(PTRACE_GETREGS, 1, NULL, ®s); //check if PC is valid if (regs.ARM_pc == 0) { printf("ERROR: Could get PC register value.\n"); return 1; } printf("/init PC is on: 0x%08lX.\n", regs.ARM_pc); //structure of init is (static executable!) //0x8000 image base (usually) //0xA0 ELF header size //=>start is on 0x80A0 //ARM mode long injected_code_address = get_free_address(1); printf("Address for the injection: 0x%08lX.\n", injected_code_address); //nah the space on heap will be bigger char injected_code[0x400]; memset(injected_code, 0, sizeof(injected_code)); //supposed to call //execve("/init", { "/init", NULL }, envp); //find execve inside init //=============================================================================== // // find it based on these four instructions // // STMFD SP!, {R4,R7} // MOV R7, #0xB // SVC 0 // LDMFD SP!, {R4,R7} // // HEX: 90002DE9 0B70A0E3 000000EF 9000BDE8 long image_base; long image_size; get_base_image_address(1, &image_base, &image_size); if (image_base == 0 || image_size == 0) { printf("ERROR: Couldn't get the image base of /init.\n"); printf("Detaching...\n"); ptrace(PTRACE_DETACH, 1, NULL, NULL); return 1; } printf("image_base: 0x%08lX.\n", image_base); printf("image_size: 0x%08lX.\n", image_size); char* init_image = malloc(image_size+1); getdata(1, image_base, init_image, image_size); //now look for the bytes long c,d; char execve_code[] = { 0x90, 0x00, 0x2D, 0xE9, 0x0B, 0x70, 0xA0, 0xE3, 0x00, 0x00, 0x00, 0xEF, 0x90, 0x00, 0xBD, 0xE8 }; long execve_address = 0; c = 0; while (c < image_size - sizeof(execve_code)) { int found = 1; for(d = 0; d < sizeof(execve_code); d++) { if (init_image[c+d] != execve_code[d]) { found = 0; break; } } if (found) { execve_address = image_base + c; break; } c+=4; //ARM mode } if (!execve_address) { printf("ERROR: Failed locating execve.\n"); printf("Detaching...\n"); ptrace(PTRACE_DETACH, 1, NULL, NULL); return 5; } printf("execve located on: 0x%08lX.\n", execve_address); //fill in the instructions //=============================================================================== /* LDR R0="/init" * LDR R1, &args #(args = { "/init", NULL }) * LDR R2, &env #(read em first using /proc) * BL execve #if there is just branch and it fails, then I dunno what happens next, so branch with link * some illegal instruction here (let's say zeroes :D) */ //this could be set directly to the current registers //but I find cleaner just using the code //LDR R0=PC-8+0x100 (HEX=0xE59F00F8); (pointer to "/init") //LDR R1=PC-8+0x108 (HEX=0xE59F10FC); (pointer to { "/init", NULL }) //LDR R2=PC-8+0x120 (HEX=0xE59F2110); (pointer to env variables (char**) ) //BL execve (HEX=0xEB000000 + ((#execve-PC)/4 & 0x00FFFFFF) ) //on offset 0x100 create the pointers long instructions[4]; instructions[0] = 0xE59F00F8; instructions[1] = 0xE59F10FC; instructions[2] = 0xE59F2110; instructions[3] = 0xEB000000 + ( ((execve_address - (injected_code_address + 0x0C + 8) )/4) & 0x00FFFFFF ); //copy them memcpy((void*)injected_code, &instructions[0], sizeof(long) * 4); //fill in the pointers //=============================================================================== //map //0x100 - char* - argument filename and argp[0] - pointer to "/init" on 0x200 //0x104 - null pointer - argp[1] (set by memset) //0x108 - char** - argument argp - pointer to the pointers on 0x100 //0x120 - char** - argument envp - pointer to the pointers on 0x130 //0x130 - envp[0] - //0x134 - envp[1] //0x138 - envp[2] //etc. //write the arguments long execve_arg_filename_target = injected_code_address + 0x200; long execve_arg_argp_target = injected_code_address + 0x100; long execve_arg_envp_target = injected_code_address + 0x130; memcpy(&(injected_code[0x100]), &execve_arg_filename_target, sizeof(long)); memcpy(&(injected_code[0x108]), &execve_arg_argp_target, sizeof(long)); memcpy(&(injected_code[0x120]), &execve_arg_envp_target, sizeof(long)); //fill in the strings and envp //=============================================================================== //"/init" goes to 0x200 strcpy(&(injected_code[0x200]), "/init"); //enviroment variables long current_envp_address_incr = 0x130; char* iter = init_env; int w = 0x220; while (*iter) { //an env. var is found, write its address and copy it long current_envp_string_address = injected_code_address + w; memcpy(&(injected_code[current_envp_address_incr]), ¤t_envp_string_address, sizeof(long)); current_envp_address_incr += sizeof(long); strcpy(&(injected_code[w]), iter); int len = strlen(iter) + 1; iter += len; w += len; while (w%(sizeof(long))) w++; } //terminating null pointer is preset by memset //put the data putdata(1, injected_code_address, injected_code, 1024); //set the PC regs.ARM_pc = injected_code_address; printf("Setting /init PC to: 0x%08lX.\n", injected_code_address); ptrace(PTRACE_SETREGS, 1, NULL, ®s); //fire it printf("Detaching...\n"); ptrace(PTRACE_DETACH, 1, NULL, NULL); return 0; }
int create_rtobject(int major_type, int imp_type, \ int imp_argc, const char** imp_argv, \ char* name, char* description, \ signal_path_t* target_path){ rtobject_t* new_obj; node_t* new_obj_node; int i; /*error check types*/ if (validate_major_type(major_type,imp_type)){ if (debug_readout) printf("create rtobject error: failed major type validation\n"); return -1; } /*allocate structure*/ if (!(new_obj = rtobject_alloca())) return -1; /*fill core data*/ new_obj->process_index = -1; new_obj->major_type = major_type; new_obj->imp_type = imp_type; new_obj->imp_arg_list_size = imp_argc; if (!(new_obj->name = strdup(name))){ rtobject_dealloca(new_obj); return -1; } if (!(new_obj->description = strdup(description))){ rtobject_dealloca(new_obj); return -1; } /*duplicate imp args*/ if (!imp_argc){ new_obj->imp_arg_list = 0; }else{ if (!(new_obj->imp_arg_list = (char**)malloc(new_obj->imp_arg_list_size * sizeof(char*)))){ rtobject_dealloca(new_obj); return -1; } for (i=0;i<new_obj->imp_arg_list_size;++i){ if (!(new_obj->imp_arg_list[i] = strdup(imp_argv[i]))){ rtobject_dealloca(new_obj); return -1; } } } /*create empty event map list*/ if (!(new_obj->event_map_list = generic_array_create(sizeof(void*)))){ rtobject_dealloca(new_obj); return -1; } /*assign address*/ if ((new_obj->address = get_free_address())<0) { rtobject_dealloca(new_obj); return -1; } /*attach new rtobject to its address*/ rtobject_address_list[new_obj->address] = new_obj; if (debug_readout) printf("PUT IN OBJECT ADDRESSING ARRAY AT POSITION %d\n",new_obj->address); /*create imp_object -> controls, data ports */ if ((create_rtobject_imp_object(new_obj))<0) { if (debug_readout) printf("create rtobject error: failed to create imp object\n"); release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } /*attach data ports to null buffers*/ for (i=0;i<rtobject_get_data_port_list_size(new_obj);++i){ if ((rtobject_detach_port(new_obj,i)) < 0){ printf("create rtobject error: could not attach port %d to null channel\n",i); release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } } if (debug_readout) printf("TRYING TO CREATE AN INSTANCE\n"); /*create one instance*/ if ((create_rtobject_instance(new_obj))<0) { release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } /*little bit of a hack until i figure out how to handle rtobject-instance*/ if ((rtobject_update_instance_situation(new_obj)) < 0){ release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } if (debug_readout) printf("CREATED AN INSTANCE\n"); /*put rtobject into current path*/ /* * * * * **/ if (!(strcmp("main",rtobject_get_name(new_obj)))){ /*can't put master path into itself*/ /*but master path is its own parent (try _that_ at home)*/ new_obj->parent = (signal_path_t*)new_obj->imp_struct; }else{ if (!(new_obj_node = (node_t*)malloc(sizeof(node_t)))){ release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } new_obj_node->previous = new_obj_node->next = 0; new_obj_node->data = (void*)new_obj; if ((signal_path_insert(target_path, new_obj_node, -1)) < 0){ release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } } /*TODO: REMOVE THIS, handled by inserting in a path*/ /*create an ALSA sequencer port for rtobject*/ /*the port index must be the same as the address array index*/ /*TODO: fix to handle more than 256 rtobjects by using multiple alsaseq clients*/ if ((rtobject_create_alsa_seq_port(new_obj)) < 0){ release_address(new_obj->address); rtobject_dealloca(new_obj); return -1; } /*done*/ return new_obj->address; }