Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Defcon 23 - Daniel Selifonov - drinking from LETHE
1. Drinking from LETHE:
New methods of exploiting and mitigating
memory corruption vulnerabilities
Daniel Selifonov
DEF CON 23
August 7, 2015
2. Show of Hands
1. Have you written programs in C or C++?
2. Have you implemented a classic stack smash
exploit?
3. … a return-to-libc or return-oriented-
programming exploit?
4. … a return-to-libc or ROP exploit that used
memory disclosure or info leaks?
3. Motivations
● Software is rife with
memory corruption
vulnerabilities
● Most memory corruption
vulnerabilities are directly
applicable to code
execution exploits
● And there's no end in
sight...
4. Motivations (II)
● Industrialized
ecosystem of
vulnerability
discovery and
brokering
weaponized exploits
● Little of this discovery
process feeds into
fixes...
The other AFL
5. Motivations (III)
● State actor (e.g. NSA
Tailored Access
Operations group)
budgets: ≈ $∞
● Bug bounties just
drive up prices
● Target supply, not
demand for exploits...
6. The Plan
● Sever the path between
vulnerability and
(reliable) exploit
● Why do programmers
keep hitting this
fundamental blindspot?
● Defenses are born in
light of attack strategies
7. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
8. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
9. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
10. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
11. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
<return address to >
12. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
<return address to >
13. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
<return address to >
<4 bytes for 'int a'>
14. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
<return address to >
<4 bytes for 'int a'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
15. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
<return address to >
<4 bytes for 'int a'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
16. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
<return address to >
<4 bytes for 'int a'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<return address to >
17. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
<return address to >
<4 bytes for 'int a'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
18. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
<return address to >
<4 bytes for 'int a'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<return address to >
19. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
<return address to >
<4 bytes for 'int a'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
<4 bytes for 'char b[]'>
20. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
<return address to >
21. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
22. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
<return address to >
23. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
<return address to >
24. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
<return address to C runtime exit>
25. Memory Safety
#include <stdio.h>
int main() {
foo();
bar(11, 12);
return 0;
}
void foo() {
int a;
char b[23];
gets(b);
printf("Hey %s!n",b);
}
int bar(int x, int y) {
return x + y;
}
56. PaX PAGEEXEC (2000)
User/
Supervisor:
Emulates
Non-Exec
Instruction TLB:
Data TLB:
Virtual Addr Physical Addr Permission
Virtual Addr Physical Addr Permission
Instruction Pointer:
PaX Page Fault Strategy:
if (supervisor page &&
IP on faulting page) {
Terminate
} else {
Set user page in PTE
Prime Data TLB
Set supervisor page in PTE
}
57. PaX PAGEEXEC (2000)
User/
Supervisor:
Emulates
Non-Exec
Instruction TLB:
Data TLB:
Virtual Addr Physical Addr Permission
Virtual Addr Physical Addr Permission
Instruction Pointer:
PaX Page Fault Strategy:
if (supervisor page &&
IP on faulting page) {
Terminate
} else {
Set user page in PTE
Prime Data TLB
Set supervisor page in PTE
}
1
58. PaX PAGEEXEC (2000)
User/
Supervisor:
Emulates
Non-Exec
Instruction TLB:
Data TLB:
Virtual Addr Physical Addr Permission
Virtual Addr Physical Addr Permission
Instruction Pointer:
PaX Page Fault Strategy:
if (supervisor page &&
IP on faulting page) {
Terminate
} else {
Set user page in PTE
Prime Data TLB
Set supervisor page in PTE
}
1
59. PaX PAGEEXEC (2000)
User/
Supervisor:
Emulates
Non-Exec
Instruction TLB:
Data TLB:
Virtual Addr Physical Addr Permission
Virtual Addr Physical Addr Permission
Instruction Pointer:
PaX Page Fault Strategy:
if (supervisor page &&
IP on faulting page) {
Terminate
} else {
Set user page in PTE
Prime Data TLB
Set supervisor page in PTE
}
1
60. PaX PAGEEXEC (2000)
User/
Supervisor:
Emulates
Non-Exec
Instruction TLB:
Data TLB:
Virtual Addr Physical Addr Permission
Virtual Addr Physical Addr Permission
Instruction Pointer:
PaX Page Fault Strategy:
if (supervisor page &&
IP on faulting page) {
Terminate
} else {
Set user page in PTE
Prime Data TLB
Set supervisor page in PTE
}
0
61. PaX PAGEEXEC (2000)
User/
Supervisor:
Emulates
Non-Exec
Instruction TLB:
Data TLB:
Virtual Addr Physical Addr Permission
Virtual Addr Physical Addr Permission
Instruction Pointer:
PaX Page Fault Strategy:
if (supervisor page &&
IP on faulting page) {
Terminate
} else {
Set user page in PTE
Prime Data TLB
Set supervisor page in PTE
}
0
62. PaX PAGEEXEC (2000)
User/
Supervisor:
Emulates
Non-Exec
Instruction TLB:
Data TLB:
Virtual Addr Physical Addr Permission
Virtual Addr Physical Addr Permission
Instruction Pointer:
~ User/~
PaX Page Fault Strategy:
if (supervisor page &&
IP on faulting page) {
Terminate
} else {
Set user page in PTE
Prime Data TLB
Set supervisor page in PTE
}
0
63. PaX PAGEEXEC (2000)
User/
Supervisor:
Emulates
Non-Exec
Instruction TLB:
Data TLB:
Virtual Addr Physical Addr Permission
Virtual Addr Physical Addr Permission
Instruction Pointer:
~ User/~
PaX Page Fault Strategy:
if (supervisor page &&
IP on faulting page) {
Terminate
} else {
Set user page in PTE
Prime Data TLB
Set supervisor page in PTE
}
1
64. PaX PAGEEXEC (2000)
User/
Supervisor:
Emulates
Non-Exec
Instruction TLB:
Data TLB:
Virtual Addr Physical Addr Permission
Virtual Addr Physical Addr Permission
Instruction Pointer:
~ User/~
PaX Page Fault Strategy:
if (supervisor page &&
IP on faulting page) {
Terminate
} else {
Set user page in PTE
Prime Data TLB
Set supervisor page in PTE
}
1
65. PaX PAGEEXEC (2000)
User/
Supervisor:
Emulates
Non-Exec
Instruction TLB:
Data TLB:
Virtual Addr Physical Addr Permission
Virtual Addr Physical Addr Permission
Instruction Pointer:
~ User/~
PaX Page Fault Strategy:
if (supervisor page &&
IP on faulting page) {
Terminate
} else {
Set user page in PTE
Prime Data TLB
Set supervisor page in PTE
}
1
66. PaX PAGEEXEC (2000)
User/
Supervisor:
Emulates
Non-Exec
Instruction TLB:
Data TLB:
Virtual Addr Physical Addr Permission
Virtual Addr Physical Addr Permission
Instruction Pointer:
~ User/~
PaX Page Fault Strategy:
if (supervisor page &&
IP on faulting page) {
Terminate
} else {
Set user page in PTE
Prime Data TLB
Set supervisor page in PTE
}
1
67. PaX PAGEEXEC (2000)
User/
Supervisor:
Emulates
Non-Exec
Instruction TLB:
Data TLB:
Virtual Addr Physical Addr Permission
Virtual Addr Physical Addr Permission
Instruction Pointer:
~ User/~
PaX Page Fault Strategy:
if (supervisor page &&
IP on faulting page) {
Terminate
} else {
Set user page in PTE
Prime Data TLB
Set supervisor page in PTE
}
~ User/~
1
68. Page Level Permissions
User Supervisor PaX/NX
Not-Writable Read/Execute Read
Writable Read/Write/Execute Read/Write
For mapped pages:
72. Return to libc (1997)
...
sh”
/bas
“/bin
<pointer to >
<dummy value>
<smashed ret to libc system() >
...
<vulnerable buffer>
73. Return to libc (1997)
...
sh”
/bas
“/bin
<pointer to >
<dummy value>
<smashed ret to libc system() >
...
<vulnerable buffer>
...
<pointer to “/bin/bash”>
<saved return address>
<local variable for system()>
<local variable for system()>
...
...
74. Return to libc (1997)
...
sh”
/bas
“/bin
<pointer to >
<dummy value>
<smashed ret to libc system() >
...
<vulnerable buffer>
...
<pointer to “/bin/bash”>
<saved return address>
<local variable for system()>
<local variable for system()>
...
...
75. Return Oriented Programming ('07)
...
<argument popping gadget addr>
<argument 2>
<argument 1>
<argument popping gadget addr>
<gadget addr 2>
<argument 2>
<argument 1>
<argument popping gadget addr>
<gadget addr 1>
push eax
ret
pop eax
ret
pop ebx
ret
mov [ebx],eax
ret
xchg ebx,esp
ret
pop edi
pop ebp
ret
76. Address Space Layout
Randomization (2003)
0...00
f...ff
Stack
Heap
mmap
Library A
Library B
Library C
Program Code
Stack
Heap
mmap
Library A
Library B
Library C
Program Code
94. C++ Virtual Function Tables
Instance of class Dog
Vtable ptr
Member: name
Member: age
Member: breed
Instance of class Cat
Vtable ptr
Member: name
Member: fav. catnip
Member: sharp claws?
Function ptr: feed()
Function ptr: pet()
Function ptr: sound()
Function ptr: feed()
Function ptr: pet()
Function ptr: sound()
Animal → Dog, Animal → Cat
class Cat : public Animal {
…
void sound() {
printf(“Meow!”);
}
…
}
class Dog : public Animal {
…
void sound() {
printf(“Woof!”);
}
…
}
95. C++ Virtual Function Tables
Instance of class Dog
Vtable ptr
Member: name
Member: age
Member: breed
Instance of class Cat
Vtable ptr
Member: name
Member: fav. catnip
Member: sharp claws?
Function ptr: feed()
Function ptr: pet()
Function ptr: sound()
Function ptr: feed()
Function ptr: pet()
Function ptr: sound()
Animal → Dog, Animal → Cat
class Cat : public Animal {
…
void sound() {
printf(“Meow!”);
}
…
}
class Dog : public Animal {
…
void sound() {
printf(“Woof!”);
}
…
}
96. Knights and Knaves
Instance of class Dog
Vtable ptr
Member: name
Member: age
Member: breed
Function ptr: feed()
Function ptr: pet()
Function ptr: sound()
97. Knights and Knaves
Instance of class Dog
Vtable ptr
Member: name
Member: age
Member: breed
Function ptr: feed()
Function ptr: pet()
Function ptr: sound()
Function ptr? feed()
Function ptr? feed()
Function ptr? feed()
Function ptr? pet()
Function ptr? pet()
Function ptr? pet()
Function ptr? sound()
Function ptr? sound()
Function ptr? sound()
98. Knights and Knaves
Instance of class Dog
Vtable ptr
Member: name
Member: age
Member: breed
Function ptr? feed()
Function ptr? feed()
Function ptr? feed()
Function ptr? pet()
Function ptr? pet()
Function ptr? pet()
Function ptr? sound()
Function ptr? sound()
Function ptr? sound()
99. Knights and Knaves
Instance of class Dog
Vtable ptr
Member: name
Member: age
Member: breed
Function ptr? feed()
Function ptr? feed()
Function ptr? feed()
Function ptr? pet()
Function ptr? pet()
Function ptr? pet()
Function ptr? sound()
Function ptr? sound()
Function ptr? sound()
100. Knights and Knaves
Instance of class Dog
Vtable ptr
Member: name
Member: age
Member: breed
Function ptr? feed()
Function ptr? feed()
Function ptr? feed()
Function ptr? pet()
Function ptr? pet()
Function ptr? pet()
Function ptr? sound()
Function ptr? sound()
Function ptr? sound()
103. Necessary vs. Sufficient
● Code reuse requires:
– No ASLR: A priori knowledge of place
– ASLR: A priori knowledge of relative place + runtime
discovery of offset
– FG-ASLR: Runtime discovery of value at discovered
place
● No runtime discovery? No discovery of value or
place and no code to reuse:
– XO-M + FG-ASLR = <3
104. Elephant in the Room
Two words: memory overhead
https://www.flickr.com/photos/mobilestreetlife/4179063482