home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Mammon_ / stree.idc < prev    next >
Text File  |  2000-05-25  |  7KB  |  137 lines

  1. //Stree.idc
  2. //code by cephren (mammon_ / the_owl / slava / modified by cephren)
  3. //
  4. //Documentation:
  5. // stree.idc is derived from fultree.idc that has been published by mammon_ earlier this year.
  6. //
  7. //It produces a call-tree from any function in an IDA disassembly and writes it to a file.
  8. //The main reason why I made it, was, that fultree often makes huge output files, which are
  9. //hard to analyze.
  10. //
  11. //The differences are:
  12. //
  13. //- Functions are traced only once. Further occurences of the same functions are marked
  14. //"Already traced in line# ...." (The line numbers are also new)
  15. //- Optional recursive tracing  only if a functionname starts with the IDA defaults "sub_" 
  16. //or "unknown". If a function is renamed either by IDA when applying signatures or by 
  17. //the user when he has identified the purpose of the function, it will be not traced deeper.
  18. //- Comments like "*** Recursive call.." or "Already Traced..." require no extra line
  19. //- The level of recursive tracing can easily be counted.
  20. //
  21. //Example output line:
  22. //   32   |  |  |  |  |0042B928  ->  sub_42B77E : 0042B77E **** Already Traced in Line 19
  23. //means line 32 in the listing, the 5th tracelevel. At location 0042B928 sub_42B77E is
  24. //called. Sub_42B77E will not be traced deeper for this has already been done at line 19 of
  25. //the listing.
  26.  
  27.  
  28. #include <idc.idc>
  29.  
  30. static OutputLine(lnumber, ea, x, nest, OutFileH){
  31.     auto j;
  32.     fprintf(OutFileH, "%5d ", lnumber);
  33.     for ( j = 0; j <= nest; j = j + 1) {
  34.         fprintf(OutFileH, "  |");
  35.     }
  36.     fprintf(OutFileH, atoa(ea) + "  ->  " + Name(x) + " : " + atoa(x));
  37. }
  38.  
  39.  
  40. static TravelFunc(ea, nest, MaxNest , ArrayID, ArrayFN, OutFileH, lnumber, UnkOnly) {
  41.    auto x, f_end, type, counter, count2, last, df, df2;
  42.    if (nest >= xtol(MaxNest)-1)
  43.       return (lnumber);
  44.  
  45.    f_end = FindFuncEnd(ea);  // note that FindFuncEnd returns the address of (FunctionEnd+1)
  46.    for (ea; ea < f_end; ea=NextAddr(ea)) {
  47.       x = Rfirst0(ea);
  48.       if (x != BADADDR) {
  49.          type = XrefType();
  50.          if (type == fl_CF || type == fl_CN) {
  51.  
  52.             for(counter = 0; counter <= GetLastIndex(AR_STR,ArrayID); counter = counter+1){ //go through array
  53.                 if (Name(x) == GetArrayElement(AR_STR,ArrayID,counter)){  // do we have this name stored in array?
  54.                     OutputLine(lnumber, ea, x, nest+1, OutFileH);  //out fuction call
  55.                     lnumber = lnumber + 1;
  56.                     fprintf(OutFileH, "***** RECURSIVE CALL *****\n"); //out warning
  57.                     DelArrayElement(AR_STR,ArrayID,nest+1); // going up, so let's adjust our array.
  58.                     {return lnumber;} // we may still need some space on our h/d, so let's get out of here right now
  59.                 }
  60.             }
  61.  
  62.  
  63.             OutputLine(lnumber, ea, x, nest+1, OutFileH);
  64.             lnumber = lnumber+1;
  65.             SetArrayString(ArrayID,nest+1,Name(x));  // no such a function in array, so add it
  66.             df2=0;
  67.             for(count2 = 0; count2 < GetLastIndex(AR_STR,ArrayFN); count2 = count2+2){ //go through AllFunc-array
  68.                 if (Name(x) == GetArrayElement(AR_STR,ArrayFN,count2) && (strstr(Name(x), "sub_" )== 0 || strstr(Name(x), "unknown" )== 0 || UnkOnly !=1) && (nest < xtol(MaxNest)-1)){
  69.                     fprintf(OutFileH, " **** Already Traced in Line %d \n", GetArrayElement(AR_LONG,ArrayFN,count2+1));
  70.                     df=1;
  71.                     df2=1;
  72.                 }
  73.             }
  74.             if (df==0){ // add function name and line# to array
  75.                 last = GetLastIndex(AR_STR,ArrayFN);
  76.                 SetArrayString(ArrayFN,last+1,Name(x));
  77.                 SetArrayLong(ArrayFN,last+2,lnumber-1);
  78.             }
  79.             if (df2==0){ // no additional comments, so print LF
  80.                 fprintf(OutFileH, "\n");
  81.             }
  82.             if (((strstr(Name(x), "sub_" )== 0 || strstr(Name(x), "unknown" )== 0) && (df == 0))|| UnkOnly !=1){ // trace only functions starting with "sub_" & not traced before 
  83.                 lnumber = TravelFunc(x, nest+1, MaxNest, ArrayID, ArrayFN, OutFileH, lnumber, UnkOnly); // let's dig deeper
  84.             }
  85.             DelArrayElement(AR_STR,ArrayID,nest+1); //it's ok to call a func multiple times from the same level
  86.          }
  87.       }
  88.    }
  89.    DelArrayElement(AR_STR,ArrayID,nest+1); // going up, so let's adjust our array for recursive calls.
  90. {return lnumber;}
  91. }
  92.  
  93. static main(){
  94.     auto ea, x, i, nest, f_end, EPOrd, OutFileH, OutFName, MaxNest, ArrayID, ArrayFN, lnumber, UnkOnly;
  95.  
  96.     ArrayID =  CreateArray("RecurFuncNames");  //create array for our recursive calls
  97.     if (ArrayID == -1){
  98.         Warning("Can't create array RecurFuncNames"); //hmm...
  99.         ArrayID = GetArrayId("RecurFuncNames");  //let's see if we already have an array with this name
  100.         DeleteArray(ArrayID);                   //if it's there, it's most probably because we abnormaly
  101.                                                 //terminated this script without removing the  array from
  102.                                                 //the database at the end of main(), so let's try to do it now.
  103.         ArrayID =  CreateArray("RecurFuncNames"); //try to create it again
  104.         if (ArrayID == -1){
  105.             Warning("Still can't create array RecurFuncNames, exiting"); // still doesn't work, so exit
  106.             return;
  107.         }
  108.     }
  109.     ArrayFN =  CreateArray("AllFuncNames");  //create array for function names and line# of first occurence
  110.     if (ArrayFN == -1){
  111.         Warning("Can't create array AllFuncNames"); // Comments see above
  112.         ArrayFN = GetArrayId("AllFuncNames");
  113.         DeleteArray(ArrayFN);
  114.  
  115.         ArrayFN =  CreateArray("AllFuncNames");
  116.         if (ArrayFN == -1){
  117.                 Warning("Still can't create array AllFuncNames, exiting"); // still doesn't work, so exit
  118.                 return;
  119.         }
  120.     }
  121.     nest = -1;
  122.     MaxNest = AskStr( "10", "Enter max number of levels");
  123.     UnkOnly = AskYN(1, "Trace sub.. and unknown.. funktions only?");
  124.     OutFName = AskStr("FuncTree.txt", "Enter output filename: ");
  125.     OutFileH = fopen(OutFName, "wt");
  126.     ea = ChooseFunction("select a function to parse");
  127.     f_end = FindFuncEnd(ea);
  128.     fprintf(OutFileH, "*** Code references from " + GetFunctionName(ea) + " : " + atoa(ea) + "\n");
  129.     lnumber = 1;
  130.     lnumber = TravelFunc(ea, nest, MaxNest, ArrayID, ArrayFN, OutFileH, lnumber, UnkOnly); // shit.. no globals??. let's pass all this crap then.
  131.     fclose (OutFileH);
  132.     Message("End of output. \n");
  133.     DeleteArray(ArrayID);
  134.     DeleteArray(ArrayFN);
  135. }
  136.  
  137.