/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß DumpInfo.IDC v0.0.0 By: J.C. Roberts ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ 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 #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\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"); }