[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/anderhil/patchdiff2/master/backup.cpp [Back]  [Original]

/*
   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 "diff.hpp"
#include "options.hpp"
#include "backup.hpp"


static void buffer_serialize_data(char * buf, size_t blen, size_t * pos, void * data, size_t dsize)
{
	if ( (*pos + dsize) > blen)
	{
		*pos = blen;
		return;
	}

	memcpy(buf+*pos, data, dsize);
	*pos += dsize;
}


static void buffer_unserialize_data(char * buf, size_t blen, size_t * pos, void * data, size_t dsize)
{
	if ( (*pos + dsize) > blen)
	{
		*pos = blen;
		return;
	}

	memcpy(data, buf+*pos, dsize);
	*pos += dsize;
}


static void buffer_serialize_ea(char * buf, size_t blen, size_t * pos, ea_t ea)
{
	buffer_serialize_data(buf, blen, pos, &ea, sizeof(ea));
}


static void buffer_serialize_bool(char * buf, size_t blen, size_t * pos, bool b)
{
	buffer_serialize_data(buf, blen, pos, &b, sizeof(b));
}


static void buffer_serialize_char(char * buf, size_t blen, size_t * pos, char c)
{
	buffer_serialize_data(buf, blen, pos, &c, sizeof(c));
}


static void buffer_serialize_int(char * buf, size_t blen, size_t * pos, int i)
{
	buffer_serialize_data(buf, blen, pos, &i, sizeof(i));
}


static void buffer_serialize_long(char * buf, size_t blen, size_t * pos, unsigned long l)
{
	buffer_serialize_data(buf, blen, pos, &l, sizeof(l));
}


static void buffer_serialize_size(char * buf, size_t blen, size_t * pos, size_t size)
{
	buffer_serialize_data(buf, blen, pos, &size, sizeof(size));
}


static void buffer_unserialize_ea(char * buf, size_t blen, size_t * pos, ea_t * ea)
{
	buffer_unserialize_data(buf, blen, pos, ea, sizeof(*ea));
}


static void buffer_unserialize_bool(char * buf, size_t blen, size_t * pos, bool * b)
{
	buffer_unserialize_data(buf, blen, pos, b, sizeof(*b));
}


static void buffer_unserialize_char(char * buf, size_t blen, size_t * pos, char * c)
{
	buffer_unserialize_data(buf, blen, pos, c, sizeof(*c));
}


static void buffer_unserialize_int(char * buf, size_t blen, size_t * pos, int * i)
{
	buffer_unserialize_data(buf, blen, pos, i, sizeof(*i));
}


static void buffer_unserialize_long(char * buf, size_t blen, size_t * pos, unsigned long * l)
{
	buffer_unserialize_data(buf, blen, pos, l, sizeof(*l));
}


static void buffer_unserialize_size(char * buf, size_t blen, size_t * pos, size_t * size)
{
	buffer_unserialize_data(buf, blen, pos, size, sizeof(*size));
}


/*------------------------------------------------*/
/* function : buffer_serialize_string             */
/* description: Serializes a string               */
/*------------------------------------------------*/

static void buffer_serialize_string(char * buf, size_t blen, size_t * pos, char * s)
{
	size_t len;

	len = strlen(s) + 1;
	if ( (*pos + len) > blen)
	{
		*pos = blen;
		return;
	}

	memcpy(buf+*pos, s, len);
	*pos += len;
}


/*------------------------------------------------*/
/* function : buffer_unserialize_string           */
/* description: Unserializes a string             */
/*------------------------------------------------*/

static void buffer_unserialize_string(char * buf, size_t blen, size_t * pos, char ** s)
{
	*s = qstrdup(buf+*pos);
	*pos += strlen(*s) + 1;
}


/*------------------------------------------------*/
/* function : singleton_serialize                 */
/* description: Serializes a signature            */
/*------------------------------------------------*/

static size_t singleton_serialize(char * buf, size_t blen, psig_t * s, int nfile)
{
	size_t pos = 0;
	fref_t * fref = NULL;
	int num, i;

	buffer_serialize_ea(buf, blen, &pos, s->startEA);

	buffer_serialize_int(buf, blen, &pos, s->mtype);

	buffer_serialize_int(buf, blen, &pos, s->id_crc);
	buffer_serialize_int(buf, blen, &pos, nfile);

	buffer_serialize_long(buf, blen, &pos, s->sig);
	buffer_serialize_long(buf, blen, &pos, s->hash);
	buffer_serialize_long(buf, blen, &pos, s->crc_hash);
	buffer_serialize_long(buf, blen, &pos, s->str_hash);
	buffer_serialize_int(buf, blen, &pos, s->flag);
	buffer_serialize_long(buf, blen, &pos, s->lines);

	num= 0;
	if (s->srefs)
	{
		fref = s->srefs->list;
		num = s->srefs->num;
	}

	buffer_serialize_int(buf, blen, &pos, num);
	for (i=0; iea);
		buffer_serialize_int(buf, blen, &pos, fref->type);

		fref = fref->next;
	}

	if (nfile == 2)
	{
		if (!strncmp(s->name, "sub_", 4))
		{
			buffer_serialize_char(buf, blen, &pos, 0);
		}
		else
		{
			buffer_serialize_char(buf, blen, &pos, 1);
			buffer_serialize_string(buf, blen, &pos, s->name);
		}
	}

	return pos;
}


/*------------------------------------------------*/
/* function : singleton_unserialize                 */
/* description: Serializes a signature            */
/*------------------------------------------------*/

static size_t singleton_unserialize(char * buf, size_t blen, psig_t ** s, int version)
{
	char tmp[512];
	size_t pos = 0;
	char c;
	int num, i;
	ea_t ea;
	int type;

	*s = sig_init();
	if (!(*s)) return 0;

	buffer_unserialize_ea(buf, blen, &pos, &(*s)->startEA);

	buffer_unserialize_int(buf, blen, &pos, &(*s)->mtype);

	buffer_unserialize_int(buf, blen, &pos, &(*s)->id_crc);
	buffer_unserialize_int(buf, blen, &pos, &(*s)->nfile);

	buffer_unserialize_long(buf, blen, &pos, &(*s)->sig);
	buffer_unserialize_long(buf, blen, &pos, &(*s)->hash);
	buffer_unserialize_long(buf, blen, &pos, &(*s)->crc_hash);
	
	if (version >= 2)
		buffer_unserialize_long(buf, blen, &pos, &(*s)->str_hash);
	if (version >= 3)
		buffer_unserialize_int(buf, blen, &pos, &(*s)->flag);

	buffer_unserialize_long(buf, blen, &pos, &(*s)->lines);

	buffer_unserialize_int(buf, blen, &pos, &num);
	for (i=0; infile == 2)
	{
		buffer_unserialize_char(buf, blen, &pos, &c);
		
		if (c == 1)
			buffer_unserialize_string(buf, blen, &pos, &(*s)->name);
		else
		{
			qsnprintf(tmp, sizeof(tmp), "sub_%" PRIea_t, (*s)->startEA);
			sig_set_name((*s), tmp);
		}
	}
	else
	{
		pget_func_name((*s)->startEA, tmp, sizeof(tmp));
		sig_set_name(*s, tmp);
	}

	return pos;
}


/*------------------------------------------------*/
/* function : pair_serialize                      */
/* description: Serializes a signature and the    */
/*              matched signature                 */
/*------------------------------------------------*/

static size_t pair_serialize(char * buf, size_t blen, psig_t * s)
{
	size_t len;

	len = singleton_serialize(buf, blen, s, 1);
	len += singleton_serialize(buf+len, blen-len, s->msig, 2);

	return len;
}


/*------------------------------------------------*/
/* function : pair_unserialize                    */
/* description: Unserializes a signature and the  */
/*              matched signature                 */
/*------------------------------------------------*/

static size_t pair_unserialize(char * buf, size_t blen, psig_t ** s, int version)
{
	size_t len;

	len = singleton_unserialize(buf, blen, s, version);
	len += singleton_unserialize(buf+len, blen-len, &(*s)->msig, version);

	(*s)->msig->msig = (*s);

	return len;
}


/*------------------------------------------------*/
/* function : backup_save_list                    */
/* description: Backups result list inside a      */
/*              netnode                           */
/*------------------------------------------------*/

static void backup_save_list(const char *node_name, slist_t * sl)
{
	char buf[5000];
	size_t i;
	size_t len;
	netnode node;

	if (!sl) return;

	node.create(node_name);

	for (i=0; inum; i++)
	{
		nodeidx_t nidx = node.altval(i);
		if (nidx != 0)
		{
			msg("backup failed: netnode already exists !!\n");
			return;
		}

		netnode n(nidx);

		n.create();
		node.altset(i, n);

		if (sl->sigs[i]->msig != NULL)
			len = pair_serialize(buf, sizeof(buf), sl->sigs[i]);
		else
			len = singleton_serialize(buf, sizeof(buf), sl->sigs[i], sl->sigs[i]->nfile);

		n.setblob(buf, len, 0, 'P');
	}
}


/*------------------------------------------------*/
/* function : backup_load_list                    */
/* description: Loads result list from a netnode  */
/*------------------------------------------------*/

static bool backup_load_list(const char *node_name, slist_t * sl, int type, int version)
{
	char buf[5000];
	size_t i;
	size_t len;
	netnode node;
	nodeidx_t nidx;

	if (!sl) return true;

	node.create(node_name);

	for (i=0; iorg_num; i++)
	{
		nidx = node.altval(i);
		if (nidx == BADNODE)
		{
			msg("backup failed: netnode does not exist !!\n");
			return false;
		}
		
		netnode n(nidx);

		len = sizeof(buf);
		if (!n.getblob(buf, &len, 0, 'P'))
		{
			msg("backup failed: netnode blob does not exist !!\n");
			return false;
		}

		if (type)
			pair_unserialize(buf, len, &sl->sigs[i], version);
		else
			singleton_unserialize(buf, len, &sl->sigs[i], version);
	}

	sl->num = sl->org_num;

	return true;
}


/*------------------------------------------------*/
/* function : backup_free_node                    */
/* description: Removes node from the IDB         */
/*------------------------------------------------*/

static void backup_free_node(const char *node_name, size_t size)
{
	netnode node;
	size_t i;

	node.create(node_name);

	for (i=0; imlist ? eng->mlist->org_num : 0);
	backup_free_node("$ pdiff2_identical", eng->ilist ? eng->ilist->org_num : 0);
	backup_free_node("$ pdiff2_unmatched", eng->ulist ? eng->ulist->org_num : 0);

	backup_free_node("$ pdiff2_eng", 1);
}


/*------------------------------------------------*/
/* function : backup_save_eng                     */
/* description:Saves engine data inside a netnode */
/*------------------------------------------------*/

static void backup_save_eng(const char *node_name, deng_t * eng)
{
	char buf[1000];
	char * file;
	size_t pos = 0;
	netnode node;
	size_t msize, isize, usize;

	node.create(node_name);

	nodeidx_t nidx = node.altval(0);
	if (nidx != 0)
	{
		backup_cleanup(eng);
		node.create(node_name);

		nidx = node.altval(0);
		if (nidx != 0)
		{
			msg("backup eng failed: netnode already exists !!\n");
			return;
		}
	}

	netnode n(nidx);

	n.create();
	node.altset(0, n);

	msize = isize = usize = 0;
	if (eng->mlist)
	{
		file = eng->mlist->file;
		msize = eng->mlist->num;
	}
	if (eng->ilist)
	{
		file = eng->ilist->file;
		isize = eng->ilist->num;
	}
	if (eng->ulist)
	{
		file = eng->ulist->file;
		usize = eng->ulist->num;
	}

	buffer_serialize_int(buf, sizeof(buf), &pos, PDIFF_BACKUP_VERSION);
	buffer_serialize_string(buf, sizeof(buf), &pos, file);
	buffer_serialize_size(buf, sizeof(buf), &pos, msize);
	buffer_serialize_size(buf, sizeof(buf), &pos, isize);
	buffer_serialize_size(buf, sizeof(buf), &pos, usize);
	buffer_serialize_bool(buf, sizeof(buf), &pos, eng->opt->ipc);

	n.setblob(buf, pos, 0, 'P');
}


/*------------------------------------------------*/
/* function : backup_load_file                    */
/* description:Loads engine data inside a netnode */
/*------------------------------------------------*/

static deng_t * backup_load_eng(const char *node_name, options_t * opt, int * version)
{
	char buf[1000];
	deng_t * eng;
	char * file = NULL;
	size_t blen, pos = 0;
	netnode node;
	size_t msize, isize, usize;

	node.create(node_name);

	nodeidx_t nidx = node.altval(0);
	if (nidx == 0)
		return NULL;

	netnode n(nidx);

	blen = sizeof(buf);
	n.getblob(buf, &blen, 0, 'P');
	if (!blen)
		return NULL;

	eng = (deng_t *)qalloc(sizeof(*eng));
	if (!eng)
		return NULL;

	eng->magic = 0x0BADF00D;
	eng->wnum = 0;
	eng->opt = opt;
	msize = isize = usize = 0;

	buffer_unserialize_int(buf, sizeof(buf), &pos, version);
	buffer_unserialize_string(buf, sizeof(buf), &pos, &file);
	buffer_unserialize_size(buf, sizeof(buf), &pos, &msize);
	buffer_unserialize_size(buf, sizeof(buf), &pos, &isize);
	buffer_unserialize_size(buf, sizeof(buf), &pos, &usize);
	buffer_unserialize_bool(buf, sizeof(buf), &pos, &eng->opt->ipc);

	// no need to save that in the IDB
	eng->opt->save_db = true;

	eng->mlist = siglist_init(msize, file);
	eng->ilist = siglist_init(isize, file);
	eng->ulist = siglist_init(usize, file);

	return eng;
}


/*------------------------------------------------*/
/* function : backup_save_results                 */
/* description: Saves diff results inside the     */
/*              IDB                               */
/*------------------------------------------------*/

void backup_save_results(deng_t * eng)
{
	backup_save_eng("$ pdiff2_eng", eng);

	backup_save_list("$ pdiff2_matched", eng->mlist);
	backup_save_list("$ pdiff2_identical", eng->ilist);
	backup_save_list("$ pdiff2_unmatched", eng->ulist);
}


/*------------------------------------------------*/
/* function : backup_load_results                 */
/* description: Loads diff results from the IDB   */
/*------------------------------------------------*/

int backup_load_results(deng_t ** eng, options_t * opt)
{
	int ret;
	int version;

	if (*eng)
	{
		ret = askbuttons_c("Reuse", "Refresh", "Cancel", 1,
						"Previous diff results have been found. Please specify the action to perform.");

		if (ret == 0)
		{
			diff_engine_free(*eng);
			*eng = NULL;
		}

		return ret;
	}


	*eng = backup_load_eng("$ pdiff2_eng", opt, &version);
	if (!(*eng)) return 0;

	ret = askbuttons_c("Reuse", "Refresh", "Cancel", 1,
						"Previous diff results have been found. Please specify the action to perform.");

	if (ret != 1) goto error;

	msg("Loading backup results... ");
	if (!backup_load_list("$ pdiff2_matched", (*eng)->mlist, 1, version)) goto error;
	if (!backup_load_list("$ pdiff2_identical", (*eng)->ilist, 1, version)) goto error;
	if (!backup_load_list("$ pdiff2_unmatched", (*eng)->ulist, 0, version)) goto error;
	msg("done.\n");

	return ret;

error:
	diff_engine_free(*eng);
	*eng = NULL;

	return ret;
}

Web Proxy Viewer  |  New URL  |  Original Page