Funkcje i funkcjonalność IDA Pro

https://chacker.pl/

IDA Pro ma dużą liczbę wbudowanych funkcji, narzędzi i funkcjonalności; jednakże, podobnie jak w przypadku wielu złożonych aplikacji, przy pierwszym uruchomieniu należy się uczyć. Wiele z tych opcji nie jest dostępnych w bezpłatnej wersji IDA. Zaczniemy od najbardziej podstawowego ustawienia preferencji, czyli schematu kolorów, a następnie omówimy niektóre z bardziej przydatnych funkcji. IDA Pro oferuje różne predefiniowane opcje ze schematem kolorów. Aby ustawić te opcje, kliknij menu Opcje, a następnie Kolory. Na rysunku pokazano menu rozwijane i opcje kolorów IDA.

Możesz wybrać pomiędzy domyślnym, darcula i ciemnym. Opcja ciemna dotyczy w całości IDA Pro. Opcja darcula dotyczy tylko okna demontażu. Rysunek pokazuje przykład trybu ciemnego.

Nawigacja w IDA Pro

https://chacker.pl/

Ważne jest, aby zrozumieć, jak prawidłowo pracować i poruszać się po IDA Pro, ponieważ istnieje wiele domyślnych zakładek i okien. Zacznijmy od przykładu załadowania podstawowego pliku binarnego do IDA Pro jako pliku wejściowego. Podczas pierwszego ładowania programu myAtoi do IDA Pro pojawia się następujące okno:

IDA Pro przeanalizował metadane pliku obiektowego i ustalił, że jest to 64-bitowy plik binarny ELF. IDA przeprowadza dużą część wstępnej analizy, takiej jak śledzenie przepływu wykonywania, przekazywanie podpisów technologii szybkiej identyfikacji i rozpoznawania bibliotek (FLIRT), śledzenie wskaźników stosu, analiza tabeli symboli i nazewnictwo funkcji, wstawianie danych o typach, jeśli są dostępne, oraz przypisanie nazw lokalizacji. Po kliknięciu OK IDA Pro przeprowadza automatyczną analizę. W przypadku dużych plików wejściowych analiza może zająć trochę czasu. Zamknięcie wszystkich okien i ukrycie paska narzędzi Nawigatora przyspiesza analizę. Po zakończeniu kliknięcie opcji Windows w opcjach menu i wybranie Resetuj pulpit przywraca układ do ustawień domyślnych. Gdy IDA Pro zakończy automatyczną analizę programu myAtoi, otrzymamy wynik pokazany na rysunku

UWAGA Wiele funkcji i elementów przedstawiono na rysunku 5-1. Pamiętaj, aby wracać do tego obrazu, gdy będziemy przeglądać różne sekcje, funkcje i opcje.

Pasek narzędzi Nawigatora na rysunku zapewnia przegląd całego pliku wejściowego, podzielonego na różne sekcje.

Każdy oznaczony kolorem obszar na pasku narzędzi można kliknąć, aby uzyskać łatwy dostęp do tej lokalizacji. W naszym przykładzie z programem myAtoi duża część ogólnego obrazu jest identyfikowana jako zwykłe funkcje. Oznacza to funkcje wewnętrzne i kod wykonywalny skompilowany do postaci binarnej, w przeciwieństwie do symboli zewnętrznych, które są zależnościami dynamicznymi, oraz funkcji bibliotecznych, które wskazywałyby statycznie skompilowany kod biblioteki. Okno Funkcje, pokazane na rysunku, zawiera listę nazw wszystkich funkcji wewnętrznych i zależności dynamicznych.

Dwukrotne kliknięcie wpisu powoduje wyświetlenie tej funkcji w głównym oknie widoku wykresu. Klawisz skrótu G umożliwia także bezpośrednie przejście do adresu. Jeśli w IDA Pro dostępna jest tabela symboli, wszystkie funkcje otrzymują odpowiednie nazwy. Jeśli informacja o symbolu nie jest dostępna dla danej funkcji, podaje się przedrostek podrzędny, po którym następuje przesunięcie względnego adresu wirtualnego (RVA), takie jak sub_1020. Poniżej znajduje się przykład sytuacji, w której tabela symboli nie jest dostępna, a kiedy jest dostępna. Poniżej okna Funkcje znajduje się okno Przegląd wykresu. . Jest to po prostu interaktywne okno przedstawiające całą aktualnie analizowaną funkcję. Okno danych wyjściowych na dole domyślnego układu IDA Pro pokazano na rysunku  wraz z interaktywnym paskiem Pythona lub IDC.

Okno Dane wyjściowe to miejsce, w którym wyświetlane są komunikaty oraz wyniki wprowadzonych danych polecenia za pośrednictwem IDA Python lub IDC. IDA Python i IDC zostały omówione w rozdziale 13. W naszym przykładzie ostatni wyświetlony komunikat brzmi: „Początkowa autoanaliza została zakończona”. Główne okno pośrodku domyślnego układu IDA Pro nosi nazwę IDA View-A w naszym przykładzie i pokazano na rysunku .  To jest widok wykresu, który wyświetla funkcje i bloki w obrębie tych funkcji w rekurencyjnym stylu opadania. Naciśnięcie spacji w tym oknie powoduje przełączenie widoku z widoku wykresu na widok tekstowy, jak pokazano na rysunku. Widok tekstowy to bardziej liniowy sposób patrzenia na demontaż. Ponowne naciśnięcie spacji przełącza pomiędzy dwiema opcjami widoku. Na rysunku  pokazano główną funkcję i jest tylko jeden blok kodu. Informacje o typie są wyświetlane u góry funkcji, po nich następują zmienne lokalne i dezasemblacja.

Rysunek przedstawia zakładkę Importy. To okno wyświetla wszystkie dynamiczne zależności pliku wejściowego od kodu biblioteki. Najwyższy wpis na liście to funkcja printf. Obiekt współdzielony zawierający tę funkcję jest wymagany do działania programu i musi zostać mapowany do procesu w czasie wykonywania. Nie pokazana jest karta Eksporty. W tym oknie wyświetlana jest lista normalnie dostępnych wyeksportowanych funkcji i skojarzonych z nimi adresów. Z tej sekcji korzystają obiekty współdzielone i biblioteki dołączane dynamicznie (DLL).

Co to jest dezasemblacja?

https://chacker.pl/

Najpierw przyjrzyjmy się procesowi deasemblacji kodu maszynowego. Jest to omówione na różne sposoby w innych miejscach tej książki, ale ważne jest, aby upewnić się, że rozumiesz podstawowy cel dezasemblera . W tym przykładzie używamy skompilowanej wersji programu myAtoi . Użyj narzędzia objdump zainstalowanego na Kali Linux z następującymi opcjami, aby zdemontować pierwsze osiem linii głównej funkcji programu myAtoi. Flaga -j pozwala określić sekcję; w tym przypadku wybieramy segment .text lub „code”. Flaga -d jest opcją demontażu. Grepujemy ciąg „<main>:” i drukujemy osiem wierszy po nim z flagą -A8.

W pierwszym wierszu wyniku w (1) widzimy, że główna funkcja zaczyna się od przesunięcia względnego adresu wirtualnego (RVA) wynoszącego 0x00000000000011ca w całym obrazie binarnym. Pierwsza linia zdezasemblowanego wyjścia w main zaczyna się od przesunięcia 11ca, jak widać w (2), po którym następuje kod operacji języka maszynowego 55, jak widać w (3). Na prawo od kodu operacji w (4) znajduje się odpowiednia zdemontowana instrukcja lub mnemoniczne push, po której następuje operand rbp w (5). Ta instrukcja spowoduje, że adres lub wartość przechowywana w rejestrze rbp zostanie wypchnięta na stos. Każdy z kolejnych wierszy wyjścia dostarcza tych samych informacji, pobierając kody operacji i wyświetlając odpowiedni demontaż. Jest to plik binarny w formacie wykonywalnym i linkującym (ELF) x86-64-bitowy. Gdyby ten program został skompilowany dla innego procesora, takiego jak ARM, kody operacji i zdezasemblowane instrukcje byłyby inne, ponieważ każda architektura procesora ma swój własny zestaw instrukcji. Dwie podstawowe metody demontażu to przeciągnięcie liniowe i zejście rekurencyjne (znane również jako przechodzenie rekurencyjne). Narzędzie objdump jest przykładem deasemblera liniowego, który rozpoczyna się na początku segmentu kodu lub określonego adresu początkowego, dezasemblując kolejno każdy kod operacji. Niektóre architektury mają zestaw instrukcji o zmiennej długości, na przykład x86-64, a inne architektury mają ustawione wymagania dotyczące rozmiaru, takie jak MIPS, gdzie każda instrukcja ma szerokość 4 bajtów. IDA jest przykładem dezasemblera rekurencyjnego, w którym kod maszynowy jest deasemblowany liniowo, aż do osiągnięcia instrukcji zdolnej do modyfikacji przepływu sterowania, takiej jak skok warunkowy lub rozgałęzienie. Przykładem skoku warunkowego jest instrukcja jz, która oznacza skok przy zera. Ta instrukcja sprawdza flagę zerową (zf) w rejestrze FLAGS, aby sprawdzić, czy jest ustawiona. Jeśli flaga jest ustawiona, skok jest wykonywany. Jeżeli flaga nie jest ustawiona, licznik programu przechodzi do kolejnego adresu sekwencyjnego, gdzie wykonanie jest kontynuowane. Aby dodać kontekst, poniższy obraz przedstawia dowolny przykład w IDA Pro skoku warunkowego po zwróceniu sterowania z funkcji alokacji pamięci:

Ten widok graficzny wewnątrz IDA Pro jest w formacie rekursywnego wyświetlania.

Najpierw wywoływana jest funkcja GetProcessHeap (1) . Jak sama nazwa wskazuje, to wywołanie funkcji zwraca adres bazowy lub uchwyt domyślnej sterty procesu. Adres sterty jest zwracany wywołującemu za pośrednictwem rejestru RAX. Argumenty wywołania HeapAlloc są teraz konfigurowane, przy czym pierwszym argumentem jest rozmiar, kopiowany z r14 do r8 w punkcie (2) przy użyciu instrukcji mov. Argument dwFlags jest ustawiany na 0 za pomocą instrukcji xor edx, edx w (3) , wskazując brak nowych opcji dla żądania alokacji. Adres sterty jest kopiowany z rax do rcx w (4) . Teraz, gdy argumenty funkcji HeapAlloc są już ustawione, instrukcja call jest wykonywana w punkcie (5) . Oczekiwany zwrot z wywołania HeapAlloc jest wskaźnikiem do przydzielonego fragmentu pamięci. Wartość przechowywana w rax jest następnie kopiowana do r15 w (6). Następnie wykonywana jest instrukcja test rax, rax w punkcie (7). Instrukcja testowa wykonuje operację bitową i. W tym przypadku testujemy rejestr rax przeciwko sobie samemu. Celem instrukcji testowej w tym przykładzie jest sprawdzenie, czy wartość zwracana z wywołania HeapAlloc wynosi 0, co oznaczałoby błąd. Jeśli rax przechowuje 0, a my i rejestr przeciwko sobie, ustawiana jest flaga zera (zf). Jeśli opcja HEAP_GENERATE_EXCEPTIONS jest ustawiona poprzez dwFlags podczas wywołania HeapAlloc, zwracane są kody wyjątków zamiast 0,1. Ostatnią instrukcją w tym bloku jest instrukcja skoku do zera (jz), at(8) . Jeśli zf jest ustawione, co oznacza, że wywołanie HeapAlloc nie powiodło się, wykonujemy skok; w przeciwnym razie przechodzimy liniowo do następnego adresu sekwencyjnego i kontynuujemy wykonywanie kodu.

Wprowadzenie do IDA Pro do inżynierii odwrotnej

https://chacker.pl/

Dlaczego przy dużej liczbie dostępnych darmowych i alternatywnych dezasemblerów wybrać IDA Pro? Do darmowych alternatywnych deasemblerów zalicza się Ghidra , radare2 i kilka innych. Komercyjne alternatywy obejmują Binary Ninja i Hopper. Każda z tych alternatyw jest świetnym deasemblerem; jednakże IDA jest bardzo szanowana, obsługuje większość architektur procesorów i posiada największą liczbę wtyczek, skryptów i innych rozszerzeń. Jest szeroko stosowany przez społeczność badaczy bezpieczeństwa i oferuje niezliczone funkcje pomagające w analizie plików binarnych. Dostępne są także bezpłatne wersje IDA Pro, z których najnowsza to IDA 7.0; jednakże ich funkcjonalność jest zazwyczaj ograniczona. W rozdziale 18 będziemy używać IDA Pro i powiązanych z nim wtyczek do przeprowadzenia analizy poprawek firmy Microsoft w celu zlokalizowania zmian w kodzie, które mogą wskazywać na załataną lukę. Wczesne wykorzystanie załatanej luki w zabezpieczeniach to potężna technika stosowana podczas ofensywnych działań związanych z bezpieczeństwem.

IDAPro

https://chacker.pl/

Deasembler i debugger znany jako Interactive Disassembler (IDA) Pro to bogata w funkcje, rozszerzalna aplikacja do inżynierii wstecznej, której właścicielem i administratorem jest firma Hex-Rays w Belgii. Jest to produkt komercyjny z dostępnymi alternatywnymi wersjami, takimi jak IDA Home i IDA Free. Rodzina dezasemblerów IDA jest aktywnie rozwijana dzięki dużej liczbie swobodnie dostępnych wtyczek i skryptów dostarczonych przez Hex-Rays i społeczność użytkowników. Hex-Rays oferuje także Dekompilator Hex-Rays, prawdopodobnie najlepszy dostępny dekompilator. W porównaniu do innych deasemblerów jest najbardziej dojrzały, obsługuje największą liczbę architektur i funkcji procesorów.

Streszczenie

https://chacker.pl/

Omówiliśmy podstawowe funkcje i funkcjonalność Ghidry, od których możesz zacząć, pozostawiając otwarte drzwi do zgłębiania bardziej zaawansowanych tematów. Przyjrzeliśmy się takim tematom, jak interfejs Ghidry, poprawa czytelności za pomocą adnotacji oraz sposób używania Ghidry do różnicowania binarnego i analizy poprawek. Poświęć trochę czasu na poznanie innych potężnych i zaawansowanych funkcji Ghidra, takich jak automatyzacja zadań inżynierii wstecznej za pomocą skryptów Ghidra i nieskończonych możliwości, na jakie pozwala system wtyczek.

Analiza poprawek

https://chacker.pl/

Narzędzie ujawniło różnice pomiędzy programami korzystającymi z funkcji ViewStudentGrades, jak pokazano poniżej:

Szybka kontrola dekompilacji funkcji obu wersji ujawnia, że podczas analizowania danych wejściowych użytkownika za pomocą funkcji atoi nie sprawdzono granic indeksu tablicy studentów. Oznacza to, że możemy wybrać dowolny dodatni lub ujemny numer indeksu, co pozwala nam traktować dowolny adres z wyrównaniem do 32 bajtów jako strukturę danych Ucznia. Opcja „Zmień oceny” pozwala na zmianę ocen uczniów, jeśli ustawione zostanie prawidłowe hasło. Okazuje się, że tę podatność możemy wykorzystać na swoją korzyść. Jeśli przejdziemy do Windows | Tabela symboli i wyszukaj admin_password symbol, zauważymy, że znajduje się on pod offsetem 0x001040a0. To jest dokładnie 64 bajty przed bazowym adresem tablicy uczniów (0x001040e0). Co by się stało, gdybyśmy skorzystali z opcji „Wyświetl oceny” i wybrali ucznia o numerze -2?

Jak widać, traktowanie pamięci admin_password jako zmiennej typu struktury Studenta zakończy się tym, że hasło będzie znajdować się dokładnie w pozycji „nazwa” struktury. Znaleźliśmy prymityw wykorzystywania odczytu i możemy teraz odczytać 24 bajty z dowolnej wartości pamięci wyrównanej do 32 bajtów. Ale to nie wszystko. Zwróć uwagę, jak kontrolujemy wartość indeksu i wartość składową ocen dla struktury uczniów w funkcji ChangeStudentGrades. Oznacza to, że możemy zapisać 4 bajty w dowolnym miejscu i 28 bajtów z dowolnego 32-bajtowego adresu pamięci.

Organizować coś

https://chacker.pl/

Ghidra udostępnia funkcję różnicowania kodów, która umożliwia porównanie różnic pomiędzy dwoma plikami binarnymi o tym samym układzie adresów i pozycji. Jest to przydatne w przypadku porównań binarnych z korelacją przesunięcia jeden do jednego, ale nie koreluje kodu pod względem kontekstu i przepływu wykonania. Na szczęście możemy rozszerzyć możliwości Ghidry, instalując wtyczki takie jak BinDiffHelper1 dla doskonałego narzędzia BinDiff. Aby to zrobić, wykonaj następujące kroki:

1. Zainstaluj narzędzie do automatyzacji kompilacji Gradle w wersji 6.5, uruchamiając następujące polecenia:

  1. Sklonuj i skompiluj wtyczkę BinExport2 z oficjalnego repozytorium. Ta wtyczka automatyzuje proces generowania bazy danych różnic BinExport:

Proces kompilacji może zająć kilka minut. Po zakończeniu należy utworzyć plik ZIP wtyczki BinExport w folderze ~/binexport/java/BinExport.

3. W oknie projektu Ghidry przejdź do Plik | Menu Zainstaluj rozszerzenie i kliknij ikonę znaku plus (+), aby dodać plik ZIP wtyczki do folderu ~/binexport/java/BinExport/dist, jak pokazano poniżej:

  1. Kliknij OK i zrestartuj Ghidrę, aby zmiany wtyczki zostały zastosowane.
  2. W oknie terminala pobierz i zainstaluj BinDiff v6 z oficjalnej strony:

Instalacja pakietu .deb wyświetli monit o podanie ścieżki IDA Pro. Pozostaw to pole puste, aby określić, że jesteśmy zainteresowani eksperymentalnymi rozszerzeniami Ghidra.

  1. Sklonuj i skompiluj wtyczkę BinDiffHelper z oficjalnego repozytorium:

7. W oknie projektu Ghidry przejdź do Plik | Zainstaluj menu rozszerzenia i dodaj plik Zip wtyczki do folderu ~/BinDiffHelper/dist/, jak pokazano poniżej.

  1. Uruchom ponownie Ghidrę, aby zastosować zmiany wtyczek.

Różnicowanie binarne

Teraz, gdy wtyczki zostały zainstalowane, kontynuujmy laboratorium, badając proces różnicowania plików binarnych:

9. Otwórz plik programu z poprawką uczniów. Zostaniesz poproszony o wykrycie nowych rozszerzeń:

Wybierz Tak, aby skonfigurować nowe wtyczki, a w kolejnym oknie kliknij OK:

  1. Uruchom Auto-Analizę i zapisz projekt.
  2. Powtórz kroki 9 i 10, ale tym razem z plikiem programu uczniów.
  3. Otwórz okno wtyczki Window/BinDiffHelper. Kliknij ikonę konfiguracji, aby ustawić poprawną ścieżkę binarną BinDiff 6 (/opt/bindiff/bin/bindiff), jak pokazano poniżej:

  1. Otwórz poprawiony przez uczniów program, klikając ikonę „Otwórz plik do porównania”. Powinieneś teraz zobaczyć wyniki podobieństwa i pewności dla każdej funkcji. Przejdź do funkcji ViewStudentGrades na dole, zaznacz pole wyboru importu i kliknij ikonę „Importuj wybraną funkcję”.

Binarna analiza różnic i poprawek

https://chacker.pl/

Po wykryciu i zgłoszeniu luk w zabezpieczeniach dostawcy przystępują do łatania swoich produktów i publikowania aktualizacji. Czasami dziennik zmian aktualizacji jest ograniczony szczegółowo w odniesieniu do załatanego błędu i aby zrozumieć zmiany i opracować exploity, konieczne staje się różnicowanie binarne. W tym laboratorium przeprowadzisz Cię przez proces odkrywania luki w narzędziu do zarządzania ocenami uczniów za pomocą różnicowania binarnego. Luka powinna być łatwa do wykrycia po prostu poprzez sprawdzenie kodu, ale ponownie będziemy udawać, że mamy dostęp tylko do plików binarnych, aby lepiej symulować scenariusz ze świata rzeczywistego.

Poprawa czytelności dzięki adnotacjom

https://chacker.pl/

Dla początkujących bardzo frustrującą i uciążliwą częścią inżynierii odwrotnej jest brak jasnego pojęcia, co oznaczają różne parametry i wartości danych. Ten brak kontekstu w zakresie różnych ustawień wartości rejestrów, przesunięć pamięci, odwołań do wskaźników i argumentów funkcji można przezwyciężyć poprzez właściwe użycie typów danych. Jak być może już wiesz, środowisko wykonawcze architektur komputerów jest niezależne od typów danych, które są istotne dla twórcy oprogramowania w czasie programowania i są wykorzystywane przez kompilator do prawidłowego przypisywania alokacji pamięci, przesunięć elementów struktury, indeksów tablic i innych ustawień w czasie kompilacji. Jeśli porównamy oryginalny kod z domyślnym widokiem dekompilacji dla funkcji LoadStudents, pokazanym poniżej, funkcja dekompilacji może nie okazać się tak przydatna, jak to tylko możliwe. Będziemy kontynuować poprawę czytelności programu studentów poprzez przypisanie typów danych do wartości w funkcji main.

Kod źródłowy przedstawia pętlę for zwiększającą zmienną licznika o 1 w każdej iteracji, która jest używana jako indeks dla zmiennej globalnej studentów, która jest tablicą zdefiniowanego przez nas typu Student. Przed adnotacją zdekompilowana reprezentacja odpowiedniego kodu asemblera w języku C pokaże zmienną licznika indeksu pomnożoną przez 0x20 (co jest rozmiarem danych Ucznia). Ponadto, biorąc pod uwagę, że dekompilator nadal nie jest świadomy typów danych dla każdej zmiennej, każde odwołanie do wartości zostanie poddane rzutowaniu typu, co jeszcze bardziej komplikuje czytelność kodu źródłowego. Możemy łatwo poprawić czytelność, ustawiając zmienne z poprawnymi adnotacjami typu danych i zmieniając nazwy zmiennych. Załóżmy, że nie mamy kodu źródłowego, abyśmy mogli doświadczyć najczęstszego scenariusza, jakiego można się spodziewać podczas prawdziwej inżynierii odwrotnej. Wykonaj następujące kroki:

  1. Przejdź do funkcji LoadStudents, wyszukując ją w widoku drzewa symboli, a następnie przejdź do okna Dekompilacja, aby wprowadzić adnotacje. Zmienimy nazwy zmiennych, typy danych i sygnatury funkcji w oparciu o operacje i funkcje, z którymi są powiązane w kodzie.
  2. Bazując na sposobie wyłuskiwania zmiennej i ustawianiu jej z przesunięciem wynoszącym 32 (0x20) pomnożonym przez zmienną indeksującą liczbę, wiemy, że jest to tablica. Ustawione są niektóre wartości w pobliżu przesunięcia, jak pokazano poniżej:

  • W linii 25. wartość całkowita jest dereferowana w odległości 24 (0x18) bajtów od przesunięcia (liczba * 32), więc można bezpiecznie założyć, że jest to wskaźnik do wartości całkowitej (int *). Nazwa powinna brzmieć „id”, ponieważ jest ustawiana ze zmiennej indeksowej licznika.
  • W linii 26. funkcja strncpy kopiuje ciąg znaków odpowiadający nazwisku ucznia odczytanemu z pliku CSV do przesunięcia bazowego (liczba * 32), więc jest to tablica znaków o nieznanym rozmiarze. Możemy jednak zgadnąć, że są to 24 bajty, ponieważ to tam znajduje się przesunięcie poprzedniej wartości i nie powinno ono nadpisywać elementu własnej struktury (char [24]). Nazwiemy ten element struktury „imięm”.
  • W linii 28. iVar1 jest ustawiany za pomocą funkcji atoi wywoływanej na podstawie wartości ocen w pliku CSV, która zwraca liczbę całkowitą, a następnie ustawiany jest z przesunięciem 0x1c od przesunięcia bazowego (liczba * 32). Załóżmy zatem, że jest to również liczba całkowita. Jest to członek „klasy” struktury ucznia.
  1. Teraz możemy zdefiniować własny typ danych struktury Studenta dla elementów tablicy studentów. Przejdź do okna Menedżer typów danych, kliknij prawym przyciskiem myszy typy danych programu „studenckiego”, wybierz podmenu Nowy i kliknij element „struktura”.
  2. Nazwij strukturę Student i ustaw jej rozmiar na 32 bajty.
  3. Przejdź do pierwszego wiersza w tabeli (offset 0), kliknij dwukrotnie DataType

pole i wpisz char[24]. Następnie kliknij dwukrotnie pole Nazwa i wpisz nazwę.

  1. W drugim wierszu (przesunięcie 24) ustaw pole DataType na int i ustaw pole Name na id.
  2. Powtórz to samo w trzecim wierszu (przesunięcie 28) i ustaw pole Nazwa na oceny.
  3. Jeśli okno Edytora struktury wygląda jak to na rysunku , kliknij ikonę Zapisz i zamknij okno. Konstrukcja jest już gotowa do użycia.

  1. Umieść kursor nad dowolną instancją zmiennej globalnej studentów i naciśnij CTRL-L, aby zmienić jej typ danych z niezdefiniowany[1024] na Student[32] (nasza struktura ma rozmiar 32, a 1024 podzielone przez 32 równa się 32) .
  2. Zmień pozostałe zmienne i funkcje w oparciu o ich kontekst. Na przykład zmienna local_20 jest ustawiana w wyniku funkcji fopen; dlatego powinien być ustawiony jako typ danych FILE *, a jego nazwa powinna wyglądać mniej więcej tak: fh.
  3. Naciśnij CTRL-L, aby zmienić jego typ na PLIK *.
  4. Wybierz nazwę zmiennej i naciśnij L lub kliknij prawym przyciskiem myszy i wybierz

Zmień nazwę zmiennej, aby zmienić nazwę zmiennej na fh.

C. Aby uniknąć rzutowania wywołania na fopen, kliknij funkcję prawym przyciskiem myszy, kliknij opcję Edytuj sygnaturę funkcji i, jeśli to konieczne, zmień sygnaturę funkcji, aby ustawić poprawny argument wywołania i zwrócić typy danych.

Jeśli nie masz pewności co do sygnatury standardowych funkcji, skorzystaj z podręcznika programisty, uruchamiając man 3 fopen w oknie terminala. Po zakończeniu tego procesu powinieneś zauważyć, że czytelność zarówno zdekompilowanego, jak i wyszczególniającego zdezasemblowany kod została znacznie poprawiona, jak pokazano poniżej. Ponadto każda inna funkcja odwołująca się do zmiennych, funkcji i typów danych z adnotacjami odniesie korzyści z tego wysiłku