home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Quines / files / idb_to_sig.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-25  |  8.6 KB  |  296 lines

  1. // IDB to SIG v1.0
  2. // Plugin module for IDA Pro v3.84
  3. // written by Quine (quine@blacksun.res.cmu.edu)
  4. // visit Quine's IDA Page at http://surf.to/quine_ida
  5.  
  6. // defining __NOT_ONLY_PRO_FUNCS__ keeps the STL stuff from freaking about min/max
  7. #define __NOT_ONLY_PRO_FUNCS__
  8. #include <ida.hpp>
  9. #include <idp.hpp>
  10. #include <loader.hpp>
  11. #include <kernwin.hpp>
  12. #include <bytes.hpp>
  13. #include <name.hpp>
  14. #include <entry.hpp>
  15. #include <funcs.hpp>
  16. #include <fpro.h>
  17. // vector must be included first because of crappy Rogue Wave STL
  18. #include <vector>
  19. #include <map>
  20. #define MIN_SIG_LENGTH 10
  21.  
  22.  
  23. typedef std::vector<bool> bool_vec;
  24. typedef std::map<ea_t, ea_t, std::less<ea_t> > ref_map;
  25.  
  26. // crc16 is ripped straight out the c file that comes with the
  27. // FLAIR package
  28. #define POLY 0x8408
  29. /*
  30. //                                      16   12   5
  31. // this is the CCITT CRC 16 polynomial X  + X  + X  + 1.
  32. // This works out to be 0x1021, but the way the algorithm works
  33. // lets us use 0x8408 (the reverse of the bit pattern).  The high
  34. // bit is always assumed to be set, thus we only use 16 bits to
  35. // represent the 17 bit value.
  36. */
  37.  
  38. unsigned short crc16(unsigned char *data_p,unsigned short length) {
  39.   unsigned char i;
  40.   unsigned int data;
  41.  
  42.   if ( length == 0 ) return 0;
  43.   unsigned int crc = 0xFFFF;
  44.   do {
  45.     data = *data_p++;
  46.     for ( i=0; i < 8; i++ ) {
  47.       if ( (crc ^ data) & 1 )
  48.         crc = (crc >> 1) ^ POLY;
  49.       else
  50.         crc >>= 1;
  51.       data >>= 1;
  52.     }
  53.   } while (--length);
  54.  
  55.   crc = ~crc;
  56.   data = crc;
  57.   crc = (crc << 8) | ((data >> 8) & 0xff);
  58.   return (crc);
  59. }
  60.  
  61. int init(void)
  62. {
  63.   return PLUGIN_OK;
  64. }
  65.  
  66. void term(void)
  67. {
  68. }
  69.  
  70. // this function finds the location of a reference within an instruction
  71. // or a data item
  72. // eg:  00401000 E8 FB 0F 00 00   call sub_402000
  73. // find_ref_loc(0x401000, 0x402000) would return 0x401001
  74. // it works for both segment relative and self-relative offsets
  75. // all references are assumed to be 4 bytes long
  76.  
  77. ea_t find_ref_loc(ea_t item, ea_t _ref) {
  78.     ea_t i;
  79.     if ( isCode(getFlags(item)) ) {
  80.         ua_ana0(item);
  81.         if ( cmd.Operands[0].type == o_near ) {
  82.             // we've got a self-relative reference
  83.             _ref = _ref - (get_item_end(item));
  84.         }
  85.     }
  86.     for ( i = item; i <= get_item_end(item)-4; i++) {
  87.         if ( get_long(i) == _ref) {
  88.             return i;
  89.         }
  90.     }
  91.     return BADADDR;
  92. }
  93.  
  94. // marks off a string of bytes as variable
  95. void set_v_bytes (bool_vec& bv, int pos, int len=4) {
  96.     for ( int i=0; i<len; i++ ) {
  97.         bv[pos+i] = true;
  98.     }
  99. }
  100.  
  101. // this is what does the real work
  102. // given a starting address, a length, and a FILE pointer, it
  103. // writes a pattern line to the file
  104.  
  105. void make_func_sig(ea_t start_ea, ulong len, FILE* f) {
  106.     ea_t ea, ref, ref_loc;
  107.     int first_string = 0, alen = 0;
  108.     int i, j;
  109.     unsigned char crc_data[256];
  110.     ushort crc = 0;
  111.     bool_vec v_bytes(len);
  112.     std::vector<ea_t> publics;
  113.     ref_map refs;
  114.     if ( len<MIN_SIG_LENGTH ) {
  115.         return;
  116.     }
  117.     ea = start_ea;
  118.     while ( ea - start_ea < len ) {
  119.         flags_t flags = getFlags(ea);
  120.         if ( has_name(flags) ) {
  121.             publics.push_back(ea);
  122.         }
  123.         if ((ref = get_first_dref_from(ea)) != BADADDR) {
  124.             // a data location is referenced
  125.             ref_loc = find_ref_loc(ea, ref);
  126.             set_v_bytes(v_bytes, ref_loc-start_ea);
  127.             refs[ref_loc] = ref;
  128.  
  129.             // check if there is a second data location ref'd
  130.             if ( (ref = get_next_dref_from(ea, ref)) != BADADDR ) {
  131.                 ref_loc = find_ref_loc(ea, ref);
  132.                 set_v_bytes(v_bytes, ref_loc-start_ea);
  133.                 refs[ref_loc] = ref;
  134.             }
  135.         } else {
  136.             // do we have a code ref?
  137.             if ( (ref = get_first_fcref_from(ea)) != BADADDR ) {
  138.                 // if so, make sure it is outside of function
  139.                 if ( (ref < start_ea) || (ref >= start_ea+len) ) {
  140.                     ref_loc = find_ref_loc(ea, ref);
  141.                     set_v_bytes(v_bytes, ref_loc-start_ea);
  142.                     refs[ref_loc] = ref;
  143.                 }
  144.             }
  145.         }
  146.         ea = nextNotTail(ea);
  147.     }
  148.  
  149.     // write out the first string of bytes, making sure not to go past the end of the function
  150.     first_string = (len < 32 ? len : 32);
  151.     for ( j = 0; j<first_string; j++ ) {
  152.         if ( v_bytes[j] ) {
  153.             qfprintf(f, "..");
  154.         } else {
  155.             qfprintf(f, "%02X", get_byte(start_ea+j));
  156.         }
  157.     }
  158.  
  159.     // fill in anything less than 32
  160.     for ( j = 0; j<(32-first_string); j++ ) {
  161.         qfprintf(f, "..");
  162.     }
  163.  
  164.     // put together the crc data
  165.     int pos = 32;
  166.     while ( (pos < len) && (!v_bytes[pos]) && (pos < 255+32) ) {
  167.         crc_data[pos-32] = get_byte(start_ea+pos);
  168.         pos++;
  169.     }
  170.  
  171.     // alen is length of the crc data
  172.     alen = pos - 32;
  173.     crc = crc16(crc_data, alen);
  174.     qfprintf(f, " %02X %04X %04X", alen, crc, len);
  175.  
  176.     // write the publics
  177.     for ( std::vector<ea_t>::iterator p = publics.begin(); p != publics.end(); p++ ) {
  178.         qfprintf(f, " :%04X %s", *p-start_ea, get_true_name(*p));
  179.     }
  180.  
  181.     // write the references
  182.     for ( ref_map::iterator r = refs.begin(); r != refs.end(); r++ ) {
  183.         qfprintf(f, " ^%04X %s", (*r).first-start_ea, get_true_name((*r).second));
  184.     }
  185.  
  186.     // and finally write out the last string with the rest of the function
  187.     qfprintf(f, " ");
  188.     for ( j = pos; j<len; j++ ) {
  189.         if ( v_bytes[j] ) {
  190.             qfprintf(f, "..");
  191.         } else {
  192.             qfprintf(f, "%02X", get_byte(start_ea+j));
  193.         }
  194.     }
  195.     qfprintf(f, "\n");
  196.     qflush(f);
  197. }
  198.  
  199. inline FILE* get_pat_file() {
  200.     char* filename;
  201.     FILE* f;
  202.     filename = askfile_c(TRUE, "*.pat", "Enter the name of the pattern file:");
  203.     f = qfopen(filename, "w");
  204.     if ( !f ) {
  205.         warning("Could not open %s for writing!\n", filename);
  206.     }
  207.     return f;
  208. }
  209.  
  210. void run(int arg)
  211. {
  212.     FILE* f;
  213.     func_t* func;
  214.     int i;
  215.     switch ( arg ) {
  216.         case 0:                         // write all publics
  217.             f = get_pat_file();
  218.             if ( !f )
  219.                 return;
  220.             for ( i = 0; i<get_func_qty(); i++ ) {
  221.                 func = getn_func(i);
  222.                 if ( !func ) {
  223.                     continue;
  224.                 }
  225.                 if ( has_name(getFlags(func->startEA)) && !(func->flags & FUNC_LIB) ) {
  226.                     make_func_sig(func->startEA, func->endEA-func->startEA, f);
  227.                 }
  228.             }
  229.             break;
  230.         case 1:                         // write all entry points
  231.             f= get_pat_file();
  232.             if ( !f )
  233.                 return;
  234.             for ( i = 1; i<get_entry_qty(); i++ ) {
  235.                 func = get_func(get_entry(get_entry_ordinal(i)));
  236.                 if ( !func ) {
  237.                     continue;
  238.                 }
  239.                 make_func_sig(func->startEA, func->endEA-func->startEA, f);
  240.             }
  241.             break;
  242.         case 2:                         // write current function
  243.             f = get_pat_file();
  244.             if ( !f )
  245.                 return;
  246.             func = get_func(get_screen_ea());
  247.             make_func_sig(func->startEA, func->endEA-func->startEA, f);
  248.             break;
  249.         default:
  250.             warning("Internal IDB to SIG error!\n");
  251.             return;
  252.     }
  253.     qfprintf(f, "---\n");
  254.     qfclose(f);
  255. }
  256.  
  257. //--------------------------------------------------------------------------
  258. char comment[] = "This is converts a function or set of functions to a FLAIR pat file.";
  259.  
  260. char help[] =
  261.         "Convert a function or functions to a PAT file\n"
  262.         "\n";
  263.  
  264.  
  265. char wanted_name[] = "IDB to SIG";
  266.  
  267.  
  268. char wanted_hotkey[] = "Alt-0";
  269.  
  270.  
  271. //--------------------------------------------------------------------------
  272. //
  273. //      PLUGIN DESCRIPTION BLOCK
  274. //
  275. //--------------------------------------------------------------------------
  276.  
  277. extern "C" plugin_t PLUGIN = {
  278.   IDP_INTERFACE_VERSION,
  279.   0,                    // plugin flags
  280.   init,                 // initialize
  281.  
  282.   term,                 // terminate. this pointer may be NULL.
  283.  
  284.   run,                  // invoke plugin
  285.  
  286.   comment,              // long comment about the plugin
  287.                         // it could appear in the status line
  288.                         // or as a hint
  289.  
  290.   help,                 // multiline help about the plugin
  291.  
  292.   wanted_name,          // the preferred short name of the plugin
  293.   wanted_hotkey         // the preferred hotkey to run the plugin
  294. };
  295.  
  296.