home *** CD-ROM | disk | FTP | other *** search
- // IDB to SIG v1.0
- // Plugin module for IDA Pro v3.84
- // written by Quine (quine@blacksun.res.cmu.edu)
- // visit Quine's IDA Page at http://surf.to/quine_ida
-
- // defining __NOT_ONLY_PRO_FUNCS__ keeps the STL stuff from freaking about min/max
- #define __NOT_ONLY_PRO_FUNCS__
- #include <ida.hpp>
- #include <idp.hpp>
- #include <loader.hpp>
- #include <kernwin.hpp>
- #include <bytes.hpp>
- #include <name.hpp>
- #include <entry.hpp>
- #include <funcs.hpp>
- #include <fpro.h>
- // vector must be included first because of crappy Rogue Wave STL
- #include <vector>
- #include <map>
- #define MIN_SIG_LENGTH 10
-
-
- typedef std::vector<bool> bool_vec;
- typedef std::map<ea_t, ea_t, std::less<ea_t> > ref_map;
-
- // crc16 is ripped straight out the c file that comes with the
- // FLAIR package
- #define POLY 0x8408
- /*
- // 16 12 5
- // this is the CCITT CRC 16 polynomial X + X + X + 1.
- // This works out to be 0x1021, but the way the algorithm works
- // lets us use 0x8408 (the reverse of the bit pattern). The high
- // bit is always assumed to be set, thus we only use 16 bits to
- // represent the 17 bit value.
- */
-
- unsigned short crc16(unsigned char *data_p,unsigned short length) {
- unsigned char i;
- unsigned int data;
-
- if ( length == 0 ) return 0;
- unsigned int crc = 0xFFFF;
- do {
- data = *data_p++;
- for ( i=0; i < 8; i++ ) {
- if ( (crc ^ data) & 1 )
- crc = (crc >> 1) ^ POLY;
- else
- crc >>= 1;
- data >>= 1;
- }
- } while (--length);
-
- crc = ~crc;
- data = crc;
- crc = (crc << 8) | ((data >> 8) & 0xff);
- return (crc);
- }
-
- int init(void)
- {
- return PLUGIN_OK;
- }
-
- void term(void)
- {
- }
-
- // this function finds the location of a reference within an instruction
- // or a data item
- // eg: 00401000 E8 FB 0F 00 00 call sub_402000
- // find_ref_loc(0x401000, 0x402000) would return 0x401001
- // it works for both segment relative and self-relative offsets
- // all references are assumed to be 4 bytes long
-
- ea_t find_ref_loc(ea_t item, ea_t _ref) {
- ea_t i;
- if ( isCode(getFlags(item)) ) {
- ua_ana0(item);
- if ( cmd.Operands[0].type == o_near ) {
- // we've got a self-relative reference
- _ref = _ref - (get_item_end(item));
- }
- }
- for ( i = item; i <= get_item_end(item)-4; i++) {
- if ( get_long(i) == _ref) {
- return i;
- }
- }
- return BADADDR;
- }
-
- // marks off a string of bytes as variable
- void set_v_bytes (bool_vec& bv, int pos, int len=4) {
- for ( int i=0; i<len; i++ ) {
- bv[pos+i] = true;
- }
- }
-
- // this is what does the real work
- // given a starting address, a length, and a FILE pointer, it
- // writes a pattern line to the file
-
- void make_func_sig(ea_t start_ea, ulong len, FILE* f) {
- ea_t ea, ref, ref_loc;
- int first_string = 0, alen = 0;
- int i, j;
- unsigned char crc_data[256];
- ushort crc = 0;
- bool_vec v_bytes(len);
- std::vector<ea_t> publics;
- ref_map refs;
- if ( len<MIN_SIG_LENGTH ) {
- return;
- }
- ea = start_ea;
- while ( ea - start_ea < len ) {
- flags_t flags = getFlags(ea);
- if ( has_name(flags) ) {
- publics.push_back(ea);
- }
- if ((ref = get_first_dref_from(ea)) != BADADDR) {
- // a data location is referenced
- ref_loc = find_ref_loc(ea, ref);
- set_v_bytes(v_bytes, ref_loc-start_ea);
- refs[ref_loc] = ref;
-
- // check if there is a second data location ref'd
- if ( (ref = get_next_dref_from(ea, ref)) != BADADDR ) {
- ref_loc = find_ref_loc(ea, ref);
- set_v_bytes(v_bytes, ref_loc-start_ea);
- refs[ref_loc] = ref;
- }
- } else {
- // do we have a code ref?
- if ( (ref = get_first_fcref_from(ea)) != BADADDR ) {
- // if so, make sure it is outside of function
- if ( (ref < start_ea) || (ref >= start_ea+len) ) {
- ref_loc = find_ref_loc(ea, ref);
- set_v_bytes(v_bytes, ref_loc-start_ea);
- refs[ref_loc] = ref;
- }
- }
- }
- ea = nextNotTail(ea);
- }
-
- // write out the first string of bytes, making sure not to go past the end of the function
- first_string = (len < 32 ? len : 32);
- for ( j = 0; j<first_string; j++ ) {
- if ( v_bytes[j] ) {
- qfprintf(f, "..");
- } else {
- qfprintf(f, "%02X", get_byte(start_ea+j));
- }
- }
-
- // fill in anything less than 32
- for ( j = 0; j<(32-first_string); j++ ) {
- qfprintf(f, "..");
- }
-
- // put together the crc data
- int pos = 32;
- while ( (pos < len) && (!v_bytes[pos]) && (pos < 255+32) ) {
- crc_data[pos-32] = get_byte(start_ea+pos);
- pos++;
- }
-
- // alen is length of the crc data
- alen = pos - 32;
- crc = crc16(crc_data, alen);
- qfprintf(f, " %02X %04X %04X", alen, crc, len);
-
- // write the publics
- for ( std::vector<ea_t>::iterator p = publics.begin(); p != publics.end(); p++ ) {
- qfprintf(f, " :%04X %s", *p-start_ea, get_true_name(*p));
- }
-
- // write the references
- for ( ref_map::iterator r = refs.begin(); r != refs.end(); r++ ) {
- qfprintf(f, " ^%04X %s", (*r).first-start_ea, get_true_name((*r).second));
- }
-
- // and finally write out the last string with the rest of the function
- qfprintf(f, " ");
- for ( j = pos; j<len; j++ ) {
- if ( v_bytes[j] ) {
- qfprintf(f, "..");
- } else {
- qfprintf(f, "%02X", get_byte(start_ea+j));
- }
- }
- qfprintf(f, "\n");
- qflush(f);
- }
-
- inline FILE* get_pat_file() {
- char* filename;
- FILE* f;
- filename = askfile_c(TRUE, "*.pat", "Enter the name of the pattern file:");
- f = qfopen(filename, "w");
- if ( !f ) {
- warning("Could not open %s for writing!\n", filename);
- }
- return f;
- }
-
- void run(int arg)
- {
- FILE* f;
- func_t* func;
- int i;
- switch ( arg ) {
- case 0: // write all publics
- f = get_pat_file();
- if ( !f )
- return;
- for ( i = 0; i<get_func_qty(); i++ ) {
- func = getn_func(i);
- if ( !func ) {
- continue;
- }
- if ( has_name(getFlags(func->startEA)) && !(func->flags & FUNC_LIB) ) {
- make_func_sig(func->startEA, func->endEA-func->startEA, f);
- }
- }
- break;
- case 1: // write all entry points
- f= get_pat_file();
- if ( !f )
- return;
- for ( i = 1; i<get_entry_qty(); i++ ) {
- func = get_func(get_entry(get_entry_ordinal(i)));
- if ( !func ) {
- continue;
- }
- make_func_sig(func->startEA, func->endEA-func->startEA, f);
- }
- break;
- case 2: // write current function
- f = get_pat_file();
- if ( !f )
- return;
- func = get_func(get_screen_ea());
- make_func_sig(func->startEA, func->endEA-func->startEA, f);
- break;
- default:
- warning("Internal IDB to SIG error!\n");
- return;
- }
- qfprintf(f, "---\n");
- qfclose(f);
- }
-
- //--------------------------------------------------------------------------
- char comment[] = "This is converts a function or set of functions to a FLAIR pat file.";
-
- char help[] =
- "Convert a function or functions to a PAT file\n"
- "\n";
-
-
- char wanted_name[] = "IDB to SIG";
-
-
- char wanted_hotkey[] = "Alt-0";
-
-
- //--------------------------------------------------------------------------
- //
- // PLUGIN DESCRIPTION BLOCK
- //
- //--------------------------------------------------------------------------
-
- extern "C" plugin_t PLUGIN = {
- IDP_INTERFACE_VERSION,
- 0, // plugin flags
- init, // initialize
-
- term, // terminate. this pointer may be NULL.
-
- run, // invoke plugin
-
- comment, // long comment about the plugin
- // it could appear in the status line
- // or as a hint
-
- help, // multiline help about the plugin
-
- wanted_name, // the preferred short name of the plugin
- wanted_hotkey // the preferred hotkey to run the plugin
- };
-
-