metasploit-framework/lib/metasm/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c

156 lines
3.8 KiB
C

#ifdef __ELF__
asm .pt_gnu_stack rw;
#endif
typedef uintptr_t VALUE;
static VALUE const_File;
static VALUE const_LinuxHeap;
VALUE rb_ary_new(void);
VALUE rb_ary_push(VALUE, VALUE);
extern VALUE *rb_cObject __attribute__((import));
VALUE rb_const_get(VALUE, VALUE);
void rb_define_method(VALUE, char*, VALUE(*)(), int);
VALUE rb_funcall(VALUE recv, unsigned int id, int nargs, ...);
VALUE rb_gv_get(const char*);
VALUE rb_intern(char*);
VALUE rb_ivar_get(VALUE, unsigned int);
VALUE rb_iv_get(VALUE, char*);
void *rb_method_node(VALUE, unsigned int);
VALUE rb_obj_as_string(VALUE);
VALUE rb_str_append(VALUE, VALUE);
VALUE rb_str_cat2(VALUE, const char*);
VALUE rb_str_new2(const char*);
VALUE rb_hash_aset(VALUE, VALUE, VALUE);
VALUE rb_hash_aref(VALUE, VALUE);
VALUE rb_uint2inum(VALUE);
VALUE rb_num2ulong(VALUE);
char *rb_string_value_ptr(VALUE*);
int printf(char*, ...);
static VALUE heap_entry(void *heap, VALUE idx, VALUE psz)
{
if (psz == 4)
return (VALUE)(((__int32*)heap)[idx]);
return (VALUE)(((__int64*)heap)[idx]);
}
static VALUE m_LinuxHeap23scan_heap(VALUE self, VALUE vbase, VALUE vlen, VALUE ar)
{
VALUE *heap;
VALUE chunks;
VALUE base = rb_num2ulong(vbase);
VALUE len = vlen >> 1;
VALUE sz, clen;
VALUE page;
VALUE psz = rb_iv_get(self, "@ptsz") >> 1;
VALUE ptr = 0;
chunks = rb_iv_get(self, "@chunks");
page = rb_funcall(self, rb_intern("pagecache"), 2, vbase, vlen);
heap = rb_string_value_ptr(&page);
sz = heap_entry(heap, 1, psz);
if (heap_entry(heap, 0, psz) != 0 || (sz & 1) != 1)
return 4;
base += 8;
for (;;) {
clen = sz & -8;
ptr += clen/psz;
if (ptr >= len/psz || clen == 0)
break;
sz = heap_entry(heap, ptr+1, psz);
if (sz & 1)
rb_hash_aset(chunks, rb_uint2inum(base), ((clen-psz)<<1)|1);
base += clen;
}
rb_funcall(self, rb_intern("del_fastbin"), 1, ar);
return 4;
}
static VALUE m_LinuxHeap23scan_heap_xr(VALUE self, VALUE vbase, VALUE vlen)
{
VALUE *heap;
VALUE chunks, xrchunksto, xrchunksfrom;
VALUE psz = rb_iv_get(self, "@ptsz") >> 1;
VALUE base = rb_num2ulong(vbase) + 2*psz;
VALUE len = vlen >> 1;
VALUE sz, clen;
VALUE page;
chunks = rb_iv_get(self, "@chunks");
xrchunksto = rb_iv_get(self, "@xrchunksto");
xrchunksfrom = rb_iv_get(self, "@xrchunksfrom");
page = rb_funcall(self, rb_intern("pagecache"), 2, vbase, vlen);
heap = rb_string_value_ptr(&page);
sz = heap_entry(heap, 1, psz);
if (heap_entry(heap, 0, psz) != 0 || (sz & 1) != 1)
return 4;
/* re-walk the heap, simpler than iterating over @chunks */
VALUE ptr = 0;
VALUE ptr0, ptrl;
for (;;) {
clen = sz & -8;
ptr0 = ptr+2;
ptrl = clen/psz-1;
ptr += clen/psz;
if (ptr >= len/psz || clen == 0)
break;
sz = heap_entry(heap, ptr+1, psz);
if ((sz & 1) &&
((rb_hash_aref(chunks, rb_uint2inum(base))|4) != 4)) {
VALUE tabto = 0;
VALUE tabfrom;
while (ptrl--) {
VALUE p = heap_entry(heap, ptr0++, psz);
//if (p == base) // ignore self-references
// continue;
if ((rb_hash_aref(chunks, rb_uint2inum(p))|4) != 4) {
if (!tabto) {
tabto = rb_ary_new();
rb_hash_aset(xrchunksto, rb_uint2inum(base), tabto);
}
rb_ary_push(tabto, rb_uint2inum(p));
tabfrom = rb_hash_aref(xrchunksfrom, rb_uint2inum(p));
if ((tabfrom|4) == 4) {
tabfrom = rb_ary_new();
rb_hash_aset(xrchunksfrom, rb_uint2inum(p), tabfrom);
}
rb_ary_push(tabfrom, rb_uint2inum(base));
}
}
}
base += clen;
}
return 4;
}
static void do_init_once(void)
{
const_LinuxHeap = rb_const_get(*rb_cObject, rb_intern("Metasm"));
const_LinuxHeap = rb_const_get(const_LinuxHeap, rb_intern("LinuxHeap"));
rb_define_method(const_LinuxHeap, "scan_heap", m_LinuxHeap23scan_heap, 3);
rb_define_method(const_LinuxHeap, "scan_heap_xr", m_LinuxHeap23scan_heap_xr, 2);
}
int Init_compiled_heapscan_lin __attribute__((export))(void)
{
do_init_once();
return 0;
}