a single gadget weird machine
play

a single gadget weird machine Highlights of Dutch Cyber Security - PowerPoint PPT Presentation

a single gadget weird machine Highlights of Dutch Cyber Security Research Framing Signals a return to portable shellcode Erik Bosman and Herbert Bos memory corruption, the problem that just won't go away 25+ years after the morris worm and


  1. a single gadget weird machine Highlights of Dutch Cyber Security Research Framing Signals a return to portable shellcode Erik Bosman and Herbert Bos

  2. memory corruption, the problem that just won't go away 25+ years after the morris worm and still going strong 1

  3. stack buffer overflow stack return addr buffer sp 2

  4. stack buffer overflow stack return addr buffer sp 2

  5. stack buffer overflow stack return addr buffer sp 2

  6. stack buffer overflow stack sp return addr buffer 2

  7. stack buffer overflow stack sp return addr buffer 2

  8. stack buffer overflow stack sp return addr buffer 2

  9. stack sp return addr buffer 3

  10. stack sp return addr buffer code 3

  11. return oriented programming stack return addr buffer gadgets code 3

  12. return addr return addr return addr buffer gadgets code 3

  13. Return Oriented Programming - dependent on available gadgets - non-trivial to program - chains may differ greatly between different binaries - Turing complete 4

  14. Sigreturn Oriented Programming - minimal number of gadgets - constructing shellcode by chaining system calls - easy to change functionality of shellcode - shellcode portable (gadgets are always present) - Turing complete 5

  15. unix signals stack sp 6

  16. unix signals stack sp 6

  17. unix signals stack ucontext siginfo sp 6

  18. unix signals stack ucontext siginfo sp sigreturn 6

  19. unix signals stack good: kernel agnostic about signal handlers ucontext siginfo sp sigreturn 6

  20. unix signals stack bad: kernel agnostic about signal handlers ucontext (we can fake 'em) siginfo sp sigreturn 6

  21. two gadgets - call to sigreturn - syscall & return 7

  22. forged signal frame sigreturn 8

  23. program counter forged signal frame sigreturn 8

  24. program counter stack pointer forged signal frame sigreturn 8

  25. program counter stack pointer RAX ... RDI RSI RDX R10 R8 R9 ... sigreturn 8

  26. program counter stack pointer syscall number ... arg1 arg2 arg3 arg4 arg5 arg6 ... sigreturn 8

  27. syscall & return stack pointer syscall number ... arg1 arg2 arg3 arg4 arg5 arg6 ... sigreturn 8

  28. syscall & return next sigframe syscall number ... arg1 arg2 arg3 arg4 arg5 arg6 ... sigreturn 8

  29. next syscall(...) 9

  30. socket() bind() listen() accept() execve() 10

  31. SROP exploit on x86-64 An exploit which does not make use of any gadgets in the target program - control over the stack - a known writable memory location (*any* location, and we don't need to write there beforehand) 11

  32. two gadgets - call to sigreturn - syscall & return 12

  33. two gadgets - call to sigreturn: RAX = 15 + syscall - syscall & return 12

  34. one gadget - RAX = 15 - syscall & return 12

  35. [vsyscall] ffffffffff600000 48 c7 c0 60 00 00 00 0f 05 c3 cc cc cc cc cc cc gettimeofday() fffffffffff60010 cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc * ffffffffff600400 48 c7 c0 c9 00 00 00 0f 05 c3 cc cc cc cc cc cc time() ffffffffff600410 cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc * ffffffffff600800 48 c7 c0 35 01 00 00 0f 05 c3 cc cc cc cc cc cc getcpu() ffffffffff600810 cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc * ffffffffff601000 0f05 syscall c3 return 13

  36. socket() bind() listen() accept() execve() 14

  37. socket() bind() listen() accept() execve() 14

  38. x64 syscall ABI RAX RDI RSI RDX read(fd, buffer, 1024) 15

  39. x64 syscall ABI RAX RDI RSI RDX read(fd, buffer, 1024) = 1024 15

  40. x64 syscall ABI RAX RDI RSI RDX read(fd, buffer, 1024) = 1024 RAX 15

  41. read() = 306 (syncfs) fsyncfs() = 0 (read) read() = 15 (sigreturn) sigreturn() execve() 16

  42. CVE-2012-5976 (asterisk) 17

  43. On some systems SROP gadgets are randomised, on others, they are not Operating system Gadget Memory map Linux i386 sigreturn [vdso] Linux < 3.11 ARM sigreturn [vectors] 0x ffff 0000 Linux < 3.3 x86-64 syscall & return [vsyscall] 0x ffffffffff 600000 Linux ≥ 3.3 x86-64 syscall & return Libc Linux x86-64 sigreturn Libc FreeBSD 9.2 x86-64 sigreturn 0x7 ffffffff 000 Mac OSX x86-64 sigreturn Libc iOS ARM sigreturn Libsystem iOS ARM syscall & return Libsystem 18

  44. On some systems SROP gadgets are randomised, on others, they are not android non-ASLR :-( Operating system Gadget Memory map Linux i386 sigreturn [vdso] Linux < 3.11 ARM sigreturn [vectors] 0x ffff 0000 Linux < 3.3 x86-64 syscall & return [vsyscall] 0x ffffffffff 600000 Linux ≥ 3.3 x86-64 syscall & return Libc Linux x86-64 sigreturn Libc FreeBSD 9.2 x86-64 sigreturn 0x7 ffffffff 000 Mac OSX x86-64 sigreturn Libc iOS ARM sigreturn Libsystem iOS ARM syscall & return Libsystem 18

  45. questions? 19

  46. questions? 27

  47. mitigation: It may be useful to disable vsyscall vsyscall=emulate (default from Linux 3.3 onward) or vsyscall=none

  48. mitigation: - Signal frame canaries

  49. stack canary stack return addr buffer sp

  50. stack canary stack return addr buffer sp

  51. program counter stack pointer RAX ... RDI RSI RDX R10 R8 R9 ... sigreturn

  52. program counter stack pointer RAX ... RDI RSI RDX R10 R8 R9 ... sigreturn

  53. mitigation: - Signal frame canaries

  54. mitigation: - Signal frame canaries - Counting signals in progress

  55. CVE-2012-5976 (asterisk) stack sp stack sp

  56. CVE-2012-5976 (asterisk) stack alloca stack sp sp

  57. CVE-2012-5976 (asterisk) stack alloca stack sp sp

  58. dispatch load CODE dispatch jmp exit cond jump jump P = P + c *P = *P + c *P=getchar() putchar(*P) store

  59. code = open("/proc/self/mem",O_RDWR); p = open("/proc/self/mem",O_RDWR); a = open("/proc/self/mem",O_RDWR);

  60. code = open("/proc/self/mem",O_RDWR); p = open("/proc/self/mem",O_RDWR); a = open("/proc/self/mem",O_RDWR); instruction dispatch: read(code, &ucontext.sp, sizeof(long));

  61. code = open("/proc/self/mem",O_RDWR); p = open("/proc/self/mem",O_RDWR); a = open("/proc/self/mem",O_RDWR); instruction dispatch: read(code, &ucontext.sp, sizeof(long)); pointer ops: p++ -> lseek(p, 1, SEEK_CUR);

  62. code = open("/proc/self/mem",O_RDWR); p = open("/proc/self/mem",O_RDWR); a = open("/proc/self/mem",O_RDWR); instruction dispatch: read(code, &ucontext.sp, sizeof(long)); pointer ops: p++ -> lseek(p, 1, SEEK_CUR); addition: lseek(a, &identity_table_x2, SEEK_SET); lseek(a, val1, SEEK_SET); lseek(a, val2, SEEK_SET); read(a, dest, 1);

Recommend


More recommend