void idaapi matched_structs_with_offsets::get_type_line(void *obj,uint32 n,char * const *arrptr) { matched_structs_with_offsets & ms = *(matched_structs_with_offsets*)obj; if (n==0) { qstrncpy(arrptr[0], "member", MAXSTR); qstrncpy(arrptr[1], "type", MAXSTR); } else { char name[MAXSTR]; name[0]=0; char type_str[MAXSTR]; type_str[0]=0; tid_t id = ms.idcka[n-1]; struc_t * struc = get_struc(id); print_struct_member_name(struc, ms.offset, name, sizeof(name)); member_t * member = 0; if(struct_get_member(get_struc(id), ms.offset, &member) && member) { //typestring type; tinfo_t type; if(get_member_type(member, &type)) { type.print(new qstring(type_str)); } } qstpncpy(arrptr[0], name, MAXSTR); qstpncpy(arrptr[1], type_str, MAXSTR); } }
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; }
tid_t idaapi merge_types(const qvector<qstring>& types_to_merge, const qstring& type_name) { tid_t struct_type_id = BADADDR; if (types_to_merge.empty()) return struct_type_id; std::set<ea_t> offsets; struct_type_id = add_struc(BADADDR, type_name.c_str()); if (struct_type_id == BADADDR) return struct_type_id; struc_t * struc = get_struc(struct_type_id); if (!struc) return struct_type_id; for (auto types_iter = types_to_merge.begin(), end = types_to_merge.end(); types_iter != end; ++types_iter) { struc_t * struc_type = get_struc(get_struc_id(types_iter->c_str())); if (!struc_type) continue; // 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) continue; if (offsets.count(member_info->soff) == 0) { qstring member_name = get_member_name(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_tinfo(&tif, member_info)) { add_struc_member(struc, member_name.c_str(), member_info->soff, dword_flag(), NULL, member_size); if (member_t * membr = get_member(struc, member_info->soff)) { set_member_tinfo(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; }
static void declare_parameter_types(ea_t ea, int count) { static const char class_name[] = "CMethodDef"; struc_t *sptr = get_struc(get_struc_id(class_name)); if ( sptr == NULL ) { sptr = get_struc(add_struc(-1, class_name)); if ( sptr == NULL ) return; add_struc_member(sptr, "methodParameterDef", -1, wordflag(), NULL, 2); add_struc_member(sptr, "handlerTypeDef", -1, byteflag(), NULL, 1); } size_t size = get_struc_size(sptr); doStruct(ea, size*count, sptr->id); }
//-------------------------------------------------------------------------- static void declare_class(ea_t ea, const char *entryname) { static const char class_name[] = "ClassStruct"; struc_t *sptr = get_struc(get_struc_id(class_name)); if ( sptr == NULL ) { sptr = get_struc(add_struc(BADADDR, class_name)); if ( sptr == NULL ) return; opinfo_t mt; mt.ri.flags = REF_OFF32; mt.ri.target = BADADDR; mt.ri.base = 0; mt.ri.tdelta = 0; add_struc_member(sptr, "superClass", BADADDR, offflag()|dwrdflag(), &mt, 4); add_struc_member(sptr, "masterOffset", BADADDR, wordflag(), NULL, 2); add_struc_member(sptr, "methodCount", BADADDR, decflag()|wordflag(), NULL, 2); add_struc_member(sptr, "instanceSize", BADADDR, decflag()|wordflag(), NULL, 2); add_struc_member(sptr, "vdRelocTable", BADADDR, wordflag(), NULL, 2); add_struc_member(sptr, "relocTable", BADADDR, wordflag(), NULL, 2); mt.ec.tid = get_class_struct_flags_enum(); mt.ec.serial = 0; add_struc_member(sptr, "flags", BADADDR, enumflag()|byteflag(), &mt, 1); add_struc_member(sptr, "masterMethods",BADADDR, byteflag(), NULL, 1); } asize_t size = get_struc_size(sptr); doStruct(ea, size, sptr->id); int count = get_word(ea+6); // bool c_handlers = get_byte(ea+14) & (1<<6); ea += size; ea_t messages = ea; doWord(ea, count*2); op_dec(ea, 0); ea += 2*count; doDwrd(ea, count*4); set_offset(ea, 0, 0); for ( int i=0; i < count; i++ ) { ea_t idx = ea + 4*i; ea_t pea = toEA(get_word(idx+2), get_word(idx)); auto_make_proc(pea); char name[MAXSTR]; qsnprintf(name, sizeof(name), "%s_%u", entryname, get_word(messages+2*i)); add_entry(pea, pea, name, true); } // commented out because it doesn't work properly // see geoplan.geo, entry number 1 for example // if ( c_handlers ) // declare_parameter_types(ea+count*4, count); }
bool idaapi check_subtype(const VTBL_info_t &vtbl_info, const qstring &subtype_name) { bool bResult = false; qstring search_str; search_str.sprnt("_%p", vtbl_info.ea_begin); tid_t type_id = get_struc_id(subtype_name.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) { qstring member_name = get_member_name2(member_info->id); if (member_name.find(search_str, 0) != -1) { bResult = true; break; } } } } } return bResult; }
void idaapi run(int arg) { char *st_name = "struc_2"; char buf[MAXSTR]; static char st_name_buf[100]; if (arg == 0) { strcpy(buf, st_name); CWin32InputBox::InputBox("Struct name", "Enter struct name:", st_name_buf, sizeof(st_name_buf)); st_name = st_name_buf; } size_t st_qty = get_struc_qty(); msg("we have: %d structs\n", st_qty); // find the structure by name tid_t id = get_struc_id(st_name); // get the size of the structure asize_t st_sz = get_struc_size(id); msg("sizeof(%s) = %d\n", st_name, st_sz); struc_t *st = get_struc(id); enum_members2(st); return; }
void idaapi dump_type_info(int file_id, const VTBL_info_t& vtbl_info, const qstring& type_name, const std::map<ea_t, VTBL_info_t>& vtbl_map) { struc_t * struc_type = get_struc(get_struc_id(type_name.c_str())); if (!struc_type) return; qstring file_entry_key; qstring key_hash; bool filtered = false; get_struct_key(struc_type, vtbl_info, file_entry_key, filtered, vtbl_map); get_hash_of_string(file_entry_key, key_hash); if (filtered) return; qstring file_entry_val; tinfo_t new_type = create_typedef(type_name.c_str()); if (new_type.is_correct() && new_type.print(&file_entry_val, NULL, PRTYPE_DEF | PRTYPE_1LINE)) { qstring line; line = key_hash + ";" + file_entry_key + ";"; line.cat_sprnt("%a;", vtbl_info.ea_begin); line += file_entry_val + ";"; if (rtti_vftables.count(vtbl_info.ea_begin) != 0) { VTBL_info_t vi = rtti_vftables[vtbl_info.ea_begin]; line += vi.vtbl_name; } line.rtrim(); line += "\r\n"; qwrite(file_id, line.c_str(), line.length()); } }
void StrucCmp::add_all_members(void) throw() { if(m_struc_id != BADNODE) { struc_t *sptr = get_struc(m_struc_id); ssize_t const struc_len = get_struc_name(m_struc_id, NULL, 0); for(size_t idx = 0; idx < sptr->memqty; ++idx) { member_t *mptr = &(sptr->members[idx]); // get_member_name crashes when given a NULL pointer... // we need to get the "struct.field" name and // substract the "struct." part // len is without the '\0' character ssize_t len = get_member_fullname(mptr->id, NULL, 0); if(len != -1) { len -= struc_len; char *buf = static_cast<char *>(qalloc(len)); if(buf != NULL) { get_member_name(mptr->id, buf, len); m_members[buf] = m_is_union ? 0 : mptr->soff; } } } } }
tid_t type_builder_t::get_structure(const qstring name) { tid_t struct_type_id = add_struc(BADADDR, name.c_str()); if (struct_type_id != 0 || struct_type_id != -1) { struc_t * struc = get_struc(struct_type_id); if(struc != NULL) { opinfo_t opinfo; opinfo.tid = struct_type_id; int j = 0; for(std::map<int, struct_filed>::iterator i = structure.begin(); i != structure.end() ; i ++) { VTBL_info_t vtbl; flags_t member_flgs = 0; if(i->second.size == 1) member_flgs = byteflag(); else if (i->second.size == 2) member_flgs = wordflag(); else if (i->second.size == 4) member_flgs = dwrdflag(); else if (i->second.size == 8) member_flgs = qwrdflag(); char field_name[258]; memset(field_name, 0x00, sizeof(field_name)); if((i->second.vftbl != BADADDR) && get_vbtbl_by_ea(i->second.vftbl, vtbl)) { qstring vftbl_name = name; vftbl_name.cat_sprnt("_VTABLE_%X_%p", i->second.offset, i->second.vftbl); tid_t vtbl_str_id = create_vtbl_struct(vtbl.ea_begin, vtbl.ea_end, (char *)vftbl_name.c_str(), 0); if (vtbl_str_id != BADADDR) { sprintf_s(field_name, sizeof(field_name), "vftbl_%d_%p", j, i->second.vftbl); int iRet = add_struc_member(struc, field_name, i->second.offset, member_flgs, NULL, i->second.size); member_t * membr = get_member_by_name(struc, field_name); if (membr != NULL) { tinfo_t new_type = create_typedef((char *)vftbl_name.c_str()); if(new_type.is_correct()) { smt_code_t dd = set_member_tinfo2(struc, membr, 0, make_pointer(new_type), SET_MEMTI_COMPATIBLE); } } } } else { sprintf_s(field_name, sizeof(field_name), "field_%X", i->second.offset); int iRet = add_struc_member(struc, field_name, i->second.offset, member_flgs, NULL, i->second.size); } j ++; } } } return struct_type_id; }
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; }
static int GetTypeOfStructInstance(ea_t ea, ea_t head, flags_t flags) { typeinfo_t ti; if (!get_typeinfo(head, 0, flags, &ti)) return T_UNK; struc_t *sptr = get_struc(ti.tid); if (!sptr) return T_UNK; member_t *mptr = get_best_fit_member(sptr, ea - head); if (!mptr || mptr->soff != ea - head) return T_UNK; return GetMemberType(mptr); }
struc_t * struct_create(int size) { struc_t *sptr; sptr = get_struc(add_struc(BADADDR, NULL, false)); if(!sptr) { msg("[idastruct] error: could not create structure\n"); return NULL; } return sptr; }
char * idaapi matched_structs::get_type_line(void *obj, uint32 n, char *buf) { matched_structs & ms = *(matched_structs*)obj; if (n==0) qstpncpy( buf, "type", MAXSTR ); else { qstring name; ; tid_t id = ms.idcka[n-1]; struc_t * struc = get_struc(id); if (struc) get_struc_name(&name, id); //asize_t size = get_struc_size(id); qsnprintf(buf, MAXSTR, "%s", name.c_str()); } return buf; }
//---------------------------------------------------------------------------- // gen_snapshot - generate "snapshot" of landscape configuration at a single point in time //---------------------------------------------------------------------------- void gen_snapshot( char *runname, int year, struct image_header out_head, int snapsum, int transsum ) { int row; // row counter int col; // column counter int index; // array index short int struc; // forest structure index char yearstr[10]; // current summary year char outfilename[30]; // output file name // open output file strcpy(outfilename, runname); itoa(year, yearstr, 10); strcat(outfilename, yearstr); strcat(outfilename, ".gis"); // write grid cell information to temporary grids for(row=0; row<maxrow; row++) { for(col=0; col<maxcol; col++) { index=row*maxcol + col; if(buffer[index] == 1) { struc = get_struc(index); temp[index] = (unsigned char)struc; } else { temp[index] = 0; } } } //Added by Ashis 12/28/2012 // write lcc info into temp grid merg_lccSnapshot(); // write grids to output files if (snapsum > 0) { write_grid(outfilename, temp, out_head); } return; }
tid_t type_builder_t::get_structure(char * name) { tid_t struct_type_id = add_struc(BADADDR, name); if (struct_type_id != 0 || struct_type_id != -1) { struc_t * struc = get_struc(struct_type_id); if(struc != NULL) { sort_fields(structure); int offs = 0; opinfo_t opinfo; opinfo.tid = struct_type_id; for(unsigned int i = 0 ; i < structure.size() ; i ++) { if(structure[i].offset > offs) { offs = structure[i].offset; } flags_t member_flgs = 0; if(structure[i].size == 1) member_flgs = byteflag(); else if (structure[i].size == 2) member_flgs = wordflag(); else if (structure[i].size == 4) member_flgs = dwrdflag(); else if (structure[i].size == 8) member_flgs = qwrdflag(); char field_name[258]; memset(field_name, 0x00, sizeof(field_name)); sprintf_s(field_name, sizeof(field_name), "field_%d", i); int iRet = add_struc_member(struc, field_name, structure[i].offset, member_flgs, NULL, structure[i].size); offs += structure[i].size; } } } return struct_type_id; }
tid_t add_class(tid_t tid_of_struc) { //classes are built on top of structures, make sure there is one before continuing if(!get_struc(tid_of_struc)) return BADNODE; if(get_class(tid_of_struc)) { return tid_of_struc; } class_t clas; clas.flags = 0; clas.tid = tid_of_struc; clas.functions_ea.clear(); clas.parents_tid.clear(); clas.virt_table_ea = BADADDR; save_class(&clas); //DONE: add to classes index add_class_at_idx(tid_of_struc, BADNODE); return tid_of_struc; }
bool idaapi check_subtype(VTBL_info_t vtbl_info, qstring subtype_name) { qstring search_str; search_str.sprnt("_%a", vtbl_info.ea_begin); struc_t * struc_type = get_struc(get_struc_id(subtype_name.c_str())); if (!struc_type) return false; // 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) continue; qstring member_name = get_member_name(member_info->id); if (member_name.find(search_str, 0) != member_name.npos) return true; } return false; }
void idaapi dump_type_info(int file_id, VTBL_info_t vtbl_info, qstring type_name, std::map<ea_t, VTBL_info_t> vtbl_map) { tid_t type_id = get_struc_id(type_name.c_str()); if (type_id != BADADDR) { struc_t * struc_type = get_struc(type_id); if(struc_type != NULL) { qstring file_entry_key; qstring key_hash; bool filtered = false; get_struct_key(struc_type, vtbl_info, file_entry_key, filtered, vtbl_map); get_hash_of_string(file_entry_key, key_hash); if (!filtered) { qstring file_entry_val; tinfo_t new_type = create_typedef(type_name.c_str()); if(new_type.is_correct()) { if (new_type.print(&file_entry_val, NULL, PRTYPE_DEF | PRTYPE_1LINE)) { qstring line; line = key_hash + ";" + file_entry_key + ";"; line.cat_sprnt("%p;", vtbl_info.ea_begin); line += file_entry_val + ";"; if (rtti_vftables.count(vtbl_info.ea_begin) != 0) { vftable::vtinfo vi = rtti_vftables[vtbl_info.ea_begin]; line += vi.type_info; } line.rtrim(); line += "\r\n"; qwrite(file_id, line.c_str(), line.length()); } } } } } }
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; //struc_name.append(qstring("_vtbl_struct")); 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; ea_t offset = 0; while (ea < vtbl_addr_end) { offset = ea - vtbl_addr; qstring method_name; #ifndef __EA64__ ea_t method_ea = get_long(ea); // get function ea #else ea_t method_ea = get_64bit(ea); #endif 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 = f_get_short_name(method_ea); // this line crash ida when compare qstring with null if (method_name.length() != 0) { struc_member_name = (char*)method_name.c_str(); } } #ifndef __EA64__ add_struc_member(new_struc, NULL, offset, dwrdflag(), NULL, 4); #else add_struc_member(new_struc, NULL, offset, qwrdflag(), NULL, sizeof(UINT64)); #endif if (struc_member_name) { if (!set_member_name(new_struc, offset, struc_member_name)) { //get_name(NULL, method_ea, method_name, sizeof(method_name)); f_get_ea_name(&method_name, method_ea); set_member_name(new_struc, offset, struc_member_name); } } #ifndef __EA64__ ea = ea + 4; #else ea = ea + sizeof(UINT64); #endif flags_t ea_flags = getFlags(ea); if (has_any_name(ea_flags)) break; } return id; }
std::vector<IDAStructure> GetStructsFromDb() { std::vector<IDAStructure> structures; constexpr size_t bufferSize = 256; std::array<char, bufferSize> buffer; for (auto i = get_first_struc_idx(); i != -1; i = get_next_struc_idx(i)) { IDAStructure newStruct; const struc_t* idaStruct = get_struc(get_struc_by_idx(i)); get_struc_name(idaStruct->id, buffer.data(), bufferSize); newStruct.m_name = std::string(buffer.data()); get_struc_cmt(idaStruct->id, true, buffer.data(), bufferSize); newStruct.m_comment = std::string(buffer.data()); newStruct.m_size = get_struc_size(idaStruct->id); msg("Struct %d = %s (%s) [%d bytes]\n", i, newStruct.m_name.c_str(), newStruct.m_comment.c_str(), newStruct.m_size); size_t offset = 0; member_t* idaStructMember = get_member(idaStruct, offset); while (idaStructMember != nullptr) { IDAStructure::Member newMember; get_member_fullname(idaStructMember->id, buffer.data(), bufferSize); newMember.m_name = std::string(buffer.data()); { tinfo_t typeInfo; get_member_tinfo2(idaStructMember, &typeInfo); qstring typeName; if (typeInfo.get_type_name(&typeName)) { newMember.m_type = std::string(typeName.c_str()); } else { newMember.m_type = "undefined"; } } get_member_cmt(idaStructMember->id, true, buffer.data(), bufferSize); newMember.m_comment = std::string(buffer.data()); newMember.m_size = get_member_size(idaStructMember); offset += newMember.m_size; msg(" %s {%s} (%s) [%d bytes]\n", newMember.m_name.c_str(), newMember.m_type.c_str(), newMember.m_comment.c_str(), newMember.m_size); newStruct.m_members.push_back(std::move(newMember)); idaStructMember = get_member(idaStruct, offset); } structures.push_back(std::move(newStruct)); } return std::move(structures); }