// 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 // 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. // 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); 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(FindFuncEnd(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 (GetReg(ea, "T")) return Dword(ea)&~1; else return Dword(ea); } static MakeTable(ea, end, pattern) { auto ofs, i, c, alen, nlen; 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 (ofs0) { MakeArray(ofs, alen); } ofs= ofs+ItemSize(ofs); } else if (c=="w") { nlen= GetNrOfDigits(pattern, i+1); if (nlen) { alen= atol(substr(pattern, i+1,i+nlen+1)); i= i+nlen; } else { alen= -1; } MakeWord(ofs); OpNumber(ofs, 0); if (alen>0) { MakeArray(ofs, alen); } ofs= ofs+ItemSize(ofs); } else if (c=="b") { nlen= GetNrOfDigits(pattern, i+1); if (nlen) { alen= atol(substr(pattern, i+1,i+nlen+1)); i= i+nlen; } else { alen= -1; } MakeByte(ofs); OpNumber(ofs, 0); if (alen>0) { MakeArray(ofs, alen); } ofs= ofs+ItemSize(ofs); } else if (c=="i") { MakeUnkn(ofs, 4); MakeCode(ofs); ofs= ofs+ItemSize(ofs); } else if (c=="o") { if (Dword(ofs)) { 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); ofs= ofs+ItemSize(ofs); } 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); } ofs= ofs+ItemSize(ofs); } else if (c=="a" || c=="A") { nlen= GetNrOfDigits(pattern, i+1); if (nlen) { alen= atol(substr(pattern, i+1,i+nlen+1)); i= i+nlen; } else { alen= -1; } SetLongPrm(INF_STRTYPE, ((Word(ofs)>=0) && (Word(ofs)<0x100) && (c=="A"))?ASCSTR_UNICODE:ASCSTR_TERMCHR); if (alen>=0) { MakeUnknownX(ofs, ofs+alen); MakeStr(ofs, ofs+alen); } else { MakeStr(ofs, -1); alen= ItemSize(ofs); if (alen==1 && Byte(ofs)==0) { MakeByte(ofs); } } ofs= ofs+alen; } else if (c=="l") { nlen= GetNrOfDigits(pattern, i+1); if (nlen) { alen= atol(substr(pattern, i+1,i+nlen+1)); i= i+nlen; } else { alen=2; } Message("Makeing %d alignment %08lx\n", alen, ofs); if (ofs&((1<="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>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