Image
 
linkedin_logo.png rss_logo.jpg
twitter_logo.png youtube_logo.jpg
Latest Additions
 
EH-Net Login
Welcome Guest.






Lost Password?
No account yet? Register
Who's Online
We have 38 guests online
 
Advertisement

You are here: Home arrow Ethical Hacking Discussions and Related Certificationsarrow Network Pen Testingarrow Trying to understand i686 architecture
EH-Net
May 21, 2013, 11:23:03 AM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: Go back to The Ethical Hacker Network Online Magazine Home Page
 
   Home   Help Calendar Login Register  
Pages: [1] 2   Go Down
  Print  
Author Topic: Trying to understand i686 architecture  (Read 10295 times)
0 Members and 1 Guest are viewing this topic.
jacksmash
Newbie
*
Offline Offline

Posts: 14


View Profile
« on: February 24, 2010, 09:24:06 AM »

Hi,

I'm hoping someone can help me with this.

The command `uname -r` gives the following output on my machine:

Code:
Linux ***-ubuntu 2.6.31-14-generic #48-Ubuntu SMP Fri Oct 16 14:04:26 UTC 2009 i686 GNU/Linux

(Note: I am running Ubuntu 9.04 on VirtualBox)

Here is some code that I am trying to run:

Code:
#include <stdio.h>

void function(int a, int b, int c) {
  char buffer1[5];
  char buffer2[10];
  int *ret;

  ret = (int *)buffer1 + 16;
  (*ret) += 7; // have checked to make sure we need 7 bytes to skip x=1;
}

void main() {
  int x;

  x = 0;
  function(1,2,3);
  x = 1;
  printf("%d\n",x);
}


The goal of the above code is to skip the instruction `x = 1;`, and so the output of the printf statement should be "0".

However, in order to do that I need to know precisely how much to increment the return pointer in "function". This is where I'm a bit stuck.

I have been reading an article that has been somewhat helpful:

http://www.ethicalhacker.net/content/view/122/2/

It has helped me to understand that the `(*ret) += 7;` statement is likely correct.

Here is an assembly dump of the main function:

Code:
(gdb) disassemble main
Dump of assembler code for function main:
0x08048404 <main+0>: push   %ebp
0x08048405 <main+1>: mov    %esp,%ebp
0x08048407 <main+3>: sub    $0x10,%esp
0x0804840a <main+6>: movl   $0x0,-0x4(%ebp)
0x08048411 <main+13>: movl   $0x3,0x8(%esp)
0x08048419 <main+21>: movl   $0x2,0x4(%esp)
0x08048421 <main+29>: movl   $0x1,(%esp)
0x08048428 <main+36>: call   0x80483e4 <function>
[B]0x0804842d <main+41>: movl   $0x1,-0x4(%ebp)[/B] <-- [I]the instruction to skip[/I]
0x08048434 <main+48>: mov    $0x8048510,%eax
0x08048439 <main+53>: mov    -0x4(%ebp),%edx
0x0804843c <main+56>: mov    %edx,0x4(%esp)
0x08048440 <main+60>: mov    %eax,(%esp)
0x08048443 <main+63>: call   0x804831c <printf@plt>
0x08048448 <main+68>: leave 
0x08048449 <main+69>: ret   
End of assembler dump.

Since we want to skip the statement at 0x0804842d and get to 0x08048434, we can calculate the difference to by 7 bytes easily enough. Hence, that's why I know it's correct to increment the ret pointer by 7.

What I can't figure out for the life of me is how many bytes have been allocated on the stack.

The memory layout should be like this:

Code:
bottom of                                                                                    top of
memory                                                                                       memory
                              buffer2     buffer1     sfp     ret
<------                    [            ][           ][     ][     ]

top of                                                                                        bottom of
stack                                                                                         stack

My best guess is from this line:

Code:
0x08048407 <main+3>: sub    $0x10,%esp

... which suggests 16 bytes have been allocated, hence: `ret = (int *)buffer1 + 16;`

But, compiling and executing the program does not result in skipping the x=1 command.

So, I'm not asking anyone to tell me what the answer is (believe it or not). in terms of what the right number is. Rather, I'm hoping that someone can point me in the right direction so I can understand the stack layout on the machine.

Hope this makes sense. Thanks for any advice!!
Logged
zeroflaw
Full Member
***
Offline Offline

Posts: 208



View Profile
« Reply #1 on: February 24, 2010, 09:55:52 AM »

What exactly are you doing to change the return address? How are you actually changing the stack? The function doesn't return to the address in your ret variable, it returns to the return value that's placed on the stack.

Also, did you keep in mind that the function arguments are also placed on the stack? The return address is placed between the saved frame pointer (or local variables) and function arguments.

Hope this helps.

ZF
« Last Edit: February 24, 2010, 09:59:57 AM by zeroflaw » Logged

ZF
jacksmash
Newbie
*
Offline Offline

Posts: 14


View Profile
« Reply #2 on: February 24, 2010, 10:02:38 AM »

Yes, you are correct about the function variables. I should have drawn the stack like this:
Code:
bottom of                                                                                             top of
memory                                                                                                memory
               buffer2    buffer1       Slack    sfp      ret   a      b       c
<------    [            ][            ][       ][     ][     ][     ][     ][     ]

top of                                                                                                    bottom of
stack                                                                                                     stack

As for the return address, I'm trying to point "ret" to the return address of function, and then increment that address so it skips the x=1 instruction in the main function.
Logged
zeroflaw
Full Member
***
Offline Offline

Posts: 208



View Profile
« Reply #3 on: February 24, 2010, 10:43:47 AM »

Excuse me for my ignorance. I didn't read the first post properly. You were actually changing the return address by pointing to it's location and then incrementing it, doh! That should work. Tongue

The problem lies in this piece of code;

ret = (int *)buffer1 + 16;

You need to take the the sum of buffer1 and 16 together en then cast it to an int pointer. So it goes like this;

ret = (int *)(buffer1 + 16);

This should do the trick assuming the rest of your math is correct.

ZF
Logged

ZF
jacksmash
Newbie
*
Offline Offline

Posts: 14


View Profile
« Reply #4 on: February 24, 2010, 10:54:50 AM »

Ok, thanks. At least now I'm getting a segmentation fault. Now back to my original question. How do I figure out how much space there is between buffer1 and ret (on the stack)?

Thanks for your patience!
Logged
zeroflaw
Full Member
***
Offline Offline

Posts: 208



View Profile
« Reply #5 on: February 24, 2010, 11:51:06 AM »

You have to keep in mind that the bytes are aligned on the stack with 4 byte values.

So let's say we have a 22 byte local buffer filled with a's. The bottom part of your stack looks like these.

----------------------------------------------------------------------

0       a a a a
4       a a a a
8       a a a a
12      a a a a
16      a a a a
20      a a 0 0  <- The compiler puts some padding to keep things properly aligned.
24      %%%% <- sfp
28       %%%% <- eip/ret

----------------------------------------------------------------------

When you you picture it like this, the math should be easy enough Wink

ZF




« Last Edit: February 24, 2010, 12:02:42 PM by zeroflaw » Logged

ZF
jacksmash
Newbie
*
Offline Offline

Posts: 14


View Profile
« Reply #6 on: February 24, 2010, 11:59:16 AM »

Ok, so let's see if I understand this then.

buffer1's size is 10 bytes. So that's going to be 12 bytes on the bottom of the stack.

The sfp's size is 4 bytes, so that's going to be a total of 16 bytes to move the ret pointer to eip/ret

Does that make sense? There must be something I'm missing though, because incrementing by 16 bytes, and then by 7 bytes (as previously explained) just causes a seg fault.

Thanks for your help with this.
Logged
zeroflaw
Full Member
***
Offline Offline

Posts: 208



View Profile
« Reply #7 on: February 24, 2010, 12:42:46 PM »

Correct, you need to move it 16 bytes to get to eip. Now there's something wrong with the value you're adding. You made an error in your calculation. You're almost there!

ZF
Logged

ZF
jacksmash
Newbie
*
Offline Offline

Posts: 14


View Profile
« Reply #8 on: February 24, 2010, 12:50:05 PM »

Do you mean there's an error when I add '7' ??

The only thing I can think of at this point is I need to add another 4 bytes to get it past eip. Is that what you mean? Because I think the 7 is correct, because that's how many bytes I need to get past the 'x=1' statement.

Cheers.
Logged
zeroflaw
Full Member
***
Offline Offline

Posts: 208



View Profile
« Reply #9 on: February 24, 2010, 01:15:42 PM »

The 7 is unfortunately incorrect. It's not enough for the whole jump. Check your math again.

ZF

Logged

ZF
jacksmash
Newbie
*
Offline Offline

Posts: 14


View Profile
« Reply #10 on: February 24, 2010, 01:20:11 PM »

Ok.

Instead of just guessing, I'm obviously not understanding something.

If we consider this assembly breakdown:

Code:
0x0804842d <main+41>: movl   $0x1,-0x4(%ebp)[/B] <-- [i]the instruction to skip[/i]
0x08048434 <main+48>: mov    $0x8048510,%eax

The first instruction is where "1" gets assigned to "x". Now, I want to move past this instruction to the next one, do I not? That's where I'm getting the '7' from.
Logged
zeroflaw
Full Member
***
Offline Offline

Posts: 208



View Profile
« Reply #11 on: February 24, 2010, 04:15:48 PM »

I've been messing around with this for a while, and I'm guessing it also has something to do with alignment. I'm not 100% sure of this, and I will look into it. 7 seems correct, but maybe the layout of your stack is different. I compiled it with Visual C++ and I need to add 10 for it to work. I feel stupid for providing you with the wrong information. I assumed the memory layout would be the same.

Edit: Apparently it is about the compiler and alignment. I also found this article which explains it.

http://www.ethicalhacker.net/content/view/122/2/

Hope this solves your problem!

ZF
« Last Edit: February 25, 2010, 07:12:25 AM by zeroflaw » Logged

ZF
jacksmash
Newbie
*
Offline Offline

Posts: 14


View Profile
« Reply #12 on: February 25, 2010, 09:11:40 AM »

Don't feel stupid. I appreciate your willingness to work through this with me.

I already included a link to the article you mentioned... so it helps to a point, but I'm obviously still missing something.
Logged
zeroflaw
Full Member
***
Offline Offline

Posts: 208



View Profile
« Reply #13 on: February 25, 2010, 10:54:14 AM »

I found the solution, when I decided to debug the whole thing on Ubuntu. If you inspect the stack layout, you will see the compiler put some extra space. The article describes this as "slack".

Run GDB, set a breakpoint at buffer1. And Inspect the stack memory for buffer1 with the command "x/8 buffer1", you will actually see the return address and some slack space. I disassembled main to be sure that it's the right address.

I'll show you some of the output to clear things up.

-----------------------------------------------------------------
(gdb) list function
1 void function(int a, int b, int c) {
2 char buffer1[5];
3 char buffer2[10];
4 int *ret;
5
6 ret = (int*)(buffer1 + 12);
7 (*ret) += 7;
8 }
9
10 void main() {
(gdb) break 2
Breakpoint 1 at 0x804837a: file ret.c, line 2.
(gdb) run
Starting program: /home/zeroflaw/Desktop/ret

Breakpoint 1, function (a=1, b=2, c=3) at ret.c:6
6 ret = (int*)(buffer1 + 12);
(gdb) x/8 buffer1
0xbffff7e0: 0xb7f9f729 0xb7fd6ff4 0xbffff818 0x08048419
0xbffff7f0: 0xb7fd6ff4 0xbffff8ac 0xbffff818 0x080483c5
(gdb) disas main
Dump of assembler code for function main:
0x08048392 <main+0>: push %ebp
0x08048393 <main+1>: mov %esp,%ebp
0x08048395 <main+3>: sub $0x18,%esp
0x08048398 <main+6>: and $0xfffffff0,%esp
0x0804839b <main+9>: mov $0x0,%eax
0x080483a0 <main+14>: sub %eax,%esp
0x080483a2 <main+16>: movl $0x0,0xfffffffc(%ebp)
0x080483a9 <main+23>: movl $0x3,0x8(%esp)
0x080483b1 <main+31>: movl $0x2,0x4(%esp)
0x080483b9 <main+39>: movl $0x1,(%esp)
0x080483c0 <main+46>: call 0x8048374 <function>
0x080483c5 <main+51>: movl $0x1,0xfffffffc(%ebp) <-- Skipping this instruction.
0x080483cc <main+58>: mov 0xfffffffc(%ebp),%eax
0x080483cf <main+61>: mov %eax,0x4(%esp)
0x080483d3 <main+65>: movl $0x80484c4,(%esp)
0x080483da <main+72>: call 0x80482a0 <printf@plt>
0x080483df <main+77>: leave
0x080483e0 <main+78>: ret
End of assembler dump.

-----------------------------------------------------------------

You can see buffer1 starts at address 0xbffff7e0 and the return address is at 0xbffff7fc. 0xbffff7fc - bffff7e0 = 28. The correct value in this case is 28!

I guess it's important to keep in mind what the compiler does. Also not every stack uses a saved frame pointer! So it's important to always dive into the assembly instructions and inspect memory carefully.

I also learned a lot from this, so thanks for posting your question Cheesy

ZF
Logged

ZF
jacksmash
Newbie
*
Offline Offline

Posts: 14


View Profile
« Reply #14 on: February 25, 2010, 11:11:05 AM »

Ok, two things:

1. When you say the return address is at 0xbffff7fc, where did you get that from? Did you mean 0xbffff7f0??

2. How are you compiling ret.c? When I run 'x/8 buffer1', I get this weird output:

0xbffff467:   75784192   -751608   -751425   75770815
0xbffff477:   264   512   768   0

which isn't very helpful to me!

THanks Smiley
Logged
Pages: [1] 2   Go Up
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines
Joomla Bridge by JoomlaHacks.com
Valid XHTML 1.0! Valid CSS!
Page created in 0.075 seconds with 22 queries.
 
Exclusive Deal

sansfire13_245x90_cw90.jpg
SANSFIRE 2013
June 15 - 22

5% Off w/ Code: EHN_5

SANS Deals 4 EH-Netters
5% OFF Any SANS Course in Any Format!
Coupon Code: EHN_5 Including SANS Rocky Mountain 2013 & SANS Boston 2013
Polls
Compared to this year, 2013 will be:
 
Recent Forum Topics
EH-Net News Feeds
Latest Additions
 
         
Advertisement

© 2013 The Ethical Hacker Network
Joomla! is Free Software released under the GNU/GPL License.