Practical Reverse Engineering - Ex 2

1 - A) Given what you learned about CALL and RET, explain how you would read the value of EIP ?

EIP is used to save the return address after a CALL or a RET for example. In this way, the program will resume correctly and it can continue the execution flow.

I’ll use a CALL to a function to modify EIP. Inside this function, we have to save the value of EIP inside a register. Next, we print the content of this register.

Code:

SECTION  .text
GLOBAL _start
_start: 
    call store_eip
    mov  ebx,0         
    mov  eax,1         
    int 080h         

store_eip:
    mov eax, [esp]
    ret

Code Explaination:

  • .text section is used for the program code (while .data is used for constants)
  • GLOBAL _start is used to declare the symbol
  • Call the function store_eip
  • We set eax to the value pointed by esp Don’t forget: when a function is call without arguments, ESP point to the bottom of the stack which contain the value of the return address function (EIP)
  • We use int 080h to use syscall. In our case, EAX = 0 so the syscall will be exit()

Installation des pré-requis:

sudo apt install nasm

Compilation:

$ nasm -f elf32 -g -F drawf prr2_ex1.asm
$ ld -m elf_i386 -o prr_ex1 prr2_ex1.o

We put a breakpoint on call store_eip and on ret using gdb.

We put a breakpoint on ret using gdb We start the program and read EIP:

image_todo

Then we read the content of EAX:

image_todo

They are both equal

1 - B) Why can’t you just do mov EAX, EIP ?

TODO

2) Come up with at least two code sequencies to set EIP to 0xAABBCCDD ?

Version A:

SECTION .data
SECTION .text
GLOBAL _start
_start:
    mov eax, AABBCCDDh
    call eax

Version B:

SECTION .data
SECTION .text
GLOBAL _start
_start:
    jmp AABBCCDDh

3) In the example function ADDME, what would happen if the stack pointer were not properly restored before executing RET ?

TODO

4) In all of the calling conventions explained, the return value is stored in a 32-bit register (EAX). What happens when the return values does not fit in a 32-bit register ? Write a program to experiment and evaluate your answer. Does the mechanism change from compiler to compiler ?

TODO