haker.info  — Etyczny hacking_
Spreading knowledge like a virus.

 Bajt zabójca (ang. rogue byte) ÔÇö metoda przeciw deasemblacji

   Dawid Farbaniec    650 s┼é├│w

1. Słowem wstępu

arz─Ö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─Ö.

2. 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.

3. 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.

4. Zakończenie

Dzi─Ökuj─Ö za po┼Ťwi─Öcony czas na przeczytanie tego wpisu.

Dawid Farbaniec


Tagi:  reverse-engineering  masm64  security 

Komentarze czytaj─ůcych

majster napisał:

Ciekawy wpis. Mo┼╝liwym jest zastosowanie takiego bajtu zab├│jcy w skompilowanym kodzie c++, deasembluj─ůc go? I na ile jest to skuteczne przeciw do┼Ťwiadczonemu crackerowi / hackerowi?

 ponad 9 miesi─Öcy temu (10 sierpnia 2019 godz. 23:02)
Dawid (haker.info) napisa┼é:

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). My┼Ťl─Ö, ┼╝e mo┼╝na zastosowa─ç pseudo-instrukcj─Ö _emit, kt├│ra odpowiada dyrektywie db z Asemblera MASM, czyli wstawia w okre┼Ťlone miejsce bajt o podanej warto┼Ťci.

Inny spos├│b po┼é─ůczenia Asemblera MASM z Visual C++ to utworzenie w projekcie Visual C++ procedur w j─Özyku Asembler, kt├│re mo┼╝na wywo┼éywa─ç w kodzie C++ i rogue byte mo┼╝na wstawi─ç w tych procedurach.

W przypadku innych kompilator├│w C++. Je┼Ťli mo┼╝na zrobi─ç wstawk─Ö w Asemblerze (ang. inline assembly) w kodzie C++ to i raczej mo┼╝liwe jest wstawienie opisywanego w artykule ÔÇ×bajtu zab├│jcyÔÇŁ.

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.

 ponad 9 miesi─Öcy temu (11 sierpnia 2019 godz. 03:52)


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. Korzystaj─ůc z zasob├│w witryny haker.info o┼Ťwiadczasz, ┼╝e akceptujesz powy┼╝sze warunki oraz polityk─Ö prywatno┼Ťci.