update to ida 7.6, add builds
This commit is contained in:
8519
idasdk76/plugins/findcrypt2/consts.cpp
Normal file
8519
idasdk76/plugins/findcrypt2/consts.cpp
Normal file
File diff suppressed because it is too large
Load Diff
266
idasdk76/plugins/findcrypt2/findcrypt.cpp
Normal file
266
idasdk76/plugins/findcrypt2/findcrypt.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
// FindCrypt - find constants used in crypto algorithms
|
||||
// Copyright 2006 Ilfak Guilfanov <ig@hexblog.com>
|
||||
// This is a freeware program.
|
||||
// This copyright message must be kept intact.
|
||||
|
||||
// This plugin looks for constant arrays used in popular crypto algorithms.
|
||||
// If a crypto algorithm is found, it will rename the appropriate locations
|
||||
// of the program and put bookmarks on them.
|
||||
|
||||
// Version 2.0
|
||||
|
||||
#include <ida.hpp>
|
||||
#include <idp.hpp>
|
||||
#include <loader.hpp>
|
||||
#include <kernwin.hpp>
|
||||
#include <bytes.hpp>
|
||||
#include <name.hpp>
|
||||
#include <moves.hpp>
|
||||
#include <auto.hpp>
|
||||
|
||||
#include "findcrypt.hpp"
|
||||
|
||||
// #define VERIFY_CONSTANTS 1
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
struct plugin_ctx_t : public plugmod_t, public event_listener_t
|
||||
{
|
||||
plugin_ctx_t()
|
||||
{
|
||||
// agree to work with any database
|
||||
#ifndef TESTABLE_BUILD
|
||||
hook_event_listener(HT_IDP, this);
|
||||
#endif
|
||||
}
|
||||
~plugin_ctx_t()
|
||||
{
|
||||
// listeners are uninstalled automatically
|
||||
// when the owner module is unloaded
|
||||
}
|
||||
|
||||
virtual bool idaapi run(size_t) override;
|
||||
virtual ssize_t idaapi on_event(ssize_t code, va_list va) override;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// retrieve the first byte of the specified array
|
||||
// take into account the byte sex
|
||||
inline uchar get_first_byte(const array_info_t *a)
|
||||
{
|
||||
const uchar *ptr = (const uchar *)a->array;
|
||||
if ( !inf_is_be() )
|
||||
return ptr[0];
|
||||
return ptr[a->elsize-1];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// check that all constant arrays are distinct (no duplicates)
|
||||
//lint -e528 not used
|
||||
#ifdef VERIFY_CONSTANTS
|
||||
static void verify_constants(const array_info_t *consts)
|
||||
{
|
||||
typedef std::set<qstring> strset_t;
|
||||
strset_t myset;
|
||||
for ( const array_info_t *ptr=consts; ptr->size != 0; ptr++ )
|
||||
{
|
||||
qstring s((char*)ptr->array, ptr->size);
|
||||
if ( !myset.insert(s).second )
|
||||
error("duplicate array %s!", ptr->name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// match a constant array against the database at the specified address
|
||||
static bool match_array_pattern(ea_t ea, const array_info_t *ai)
|
||||
{
|
||||
uchar *ptr = (uchar *)ai->array;
|
||||
for ( size_t i=0; i < ai->size; i++ )
|
||||
{
|
||||
switch ( ai->elsize )
|
||||
{
|
||||
case 1:
|
||||
if ( get_byte(ea) != *(uchar*)ptr )
|
||||
return false;
|
||||
break;
|
||||
case 2:
|
||||
if ( get_word(ea) != *(ushort*)ptr )
|
||||
return false;
|
||||
break;
|
||||
case 4:
|
||||
if ( get_dword(ea) != *(uint32*)ptr )
|
||||
return false;
|
||||
break;
|
||||
case 8:
|
||||
if ( get_qword(ea) != *(uint64*)ptr )
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
error("interr: unexpected array '%s' element size %" FMT_Z,
|
||||
ai->name, ai->elsize);
|
||||
}
|
||||
ptr += ai->elsize;
|
||||
ea += ai->elsize;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// match a sparse array against the database at the specified address
|
||||
// NB: all sparse arrays must be word32!
|
||||
static bool match_sparse_pattern(ea_t ea, const array_info_t *ai)
|
||||
{
|
||||
const word32 *ptr = (const word32*)ai->array;
|
||||
if ( get_dword(ea) != *ptr++ )
|
||||
return false;
|
||||
ea += 4;
|
||||
for ( size_t i=1; i < ai->size; i++ )
|
||||
{
|
||||
word32 c = *ptr++;
|
||||
if ( inf_is_be() )
|
||||
c = swap32(c);
|
||||
// look for the constant in the next N bytes
|
||||
const size_t N = 64;
|
||||
uchar mem[N+4];
|
||||
memset(mem, 0xFF, sizeof(mem));
|
||||
get_bytes(mem, sizeof(mem), ea);
|
||||
int j;
|
||||
for ( j=0; j < N; j++ )
|
||||
if ( *(uint32*)(mem+j) == c )
|
||||
break;
|
||||
if ( j == N )
|
||||
return false;
|
||||
ea += j + 4;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// mark a location with the name of the algorithm
|
||||
// use the first free slot for the marker
|
||||
static void mark_location(ea_t ea, const char *name)
|
||||
{
|
||||
idaplace_t ipl(ea, 0);
|
||||
renderer_info_t rinfo;
|
||||
rinfo.rtype = TCCRT_FLAT;
|
||||
rinfo.pos.cx = 0;
|
||||
rinfo.pos.cy = 5;
|
||||
lochist_entry_t e(&ipl, rinfo);
|
||||
|
||||
uint32 i, n = bookmarks_t::size(e, NULL);
|
||||
for ( i = 0; i < n; ++i )
|
||||
{
|
||||
qstring desc;
|
||||
lochist_entry_t loc(e);
|
||||
if ( !bookmarks_t::get(&loc, &desc, &i, NULL) )
|
||||
break;
|
||||
// reuse old "Crypto: " slots
|
||||
if ( strneq(desc.c_str(), "Crypto: ", 7) && loc.place()->toea() == ea )
|
||||
break;
|
||||
}
|
||||
qstring buf;
|
||||
buf.sprnt("Crypto: %s", name);
|
||||
bookmarks_t::mark(e, i, NULL, buf.c_str(), NULL);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// try to find constants at the given address range
|
||||
static void recognize_constants(ea_t ea1, ea_t ea2)
|
||||
{
|
||||
int count = 0;
|
||||
show_wait_box("Searching for crypto constants...");
|
||||
for ( ea_t ea=ea1; ea < ea2; ea=next_addr(ea) )
|
||||
{
|
||||
if ( (ea % 0x1000) == 0 )
|
||||
{
|
||||
show_addr(ea);
|
||||
if ( user_cancelled() )
|
||||
break;
|
||||
}
|
||||
uchar b = get_byte(ea);
|
||||
// check against normal constants
|
||||
for ( const array_info_t *ptr=non_sparse_consts; ptr->size != 0; ptr++ )
|
||||
{
|
||||
if ( b != get_first_byte(ptr) )
|
||||
continue;
|
||||
if ( match_array_pattern(ea, ptr) )
|
||||
{
|
||||
msg("%a: found const array %s (used in %s)\n", ea, ptr->name, ptr->algorithm);
|
||||
mark_location(ea, ptr->algorithm);
|
||||
force_name(ea, ptr->name);
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// check against sparse constants
|
||||
for ( const array_info_t *ptr=sparse_consts; ptr->size != 0; ptr++ )
|
||||
{
|
||||
if ( b != get_first_byte(ptr) )
|
||||
continue;
|
||||
if ( match_sparse_pattern(ea, ptr) )
|
||||
{
|
||||
msg("%a: found sparse constants for %s\n", ea, ptr->algorithm);
|
||||
mark_location(ea, ptr->algorithm);
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
hide_wait_box();
|
||||
if ( count != 0 )
|
||||
msg("Found %d known constant arrays in total.\n", count);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// This callback is called for IDP notification events
|
||||
ssize_t idaapi plugin_ctx_t::on_event(ssize_t code, va_list /*va*/)
|
||||
{
|
||||
if ( code == processor_t::ev_newfile ) // a new file has been loaded
|
||||
recognize_constants(inf_get_min_ea(), inf_get_max_ea());
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool idaapi plugin_ctx_t::run(size_t)
|
||||
{
|
||||
ea_t ea1;
|
||||
ea_t ea2;
|
||||
read_range_selection(NULL, &ea1, &ea2); // if fails, inf.min_ea and inf.max_ea will be used
|
||||
recognize_constants(ea1, ea2);
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static plugmod_t *idaapi init()
|
||||
{
|
||||
#ifdef VERIFY_CONSTANTS
|
||||
verify_constants(non_sparse_consts);
|
||||
verify_constants(sparse_consts);
|
||||
#endif
|
||||
return new plugin_ctx_t;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char help[] = "Find crypt v2";
|
||||
static const char comment[] = "Find crypt v2";
|
||||
static const char wanted_name[] = "Find crypt v2";
|
||||
static const char wanted_hotkey[] = "";
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// PLUGIN DESCRIPTION BLOCK
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
plugin_t PLUGIN =
|
||||
{
|
||||
IDP_INTERFACE_VERSION,
|
||||
PLUGIN_PROC // Load plugin when a processor module is loaded
|
||||
| PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel
|
||||
init, // initialize
|
||||
nullptr,
|
||||
nullptr,
|
||||
comment, // long comment about the plugin
|
||||
help, // multiline help about the plugin
|
||||
wanted_name, // the preferred short name of the plugin
|
||||
wanted_hotkey // the preferred hotkey to run the plugin
|
||||
};
|
||||
31
idasdk76/plugins/findcrypt2/findcrypt.hpp
Normal file
31
idasdk76/plugins/findcrypt2/findcrypt.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
#define IS_LITTLE_ENDIAN
|
||||
|
||||
#if defined(__GNUC__) || defined(__MWERKS__)
|
||||
#define WORD64_AVAILABLE
|
||||
typedef unsigned long long word64;
|
||||
typedef unsigned long word32;
|
||||
typedef unsigned char byte;
|
||||
#define W64LIT(x) x##LL
|
||||
#elif defined(_MSC_VER) || defined(__BCPLUSPLUS__)
|
||||
#define WORD64_AVAILABLE
|
||||
typedef unsigned __int64 word64;
|
||||
typedef unsigned __int32 word32;
|
||||
typedef unsigned __int8 byte;
|
||||
#define W64LIT(x) x##ui64
|
||||
#endif
|
||||
|
||||
struct array_info_t
|
||||
{
|
||||
const void *array;
|
||||
size_t size;
|
||||
size_t elsize;
|
||||
const char *name;
|
||||
const char *algorithm;
|
||||
};
|
||||
|
||||
extern const array_info_t non_sparse_consts[];
|
||||
extern const array_info_t sparse_consts[];
|
||||
|
||||
#define ARR(x) x, qnumber(x), sizeof(x[0]), #x
|
||||
|
||||
16
idasdk76/plugins/findcrypt2/makefile
Normal file
16
idasdk76/plugins/findcrypt2/makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
PROC=findcrypt
|
||||
O1=consts
|
||||
O2=sparse
|
||||
|
||||
include ../plugin.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)consts$(O) : $(I)llong.hpp $(I)pro.h consts.cpp findcrypt.hpp
|
||||
$(F)findcrypt$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)dirtree.hpp $(I)fpro.h $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)moves.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)pro.h \
|
||||
$(I)range.hpp $(I)segment.hpp $(I)ua.hpp \
|
||||
$(I)xref.hpp findcrypt.cpp findcrypt.hpp
|
||||
$(F)sparse$(O) : $(I)llong.hpp $(I)pro.h findcrypt.hpp sparse.cpp
|
||||
122
idasdk76/plugins/findcrypt2/sparse.cpp
Normal file
122
idasdk76/plugins/findcrypt2/sparse.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include <pro.h>
|
||||
#include "findcrypt.hpp"
|
||||
|
||||
// Various constants used in crypto algorithms
|
||||
// They were copied from public domain codes
|
||||
|
||||
static const word32 SHA_1[] =
|
||||
{
|
||||
0x67452301L,
|
||||
0xEFCDAB89L,
|
||||
0x98BADCFEL,
|
||||
0x10325476L,
|
||||
0xC3D2E1F0L,
|
||||
};
|
||||
|
||||
static const word32 RC5_RC6[] =
|
||||
{
|
||||
0xb7e15163L, // magic constant P for wordsize
|
||||
0x9e3779b9L, // magic constant Q for wordsize
|
||||
};
|
||||
|
||||
static const word32 MD5[] =
|
||||
{
|
||||
0xd76aa478,
|
||||
0xe8c7b756,
|
||||
0x242070db,
|
||||
0xc1bdceee,
|
||||
0xf57c0faf,
|
||||
0x4787c62a,
|
||||
0xa8304613,
|
||||
0xfd469501,
|
||||
0x698098d8,
|
||||
0x8b44f7af,
|
||||
0xffff5bb1,
|
||||
0x895cd7be,
|
||||
0x6b901122,
|
||||
0xfd987193,
|
||||
0xa679438e,
|
||||
0x49b40821,
|
||||
|
||||
0xf61e2562,
|
||||
0xc040b340,
|
||||
0x265e5a51,
|
||||
0xe9b6c7aa,
|
||||
0xd62f105d,
|
||||
0x02441453,
|
||||
0xd8a1e681,
|
||||
0xe7d3fbc8,
|
||||
0x21e1cde6,
|
||||
0xc33707d6,
|
||||
0xf4d50d87,
|
||||
0x455a14ed,
|
||||
0xa9e3e905,
|
||||
0xfcefa3f8,
|
||||
0x676f02d9,
|
||||
0x8d2a4c8a,
|
||||
|
||||
0xfffa3942,
|
||||
0x8771f681,
|
||||
0x6d9d6122,
|
||||
0xfde5380c,
|
||||
0xa4beea44,
|
||||
0x4bdecfa9,
|
||||
0xf6bb4b60,
|
||||
0xbebfbc70,
|
||||
0x289b7ec6,
|
||||
0xeaa127fa,
|
||||
0xd4ef3085,
|
||||
0x04881d05,
|
||||
0xd9d4d039,
|
||||
0xe6db99e5,
|
||||
0x1fa27cf8,
|
||||
0xc4ac5665,
|
||||
|
||||
0xf4292244,
|
||||
0x432aff97,
|
||||
0xab9423a7,
|
||||
0xfc93a039,
|
||||
0x655b59c3,
|
||||
0x8f0ccc92,
|
||||
0xffeff47d,
|
||||
0x85845dd1,
|
||||
0x6fa87e4f,
|
||||
0xfe2ce6e0,
|
||||
0xa3014314,
|
||||
0x4e0811a1,
|
||||
0xf7537e82,
|
||||
0xbd3af235,
|
||||
0x2ad7d2bb,
|
||||
0xeb86d391,
|
||||
};
|
||||
|
||||
static const word32 MD4[] =
|
||||
{
|
||||
0x67452301L,
|
||||
0xefcdab89L,
|
||||
0x98badcfeL,
|
||||
0x10325476L,
|
||||
};
|
||||
|
||||
static const word32 HAVAL[] =
|
||||
{
|
||||
0x243F6A88,
|
||||
0x85A308D3,
|
||||
0x13198A2E,
|
||||
0x03707344,
|
||||
0xA4093822,
|
||||
0x299F31D0,
|
||||
0x082EFA98,
|
||||
0xEC4E6C89,
|
||||
};
|
||||
|
||||
// NB: all sparse arrays must be word32!
|
||||
const array_info_t sparse_consts[] =
|
||||
{
|
||||
{ ARR(SHA_1), "SHA-1" },
|
||||
{ ARR(RC5_RC6), "RC5_RC6" },
|
||||
{ ARR(MD5), "MD5" },
|
||||
{ ARR(MD4), "MD4" },
|
||||
{ ARR(HAVAL), "HAVAL" },
|
||||
{ NULL, 0, 0, NULL, NULL }
|
||||
};
|
||||
Reference in New Issue
Block a user