1 of 15

Stack and Buffer Overflow

Author : Md. Monowarul Amin, BSc. In SWE (Batch-20), IUT

1

2 of 15

Objective

  • Introducing Stack of our memory
  • The power of knowing about Stack

2

Process’ memory

Code

3 of 15

How generate the binary for this…

Flags’ Description

  • -fno-stack-protector -> Disable Canary
  • -g -> For debugging with gdb (gnu debugger)
  • O0 -> No optimization by the compiler
  • -no-pie -> Disable dynamic memory address
  • -m32 -> Generate binary for a 32-bit system

3

4 of 15

Buffer Overflow Overview

  • At first, execute line 22 by user input
  • Secondly, execute the hidden() function

although no one called it.

4

5 of 15

Representation of main() in stack

ebp(previous)

ebp(main)

stack

  • At the very beginning, there is the base pointer(ebp)

of the previous function.

esp

6 of 15

Representation of main() in stack

6

ebp(previous)

ebp(main)

ebx

ecx

1(a)

2(b)

stack

Local Variables

  • At the very beginning, there is the base pointer(ebp)

of the previous function.

  • Next, it pushes the values of local variables (a, b in this function)

ebp - 4

ebp - 8

ebp - 12

ebp - 16

esp

7 of 15

Representation of main() in stack

ebp(previous)

ebx

ecx

1(a)

2(b)

-

-

2(b)

1(a)

ebp(main)

Function

parameters

  • At the very beginning, there is the base pointer(ebp)

of the previous function.

  • Next, it pushes the values of local variables (a, b in this function)
  • Then comes the Function Parameters in reverse order. The last parameter is pushed first.

ebp - 4

ebp - 8

ebp - 12

ebp - 16

ebp - 20

ebp - 24

ebp - 28

ebp - 32

esp

8 of 15

Representation of main() in stack

8

ebp(previous)

ebx

ecx

1(a)

2(b)

-

-

2(b)

1(a)

ret

ebp(main)

stack

  • At the very beginning, there is the base pointer(ebp)

of the previous function.

  • Next, it pushes the values of local variables (a, b in this function)
  • Then comes the Function Parameters in reverse order. The last parameter is pushed first.
  • Finally, the return address has been pushed. (The address from where the execution will continue after returning from callee)

ebp - 4

ebp - 8

ebp - 12

ebp - 16

ebp - 20

ebp - 24

ebp - 28

ebp - 32

ebp - 36

esp

9 of 15

Inside Callee()’s Stack

9

ebp(main)

ebx

-

91(f)

(c)

buff

buff

buff

buff

buff

ebp(callee)

stack

  • At the very beginning, there is the base pointer(ebp)

of the main().

  • The rest are similar to the previous one.
  • Now the vulnerable function gets() starts taking input from (ebp – 36) and goes upper wards.

ret

ebp - 4

ebp - 8

ebp - 12

ebp - 16

ebp - 20

ebp - 24

ebp - 28

ebp - 32

ebp - 36

gets() inserts

esp

10 of 15

Overwriting Variable’s value

10

ebp(main)

ebx

-

91(f)

(c)

buff

buff

buff

buff

buff

ebp(callee)

stack

  • Now how to modify the value of (f) to 1 so that line 22 (the desired printf() function) can be executed?

ret

ebp - 4

ebp - 8

ebp - 12

ebp - 16

ebp - 20

ebp - 24

ebp - 28

ebp - 32

ebp - 36

gets() inserts

  • At first, insert 24 bytes of garbage value, then 1 in hex format ( 0x 00 00 00 01).
  • Now, f=1, and the condition gets satisfied and the expected printf() also gets executed…..

esp

11 of 15

Modify Variable’s value(contd…)

  • This time we will generate the exact payload
  • At first, insert 20 bytes of garbage value, then 1 in hex format ( 0x 00 00 00 01).
  • Now, f=1, and the condition gets satisfied and the expected printf() also gets executed…..

python2 -c "print('A' * 24 + '\x01\x00\x00\x00')" |./buffer_overflow1

12 of 15

Jumping to Another Function

12

ebp(main)

ebx

-

91(f)

(c)

buff

buff

buff

buff

buff

ebp(callee)

stack

  • Insert 40 bytes of garbage value to overwrite upto ebp(main).
  • Then overwrite the value of ret with the value of hidden() function’s starting address (in this case 0x8049196).

ret

ebp - 4

ebp - 8

ebp - 12

ebp - 16

ebp - 20

ebp - 24

ebp - 28

ebp - 32

ebp - 36

gets() inserts

  • The hidden() function declared here not invoked by any other function.
  • Now when callee() completes its execution, instead of returning to main(), how can we jump to the hidden() and execute it?

13 of 15

Jumping to Another Function(contd..)

13

ebp(main)

ebx

-

91(f)

(c)

buff

buff

buff

buff

buff

ebp(callee)

stack

Payload

ret

ebp - 4

ebp - 8

ebp - 12

ebp - 16

ebp - 20

ebp - 24

ebp - 28

ebp - 32

ebp - 36

gets() inserts

  • How to get the starting address of the hidden function?
  • Inside gdb, execute print hidden

python2 -c "print('A' * 40 + '\x96\x91\x04\x08')" | ./buffer_overflow1

Note: Why the address inserted in this way?

As our system is Little Endian

14 of 15

Reference

  • Hacking: The Art of Exploitation, 2nd Edition by Jon Erickson (Author)
  • https://www.cs.virginia.edu/~evans/cs216/guides/x86.html

14

15 of 15

Thank You