static BOOL process_vtbl(ea_t &ea_sect) { VTBL_info_t vftable_info_t; if(get_vtbl_info(ea_sect, vftable_info_t)) { ea_sect = vftable_info_t.ea_end; ea_t ea_assumed; verify_32_t((vftable_info_t.ea_begin - 4), ea_assumed); if(vftable_info_t.methods > 1) { if(has_user_name(getFlags(vftable_info_t.ea_begin))) { vftable_info_t.vtbl_name = get_short_name(vftable_info_t.ea_begin); qstring vtbl_info_str; vtbl_info_str.cat_sprnt(" 0x%x - 0x%x: %s methods count: %d", vftable_info_t.ea_begin, vftable_info_t.ea_end, vftable_info_t.vtbl_name.c_str(), vftable_info_t.methods); vtbl_list.push_back(vtbl_info_str); vtbl_t_list.push_back(vftable_info_t); return(TRUE); } } return(FALSE); } ea_sect += sizeof(UINT); return(FALSE); }
void toolbar_extension::button::get_display_text(pfc::string_base & p_out) //display { p_out.reset(); if (m_use_custom_text) p_out = m_text; else get_short_name(p_out); }
tid_t create_vtbl_struct(ea_t vtbl_addr, ea_t vtbl_addr_end, char* vtbl_name, uval_t idx, unsigned int* vtbl_len) { qstring struc_name = vtbl_name; tid_t id = add_struc(BADADDR, struc_name.c_str()); if (id == BADADDR) { struc_name.clear(); struc_name = askstr(HIST_IDENT, NULL, "Default name %s not correct. Enter other structure name: ", struc_name.c_str()); id = add_struc(BADADDR, struc_name.c_str()); set_struc_cmt(id, vtbl_name, true); } struc_t* new_struc = get_struc(id); if (!new_struc) return BADNODE; ea_t ea = vtbl_addr; int offset = 0; while (ea < vtbl_addr_end) { offset = ea - vtbl_addr; qstring method_name; ea_t method_ea = get_long(ea); if (method_ea == 0) break; if (!isEnabled(method_ea)) break; flags_t method_flags = getFlags(method_ea); char* struc_member_name = NULL; if (isFunc(method_flags)) { method_name = get_short_name(method_ea); if (method_name.length() != 0) struc_member_name = (char*)method_name.c_str(); } add_struc_member(new_struc, NULL, offset, dwrdflag(), NULL, 4); if (struc_member_name) { if (!set_member_name(new_struc, offset, struc_member_name)) { //get_name(NULL, method_ea, method_name, sizeof(method_name)); get_ea_name(&method_name, method_ea); set_member_name(new_struc, offset, struc_member_name); } } ea = ea + 4; flags_t ea_flags = getFlags(ea); if (has_any_name(ea_flags)) break; } return id; }
//ea_t find_function_EA_by_name(FILE *file, char *name) ea_t find_function_EA_by_name(char *name) { int count = strlen(name); for (uint i = 0; i < get_func_qty(); ++i) { func_t *f = getn_func(i); qstring buffer; get_short_name(&buffer, f->startEA); //qfprintf(file,"%s \n", buffer); if(strncmp(buffer.c_str(), name, count) == 0){ return f->startEA; } } return BADADDR; }
//ea_t find_function_EA_by_name(FILE *file, char *name) ea_t find_function_EA_by_name(char *name) { int count = strlen(name); for (uint i = 0; i < get_func_qty(); ++i) { func_t *f = getn_func(i); char buffer[MAXSTR]; get_short_name(BADADDR, f->startEA, buffer, MAXSTR); //qfprintf(file,"%s \n", buffer); if(strncmp(buffer, name, count) == 0){ return f->startEA; } } return BADADDR; }
void FindInvalidFunctionStartAndConnectBrokenFunctionChunk() { int connected_links_count=0; do { connected_links_count=0; for(size_t i=0;i<get_func_qty();i++) { func_t *f=getn_func(i); if(!IsValidFunctionStart(f->startEA)) { char function_name[100] = { 0, }; get_short_name(f->startEA, f->startEA, function_name, sizeof(function_name)); msg("Found invalid function: %s\n", function_name); connected_links_count+=ConnectBrokenFunctionChunk(f->startEA); } } }while(connected_links_count>0); }
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()); }
int ConnectBrokenFunctionChunk(ea_t address) { int connected_links_count=0; func_t *func=get_func(address); char function_name[1024]={0,}; get_short_name(address, address, function_name, sizeof(function_name)); bool is_function=false; bool AddFunctionAsMemberOfFunction=false; ea_t cref=get_first_cref_to(address); while(cref!=BADADDR) { func_t *cref_func=get_func(cref); if(cref_func!=func) { char op_buffer[40]={0,}; ua_mnem(cref,op_buffer,sizeof(op_buffer)); if(cmd.itype==NN_call || cmd.itype==NN_callfi || cmd.itype==NN_callni) { is_function=true; break; } } cref=get_next_cref_to(address,cref); } msg("ConnectBrokenFunctionChunk: %s %s\n", function_name, is_function? "is function": "is not function" ); if(!is_function) { if(func) del_func(address); cref=get_first_cref_to(address); while(cref!=BADADDR) { func_t *cref_func=get_func(cref); if(cref_func) { char cref_function_name[1024]; get_func_name(cref,cref_function_name,sizeof(cref_function_name)); msg("Adding Location %s(%X) To Function Member Of %s(%X:%X)\n",function_name,address,cref_function_name,cref_func->startEA,cref); append_func_tail(cref_func,address,GetBlockEnd(address)); connected_links_count++; } cref=get_next_cref_to(address,cref); } }else if(AddFunctionAsMemberOfFunction) { cref=get_first_cref_to(address); while(cref!=BADADDR) { char op_buffer[40]={0,}; ua_mnem(cref,op_buffer,sizeof(op_buffer)); if(!(cmd.itype==NN_call || cmd.itype==NN_callfi || cmd.itype==NN_callni)) { func_t *cref_func=get_func(cref); if(cref_func) { char cref_function_name[1024]; get_func_name(cref,cref_function_name,sizeof(cref_function_name)); msg("Adding Function %s(%X) To Function Member Of %s(%X:%X)\n",function_name,address,cref_function_name,cref_func->startEA,cref); append_func_tail(cref_func,address,GetBlockEnd(address)); connected_links_count++; } } cref=get_next_cref_to(address,cref); } } return connected_links_count; }
// Process function void processFunction(func_t *f) { // Skip tiny functions if(f->size() >= 5) { // Don't add comments to API wrappers char name[MAXNAMELEN]; name[0] = name[SIZESTR(name)] = 0; if(!apiMap.empty()) { if(get_short_name(BADADDR, f->startEA, name, SIZESTR(name))) { if(apiMap.find(name) != apiMap.end()) return; } } // Iterate function body STRLIST importLstTmp; LPSTR commentPtr = NULL; char comment[MAXSTR]; comment[0] = comment[SIZESTR(comment)] = 0; UINT commentLen = 0; #define ADDNM(_str) { UINT l = strlen(_str); memcpy(comment + commentLen, _str, l); commentLen += l; _ASSERT(commentLen < MAXSTR); } func_item_iterator_t it(f); do { ea_t currentEA = it.current(); // Will be a "to" xref xrefblk_t xb; if(xb.first_from(currentEA, XREF_FAR)) { BOOL isImpFunc = FALSE; name[0] = 0; // If in import segment // ============================================================================================ ea_t refAdrEa = xb.to; if(isInImportSeg(refAdrEa)) { flags_t flags = get_flags_novalue(refAdrEa); if(has_name(flags) && hasRef(flags) && isDwrd(flags)) { if(get_short_name(BADADDR, refAdrEa, name, SIZESTR(name))) { // Nix the imp prefix if there is one if(strncmp(name, "__imp_", SIZESTR("__imp_")) == 0) memmove(name, name + SIZESTR("__imp_"), ((strlen(name) - SIZESTR("__imp_")) + 1)); isImpFunc = TRUE; } else msg(EAFORMAT" *** Failed to get import name! ***\n", refAdrEa); } } // Else, check for import wrapper // ============================================================================================ else if(!apiMap.empty()) { // Reference is a function entry? flags_t flags = get_flags_novalue(refAdrEa); if(isCode(flags) && has_name(flags) && hasRef(flags)) { if(func_t *refFuncPtr = get_func(refAdrEa)) { if(refFuncPtr->startEA == refAdrEa) { if(get_short_name(BADADDR, refAdrEa, name, SIZESTR(name))) { // Skip common unwanted types "sub_.." or "unknown_libname_.." if( // not "sub_.. /*"sub_"*/ (*((PUINT) name) != 0x5F627573) && // not "unknown_libname_.. /*"unknown_"*/ ((*((PUINT64) name) != 0x5F6E776F6E6B6E75) && (*((PUINT64) (name + 8)) != /*"libname_"*/ 0x5F656D616E62696C)) && // not nullsub_.. /*"nullsub_"*/ (*((PUINT64) name) != 0x5F6275736C6C756E) ) { // Nix the import prefixes if(strncmp(name, "__imp_", SIZESTR("__imp_")) == 0) memmove(name, name + SIZESTR("__imp_"), ((strlen(name) - SIZESTR("__imp_")) + 1)); // Assumed to be a wrapped import if it's in the list isImpFunc = (apiMap.find(name) != apiMap.end()); } } else msg(EAFORMAT" *** Failed to get function name! ***\n", refAdrEa); } } } } // Found import function to add list if(isImpFunc) { // Skip those large common STL names if(strncmp(name, "std::", SIZESTR("std::")) != 0) { // Skip if already seen in this function BOOL known = FALSE; for(STRLIST::iterator ji = importLstTmp.begin(); ji != importLstTmp.end(); ji++) { if(strcmp(ji->c_str(), name) == 0) { known = TRUE; break; } } // Not seen if(!known) { importLstTmp.push_front(name); // Append to existing comments w/line feed if(!commentLen && !commentPtr) { commentPtr = get_func_cmt(f, true); if(!commentPtr) get_func_cmt(f, false); if(commentPtr) { commentLen = strlen(commentPtr); // Bail out not enough comment space if(commentLen >= (MAXSTR - 20)) { qfree(commentPtr); return; } memcpy(comment, commentPtr, commentLen); ADDNM("\n"MYTAG); } } if(!commentLen) ADDNM(MYTAG); // Append a "..." (continuation) and bail out if name hits max comment length if((commentLen + strlen(name) + SIZESTR("()") + sizeof(", ")) >= (MAXSTR - sizeof("..."))) { ADDNM(" ..."); break; } // Append this function name else { if(importLstTmp.size() != 1) ADDNM(", "); ADDNM(name); ADDNM("()"); } } } else { //msg("%s\n", szName); } } } }while(it.next_addr()); if(!importLstTmp.empty() && commentLen) { // Add comment comment[commentLen] = 0; set_func_cmt(f, comment, true); commentCount++; } if(commentPtr) qfree(commentPtr); } }