Go Down

Topic: Handle memory (Read 14176 times) previous topic - next topic

AWOL

See replies #16 and #28.

radman

Quote
The goal of the project is attack the board exploiting stack buffer overflows, hence finding the return address to overwriting with a pointer.

Are those the actual requirements as given to you?
Were you given the program?

Are you sure you are not supposed to write a program that loops printing "Hello World" then demonstrate that by using input to cause a buffer overflow you can get it to loop saying "Hacked!" instead?

DarkCoffee

#32
Aug 16, 2013, 06:24 pm Last Edit: Aug 16, 2013, 06:39 pm by DarkCoffee Reason: 1

See replies #16 and #28.

That is like the memories location that I get with disassemble.  But they are different from the stack memories location....


Quote
The goal of the project is attack the board exploiting stack buffer overflows, hence finding the return address to overwriting with a pointer.

Are those the actual requirements as given to you?
Were you given the program?

Are you sure you are not supposed to write a program that loops printing "Hello World" then demonstrate that by using input to cause a buffer overflow you can get it to loop saying "Hacked!" instead?



The requirement is: try to hack a program that they give me, but initially, write a small program that has the vulnerability and try the concept of the attack on this small program.
Yes, I'm sure.

P.S.: Thank you everyone, for helping me.

nickgammon

Now I'm confused. This should print the stack pointer:

Code: [Select]

void setup ()
  {
  Serial.begin (115200);
  }  // end of setup

void foo ()
  {
  Serial.println (SP, HEX); 
  }
 
void loop ()
  {
  foo ();
  delay (1000);
  }  // end of loop


SP is defined as the memory location of the stack pointer, and indeed the generated code seems right:

Code: [Select]

000000be <_Z3foov>:
  be: 6d b7        in r22, 0x3d ; 61
  c0: 7e b7        in r23, 0x3e ; 62
  c2: 8d e9        ldi r24, 0x9D ; 157
  c4: 91 e0        ldi r25, 0x01 ; 1
  c6: 40 e1        ldi r20, 0x10 ; 16
  c8: 50 e0        ldi r21, 0x00 ; 0
  ca: 0e 94 3d 04 call 0x87a ; 0x87a <_ZN5Print7printlnEji>
  ce: 08 95        ret


0x3d and 0x3e are indeed the stack pointer location as defined in the datasheet. But what does it print?

Code: [Select]

8F7


Trouble is, the processor only has 2048 bytes of memory (0x800 bytes) so it seems its stack is outside available memory. And if you clear the high-order bit (making it 0xF7) then the address is ridiculously low.

It seems to set up the stack here in the "constructors end" code:

Code: [Select]

0000006a <__ctors_end>:
  6a: 11 24        eor r1, r1
  6c: 1f be        out 0x3f, r1 ; 63
  6e: cf ef        ldi r28, 0xFF ; 255
  70: d8 e0        ldi r29, 0x08 ; 8
  72: de bf        out 0x3e, r29 ; 62
  74: cd bf        out 0x3d, r28 ; 61

Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

DarkCoffee

I want to thank you again for helping me.

In realty I think I need to know the stack in a certain moment.
For example if I have to do this in c on a x86 architecture I would have done it in this way:

Code: [Select]
getInput(){
  char buff[8];
  getc(buff);
  putc(buff);
}

int main(){
  getInput();
  return 0;
}

and with gdb I would have set a breakpoint on getInput and step into, reading the first 4 bytes of the memory stack.
for example:
Code: [Select]
0xbfafffff: 0x08044444 0xb8888888 0xbfafffff1f ax01111111
where the last (ax01111111) is indeed the next instruction in the main (return 0);

I would like to do the same with my atmega2560.

nickgammon


In realty I think I need to know the stack in a certain moment.


Yes, I understand that.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

Coding Badly

Now I'm confused. This should print the stack pointer:


It actually does.  Wait for it (we need some suspense)...

Code: [Select]
8F7
Quote
Trouble is, the processor only has 2048 bytes of memory (0x800 bytes) so it seems its stack is outside available memory.


It (sort of) actually has more memory than that.  The first 0x100 memory addresses are the I/O registers.  Addresses 0x100 through 0x8FF are SRAM.  So, the stack starts at 0x8FF instead of 0x7FF.  0x8F7 indicates eight bytes are on the stack (0x8FF - 0x8F7).  CRT0 to main = 2 bytes. main (unfortunately) preserves r28 and r29 = 2 bytes.  main to loop = 2 bytes.  loop to foo = 2 bytes.

nickgammon

Thank you, now that's a trap for young players. And to think I used to wonder why the compiler allocated the first variable at address 0x100! I assumed there must have been 100 bytes for other purposes, or (more reasonably) so it didn't clash with the registers. So the first byte of RAM is at 0x100. Now I learned something new.

@DarkCoffee: The variable "SP" gives you the "stack at a certain moment".
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

nickgammon

Well I'm not recommending this at all, but this seems to work:

Code: [Select]

void setup ()
  {
  Serial.begin (115200);
  }  // end of setup

void bar ()
  {
  Serial.println ("hacked!");
  while (true); 
  }
 
void foo ()
  {
  Serial.println ("in foo.");
  // corrupt return address
  unsigned int * stack = (unsigned int *) SP;
  stack [1] = (unsigned int) bar;
  }
 
void loop ()
  {
  foo ();
  }  // end of loop


Output:

Code: [Select]

in foo.
hacked!
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

nickgammon

Just a tip for anyone following this thread. The program address stored on the stack is in words, not bytes. So for example:

Code: [Select]

00000110 <loop>:
110: 0e 94 5f 00 call 0xbe ; 0xbe <_Z3foov>
114: 89 ea       ldi r24, 0xA9 ; 169
116: 91 e0       ldi r25, 0x01 ; 1
118: 64 e0       ldi r22, 0x04 ; 4
11a: 71 e0       ldi r23, 0x01 ; 1
...


The stack contained 0x00/0x8A (which is half of 0x114).

This implies that all instructions occupy an even number of bytes.

Also note that to call 0xBE (foo) the instruction is 0e 94 5f 00 where 0X5F is half of 0xBE.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

DarkCoffee


Well I'm not recommending this at all, but this seems to work:

Code: [Select]

void setup ()
  {
  Serial.begin (115200);
  }  // end of setup

void bar ()
  {
  Serial.println ("hacked!");
  while (true); 
  }
 
void foo ()
  {
  Serial.println ("in foo.");
  // corrupt return address
  unsigned int * stack = (unsigned int *) SP;
  stack [1] = (unsigned int) bar;
  }
 
void loop ()
  {
  foo ();
  }  // end of loop


Output:

Code: [Select]

in foo.
hacked!



For me doesn't work  :smiley-sad-blue:
The output is "in in in in in ...." and it blocked.
I expected "in foo", but there isn't even foo... I don't understand  :smiley-red:


Just a tip for anyone following this thread. The program address stored on the stack is in words, not bytes. So for example:

Code: [Select]

00000110 <loop>:
110: 0e 94 5f 00 call 0xbe ; 0xbe <_Z3foov>
114: 89 ea        ldi r24, 0xA9 ; 169
116: 91 e0        ldi r25, 0x01 ; 1
118: 64 e0        ldi r22, 0x04 ; 4
11a: 71 e0        ldi r23, 0x01 ; 1
...


The stack contained 0x00/0x8A (which is half of 0x114).

This implies that all instructions occupy an even number of bytes.

Also note that to call 0xBE (foo) the instruction is 0e 94 5f 00 where 0X5F is half of 0xBE.

Thank you!

testato

#41
Aug 17, 2013, 12:29 pm Last Edit: Aug 17, 2013, 12:35 pm by Testato Reason: 1
for me on a mega2560, it print only
Code: [Select]
in foo.
in foo.


your code maybe work only on a 328P ?
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

nickgammon

Very likely. I tested on a Uno (Atmega328P) with IDE 1.0.5.

It probably will only work as written, as written. That is, it would be very hard to reproduce on a different processor, different compiler, or even if you add or remove one instruction.

That's why I said:

Quote
I'm not recommending this at all


I wasn't joking.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

DarkCoffee


for me also, on a mega2560, it print only
Code: [Select]
in foo.
in foo.


your code maybe work only on a 328P ?

I think so too.
Atmega2560 has the same architecture of 640/1280/1281/2561, in the datasheet there is not 328P  :(

Edit:ops, I didn't see the reply by Nick Gammon, sorry

majenko

Stack smashing is incredibly easy to do.  All you need is a local variable to which you write more data to than is allocated to it.

For instance
Code: [Select]

void foo() {
  char smasher[4];
  smasher[7] = 34; // Some byte on the stack will be corrupted
}

The trick is to know just what is on the stack and where.  That will all be compiler, chip, architecture, etc specific.  If you have no other local variables, and no parameters, then the stack will contain just the smasher[4] variable, copies of certain registers, and the return address you are interested in.  If you can find out that information then you can know which bytes to modify.  However, doing anything "useful" with it is harder.

You need to have some way of injecting the new code.  Typically this is injected as binary machine code into the buffer you are overflowing, then you tweak the return address to point to the location of said buffer.

This all means that you need a) knowledge of the layout of the stack frame for that specific function (all local variables, sizes, locations, etc), b) an ability to generate raw machine code for the target architecture, and c) a program that has a large enough vulnerable buffer to take your injected code as well as some way to get that code into the buffer.

Go Up