Pending Constraints in Symbolic Execution for Better Exploration and Seeding Timotej Kapus Frank Busse Cristian Cadar Imperial College London 1
Symbolic Execution ● Program analysis technique ● Active research area ● Used in industry ○ IntelliTest, SAGE Angr ○ KLOVER 2
Why symbolic execution? ● No false positives! ○ Every bug found has a concrete input triggering it ● Can interact with the environment ○ I/O, unmodeled libraries ● Only relevant code executed “symbolically”, the rest is fast “native” execution 3
Why (not) symbolic execution? ● Scalability, scalability, scalability ○ Constraint solving is hard ○ Path explosion 4
This talk Introduce pending constraints which enhance the scalability of symbolic execution via aggressively tackling paths that are known to be feasible. 5
“known to be feasible” Caching Seeding ● Cache assignments from ● External, usually valid previous solver queries concrete inputs ● Already widely adopted ● Used to bootstrap symbolic execution ● From test-suites, examples, production data 6
Symbolic execution example: get_sign int get_sign( int x) { int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; return r; } 7
get_sign( x ); int get_sign( int x) { int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; return r; } Known assignments ∅ 8
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; return r; } Known assignments ∅ 9
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } Known assignments ∅ 10
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x < 1 Known assignments Known assignments x = -2 x = -2 11
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments Known assignments x = -2 x = -2 x = 7 12
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments x == 0 x = -2 x = 7 13
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments x == 0 x ≠ 0 x = -2 x = 7 14
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments x == 0 x ≠ 0 x = -2 x = 0 x = 0 x = 7 x = 0 15
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments x == 0 x ≠ 0 x = -2 x = 0 x = 0 x = 7 x = 0 r = 0; 16
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments x == 0 x ≠ 0 x = -2 x = 0 x = 7 x = 0 r = 0; return r; 17
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments x == 0 x ≠ 0 x = -2 x = 0 x = 7 x = 0 r = 0; return r; return r; 18
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 r = 1; Known assignments x == 0 x ≠ 0 x = -2 x = 0 x = 7 x = 0 r = 0; return r; return r; 19
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 r = 1; Known assignments x == 0 x ≠ 0 x = -2 x = 0 x == 0 x = 7 x = 0 r = 0; return r; return r; 20
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 r = 1; Known assignments x == 0 x ≠ 0 x = -2 x = 0 x == 0 x = 7 x = 0 x = 0 r = 0; return r; return r; 21
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 r = 1; Known assignments x == 0 x ≠ 0 x = -2 x = 0 x == 0 x = 7 x ≠ 0 x = 0 x = 0 r = 0; return r; return r; 22
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 r = 1; Known assignments x == 0 x ≠ 0 x = -2 x = 0 x == 0 x = 7 x ≠ 0 x = 0 x = 0 r = 0; return r; return r; return r; 23
Symbolic execution with pending constraints int get_sign( int x) { ● Explore paths that are known int r = -1; to be feasible if (x >= 1) r = 1; ● Solve constraints only when if (x == 0) r = 0; necessary to make progress return r; } 24
get_sign( x ); int get_sign( int x) { int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; return r; } Known assignments ∅ 25
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; return r; } Known assignments ∅ 26
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments ∅ 27
get_sign( x ); int get_sign( int x) { Pending constraints r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; ● Not known to be feasible } x ≥ 1 x < 1 ● When only pending constraints left ○ Pick one and check Known assignments ∅ 28
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments x = -2 29
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments x == 0 x ≠ 0 x = -2 x = 0 30
get_sign( x ); int get_sign( int x) { Pending constraints: still not known if feasible r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments x == 0 x ≠ 0 x = -2 x = 0 31
get_sign( x ); int get_sign( int x) { Pending constraints: known feasible path! r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments x == 0 x ≠ 0 x = -2 x = 0 32
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments x == 0 x ≠ 0 x = -2 x = 0 return r; 33
get_sign( x ); int get_sign( int x) { Only pending constraints: check one r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments x == 0 x ≠ 0 x = -2 x = 0 return r; 34
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 Known assignments x == 0 x ≠ 0 x = -2 x = 0 x = 0 r = 0; return r; return r; 35
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 r = 1; Known assignments x == 0 x ≠ 0 x = -2 x = 0 x = 0 x = 7 r = 0; return r; return r; 36
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 r = 1; Known assignments x == 0 x ≠ 0 x = -2 x = 0 x == 0 x = 0 x ≠ 0 x = 0 x = 7 r = 0; return r; return r; 37
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 r = 1; Known assignments x == 0 x ≠ 0 x = -2 x = 0 x == 0 x = 0 x ≠ 0 x = 0 x = 7 r = 0; return r; return r; return r; 38
get_sign( x ); int get_sign( int x) { r = -1; int r = -1; if (x >= 1) r = 1; if (x == 0) r = 0; x >= 1 return r; } x ≥ 1 x < 1 r = 1; Known assignments x == 0 x ≠ 0 x = -2 x = 0 x == 0 x = 0 x ≠ 0 x = 0 x = 7 r = 0; return r; return r; return r; 39
Pending constraints: why would they be useful? ● Reversing md5 hash char msg[8] = symbolic; ○ Very hard for SMT solvers uint32_t *hash = md5(msg, 8); ● assert(hash[0] == 1471037522) 1471037522 = md5("ase2020")[0] ○ Use as seed 40
Suppose this exploration tree for md5 41
Suppose this path md5("ase2020") 42
Solver queries: 0 Pending Vanilla 43
Solver queries: 0 Pending Vanilla ase20 20 44
Solver queries: 0 Pending Vanilla ase20 20 45
Solver queries: 0 Pending Vanilla ase20 20 46
Solver queries: 1 Pending Vanilla ase20 20 47
Solver queries: 2 Pending Vanilla ase20 20 48
Solver queries: 3 Pending Vanilla ase20 20 49
Solver queries: 4 Pending Vanilla ase20 20 50
Solver queries: 5 Pending Vanilla ase20 20 51
Solver queries: 6 Pending Vanilla ase20 20 52
Solver queries: 7 Pending Vanilla ase20 20 53
Solver queries: 8 Pending Vanilla ase20 ase20 20 20 54
Recommend
More recommend