Bezpośrednie interakcje zewnętrzne

https://chacker.pl/

Alternatywnie, silnik wykonywania symbolicznego może bezpośrednio wykonywać interakcje zewnętrzne. Na przykład, zamiast modelować efekty wywołania systemowego, silnik Symbex może faktycznie wykonać wywołanie systemowe i włączyć konkretną wartość zwracaną oraz efekty uboczne do stanu symbolicznego. Chociaż to podejście jest proste, prowadzi do problemów, gdy wiele ścieżek, które wykonują konkurujące ze sobą interakcje zewnętrzne, jest badanych równolegle. Przykładowo, jeśli wiele ścieżek działa równolegle na tym samym pliku fizycznym, może to prowadzić do problemów ze spójnością, jeśli zmiany będą ze sobą kolidować. Można to obejść, klonując pełny stan systemu dla każdej badanej ścieżki, ale takie rozwiązanie jest niezwykle pamięciochłonne. Co więcej, ponieważ zewnętrzne komponenty oprogramowania nie są w stanie obsłużyć stanu symbolicznego, bezpośrednia interakcja ze środowiskiem oznacza kosztowne wywołanie solvera ograniczeń w celu obliczenia odpowiednich wartości konkretnych, które można przekazać do wywołania systemowego lub bibliotecznego.Ze względu na trudności związane ze statycznym wykonywaniem symbolicznym, nowsze badania skupiają się na alternatywnych implementacjach symbexu w oparciu o analizę dynamiczną.

Modelowanie efektów

https://chacker.pl/

Powszechnym podejściem jest modelowanie przez silnik SSE efektów interakcji zewnętrznych, takich jak wywołania systemowe i biblioteczne. Modele te stanowią swego rodzaju „podsumowanie” efektów, jakie wywołanie systemowe lub biblioteczne wywiera na stan symboliczny. (Należy pamiętać, że słowo „model” w tym znaczeniu nie ma nic wspólnego z modelami zwracanymi przez solver ograniczeń).Pod względem wydajności modelowanie efektów jest stosunkowo tanim rozwiązaniem. Jednak stworzenie dokładnych modeli dla wszystkich możliwych interakcji ze środowiskiem – w tym z siecią, systemem plików i innymi procesami – jest monumentalnym zadaniem, które może wymagać stworzenia symulowanego symbolicznego systemu plików, symbolicznego stosu sieciowego itd. Co gorsza, modele muszą zostać przepisane, jeśli chcemy symulować inny system operacyjny lub jądro. Dlatego w praktyce modele są często niekompletne lub niedokładne.

Statyczne wykonywanie symboliczne (SSE)

https://chacker.pl/

Podobnie jak większość technik analizy oprogramowania i plików binarnych, wykonywanie symboliczne występuje w wariantach statycznych i dynamicznych, charakteryzujących się różnymi kompromisami w zakresie skalowalności i kompletności. Tradycyjnie wykonywanie symboliczne to technika analizy statycznej, która emuluje część programu, propagując stan symboliczny z każdą emulowaną instrukcją. Ten typ wykonywania symbolicznego jest również znany jako statyczne wykonywanie symboliczne (SSE). Analizuje ono wyczerpująco wszystkie możliwe ścieżki lubwykorzystuje heurystykę, aby zdecydować, które ścieżki należy wybrać. Zaletą SSE jest to, że umożliwia analizowanie programów, które nie mogą zostać uruchomione na danym procesorze. Na przykład można analizować pliki binarne ARM na komputerze x86. Kolejną zaletą jest to, że łatwo jest emulować tylko część pliku binarnego (na przykład tylko jedną funkcję) zamiast całego programu. Wadą jest to, że eksploracja obu kierunków w każdej gałęzi nie zawsze jest możliwa ze względu na problemy ze skalowalnością. Chociaż można użyć heurystyki, aby ograniczyć liczbę eksplorowanych gałęzi, opracowanie skutecznej heurystyki, która wychwyci wszystkie interesujące ścieżki, nie jest łatwe. Co więcej, niektóre elementy działania aplikacji są trudne do poprawnego modelowania za pomocą SSE, szczególnie gdy sterowanie przepływa poza aplikację do komponentów oprogramowania, nad którymi nie ma kontroli silnik wykonywania symbolicznego, takich jak jądro lub biblioteka. Dzieje się tak, gdy program wydaje wywołanie systemowe lub biblioteczne, odbiera sygnał, próbuje odczytać zmienną środowiskową itd. Aby obejść ten problem, można zastosować poniższe rozwiązania, choć każde z nich ma swoje wady.

Statyczne a dynamiczne

https://chacker.pl/

Czy implementacja Symbex opiera się na analizie statycznej, czy dynamicznej?

Online a offline

Czy silnik Symbex bada wiele ścieżek równolegle (online), czy nie (offline)?

Stan symboliczny

Które części stanu programu są reprezentowane symbolicznie, a które są konkretne? Jak obsługiwany jest symboliczny dostęp do pamięci?

Pokrycie ścieżki

Które (i ile) ścieżek programu bada analiza symboliczna?

Omówmy każdą z tych decyzji projektowych i ich konsekwencje w zakresie wydajności, ograniczeń i kompletności.

Warianty i ograniczenia wykonywania symbolicznego

https://chacker.pl/

Podobnie jak silniki analizy skażeń, silniki Symbex są często projektowane jako framework, którego można użyć do tworzenia własnych narzędzi Symbex. Wiele silników Ymbex implementuje aspekty z wielu wariantów wykonywania symbolicznego i pozwala na wybór między nimi. Dlatego ważne jest, aby znać kompromisy związane z tymi decyzjami projektowymi.Rysunek ilustruje najważniejsze wymiary projektowe implementacji Symbex, pokazując jeden wymiar na każdy poziom drzewa.

Symboliczne wykonywanie przykładowego programu

https://chacker.pl/

Uściślijmy koncepcję wykonywania symbolicznego, korzystając z pseudokodu z Listingu.

Listing : Przykład pseudokodu ilustrujący wykonywanie symboliczne

Ten program pseudokodu pobiera dwie liczby całkowite o nazwach x i y z danych wprowadzonych przez użytkownika. Przykład omawiany w tej sekcji wykorzystuje wykonywanie symboliczne w celu znalezienia danych wprowadzonych przez użytkownika, które obejmowałyby ścieżki w kodzie prowadzące odpowiednio do funkcji foo i bar. Aby to osiągnąć, należy przedstawić wartości x i y jako wartości symboliczne, a następnie symbolicznie wykonać program, aby obliczyć ograniczenie ścieżki i wyrażenia symboliczne nałożone na wartości x i y przez operacje programu. Na koniec rozwiązuje się te formuły, aby znaleźć konkretne wartości (jeśli istnieją) dla wartości x i y, które prowadzą program do przejścia każdej ścieżki. Rysunek  pokazuje, jak ewoluuje stan symboliczny dla wszystkich możliwych ścieżek w funkcji przykładowej.

Listing  rozpoczyna się od odczytania x i y z danych wejściowych użytkownika (1). Jak widać na rysunku , ograniczenie ścieżki π jest początkowo ustawione na ⊤, symbol tautologii. Oznacza to, że żadne gałęzie nie zostały jeszcze wykonane, więc nie nałożono żadnych ograniczeń. Podobnie, magazyn wyrażeń symbolicznych jest początkowo zbiorem pustym. Po odczytaniu x, silnik Symbex tworzy nowe wyrażenie symboliczne φ1 = α1, które odpowiada nieograniczonej wartości symbolicznej, która może reprezentować dowolną konkretną wartość, i odwzorowuje x na to wyrażenie. Odczyt y powoduje analogiczny efekt, odwzorowując y na φ2 = α2. Następnie, operacja z = x + y (2) powoduje, że silnik Symbex odwzorowuje z na nowe wyrażenie symboliczne, φ3 = φ1 + φ2. Załóżmy, że silnik wykonania symbolicznego najpierw bada prawdziwą gałąź warunku if(x >= 5) (3). Aby to zrobić, silnik dodaje ograniczenie rozgałęzienia φ1 ≥ 5 do π i kontynuuje symboliczne wykonywanie w miejscu docelowym rozgałęzienia, którym jest wywołanie funkcji foo. Przypomnijmy, że celem było znalezienie konkretnych danych wejściowych użytkownika, które prowadzą do funkcji foo lub bar. Ponieważ dotarliśmy do wywołania funkcji foo, możemy rozwiązać wyrażenia i ograniczenia rozgałęzienia, aby znaleźć konkretne wartości dla x i y, które prowadzą do tego wywołania funkcji foo. Na tym etapie wykonywania x i y są mapowane na wyrażenia symboliczne φ1 = α1 i φ2 = α2, odpowiednio, a α1 i α2 są jedynymi wartościami symbolicznymi. Co więcej, masz tylko jedno ograniczenie gałęzi: φ1 ≥ 5. Zatem jednym z możliwych rozwiązań prowadzących do tego wywołania foo jest α1 = 5 ∧ α2 = 0. Oznacza to, że jeśli uruchomisz program normalnie (konkretne wykonanie) z danymi wejściowymi użytkownika x = 5 i y = 0, dojdziesz do wywołania foo. Zauważ, że α2 może przyjmować dowolną wartość, ponieważ nie występuje w żadnym z wyrażeń symbolicznych pojawiających się w ograniczeniu ścieżki. Rozwiązanie takie jak to, które właśnie zobaczyłeś, nazywa się modelem. Zwykle modele oblicza się automatycznie za pomocą specjalnego programu zwanego rozwiązywaczem ograniczeń, który jest w stanie rozwiązywać problemy dla wartości symbolicznych w taki sposób, że wszystkie ograniczenia i wyrażenia symboliczne są spełnione, jak wkrótce poznasz w rozdziale 12.2. Załóżmy teraz, że chcesz dowiedzieć się, jak zamiast tego dotrzeć do wywołania bar. Aby to zrobić, musisz uniknąć gałęzi if(x >= 5) i zamiast tego wziąć gałąź else (4). Zmieniasz więc stare ograniczenie ścieżki φ1 ≥ 5 na φ1 < 5 i prosisz solver o nowy model. W tym przypadku możliwym modelem byłby α1 = 4 ∧ α2 = 0. W niektórych przypadkach solver może również zgłosić brak rozwiązania, co oznacza, że ​​ścieżka jest nieosiągalna. Ogólnie rzecz biorąc, nie jest możliwe pokrycie wszystkich ścieżek za pomocą nietrywialnego programu, ponieważ liczba możliwych ścieżek rośnie wykładniczo wraz z liczbą rozgałęzień. Dowiesz się, jak używać heurystyk do decydowania, które ścieżki eksplorować. Jak wspomniałem, istnieje kilka wariantów wykonywania symbolicznego, z których niektóre działają nieco inaczej niż w przykładzie, który właśnie omówiłem. Przyjrzyjmy się tym innym wariantom wykonywania symbolicznego i zbadajmy ich wady i zalety.

Ograniczenie ścieżki

https://chacker.pl/

Ograniczenie ścieżki koduje ograniczenia nałożone na wyrażenia symboliczne przez rozgałęzienia podejmowane podczas wykonywania. Na przykład, jeśli wykonanie symboliczne przyjmuje gałąź if(x < 5), a następnie kolejną gałąź if(y >= 4), gdzie x i y są odpowiednio odwzorowane na wyrażenia symboliczne φ1 i φ2, wzór ograniczenia ścieżki przyjmuje postać φ1 < 5 ∧ φ2 ≥ 4. Ograniczenie ścieżki będę oznaczał symbolem π. W literaturze poświęconej wykonywaniu symbolicznemu ograniczenia ścieżki są czasami nazywane ograniczeniami rozgałęzienia. Będę używał terminu ograniczenie rozgałęzienia w odniesieniu do ograniczenia narzuconego przez pojedynczą gałąź, a terminu ograniczenie ścieżki w odniesieniu do koniunkcji wszystkich ograniczeń rozgałęzienia zgromadzonych wzdłuż ścieżki programu.

Wyrażenia symboliczne

https://chacker.pl/

Wyrażenie symboliczne φj, gdzie j ∈ N, odpowiada albo wartości symbolicznej αi, albo pewnej matematycznej kombinacji wyrażeń symbolicznych, takiej jak φ3 = φ1 + φ2. σ będę używać do oznaczenia magazynu wyrażeń symbolicznych, który jest zbiorem wszystkich wyrażeń symbolicznych użytych w wykonaniu symbolicznym. Jak wspomniałem, binarny system symboliczny (symbex) odwzorowuje wszystkie lub niektóre rejestry i lokalizacje pamięci na wyrażenie w σ.

Stan symboliczny

https://chacker.pl/

Wykonanie symboliczne działa na wartościach symbolicznych, które reprezentują dowolną możliwą wartość konkretną. Wartości symboliczne będę oznaczać jako αi, gdzie i jest liczbą całkowitą (i ∈ N). Silnik Symbex oblicza dwa różne rodzaje formuł na podstawie tych wartości symbolicznych: zbiór wyrażeń symbolicznych i ograniczenie ścieżki. Ponadto utrzymuje mapowanie zmiennych (lub w przypadku binarnego Symbex, rejestrów i lokalizacji pamięci) na wyrażenia symboliczne. Połączenie ograniczenia ścieżki i wszystkich wyrażeń symbolicznych oraz mapowań nazywam stanem symbolicznym.

Wykonanie symboliczne a konkretne

https://chacker.pl/

Symbex wykonuje (lub emuluje) aplikację z wartościami symbolicznymi, a nie z wartościami konkretnymi używanymi podczas normalnego uruchamiania programu. Oznacza to, że zmienne nie zawierają konkretnych wartości, takich jak 42 czy foobar, jak miałoby to miejsce podczas normalnego wykonywania. Zamiast tego, niektóre lub wszystkie zmienne (lub w kontekście analizy binarnej, rejestry lub komórki pamięci) są reprezentowane przez symbol, który zastępuje dowolną możliwą wartość, jaką zmienna może przyjąć. W trakcie wykonywania, wykonywanie symboliczne oblicza formuły logiczne dla tych symboli. Formuły te reprezentują operacje wykonywane na symbolach podczas wykonywania i opisują granice zakresu wartości, które symbole mogą reprezentować. Jak wyjaśnię, wiele silników Symbex przechowuje symbole i formuły jako metadane oprócz wartości konkretnych, zamiast je zastępować, podobnie jak analiza skażeń śledzi metadane skażeń. Zbiór wartości symbolicznych i formuł przechowywanych przez silnik Symbex nazywa się stanem symbolicznym. Przyjrzyjmy się, jak zorganizowany jest stan symboliczny, a następnie przeanalizujmy konkretny przykład ewolucji stanu w wykonaniu symbolicznym.