0% found this document useful (0 votes)
2 views

Week 11 - Symbolic Execution

Week 11 symbolic execution

Uploaded by

amrtdmr
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Week 11 - Symbolic Execution

Week 11 symbolic execution

Uploaded by

amrtdmr
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 32

CENG405

Computer Systems
Security

Week 11 –
Symbolic Execution
Introduction

• Previously, we discussed methods for tolerating bugs


– Container
– Privilege Separation
– Fault Isolation

• Finding bugs
– Dynamic Analysis: Fuzzers - AFL
– Static Analysis: Symbolic Execution – EXE, KLEE,
SAGE, STACK
Introduction

• Bugs: Major source of security exploits


– Bugs ~ Exploit?
• How to decide if a bug is exploitable?
– Often hard, time-consuming task
– Assuming that bugs are exploitable is more feasible
• Finding bugs
– Encourage researchers/security practitioners to
find exploits
• Disclosing exploit?
– Contact vendor
– after some time disclose bug to the public
Approaches to Finding Bugs

• Verification
– Eliminates classes of bugs
– Proves that implementations obey specifications
– Promising, but requires a lot of resource
• Testing
– Making sure software acts in intended ways
– As strong as the test cases
– Against known bugs
• Fuzzing
– Concrete inputs are given to software
– Aim to cover the corner cases
– Against unknown bugs
Overview of EXE

• Crashes
– Divide by zero
– Null pointer dereference
• Out-of-bound array access
• Application specific bugs

• The goal is not to prove the absence of the bug


• The goal is to find deep bugs
Overview of EXE

• Symbolic execution
• Aims to detect deep bugs
– Not prove to absence of bugs
• Drives program along all paths in program
• Runs with symbolic values
• Branches on each if statement
– Creates one path condition for each if and else
branch
Overview of EXE

• Uses constraint solver to see whether branches are


possible
• Solver might say YES, provide the corresponding
concrete input
• Solver might say NO, stop exploring further
• Path-explosion problem
Example for Standard Fuzz
Testing
𝒙 𝒚 𝒕
1. read int x, y
2. t = 0
3. if x > y
4. t = x
5. else
6. t = y
7. if t < x
8. error()
Example for EXE

1. read int x, y
2. if x > y
3. x = y
4. if x < y
5. x = x + 1
6. if x + y == 7
7. error()

Line 6 and 7 is the expansion of the assert x+y!=7


Decide to if attacker could trigger the error
Example of EXE

• Compile time
– Program is taken
– EXE runs over the code, instruments it
– When you get a branch statement in runtime, EXE runtime is
called

• Runtime
– Paths are explored
Example of EXE

• Runtime components
– The running app
– Constraints
– Constraint solver (STP)

x > y

App STP
OK/NO/DON’T KNOW
Example of EXE

• Solver says “I do not know”


– We might miss a bug
– Reminder: Aim is not to prove the absence of the bugs

x > y

App STP
OK/NO/DON’T KNOW

Depth First Search or


Scheduler
Breadth First Search
Example of EXE

• Solver says “I do not know”


– We might miss a bug
– Reminder: Aim is not to prove the absence of the bugs

2. x > y

App STP
OK/NO/DON’T KNOW

Depth First Search : Loops


Scheduler
Breadth First Search :
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is true Condition
1. read int x, y
2. if x > y
3. x = y
4. if x < y
5. x = x + 1
6. if x + y == 7
7. error()
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is true Condition
1. read int x, y 𝜶 𝜷
2. if x > y
3. x = y
4. if x < y
5. x = x + 1
6. if x + y == 7
7. error()
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is true Condition
1. read int x, y 𝜶 𝜷
2. if x > y 𝜶 𝜷 𝛼>𝛽
3. x = y
4. if x < y
5. x = x + 1
6. if x + y == 7
7. error()
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is true Condition
1. read int x, y 𝜶 𝜷
2. if x > y 𝜶 𝜷 𝛼>𝛽
3. x = y 𝜷 𝜷 𝛼>𝛽
4. if x < y
5. x = x + 1
6. if x + y == 7
7. error()
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is true Condition
1. read int x, y 𝜶 𝜷
2. if x > y 𝜶 𝜷 𝛼>𝛽
3. x = y 𝜷 𝜷 𝛼>𝛽
4. if x < y NO FORK
5. x = x + 1
6. if x + y == 7
7. error()
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is true Condition
1. read int x, y 𝜶 𝜷
2. if x > y 𝜶 𝜷 𝛼>𝛽
3. x = y 𝜷 𝜷 𝛼>𝛽
4. if x < y NO FORK
5. x = x + 1 NO FORK
6. if x + y == 7
7. error()
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is true Condition
1. read int x, y 𝜶 𝜷
2. if x > y 𝜶 𝜷 𝛼>𝛽
3. x = y 𝜷 𝜷 𝛼>𝛽
4. if x < y NO FORK
5. x = x + 1 NO FORK
6. if x + y == 7 NO FORK
7. error() NO FORK
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is false Condition
1. read int x, y 𝜶 𝜷 𝑎≤𝛽
2. if x > y
3. x = y
4. if x < y
5. x = x + 1
6. if x + y == 7
7. error()
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is false Condition
1. read int x, y 𝜶 𝜷 𝑎≤𝛽
2. if x > y FALSE
3. x = y
4. if x < y
5. x = x + 1
6. if x + y == 7
7. error()
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is false Condition
1. read int x, y 𝜶 𝜷 𝑎≤𝛽
2. if x > y FALSE
3. x = y NO FORK
4. if x < y
5. x = x + 1
6. if x + y == 7
7. error()
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is false Condition
1. read int x, y 𝜶 𝜷 𝑎≤𝛽
2. if x > y FALSE
3. x = y NO FORK
4. if x < y 𝜶 𝜷 𝑎<𝛽
5. x = x + 1
6. if x + y == 7
7. error()
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is false Condition
1. read int x, y 𝜶 𝜷 𝑎≤𝛽
2. if x > y FALSE
3. x = y NO FORK
4. if x < y 𝜶 𝜷 𝑎<𝛽
5. x = x + 1 𝜶+𝟏 𝜷 𝑎<𝛽
6. if x + y == 7
7. error()
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is false Condition
1. read int x, y 𝜶 𝜷 𝑎≤𝛽
2. if x > y FALSE
3. x = y NO FORK
4. if x < y 𝜶 𝜷 𝑎<𝛽
5. x = x + 1 𝜶+𝟏 𝜷 𝑎<𝛽
6. if x + y == 7 𝜶 + 𝟏 + 𝜷 = 𝟕; 𝜶 = 𝟐, 𝜷 = 𝟒
7. error()
Example for EXE
𝒙(𝜶) 𝒚(𝜷) Path
If Line 2 is false Condition
1. read int x, y 𝜶 𝜷 𝑎≤𝛽
2. if x > y FALSE
3. x = y NO FORK
4. if x < y 𝜶 𝜷 𝑎<𝛽
5. x = x + 1 𝜶+𝟏 𝜷 𝑎<𝛽
6. if x + y == 7 𝜶 + 𝟏 + 𝜷 = 𝟕; 𝜶 = 𝟐, 𝜷 = 𝟒
7. error() CRASH
The Solver

• Easy
– x+7=y
• Hard
– x . y = 900
• Too hard
– 10 = hash(x)
The Solver

• Arrays can be tough for a solver


• Easy
– s[c] -> concrete index, symbolic value
– looping over an input string
• Hard
– c[s] -> symbolic index, concrete value
– could refer to any element
– equivalent to a big disjunction (c[0] or c[1] or …)
• Too hard
– *p
– if p is symbolic, which array? which disjunction
The Solver

• What if the solver times out?


• How big the size of execution tree
• How long will you run the symbolic execution
• When to terminate?
– Finding all bugs?
• How to deal with libraries/databases/file systems?
– We assume that we have the whole program in our
hand
Concolic Execution

• Concrete + symbolic execution


Conclusion

• Symbolic execution is powerful and productive


• Not so practical as programs grow large
• Promising research area as well as a useful tool

You might also like