dl_fl_t *ptrace_find_dlinfo(int target_pid) { const char *linker_path = "/system/bin/linker"; ldl.l_dlopen = (long) get_remote_addr( target_pid, linker_path, (void *)dlopen ); ldl.l_dlsym = (long) get_remote_addr( target_pid, linker_path, (void *)dlsym ); ldl.l_dlclose = (long) get_remote_addr( target_pid, linker_path, (void *)dlclose ); LOGD( "[+] Get imports: dlopen: %x, dlsym: %x, dlclose: %x\n", ldl.l_dlopen, ldl.l_dlsym, ldl.l_dlclose ); return &ldl; }
static void _mpi_scalar_mput(const int target_rank, const _XMP_coarray_t *dst_desc, const void *src, const size_t dst_offset, const size_t src_offset, const int dst_dims, const _XMP_array_section_t *dst_info, const bool is_dst_on_acc) { int allelmt_dim = _XMP_get_dim_of_allelmts(dst_dims, dst_info); size_t element_size = dst_desc->elmt_size; size_t allelmt_size = (allelmt_dim == dst_dims)? element_size : dst_info[allelmt_dim].distance * dst_info[allelmt_dim].elmts; char *laddr = (allelmt_dim == dst_dims)? ((char*)src + src_offset) : _XMP_alloc(allelmt_size); char *raddr = get_remote_addr(dst_desc, target_rank, is_dst_on_acc) + dst_offset; MPI_Win win = get_window(dst_desc, is_dst_on_acc); XACC_DEBUG("scalar_mput(src_p=%p, size=%zd, target=%d, dst_p=%p, is_acc=%d)", laddr, element_size, target_rank, raddr, is_dst_on_acc); XACC_DEBUG("allelmt_dim=%d, dst_dims=%d", allelmt_dim, dst_dims); if(allelmt_dim != dst_dims){ //mcopy _XMP_array_section_t info; info.start = 0; info.length = allelmt_size/element_size; info.stride = 1; info.elmts = info.length; info.distance = element_size; _XMP_stride_memcpy_1dim(laddr, (char*)src+src_offset, &info, element_size, _XMP_SCALAR_MCOPY); XACC_DEBUG("mcopy(%lld, %lld, %lld), %lld",info.start, info.length, info.stride, info.elmts); } long long idxs[allelmt_dim+1]; for(int i = 0; i < allelmt_dim+1; i++) idxs[i]=0; while(1){ size_t offset = 0; for(int i = 0; i < allelmt_dim; i++){ offset += dst_info[i].distance * idxs[i+1] * dst_info[i].stride; } MPI_Put((void*)laddr, allelmt_size, MPI_BYTE, target_rank, (MPI_Aint)(raddr+offset), allelmt_size, MPI_BYTE, win); ++idxs[allelmt_dim]; for(int i = allelmt_dim-1; i >= 0; i--){ long long length = dst_info[i].length; if(idxs[i+1] >= length){ idxs[i+1] -= length; ++idxs[i]; }else{ break; } } if(idxs[0] > 0){ break; } } _wait_puts(target_rank, win); if(allelmt_dim != dst_dims){ _XMP_free(laddr); } }
APR_DECLARE(apr_status_t) apr_socket_addr_get(apr_sockaddr_t **sa, apr_interface_e which, apr_socket_t *sock) { if (which == APR_LOCAL) { if (sock->local_interface_unknown || sock->local_port_unknown) { apr_status_t rv = get_local_addr(sock); if (rv != APR_SUCCESS) { return rv; } } *sa = sock->local_addr; } else if (which == APR_REMOTE) { if (sock->remote_addr_unknown) { apr_status_t rv = get_remote_addr(sock); if (rv != APR_SUCCESS) { return rv; } } *sa = sock->remote_addr; } else { *sa = NULL; return APR_EINVAL; } return APR_SUCCESS; }
int return_error(bool transient, const char* message, ...) { va_list va; va_start(va, message); char buf[10240]; vsprintf(buf, message, va); va_end(va); fprintf(stdout, "Content-type: text/plain\n\n" "<data_server_reply>\n" " <status>%d</status>\n" " <message>%s</message>\n" "</data_server_reply>\n", transient?1:-1, buf ); log_messages.printf(MSG_NORMAL, "Returning error to client %s: %s (%s)\n", get_remote_addr(), buf, transient?"transient":"permanent" ); return 1; }
static void _mpi_contiguous(const int op, const int target_rank, const _XMP_coarray_t *remote_desc, const void *local, const size_t remote_offset, const size_t local_offset, const size_t transfer_size, const int is_remote_on_acc) { if(transfer_size == 0) return; char *laddr = (char*)local + local_offset; char *raddr = get_remote_addr(remote_desc, target_rank, is_remote_on_acc) + remote_offset; MPI_Win win = get_window(remote_desc, is_remote_on_acc); if(op == _XMP_N_COARRAY_PUT){ XACC_DEBUG("contiguous_put(local=%p, size=%zd, target=%d, remote=%p, is_acc=%d)", laddr, transfer_size, target_rank, raddr, is_remote_on_acc); MPI_Put((void*)laddr, transfer_size, MPI_BYTE, target_rank, (MPI_Aint)raddr, transfer_size, MPI_BYTE, win); _wait_puts(target_rank, win); }else if(op == _XMP_N_COARRAY_GET){ XACC_DEBUG("contiguous_get(local=%p, size=%zd, target=%d, remote=%p, is_acc=%d)", laddr, transfer_size, target_rank, raddr, is_remote_on_acc); MPI_Get((void*)laddr, transfer_size, MPI_BYTE, target_rank, (MPI_Aint)raddr, transfer_size, MPI_BYTE, win); _wait_gets(target_rank, win); }else{ _XMP_fatal("invalid coarray operation type"); } /* MPI_Request req[2]; size_t size_multiple128k = (transfer_size / (128*1024)) * (128*1024); size_t size_rest = transfer_size - size_multiple128k; if(transfer_size >= (128*1024) && size_rest > 0 && size_rest <= (8*1024)){ XACC_DEBUG("put(src_p=%p, size=%zd, target=%d, dst_p=%p, is_acc=%d) divied! (%d,%d)", laddr, transfer_size, target_rank, raddr, is_dst_on_acc, size128k, size_rest); MPI_Rput((void*)laddr, size_multiple128k, MPI_BYTE, target_rank, (MPI_Aint)raddr, size_multiple128k, MPI_BYTE, win,req); MPI_Rput((void*)(laddr+size_multiple128k), size_rest, MPI_BYTE, target_rank, (MPI_Aint)(raddr+size_multiple128k), size_rest, MPI_BYTE, win,req+1); MPI_Waitall(2, req, MPI_STATUSES_IGNORE); }else{ MPI_Rput((void*)laddr, transfer_size, MPI_BYTE, target_rank, (MPI_Aint)raddr, transfer_size, MPI_BYTE, win,req); MPI_Wait(req, MPI_STATUS_IGNORE); } */ }
static void log_incomplete_request() { // BOINC scheduler requests use method POST. // So method GET means that someone is trying a browser. // char *rm=getenv("REQUEST_METHOD"); bool used_get = false; if (rm && !strcmp(rm, "GET")) { used_get = true; } log_messages.printf(MSG_NORMAL, "Incomplete request received %sfrom IP %s, auth %s, platform %s, version %d.%d.%d\n", used_get?"(used GET method - probably a browser) ":"", get_remote_addr(), g_request->authenticator, g_request->platform.name, g_request->core_client_major_version, g_request->core_client_minor_version, g_request->core_client_release ); }
static void log_request() { log_messages.printf(MSG_NORMAL, "Request: [USER#%d] [HOST#%d] [IP %s] client %d.%d.%d\n", g_reply->user.id, g_reply->host.id, get_remote_addr(), g_request->core_client_major_version, g_request->core_client_minor_version, g_request->core_client_release ); if (config.debug_request_details) { log_messages.printf(MSG_DEBUG, "Request details: auth %s, RPC seqno %d, platform %s\n", g_request->authenticator, g_request->rpc_seqno, g_request->platform.name ); } log_messages.set_indent_level(2); }
void boinc_catch_signal(int signal_num) { char buffer[512]=""; if (this_filename[0]) { sprintf(buffer, "FILE=%s (%.0f bytes left) ", this_filename, bytes_left); } log_messages.printf(MSG_CRITICAL, "%sIP=%s caught signal %d [%s]\n", buffer, get_remote_addr(), signal_num, strsignal(signal_num) ); // there is no point in trying to return an error. // At this point Apache has broken the connection // so a write to stdout will just generate a SIGPIPE // // return_error(ERR_TRANSIENT, "while downloading %s server caught signal %d", this_filename, signal_num); _exit(1); }
static void _mpi_non_contiguous(const int op, const int target_rank, const _XMP_coarray_t *remote_desc, const void *local_ptr, const size_t remote_offset, const size_t local_offset, const int remote_dims, const int local_dims, const _XMP_array_section_t *remote_info, const _XMP_array_section_t *local_info, const size_t remote_elmts, const int is_remote_on_acc) { char *laddr = (char*)local_ptr + local_offset; char *raddr = get_remote_addr(remote_desc, target_rank, is_remote_on_acc) + remote_offset; MPI_Win win = get_window(remote_desc, is_remote_on_acc); MPI_Datatype local_types[_XMP_N_MAX_DIM], remote_types[_XMP_N_MAX_DIM]; size_t element_size = remote_desc->elmt_size; _mpi_make_types(local_types, local_dims, local_info, element_size); _mpi_make_types(remote_types, remote_dims, remote_info, element_size); // XACC_DEBUG("nonc_put(src_p=%p, target=%d, dst_p=%p, is_acc=%d)", laddr, src_cnt,src_bl,src_str, target_rank, raddr, is_dst_on_acc); if(op == _XMP_N_COARRAY_PUT){ MPI_Put((void*)laddr, 1, local_types[0], target_rank, (MPI_Aint)raddr, 1, remote_types[0], win); }else if (op == _XMP_N_COARRAY_GET){ MPI_Get((void*)laddr, 1, local_types[0], target_rank, (MPI_Aint)raddr, 1, remote_types[0], win); }else{ _XMP_fatal("invalid coarray operation type"); } //free datatype _mpi_free_types(local_types, local_dims ); _mpi_free_types(remote_types, remote_dims); if(op == _XMP_N_COARRAY_PUT){ _wait_puts(target_rank, win); }else if (op == _XMP_N_COARRAY_GET){ _wait_gets(target_rank, win); } }
static void _mpi_scalar_mget(const int target_rank, void *dst, const _XMP_coarray_t *src_desc, const size_t dst_offset, const size_t src_offset, const int dst_dims, const _XMP_array_section_t *dst_info, const bool is_src_on_acc) { char *laddr = (char*)dst + dst_offset; char *raddr = get_remote_addr(src_desc, target_rank, is_src_on_acc) + src_offset; MPI_Win win = get_window(src_desc, is_src_on_acc); size_t transfer_size = src_desc->elmt_size; XACC_DEBUG("scalar_mget(local_p=%p, size=%zd, target=%d, remote_p=%p, is_acc=%d)", laddr, transfer_size, target_rank, raddr, is_src_on_acc); MPI_Get((void*)laddr, transfer_size, MPI_BYTE, target_rank, (MPI_Aint)raddr, transfer_size, MPI_BYTE, win); //we have to wait completion of the get XACC_DEBUG("flush_local(%d) for [host|acc]", target_rank); MPI_Win_flush_local(target_rank, win); _unpack_scalar((char*)dst, dst_dims, laddr, dst_info); }
// ALWAYS generates an HTML reply // int handle_file_upload(FILE* in, R_RSA_PUBLIC_KEY& key) { char buf[256], path[512], temp[256]; FILE_INFO file_info; int retval; double nbytes=-1, offset=0; bool is_valid; while (fgets(buf, 256, in)) { #if 0 log_messages.printf(MSG_NORMAL, "got:%s\n", buf); #endif if (match_tag(buf, "<file_info>")) { retval = file_info.parse(in); if (retval) { return return_error(ERR_PERMANENT, "FILE_INFO::parse"); } #if 0 log_messages.printf(MSG_NORMAL, "file info:\n%s\n", file_info.signed_xml ); #endif if (!config.ignore_upload_certificates) { if (!file_info.signed_xml || !file_info.xml_signature) { log_messages.printf(MSG_CRITICAL, "file info is missing signature\n" ); return return_error(ERR_PERMANENT, "invalid signature"); } else { retval = verify_string( file_info.signed_xml, file_info.xml_signature, key, is_valid ); if (retval || !is_valid) { log_messages.printf(MSG_CRITICAL, "verify_string() [%s] [%s] retval %d, is_valid = %d\n", file_info.signed_xml, file_info.xml_signature, retval, is_valid ); log_messages.printf(MSG_NORMAL, "signed xml: %s", file_info.signed_xml ); log_messages.printf(MSG_NORMAL, "signature: %s", file_info.xml_signature ); return return_error(ERR_PERMANENT, "invalid signature"); } } } continue; } if (parse_double(buf, "<offset>", offset)) continue; if (parse_double(buf, "<nbytes>", nbytes)) continue; if (parse_str(buf, "<md5_cksum>", temp, sizeof(temp))) continue; if (match_tag(buf, "<data>")) { if (nbytes < 0) { return return_error(ERR_PERMANENT, "nbytes missing or negative"); } // enforce limits in signed XML // if (!config.ignore_upload_certificates) { if (nbytes > file_info.max_nbytes) { sprintf(buf, "file size (%d KB) exceeds limit (%d KB)", (int)(nbytes/1024), (int)(file_info.max_nbytes/1024) ); copy_socket_to_null(in); return return_error(ERR_PERMANENT, buf); } } // make sure filename is legit // if (strstr(file_info.name, "..")) { return return_error(ERR_PERMANENT, "file_upload_handler: .. found in filename: %s", file_info.name ); } if (strlen(file_info.name) == 0) { return return_error(ERR_PERMANENT, "file_upload_handler: no filename; nbytes %f", nbytes ); } retval = dir_hier_path( file_info.name, config.upload_dir, config.uldl_dir_fanout, path, true ); if (retval) { log_messages.printf(MSG_CRITICAL, "Failed to find/create directory for file '%s' in '%s'\n", file_info.name, config.upload_dir ); return return_error(ERR_TRANSIENT, "can't open file"); } log_messages.printf(MSG_NORMAL, "Starting upload of %s from %s [offset=%.0f, nbytes=%.0f]\n", file_info.name, get_remote_addr(), offset, nbytes ); #ifndef _USING_FCGI_ fflush(stderr); #endif if (offset >= nbytes) { log_messages.printf(MSG_CRITICAL, "ERROR: offset >= nbytes!!\n" ); return return_success(0); } retval = copy_socket_to_file(in, path, offset, nbytes); log_messages.printf(MSG_NORMAL, "Ended upload of %s from %s; retval %d\n", file_info.name, get_remote_addr(), retval ); #ifndef _USING_FCGI_ fflush(stderr); #endif return retval; } log_messages.printf(MSG_CRITICAL, "unrecognized: %s", buf ); } return return_error(ERR_PERMANENT, "Missing <data> tag"); }
// ALWAYS generates an HTML reply // int handle_file_upload(FILE* in, R_RSA_PUBLIC_KEY& key) { char buf[256], path[MAXPATHLEN], signed_xml[1024]; char name[256], stemp[256]; double max_nbytes=-1; char xml_signature[1024]; int retval; double offset=0, nbytes = -1; bool is_valid, btemp; strcpy(name, ""); strcpy(xml_signature, ""); bool found_data = false; while (fgets(buf, 256, in)) { #if 1 log_messages.printf(MSG_NORMAL, "got:%s\n", buf); #endif if (match_tag(buf, "<file_info>")) continue; if (match_tag(buf, "</file_info>")) continue; if (match_tag(buf, "<signed_xml>")) continue; if (match_tag(buf, "</signed_xml>")) continue; if (parse_bool(buf, "generated_locally", btemp)) continue; if (parse_bool(buf, "upload_when_present", btemp)) continue; if (parse_str(buf, "<url>", stemp, sizeof(stemp))) continue; if (parse_str(buf, "<md5_cksum>", stemp, sizeof(stemp))) continue; if (match_tag(buf, "<xml_signature>")) { copy_element_contents( in, "</xml_signature>", xml_signature, sizeof(xml_signature) ); continue; } if (parse_str(buf, "<name>", name, sizeof(name))) { strcpy(this_filename, name); continue; } if (parse_double(buf, "<max_nbytes>", max_nbytes)) continue; if (parse_double(buf, "<offset>", offset)) continue; if (parse_double(buf, "<nbytes>", nbytes)) continue; if (match_tag(buf, "<data>")) { found_data = true; break; } log_messages.printf(MSG_CRITICAL, "unrecognized: %s", buf); } if (strlen(name) == 0) { return return_error(ERR_PERMANENT, "Missing name"); } if (!found_data) { return return_error(ERR_PERMANENT, "Missing <data> tag"); } if (!config.ignore_upload_certificates) { if (strlen(xml_signature) == 0) { return return_error(ERR_PERMANENT, "missing signature"); } if (max_nbytes < 0) { return return_error(ERR_PERMANENT, "missing max_nbytes"); } sprintf(signed_xml, "<name>%s</name><max_nbytes>%.0f</max_nbytes>", name, max_nbytes ); retval = check_string_signature( signed_xml, xml_signature, key, is_valid ); if (retval || !is_valid) { log_messages.printf(MSG_CRITICAL, "check_string_signature() [%s] [%s] retval %d, is_valid = %d\n", signed_xml, xml_signature, retval, is_valid ); log_messages.printf(MSG_NORMAL, "signed xml: %s\n", signed_xml ); log_messages.printf(MSG_NORMAL, "signature: %s\n", xml_signature ); return return_error(ERR_PERMANENT, "invalid signature"); } } if (nbytes < 0) { return return_error(ERR_PERMANENT, "nbytes missing or negative"); } // enforce limits in signed XML // if (!config.ignore_upload_certificates) { if (nbytes > max_nbytes) { sprintf(buf, "file size (%d KB) exceeds limit (%d KB)", (int)(nbytes/1024), (int)(max_nbytes/1024) ); copy_socket_to_null(in); return return_error(ERR_PERMANENT, buf); } } // make sure filename is legit // if (strstr(name, "..")) { return return_error(ERR_PERMANENT, "file_upload_handler: .. found in filename: %s", name ); } if (strlen(name) == 0) { return return_error(ERR_PERMANENT, "file_upload_handler: no filename; nbytes %f", nbytes ); } retval = dir_hier_path( name, config.upload_dir, config.uldl_dir_fanout, path, true ); if (retval) { log_messages.printf(MSG_CRITICAL, "Failed to find/create directory for file '%s' in '%s'\n", name, config.upload_dir ); return return_error(ERR_TRANSIENT, "can't open file"); } log_messages.printf(MSG_NORMAL, "Starting upload of %s from %s [offset=%.0f, nbytes=%.0f]\n", name, get_remote_addr(), offset, nbytes ); #ifndef _USING_FCGI_ fflush(stderr); #endif if (offset >= nbytes) { log_messages.printf(MSG_CRITICAL, "ERROR: offset >= nbytes!!\n" ); return return_success(0); } retval = copy_socket_to_file(in, path, offset, nbytes); log_messages.printf(MSG_NORMAL, "Ended upload of %s from %s; retval %d\n", name, get_remote_addr(), retval ); #ifndef _USING_FCGI_ fflush(stderr); #endif return retval; }
/** \brief convert the object into a string */ std::string udp_itor_t::to_string() const throw() { if( is_null() ) return "null"; return get_local_addr().to_string() + " to " + get_remote_addr().to_string(); }
/* write the assembler code into target proc, * and invoke it to execute */ int writecode_to_targetproc( pid_t target_pid, // target process pid const char *library_path, // the path of .so that will be // upload to target process const char *function_name, // .so init fucntion e.g. hook_init void *param, // the parameters of init function size_t param_size ) // number of parameters { int ret = -1; void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr; void *local_handle, *remote_handle, *dlhandle; uint8_t *map_base; uint8_t *dlopen_param1_ptr, *dlsym_param2_ptr, *saved_r0_pc_ptr, *inject_param_ptr, *remote_code_ptr, *local_code_ptr; struct pt_regs regs, original_regs; // extern global variable in the assembler code extern uint32_t _dlopen_addr_s, _dlopen_param1_s, _dlopen_param2_s, \ _dlsym_addr_s, _dlsym_param2_s, _dlclose_addr_s, \ _inject_start_s, _inject_end_s, _inject_function_param_s, \ _saved_cpsr_s, _saved_r0_pc_s; uint32_t code_length; long parameters[10]; // make target_pid as its child process and stop if ( ptrace_attach( target_pid ) == -1 ) return -1; // get the values of 18 registers from target_pid if ( ptrace_getregs( target_pid, ®s ) == -1 ) goto exit; // save original registers memcpy( &original_regs, @regs, sizeof(regs) ); // get mmap address from target_pid // the mmap is the address of mmap in the cur process mmap_addr = get_remote_addr( target_pid, "/system/lib/libc.so", (void *)mmap ); // set mmap parameters parameters[0] = 0; // addr parameters[1] = 0x4000; // size parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; // prot parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; // flags parameters[4] = 0; //fd parameters[5] = 0; //offset // execute the mmap in target_pid if ( ptrace_call( target_pid, (uint32_t)mmap_addr, parameters, 6, ®s) == -1 ) goto exit; // get the return values of mmap <in r0> if ( ptrace_getregs( target_pid, ®s) == -1 ) goto exit; // get the start address for assembler code map_base = (uint8_t *)regs.ARM_r0; // get the address of dlopen, dlsym and dlclose in target process dlopen_addr = get_remote_addr( target_pid, "/system/bin/linker", (void *)dlopen ); dlsym_addr = get_remote_addr( target_pid, "/system/bin/linker", (void *)dlsym ); dlclose_addr = get_remote_addr( target_pid, "/system/bin/linker", (void *)dlclose ); // set the start address for assembler code in target process remote_code_ptr = map_base + 0x3C00; // set the start address for assembler code in cur process local_code_ptr = (uint8_t *)&_inject_start_s; // set global variable of assembler code // and these address is in the target process _dlopen_addr_s = (uint32_t)dlopen_addr; _dlsym_addr_s = (uint32_t)dlsym_addr; _dlclose_addr_s = (uint32_t)dlclose_addr; code_length = (uint32_t)&_inject_end_s - (uint32_t)&_inject_start_s; dlopen_param1_ptr = local_code_ptr + code_length + 0x20; dlsym_param2_ptr = dlopen_param1_ptr + MAX_PATH; saved_r0_pc_ptr = dlsym_param2_ptr + MAX_PATH; inject_param_ptr = saved_r0_pc_ptr + MAX_PATH; // save library path to assembler code global variable strcpy( dlopen_param1_ptr, library_path ); _dlopen_param1_s = REMOTE_ADDR( dlopen_param1_ptr, local_code_ptr, remote_code_ptr ); // save function name to assembler code global variable strcpy( dlsym_param2_ptr, function_name ); _dlsym_param2_s = REMOTE_ADDR( dlsym_param2_ptr, local_code_ptr, remote_code_ptr ); // save cpsr to assembler code global variable _saved_cpsr_s = original_regs.ARM_cpsr; // save r0-r15 to assembler code global variable memcpy( saved_r0_pc_ptr, &(original_regs.ARM_r0), 16 * 4 ); // r0 ~ r15 _saved_r0_pc_s = REMOTE_ADDR( saved_r0_pc_ptr, local_code_ptr, remote_code_ptr ); // save function parameters to assembler code global variable memcpy( inject_param_ptr, param, param_size ); _inject_function_param_s = REMOTE_ADDR( inject_param_ptr, local_code_ptr, remote_code_ptr ); // write the assembler code into target process // now the values of global variable is in the target process space ptrace_writedata( target_pid, remote_code_ptr, local_code_ptr, 0x400 ); memcpy( ®s, &original_regs, sizeof(regs) ); // set sp and pc to the start address of assembler code regs.ARM_sp = (long)remote_code_ptr; regs.ARM_pc = (long)remote_code_ptr; // set registers for target process ptrace_setregs( target_pid, ®s ); // make the target_pid is not a child process of cur process // and make target_pid continue to running ptrace_detach( target_pid ); // now finish it successfully ret = 0; exit: return ret; }
int inject_remote_process_new(pid_t target_pid, const char *library_path, const char *function_name, const char *param, size_t param_size) { int ret = -1; void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr, *dlerror_addr; void *local_handle, *remote_handle, *dlhandle; uint8_t *map_base = 0; uint8_t *dlopen_param1_ptr, *dlsym_param2_ptr, *saved_r0_pc_ptr, *inject_param_ptr, *remote_code_ptr, *local_code_ptr; struct pt_regs regs, original_regs; extern uint32_t _dlopen_addr_s, _dlopen_param1_s, _dlopen_param2_s, _dlsym_addr_s, \ _dlsym_param2_s, _dlclose_addr_s, _inject_start_s, _inject_end_s, _inject_function_param_s, \ _saved_cpsr_s, _saved_r0_pc_s; uint32_t code_length; long parameters[10]; DEBUG_PRINT("[+] Injecting process: %d\n", target_pid); if (ptrace_attach(target_pid) == -1) goto exit; if (ptrace_getregs(target_pid, ®s) == -1) goto exit; /* save original registers */ memcpy(&original_regs, ®s, sizeof(regs)); mmap_addr = get_remote_addr(target_pid, libc_path, (void *)mmap); DEBUG_PRINT("[+] Remote mmap address: %x\n", mmap_addr); /* call mmap */ parameters[0] = 0; // addr parameters[1] = 0x4000; // size parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; // prot parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; // flags parameters[4] = 0; //fd parameters[5] = 0; //offset if (ptrace_call_wrapper(target_pid, "mmap", mmap_addr, parameters, 6, ®s) == -1) goto exit; map_base = ptrace_retval(®s); dlopen_addr = get_remote_addr( target_pid, linker_path, (void *)dlopen ); dlsym_addr = get_remote_addr( target_pid, linker_path, (void *)dlsym ); dlclose_addr = get_remote_addr( target_pid, linker_path, (void *)dlclose ); dlerror_addr = get_remote_addr( target_pid, linker_path, (void *)dlerror ); DEBUG_PRINT("[+] Get imports: dlopen: %x, dlsym: %x, dlclose: %x, dlerror: %x\n", dlopen_addr, dlsym_addr, dlclose_addr, dlerror_addr); printf("library path = %s\n", library_path); ptrace_writedata(target_pid, map_base, library_path, strlen(library_path) + 1); parameters[0] = map_base; parameters[1] = RTLD_NOW| RTLD_GLOBAL; if (ptrace_call_wrapper(target_pid, "dlopen", dlopen_addr, parameters, 2, ®s) == -1) goto exit; void * sohandle = ptrace_retval(®s); #define FUNCTION_NAME_ADDR_OFFSET 0x100 ptrace_writedata(target_pid, map_base + FUNCTION_NAME_ADDR_OFFSET, function_name, strlen(function_name) + 1); parameters[0] = sohandle; parameters[1] = map_base + FUNCTION_NAME_ADDR_OFFSET; if (ptrace_call_wrapper(target_pid, "dlsym", dlsym_addr, parameters, 2, ®s) == -1) goto exit; void * hook_entry_addr = ptrace_retval(®s); DEBUG_PRINT("hook_entry_addr = %p\n", hook_entry_addr); #define FUNCTION_PARAM_ADDR_OFFSET 0x200 ptrace_writedata(target_pid, map_base + FUNCTION_PARAM_ADDR_OFFSET, param, strlen(param) + 1); parameters[0] = map_base + FUNCTION_PARAM_ADDR_OFFSET; if (ptrace_call_wrapper(target_pid, "hook_entry", hook_entry_addr, parameters, 1, ®s) == -1) goto exit; printf("Press enter to dlclose and detach\n"); getchar(); parameters[0] = sohandle; if (ptrace_call_wrapper(target_pid, "dlclose", dlclose, parameters, 1, ®s) == -1) goto exit; /* restore */ ptrace_setregs(target_pid, &original_regs); ptrace_detach(target_pid); ret = 0; exit: return ret; }
int main(int argc, char** argv) { #ifndef _USING_FCGI_ FILE* fin, *fout; #else FCGI_FILE *fin, *fout; #endif int i, retval; char req_path[MAXPATHLEN], reply_path[MAXPATHLEN]; char log_path[MAXPATHLEN], path[MAXPATHLEN]; unsigned int counter=0; char* code_sign_key; int length = -1; log_messages.pid = getpid(); bool debug_log = false; for (i=1; i<argc; i++) { if (!strcmp(argv[i], "--batch")) { batch = true; continue; } else if (!strcmp(argv[i], "--mark_jobs_done")) { mark_jobs_done = true; } else if (!strcmp(argv[i], "--debug_log")) { debug_log = true; #ifdef GCL_SIMULATOR } else if (!strcmp(argv[i], "--simulator")) { if(!argv[++i]) { log_messages.printf(MSG_CRITICAL, "%s requires an argument\n\n", argv[--i]); usage(argv[0]); exit(1); } simtime = atof(argv[i]); #endif } else if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { usage(argv[0]); exit(0); } else if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) { printf("%s\n", SVN_VERSION); exit(0); } else if (strlen(argv[i])){ log_messages.printf(MSG_CRITICAL, "unknown command line argument: %s\n\n", argv[i]); usage(argv[0]); exit(1); } } // install a signal handler that catches SIGTERMS sent by Apache if the CGI // times out. // signal(SIGTERM, sigterm_handler); if (debug_log) { if (!freopen("debug_log", "w", stderr)) { fprintf(stderr, "Can't redirect stderr\n"); exit(1); } } else { char *stderr_buffer; get_log_path(path, "scheduler.log"); #ifndef _USING_FCGI_ char buf[256]; if (!freopen(path, "a", stderr)) { fprintf(stderr, "Can't redirect stderr\n"); sprintf(buf, "Server can't open log file (%s)", path); send_message(buf, 3600); exit(1); } #else FCGI_FILE* f = FCGI::fopen(path, "a"); if (f) { log_messages.redirect(f); } else { char buf[256]; fprintf(stderr, "Can't redirect FCGI log messages\n"); sprintf(buf, "Server can't open log file for FCGI (%s)", path); send_message(buf, 3600); exit(1); } #endif // install a larger buffer for stderr. This ensures that // log information from different scheduler requests running // in parallel aren't intermingled in the log file. // if (config.scheduler_log_buffer) { stderr_buffer = (char*)malloc(config.scheduler_log_buffer); if (!stderr_buffer) { log_messages.printf(MSG_CRITICAL, "Unable to allocate stderr buffer\n" ); } else { #ifdef _USING_FCGI_ retval = setvbuf( f->stdio_stream, stderr_buffer, _IOFBF, config.scheduler_log_buffer ); #else retval = setvbuf( stderr, stderr_buffer, _IOFBF, config.scheduler_log_buffer ); #endif if (retval) { log_messages.printf(MSG_CRITICAL, "Unable to change stderr buffering\n" ); } } } } srand(time(0)+getpid()); log_messages.set_debug_level(DEBUG_LEVEL); #if DUMP_CORE_ON_SEGV set_core_dump_size_limit(); #endif retval = config.parse_file(); if (retval) { log_messages.printf(MSG_CRITICAL, "Can't parse config.xml: %s\n", boincerror(retval) ); send_message("Server can't parse configuration file", 3600); exit(0); } log_messages.set_debug_level(config.sched_debug_level); if (config.sched_debug_level == 4) g_print_queries = true; gui_urls.init(); project_files.init(); init_file_delete_regex(); sprintf(path, "%s/code_sign_public", config.key_dir); retval = read_file_malloc(path, code_sign_key); if (retval) { log_messages.printf(MSG_CRITICAL, "Can't read code sign key file (%s)\n", path ); send_message("Server can't find key file", 3600); exit(0); } strip_whitespace(code_sign_key); g_pid = getpid(); #ifdef _USING_FCGI_ //while(FCGI_Accept() >= 0 && counter < MAX_FCGI_COUNT) { while(FCGI_Accept() >= 0) { counter++; log_messages.set_indent_level(0); #endif if (config.debug_request_headers) { log_request_headers(length); } if (!debug_log && check_stop_sched()) { send_message("Project is temporarily shut down for maintenance", 3600); goto done; } if (!ssp) { attach_to_feeder_shmem(); } if (!ssp) { send_message("Server error: can't attach shared memory", 3600); goto done; } if (strlen(config.debug_req_reply_dir)) { struct stat statbuf; // the code below is convoluted because, // instead of going from stdin to stdout directly, // we go via a pair of disk files // (this makes it easy to save the input, // and to know the length of the output). // NOTE: to use this, you must create group-writeable dirs // boinc_req and boinc_reply in the project dir // sprintf(req_path, "%s/%d_%u_sched_request.xml", config.debug_req_reply_dir, g_pid, counter); sprintf(reply_path, "%s/%d_%u_sched_reply.xml", config.debug_req_reply_dir, g_pid, counter); // keep an own 'log' per PID in case general logging fails // this allows to associate at leas the scheduler request with the client // IP address (as shown in httpd error log) in case of a crash sprintf(log_path, "%s/%d_%u_sched.log", config.debug_req_reply_dir, g_pid, counter); #ifndef _USING_FCGI_ fout = fopen(log_path, "a"); #else fout = FCGI::fopen(log_path,"a"); #endif fprintf(fout, "PID: %d Client IP: %s\n", g_pid, get_remote_addr()); fclose(fout); log_messages.printf(MSG_DEBUG, "keeping sched_request in %s, sched_reply in %s, custom log in %s\n", req_path, reply_path, log_path ); #ifndef _USING_FCGI_ fout = fopen(req_path, "w"); #else fout = FCGI::fopen(req_path,"w"); #endif if (!fout) { log_messages.printf(MSG_CRITICAL, "can't write request file\n" ); exit(1); } copy_stream(stdin, fout); fclose(fout); stat(req_path, &statbuf); if (length>=0 && (statbuf.st_size != length)) { log_messages.printf(MSG_CRITICAL, "Request length %d != CONTENT_LENGTH %d\n", (int)statbuf.st_size, length ); } #ifndef _USING_FCGI_ fin = fopen(req_path, "r"); #else fin = FCGI::fopen(req_path,"r"); #endif if (!fin) { log_messages.printf(MSG_CRITICAL, "can't read request file\n" ); exit(1); } #ifndef _USING_FCGI_ fout = fopen(reply_path, "w"); #else fout = FCGI::fopen(reply_path, "w"); #endif if (!fout) { log_messages.printf(MSG_CRITICAL, "can't write reply file\n" ); exit(1); } handle_request(fin, fout, code_sign_key); fclose(fin); fclose(fout); #ifndef _USING_FCGI_ fin = fopen(reply_path, "r"); #else fin = FCGI::fopen(reply_path, "r"); #endif if (!fin) { log_messages.printf(MSG_CRITICAL, "can't read reply file\n" ); exit(1); } copy_stream(fin, stdout); fclose(fin); // if not contacted from a client, don't keep the log files /* not sure what lead to the assumption of a client setting CONTENT_LENGTH, but it's wrong at least on our current project / Apache / Client configuration. Commented out. if (getenv("CONTENT_LENGTH")) { unlink(req_path); unlink(reply_path); } */ #ifndef _USING_FCGI_ } else if (batch) { while (!feof(stdin)) { handle_request(stdin, stdout, code_sign_key); fflush(stdout); } #endif } else { handle_request(stdin, stdout, code_sign_key); fflush(stderr); } done: #ifdef _USING_FCGI_ if (config.debug_fcgi) { log_messages.printf(MSG_NORMAL, "FCGI: counter: %d\n", counter ); log_messages.flush(); } } // do() if (counter == MAX_FCGI_COUNT) { fprintf(stderr, "FCGI: counter passed MAX_FCGI_COUNT - exiting..\n"); } else { fprintf(stderr, "FCGI: FCGI_Accept failed - exiting..\n"); } // when exiting, write headers back to apache so it won't complain // about "incomplete headers" fprintf(stdout,"Content-type: text/plain\n\n"); #endif if (db_opened) { boinc_db.close(); } }
/** * inject shared library to target process */ int inject_remote_process( pid_t target_pid, const char *library_path, const char *function_name, void *param, size_t param_size ) { int ret = -1; void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr; void *local_handle, *remote_handle, *dlhandle; uint8_t *map_base; uint8_t *dlopen_param1_ptr, *dlsym_param2_ptr, *saved_r0_pc_ptr, *inject_param_ptr, *remote_code_ptr, *local_code_ptr; struct pt_regs regs, original_regs; // declared in shellcode.s extern uint32_t _dlopen_addr_s, _dlopen_param1_s, _dlopen_param2_s, _dlsym_addr_s, \ _dlsym_param2_s, _dlclose_addr_s, _inject_start_s, _inject_end_s, _inject_function_param_s, \ _saved_cpsr_s, _saved_r0_pc_s, _hook_entry_addr_s; uint32_t code_length; long parameters[10]; DEBUG_PRINT( "[+] Injecting process: %d\n", target_pid ); if ( ptrace_attach( target_pid ) == -1 ) return EXIT_SUCCESS; if ( ptrace_getregs( target_pid, ®s ) == -1 ) goto exit; /* save original registers */ memcpy( &original_regs, ®s, sizeof(regs) ); mmap_addr = get_remote_addr( target_pid, "/system/lib/libc.so", (void *)mmap ); DEBUG_PRINT( "[+] Remote mmap address: %x\n", mmap_addr ); /* call mmap */ parameters[0] = 0; // addr parameters[1] = 0x4000; // size parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; // prot parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; // flags parameters[4] = 0; //fd parameters[5] = 0; //offset DEBUG_PRINT( "[+] Calling mmap in target process.\n" ); if ( ptrace_call( target_pid, (uint32_t)mmap_addr, parameters, 6, ®s ) == -1 ) goto exit; if ( ptrace_getregs( target_pid, ®s ) == -1 ) goto exit; DEBUG_PRINT( "[+] Target process returned from mmap, return value=%x, pc=%x \n", regs.ARM_r0, regs.ARM_pc ); map_base = (uint8_t *)regs.ARM_r0; // get address of dlopen(), dlsym() and dlclose() in target process dlopen_addr = get_remote_addr( target_pid, linker_path, (void *)dlopen ); dlsym_addr = get_remote_addr( target_pid, linker_path, (void *)dlsym ); dlclose_addr = get_remote_addr( target_pid, linker_path, (void *)dlclose ); DEBUG_PRINT( "[+] Get imports: dlopen: %x, dlsym: %x, dlclose: %x\n", dlopen_addr, dlsym_addr, dlclose_addr ); remote_code_ptr = map_base + 0x3C00; local_code_ptr = (uint8_t *)&_inject_start_s; _dlopen_addr_s = (uint32_t)dlopen_addr; _dlsym_addr_s = (uint32_t)dlsym_addr; _dlclose_addr_s = (uint32_t)dlclose_addr; DEBUG_PRINT( "[+] Inject code start: %x, end: %x\n", local_code_ptr, &_inject_end_s ); code_length = (uint32_t)&_inject_end_s - (uint32_t)&_inject_start_s; dlopen_param1_ptr = local_code_ptr + code_length + 0x20; // 0x20 == 32 dlsym_param2_ptr = dlopen_param1_ptr + MAX_PATH; saved_r0_pc_ptr = dlsym_param2_ptr + MAX_PATH; inject_param_ptr = saved_r0_pc_ptr + MAX_PATH; /* dlopen parameter 1: library name */ strcpy( dlopen_param1_ptr, library_path ); _dlopen_param1_s = REMOTE_ADDR( dlopen_param1_ptr, local_code_ptr, remote_code_ptr ); DEBUG_PRINT( "[+] _dlopen_param1_s: %x\n", _dlopen_param1_s ); /* dlsym parameter 2: function name */ strcpy( dlsym_param2_ptr, function_name ); _dlsym_param2_s = REMOTE_ADDR( dlsym_param2_ptr, local_code_ptr, remote_code_ptr ); DEBUG_PRINT( "[+] _dlsym_param2_s: %x\n", _dlsym_param2_s ); /* saved cpsr */ _saved_cpsr_s = original_regs.ARM_cpsr; /* saved r0-pc */ memcpy( saved_r0_pc_ptr, &(original_regs.ARM_r0), 16 * 4 ); // r0 ~ r15 _saved_r0_pc_s = REMOTE_ADDR( saved_r0_pc_ptr, local_code_ptr, remote_code_ptr ); DEBUG_PRINT( "[+] _saved_r0_pc_s: %x\n", _saved_r0_pc_s ); /* Inject function parameter */ memcpy( inject_param_ptr, param, param_size ); _inject_function_param_s = REMOTE_ADDR( inject_param_ptr, local_code_ptr, remote_code_ptr ); DEBUG_PRINT( "[+] _inject_function_param_s: %x\n", _inject_function_param_s ); DEBUG_PRINT( "[+] Remote shellcode address: %x\n", remote_code_ptr ); ptrace_writedata( target_pid, remote_code_ptr, local_code_ptr, 0x400 ); memcpy( ®s, &original_regs, sizeof(regs) ); regs.ARM_sp = (long)remote_code_ptr; // change pc to execute instructions at remote_code_ptr regs.ARM_pc = (long)remote_code_ptr; DEBUG_PRINT( "[+] hook_entry address: %x\n", _hook_entry_addr_s); ptrace_setregs( target_pid, ®s ); ptrace_detach( target_pid ); // inject succeeded ret = 0; exit: return ret; }
char *_XMP_mpi_coarray_get_remote_addr(const _XMP_coarray_t *desc, const int target_rank, const bool is_acc) { return get_remote_addr(desc, target_rank, is_acc); }
void injectSo(pid_t pid,char* so_path, char* function_name,char* parameter) { struct pt_regs old_regs,regs; long mmap_addr, dlopen_addr, dlsym_addr, dlclose_addr; //save old regs ptrace(PTRACE_GETREGS, pid, NULL, &old_regs); memcpy(®s, &old_regs, sizeof(regs)); //get remote addres printf("getting remote addres:\n"); mmap_addr = get_remote_addr(pid, libc_path, (void *)mmap); dlopen_addr = get_remote_addr( pid, libc_path, (void *)dlopen ); dlsym_addr = get_remote_addr( pid, libc_path, (void *)dlsym ); dlclose_addr = get_remote_addr( pid, libc_path, (void *)dlclose ); printf("mmap_addr=%p dlopen_addr=%p dlsym_addr=%p dlclose_addr=%p\n", (void*)mmap_addr,(void*)dlopen_addr,(void*)dlsym_addr,(void*)dlclose_addr); long parameters[10]; //mmap parameters[0] = 0; //address parameters[1] = 0x4000; //size parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; //WRX parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; //flag parameters[4] = 0; //fd parameters[5] = 0; //offset ptrace_call(pid, mmap_addr, parameters, 6, ®s); ptrace(PTRACE_GETREGS, pid, NULL, ®s); long map_base = regs.ARM_r0; printf("map_base = %p\n", (void*)map_base); //dlopen printf("save so_path = %s to map_base = %p\n", so_path, (void*)map_base); putdata(pid, map_base, so_path, strlen(so_path) + 1); parameters[0] = map_base; parameters[1] = RTLD_NOW| RTLD_GLOBAL; ptrace_call(pid, dlopen_addr, parameters, 2, ®s); ptrace(PTRACE_GETREGS, pid, NULL, ®s); long handle = regs.ARM_r0; printf("handle = %p\n",(void*) handle); //dlsym printf("save function_name = %s to map_base = %p\n", function_name, (void*)map_base); putdata(pid, map_base, function_name, strlen(function_name) + 1); parameters[0] = handle; parameters[1] = map_base; ptrace_call(pid, dlsym_addr, parameters, 2, ®s); ptrace(PTRACE_GETREGS, pid, NULL, ®s); long function_ptr = regs.ARM_r0; printf("function_ptr = %p\n", (void*)function_ptr); //function_call printf("save parameter = %s to map_base = %p\n", parameter, (void*)map_base); putdata(pid, map_base, parameter, strlen(parameter) + 1); parameters[0] = map_base; ptrace_call(pid, function_ptr, parameters, 1, ®s); //dlcose parameters[0] = handle; ptrace_call(pid, dlclose_addr, parameters, 1, ®s); //restore old regs ptrace(PTRACE_SETREGS, pid, NULL, &old_regs); }
/* 实现核心功能--注入 */ int inject_remote_process(pid_t target_pid, const char *library_path, const char *function_name, const char *param, size_t param_size) { int ret = -1; // 存放目标进程地址 void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr, *dlerror_addr; void *local_handle, *remote_handle, *dlhandle; uint8_t *map_base = 0; // 存放目标进程mmap获取的内存块地址,mmap将一个文件或者其它对象映射进内存 uint8_t *dlopen_param1_ptr, *dlsym_param2_ptr, *saved_r0_pc_ptr, *inject_param_ptr, *remote_code_ptr, *local_code_ptr; struct pt_regs regs, original_regs; extern uint32_t _dlopen_addr_s, _dlopen_param1_s, _dlopen_param2_s, _dlsym_addr_s, \ _dlsym_param2_s, _dlclose_addr_s, _inject_start_s, _inject_end_s, _inject_function_param_s, \ _saved_cpsr_s, _saved_r0_pc_s; uint32_t code_length; long parameters[10]; DEBUG_PRINT("[+] Injecting process: %d\n", target_pid); // step 1. attach到目标进程 if (ptrace_attach(target_pid) == -1) goto exit; // step 2. save context, 保存目标进程被注入前的寄存器内容 // 方便注入完成后恢复 if (ptrace_getregs(target_pid, ®s) == -1) goto exit; /* save original registers */ memcpy(&original_regs, ®s, sizeof(regs)); /* step 3. 获取目标进程存放mmap()代码的地址,执行mmap调用, * 在目标进程分配一块地址,用于存放后面要注入的库路径和相关函数地址等 * mmap()会开辟一块内存,用于将一个文件或者其它对象映射进内存 */ // 寻找目标进程mmap的地址 // libc为c语音标准库,一般进程都会加载;libc.so包含mmap函数 mmap_addr = get_remote_addr(target_pid, libc_path, (void *)mmap); DEBUG_PRINT("[+] Remote mmap address: %x\n", mmap_addr); parameters[0] = 0; // addr parameters[1] = 0x4000; // size parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; // prot parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; // flags parameters[4] = 0; //fd parameters[5] = 0; //offset // 目标进程执行mmap if (ptrace_call_wrapper(target_pid, "mmap", mmap_addr, parameters, 6, ®s) == -1) goto exit; map_base = ptrace_retval(®s);// mmap调用后返回值存入regs内的ax寄存器,syscall之前ax存调用号,调用后存返回值 // step 4. 获取目标进程动态库的几个函数,并将要注入的so的路径写入刚刚申请的内存初始地址 // dlopen()函数以指定模式打开指定的动态链接库文件,并返回一个句柄给dlsym()的调用进程。使用dlclose()来卸载打开的库。 dlopen_addr = get_remote_addr(target_pid, linker_path, (void *)dlopen); // 找到dlopen()的地址 dlsym_addr = get_remote_addr(target_pid, linker_path, (void *)dlsym); // 找到dlsys()地址 dlclose_addr = get_remote_addr(target_pid, linker_path, (void *)dlclose); // 找到dlclose()地址 dlerror_addr = get_remote_addr(target_pid, linker_path, (void *)dlerror); // 找到dlerror()地址 DEBUG_PRINT("[+] Get imports: dlopen: %x, dlsym: %x, dlclose: %x, dlerror: %x\n", dlopen_addr, dlsym_addr, dlclose_addr, dlerror_addr); printf("library path = %s\n", library_path); // 将要注入的so的路径写入刚刚申请的内存初始地址,作为即将要调用的dlopen函数的参数parameters[0] ptrace_writedata(target_pid, map_base, library_path, strlen(library_path) + 1); // step 5. 在目标进程内调用dlopen函数加载要注入的so // 完成后so已经被注入目标进程的地址空间内了 // 当库被装入后,可以把 dlopen() 返回的句柄作为给 dlsym() 的第一个参数,以获得符号在库中的地址。 // 使用这个地址,就可以获得库中特定函数的指针,并且调用装载库中的相应函数。 parameters[0] = map_base; parameters[1] = RTLD_NOW| RTLD_GLOBAL; if (ptrace_call_wrapper(target_pid, "dlopen", dlopen_addr, parameters, 2, ®s) == -1) goto exit; // step 6. 在目标进程内调用dlsym函数获取刚刚注入的so里的hook函数 void * sohandle = ptrace_retval(®s); #define FUNCTION_NAME_ADDR_OFFSET 0x100 ptrace_writedata(target_pid, map_base + FUNCTION_NAME_ADDR_OFFSET, function_name, strlen(function_name) + 1); parameters[0] = sohandle; parameters[1] = map_base + FUNCTION_NAME_ADDR_OFFSET; if (ptrace_call_wrapper(target_pid, "dlsym", dlsym_addr, parameters, 2, ®s) == -1) goto exit; // step 7. 在目标进程内调用hook函数 void * hook_entry_addr = ptrace_retval(®s); // dlsys()返回hook函数地址 DEBUG_PRINT("hook_entry_addr = %p\n", hook_entry_addr); #define FUNCTION_PARAM_ADDR_OFFSET 0x200 ptrace_writedata(target_pid, map_base + FUNCTION_PARAM_ADDR_OFFSET, param, strlen(param) + 1); parameters[0] = map_base + FUNCTION_PARAM_ADDR_OFFSET; function_name if (ptrace_call_wrapper(target_pid, "hook_entry", hook_entry_addr, parameters, 1, ®s) == -1) goto exit; printf("Press enter to dlclose and detach\n"); getchar(); parameters[0] = sohandle; if (ptrace_call_wrapper(target_pid, "dlclose", dlclose, parameters, 1, ®s) == -1) goto exit; /* restore */ // step 8. 恢复目标进程的寄存器,detach ptrace ptrace_setregs(target_pid, &original_regs); ptrace_detach(target_pid); ret = 0; exit: return ret; }
int inject_remote_process(pid_t target_pid, const char *library_path, const char *function_name, const char *param, size_t param_size){ /* [1]通过远程进程pid,ATTACH到远程进程。 [2]获取远程进程寄存器值,并保存,以便注入完成后恢复进程原有状态。 [3]获取远程进程系统调用mmap、dlopen、dlsym调用地址。 [4]调用远程进程mmap分配一段存储空间,并在空间中写入so库路径以及函数调用参数。 [5]执行远程进程dlopen,加载so库。 [6]执行远程进程dlsym,获取so库中需要执行的函数地址。 [7]执行远程进程中的函数。 [7]恢复远程进程寄存器。 [8]DETACH远程进程。 * */ int ret = -1; void*mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr; void*local_handle, *remote_handle, *dlhandle; unsigned char* map_base; unsigned char* dlopen_param1_ptr, *dlsym_param2_ptr, *saved_r0_pc_ptr, *inject_param_ptr, *remote_code_ptr, *local_code_ptr; struct pt_regs regs, original_regs; extern unsigned int _dlopen_addr_s, _dlopen_param1_s, _dlopen_param2_s, _dlsym_addr_s, _dlsym_param2_s, _dlclose_addr_s, _inject_start_s, _inject_end_s, _inject_function_param_s, _saved_cpsr_s, _saved_r0_pc_s; unsigned int code_length; long parameters[10]; printf("[+] Injecting process: %d\n", target_pid ); if (ptrace_attach(target_pid)== -1) return EXIT_SUCCESS; if (ptrace_getregs(target_pid, ®s)== -1) goto exit; /* save original registers */ memcpy(&original_regs, ®s, sizeof(regs)); mmap_addr = get_remote_addr(target_pid, "/system/lib/libc.so", (void*)mmap); printf("[+] Remote mmap address: %x\n", mmap_addr ); /* call mmap */ parameters[0] = 0; // addr parameters[1] = 0x4000; // size parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; // prot parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; // flags parameters[4] = 0; //fd parameters[5] = 0; //offset printf("[+] Calling mmap in target process.\n" ); if (ptrace_call(target_pid, (unsigned int)mmap_addr, parameters, 6, ®s) == -1) goto exit; if (ptrace_getregs(target_pid, ®s)== -1) goto exit; printf("[+] Target process returned from mmap, return value=%x, pc=%x \n", regs.ARM_r0, regs.ARM_pc ); map_base = (unsigned char*)regs.ARM_r0; /*------------------------------------------------------------------------------------------------------*/ dlopen_addr = get_remote_addr(target_pid, linker_path, (void*)dlopen); dlsym_addr = get_remote_addr(target_pid, linker_path, (void*)dlsym); dlclose_addr = get_remote_addr(target_pid, linker_path, (void*)dlclose); printf("[+] Get imports: dlopen: %x, dlsym: %x, dlclose: %x\n", dlopen_addr, dlsym_addr, dlclose_addr ); remote_code_ptr = map_base + 0x3C00; local_code_ptr = (unsigned char*)&_inject_start_s; _dlopen_addr_s = (unsigned int)dlopen_addr; _dlsym_addr_s = (unsigned int)dlsym_addr; _dlclose_addr_s = (unsigned int)dlclose_addr; printf("[+] Inject code start: %x, end: %x\n", local_code_ptr, &_inject_end_s ); code_length = (unsigned int)&_inject_end_s - (unsigned int)&_inject_start_s; dlopen_param1_ptr = local_code_ptr + code_length + 0x20; dlsym_param2_ptr = dlopen_param1_ptr + MAX_PATH; // 偏移 saved_r0_pc_ptr = dlsym_param2_ptr + MAX_PATH; //偏移 inject_param_ptr = saved_r0_pc_ptr + MAX_PATH; //偏移 /* dlopen parameter 1: library name */ strcpy((char*)dlopen_param1_ptr, library_path); _dlopen_param1_s = REMOTE_ADDR(dlopen_param1_ptr, local_code_ptr, remote_code_ptr); printf("[+] _dlopen_param1_s: %x\n", _dlopen_param1_s ); /* dlsym parameter 2: function name */ strcpy((char*)dlsym_param2_ptr, function_name); _dlsym_param2_s = REMOTE_ADDR(dlsym_param2_ptr, local_code_ptr, remote_code_ptr); printf("[+] _dlsym_param2_s: %x\n", _dlsym_param2_s ); /* saved cpsr */ _saved_cpsr_s = original_regs.ARM_cpsr; /* saved r0-pc */ memcpy(saved_r0_pc_ptr, &(original_regs.ARM_r0), 16 * 4); // r0 ~ r15 _saved_r0_pc_s = REMOTE_ADDR(saved_r0_pc_ptr, local_code_ptr, remote_code_ptr); printf("[+] _saved_r0_pc_s: %x\n", _saved_r0_pc_s ); /* Inject function parameter */ memcpy(inject_param_ptr, param, param_size); _inject_function_param_s = REMOTE_ADDR(inject_param_ptr, local_code_ptr, remote_code_ptr); printf("[+] _inject_function_param_s: %x\n", _inject_function_param_s ); printf("[+] Remote shellcode address: %x\n", remote_code_ptr ); ptrace_writedata(target_pid, remote_code_ptr, local_code_ptr, 0x400); memcpy(®s, &original_regs, sizeof(regs)); regs.ARM_sp= (long)remote_code_ptr; regs.ARM_pc= (long)remote_code_ptr; printf("[+] recovery regs.\n"); ptrace_setregs(target_pid, ®s); printf("[+] detach.\n"); ptrace_detach(target_pid); // inject succeeded printf("[+] inject succeeded\n"); ret = 0; exit: return ret; }