pending constraints in symbolic execution for better
play

Pending Constraints in Symbolic Execution for Better Exploration and - PowerPoint PPT Presentation

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


  1. Pending Constraints in Symbolic Execution for Better Exploration and Seeding Timotej Kapus Frank Busse Cristian Cadar Imperial College London 1

  2. Symbolic Execution ● Program analysis technique ● Active research area ● Used in industry ○ IntelliTest, SAGE Angr ○ KLOVER 2

  3. 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

  4. Why (not) symbolic execution? ● Scalability, scalability, scalability ○ Constraint solving is hard ○ Path explosion 4

  5. This talk Introduce pending constraints which enhance the scalability of symbolic execution via aggressively tackling paths that are known to be feasible. 5

  6. “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

  7. 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

  8. 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

  9. 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

  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; } Known assignments ∅ 10

  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 Known assignments Known assignments x = -2 x = -2 11

  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 Known assignments x = -2 x = -2 x = 7 12

  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 = -2 x = 7 13

  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 = 7 14

  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 15

  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 = 0 x = 7 x = 0 r = 0; 16

  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; 17

  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 Known assignments x == 0 x ≠ 0 x = -2 x = 0 x = 7 x = 0 r = 0; return r; return r; 18

  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 = 7 x = 0 r = 0; return r; return r; 19

  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 r = 0; return r; return r; 20

  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 r = 0; return r; return r; 21

  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; 22

  23. 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

  24. 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

  25. 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

  26. 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

  27. 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

  28. 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

  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 = -2 29

  30. 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

  31. 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

  32. 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

  33. 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

  34. 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

  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 Known assignments x == 0 x ≠ 0 x = -2 x = 0 x = 0 r = 0; return r; return r; 35

  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 = 7 r = 0; return r; return r; 36

  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; 37

  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; 38

  39. 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

  40. 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

  41. Suppose this exploration tree for md5 41

  42. Suppose this path md5("ase2020") 42

  43. Solver queries: 0 Pending Vanilla 43

  44. Solver queries: 0 Pending Vanilla ase20 20 44

  45. Solver queries: 0 Pending Vanilla ase20 20 45

  46. Solver queries: 0 Pending Vanilla ase20 20 46

  47. Solver queries: 1 Pending Vanilla ase20 20 47

  48. Solver queries: 2 Pending Vanilla ase20 20 48

  49. Solver queries: 3 Pending Vanilla ase20 20 49

  50. Solver queries: 4 Pending Vanilla ase20 20 50

  51. Solver queries: 5 Pending Vanilla ase20 20 51

  52. Solver queries: 6 Pending Vanilla ase20 20 52

  53. Solver queries: 7 Pending Vanilla ase20 20 53

  54. Solver queries: 8 Pending Vanilla ase20 ase20 20 20 54

Recommend


More recommend