// vim: ft=cpp sw=4 ts=4 et /* (C) 2003-2008 Willem Jan Hengeveld * * Web: http://www.xs4all.nl/~itsme/projects/ida/ */ // // the useful function in this script are: // ParsePdata(); ... will parse the currently selected data as 'pdata' // ( and create functions accordingly ) // FixFunctions(); ... will set the function 'ends' to include the // constant pools at the end of each function, such // that xrefs from there show belonging to this function // Table(pattern); format the current selection as 'pattern' // // fix4033() isolate EdbgVendorIds blocks, in windows ce binaries. // memcmp, memcpy, memset - like the clib functions // summarize_unk create dwords, or byte arrays from undefined area's // // PATTERNS: // a sequence of format characters ( letters ) // followed by a count. // // format specifiers: // o - pointer to data // s - pointer to ascii string // s - pointer to unicode string // d[N] - dword // w[N] - word // b[N] - byte // u[N] - double // f[N] - fload // c - pointer to code // p - pointer to proc ( function ) // A[N] - fixed length or zero terminated ascii or unicode string // a[N] - ascii string // i - instructions // l[N] - align dword, or N: align 1< // commented out, did not work very well. //#include // todo: force creation of functions in ParsePdata // todo: ask user about whether to include data after fn in FixFunctions. // todo: add processor dependend flags, code address alignment. // todo: add settable flags: like ascii+unicode, or only ascii strings, and alignment. // done: add '*' to automatically find the next ref/name // static ParsePdata(ea,end) { auto x, fn, pd; if (ea==BADADDR) { ea=SelStart(); end=SelEnd(); } if (ea==BADADDR) { return; } MakeTable(ea, end, "cd"); x= ea; while (x>6, ((pd&0xffff0)>>6) + fn); MakeFunction(fn, ((pd&0xffff0)>>6) + fn); x=x+8; } } static FixFunctions() { auto next; auto ofs, name; auto f,g; next= 0; f= NextFunction(0); while (f!=BADADDR && (g= NextFunction(f))!=BADADDR) { //analyzefuncframe(f, 1); //todo: think of better condition why it might not be a func. if (g-FindFuncEnd(f) > 0x80) { //Message("function %08lx - %08lx : +%08lx\n", f, g, g-FindFuncEnd(f)); if (f>ScreenEA() && next==0) { next= f; } } else { SetFunctionEnd(f, g); } f= g; } ofs=NextFunction(0); while (ofs!=0xffffffff) { name= GetFunctionName(ofs); if (substr(name, 0, 4)=="sub_" || substr(name, 0, 8)=="nullsub_" || name=="start") SetFunctionFlags(ofs, GetFunctionFlags(ofs)&~FUNC_LIB); else SetFunctionFlags(ofs, GetFunctionFlags(ofs)|FUNC_LIB); ofs= NextFunction(ofs); } if (next) { Jump(PrevHead(NextFunction(next), next)); } else { Message("no more constant pool found\n"); } } static FixJumpCalls() { auto ea,r; ea= NextFunction(0); while (ea!=-1) { r=RfirstB(ea); while (r!=-1) { if (XrefType()!=fl_CF && XrefType()!=fl_CN) { Message("%08lx -> %08lx : %d\n", r, ea, XrefType()); AddCodeXref(r, ea, fl_CN); } r= RnextB(ea,r); } ea= NextFunction(ea); } } static CodeOffset(ea) { if ((Dword(ea)&1) && GetReg(Dword(ea), "T")==0) { SetReg(Dword(ea)&~1, "T", 1); Wait(); } if (GetReg(Dword(ea), "T")) return Dword(ea)&~1; else return Dword(ea); } static MakeTable(ea, end, pattern) { auto ofs, i, c, alen, nlen; auto ofs2; if (ea==0 && end==0) { ea=SelStart(); end=SelEnd(); if (ea==BADADDR) { return; } } if (end==BADADDR) { end= FindExplored(ea, SEARCH_DOWN); } if (end==BADADDR) { end= SegEnd(ea); } if (end==BADADDR) { return; } ofs= ea; i= 0; //Message("making table %08lx-%08lx %s\n", ea, end, pattern); while (ofs1?alen:4); MakeCode(ofs); } else if (c=="o") { if (Dword(ofs) && SegStart(Dword(ofs))!=BADADDR) { OpOff(ofs, 0, 0); } else { MakeDword(ofs); } // ??? somehow sometimes ida forgets to create a xref if (Dfirst(ofs)!=Dword(ofs)) add_dref(ofs, Dword(ofs), dr_O); } else if (c=="s" || c=="S") { if (Dword(ofs)) { SetLongPrm(INF_STRTYPE, ((Word(Dword(ofs))>=0) && (Word(Dword(ofs))<0x100) && (c=="S"))?ASCSTR_UNICODE:ASCSTR_TERMCHR); OpOff(ofs, 0, 0); MakeUnkn(Dword(ofs),1); MakeStr(Dword(ofs), -1); } else { MakeDword(ofs); } } else if (c=="a" || c=="A") { // if at ofs there are at 2 unicode chars in the ascii set then str is unicode SetLongPrm(INF_STRTYPE, ((Word(ofs)>=0) && (Word(ofs)<0x100 && Word(ofs+2)>0 && Word(ofs+2)<0x100) && (c=="A"))?ASCSTR_UNICODE:ASCSTR_TERMCHR); if (alen>=1) { MakeUnknownX(ofs, ofs+alen); MakeStr(ofs, ofs+alen); } else if (alen==0) { // no length specified: look for terminating NUL MakeStr(ofs, -1); alen= ItemSize(ofs); if (alen==1 && Byte(ofs)==0) { // empty string MakeByte(ofs); } } else { // ... todo, think of action for 'a*' } } else if (c=="l") { //Message("Makeing %d alignment %08lx\n", alen, ofs); if (ofs&((1<1) MakeArray(ofs, alen); } //Message("%08lx:c=%s alen=%d isize=%d\n", ofs, c, alen, ItemSize(ofs)); if (ItemSize(ofs)==0) break; if (c!="l" || isAlign(GetFlags(ofs))) ofs= ofs+ItemSize(ofs); i= i+1; if (i==strlen(pattern)) { i= 0; } } } static findnext_ref_or_name(ea) { auto end; end= NextHead(ea, SegEnd(ea)); if (end==BADADDR) return BADADDR; ea=NextAddr(ea); while (ea="0" && c<="9"; } static isxdigit(c) { return isdigit(c) || (c>="a" && c<="f") || (c>="A" && c<="F"); } static CheckEmpty(ea, end) { auto ofs, b, p; for (ofs=ea ; ofs=0) { return GetString(ea, -1,t); } else { s=""; while(b=Byte(ea)) { s=s+form("%c", b); ea=ea+1; } return s; } } static WString(ea) { auto s,w; s=""; while(w=Word(ea)) { s=s+form("%c", w); ea=ea+2; } return s; } static MakeGuid(ea) { auto s,suffix; s=form("DGUID {%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", Dword(ea), Word(ea+4), Word(ea+6), Byte(ea+8), Byte(ea+9), Byte(ea+10), Byte(ea+11), Byte(ea+12), Byte(ea+13), Byte(ea+14), Byte(ea+15)); MakeUnknownX(ea, ea+16); MakeByte(ea); MakeArray(ea, 16); SetManualInsn(ea, s); if (!hasUserName(GetFlags(ea))) { suffix=0; while (!MakeNameEx(ea, form("guid_%08lx_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x%s", Dword(ea), Word(ea+4), Word(ea+6), Byte(ea+8), Byte(ea+9), Byte(ea+10), Byte(ea+11), Byte(ea+12), Byte(ea+13), Byte(ea+14), Byte(ea+15), suffix?form("_%d",suffix):""), SN_NOWARN)) { suffix=suffix+1; } } } // auto ea, o, s; // ea=SelStart(); // while (ea>8)&0xff, (dw>>16)&0xff, (dw>>24)&0xff); } // changes exception handler data from instruction to dwords. static fix_exccalls(dw) { auto ea,str; str= dword_to_findstr(dw); ea= FindBinary(0, SEARCH_DOWN, str); while (ea!=BADADDR) { MakeUnkn(ea, 1); MakeDword(ea); OpNumber(ea, 0); MakeArray(ea,2); ea= FindBinary(ea+8, SEARCH_DOWN, str); } } // these functions allow you to peek at the internals of IDA. static lpeek(ea) { return _peek(ea) | (_peek(ea+1)<<8) | (_peek(ea+2)<<16) | (_peek(ea+3)<<24); } static peekstring(ea) { auto s,b; s=""; while(b=_peek(ea)) { s=s+form("%c", b); ea=ea+1; } return s; } static memset(ea, v, len) { auto vvvv; vvvv= (v)|(v<<8)|(v<<16)|(v<<24); while (len && (ea&3)) { PatchByte(ea++, v); --len; } while (len>=4) { PatchDword(ea, vvvv); ea=ea+4; len=len-4; } while (len--) { PatchByte(ea++, v); } } static memcpy(dst, src, len) { if ((dst&3)==(src&3)) { while (len && (dst&3)) { PatchByte(dst++, Byte(src++)); --len; } while (len>=4) { PatchDword(dst, Dword(src)); dst=dst+4; src=src+4; len=len-4; } while (len--) { PatchByte(dst++, Byte(src++)); } } else if ((dst&1)==(src&1)) { while (len && (dst&1)) { PatchByte(dst++, Byte(src++)); --len; } while (len>=2) { PatchWord(dst, Word(src)); dst=dst+2; src=src+2; len=len-2; } while (len--) { PatchByte(dst++, Byte(src++)); } } else { while (len--) { PatchByte(dst++, Byte(src++)); } } } static memcmp(eal, ear, len) { while (len && Byte(eal)==Byte(ear)) { --len; ++eal; ++ear; } if (len==0) return 0; else if (Byte(eal)Byte(ear)) return 1; else return 0; } // creates arrays from 0, 0x4033, 0x444101, ... sequences. static fix4033() { auto ea; ea=0; while (1) { ea= FindBinary(ea, 0x23, "00 00 00 00 33 40 00 00 01 41 44 00") ; if (ea==BADADDR) break; Message("%08lx 4033 sequence\n", ea); MakeUnknownX(ea, ea+36*4); MakeDword(ea); MakeArray(ea, 36); ExtLinA(ea, 0, ""); ExtLinA(ea, 1, ""); ExtLinB(ea, 0, ""); ExtLinB(ea, 1, ""); } ea=0; while (1) { ea= FindBinary(ea, 0x23, "85E0B100 11D104FA A000DAB7 D64803C9") ; if (ea==BADADDR) break; Message("%08lx 85e0b100 sequence\n", ea); MakeUnknownX(ea, ea+16); MakeDword(ea); MakeArray(ea, 4); ExtLinA(ea, 0, ""); ExtLinA(ea, 1, ""); ExtLinB(ea, 0, ""); ExtLinB(ea, 1, ""); } } static hexdump(ea, n) { auto s, i; s= ""; for (i=0 ; i