Ta witryna korzysta z plików cookies. Korzystając z witryny akceptujesz: polityka prywatności.   [×]
Online: 0x09 (9)
haker.iиfø — Etyczny hacking _
Spreading knowledge like a virus.

Bajt zabójca — metoda przeciw deasemblacji

🕰 ✒️ Dawid Farbaniec 📄 650 słów

0x01. Słowem wstępu

Narzędzia typu deasembler (ang. disassembler) to jedne z podstawowych programów, które są używane w inżynierii odwrotnej kodu (RCE). Pozwalają one uzyskać kod w języku Asembler z analizowanego pliku wykonywalnego *.exe. Dzięki tego typu narzędziom nie ma potrzeby pracy z kodem maszynowym, który jest praktycznie nieczytelny dla człowieka. W tym wpisie zaprezentowano prostą metodę, która pozwala oszukać deasemblery, a w połączeniu z dodatkowymi technikami (Kod samo-modyfikujący się i inne) może nieco utrudnić pracę crackerom łamiącym zabezpieczenia oprogramowania. Nawet jeśli nie zabezpieczasz software'u, to zapraszam do lektury, gdyż kto wie czy kiedyś pod debuggerem nie spotkasz pliku zawierającego tę metodę.

0x02. Teoria

Programując aplikacje np. w Visual C++ pisze się kod wyższego poziomu abstrakcji. Następnie kod źródłowy jest tłumaczony na język Asembler i dalej na kod maszynowy przez kompilator, czyli program budujący (rysunek 2.1). W prostych słowach: Plik wykonywalny (PE/PE32+) oprócz dodatkowych struktur (nagłówka itp.) zawiera kod maszynowy aplikacji.

Jeśli jesteś zainteresowany sposobem kodowania instrukcji (zamianą kodu Asemblera na kod maszynowy) dla architektury x64 odsyłam do poniższych dokumentów:

Dla procesorów Intel 64:
» Intel ® 64 and IA-32 Architectures Software Developer's Manual
   » Volume 2: Instruction Set Reference, A-Z
     » Chapter 2: Instruction Format

Dla procesorów AMD64:
» AMD64 Architecture Programmer's Manual
   » Volume 3: General-Purpose and System Instructions
     » Chapter 1: Instruction Encoding

Proces kompilacji (budowania) programu
Rysunek 2.1. Proces kompilacji (budowania) programu — schemat ogólny

Natomiast zadaniem deasemblera (ang. disassembler) jest proces odwrotny. Narzędzia tego typu starają się odtworzyć kod w języku Asembler z podanego im pliku wykonywalnego (zawierającego kod maszynowy). Spotkałem się także z dekompilatorami, które z kodu maszynowego odtwarzały pseudokod podobny do języka C (np. REC Decompiler). Celowo tutaj został użyty termin dekompilator, gdyż tworzy on kod o wyższym poziomie abstrakcji niż deasembler.

0x03. Prezentacja techniki Rogue Byte (z ang. bajt zabójca)

Technika Rogue byte korzysta z możliwości umieszczania bajtów o określonej wartości w kodzie programu. Przykład będzie w Asemblerze MASM64 (ML64.EXE), który jest dołączony do środowiska Microsoft Visual Studio.

Aby zrozumieć działanie tej metody należy pomyśleć jak działa deasembler. W uproszczeniu pobiera on kolejne bajty kodu maszynowego i zgodnie z regułami kodowania instrukcji procesora zamienia je na określone rozkazy.

Jeśli wewnątrz ciągu instrukcji programu wstawi się bajt o określonej wartości, to większość (a na pewno wiele) deasemblerów potraktuje go jako część kodu maszynowego i błędnie zinterpretuje rozkazy w pobliżu tego bajtu.

Spójrzmy na poniższy kod aplikacji w Asemblerze MASM64:

Listing 3.1. Przykład metody Rogue byte przeciw deasemblerom (MASM64)
extrn ExitProcess : proc extrn MessageBoxA : proc .data szText db "http://haker.info/", 0 .code Main proc jmp @f db 0E8h ;bajt zabójca     @@: sub rsp, 28h xor r9, r9 lea r8, szText lea rdx, szText xor rcx, rcx jmp @f db 0E9h ;bajt zabójca     @@: call MessageBoxA add rsp, 28h sub rsp, 8h xor rcx, rcx call ExitProcess Main endp end

Na listingu 3.1 znajduje się program, który wyświetla okno informacyjne (komunikat) za pomocą funkcji MessageBox, a następnie kończy swoje działanie (funkcja ExitProcess).

Należy zauważyć, że pomiędzy instrukcje zostały wstawione dwa fragmenty kodu:

jmp @f db 0E8h ;bajt zabójca @@:

Gdy deasembler (często wbudowany w debugger) napotka na bajt 0E8h uzna, że jest to początek rozkazu w kodzie maszynowym. Dokładnie to rozkazu CALL (wywołanie procedury). Od tego momentu kod będzie błędnie interpretowany co spowoduje jego zaciemnienie (ang. obfuscation). Bajt wstawiony w drugie miejsce ma kod operacyjny 0E9h, czyli rozkaz JMP (skok bezwarunkowy). Za tym miejscem również instrukcje zostaną błędnie rozkodowane.

Widok kodu z listingu 3.1 w debuggerze x64dbg przedstawiono na rysunku 3.1.

Metoda Rogue byte przeciw deasemblacji
Rysunek 3.1. Prezentacja działania metody Rogue byte — porównanie kodu

Jak widać na rysunku 3.1 oryginalny kod programu po deasemblacji nie jest poprawny. Szkodliwy bajt wstawiony między instrukcje częściowo zaburzył ich tłumaczenie m.in. wywołanie funkcji MessageBox całkowicie zniknęło, a dookoła pojawiło się pełno dziwnych instrukcji.

Dla całkowitej jasności wspomnę, że kod z zastosowaną metodą Rogue byte wykonuje się poprawnie.
Dzieje się tak dlatego, że bajt zabójca jest przeskakiwany instrukcją skoku JMP.

0x04. Zakończenie

Dziękuję za poświęcony czas na przeczytanie tego wpisu.

Wykaz literatury (bibliografia)

[1] x64dbg, 2019 – https://x64dbg.com/ [dostęp: 30.07.2019 r.]
[2] REC Decompiler, 1997 – http://www.backerstreet.com/rec/rec.htm [dostęp: 30.07.2019 r.]
[3] Microsoft Corporation, 2019 – https://docs.microsoft.com/pl-pl/cpp/assembler/masm/masm-for-x64-ml64-exe [dostęp: 30.07.2019 r.]


Komentarze czytelników

💬 majster | 🕰️ 10 sierpnia 2019 godz. 23:02:12 | 🌎 IP address logged
Ciekawy wpis. Czy możliwe jest zastosowanie takiego bajtu zabójcy w skompilowanym kodzie c++ deasemblując go? I na ile jest to skuteczne przeciw doświadczonemu crackerowi / hackerowi?
💬 Odpowiedź od Dawid // haker.iиfø | 🕰️ 10 sierpnia 2019 godz. 23:02:12
Dziękuję za komentarz i zainteresowanie wpisem. :) Jeśli chodzi o Visual C++ z którym czasem pracuję, to kompilator dla architektury 64-bitowej (x64) nie wspiera tzw. inline assembly, czyli wstawek w języku Asembler w kodzie C++ (wprowadzili za to funkcje wewnętrzne nazywane intrinsics).  A w skompilowanym kodzie (np. pliku exe), to należy zmodyfikować rozkazy np. za pomocą debuggera z deasemblerem (np. x64dbg) czy też poszczególne bajty w hex edytorze. Ciężko powiedzieć na ile ta metoda jest skuteczna. Na pewno nie będzie skuteczna w prostej formie i zastosowana samodzielnie bez innych zabezpieczeń. Ja traktowałbym technikę „bajtu zabójcy” jako dodatkowe zabezpieczenie.

💬 Komentarze [0]

jas napisał komentarz do ↴
🔳 Dekodowanie kodu Aztec 2D z dowodu rejestracyjnego
[🕰 / 🌎 IP address logged ]
jas napisał komentarz do ↴
🔳 Mowa szesnastkowa (ang. hex speech)
[🕰 / 🌎 IP address logged ]
Iceman napisał komentarz do ↴
🔳 Mowa szesnastkowa (ang. hex speech)
[🕰 / 🌎 IP address logged ]

🎲 Losowe wpisy

Dekodowanie kodu Aztec 2D z dowodu rejestracyjnego (2290 słów) Przeczytaj teraz »
Kod relokowalny/wstrzykiwalny (x64) (3020 słów) Przeczytaj teraz »
Bajt zabójca — metoda przeciw deasemblacji (650 słów) Przeczytaj teraz »

Maskotka haker.info

Postać Mr. At nawiązuje do gier z gatunku roguelike/ASCII RPG w których do wyświetlania grafiki korzysta się ze znaków tekstowych. Znak @ (at) w grach roguelike przeważnie oznacza postać bohatera.

Kontakt

mgr inż. Dawid Farbaniec  //  haker.iиfø

E-mail:
office@haker.info

Odwiedź mnie również na:

 

Wyrazy uznania: 📜 Credits page

Wszystkie treści umieszczone na tej witrynie są chronione prawem autorskim. Surowo zabronione jest kopiowanie i rozpowszechnianie zawartości tej witryny bez zgody autora. Wszelkie opublikowane tutaj treści (w tym kody źródłowe i inne) służą wyłącznie celom informacyjnym oraz edukacyjnym. Właściciele tej witryny nie ponoszą odpowiedzialności za ewentualne niezgodne z prawem wykorzystanie zasobów dostępnych w witrynie. Użytkownik tej witryny oświadcza, że z zamieszczonych tutaj danych korzysta na własną odpowiedzialność. Wszelkie znaki towarowe i nazwy zastrzeżone zostały użyte jedynie w celach informacyjnych i należą wyłącznie do ich prawnych właścicieli. Autor tej witryny w czasie tworzenia treści nie działa w imieniu firm, których technologie czy produkty opisuje — chyba, że jest to jasno oznaczone. Korzystając z zasobów witryny haker.info oświadczasz, że akceptujesz powyższe warunki oraz politykę prywatności.