5

Zawarłem tag iOS, ale używam symulatora na komputerze MacBook Pro Core i7 (x86-64, prawda?), Więc myślę, że to nieistotne.Co zawiera zawartość rejestrów ogólnego przeznaczenia?

Obecnie trwa debugowanie awarii w reklamach wideo Flurry. Mam punkt przerwania ustawiony na wyjątków Objective-C. Po trafieniu punktu przerwania znajduję się w objc_msgSend. Callstack zawiera mieszankę prywatnych metod Flurry i iOS, nic publicznego i nic, co napisałem. Wywołanie register read wyjść z ramy stos objc_msgSend następujące:

(lldb) register read 
General Purpose Registers: 
     eax = 0x1ac082d0 
     ebx = 0x009600b5 "spaceWillDismiss:interstitial:" 
     ecx = 0x03e2cddb "makeKeyAndVisible" 
     edx = 0x0000003f 
     edi = 0x0097c6f3 "removeWindow" 
     esi = 0x00781e65 App`-[FlurryAdViewController removeWindow] + 12 
     ebp = 0xbfffd608 
     esp = 0xbfffd5e8 
     ss = 0x00000023 
    eflags = 0x00010202 App`-[FeedTableCell setupVisibleCommentAndLike] + 1778 at FeedTableCell.m:424 
     eip = 0x049bd09b libobjc.A.dylib`objc_msgSend + 15 
     cs = 0x0000001b 
     ds = 0x00000023 
     es = 0x00000023 
     fs = 0x00000000 
     gs = 0x0000000f 

Mam kilka pytań dotyczących tego wyjścia.

  • Założono, że $ ebx zawiera selektor, który spowodował awarię, a $ edi jest ostatnią metodą wykonywania. Czy tak jest?
  • $ eip to miejsce, w którym się rozbiłem. Czy to zwykle tak jest?
  • $ eflags odwołuje się do metody instancji, która, o ile mi wiadomo, nie ma nic wspólnego z tą awarią. Co to jest?
  • Czy są jakieś inne informacje, które mogę wyciągnąć z tych rejestrów?

Odpowiedz

1

Nie mogę mówić do układów ramek iOS/Objective-C, więc nie mogę odpowiedzieć na twoje pytanie dotyczące EBX i EDI. Mogę jednak pomóc w kwestii EIP i EFLAGS oraz udzielić ogólnych wskazówek na temat ESP/EBP i rejestrów selektorów. (Nawiasem mówiąc, symulator jest symulowanie x86 środowiska 32-bitowego, można powiedzieć, bo twoje rejestry są 32 bitów.)

EIP jest rejestrem instruction pointer, znany również jako licznik programu, który zawiera adres aktualnie wykonywanej instrukcji maszyny. W ten sposób wskaże miejsce, w którym rozbił się program, lub bardziej ogólnie, gdzie jest twój program, kiedy trafia w punkt przerwania, zrzuca rdzeń itp.

EIP jest zapisywany i przywracany w celu zaimplementowania wywołań funkcji (na poziomie kodu maszynowego - podświetlanie może spowodować, że połączenia językowe wysokiego poziomu nie będą wykonywać rzeczywistych połączeń). W językach, które nie są bezpieczne dla pamięci, przepełnienie bufora stosu może zastąpić zapisaną wartość wskaźnika instrukcji, powodując powrót instrukcji powrotu do niewłaściwego miejsca. Jeśli masz szczęście, nadpisana wartość wyzwoli błąd segfault w następnym pobraniu pamięci, ale wartość EIP będzie arbitralna i nie będzie pomocna przy debugowaniu problemu. Jeśli masz pecha, osoba atakująca stworzyła nowy EIP, aby wskazać użyteczny kod, więc wiele środowisk używa "plików cookie stosu" lub "kanarków", aby wykryć te nadpisania przed przywróceniem zapisanego/nadpisanego EIP, w którym to przypadku wartość EIP może być przydatny.

EFLAGS nie jest adresem pamięci i prawdopodobnie nie jest rejestrem ogólnego przeznaczenia. Każdy bit EFLAGS jest flagą, którą można ustawić lub przetestować za pomocą różnych instrukcji. Najważniejszymi flagami są flagi carry, zero i sign, które są ustawiane za pomocą instrukcji arytmetycznych i używane do rozgałęziania warunkowego. Twój debugger źle interpretuje go jako adres pamięci i wyświetla go jako najbliższą funkcję, ale nie jest to faktycznie związane z awarią. (+ 1778 to gratka: oznacza to, że EFLAGS wskazuje 1778 bajtów na tę funkcję, ale funkcja prawdopodobnie nie będzie miała długości 1778 bajtów.)

ESP to wskaźnik stosu, a EBP to (zwykle) wskaźnik ramki (również nazywany wskaźnikiem bazowym). Rejestry te wiążą bieżącą ramkę na stosie wywołań. Twój debugger zwykle może pokazać wartości zmiennych stosu i bieżącego stosu połączeń na podstawie tych wskaźników. W przypadku uszkodzenia, czasami można ręcznie sprawdzić stos, aby odzyskać EBP i ręcznie rozwinąć stos wywoławczy.Zauważ, że kod może być kompilowany bez wskaźników ramek (pominięcie wskaźnika ramki), zwalniając EBP dla innych zastosowań; jest to powszechne na x86, ponieważ jest tak mało rejestrów ogólnego przeznaczenia.

SS, CS, DS, ES, FS i GS posiadają selektory segmentów, używane w złych dawnych czasach przed przywoływaniem do wdrożenia segmentation. Obecnie FS i GS są powszechnie używane przez systemy operacyjne dla bloków stanu procesu i wątku; były to jedyne rejestry selektorów przeniesione na x86-64. Rejestry selektora generalnie nie są pomocne przy debugowaniu.

Powiązane problemy