Użycie gdb do jednoetapowego kodu asemblera poza określonym plikiem wykonywalnym powoduje błąd „nie można znaleźć granic bieżącej funkcji”

86

Jestem poza docelowym plikiem wykonywalnym gdb i nie mam nawet stosu, który odpowiadałby temu celowi. I tak chcę zrobić jednoetapowo, aby móc zweryfikować, co się dzieje w moim kodzie asemblera, ponieważ nie jestem ekspertem w montażu x86. Niestety, gdb odmawia wykonania tego prostego debugowania na poziomie zestawu. Pozwala mi ustawić i zatrzymać się na odpowiednim punkcie przerwania, ale gdy tylko próbuję wykonać krok naprzód, gdb zgłasza błąd „Nie można znaleźć granic bieżącej funkcji”, a EIP się nie zmienia.

Dodatkowe Szczegóły:

Kod maszynowy został wygenerowany przez instrukcje gcc asm i skopiowałem go do lokalizacji pamięci jądra, w której jest wykonywany, z wyjścia objdump -d. Nie miałbym nic przeciwko prostemu sposobowi użycia programu ładującego do załadowania mojego kodu obiektowego na przeniesiony adres, ale pamiętaj, że ładowanie musi być wykonane w module jądra.

Przypuszczam, że inną alternatywą byłoby stworzenie fałszywego modułu jądra lub pliku informacji debugowania, który zostanie przekazany gdb, aby uwierzył, że ten obszar znajduje się w kodzie programu. gdb działa dobrze na samym pliku wykonywalnym jądra.

(Dla tych, którzy naprawdę chcą wiedzieć, wstawiam kod w czasie wykonywania do przestrzeni danych jądra systemu Linux wewnątrz maszyny wirtualnej VMware i debuguję go ze zdalnego debugowania jądra gdb za pośrednictwem wbudowanego kodu gdb wbudowanego w VMware Workstation. Uwaga: nie piszę jądra exploity; Jestem absolwentem bezpieczeństwa piszącym prototyp).

(Mogę ustawić punkt przerwania dla każdej instrukcji w moim zestawie. Działa, ale po pewnym czasie będzie to dość pracochłonne, ponieważ rozmiar instrukcji montażu x86 jest różny, a lokalizacja zestawu będzie się zmieniać za każdym razem, gdy uruchomię ponownie).

Paweł
źródło
Sprytni ludzie z ksplice.com wstrzykują dane i kod do jądra, montując „fałszywe” moduły jądra i ładując je. A jeśli oni mogą to zrobić, dlaczego nie możesz? ;-)
ephemient

Odpowiedzi:

116

Możesz użyć stepilub nexti(co można skrócić do silub ni), aby przejść przez kod maszynowy.

R Samuel Klatchko
źródło
1
Łał. Z perspektywy czasu nie wiem, jak zapomniałem o stepi. Wydaje mi się, że po prostu założyłem, że ponieważ gdb nie ma kodu źródłowego, krok wróci do instrukcji asemblera.
Paul
1
uwaga: często nie możesz wpisać "break main", "run" dla programów asemblerowych. Zamiast tego wpisz „layout asm”, „start”. Mam to po przeczytaniu poniższej wiadomości, ale ktoś inny czytający ten post może nie być tak cierpliwy.
Dmitry
1
@Dmitry startjest równoważne tbreak mainnastępujący po run(uwaga: tbreakzamiast break)
Ruslan
151

Zamiast gdbuciekać gdbtui. Lub biegnij gdbz -tuiprzełącznikiem. Lub naciśnij C-x C-apo wprowadzeniu gdb. Teraz jesteś w trybie TUI GDB .

Enter, layout asmaby utworzyć zestaw wyświetlania górnego okna - automatycznie podąży za wskaźnikiem instrukcji, chociaż możesz także zmieniać ramki lub przewijać podczas debugowania. Naciśnij, C-x saby przejść do trybu SingleKey, w którym run continue up down finishitp. Są skracane do pojedynczego klawisza, co pozwala na bardzo szybkie przejście przez program.

   + ------------------------------------------------- -------------------------- +
B +> | 0x402670 <główne> push% r15 |
   | 0x402672 <main + 2> mov% edi,% r15d |
   | 0x402675 <main + 5> push% r14 |
   | 0x402677 <main + 7> push% r13 |
   | 0x402679 <main + 9> mov% rsi,% r13 |
   | 0x40267c <main + 12> push% r12 |
   | 0x40267e <main + 14> push% rbp |
   | 0x40267f <main + 15> push% rbx |
   | 0x402680 <main + 16> sub $ 0x438,% rsp |
   | 0x402687 <main + 23> mov (% rsi),% rdi |
   | 0x40268a <main + 26> movq $ 0x402a10,0x400 (% rsp) |
   | 0x402696 <main + 38> movq $ 0x0,0x408 (% rsp) |
   | 0x4026a2 <main + 50> movq $ 0x402510,0x410 (% rsp) |
   + ------------------------------------------------- -------------------------- +
proces potomny 21518 In: main Line: ?? PC: 0x402670
(gdb) plik / opt / j64-602 / bin / jconsole
Czytanie symboli z /opt/j64-602/bin/jconsole...done.
(nie znaleziono symboli debugowania) ... gotowe.
(gdb) układ asm
(gdb) start
(gdb)
ephemient
źródło
26

Najbardziej użyteczną rzeczą, jaką możesz tutaj zrobić, jest to display/i $pc, że przed użyciem, stepijak już zasugerowano w odpowiedzi R. Samuela Klatchko. Mówi to gdb, aby za każdym razem zdemontował bieżącą instrukcję tuż przed wyświetleniem zachęty; następnie możesz po prostu wciskać Enter, aby powtórzyć stepipolecenie.

(Zobacz moją odpowiedź na inne pytanie po więcej szczegółów - kontekst tego pytania był inny, ale zasada jest taka sama).

Matthew Slattery
źródło