Sicurezza Informatica - LaSERsecurity.di.unimi.it/sicurezza1314/slides/Lezione2.pdf · Stack •...

48
Sicurezza Informatica Lez. 2 Assembler (II parte) A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Transcript of Sicurezza Informatica - LaSERsecurity.di.unimi.it/sicurezza1314/slides/Lezione2.pdf · Stack •...

Sicurezza Informatica

Lez. 2 Assembler (II parte)

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Memory Layout

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Memory Layout

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Stack

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Where is stored msg?

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Why on the stack and not in .data?

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Executable structure

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Stack

•  Many CPU’s have built-in support for a stack A stack is a Last-In First-Out (LIFO) list

•  The stack is an area of memory that is organized in this fashion. The PUSH instruction adds data to the stack and the POP instruction removes data

•  The data removed is always the last data added •  The ESP register contains the address of the data that would be

removed from the stack. This data is said to be at the top of the stack •  The processor references the SS register automatically for all stack

operations. Also, the CALL, RET, PUSH, POP, ENTER, and LEAVE instructions all perform operations on the current stack.

•  Data can only be added in double word units. That is, one can not push a single byte on the stack

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Stack

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Runtime Stack

•  Managed by the CPU, using two registers •  SS (stack segment) •  ESP (stack pointer) *

* SP in Real-address mode

00000006 ESP00001000

Offset

00000FF8

00000FF4

00000FF0

00000FFC

PUSH

•  The PUSH instruction inserts a double word on the stack by subtracting 4 from ESP and then stores the double word at [ESP]

!

•  The 80x86 also provides a PUSHA instruction that pushes the values of EAX, EBX, ECX, EDX, ESI, EDI and EBP registers (not in this order)

pushl src ! à !subl $4,%esp!! ! ! ! !movl src,(%esp)!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

PUSH Operation (1 of 2) •  A 32-bit push operation decrements the stack pointer

by 4 and copies a value into the location pointed to by the stack pointer.

00000006 00000006

ESP

00001000

00000FFC

00000FF8

00000FF4

00000FF0

000000A5

ESP00001000

BEFORE

00000FFC

00000FF8

00000FF4

00000FF0

AFTER

PUSH Operation (2 of 2) •  This is the same stack, after pushing two more

integers:

00000006

ESP

00001000

Offset

00000FFC

00000FF8

00000FF4

00000FF0

000000A5

00000001

00000002

The stack grows downward. The area below ESP is always available (unless the stack has overflowed).

POP

•  The POP instruction reads the double word at [ESP] and then adds 4 to ESP

•  The popa instruction, recovers the original values of the registers saved by the pusha!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

!popl dest ! à movl (%esp),dest!! ! ! ! addl $4,%esp!

POP Operation •  Copies value at stack[ESP] into a register or variable. •  Adds n to ESP, where n is either 2 or 4.

•  depends on the operand receiving the data

BEFORE AFTER

00000006

000000A5

00000001

00000002 ESP

00000006

000000A5

00000001 ESP

00001000

00000FFC

00000FF8

00000FF4

00000FF0

00001000

00000FFC

00000FF8

00000FF4

00000FF0

Esercizio

•  Scrivere un programma in assembler che inverte il contenuto di una stringa data.

•  Esempio: •  Data la stringa: Hello World! •  Stampa la stringa: !dlroW olleH

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Function call

•  Calling and returning •  How does caller function jump to callee function? •  How does callee function jump back to the right place in caller

function? •  Passing parameters

•  How does caller function pass parameters to callee function? •  Storing local variables

•  Where does callee function store its local variables? •  Handling registers

•  How do caller and callee functions use same registers without interference?

•  Returning a value •  How does callee function send return value back to caller function?

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Calling and returning

•  How does caller function jump to callee function? •  I.e., Jump to the address of the callee’s first instruction

•  How does the callee function jump back to the right place in caller function?

•  Jump to the instruction immediately following the most-recently-executed call instruction

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

CALL/RET

•  The 80x86 provides two instructions that use the stack to make calling subprograms quick and easy. The CALL instruction makes an unconditional jump to a subprogram and pushes the address of the next instruction on the stack.

•  The RET instruction pops off an address and jumps to that address.

•  When using these instructions, it is very important that one manage the stack correctly so that the right number is popped off by the RET instruction

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Implementation of Call

•  call subprogram1 becomes:!pushl %eip!jmp subprogram1 !!!!!ESP à!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Saved EIP!

Implementation of ret

•  ret becomes:!•  pop %eip!

• ESP à!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Saved EIP!

Passing Parameters

•  How does caller function pass parameters to callee function?

•  Attempted solution: Pass parameters in registers •  Problem: Cannot handle nested function calls •  Also: How to pass parameters that are longer than 4 bytes?

•  Caller pushes parameters before executing the call instruction

•  Parameters are pushed in the reverse order •  Push the nth parameter first •  Push 1° parameter last

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Parameter

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Parameter n!

Parameter …!

Parameter 1!ESP before à call

Parameter

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Parameter n!

Parameter …!

Parameter 1!

Saved EIP!ESP after à call

Callee addresses params relative to ESP: Param 1 as 4(%esp)

Parameter

•  After returning to the caller, the caller pops the parameters from the stack !… ! ! ! !sub:!# Push parameters ! !…!pushl $5 ! ! !movl 4(%esp),var1!pushl $4 ! ! !movl 8(%esp),var2!pushl $3 ! ! !movl 12(%esp), var3!call sub ! ! !…!# Pop parameters ! !ret!addl $12, %esp!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

%ebp

•  As callee executes, ESP may change •  E.g., preparing to call another function

•  It can be very error prone to use ESP when referencing parameters. To solve this problem, the 80386 supplies another register to use: EBP. This register’s only purpose is to reference data on the stack

•  Use EBP as fixed reference point to access params

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Using EBP (prolog)

•  A subprogram before overwriting ebp first save the old value of EBP on the stack and then set EBP to be equal to ESP. This allows ESP to change as data is pushed or popped off the stack without modifying EBP

pushl %ebp!! !movl !%esp, %ebp!! !(sub !Local_bytes, %esp)!

•  Regardless of ESP, the subprogram can reference param 1 as 8(%ebp), param 2 as 12(%ebp), etc.

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Using ebp (epilog)

•  Before returning, callee must restore ESP and EBP to their old values executing the epilog

movl %ebp, %esp!popl %ebp!ret!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Enter/Leave

•  The ENTER instruction performs the prologue code and the LEAVE performs the epilogue

•  The ENTER instruction takes two immediate operands. •  For the C calling convention, the second operand is always 0.

The first operand is the number bytes needed by local variables. The LEAVE instruction has no operands

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Epilogo

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Parameter n!

Parameter …!

Parameter 1!

Saved EIP!

Old EBP!Ebp à

Esp à

movl %ebp, %esp popl %ebp ret

à

Epilogo

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Parameter n!

Parameter …!

Parameter 1!

Saved EIP!

Old EBP!Esp = Ebp à movl %ebp, %esp popl %ebp ret

à

Epilogo

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Parameter n!

Parameter …!

Parameter 1!

Saved EIP!Esp à movl %ebp, %esp popl %ebp ret

à

Ebp à

Epilogo

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Parameter n!

Parameter …!

Parameter 1!Esp à

movl %ebp, %esp popl %ebp ret à

Ebp à

Storing local variables •  Where does callee function store its local variables? •  Local variables:

•  Short-lived, so don’t need a permanent location in Memory •  Size known in advance, so don’t need to allocate on the

heap

•  The function just uses the top of the stack •  Local variables of the callee are allocated on the

stack by moving the stack pointer •  subl $8,%esp #allocate memory for 2 integers!

•  Reference local variables as negative offsets relative to EBP!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Registers Handling

•  How do caller and callee functions use same registers without interference?

•  Callee may use a register that the caller also is using •  Solution: save the registers on the stack

•  Someone must save old register contents •  Someone must later restore the register contents

•  Define a convention for who saves and restores which registers

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Registers handling

•  Caller-save registers EAX, EBX, ECX … (when necessary…) •  Saves on stack before call •  Restores from stack after call

•  Callee-save registers EAX, EBX, ECX … (when necessary) •  Saves on stack after prolog •  Restores from stack before epilog

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Stack Frame

•  Any active function has its own stack frame •  Stack frame contains:

•  Return address (Saved EIP) •  Old EBP •  Saved register values •  Local variables •  Parameters to be passed to callee function

•  ESP points to top (low memory) of current stack frame

•  EBP points to bottom (high memory) of current stack frame

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Esempio: stack.c

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

#include <stdio.h>!int main() {!

!int x = foo( 10 );!!printf( "the value of x = %d\n", x );!!return 0;!!}!

int foo( int i ) {!!int ii = i + i;!!int iii = bar( ii );!!int iiii = iii;!!return iiii;!!}!

int bar( int j ) {!!int jj = j + j;!!return jj;!!}!

Compiliamo con il comando gcc –S stack.c - o stack.s!

Lo stack che ci aspettiamo

jj

Ret. Addr. foo

j

iiii

iii ii

Ret. Addr. main

i

x

ESP à

bar

foo

main A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Saved EBP

Saved EBP

Assembler: main

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

.file "stack.c"! .section .rodata!.LC0:! .string "the value of x = %d\n"! .text!.globl main! .type main, @function!main:! leal 4(%esp), %ecx! andl $-16, %esp! pushl -4(%ecx)! pushl %ebp! movl %esp, %ebp! pushl %ecx! subl $36, %esp! movl $10, (%esp)! call foo! movl %eax, -8(%ebp)! movl -8(%ebp), %eax! movl %eax, 4(%esp)! movl $.LC0, (%esp)! call printf! movl $0, %eax! addl $36, %esp! popl %ecx! popl %ebp!

Assembler : foo

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

.globl foo! .type foo, @function!foo:! pushl %ebp! movl %esp, %ebp! subl $24, %esp! movl 8(%ebp), %eax! addl %eax, %eax! movl %eax, -12(%ebp)! movl -12(%ebp), %eax! movl %eax, (%esp)! call bar! movl %eax, -8(%ebp)! movl -8(%ebp), %eax! movl %eax, -4(%ebp)! movl -4(%ebp), %eax! leave! ret! .size foo, .-foo!

Assembler: foo

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

.globl bar! .type bar, @function!bar:! pushl %ebp! movl %esp, %ebp! subl $16, %esp! movl 8(%ebp), %eax! addl %eax, %eax! movl %eax, -4(%ebp)! movl -4(%ebp), %eax! leave! ret! .size bar, .-bar!

Compilazione ottimizzata

Non Ottimizzata

.globl bar! .type bar, @function!bar:! pushl %ebp! movl %esp, %ebp! subl $16, %esp! movl 8(%ebp), %eax! addl %eax, %eax! movl %eax, -4(%ebp)! movl -4(%ebp), %eax! leave! ret! .

Ottimizzata

.globl bar! .type bar,@function!bar:! pushl %ebp! movl %esp, %ebp! movl 8(%ebp), %eax! addl %eax, %eax! popl %ebp! ret! !

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Compilazione ottimizzata

Non Ottimizzata .globl foo! .type foo, @function!foo:!

pushl %ebp! movl %esp, %ebp! subl $24, %esp! movl 8(%ebp), %eax! addl %eax, %eax! movl %eax, -12(%ebp)!

movl -12(%ebp), %eax! movl %eax, (%esp)! call bar! movl %eax, -8(%ebp)! movl -8(%ebp), %eax! movl %eax, -4(%ebp)!

movl -4(%ebp), %eax! leave! ret!

Ottimizzata .globl foo! .type foo, @function!foo:! pushl %ebp! movl %esp, %ebp! subl $4, %esp! movl 8(%ebp), %eax! addl %eax, %eax! movl %eax, (%esp)! call bar! leave! ret!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Esercizio

•  Risolvere i seguenti esercizi e descrivere quali sono i principi di funzionamento della soluzione adottata

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Esercizio 1

/* stack1-stdin.c *! * specially crafted to feed your brain by gera

InsecureProgramming */!!#include <stdio.h>!!int main() {!!int cookie;!!char buf[80];!

!!printf("buf: %08x cookie: %08x\n", &buf, &cookie);!!gets(buf);!

!!if (cookie == 0x41424344)!! !printf("you win!\n");!

}!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Esercizio 2

/* stack2-stdin.c *! * specially crafted to feed your brain by gera */!!#include <stdio.h>!!int main() {!!int cookie;!!char buf[80];!

!!printf("buf: %08x cookie: %08x\n", &buf, &cookie);!!gets(buf);!

!!if (cookie == 0x01020305)!

! !printf("you win!\n");!}!