Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
- ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
- DumpInfo.IDC v0.0.0 By: J.C. Roberts <freeware>
- ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
- The idea behind DumpInfo was to dump only _user_ created information from the disassembly into
- text a file for your notes or into and IDC script for porting to a new disassembly. Since the
- accuracy of IDA is constantly improving, sometimes the only thing I've wanted to save are my
- comments and names from an old disassembly and just let a newer version of IDA do what it does
- best when creating a new disassembly.
- Unfortunately, a lot of automatically created names, comments and such are maked as _user_
- created rather than auto-generated. I've worked around this where possible by using filters.
- I hope you find it useful.
- -JCR
- ----------------------------------------------------------------------------------------------------
- Features:
- --> The scope of operation is user defined.
- 1.) The Entire Disassembly.
- 2.) Currently Selected Area.
- 3.) A Single Segment. //If you've ever screwed up your segmentation...
- 4.) A Single Function.
- --> It can export the following types of IDA information:
- 1.) Regular Function Comments
- 2.) Repeatable Function Comments
- 3.) Regular Indented Comments
- 4.) Repeatable Indented Comments
- 5.) Anterior Lines
- 6.) Posterior lines
- 7.) User Defined Names
- 8.) Code String References (Not Exported To IDC Format)
- 9.) Data String References
- --> It can write the output to either a file or the message window in case you just want
- to quicky see what's in an area rather than save the information.
- --> It can create two different types of output, either simple text or an IDC script for
- reimporting the information into a new disassembly.
- --> Since dumping information from the entire data base can take some time, I've incorporated a
- simple progress meter, so you know what's happening. Even the IDC files that this produces for
- porting your info into a new disassembly have a progress indicator of sorts.
- --> I've done what I can for the speed of this thing but it's just a first draft. I'll probably
- optimize it further in future revisions.
- ----------------------------------------------------------------------------------------------------
- Usage:
- There are defined options (OPT_...) and defined types (TYP_...). The OPTions are used to either
- allow of disallow specific info from being written as well as where (file or message window) and
- how (as IDC or simple text). You can control the options in main() by commenting out the info
- you don't want. On the other hand, the TYPes are used during the program execution to tell the
- writeLine() function _WHAT_ kind of info it's supposed to write so it can decide _HOW_ it will
- be written.
- Decide if you want a file written - OPT_MAK_FILE
- Decide the if you want an IDC script or a text file - OPT_IDC_FILE
- Decide what kind of info you want dumped - All the rest :)
- Comments:
- OPT_REG_FCOM - Regular Function Comments (Reg FCom)
- OPT_RPT_FCOM - Repeatable Function Comments (Rpt FCom)
- OPT_REG_ICOM - Regular Indented Comments (Reg ICom)
- OPT_RPT_ICOM - Repeatable Indented Comments (Rep ICom)
- Lines:
- OPT_ANT_LINE - Anterior Lines (AntLn#X)
- OPT_POS_LINE - Posterior Lines (PosLn#X)
- Names:
- OPT_USR_NAME - User Names (Non-Autogenerated) (UserName)
- Strings:
- OPT_STR_CODE - String References From Code (Operand = Offset) (StrCodeX)
- OPT_STR_DATA - String References In Data (Str Data)
- The text files created are marked the information type with the text shown above in parenthesis
- where the "X" is a number. On lines the number represents the Anterior/Posterior line number. On
- string references from code, the "X" number represents the operand where the data was found.
- All string gathering is based on the NAME of the string. If the name of the string doesn't start
- with the default "a" or the more useful "str_" it will not be found. Since I couldn't figure out
- how to get the string prefix from the IDA settings in IDA.CFG (assuming it's even possible), we
- are stuck with the hard coded prefixes above and you'll need to change them if you use a
- different prefix.
- Sting references from code are not included in IDC files, since there's no point in it.
- ----------------------------------------------------------------------------------------------------
- Annoyances & Work-Arounds:
- 0.) There's no way that I've found to REALLY differentiate between USER created and script/IDA
- created comments, names et al... I'm still looking for a way. Until I figure it out
- (assuming it's actually possible), we're stuck with _ALL_ non-autogenerated comments, names,
- lines & etc... Major Bummer!
- Using the FF_NAME, FF_COMM and FF_LINE flags still results in tons of stuff that was either
- autogenerated during the disassembly or created via other IDC scripts.
- I've dealt with this by using a (slow) string filter, xFiter(), to look for the commonly
- created strings. This filter can be shut off in main() via the OPT_USE_FLTR. The function
- is set for win32 stuff, so you may need to edit it as you see fit.
- THERE ARE SOME SERIOUS DISADVANTAGES TO USING A TEXT FILTER TO IGNORE SPECIFIC TEXT
- PATTERNS, SO BE AWARE OF WHAT TEXT STRINGS WILL BE FILTERED OUT...
- 1.) You may get a "varriable not defined" error on IDA_STATUS_WORK or IDA_STATUS_READY if your
- IDC.IDC hasn't been updated. There was a missing #endif/#ifdef pair in the v4.1.4 release.
- It should read:
- #endif
- #define IDA_STATUS_READY 0 // READY IDA is idle
- #define IDA_STATUS_THINKING 1 // THINKING Analyzing but the user may press keys
- #define IDA_STATUS_WAITING 2 // WAITING Waiting for the user input
- #define IDA_STATUS_WORK 3 // BUSY IDA is busy
- #ifdef _notdefinedsymbol
- 2.) The FindA() function has a bug on lines greater than 999, so getting more anterior lines
- than that isn't possible even though the MAX_ITEM_LINES value set in IDA.CFG is 5000. Also,
- there's currently no way to read the MAX_ITEM_LINES value set by IDA.CFG -In a nutshell, if
- you have more than 999 Anterior Lines on a single EA, then you're hosed.
- The Ant/Pos Line loop is hard coded to read from 0 to 999. If we're ever able to get the
- info from IDA.CFG and the LineA() gets fixed, I'll have to recode things to access the full
- number of lines.
- 3.) Both FindA() and FindB() return 0 (Failure) if a line contains nothing more than a
- NewLine (/n). I've gotten around this problem by using a reverse counter from 999 to 0
- to find the last line with any text. If empty lines are used at the end (the higher line
- numbers) of an Anterior or posterior comment, they are not read and/or saved. The reverse
- counter is necessary because if you have text on line #1 and nothing on line #0 then import
- only Line #1 and not the empty Line #0, the line with text is not visible.
- 4.) There's a 64K limit to main(), so I used the same type of IDC stucture as Ilfak does when
- creating the IDC file from the "Dump Database to IDC" menu function. e.g.
- main(){ parts();}
- part_0() { }
- part_1() { }
- part_X...
- parts() { part_0(); part_1(); partX... }
- I've got it set so each part_X has 1000 instruction lines but this could be increased.
- ----------------------------------------------------------------------------------------------------
- Future Plans:
- 1.) Make a decent UI for entering options rather than (un)commenting lines.
- 2.) Add a BaseAddress0/AskBase/ChooseFunction kind of thing, so you can port comments to specific
- places in the new disassembly. It would be real a useful addition for restoring _ALL_ your
- comments when you're dealing with a new version of an executable or you've augmented the
- line by line comments of a FLIRT recognized function or library.
- 3.) Figure out how to write this as a plugin -It might be faster that way and make it easier for
- adding plan #1.
- ----------------------------------------------------------------------------------------------------
- Bugs: -Tested On IDA Version 4.1.4.483 (With Fixes)
- No Known Bugs... :)
- ----------------------------------------------------------------------------------------------------
- Revisions:
- 2000.10.17 First Version v0.0.0
- ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
- //__________________________________________________________________________________________________
- //ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
- // Start Code
- //--------------------------------------------------------------------------------------------------
- #include <idc.idc>
- #define FALSE 0
- #define TRUE 1
- #define OPT_MAK_FILE 0x00000001L // Write to file - OR - Write to message window
- #define OPT_IDC_FILE 0x00000002L // Create IDC file - OR - Create text file.
- #define OPT_USE_FLTR 0x00000004L // Use Text Filter
- #define OPT_REG_FCOM 0x00000010L // Regular Function Comments
- #define OPT_RPT_FCOM 0x00000020L // Repeatable Function Comments
- #define OPT_REG_ICOM 0x00000040L // Regular Indented Comments
- #define OPT_RPT_ICOM 0x00000080L // Repeatable Indented Comments
- #define OPT_ANT_LINE 0x00000100L // Anterior Lines
- #define OPT_POS_LINE 0x00000200L // Posterior Lines
- #define OPT_USR_NAME 0x00000400L // User Names (Non-Autogenerated)
- #define OPT_STR_CODE 0x00000800L // String References From Code (Operand = Offset)
- #define OPT_STR_DATA 0x00001000L // String References In Data
- #define TYP_REG_FCOM 0x00010000L // Regular Function Comments
- #define TYP_RPT_FCOM 0x00020000L // Repeatable Function Comments
- #define TYP_REG_ICOM 0x00040000L // Regular Indented Comments
- #define TYP_RPT_ICOM 0x00080000L // Repeatable Indented Comments
- #define TYP_ANT_LINE 0x00100000L // Anterior Lines
- #define TYP_POS_LINE 0x00200000L // Posterior Lines
- #define TYP_USR_NAME 0x00400000L // User Names (Non-Autogenerated)
- #define TYP_STR_CODE 0x00800000L // String References From Code (Operand = Offset)
- #define TYP_STR_DATA 0x01000000L // String References In Data
- //__________________________________________________________________________________________________
- //ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
- // FUNCTION: char* xFilter(char *)
- //--------------------------------------------------------------------------------------------------
- // Purpose: To find and remove commonly autogenerated comments and names.
- //
- // NOTES:
- // I did what I could for the speed of this thing but string work is slow by nature.
- //
- //--------------------------------------------------------------------------------------------------
- static xFilter(xTxt) {
- auto xTmp;
- xTmp = substr(xTxt, 0, 1);
- // Length 1
- if (xTmp == "_") xTxt = FALSE; //NAME: stdlib
- else if (xTmp == "?") xTxt = FALSE; //NAME: libs
- else xTmp = substr(xTxt, 0, 2);
- // Length 2
- if (xTxt != FALSE) {
- if (xTmp == "lp") xTxt = FALSE; //COMMENT:
- else if (xTmp == "dw") xTxt = FALSE; //COMMENT:
- else if (xTmp == "fl") xTxt = FALSE; //COMMENT:
- else if (xTmp == "j_") xTxt = FALSE; //NAME: jump subs
- else xTmp = substr(xTxt, 0, 3);
- }
- // Length 3
- if (xTxt != FALSE) {
- if (xTmp == "int") xTxt = FALSE; //COMMENT:
- else if (xTmp == "int") xTxt = FALSE; //COMMENT:
- else if (xTmp == "cch") xTxt = FALSE; //COMMENT:
- else if (xTmp == "Msg") xTxt = FALSE; //COMMENT:
- else if (xTmp == "unk") xTxt = FALSE; //NAME: unkown_libname
- else if (xTmp == "HDC") xTxt = FALSE; //COMMENT: HDC
- else xTmp = substr(xTxt, 0, 4);
- }
- // Length 4
- if (xTxt != FALSE) {
- if (xTmp == "hWnd") xTxt = FALSE; //COMMENT:
- else if (xTmp == "void") xTxt = FALSE; //COMMENT:
- else if (xTmp == "char") xTxt = FALSE; //COMMENT:
- else if (xTmp == "hPre") xTxt = FALSE; //COMMENT:
- else if (xTmp == "case") xTxt = FALSE; //COMMENT:
- else if (xTmp == "hMem") xTxt = FALSE; //COMMENT:
- else if (xTmp == "hKey") xTxt = FALSE; //COMMENT:
- else if (xTmp == "yBot") xTxt = FALSE; //COMMENT: yBot
- else if (xTmp == "xRig") xTxt = FALSE; //COMMENT: xRig
- else if (xTmp == "yTop") xTxt = FALSE; //COMMENT: yTop
- else if (xTmp == "xLef") xTxt = FALSE; //COMMENT: xLef
- else if (xTmp == "wMsg") xTxt = FALSE; //COMMENT: wMsg
- else if (xTmp == "UINT") xTxt = FALSE; //COMMENT:
- else if (xTmp == "hRes") xTxt = FALSE; //COMMENT: hRes
- else if (xTmp == "hDlg") xTxt = FALSE; //COMMENT: hDlg
- else if (xTmp == "hCtl") xTxt = FALSE; //COMMENT: hCtl
- else if (xTmp == "uCmd") xTxt = FALSE; //COMMENT: uCmd
- else if (xTmp == "iMax") xTxt = FALSE; //COMMENT: iMax
- else xTmp = substr(xTxt, 0, 5);
- }
- // Length 5
- if (xTxt != FALSE) {
- if (xTmp == "hHeap") xTxt = FALSE; //COMMENT:
- else if (xTmp == "hData") xTxt = FALSE; //COMMENT:
- else if (xTmp == "const") xTxt = FALSE; //COMMENT:
- else if (xTmp == "hInst") xTxt = FALSE; //COMMENT:
- else if (xTmp == "uExit") xTxt = FALSE; //COMMENT:
- else if (xTmp == "hProc") xTxt = FALSE; //COMMENT:
- else if (xTmp == "hFile") xTxt = FALSE; //COMMENT:
- else if (xTmp == "nSize") xTxt = FALSE; //COMMENT:
- else if (xTmp == "uType") xTxt = FALSE; //COMMENT: UINT
- else if (xTmp == "hMenu") xTxt = FALSE; //COMMENT: hMenu
- else if (xTmp == "nBuff") xTxt = FALSE; //COMMENT: nBuff
- else if (xTmp == "nFile") xTxt = FALSE; //COMMENT: nFile
- else if (xTmp == "nVolu") xTxt = FALSE; //COMMENT: nVolu
- else if (xTmp == "hFind") xTxt = FALSE; //COMMENT: hFind
- else xTmp = substr(xTxt, 0, 6);
- }
- // Length 6
- if (xTxt != FALSE) {
- if (xTmp == "hModul") xTxt = FALSE; //COMMENT:
- else if (xTmp == "hObjec") xTxt = FALSE; //COMMENT:
- else if (xTmp == "hHandl") xTxt = FALSE; //COMMENT:
- else if (xTmp == "nStdHa") xTxt = FALSE; //COMMENT:
- else if (xTmp == "nIndex") xTxt = FALSE; //COMMENT:
- else if (xTmp == "CodePa") xTxt = FALSE; //COMMENT:
- else if (xTmp == "uNumbe") xTxt = FALSE; //COMMENT:
- else if (xTmp == "uFlags") xTxt = FALSE; //COMMENT: uFlags
- else if (xTmp == "switch") xTxt = FALSE; //COMMENT:
- else if (xTmp == "Locale") xTxt = FALSE; //COMMENT:
- else if (xTmp == "lParam") xTxt = FALSE; //COMMENT:
- else if (xTmp == "wParam") xTxt = FALSE; //COMMENT:
- else if (xTmp == "size_t") xTxt = FALSE; //COMMENT:
- else if (xTmp == "nullsu") xTxt = FALSE; //NAME: nullsub
- else if (xTmp == "nNumer") xTxt = FALSE; //COMMENT:
- else if (xTmp == "nNumbe") xTxt = FALSE; //COMMENT: nNumbe
- else if (xTmp == "nDenom") xTxt = FALSE; //COMMENT:
- else if (xTmp == "LPSIZE") xTxt = FALSE; //COMMENT: LPSIZE
- else if (xTmp == "LPCSTR") xTxt = FALSE; //COMMENT: LPCSTR
- else if (xTmp == "LPPOIN") xTxt = FALSE; //COMMENT: LPPOIN
- else if (xTmp == "COLORR") xTxt = FALSE; //COMMENT: COLORR
- else if (xTmp == "hSourc") xTxt = FALSE; //COMMENT: hSourc
- else if (xTmp == "hTarge") xTxt = FALSE; //COMMENT: hTarge
- else if (xTmp == "lDista") xTxt = FALSE; //COMMENT: lDista
- else if (xTmp == "uBytes") xTxt = FALSE; //COMMENT: uBytes
- else if (xTmp == "HGDIOB") xTxt = FALSE; //COMMENT: HGDIOB
- else if (xTmp == "bEnabl") xTxt = FALSE; //COMMENT: bEnabl
- else if (xTmp == "wRemov") xTxt = FALSE; //COMMENT: wRemov
- else if (xTmp == "LPVOID") xTxt = FALSE; //COMMENT: LPVOID
- // else if (xTmp == "jump t") xTxt = FALSE; //COMMENT: jump table
- }
- return xTxt;
- }
- //__________________________________________________________________________________________________
- //ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
- //FUNCTION: writeLine(long oOption, handle oFileH, long oEA, char* oTxt, long oNum, long oLineX)
- //--------------------------------------------------------------------------------------------------
- //PURPOSE: Write formated information to file. Returns number of the line it wrote.
- //--------------------------------------------------------------------------------------------------
- //NOTES:
- // oOption - (long) Holds OPTion and TYPe information.
- // oFileH - (file*) File handle
- // oEA - (long) Current Effective Address
- // oTxt - (char*) Text info from the EA
- // oNum - (long) General Number
- // Used for Line Number in Anterior & Posterior Lines.
- // Used for FIRST _OR_ SECOND Operand in x_STR_CODE
- // Used for String Length in x_STR_DATA
- // oLineX - (long) Information Line Number of Output File
- //
- // outTxt - (char*) Text to be written to file. (Also used in part_X and killing /n)
- // oTypTxt - (char*) Use in text files to show information Type.
- // oTxtPos - (long) Position in character array.
- // oMsg -
- //
- //----------------------------------------------------------------------------------------------------
- static writeLine(oOption, oFileH, oEA, oTxt, oNum, oLineX) {
- auto outTxt, oTypTxt, oTxtPos, oMsg;
- //Create "part_X()" subs.
- if (oOption & OPT_IDC_FILE) {
- if ((oLineX%1000) == 0) { //Test 1000 Printed Lines
- if ((oLineX/1000)==0) outTxt = ""; //Test First run of loop.
- else outTxt = form("}\n\n"); //Close Previous part_X sub
- outTxt = outTxt + form("\nstatic part_%d() {\n",(oLineX/1000)); //Create New part_X sub
- fprintf(oFileH, outTxt);
- }
- }
- //Parse Input String For "\n" New Line
- oTxtPos = 1;
- outTxt = oTxt;
- while(oTxtPos != -1) {
- oTxtPos = strstr(oTxt,"\n"); //Find NewLine
- if (oTxtPos != -1) {
- outTxt = substr(oTxt,0,oTxtPos); //Get Text up to NewLine
- outTxt = outTxt + "\\n"; //Append Text "\n"
- outTxt = outTxt + substr(oTxt,(oTxtPos+1),strlen(oTxt)); //Append Rest of String
- }
- oTxt = outTxt; //Rewite Original String
- }
- //Create IDC string
- if (oOption & OPT_IDC_FILE) {
- if (oOption & TYP_REG_FCOM) { //Regular Function Comment
- outTxt = form("\tSetFunctionCmt(0x%s, \"%s\", 0);\n", ltoa(oEA,16), oTxt);
- } else if (oOption & TYP_RPT_FCOM) { //Repeatable Function Comm.
- outTxt = form("\tSetFunctionCmt(0x%s, \"%s\", 1);\n", ltoa(oEA,16), oTxt);
- } else if (oOption & TYP_REG_ICOM) { //Regular Indented Comment
- outTxt = form("\tMakeComm(0x%s, \"%s\");\n", ltoa(oEA,16), oTxt);
- } else if (oOption & TYP_RPT_ICOM) { //Repeatable Indented Comm.
- outTxt = form("\tMakeRptCmt(0x%s, \"%s\");\n", ltoa(oEA,16), oTxt);
- } else if (oOption & TYP_ANT_LINE) { //Anterior Lines
- outTxt = form("\tExtLinA(0x%s, %d, \"%s\");\n", ltoa(oEA,16), oNum, oTxt);
- } else if (oOption & TYP_POS_LINE) { //Posterior Lines
- outTxt = form("\tExtLinB(0x%s, %d, \"%s\");\n", ltoa(oEA,16), oNum, oTxt);
- } else if (oOption & TYP_USR_NAME) { //User Defined Names
- outTxt = form("\tMakeName(0x%s, \"%s\");\n", ltoa(oEA,16), oTxt);
- // } else if (oOption & TYP_STR_CODE) { //Strings From Code
- } else if (oOption & TYP_STR_DATA) { //Strings in Data
- outTxt = form("\tMakeStr(0x%s, 0x%s);\n",ltoa(oEA,16),ltoa((oEA+oNum),16));
- }
- //Create TEXT string
- } else {
- if (oOption & TYP_REG_FCOM) oTypTxt = "(Reg FCom)";
- else if (oOption & TYP_RPT_FCOM) oTypTxt = "(Rpt FCom)";
- else if (oOption & TYP_REG_ICOM) oTypTxt = "(Reg ICom)";
- else if (oOption & TYP_RPT_ICOM) oTypTxt = "(Rep ICom)";
- else if (oOption & TYP_ANT_LINE) oTypTxt = "(AntLn#";
- else if (oOption & TYP_POS_LINE) oTypTxt = "(PosLn#";
- else if (oOption & TYP_USR_NAME) oTypTxt = "(UserName)";
- else if (oOption & TYP_STR_CODE) oTypTxt = "(StrCode";
- else if (oOption & TYP_STR_DATA) oTypTxt = "(Str Data)";
- if ((oOption & TYP_ANT_LINE) || (oOption & TYP_POS_LINE)) {
- outTxt = form("%a %s%2d)\t%s\n", oEA, oTypTxt, oNum, oTxt);
- }else if (oOption & TYP_STR_CODE) {
- outTxt = form("%a %s%d)\t%s\n", oEA, oTypTxt, oNum, oTxt);
- }else if (oOption & TYP_STR_DATA) {
- outTxt = form("%a %s\t%s\n", oEA, oTypTxt, oTxt);
- }else outTxt = form("%a %s\t%s\n", oEA, oTypTxt, oTxt);
- }
- //Output to File
- if (oOption & OPT_MAK_FILE) {
- fprintf(oFileH, outTxt);
- //Output to Message Window
- } else {
- Message (outTxt);
- }
- oLineX++;
- return oLineX;
- }
- //__________________________________________________________________________________________________
- //ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
- //FUNCTION: findInfo(lonh fOption, handle fFile, long fCurEA, long fEndEA)
- //--------------------------------------------------------------------------------------------------
- //PURPOSE: To find, retrieve and sometimes format the desired information.
- //--------------------------------------------------------------------------------------------------
- //NOTES:
- // fOption - (long) Holds option and type info
- // fFileH - (handle) File Handle
- // fCurEA - (long) Starting/Current EA
- // fEndEA - (long) Ending EA
- //
- // i, j, k - (long?) Counters
- // fSrtEA - (long) Starting EA
- // fTmpEA - (long) Temporary EA used for gathering string bytes.
- // fTxt - (char*) Holds String to be written
- // fNum - (long) Holds Ant/Pos Line #, _OR_ 1st/2nd Operand _OR_ Length of String
- // fFlags - (long) Holds the flags for the current EA
- // fLineX - (long) Number of written lines.
- // ProgNum - (long) Progress Number
- // ProgPer - (long) Progress Percent (5%)
- // ProgDot - (long) Progress * Mark (1%)
- //--------------------------------------------------------------------------------------------------
- static findInfo(fOption, fFileH, fCurEA, fEndEA) {
- auto i, j, k, fSrtEA, fTmpEA, fNum, fTxt, fFlags, fLineX, ProgNum, ProgPer, ProgDot;
- SetStatus(IDA_STATUS_WORK); //Set Status: 'Busy'
- ProgPer = 4; //Initial Percent
- ProgDot = 0;
- Message("\nPercent Complete: 0 ");
- fSrtEA = fCurEA; //Save Start for %Prog
- fNum = 0;
- fLineX = 0;
- while ( (fCurEA != BADADDR) && (fCurEA < fEndEA) ) {
- fFlags = GetFlags(fCurEA);
- if ( (fFlags & FF_COMM) || (fFlags & FF_LINE) || (fFlags & FF_NAME) ||\
- (fFlags & FF_0OFF) || (fFlags & FF_1OFF)) { //Big IF
- for (i=0; i < 10; i++) {
- fOption = fOption & 0x0000FFFFL; //Clear BitMask
- fTxt = FALSE; //Clear Text
- fNum = 0;
- //Type 0: Regular Function Comment
- if ( (i==0) && (fOption & OPT_REG_FCOM)) {
- if (fFlags & FF_FUNC) {
- fOption = fOption + TYP_REG_FCOM; //Set Type
- fTxt = GetFunctionCmt(fCurEA, 0); //Get Comment
- }
- //Type 1: Repeatable Function Comment
- }else if ( (i==1) && (fOption & OPT_RPT_FCOM) ) {
- if (fFlags & FF_FUNC) {
- fOption = fOption + TYP_RPT_FCOM; //Set Type
- fTxt = GetFunctionCmt(fCurEA, 1); //Get Comment
- }
- //Type 2: Regular Indented Comment
- }else if ( (i==2) && (fOption & OPT_REG_ICOM) ){
- if (fFlags & FF_COMM) {
- fOption = fOption + TYP_REG_ICOM; //Set Type
- fTxt = Comment(fCurEA); //Get Comment
- }
- //Type 3: Repeatable Indented Comment
- }else if ( (i==3) && (fOption & OPT_RPT_ICOM)) {
- if (fFlags & FF_COMM) {
- fOption = fOption + TYP_RPT_ICOM; //Set Type
- fTxt = RptCmt(fCurEA); //Get Comment
- }
- //Type 4: Anterior Line
- }else if ( (i==4) && (fOption & OPT_ANT_LINE) ){
- if (fFlags & FF_LINE) {
- fOption = fOption + TYP_ANT_LINE; //Set Type
- for (k=998; k >=0; k--) if (LineA(fCurEA,k)!="") break; //Find Last Line
- for(j=0;j <= k; j++) { //LineA() bug >1000t
- fTxt = LineA(fCurEA, j); //Get Ant Line j
- fLineX = writeLine(fOption, fFileH, fCurEA, fTxt, j, fLineX);
- }
- }
- //Type 5: posterior Line
- }else if ( (i==5) && (fOption & OPT_POS_LINE) ){
- if (fFlags & FF_LINE) {
- fOption = fOption + TYP_POS_LINE; //Set Type
- for (k=998; k >=0; k--) if (LineB(fCurEA,k)!="") break; //Find Last Line
- for(j=0;j <= k; j++) { //Get All Lines
- fTxt = LineB(fCurEA, j); //Get Pos Line j
- fLineX = writeLine(fOption, fFileH, fCurEA, fTxt, j, fLineX);
- }
- }
- //Type 6: User Defined Names
- }else if ( (i==6) && (fOption & OPT_USR_NAME) ){
- if (fFlags & FF_NAME) {
- fOption = fOption + TYP_USR_NAME; //Set Type
- fTxt = Name(fCurEA); //Get Name
- }
- //Type 7: String References in CODE Opnd0
- }else if ( (i==7) && (fOption & OPT_STR_CODE) ){
- //isCode(F) // is code byte?
- if (fFlags & FF_0OFF) { //Test First Operand
- fTxt = GetOpnd(fCurEA,0); //Get 1st Op Name
- if ((substr(fTxt,0,11) == "offset str_") || \
- (substr(fTxt,0,8) == "offset a")) {
- fTxt = substr(fTxt,7,-1); //Trim "offset "
- fOption = fOption + TYP_STR_CODE; //Set Type
- fTmpEA = LocByName(fTxt); //Get String EA
- fNum = ItemSize(fTmpEA); //Get String Length
- fTxt = form("\""); //Add Quote (")
- for (j=0; j<=fNum; j++) { //Get Each Str Byte
- fTxt = fTxt + byteValue(GetFlags(fTmpEA)); //Append Byte to Str
- fTmpEA = fTmpEA + 1; //Inc EA by 1 Byte
- }
- fTxt = fTxt + form("\""); //Add End Quote (")
- fNum = 0; //Set num for Code0
- }else fTxt = FALSE; //Delete if not Str
- if (fOption & OPT_IDC_FILE) fTxt = FALSE; //Delete if IDC
- }
- //Type 7: String References in CODE Opnd1
- }else if ( (i==8) && (fOption & OPT_STR_CODE) ){
- if (fFlags & FF_1OFF) { //Test Second Opernd
- fTxt = GetOpnd(fCurEA,1); //Get 2nd Op Name
- if ((substr(fTxt,0,11) == "offset str_") || \
- (substr(fTxt,0,8) == "offset a")) {
- fTxt = substr(fTxt,7,-1); //Trim "offset "
- fOption = fOption + TYP_STR_CODE; //Set Type
- fTmpEA = LocByName(fTxt); //Get String EA
- fNum = ItemSize(fTmpEA); //Get String Length
- fTxt = form("\""); //Add Quote (")
- for (j=0; j<=fNum; j++) { //Get Each Str Byte
- fTxt = fTxt + byteValue(GetFlags(fTmpEA)); //Append Byte to Str
- fTmpEA = fTmpEA + 1; //Inc EA by 1 Byte
- }
- fTxt = fTxt + form("\""); //Add End Quote (")
- fNum = 1; //Set num for Code1
- }else fTxt = FALSE; //Delete if not Str
- if (fOption & OPT_IDC_FILE) fTxt = FALSE; //Delete if IDC
- }
- //Type 8: String References in DATA
- }else if ( (i==9) && (fOption & OPT_STR_DATA) ){
- //isData(F) // is data byte?
- if (fFlags & FF_NAME) { //Test for Name
- fTxt = Name(fCurEA); //Get Name
- if ((substr(fTxt,0,4) == "str_") || (substr(fTxt,0,1) == "a")) {
- fOption = fOption + TYP_STR_DATA; //Set Type
- fTmpEA = fCurEA; //Set Str EA
- fNum = ItemSize(fTmpEA); //Get String Length
- fTxt = form("\""); //Add Quote (")
- for (j=0; j<=fNum; j++) { //Get Each Str Byte
- fTxt = fTxt + byteValue(GetFlags(fTmpEA)); //Append Byte to Str
- fTmpEA = fTmpEA + 1; //Inc EA by 1 Byte
- }
- fTxt = fTxt + form("\""); //Add End Quote (")
- }else fTxt = FALSE;
- }
- }
- //Filter Output
- if ( (fTxt != FALSE) && (fOption & OPT_USE_FLTR) ) fTxt = xFilter(fTxt);
- //Write Output
- if ( (fTxt != FALSE) && (i != 4) && (i!=5) ){ //Print ?
- fLineX = writeLine(fOption, fFileH, fCurEA, fTxt, fNum, fLineX);
- }
- } //End FOR Loop
- } //End BIG IF
- //Message Percent Complete
- ProgNum = ((fCurEA - fSrtEA) * 100) / (fEndEA - fSrtEA) ; //Get Percent Finsihed
- if (ProgNum > ProgPer) { //If serious gain (5%) write.
- fTxt = form("\nPercent Complete: %d ",ProgNum); //Full Message
- Message(fTxt);
- ProgPer = ProgNum + 4;
- } else if (ProgNum > ProgDot) { //Else write a "*" for 1% gain
- Message("*");
- ProgDot = ProgNum;
- }
- //Increment Current EA
- fCurEA = NextAddr(fCurEA);
- } //End WHILE Loop
- //Write "parts()" Function
- if (fOption & OPT_IDC_FILE) {
- fLineX = fLineX/1000;
- fTxt = form("}\n\nstatic parts() {\n\tMessage(\"\\nSTART!\\n\");\n"); //parts() and Message
- fprintf(fFileH, fTxt);
- for(i=0; i <= fLineX; i++) { //write part_X subs
- fTxt = form("\tpart_%d();\n",i);
- fTxt = fTxt + form("\tMessage(\"Part %d of %d Completed\\n\");\n", i, fLineX);
- fprintf(fFileH, fTxt);
- }
- fTxt = form("\tMessage(\"\\nFINISHED!\\n\");\n}\n"); //End parts() & Msg.
- fprintf(fFileH, fTxt);
- }
- //Change Status
- Message("\nPercent Complete: 100\n");
- SetStatus(IDA_STATUS_READY); //Set Status 'Ready'
- }
- //__________________________________________________________________________________________________
- //ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
- //FUNCTION: void main()
- //--------------------------------------------------------------------------------------------------
- //NOTES:
- // i, j - (long) Counters
- // mOption - (long) Holds program option and type info
- // mStartEA - (long) For the starting address
- // mEndEA - (long) For the ending address
- // mFName - (char*) Name for output file
- // mFileH - (handle) File Handle
- // mStartTxt - (char*)
- // mStrLine - (char*)
- // mError - (bool) Error Status
- //--------------------------------------------------------------------------------------------------
- static main() {
- auto i, j, mOption, mStartEA, mEndEA, mFName, mFileH, mStartTxt, mStrLine, mError;
- mError = TRUE; //Set Error Status True
- Message("\n\nBegin Dump: DumpInfo.idc. \n"); //Show Start Message To Window
- //Program Options -I should really build a UI prompt of some sort...
- //Control the program by commenting/uncommenting the information types you want.
- mOption = 0x00000000L; //Initialize Option Var
- mOption = mOption + OPT_MAK_FILE; //Set Option: Write File (Or MessageWindow)
- //mOption = mOption + OPT_IDC_FILE; //Set Option: Create IDC (Or Text File)
- //mOption = mOption + OPT_USE_FLTR; //Set Option: Use Filter
- //mOption = mOption + OPT_REG_FCOM; //Set Option: Regular Function Comments
- //mOption = mOption + OPT_RPT_FCOM; //Set Option: Repeatable Function Comments
- //mOption = mOption + OPT_REG_ICOM; //Set Option: Regular Indented Comments
- //mOption = mOption + OPT_RPT_ICOM; //Set Option: Repeatable Indented Comments
- //mOption = mOption + OPT_ANT_LINE; //Set Option: Anterior Lines
- //mOption = mOption + OPT_POS_LINE; //Set Option: Posterior Lines
- mOption = mOption + OPT_USR_NAME; //Set Option: User Created Names
- //mOption = mOption + OPT_STR_CODE; //Set Option: String References From CODE
- //mOption = mOption + OPT_STR_DATA; //Set Option: String References In DATA
- //Prompt User For Starting/Ending Point
- mStartTxt = form("Start Dump From\n (E)tire Disassembly - From %s To %s\n", \
- ltoa(MinEA(),16),ltoa(MaxEA(),16));
- mStartTxt = mStartTxt + form(" (C)urent Selection - From %s to %s\n", \
- ltoa(SelStart(),16),ltoa(SelEnd(),16));
- mStartTxt = mStartTxt + form(" (S)egment Only - (You'll Select a Single Segment)\n");
- mStartTxt = mStartTxt + form(" (F)unction Only - (You'll Select a Single Function)\n");
- mStartTxt = AskIdent("E", mStartTxt);
- //(E)ntire File
- if ((mStartTxt == "E") || (mStartTxt == "b")) {
- mStartEA = MinEA();
- mEndEA = MaxEA();
- if ((mStartEA != 0) || (mEndEA != 0)) mError = FALSE; //Error Checking
- //(C)urrent Selection
- } else if ((mStartTxt == "C") || (mStartTxt == "c")) {
- mStartEA = SelStart(); //Get Selection Start
- mEndEA = SelEnd(); //Get Selection End
- if ((mStartEA != BADADDR) || (mEndEA != BADADDR)) mError = FALSE; //Error Checking
- else Warning("There Is No Currently Selected Area"); //No Selection Warning
- //(S)egment Only -A "ChooseSegment()" Function would be nice... :)
- } else if ((mStartTxt == "S") || (mStartTxt == "s")) {
- i = 1;
- mStartEA = FirstSeg(); //Set StartEA
- mStartTxt = "Please Choose Segment By Number:\n"; //Create Text for UI
- do {mStartTxt = mStartTxt + form(" (%d) %s", i, SegName(mStartEA));
- mStartEA = NextSeg(mStartEA); //Get Text Seg Name
- i++;
- } while ( mStartEA != BADADDR);
- j = AskLong("1", mStartTxt); //Get User Input (long)
- mStartEA = FirstSeg(); //Set StartEA First Seg
- mEndEA = SegEnd(mStartEA); //Set EndEA to End of Seg
- for (i=1; i<j; i++) { //Loop to user selected -
- mStartEA = NextSeg(mStartEA); //segment setting start -
- mEndEA = SegEnd(mStartEA); //and end
- }
- if ((mStartEA != BADADDR) || (mEndEA != BADADDR)) mError = FALSE; //Error Checking
- //(F)unction Only
- } else if ((mStartTxt == "F") || (mStartTxt == "f")) {
- mStartEA = ChooseFunction("Choose Function");
- mEndEA = FindFuncEnd(mStartEA);
- if ((mStartEA != -1) || (mEndEA != BADADDR)) mError = FALSE; //Error Checking
- }
- //Show Status Messages
- if (mOption & OPT_MAK_FILE) Message("Create File: TRUE \n");
- else Message("Create File: FALSE \n");
- if (mOption & OPT_IDC_FILE) Message("Create IDC: TRUE \n");
- else Message("Create IDC: FALSE \n");
- //Error Test
- if (mError == TRUE) Message("\nThere was an error getting address info. \n");
- else {
- //Setup Output
- //Create IDC string
- if (mOption & OPT_IDC_FILE) {
- mStrLine = form("// User Dump: IDC Format\n// Autogenerated by DumpInfo.IDC \n");
- mStrLine = mStrLine + form("// IDC script for porting info to a new disassembly.\n");
- mStrLine = mStrLine + form("// Disassembled File: %s\n",GetInputFile());
- mStrLine = mStrLine + form("// Cursor Address: %s\n",ltoa(BeginEA(),16));
- mStrLine = mStrLine + form("// Minimum Address: %s\n",ltoa(MinEA(),16));
- mStrLine = mStrLine + form("// Maximum Address: %s\n",ltoa(MaxEA(),16));
- mStrLine = mStrLine + form("// Segment Address: %s\n",ltoa(SegStart(mStartEA),16));
- mStrLine = mStrLine + form("// Segment Name...: %s\n",SegName(mStartEA));
- mStrLine = mStrLine + form("// StartingAddress: %s\n",ltoa(mStartEA,16));
- mStrLine = mStrLine + form("// Ending Address: %s\n\n",ltoa(mEndEA,16));
- mStrLine = mStrLine + form("#include <idc.idc>\n\nstatic main ( ) {\n");
- mStrLine = mStrLine + form("\t parts();\n}\n\n");
- //Create TEXT string
- } else {
- mStrLine = form("User Dump: Text Format\nAutogenerated by DumpInfo.IDC \n");
- mStrLine = mStrLine + form("Disassembled File: %s\n",GetInputFile());
- mStrLine = mStrLine + form("Cursor Address: %s\n",ltoa(BeginEA(),16));
- mStrLine = mStrLine + form("Minimum Address: %s\n",ltoa(MinEA(),16));
- mStrLine = mStrLine + form("Maximum Address: %s\n",ltoa(MaxEA(),16));
- mStrLine = mStrLine + form("Segment Address: %s\n",ltoa(SegStart(mStartEA),16));
- mStrLine = mStrLine + form("Segment Name...: %s\n",SegName(mStartEA));
- mStrLine = mStrLine + form("StartingAddress: %s\n",ltoa(mStartEA,16));
- mStrLine = mStrLine + form("Ending Address: %s\n\n",ltoa(mEndEA,16));
- }
- //Output To File
- if (mOption & OPT_MAK_FILE) {
- if (mOption & OPT_IDC_FILE)
- mFName = AskFile(1,"*.idc", "Output File Name?"); //Get *.IDC File Name
- else mFName = AskFile(1,"*.txt", "Output File Name?"); //Get *.TXT File Name
- mFileH = fopen(mFName, "wt"); //Open File for Output
- if (mFileH == 0) Warning("Error opening output file!\n"); //Error Opening File
- else {
- fprintf(mFileH, mStrLine); //Else Run Program
- findInfo(mOption,mFileH,mStartEA,mEndEA);
- }
- //Output to Message Window
- } else {
- Message (mStrLine);
- findInfo(mOption,mFileH,mStartEA,mEndEA);
- }
- //Cleanup
- if (mFileH != 0) {
- if (mOption & OPT_IDC_FILE) mStrLine = form("\n\n// End of IDC File.");
- else mStrLine = form("\n\nEnd of Text File.");
- fprintf(mFileH, mStrLine);
- fclose(mFileH);
- }
- }
- //Show End Message
- Message("\nEnd of DumpInfo.idc. \n");
- }
Add Comment
Please, Sign In to add comment