aslr nx bounds checking
play

ASLR / NX / Bounds Checking 1 last time stack canaries - PowerPoint PPT Presentation

ASLR / NX / Bounds Checking 1 last time stack canaries less-compatible alternative: shadow stacks page-level protection RELRO protect global ofgset table guard pages around memory allocations/etc. start ASLR choose random addresses


  1. ASLR / NX / Bounds Checking 1

  2. last time stack canaries less-compatible alternative: shadow stacks page-level protection RELRO — protect global ofgset table guard pages around memory allocations/etc. start ASLR choose random addresses ideally attacker never learns addresses except overfmows can leak them 2

  3. logistical note: FORMAT deadline Saturday since executable was not linked correctly on time format string exploit sufficient to overwrite defaultLetterGrade variable 3

  4. Linux stack randomization (x86-64) 1. choose random number between 0 and 0x3F FFFF 0x1000 16 GB range! 6 2. stack starts at 0x7FFF FFFF FFFF - random number × randomization disabled? random number = 0

  5. Linux stack randomization (x86-64) 1. choose random number between 0 and 0x3F FFFF 0x1000 16 GB range! 6 2. stack starts at 0x7FFF FFFF FFFF - random number × randomization disabled? random number = 0

  6. program memory (x86-64 Linux; ASLR) Used by OS why are these addresses fjxed? Code + Constants Writable data Heap (brk/sbrk) Dynamic/Libraries (mmap) Stack 0x0000 0000 0040 0000 0xFFFF FFFF FFFF FFFF (constants + 2MB alignment) 0x0000 0000 0060 0000* (fjlled from top with ASLR) 0xFFFF 8000 0000 0000 7 ± 0x004 0000 0000 ± 0x100 0000 0000 ± 0x200 0000

  7. program memory (x86-32 Linux; ASLR) 0xFFFF FFFF 0xC000 0000 0x0804 8000 Used by OS Stack Dynamic/Libraries (mmap) Heap (brk/sbrk) Writable data Code + Constants 8 ± 0x080 0000 (default) ± 0x008 0000 (default) ± 0x200 0000

  8. how much guessing? gaps change by multiples of page (4K) 64-bit: huge ranges — need millions of guesses only about 8 randomized bits in addresses why? only 4 GB to work with! can be confjgured higher — but larger gaps 9 lower 12 bits are fjxed about 30 randomized bits in addresses 32-bit: smaller ranges — hundreds of guesses

  9. danger of leaking pointers any stack pointer? know everything on the stack! any pointer to a particular library? know everything in library! library loaded as one big chunk contains many ofgsets in instructions — can’t split easily 10

  10. program memory (x86-64 Linux; ASLR) Used by OS why are these addresses fjxed? Code + Constants Writable data Heap (brk/sbrk) Dynamic/Libraries (mmap) Stack 0x0000 0000 0040 0000 0xFFFF FFFF FFFF FFFF (constants + 2MB alignment) 0x0000 0000 0060 0000* (fjlled from top with ASLR) 0xFFFF 8000 0000 0000 11 ± 0x004 0000 0000 ± 0x100 0000 0000 ± 0x200 0000

  11. program memory (x86-64 Linux; ASLR) Used by OS why are these addresses fjxed? Code + Constants Writable data Heap (brk/sbrk) Dynamic/Libraries (mmap) Stack 0x0000 0000 0040 0000 0xFFFF FFFF FFFF FFFF (constants + 2MB alignment) 0x0000 0000 0060 0000* (fjlled from top with ASLR) 0xFFFF 8000 0000 0000 11 ± 0x004 0000 0000 ± 0x100 0000 0000 ± 0x200 0000

  12. fjxed addresses machine code contains hard-coded addresses and is supposed to be loaded without changes only small global ofgset table, etc. changed 12

  13. one possibility — not fjxed could just edit fjxed addresses at load time usual dynamic linking strategy avoids this typical dynamic linkers support it, but unused by compilers, etc. a lot slower than writing small table of addresses a lot more “metadata” for linker harder to share memory between programs 13

  14. relocating: Windows Windows will edit code to relocate typically one fjxed location per program/library per boot same address used across all instances of program/library still allows sharing memory fjxup once per program/library per boot before ASLR: code could be pre-relocated Windows + Visual Studio had ‘full’ ASLR by default since 2010 14 programs/libraries usually include relocation table

  15. recall: relocation 48 c7 c7 00 00 00 00 .data : address to insert R_X86_64_32S : 32-bit signed integer 3: location in machine code relocation record says how to fjx 0x0 in mov 3: R_X86_64_32S .data $0x0,%rdi mov 0: .data generates: ( objdump --disassemble --reloc ) movq $string, %rdi /* NOT PC/RIP-relative mov */ main: .text World!" string: .asciz "Hello, 15 ␣

  16. relocating and stubs: Windows What about the “stubs” and lookup tables? Windows GOT equivalent is IAT (Import Address Table) Can’t Windows avoid them by editing code? Probably, but…it doesn’t Why? 16

  17. Windows ASLR limitation same address in all programs — not very useful against local exploits 17

  18. PIC: Linux, OS X position independent code instead of fjxed-up hard-coded addresses Linux, OS X don’t fjxup code at runtime previously a challenge for ASLR libraries on these systems previously had no fjxed address …but executables had a bunch 18

  19. hard-coded addresses? (64-bit) .quad *lookupTable(,%rdi,8) /* code for defaultCase, returnOne, returnTwo */ ... .section .rodata .quad returnOne returnTwo int foo( long n) { .quad returnOne .quad returnTwo .quad returnOne .quad returnOne jmp defaultCase ja return 2; switch (n) { case 0: case 2: case 4: case 5: return 1; case 1: case 3: default : $5, %rdi return 3; } } foo: movl $3, %eax cmpq 19 lookupTable: /* read-only pointers: */

  20. hard-coded addresses? (64-bit) *0x400618(,%rdi,8) 77 12 ja 0x40058d /* lookup table jump: */ ff 24 fd 18 06 40 00 jmpq ... $0x5,%rdi /* lookupTable @ 0x400618 */ @ 400618: 0x400588 /* returnOne */ @ 400620: 0x400582 /* returnTwo */ @ 400628: 0x400588 @ 400630: 0x400582 /* jump to defaultCase: */ cmp int foo( long n) { case 3: switch (n) { case 0: case 2: case 4: case 5: return 1; case 1: return 2; 48 83 ff 05 default : return 3; } } 400570 <foo> : b8 03 00 00 00 mov $0x3,%eax 20

  21. hard-coded addresses? (64-bit) *0x400618(,%rdi,8) 77 12 ja 0x40058d /* lookup table jump: */ ff 24 fd 18 06 40 00 jmpq ... $0x5,%rdi /* lookupTable @ 0x400618 */ @ 400618: 0x400588 /* returnOne */ @ 400620: 0x400582 /* returnTwo */ @ 400628: 0x400588 @ 400630: 0x400582 /* jump to defaultCase: */ cmp int foo( long n) { case 3: switch (n) { case 0: case 2: case 4: case 5: return 1; case 1: return 2; 48 83 ff 05 default : return 3; } } 400570 <foo> : b8 03 00 00 00 mov $0x3,%eax 20

  22. hard-coded addresses? (64-bit) *0x400618(,%rdi,8) 77 12 ja 0x40058d /* lookup table jump: */ ff 24 fd 18 06 40 00 jmpq ... $0x5,%rdi /* lookupTable @ 0x400618 */ @ 400618: 0x400588 /* returnOne */ @ 400620: 0x400582 /* returnTwo */ @ 400628: 0x400588 @ 400630: 0x400582 /* jump to defaultCase: */ cmp int foo( long n) { case 3: switch (n) { case 0: case 2: case 4: case 5: return 1; case 1: return 2; 48 83 ff 05 default : return 3; } } 400570 <foo> : b8 03 00 00 00 mov $0x3,%eax 20

  23. exercise: avoiding absolute addresses movl but fast exercise: rewrite this without absolute addresses .quad returnOne .quad returnOne .quad returnTwo .quad returnOne .quad returnTwo .quad returnOne lookupTable: ret defaultCase: $2, %eax returnTwo: foo: ret $1, %eax movl returnOne: *lookupTable(,%rdi,8) jmp defaultCase ja $5, %rdi cmpq $3, %eax movl 21

  24. hard-coded addresses 0x0000000000000238 vaddr 0x0000000000400238 filesz 0x0000000000000228 memsz 0x0000000000000230 flags rw paddr 0x0000000000600e10 align 2**21 0x0000000000000e10 vaddr 0x0000000000600e10 LOAD off filesz 0x000000000000078c memsz 0x000000000000078c flags r x paddr 0x0000000000400000 align 2**21 LOAD off filesz 0x000000000000001c memsz 0x000000000000001c flags r paddr 0x0000000000400238 align 2**0 INTERP off filesz 0x00000000000001f8 memsz 0x00000000000001f8 flags r x paddr 0x0000000000400040 align 2**3 PHDR off Program Header: start address 0x0000000000400450 EXEC_P, HAS_SYMS, D_PAGED 22 test − 64 − nopie.exe: file format elf64 − x86 − 64 test − 64 − nopie.exe architecture: i386:x86 − 64, flags 0x00000112: 0x0000000000000040 vaddr 0x0000000000400040 0x0000000000000000 vaddr 0x0000000000400000

  25. relocation? one solution: be willing change addresses at load time Windows does this Linux’s dynamic linker is not willing to 23 requires: table of relocations in executable code

  26. PIE position-independent executables (PIE) no hardcoded addresses Windows solution GCC: -pie -fPIE -pie is linking option -fPIE is compilation option related option: -fPIC (position independent code) used to compile runtime-loaded libraries 24 alternative: edit code (not global ofgset table) at load time

  27. PIE jump-table returnTwo: jumpTable: .rodata .section ret defaultCase: $1, %eax movl returnOne: ret foo: movl $2, %eax *%rax ja movl $3, %eax jmp $5, %rdi cmpq retDefault leaq jumpTable(%rip), %rax movslq (%rax,%rdi,4), %rdx addq %rdx, %rax 25 .long returnOne − jumpTable .long returnTwo − jumpTable .long returnOne − jumpTable .long returnTwo − jumpTable .long returnOne − jumpTable .long returnOne − jumpTable

  28. PIE jump-table returnTwo: jumpTable: .rodata .section ret defaultCase: $1, %eax movl returnOne: ret foo: movl $2, %eax *%rax ja movl $3, %eax jmp $5, %rdi cmpq retDefault leaq jumpTable(%rip), %rax addq %rdx, %rax 25 .long returnOne − jumpTable .long returnTwo − jumpTable .long returnOne − jumpTable .long returnTwo − jumpTable movslq (%rax,%rdi,4), %rdx .long returnOne − jumpTable .long returnOne − jumpTable

Recommend


More recommend