#include #define isRef(F) ((F & FF_REF) != 0) #define hasName(F) ((F & FF_NAME) != 0) static GetVtableSize(a) { auto b,c,f; b = BADADDR; f = GetFlags(a); do { f = GetFlags(a); if (b == BADADDR) //first entry { b=a; if (!(isRef(f) && (hasName(f) || (f&FF_LABL)))) { return 0; } } else if (isRef(f)) //might mean start of next vtable break; if (!hasValue(f) || !isData(f)) break; c = Qword(a); if (c) { f = GetFlags(c); if (!hasValue(f) || !isCode(f) || Dword(c)==0) break; } a = a+8; } while (1); if (b!=BADADDR) { c = (a-b)/8; return c; } else { return 0; } } static Unknown( ea, length ) { auto i; if (ea==BADADDR) return; for(i=0; i < length; i++) { MakeUnkn(ea+i,0); } } static DwordRel(x) { x = Dword(x) + 0x140000000; return x; } static ForceQword( x ) { //Make dword, undefine as needed if (x==BADADDR || x==0) return; if (!MakeQword( x )) { Unknown(x,8); MakeQword(x); } } static ForceDword( x ) { //Make dword, undefine as needed if (x==BADADDR || x==0) return; if (!MakeDword( x )) { Unknown(x,4); MakeDword(x); } } static SoftOff64 ( x ) { //Make 64-bit offset if !=0 if (x==BADADDR || x==0) return; ForceQword(x); if (Qword(x)>0 && Qword(x)<=MaxEA()) OpOff(x, 0, 0); } static SoftOff ( x ) { //Make 32-bit base-relative offset if !=0 if (x==BADADDR || x==0) return; ForceDword(x); if (Dword(x)>0 && Dword(x)<=MaxEA()) OpOffEx(x,0,REF_OFF32|REFINFO_RVA|REFINFO_SIGNEDOP, -1, 0, 0); } //check if pointer is to typeinfo record and extract the type name from it static GetTypeName(vtbl) { auto x; if (vtbl==BADADDR) return; x = DwordRel(vtbl+12); if ((!x) || (x==BADADDR)) return ""; return GetAsciizStr(x+16); } static DwordCmt(x, cmt) { if (x==BADADDR || x==0) return; ForceDword(x); MakeComm(x, cmt); } static OffCmt(x, cmt) { if (x==BADADDR || x==0) return; SoftOff(x); if (cmt != "") MakeComm(x, cmt); } static OffCmt64(x, cmt) { if (x==BADADDR || x==0) return; SoftOff64(x); MakeComm(x, cmt); } static StrCmt(x, cmt) { auto save_str; if (x==BADADDR || x==0) return; MakeUnkn(x, 0); save_str = GetLongPrm(INF_STRTYPE); SetLongPrm(INF_STRTYPE,0); MakeStr(x, BADADDR); MakeName(x, ""); MakeComm(x, cmt); SetLongPrm(INF_STRTYPE,save_str); } static DwordArrayCmt(x, n, cmt) { if (x==BADADDR || x==0) return; Unknown(x,4*n); ForceDword(x); MakeArray(x,n); MakeComm(x, cmt); } //check if values match a pattern static matchBytes(addr,match) { auto i,len,s; len = strlen(match); if (len%2) { Warning("Bad match string in matchBytes: %s",match); return 0; } i=0; while (i 2147483647) x = x - 4294967296; if (x<0) { sign = 1; x = -x; } if (x==0) return "A@"; else if (x<=10) return form("%s%d",sign?"?":"",x-1); else { while (x>0) { s = form("%c%s",'A'+x%16,s); x = x / 16; } return sign?"?":""+s+"@"; } } static Parse_BCD(x, indent) { auto indent_str,i,a,s; if (x==BADADDR || x==0) return; indent_str="";i=0; while(i0) //check numContainedBases DumpNestedClass(a+4, indent+1, n); //nested classes following a=a+4*(n+1); i=i+n+1; } } static Parse_CHD(x, indent) { auto indent_str,i,a,n,p,s; if (x==BADADDR || x==0) return; indent_str="";i=0; while(i ea ) // InSort { for ( ; idx != -1; idx = GetNextIndex(AR_LONG, id, idx) ) { val = GetArrayElement(AR_LONG, id, idx); SetArrayLong(id, idx, ea); ea = val; } } } SetArrayLong(id, GetLastIndex(AR_LONG, id) + 1, ea); } static getArraySize(id) { auto idx, count; count = 0; for ( idx = GetFirstIndex(AR_LONG, id); idx != -1; idx = GetNextIndex(AR_LONG, id, idx) ) { count++; } return count; } static doAddrList(name) { auto idx, id, val, ctr, dtr; id = GetArrayId("AddrList"); ctr = 0; dtr = 0; if ( name!=0 && id != -1 ) { if (getArraySize(id)!=2) return; for ( idx = GetFirstIndex(AR_LONG, id); idx != -1; idx = GetNextIndex(AR_LONG, id, idx) ) { val = GetArrayElement(AR_LONG, id, idx); if (Byte(val)==0xE9) val = getRelJmpTarget(val); if ((substr(Name(val),0,3)=="??1")) dtr = val; else ctr = val; } } if (ctr!=0 && dtr!=0) { MakeName(ctr, MakeSpecialName(name,SN_constructor,0)); } DeleteArray(GetArrayId("AddrList")); } //check if there's a vtable at a and dump into to f //returns position after the end of vtable static DoVtable(a) { auto x,y,s,p,q,i,name; //check if it looks like a vtable y = GetVtableSize(a); if (y == 0) return a+8; //check if it's named as a vtable name = Name(a); if (substr(name,0,4)!="??_7") name=0; x = Qword(a-8); //otherwise try to get it from RTTI if (IsValidCOL(x)) { Parse_Vtable(a); if (name==0) name = GetVtblName(x); MakeName(a, name); } if (name!=0) { name = ".?AV"+substr(name, 4, strstr(name,"@@6B")+2); } { DeleteArray(GetArrayId("AddrList")); q = 0; i = 1; for ( x=DfirstB(a); x != BADADDR; x=DnextB(a,x) ) { p = funcStart(x); if (p!=-1) { if (q==p) i++; else { if (q) { AddAddr(q); } i = 1; q = p; } } } if (q) { AddAddr(q); } x = a; while (y>0) { p = Dword(x); if (GetFunctionFlags(p) == -1) { MakeCode(p); MakeFunction(p, BADADDR); } checkSDD(p,name,a,0); y--; x = x+8; } doAddrList(name); } return x; } static scan_for_vtables(void) { auto rmin, rmax, cmin, cmax, s, a, x, y; s = FirstSeg(); rmin = 0; rmax = 0; while (s!=BADADDR) { if (SegName(s)==".rdata") { rmin = s; rmax = NextSeg(s); } else if (SegName(s)==".text") { cmin = s; cmax = NextSeg(s); } s = NextSeg(s); } if (rmin==0) {rmin=cmin; rmax=cmax;} a = rmin; while (a=cmin && x //74 07 jz short @@no_free //56 push esi //E8 CA 2D 0D 00 call operator delete(void *) //59 pop ecx // @@no_free: //8B C6 mov eax, esi //5E pop esi //C2 04 00 retn 4 t = SN_scalardtr; } else if (matchBytes(x,"538A5C2408568BF1F6C302742B8B46FC578D7EFC68????????506A??56E8") || matchBytes(x,"538A5C2408F6C302568BF1742E8B46FC5768????????8D7EFC5068????????56E8")) { //53 push ebx //8A 5C 24 08 mov bl, [esp+arg_0] //56 push esi //8B F1 mov esi, ecx //F6 C3 02 test bl, 2 //74 2B jz short loc_100037F8 //8B 46 FC mov eax, [esi-4] //57 push edi //8D 7E FC lea edi, [esi-4] //68 xx xx xx xx push offset class::~class(void) //50 push eax //6A xx push xxh //56 push esi //E8 xx xx xx xx call `eh vector destructor iterator'(void *,uint,int,void (*)(void *)) t = SN_vectordtr; if (name!=0) a = Dword(x+21); if (gate && Byte(a)==0xE9) { a = getRelJmpTarget(a); } } if (t>0) { if (t==SN_vectordtr) s = "vector"; else s = "scalar"; if (name!=0) MakeName(x, MakeSpecialName(name,t,0)); if (a!=BADADDR) { if (name!=0) MakeName(a, MakeSpecialName(name,SN_vdestructor,0)); } CommentStack(x, 4, "__flags$",-1); } return t; } static main(void) { scan_for_vtables(); }