/*
Patchdiff2
Portions (C) 2010 - 2011 Nicolas Pouvesle
Portions (C) 2007 - 2009 Tenable Network Security, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "precomp.hpp"
#include "sig.hpp"
#include "parser.hpp"
#include "patchdiff.hpp"
#include "diff.hpp"
#include "backup.hpp"
#include "display.hpp"
#include "options.hpp"
#include "system.hpp"
extern plugin_t PLUGIN;
extern char *exename;
deng_t * d_engine;
cpu_t patchdiff_cpu;
options_t * d_opt;
static int idaapi init(void)
{
if (!strcmp(inf.procName, "metapc"))
{
if (inf.is_64bit())
patchdiff_cpu = CPU_X8664;
else
patchdiff_cpu = CPU_X8632;
}
else if (!strcmp(inf.procName, "PPC"))
{
patchdiff_cpu = CPU_PPC;
}
else
patchdiff_cpu = CPU_DEFAULT;
d_engine = NULL;
// handle IPC
ipc_init(NULL, 0, 0);
d_opt = options_init();
if (!d_opt)
return PLUGIN_SKIP;
return PLUGIN_OK;
}
static void idaapi term(void)
{
if (d_engine)
{
if (options_save_db(d_opt))
backup_save_results(d_engine);
diff_engine_free(d_engine);
unhook_from_notification_point(HT_UI, ui_callback);
}
ipc_close();
options_close(d_opt);
}
static void run_first_instance()
{
char * file;
slist_t * sl1 = NULL;
slist_t * sl2 = NULL;
int ret;
msg ("\n---------------------------------------------------\n"
"PatchDiff Plugin v2.0.10\n"
"Copyright (c) 2010-2011, Nicolas Pouvesle\n"
"Copyright (C) 2007-2009, Tenable Network Security, Inc\n"
"---------------------------------------------------\n\n");
ret = backup_load_results(&d_engine, d_opt);
if (ret == 1)
{
display_results(d_engine);
return;
}
else if (ret == -1)
{
return;
}
show_wait_box ("PatchDiff is in progress ...");
msg ("Scanning for functions ...\n");
msg ("parsing second idb...\n");
sl2 = parse_second_idb(&file, d_opt);
if (!sl2)
{
msg("Error: IDB2 parsing cancelled or failed.\n");
hide_wait_box();
return;
}
msg ("parsing first idb...\n");
sl1 = parse_idb ();
if (!sl1)
{
msg("Error: IDB1 parsing failed.\n");
siglist_free(sl2);
hide_wait_box();
return;
}
msg ("diffing...\n");
generate_diff(&d_engine, sl1, sl2, file, true, d_opt);
msg ("done!\n");
hide_wait_box();
if (sl1) siglist_partial_free(sl1);
if (sl2) siglist_partial_free(sl2);
}
static void run_second_instance(const char * options)
{
slist_t * sl;
char file[QMAXPATH];
ea_t ea = BADADDR;
unsigned char opt = 0;
long id;
unsigned int v;
bool cont;
char tmp[QMAXPATH*4];
qsscanf(options, "%lu:%a:%u:%s", &id, &ea, &v, file);
opt = (unsigned char)v;
if (id)
{
if (ipc_init(file, 2, id))
{
do
{
cont = ipc_recv_cmd(tmp, sizeof(tmp));
if (cont)
{
run_second_instance(tmp);
ipc_recv_cmd_end();
}
}while(cont);
}
}
else
{
if (ea == BADADDR)
{
sl = parse_idb ();
}
else
sl = parse_fct(ea, opt);
if (!sl) return;
siglist_save(sl, file);
siglist_free(sl);
}
}
static void idaapi run(int arg)
{
const char * options = NULL;
autoWait();
options = get_plugin_options("patchdiff2");
if (options == NULL)
run_first_instance();
else
run_second_instance(options);
}
char comment[] = "w00t";
char help[] = "A Binary Difference Analysis plugin module\n";
char wanted_name[] = "PatchDiff2";
char wanted_hotkey[] = "Ctrl-8";
plugin_t PLUGIN =
{
IDP_INTERFACE_VERSION,
PLUGIN_MOD | PLUGIN_PROC,
init,
term,
run,
comment,
help,
wanted_name,
wanted_hotkey
};