Na koniec musisz wiedzieć, które ścieżki programu są badane przez analizę symboliczną. Klasyczne wykonywanie symboliczne bada wszystkie ścieżki programu, tworząc nowy stan symboliczny w każdej gałęzi. To podejście nie jest skalowalne, ponieważ liczba możliwych ścieżek rośnie wykładniczo wraz z liczbą gałęzi w programie; jest to dobrze znany problem eksplozji ścieżek. W rzeczywistości liczba ścieżek może być nieskończona, jeśli występują nieograniczone pętle lub wywołania rekurencyjne. W przypadku programów nietrywialnych potrzebne jest inne podejście, aby wykonywanie symboliczne było bardziej praktyczne. Alternatywnym podejściem dla SSE jest użycie heurystyki do decydowania, które ścieżki badać. Na przykład, w narzędziu do automatycznego wykrywania błędów, możesz skupić się na analizie pętli indeksujących tablice, ponieważ stosunkowo często zawierają one błędy, takie jak przepełnienia bufora. Inną powszechną heurystyką jest przeszukiwanie w głąb (DFS), które bada jedną kompletną ścieżkę programu przed przejściem do kolejnej ścieżki, przy założeniu, że głęboko zagnieżdżony kod jest prawdopodobnie bardziej „interesujący” niż kod powierzchowny. Przeszukiwanie wszerz (BFS) działa odwrotnie, badając wszystkie ścieżki równolegle, ale zajmuje więcej czasu, aby dotrzeć do głęboko zagnieżdżonego kodu. Wybór heurystyki zależy od celu narzędzia Symbex, a znalezienie odpowiedniej heurystyki może stanowić poważne wyzwanie. Wykonywanie Concolic bada tylko jedną ścieżkę na raz, w oparciu o konkretne dane wejściowe. Można je jednak również połączyć z podejściem heurystycznej eksploracji ścieżek, a nawet z podejściem eksploracji wszystkich ścieżek. W przypadku wykonywania Concolic najłatwiejszym sposobem eksploracji wielu ścieżek jest wielokrotne uruchamianie aplikacji, za każdym razem z nowymi danymi wejściowymi odkrytymi poprzez „odwrócenie” ograniczeń gałęzi w poprzednim przebiegu. Bardziej wyrafinowanym podejściem jest tworzenie migawek stanu programu, tak aby po zakończeniu eksploracji jednej ścieżki można było przywrócić migawkę do wcześniejszego punktu wykonania i stamtąd eksplorować inną ścieżkę. Podsumowując, wykonywanie symboliczne ma wiele parametrów, które można modyfikować, aby zrównoważyć wydajność i ograniczenia analizy. Optymalna konfiguracja będzie zależeć od celów, a różne silniki Symbex dokonują różnych wyborów konfiguracyjnych. Na przykład Triton ( i angr1 to silniki Symbex na poziomie binarnym, które obsługują SSE na poziomie aplikacji i wykonywanie concolic. S2E2 również działa na plikach binarnych, ale wykorzystuje podejście oparte na maszynie wirtualnej w całym systemie, które może stosować Symbex nie tylko do aplikacji, ale także do jądra, bibliotek i sterowników działających na maszynie wirtualnej. Natomiast KLEE3 wykonuje klasyczne SSE online na kodzie bitowym LLVM, a nie bezpośrednio na plikach binarnych, obsługując wiele heurystyk wyszukiwania w celu optymalizacji pokrycia ścieżki. Istnieją nawet silniki Symbex wyższego poziomu, które działają bezpośrednio na kodzie C, Java lub Python. Teraz, gdy znasz już działanie różnych technik Symbex, omówmy kilka typowych optymalizacji, których możesz użyć, aby zwiększyć skalowalność swoich narzędzi Symbex.
