ea_t map_port(ea_t from) { for ( int i=0; i < map.size(); i++ ) if ( map[i].from == from ) return map[i].to; return from; }
int does_exist(TFuncMallocWrapper new_func_malloc) { for(int i = 0; i< funcMalloc_wrappers.size(); i++){ if(funcMalloc_wrappers[i].address == new_func_malloc.address)return 1; } return 0; }
int writeQIntVec(qvector & qv, string fname, int buffsize) { int j, nrows, fmt, ncols, nnz; uint64 v; ostream *ofstr = open_out_buf(fname, buffsize); ncols = qv.size(); nrows = 4; nnz = nrows * ncols; fmt = 110; ofstr->write((const char *)&fmt, 4); ofstr->write((const char *)&nrows, 4); ofstr->write((const char *)&ncols, 4); ofstr->write((const char *)&nnz, 4); for (j = 0; j < qv.size(); j++) { v = qv[j].bottom; ofstr->write((const char *)&v, 8); v = qv[j].top; ofstr->write((const char *)&v, 8); } closeos(ofstr); return 0; }
tid_t idaapi merge_types(qvector<qstring> types_to_merge, qstring type_name) { tid_t struct_type_id = BADADDR; std::set<ea_t> offsets; if (types_to_merge.size() != 0) { struct_type_id = add_struc(BADADDR, type_name.c_str()); if (struct_type_id != 0 || struct_type_id != BADADDR) { struc_t * struc = get_struc(struct_type_id); if (struc != NULL) { qvector<qstring>::iterator types_iter; for (types_iter = types_to_merge.begin(); types_iter != types_to_merge.end(); types_iter++) { tid_t type_id = get_struc_id((*types_iter).c_str()); if (type_id != BADADDR) { struc_t * struc_type = get_struc(type_id); if (struc_type != NULL) { // enumerate members for (ea_t offset = get_struc_first_offset(struc_type); offset != BADADDR; offset = get_struc_next_offset(struc_type, offset)) { member_t * member_info = get_member(struc_type, offset); if (member_info != NULL) { if (offsets.count(member_info->soff) == 0) { qstring member_name = get_member_name2(member_info->id); asize_t member_size = get_member_size(member_info); if (member_name.find("vftbl_", 0) != -1) { tinfo_t tif; if (get_member_tinfo2(member_info, &tif)) { add_struc_member(struc, member_name.c_str(), member_info->soff, dwrdflag(), NULL, member_size); member_t * membr = get_member(struc, member_info->soff); if (membr != NULL) { set_member_tinfo2(struc, membr, 0, tif, SET_MEMTI_COMPATIBLE); } } } else { add_struc_member(struc, member_name.c_str(), member_info->soff, member_info->flag, NULL, member_size); } offsets.insert(member_info->soff); } } } } } } } } } return struct_type_id; }
//queue up a received datagram for eventual handlng via IDA's execute_sync mechanism //call no sdk functions other than execute_sync void disp_request_t::queueObject(json_object *obj) { bool call_exec = false; qmutex_lock(mtx); objects.push_back(obj); call_exec = objects.size() == 1; qmutex_unlock(mtx); if (call_exec) { //only invoke execute_sync if the buffer just added was at the head of the queue //in theory this allows multiple datagrams to get queued for handling //in a single execute_sync callback execute_sync(*this, MFF_WRITE); } }
int writeQIntVecx(qvector & im, string fname, int buffsize) { int fmt, nrows, ncols, nnz; ostream *ofstr = open_out_buf(fname.c_str(), buffsize); fmt = 170; nrows = im.size(); ncols = 1; nnz = nrows; ofstr->write((const char *)&fmt, 4); ofstr->write((const char *)&nrows, 4); ofstr->write((const char *)&ncols, 4); ofstr->write((const char *)&nnz, 4); ofstr->write((const char *)&im[0], 16 * nrows); closeos(ofstr); return 0; }
//this is the callback that gets called by execute_sync, in theory new datagrams //can arrive and be processed during the loop since queue synchronization takes //place within the StringList int idaapi disp_request_t::execute(void) { while (objects.size() > 0) { qmutex_lock(mtx); qvector<json_object*>::iterator i = objects.begin(); json_object *obj = *i; objects.erase(i); qmutex_unlock(mtx); bool res = (*_disp)(obj); if (!res) { //not sure we really care what is returned here // msg(PLUGIN_NAME": connection to server severed at dispatch.\n"); // comm->cleanup(true); //probably not the right thing to do?? // break; } else { //msg(PLUGIN_NAME": dispatch routine called successfully.\n"); } } return 0; }
void IDAP_run(int arg) { FILE *f, *f2; char *filename = construct_output_filename(".import_allocs.txt"); f = qfopen(filename, "wb"); char *filename2 = construct_output_filename(".import_allocs_wrappers.txt"); f2 = qfopen(filename2, "wb"); //r0 allocators funcMalloc.push_back(TFuncMalloc(" ExAllocatePoolWithQuota", 2)); funcMalloc.push_back(TFuncMalloc(" __imp__ExAllocatePoolWithQuota@8", 2));//ntoskrnl.exe funcMalloc.push_back(TFuncMalloc(" ExAllocatePoolWithQuotaTag", 2)); funcMalloc.push_back(TFuncMalloc(" __imp__ExAllocatePoolWithQuotaTag@12", 2));//ntoskrnl.exe funcMalloc.push_back(TFuncMalloc("ExAllocatePoolWithTag", 2)); funcMalloc.push_back(TFuncMalloc("__imp__ExAllocatePoolWithTag@12", 2));//ntoskrnl.exe funcMalloc.push_back(TFuncMalloc("ExAllocatePoolWithTagPriority", 2)); funcMalloc.push_back(TFuncMalloc("__imp__ExAllocatePoolWithTagPriority@16", 2));//ntoskrnl.exe funcMalloc.push_back(TFuncMalloc("IoAllocateMdl", 2)); funcMalloc.push_back(TFuncMalloc("__imp__IoAllocateMdl@20", 2));//ntoskrnl.exe funcMalloc.push_back(TFuncMalloc("RtlAllocateHeap", 3)); funcMalloc.push_back(TFuncMalloc("__imp__RtlAllocateHeap", 3));//ntoskrnl.exe funcMalloc.push_back(TFuncMalloc("EngAllocMem", 2)); funcMalloc.push_back(TFuncMalloc("__imp__EngAllocMem", 2));//win32k.sys funcMalloc.push_back(TFuncMalloc("__imp__EngAllocMem@12", 2));//win32k.sys //type pointer to size!!! //funcMalloc.push_back(TFuncMalloc("ZwAllocateVirtualMemory", 4)); //funcMalloc.push_back(TFuncMalloc("__imp__ZwAllocateVirtualMemory@24", 4));//ntoskrnl.exe //funcMalloc.push_back(TFuncMalloc("NtAllocateVirtualMemory", 4)); //funcMalloc.push_back(TFuncMalloc("__imp__NtAllocateVirtualMemory@24", 4));//ntoskrnl.exe //funcMalloc.push_back(TFuncMalloc("RtlReAllocateHeap", 4)); //funcMalloc.push_back(TFuncMalloc("HeapAlloc", 3)); //r3 allocators funcMalloc.push_back(TFuncMalloc("GlobalAlloc", 2));//kernel32.dll funcMalloc.push_back(TFuncMalloc("HeapAlloc", 3));//kernel32.dll funcMalloc.push_back(TFuncMalloc("__imp__HeapAlloc@12", 3));//kernel32.dll funcMalloc.push_back(TFuncMalloc("__imp__HeapReAlloc@16", 4));//kernel32.dll funcMalloc.push_back(TFuncMalloc("HeapReAlloc", 4));//kernel32.dll funcMalloc.push_back(TFuncMalloc("__imp__LocalAlloc@8", 2));//kernel32.dll funcMalloc.push_back(TFuncMalloc("LocalAlloc", 2));//kernel32.dll funcMalloc.push_back(TFuncMalloc("__imp__LocalReAlloc@12", 3));//kernel32.dll funcMalloc.push_back(TFuncMalloc("LocalReAlloc", 3));//kernel32.dll funcMalloc.push_back(TFuncMalloc("VirtualAlloc", 2)); funcMalloc.push_back(TFuncMalloc("__imp__VirtualAlloc@16", 2));//kernel32.dll funcMalloc.push_back(TFuncMalloc("__imp__MpHeapAlloc", 3));//msdart.dll export funcMalloc.push_back(TFuncMalloc("__imp__MpHeapReAlloc", 3));//msdart.dll export funcMalloc.push_back(TFuncMalloc("__imp__GdipAlloc@4", 1));//gdiplus.dll export //funcMalloc.push_back(TFuncMalloc("GpMalloc", 1));//gdiplus.dll funcMalloc.push_back(TFuncMalloc("__imp__malloc", 1));//msvcrt.dll funcMalloc.push_back(TFuncMalloc("_malloc", 1));//msvcrt.dll, the same as __imp__malloc funcMalloc.push_back(TFuncMalloc("__imp__realloc", 2));//msvcrt.dll funcMalloc.push_back(TFuncMalloc("_realloc", 2));//msvcrt.dll //funcMalloc.push_back(TFuncMalloc("_alloca", 1)); //funcMalloc.push_back(TFuncMalloc("_malloca", 1)); uint i = 0, j = funcMalloc.size(); msg("standart funcMalloc.size() = %d\n", funcMalloc.size()); for(; i< funcMalloc.size(); i++){ find_alloc_calls_ex(f, funcMalloc[i]); pretty_printing_ex(f, funcMalloc[i]); if(Malloc_calls.size() > 0 ) Malloc_calls.clear(); qfprintf(f,"\n\n"); qflush( f ); } qfclose( f ); j = funcMalloc_wrappers.size(); msg("standart funcMalloc_wrappers.size() = %d\n", j); //TODO: add level property i = 0; while( i < j){ find_alloc_calls_warreps_ex(f2, funcMalloc_wrappers[i]); msg("[%d].funcMalloc.size() = %d\n", i, funcMalloc_wrappers.size()); msg("[%d].Malloc_calls.size() = %d\n", i, Malloc_calls.size()); pretty_printing_ex(f2, funcMalloc_wrappers[i]); if(Malloc_calls.size() > 0 ) Malloc_calls.clear(); j = funcMalloc_wrappers.size(); i++; qflush( f2 ); } qfclose( f2 ); return ; }
void pretty_printing_ex(FILE* f, TFuncMalloc func) { func_t *callee_func; qstring name_of_malloc_callee_function; int func_name_set = 0; for(int i = 0; i < Malloc_calls.size(); i++){ qfprintf(f,"\r\n"); callee_func = get_func(Malloc_calls[i].address); func_name_set = 0; if(callee_func){ func_name_set = 1; get_short_name(&name_of_malloc_callee_function, callee_func->startEA); //generate_disasm_line(callee_func->startEA, name_of_malloc_callee_function, sizeof(name_of_malloc_callee_function)); //tag_remove(name_of_malloc_callee_function, name_of_malloc_callee_function, sizeof(name_of_malloc_callee_function)); } if(func_name_set) qfprintf(f,"%s xref: at %a %s\n", func.alloc_func_name, Malloc_calls[i].address, name_of_malloc_callee_function.c_str()); else qfprintf(f,"%s xref: at %a %s\n", func.alloc_func_name, Malloc_calls[i].address, "CISSRT_undefined_function"); if(Malloc_calls[i].type == CONSTVALUE){ qfprintf(f,"Type: CONST = %d Malloc bytes\n", Malloc_calls[i].value); } if(Malloc_calls[i].type == VARVALUE){ char buffer[MAXSTR]; //char instr_clean[MAXSTR]; // Store the disassembled text in buf ua_ana0(Malloc_calls[i].address_of_last_size_object_modified); generate_disasm_line(cmd.ea, buffer, sizeof(buffer)); tag_remove(buffer, buffer, sizeof(buffer)); if(Malloc_calls[i].address_of_last_size_object_modified != BADADDR) qfprintf(f,"Type: VAR, last modif at %a %s\n", Malloc_calls[i].address_of_last_size_object_modified, buffer); else qfprintf(f,"Type: VAR, last modif lost :( \n"); //qfprintf(f,"last modif: \n", instr_clean); } if(Malloc_calls[i].type == VARVALUEVULN){ char buffer[MAXSTR]; //char instr_clean[MAXSTR]; // Store the disassembled text in buf ua_ana0(Malloc_calls[i].address_of_last_size_object_modified); generate_disasm_line(cmd.ea, buffer, sizeof(buffer)); tag_remove(buffer, buffer, sizeof(buffer)); //qfprintf(f,"get_first_operand disasm instruction: %s\n", instr_clean); if(Malloc_calls[i].address_of_last_size_object_modified != BADADDR) qfprintf(f,"Type: VAR, Possible Integer Overflow %a %s\n", Malloc_calls[i].address_of_last_size_object_modified, buffer); else qfprintf(f,"Type: VAR, last modif lost :( \n");//shouldnt be here } if(Malloc_calls[i].type == UNDEFINED){ char buffer[MAXSTR]; // Store the disassembled text in buf ua_ana0(Malloc_calls[i].address_of_last_size_object_modified); generate_disasm_line(cmd.ea, buffer, sizeof(buffer)); tag_remove(buffer, buffer, sizeof(buffer)); //qfprintf(f,"get_first_operand disasm instruction: %s\n", instr_clean); if(Malloc_calls[i].address_of_last_size_object_modified != BADADDR) qfprintf(f,"Type: UNDEFINED, at %a %s", Malloc_calls[i].address_of_last_size_object_modified, buffer);//shouldnt be here else qfprintf(f,"Type: UNDEFINED, last modif lost :("); } } }
void pretty_printing_ex(FILE* f, TFuncMallocWrapper func) { func_t *callee_func; qstring name_of_malloc_callee_function; int func_name_set = 0; for(int i = 0; i < Malloc_calls.size(); i++){ //qfprintf(f,"%s ----> %s xref: at %a \n", func.alloc_func_name, func.ancestor, Malloc_calls[i].address); qfprintf(f,"\r\n"); callee_func = get_func(Malloc_calls[i].address); func_name_set = 0; if(callee_func){ func_name_set = 1; get_short_name(&name_of_malloc_callee_function, callee_func->startEA); //generate_disasm_line(callee_func->startEA, name_of_malloc_callee_function, sizeof(name_of_malloc_callee_function)); //tag_remove(name_of_malloc_callee_function, name_of_malloc_callee_function, sizeof(name_of_malloc_callee_function)); } if(func_name_set) qfprintf(f,"%s argNumber = %d ----> %s xref: at %a %s\n", func.alloc_func_name, func.push_malloc_size_count, func.ancestor, Malloc_calls[i].address, name_of_malloc_callee_function.c_str()); else qfprintf(f,"%s argNumber = %d ----> %s xref: at %a %s\n", func.alloc_func_name, func.push_malloc_size_count, func.ancestor, Malloc_calls[i].address, "CISSRT_undefined_function"); //qfprintf(f,"%s xref: at %a %s\n", func.alloc_func_name, Malloc_calls[i].address, "CISSRT_undefined_function"); if(Malloc_calls[i].type == CONSTVALUE){ qfprintf(f,"Type: CONST = %d Malloc bytes\n", Malloc_calls[i].value); } else if(Malloc_calls[i].type == VARVALUE){ char buf[MAXSTR]; char instr_clean[MAXSTR]; // Store the disassembled text in buf ua_ana0(Malloc_calls[i].address_of_last_size_object_modified); generate_disasm_line(cmd.ea, buf, sizeof(buf)-1); // This will appear as colour-tagged text (which will // be mostly unreadable in IDA's tag_remove(buf, instr_clean, sizeof(instr_clean)-1); if(Malloc_calls[i].address_of_last_size_object_modified != BADADDR) qfprintf(f,"Type: VAR, last modif at %a %s\n", Malloc_calls[i].address_of_last_size_object_modified, instr_clean); else qfprintf(f,"Type: VAR, last modif lost :("); //qfprintf(f,"last modif: %s\n", instr_clean); } else if(Malloc_calls[i].type == VARVALUEVULN){ char buf[MAXSTR]; char instr_clean[MAXSTR]; // Store the disassembled text in buf ua_ana0(Malloc_calls[i].address_of_last_size_object_modified); generate_disasm_line(cmd.ea, buf, sizeof(buf)-1); // This will appear as colour-tagged text (which will // be mostly unreadable in IDA's tag_remove(buf, instr_clean, sizeof(instr_clean)-1); //qfprintf(f,"get_first_operand disasm instruction: %s\n", instr_clean); if(Malloc_calls[i].address_of_last_size_object_modified != BADADDR) qfprintf(f,"Type: VAR, Possible Integer Overflow at %a %s\n", Malloc_calls[i].address_of_last_size_object_modified, instr_clean); else qfprintf(f,"Type: VAR, last modif lost :("); } else if(Malloc_calls[i].type == UNDEFINED){ char buf[MAXSTR]; char instr_clean[MAXSTR]; // Store the disassembled text in buf ua_ana0(Malloc_calls[i].address_of_last_size_object_modified); generate_disasm_line(cmd.ea, buf, sizeof(buf)-1); // This will appear as colour-tagged text (which will // be mostly unreadable in IDA's tag_remove(buf, instr_clean, sizeof(instr_clean)-1); //qfprintf(f,"get_first_operand disasm instruction: %s\n", instr_clean); //qfprintf(f,"Type:var bytes, Possible Integer Overflow at %a %s\n", Malloc_calls[i].address_of_last_size_object_modified, instr_clean); if(Malloc_calls[i].address_of_last_size_object_modified != BADADDR) qfprintf(f,"Type: UNDEFINED, at %a %s", Malloc_calls[i].address_of_last_size_object_modified, instr_clean);//shouldnt be here else qfprintf(f,"Type: UNDEFINED, last modif lost :("); } } }
void analyze_malloc_xref_ex(char *name, ea_t xref_addr, int push_count) { qstring buffer; int value = 0; int type; op_t memory_size_var; if(is_trampoline(xref_addr)){ func_t *func = get_func(xref_addr); //msg("analyze_malloc_xref: %s %a - trampoline!\n", name, xref_addr); //too easy, how about mov ebp,esp jmp:malloc? if(func){ qstring buff; get_short_name(&buff, func->startEA); //get_long_name(BADADDR, func->startEA, buffer, MAXSTR); TFuncMallocWrapper new_malloc = TFuncMallocWrapper((char *)buff.c_str(), name, push_count, xref_addr, TRAMPOLINE); if(!does_exist(new_malloc)) funcMalloc_wrappers.push_back(new_malloc); } else{ TFuncMallocWrapper new_malloc = TFuncMallocWrapper("new malloc", name, push_count, xref_addr, TRAMPOLINE); if(!does_exist(new_malloc)) funcMalloc_wrappers.push_back(new_malloc); } } ea_t push_malloc_size_addr = find_instruction_N_times_backward(xref_addr, NN_push, push_count); if(push_malloc_size_addr != BADADDR){ memory_size_var = get_first_operand_new(push_malloc_size_addr); //Allocation of const memory size if(memory_size_var.type == o_imm){ //msg("analyze_malloc_xref: %s %a - immediate!\n", name, push_malloc_size_addr); Malloc_calls.push_back(TFuncMalloc_call(xref_addr, CONSTVALUE, memory_size_var.value)); //msg("analyze_malloc_xref: %s Malloc_call_list.size() = %d!\n", name, Malloc_calls.size()); return; } //Allocation of var memory size //Allocation of var by register if(memory_size_var.type == o_reg){ ea_t addr_of_src = find_instruction_that_changes_operand_backward_smart(push_malloc_size_addr, memory_size_var); msg("analyze_malloc_xref: %s %a - var!\n", name, push_malloc_size_addr); if(addr_of_src != BADADDR){ type = assign_type(addr_of_src, &value); Malloc_calls.push_back(TFuncMalloc_call(xref_addr, type, value, addr_of_src)); } else Malloc_calls.push_back(TFuncMalloc_call(xref_addr, UNDEFINED)); msg("analyze_malloc_xref: %s Malloc_call_list.size() = %d!\n", name, Malloc_calls.size()); return; } //Allocation of var by argument - new trampoline //TODO: better algo! if( (memory_size_var.type == o_displ) && (memory_size_var.reg == 5) && (memory_size_var.phrase == 5) && (memory_size_var.value == 0) && ( (int)memory_size_var.addr > 0) ){ func_t *func = get_func(xref_addr); //too easy, how about mov ebp,esp call:malloc? if(func) get_short_name(&buffer, func->startEA); //get_long_name(BADADDR, func->startEA, buffer, MAXSTR); TFuncMallocWrapper new_malloc = TFuncMallocWrapper((char *)buffer.c_str(), name, memory_size_var.addr / sizeof(ea_t) - 1, func->startEA, WRAPPER); if(!does_exist(new_malloc)) funcMalloc_wrappers.push_back(new_malloc); //funcMalloc.push_back(TFuncMalloc("here var name", memory_size_var.addr / sizeof(ea_t),func->startEA, WRAPPER)); else{ TFuncMallocWrapper new_malloc = TFuncMallocWrapper("new malloc", name, memory_size_var.addr / sizeof(ea_t) - 1, xref_addr, WRAPPER);//maybetter name malloc_at_%a? if(!does_exist(new_malloc)) funcMalloc_wrappers.push_back(new_malloc); //funcMalloc.push_back(TFuncMalloc("here name of addr", memory_size_var.addr / sizeof(ea_t), xref_addr, WRAPPER)); } return; msg("analyze_malloc_xref: %s Malloc_call_list.size() = %d!\n", name, Malloc_calls.size()); } else{ Malloc_calls.push_back(TFuncMalloc_call(xref_addr, VARVALUE)); } } else{ Malloc_calls.push_back(TFuncMalloc_call(xref_addr, UNDEFINED)); } msg("analyze_malloc_xref: %s Malloc_call_list.size() = %d!\n", name, Malloc_calls.size()); }