static void get_xrefs_to_vtbl() { ea_t cur_vt_ea = vtbl_t_list[current_line_pos].ea_begin; for (ea_t addr = get_first_dref_to(cur_vt_ea); addr != BADADDR; addr = get_next_dref_to(cur_vt_ea, addr)) { qstring name; get_func_name2(&name, addr); xref_addr.push_back(addr); qstring tmp; tmp.cat_sprnt(" 0x%x: %s", addr, name); xref_list.push_back(tmp); } }
static void get_xrefs_to_vtbl() { // the list is repeat while select another vtable xref_list.clear(); xref_addr.clear(); ea_t cur_vt_ea = vtbl_t_list[current_line_pos].ea_begin; for (ea_t addr = get_first_dref_to(cur_vt_ea); addr != BADADDR; addr = get_next_dref_to(cur_vt_ea, addr)) { qstring name; f_get_func_name2(&name, addr); xref_addr.push_back(addr); qstring tmp; #ifndef __EA64__ tmp.cat_sprnt(" 0x%x: %s", addr, name); #else tmp.cat_sprnt(_T(" 0x%I64X: %s"), addr, name); #endif xref_list.push_back(tmp); } }
BOOL get_vtbl_info(ea_t ea_address, VTBL_info_t &vtbl_info) { flags_t flags = getFlags(ea_address); if (!(hasRef(flags) || has_any_name(flags) && (isDwrd(flags) || isUnknown(flags)))) return(FALSE); else { BOOL is_move_xref = FALSE; ea_t ea_code_ref = get_first_dref_to(ea_address); if (ea_code_ref && (ea_code_ref != BADADDR)) { do { if (isCode(getFlags(ea_code_ref))) { LPCTSTR disasm_line = get_text_disasm(ea_code_ref); #ifndef __EA64__ if ((*((PUINT)disasm_line) == 0x20766F6D /*"mov "*/) && (strstr(disasm_line + 4, " offset ") != NULL)) #else if ((*((PUINT)disasm_line) == 0x2061656c /*"lea "*/) && (strstr(disasm_line + 4, "rcx") != NULL) && (strstr(disasm_line + 4, "const") != NULL)) #endif { is_move_xref = TRUE; break; } } ea_code_ref = get_next_dref_to(ea_address, ea_code_ref); } while (ea_code_ref && (ea_code_ref != BADADDR)); } if (!is_move_xref) return(FALSE); ZeroMemory(&vtbl_info, sizeof(VTBL_info_t)); // get_name(BADADDR, ea_address, vtbl_info.vtbl_name, (MAXSTR - 1)); f_get_ea_name(&vtbl_info.vtbl_name, ea_address); ea_t ea_start = vtbl_info.ea_begin = ea_address; while (TRUE) { flags_t index_flags = getFlags(ea_address); #ifndef __EA64__ if (!(hasValue(index_flags) && (isDwrd(index_flags) || isUnknown(index_flags)))) #else if (!(hasValue(index_flags) && (isQwrd(index_flags) || isUnknown(index_flags)))) #endif break; #ifndef __EA64__ ea_t ea_index_value = get_32bit(ea_address); #else ea_t ea_index_value = get_64bit(ea_address); #endif if (!(ea_index_value && (ea_index_value != BADADDR))) break; if (ea_address != ea_start) if (hasRef(index_flags)) break; flags_t value_flags = getFlags(ea_index_value); if (!isCode(value_flags)) break; else if (isUnknown(index_flags)) #ifndef __EA64__ doDwrd(ea_address, sizeof(DWORD)); ea_address += sizeof(UINT); #else doQwrd(ea_address, sizeof(UINT64)); ea_address += sizeof(UINT64); #endif }; #ifndef __EA64__ if ((vtbl_info.methods = ((ea_address - ea_start) / sizeof(UINT))) > 0) #else if((vtbl_info.methods = ((ea_address - ea_start) / sizeof(UINT64))) > 0) #endif { vtbl_info.ea_end = ea_address; return(TRUE); } else return(FALSE); } }
bool idaapi extract_all_types(void *ud) { logmsg(DEBUG, "extract_types()\n"); // find vtables in the binary search_objects(false); qvector <VTBL_info_t>::iterator vtbl_iter; std::map<ea_t, VTBL_info_t> vtbl_map; for (vtbl_iter = vtbl_t_list.begin(); vtbl_iter != vtbl_t_list.end(); vtbl_iter++) vtbl_map[(*vtbl_iter).ea_begin] = (*vtbl_iter); int file_id = create_open_file("types.txt"); if (file_id == -1) { logmsg(ERROR, "Failed to open file for dumping types.txt\r\n"); return false; } int struct_no = 0; for (vtbl_iter = vtbl_t_list.begin(); vtbl_iter != vtbl_t_list.end(); vtbl_iter++) { qstring info_msg; info_msg.cat_sprnt("Processing vtable %s\n", (*vtbl_iter).vtbl_name.c_str()); logmsg(DEBUG, info_msg.c_str()); qstring type_name; type_name.sprnt("struc_2_%d", struct_no); ea_t cur_vt_ea = (*vtbl_iter).ea_begin; int struct_subno = 0; qvector <qstring> types_to_merge; for (ea_t addr = get_first_dref_to(cur_vt_ea); addr != BADADDR; addr = get_next_dref_to(cur_vt_ea, addr)) { qstring name; if (get_func_name(&name, addr) <= 0) continue; qstring info_msg1; info_msg1.cat_sprnt("\t%s\n", name.c_str()); logmsg(DEBUG, info_msg1.c_str()); func_t *pfn = get_func(addr); if (!pfn) continue; hexrays_failure_t hf; cfuncptr_t cfunc = decompile(pfn, &hf); if (cfunc != NULL) { qstring var_name; info_msg.clear(); if (find_var(cfunc, (*vtbl_iter).vtbl_name, var_name)) { info_msg.cat_sprnt(" : %s\n", var_name.c_str()); logmsg(DEBUG, info_msg.c_str()); qstring sub_type_name = type_name; sub_type_name.cat_sprnt("_%d", struct_subno); struct_subno++; if (reconstruct_type(cfunc, var_name, sub_type_name)) { if (check_subtype((*vtbl_iter), sub_type_name)) { types_to_merge.push_back(sub_type_name); } } } else { info_msg.cat_sprnt(" : none\n"); logmsg(DEBUG, info_msg.c_str()); } } } struct_no++; merge_types(types_to_merge, type_name); dump_type_info(file_id, (*vtbl_iter), type_name, vtbl_map); } qclose(file_id); return true; }