Dlaczego nie możemy zrozumieć zawartości pliku binarnego po skompilowaniu?


11

O ile wiem, każdy program składa się z zestawu instrukcji procesora z pewnymi specyficznymi zmiennymi danych (float, int, char ...) do pracy na rejestrach procesora .

Pierwszą rzeczą, o której pomyślałem (dawno temu) jest to, że jeśli wiesz, że wartość ASCII %¨#$¨#(tylko przypadkowy przykład) może być interpretowana jako adres rejestru wskaźnika stosu (przykładowo) x86 edytor. Jeśli jest to prawda, za każdym razem, gdy podczas czytania zawartości pliku binarnego znajduje się ta „nieczytelna” wartość, można zinterpretować, że rejestr wskaźników stosu jest używany do zarządzania pewnymi zmiennymi danych.

Niestety tak się nie dzieje. Poniżej znajduje się przykład treści ping.exeprogramu z systemu Windows otwartego za pomocą notepad.exe:

Ping.exe widziany w MS Notepad

Jest to plik binarny, a jego dane są dla nas, ludzi, niezrozumiałe (jest zrozumiałe dla maszyn). Dla nikogo nie ma sensu, nawet jeśli znają kod asemblera (najniższy poziom języka maszynowego).

Więc jeśli wszystko zrozumiałem poprawnie, czy ktoś mógłby to wyjaśnić

  1. Dlaczego kod binarny nie może powrócić do kodu asemblera, skoro są one w gruncie rzeczy tym samym?
  2. Jeśli można zrozumieć kod asemblera, dlaczego skompilowany plik binarny wynikający z tego kodu nie jest już „czytelny”?

12
Możesz, potrzebujesz dezasemblera .
David Schwartz

Więc mogę zdemontować dowolny plik .exe ??? Po prostu wiedziałem, że działa z kodem zarządzanym ...
Diogo,

13
Możesz zdemontować dowolny plik wykonywalny. To, czy potrafisz zrozumieć zdemontowane dane wyjściowe, to inna historia.
David Schwartz

5
Kompilacja lub zestaw usuwa wiele istotnych dla człowieka informacji, takich jak nazwy zmiennych, etykiety gałęzi itp. Dissasembly pobiera strumień instrukcji, ale wciąż masz wiele do zrobienia.
mpez0

1
Również zaciemnianie kodu może utrudniać demontaż.
matematyka

Odpowiedzi:


13

Po pierwsze, rejestry nie mają adresów. Każda instrukcja w dowolnym języku asemblera tłumaczy się na kod operacyjny. Kody w x86 mogą mieć jeden, dwa, trzy lub nawet więcej bajtów (w niektórych innych procesorach mają one „stałą szerokość”). Zwykle kod operacyjny wskazuje instrukcję, tryb adresowania i rejestry. „Tryb adresowania” określa, czy procesor potrzebuje więcej niż kod operacji, tzn. Tryb „natychmiastowego” oznacza, że ​​dodatkowe instrukcje znajdują się zaraz po instrukcji dla tej instrukcji (lub „bezpośrednio po niej”) - tryby adresowania „bezwzględnego” oznaczają, że adres pamięci jest zgodny z instrukcją i jest używany przez tę instrukcję.

Możesz znaleźć kod operacji czegoś podobnego MOV AL,SPlub podobnego, a następnie wyszukać. x86 ma wiele instrukcji, które działają na wskaźniku stosu.

Ale proszę, proszę zamknąć za pomocą Notatnika i użyć edytora hex zamiast. Poleciłbym HxD, chociaż jest wiele innych.

I @David Schwartz ma rację. Dezasembler będzie iterował plik i tłumaczy kody z powrotem na czytelny tekst. To, co chcesz zrobić, jest całkowicie możliwe.

Jednak trzeba wiedzieć, gdzie w pliku instrukcje zacząć bo jeśli zaczniesz na niewłaściwy adres, niektóre dane, które powinny być „argumenty” na rozkazy (takich jak instrukcje, które mają adresu dla argumentu lub „argument”) mogą zostać źle zinterpretowanym jako opcodes. Świadomość tego wymaga znajomości formatu, w jakim znajduje się plik wykonywalny, którym w systemie Windows jest „Przenośny plik wykonywalny” lub PE (i często jest to ELF dla systemów Linux). Jestem pewien, że są deasemblery, które rozumieją WF itp., Ale nie znam żadnego odręcznego.


1
IDA jest jednym z najczęstszych dezintegratorów PE. Działa również z plikami Linux i Mac. Wersja 5.0 jest nadal dostępna jako freeware
Scott Chamberlain

1
> jeśli zaczniesz od niewłaściwego adresu,… może zostać źle zinterpretowany. Dlatego wszystkie wystąpienia %¨#$¨#niekoniecznie będą odwołaniem do wskaźnika stosu; może to być tylko środek dwóch różnych poleceń : _3p%¨#i $¨#b5F( _3p   %¨#$¨#   b5F).
Synetech

12

Więc jeśli wszystko zrozumiałem poprawnie

Nie do końca.

Jest to plik binarny, a jego dane są dla nas, ludzi, niezrozumiałe

Zazwyczaj plik binarny jest niezrozumiały dla człowieka i komputera, szczególnie gdy jego cel jest nieznany. Zauważ, że nie wszystkie pliki binarne są plikami wykonywalnymi. Wiele plików binarnych to pliki danych, które nie zawierają żadnych instrukcji maszynowych. Dlatego podczas nazywania plików (w niektórych systemach operacyjnych) używane są rozszerzenia plików. The. com przedłużenie był używany przez CP / M dla oznaczenia plik wykonywalny. The. rozszerzenie exe zostało dodane przez MS-DOS w celu oznaczenia innego formatu pliku wykonywalnego. * Nixy używają atrybutu execute, aby wskazać, które pliki można wykonać, chociaż może to być zarówno skrypt, jak i kod.

Jak już wspomniano inni, pliki binarne zawierające liczby powinny być przeglądane przez program zrzutu heksadecymalnego lub edytor heksadecymalny, a nie przez przeglądarkę tekstową.

istnieje przykład zawartości programu ping.exe

Ten plik jest programem relokowalnym i nie wszystkie dane w tym pliku reprezentują kod maszynowy. Istnieją informacje na temat programu, takie jak biblioteki dynamiczne, których potrzebuje, które procedury muszą być połączone, wymagania dotyczące stosu, programu i pamięci danych oraz punkt wejścia programu. Operandy adresowe w pliku mogą być względnymi wartościami, które należy obliczyć do wartości bezwzględnych lub referencjami, które należy rozwiązać.

„Plik programu”, o którym prawdopodobnie myślisz, nazywa się plikiem obrazu binarnego lub zrzutem pamięci programu. Taki plik zawierałby tylko kod maszynowy i dane, a wszystkie odwołania do adresów były odpowiednio ustawione do wykonania.

nawet jeśli znają kod asemblera (najniższy poziom języka maszynowego).

Język asemblera to nie to samo co język maszynowy . Typowy (aby wykluczyć komputery wysokiego poziomu) procesor przyjmuje kod maszynowy jako dane wejściowe, jedna instrukcja na raz. Argumentami są albo rejestry, albo numeryczne adresy pamięci. Język asemblera jest językiem wyższego poziomu, który może używać symbolicznych etykiet dla lokalizacji instrukcji i zmiennych, a także zastępować numeryczne kody operacyjne mnemonikami. Program w asemblerze musi zostać przekonwertowany na język / kod maszynowy, zanim będzie mógł zostać faktycznie wykonany (zazwyczaj za pomocą narzędzi zwanych asemblerem, konsolidatorem i modułem ładującym).

Operację odwrotną, deasemblację, można wykonać na plikach programu z pewnym sukcesem i utratą informacji symbolicznych. Demontaż zrzutu pamięci lub pliku obrazu programu wymaga więcej prób i błędów, ponieważ lokalizacje kodu i danych muszą być identyfikowane ręcznie.

BTW są osoby, które potrafią czytać i kodować (numeryczny) kod maszynowy. Oczywiście jest to o wiele łatwiejsze na 8-bitowym procesorze lub mikrokontrolerze niż na 32-bitowym procesorze CISC z tuzinem trybów adresów pamięci.


3

Nie widać prawidłowego, zamierzonego kodowania pliku binarnego za pomocą Notatnika. Zapoznaj się z tym do wykorzystania w przyszłości. Większość programów do edycji tekstu nie analizuje formatów kodowania binarnego i oczekuje się, że będą one analizować formatowanie znaków ASCII.

Tak więc otwarcie pliku binarnego w edytorze tekstowym da równoważne znaki ASCII, które nie mają żadnego znaczenia w oryginalnym formacie danych binarnych analizowanym przez edytor tekstowy. Jak wspomniano, edytory szesnastkowe i niektóre mają funkcje binarne, aby wyświetlić zawartość w czystym formacie binarnym.

Masz rację, że zawartości pliku binarnego nie można zrozumieć. Choć będą one trudne, a we współczesnych architekturach komputerowych niezwykle trudne jest ręczne zdemontowanie z samego pliku binarnego na odpowiednie instrukcje rozpoznawane przez CPU do wykonania (lub emulowanego / wirtualnego procesora) itp., Można to zrobić.

Jak myślisz, jak są programowane emulatory? Deweloper musiałby znać kody, aby móc zaprogramować fikcyjny system tak, aby rozpoznawał i zachowywał się tak jak prawdziwy sprzęt. Dokumentacje wyjaśniają wiele architektur procesorów, a nawet GPU je mają (choć bardziej tajne).

Inną rzeczą wartą odnotowania jest to, że na najniższym poziomie, chociaż korelacyjne, „dane binarne” nie są tak naprawdę wiązką zer i jedynek, ale wysokimi i niskimi napięciami wzmacnianymi / przełączanymi przez obwód elektryczny jako prąd.

Binarny zwykle ma przy tym 1: 1, więc warto w tym celu użyć systemu liczbowego.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.