lez. 2 formato file e assembler (ii parte) -...
TRANSCRIPT
Sicurezza Informatica
Lez. 2 Formato file e Assembler (II parte)
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Avviso
• Causa sovrapposizione orario lezione con Consiglio di Dipartimento si propone di anticipare la lezione del 14/10 al 13/10 aula ALFA ore 13.30
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
I FORMATI DI UN FILE
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Sorgente
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
#include<stdio.h>
int main(void){ int n = 6; float f=1; int i = 1; for(; i<=n; i++) f=f*i; printf("\n Factorial is : [%f]\n",f); return 0;}
From src to exe
Editor (es. vi)
Compilatore (es. gcc)
Linker (es. ld)
source (es. *.c. *.as)
Object code (es. *.o, *.obj)
Debugging information
Exec file
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
A more refined model C program: foo.c
Assembly program: foo.s
Executable(mach lang pgm): a.out
Compiler
Assembler
Linker
Loader
Memory
Object(mach lang module): foo.o
lib.o
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
ELF (EXECUTABLE AND LINKABLE FORMAT)
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
.elf
• It is a common standard file format for executables, object code, shared libraries, and core dumps
• First published in the System V Application Binary Interface specification,and later in the Tool Interface Standard, it was quickly accepted among different vendors of Unix systems
• In 1999 it was chosen as the standard binary file format for Unix and Unix-like systems on x86 by the 86open project
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
.elf
• An ELF binary starts with a fixed-length ELF header, followed by a variable-length program header listing each of the program sections to be loaded
• The ELF format specifies two "views" of an ELF file -- one is used for linking and the other is used for execution. This affords significant flexibility for systems designers
• We talk about sections in object code waiting to be linked into an executable. One or more sections map to a segment in the executable.
.elf
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Elf Header
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
#define ELF_MAGIC 0x464C457FU /* "\x.ELF" in little endian */ struct Elf {
uint32_t e_magic; // must equal ELF_MAGIC uint8_t e_elf[12]; uint16_t e_type; uint16_t e_machine; uint32_t e_version; uint32_t e_entry; uint32_t e_phoff; uint32_t e_shoff; uint32_t e_flags; uint16_t e_ehsize; uint16_t e_phentsize; uint16_t e_phnum; uint16_t e_shentsize; uint16_t e_shnum; uint16_t e_shstrndx;
};
Header: campi importanti
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
e_entry This member gives the virtual address to which the system first transfers control, thus starting the process. If the file has no associated entry point, this member holds zero. e_phoff This member holds the program header table’s file offset in bytes. If the file has no program header table, this member holds zero. e_shoff This member holds the section header table’s file offset in bytes. If the file has no section
header table, this member holds zero. e_flags This member holds processor-specific flags associated with the file. Flag names takethe form EF_machine _flag. See ‘‘Machine Information’’ for flag definitions. e_ehsize This member holds the ELF header’s size in bytes. e_phentsize This member holds the size in bytes of one entry in the file’s program header table; all entries are the same size. e_phnum This member holds the number of entries in the program header table. Thus the product of e_phentsize and e_phnum gives the table’s size in bytes. If a file has no program header table, e_phnum holds the value zero.
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
.elf
Program Header
• The ELF header actually points to another group of headers called the program headers
• These headers describe to the operating system anything that might be required for it to load the binary into memory and execute it
• Segments are described by program headers, but so are some other things required to get the executable running
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
ELF header and Program header
• ELF header definition contains fields e_phoff, e_phnum and e_phentsize; these are simply the offset in the file where the program headers start, how many program headers there are and how big each program header is
• With these three information you can easily find and read the program headers
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Proghdr
struct Proghdr { !uint32_t p_type; !uint32_t p_offset; !uint32_t p_va; !uint32_t p_pa; !uint32_t p_filesz; !uint32_t p_memsz; !uint32_t p_flags; !uint32_t p_align; !
}; A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Which segments
• The C definitions for these ELF headers are in inc/elf.h. The program segments we're interested in are: • .text: the program's executable instructions • .rodata: read-only data, such as ASCII string constants
produced by the C compiler. (We will not bother setting up the hardware to prohibit writing, however.)
• .data: The data section holds the program's initialized data, such as global variables declared with initializers like int x = 5;.
• .bss
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
.elf
• When the linker computes the memory layout of a program, it reserves space for uninitialized global variables, such as int x; in a section called .bss that immediately follows .data in memory
• C requires that "uninitialized" global variables start
with a value of zero. Thus there is no need to store contents for .bss in the ELF binary; instead, the linker records just the address and size of the .bss section. The loader or the program itself must arrange to zero the .bss section.
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Various tools for various formats
• Depending on the file format we use different tools for inspecting their content:
• Editor (vi, vim, emacs, …) for source files • Objdump for obj and exe files
• A c object file is obtained by using the “-c” option in GCC, the suffix of an object file is .o
• An executable file is obtained by using the “-o” option in GCC, executable files usually have no suffixes
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
objdump
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
objdump –d fattoriale.o
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
objdump –h fattoriale.o
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
objdump –h fattoriale
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
objdump –h (2)
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
objdump –h (3)
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
GDB
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Why use a debugger?
• No one writes perfect code first time, every time • Desk checking code can be tedious and error-prone • Putting print statements in the code requires re-
compilation and a guess as to the source of the problem
• Debuggers are powerful and flexible
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Common debugger functions
• Run program • Stop program at breakpoints • Execute one line at a time • Display values of variables • Show sequence of function calls
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
The GNU debugger (gdb)
• A debugger is closely tied to the compiler. • gcc – gdb, cxx – ladebug, cc - dbx
• Command line debugger for gnu's compilers (gcc, g++) • gdb
• The most common way to invoke: • gdb executable
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Sicurezza Informatica © Danilo Bruschi
Invoking gdb
• Start debugging an executable • gdb executable*
• Load a corefile • gdb executable [-c] corefile
• Attach to a running process • gdb executable pid
• as long as pid is not a file in the current directory
A.A. 2015/2016
Inspecting a corefile
• When a program crashes it may leave a core dump which can be used to figure out exactly why the program crashed
• Core dumps are disabled by default on many Linux distributions they can be enabled with the command $ulimit –c unlimited
• You can look at any corefile to see the state of the corresponding program at the time of the crash
• Load executable and corefile into the debugger • Use GDB's backtrace (bt) command to see the
call stack
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Running a program in GDB
• You can run programs in the debugger • see value of variables and expressions • look at source code as it's executed • change the value of variables • move the execution pointer • many other things
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Compile for debugging
• When compiling your program, add the –g flag to the command line: • gcc -g -o prog prog.c
• This adds extra symbol information, so the debugger knows how you called the variables in your source, can show you the source code and which line will be executed next
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Looking at your source
• list or l (list code) • list • list main • list 56 • list 53,77
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Breakpoints
• A place where execution pauses, waits for a user command
• Can break at a function, a line number, or on a certain condition • break or b (set a breakpoint)
• break main • break 10
• watch expr
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Execution commands • run or r (run program from beginning)
• run • run argList
• Or, you can set arguments to be passed to the program this way: • set args arglist
• start • starts debugging, breaks at main
• kill • stops debugging
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
More Execution commands
• next or n • execute next line, stepping over function calls
• step or s • execute next line, stepping into function calls
• continue or cont • resume execution, until next breakpoint
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Examining data • print [expr] • print [/format] [expr]
• print /d x • print x*y • print function(x)
• printf “X=%d, Y=%d\n”,X,Y • display (continuously display value) • undisplay (remove displayed value) • where (show current function stack) • set (change a value)
• set n=3 A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Miscellaneous commands
• help or h (display help text) • help • help step • help breakpoints
• quit or q (quit gdb)
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Registers content Registers’ name is prefixed by $. $pc indicates the program counter and $sp the stack pointer
(gdb) info registers Shows the contents of all general purpose registers
(gdb) info all-registers Shows all registers
Es. (gdb) p/x $pc $6 = 0x401100
Shows the content of the program counter
(gdb) x/i $pc lea 0xffffffe8(%ebp),%eax
0x401100 <main+30>:
Show the content of the memory addressed by pc
(gdb) set $sp += 4
Modify the stack pointer’s value A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
gdb exercise
• The programs below are buggy • Copy the files to your local file system; then, compile
and run • Do you see the problem? • Can you fix it easily? • gdb will help • Use gdb to examine programs behavior and fix the
bug
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
GBD 1 .text # section declaration
# we must export the entry point to the ELF linker or.global _start # loader. They conventionally recognize _start as
# entry point. Use ld -e foo to override the default_start:
# write our string to stdoutmovl len,%edx # third argument: message lengthmovl $msg,%ecx # second argument: pointer to msgmovl $1,%ebx # first argument: file handle (stdout)movl $4,%eax # system call number (sys_write)int $0x80 # call kernel and exit
movl $0,%ebx # first argument: exit codemovl $1,%eax # system call number (sys_exit)int $0x80 # call kernel
.data # section declarationmsg: .ascii "Hello, world!\n"# our dear string
len = . - msg # length of our dear string
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
GDB 2
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
1 : #include <stdio.h>2 : #include <ctype.h>3 : 4 : int main(int argc, char **argv)5 : {6 : char c;7 :8 : c = fgetc(stdin);9 : while(c != EOF){10:11: if(isalnum(c))12: printf("%c", c);13: else14: c = fgetc(stdin);15: }16:17: return 1;18: }
ASSEMBLER (II PARTE)
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Memory Layout
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Memory Layout
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Stack
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Where is stored msg?
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Why on the stack and not in .data?
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Stack
• Many CPU’s have built-in support for a stack 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. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Stack
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Runtime Stack
• Managed by the CPU, using two registers • SS (stack segment) • ESP (stack pointer) *
00000006 ESP00001000
Offset
00000FF8
00000FF4
00000FF0
00000FFC
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
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,%espmovl src,(%esp)
A.A. 2015/2016 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
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
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).
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
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. 2015/2016 Sicurezza Informatica © Danilo Bruschi
popl dest à movl (%esp),dest addl $4,%esp
POP Operation • Copies a 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
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
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. 2015/2016 Sicurezza Informatica © Danilo Bruschi
The stack for managing 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. 2015/2016 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. 2015/2016 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. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Implementation of Call
• call subprogram1 becomes:pushl %eipjmp subprogram1
ESP à
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Saved EIP
Implementation of ret
• ret becomes:• pop %eip
• ESP à
A.A. 2015/2016 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. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Parameter
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Parameter 1
Parameter …
Parameter n
ESP before à call
Parameter
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Parameter 1
Parameter …
Parameter n
Saved EIPESP after à call Callee addresses params
relative to ESP: Param 1 as 4(%esp)
Parameter
• After returning, the caller pops the parameters from the stack
… sub:# Push parameters …pushl $5 movl 4(%esp),var1pushl $4 movl 8(%esp),var2pushl $3 movl 12(%esp), var3call sub …# Pop parameters retaddl $12, %esp
A.A. 2015/2016 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. 2015/2016 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 %ebpmovl %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. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Using ebp (epilog)
• Before returning, callee must restore ESP and EBP to their old values executing the epilog
movl %ebp, %esppopl %ebpret
A.A. 2015/2016 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. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Epilogo
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Parameter n
Parameter …
Parameter 1
Saved EIP
Old EBPEbp à
Esp à
movl %ebp, %esp popl %ebp ret
à
Epilogo
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Parameter n
Parameter …
Parameter 1
Saved EIP
Old EBP
Esp = Ebp à movl %ebp, %esp popl %ebp ret
à
Parameter n
Parameter …
Parameter 1
Saved EIP
Old EBP
Old Esp à
Epilogo
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
movl %ebp, %esp popl %ebp ret
à
Parameter n
Parameter …
Parameter 1
Saved EIP
Ebp à
Esp à
Epilogo
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
movl %ebp, %esp popl %ebp ret à
Parameter n
Parameter …
Parameter 1
Ebp à
Esp à
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. 2015/2016 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. 2015/2016 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. 2015/2016 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. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Example: stack.c
A.A. 2015/2016 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
iiii
iii
ii
Ret. Addr. Main
x
ESP à bar
foo
main
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Saved EBP
Saved EBP
Ret. Addr. Saved EBP
param. 1
param. 1
Assembler: main
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
.file "stack.c" .section .rodata.LC0: .string "the value of x = %d\n" .text.globl main .type main, @functionmain: 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. 2015/2016 Sicurezza Informatica © Danilo Bruschi
.globl foo .type foo, @functionfoo: 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: bar
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
.globl bar .type bar, @functionbar: 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, @functionbar: 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,@functionbar: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax addl %eax, %eax popl %ebp ret
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
Compilazione ottimizzata
Non Ottimizzata .globl foo .type foo, @functionfoo:
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, @functionfoo: pushl %ebp movl %esp, %ebp subl $4, %esp movl 8(%ebp), %eax addl %eax, %eax movl %eax, (%esp) call bar leave ret
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
A.A. 2015/2016 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");
}
Compile
• Compile (64/32): • gcc -fno-stack-protector -z execstack (-m32) classic.c -o classic
• Disable ASLR: • echo 0 > /proc/sys/kerne/randomize_va_space
• Solution • perl -e 'print "A" x 92 . "DCBA"' | ./gera1
A.A. 2015/2016 Sicurezza Informatica © Danilo Bruschi
A.A. 2015/2016 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");}