Wyślij zapytanie Dołącz do Sii

Inżynieria odwrotna (ang. Reverse Engineering), czasami nazywana inżynierią wsteczną, to proces, w którym produkty są dekonstruowane w celu wyodrębnienia z nich informacji projektowych. Często inżynieria odwrotna polega na dekonstrukcji poszczególnych elementów większych produktów. Proces umożliwia określenie, w jaki sposób produkt został zaprojektowany, aby można było go odtworzyć.

Kilka słów o historii

Nazwa inżynierii odwrotnej wywodzi się z tego, że proces obejmuje przechodzenie „wstecz” przez oryginalny proces projektowania. Często wiedza na temat metod inżynierskich, które zostały wykorzystane do stworzenia produktu, jest ograniczona, dlatego wyzwaniem jest jej zdobycie.

Inżynieria odwrotna istnieje od samego początku, kiedy ludzie tworzyli rzeczy, takie jak koła, powozy czy infrastrukturę architektoniczną. Aby odtworzyć te obiekty, wykorzystywano prymitywną inżynierię wsteczną. Zdejmowano wymiary obiektów i odtwarzano je w całości albo częściowo je przebudowywano. Na przykład armia rzymska, która nie miała stałej marynarki wojenne, po I wojnie punickiej w roku 264 p.n.e. dokonała inżynierii wstecznej na wraku kartagińskiego pięciorzędowca. Niestety, jako początkujący cieśle, Rzymianie zbudowali kopie, które były cięższe niż statki kartagińskie, a więc wolniejsze i mniej zwrotne.

Techniki inżynierii odwrotnej znacznie ewoluowały od tych minionych epok. Chociaż inżynieria odwrotna mogła zacząć się od zastosowań wojskowych, jest teraz przydatna w wielu różnych dziedzinach, w tym w inżynierii komputerowej, inżynierii mechanicznej, projektowaniu, inżynierii elektronicznej, inżynierii oprogramowania, inżynierii chemicznej czy też biologii systemów.

Inżynieria odwrotna w produkcji

Dla producentów inżynieria odwrotna jest niezwykle ważnym procesem. Istnieje jej wiele powszechnych zastosowań w produkcji:

  • Jest często stosowana, gdy brakuje oryginalnej dokumentacji lub jeśli nie ma rysunków 2D lub 3D/modeli CAD. Inżynieria odwrotna jest szczególnie ważna, jeśli informacje projektowe części zależą od ludzkiej pamięci.
  • Firmy przeprowadzają inżynierię wsteczną części, gdy części zamienne od producenta oryginalnego sprzętu (OEM) nie są dostępne, ponieważ producent już ich nie tworzy lub też producent już nie istnieje.
  • Jest również wykorzystywana do optymalizacji złożeń i ulepszania produktów o nowe funkcje.
  • Producenci stosują ją, aby ulepszyć części, które uległy awarii lub odtworzyć ręcznie wykonane części lub zespoły części.
  • Czasami jest po prostu wykorzystywana do budowania cyfrowego archiwum lub tworzenia wirtualnego środowiska do wykorzystania w przyszłości.

Korzyści inżynierii wstecznej w produkcji

Do zalet wykorzystania inżynierii odwrotnej należą:

  • Inżynieria wsteczna może zmniejszyć ryzyko związane ze starszymi produktami oraz wadami produktów. Dzięki niej można stworzyć części zamienne, a także zidentyfikować i pomóc w naprawie usterek w produktach.
  • Ponadto inżynieria odwrotna może przyspieszyć innowacje produktowe. Na przykład zespół inżynierów może badać projekty istniejących produktów i szukać sposobów na zwiększenie ich wydajności, uaktualnienie funkcji lub znalezienie sposobów na obniżenie kosztów produkcji.
  • Producenci wykorzystują ten proces, aby szybko produkować części, zamiast kupować komponenty od producenta OEM, który może mieć długi czas realizacji i wymagać wysokich kosztów.
  • Inżynieria odwrotna może być również kluczową strategią w planie proaktywnej konserwacji producenta. Dzięki inżynierii wstecznej krytycznych komponentów, zanim komponenty ulegną awarii, producent może magazynować części zamienne i skrócić nieplanowane przestoje.

Branże wykorzystujące inżynierię wsteczną

Producenci z wielu branż wykorzystują procesy inżynierii odwrotnej do optymalizacji produkcji, uzyskania przewagi konkurencyjnej i obniżenia kosztów. Najpopularniejsze branże, w których ma rację bytu:

  • Przemysł lotniczy – przeprowadzanie analizy aerodynamicznej, opracowanie planów utrzymania statków powietrznych, dodawanie/ulepszanie komponentów samolotu, produkcja narzędzi.
  • Przemysł samochodowy – studiowanie konkurencji, digitalizacja części starszych modeli pojazdów, zrozumienie problemów z komponentami pojazdu, produkcja części zamiennych.
  • Firmy narzędziowe – ulepszanie uchwytów, opraw, matryc, form, części do maszyn i narzędzi skrawających.
  • Dobra konsumpcyjne – szybkie tworzenie prototypów, testowanie i walidacja projektów koncepcyjnych, analiza produktów konkurencji, dokumentowanie i archiwizowanie różnych iteracji projektowych.
  • Ochrona sztuki i dziedzictwa – odtwarzanie dzieł sztuki do celów edukacyjnych, ochrona cyfrowa sztuk wizualnych, takich jak obrazy, rzeźby, starożytne artefakty archeologiczne i budynki historyczne, odrestaurowane artefaktów kultury.

Inżynieria odwrotna w oprogramowaniu

Inżynieria odwrotna oprogramowania (ang. Software reverse engineering) to proces polegający na analizie systemu oprogramowania, w całości lub w części, w celu wyodrębnienia informacji o projekcie i implementacji.

Inżynieria odwrotna oprogramowania jest szeroko stosowana w elektronice, a także w obszarach przemysłowych, komputerowych i wojskowych. Przykładowe zastosowania inżynierii odwrotnej:

  • Badanie formatów plików używanych do przechowywania danych.
  • Zwiększanie zgodności produktu z oprogramowaniem lub platformą stron trzecich.
  • Badanie nieudokumentowanych cech produktu komercyjnego.
  • Szukanie nieznanych wcześniej mechanik, które można wykorzystać w przyszłości.
  • Zwiększenie bezpieczeństwa: sprawdzenie czy oprogramowanie jest w stanie oprzeć się inżynierii wstecznej przeprowadzanej przez osoby trzecie, ochrona antywirusowa itp.
  • Uzupełnienie/zaktualizowanie dokumentacji produktu.
  • Usuwanie zabezpieczeń przed kopiowaniem, omijanie ograniczeń dostępu.
  • Badanie złośliwego oprogramowania, aby zrozumieć, jak działa w celu obrony przed nim oraz wykorzystania zdobytej wiedzy do aktualizacji baz wirusów i przygotowania obrony na wypadek przyszłych ataków złośliwego oprogramowania.
  • Dostosowywanie systemów wbudowanych przykładowo systemy zarządzania silnikiem.
  • Inżynieria odwrotna może być nieocenionym narzędziem do nauki korzystania z określonego języka programowania lub pracy z określonym typem aplikacji, początkujący mogą wykorzystać tę technikę do doskonalenia swoich umiejętności.

Przypadki wykorzystania inżynierii wstecznej

W zależności od tego jaki jest cel zastosowanie inżynierii odwrotnej w oprogramowaniu możemy wyróżnić dwa przypadki. W pierwszym przypadku kod źródłowy jest dostępny dla oprogramowania, ale wysokopoziomowe aspekty programu już nie, natomiast w drugim przypadku nie ma dostępu ani do kodu źródłowego oprogramowania ani do wysokopoziomowych aspektów programu.

Drugi przypadek jest często nazywany jako inżynieria odwrotnego kodu (ang. reverse code engineering) i jest on bardziej powszechny niż przypadek pierwszy.

Proces analizy działania danego programu można podzielić na następujące kroki (Ryc. 1):

  • Dezasemblacja – zamiana kodu binarnego na komendy assamblera.
  • Dekompilacja – zamiana komend assemblera na kod programu.
Ryc. 1 Uproszczony schemat procesu inżynierii odwrotnej
Ryc. 1 Uproszczony schemat procesu inżynierii odwrotnej

Znany przykład zastosowania inżynierii odwrotnej w oprogramowaniu

Firma Phoenix Technologies Ltd., która w połowie lat 80. chciała wyprodukować BIOS dla komputerów PC, będący kompatybilnym z firmowym BIOS-em IBM PC. Aby uchronić się przed zarzutami nielegalnego skopiowania BIOS-u IBM, firma Phoenix użyła inżynierii wstecznej, stosując podejście zwane „czystym pokojem” lub „chińską ścianą”.

Najpierw zespół inżynierów przestudiował BIOS IBM, około 8 KB kodu. Następnie opisał wszystko, co BIOS robił, tak dokładnie, jak to możliwe, bez używania lub odwoływania się do żadnego rzeczywistego kodu. Następnie Phoenix sprowadził drugi zespół programistów, którzy nie mieli do czynienia z BIOS-em IBM-u i nigdy nie widzieli jego kodu.

Pracując tylko na podstawie specyfikacji funkcjonalnych pierwszego zespołu, drugi zespół napisał nowy BIOS, który działał zgodnie ze specyfikacją. Powstały BIOS różnił się od kodu IBM, ale pod każdym względem działał identycznie. Stosując podejście czystego pokoju, nawet jeśli niektóre sekcje kodu były identyczne, nie doszło do naruszenia praw autorskich. Phoenix zaczął sprzedawać swój BIOS firmom, które wykorzystały go do stworzenia pierwszych komputerów PC kompatybilnych z IBM.

Narzędzia wykorzystywane przy inżynierii odwrotnej oprogramowania

Inżynierowie pracując nad inżynierią odwrotną oprogramowania wykorzystują między innymi:

  • Deasemblery – służą do zamiany kodów binarnych na kody asemblera. Są również wykorzystywane do wyodrębniania ciągów, funkcji (zarówno importowanych, jak i eksportowanych), bibliotek itp. Pomagają konwertować język maszynowy na format bardziej przyjazny dla użytkownika. Różne deasemblery są używane do różnych celów.
  • Debugery – rozszerzają funkcjonalność deasemblerów między innymi o monitorowanie rejestrów procesora, widok stosu, heksowe zrzuty programu. Programiści używają debuggerów do ustawiania punktów przerwania, a także do edycji kodów asemblera w czasie wykonywania.
  • Narzędzia do monitorowania systemu – śledzą operacje sieciowe, dostęp do danych, dostęp do plików systemowych i tym podobne. Niektóre narzędzia pokazują wykorzystanie przez program artefaktów systemu operacyjnego, takich jak muteksy, strumienie, zdarzenia itp.
  • Edytory szesnastkowe – pozwalają programistom przeglądać i edytować pliki binarne. Pomagają w manipulowaniu podstawowymi danymi binarnymi składającymi się na plik komputerowy. Ponieważ są używane do edycji plików binarnych, są czasami określane jako edytor binarny lub edytor plików binarnych.
  • Przeglądarka zasobów – to narzędzie pozwala programistom przeglądać i edytować zasoby osadzone w pliku EXE. Pozwalają na zmianę ikon, edycję menu, informacje o wersji, okno dialogowe itp. PE Explorer ułatwia tłumaczenie aplikacji, które nie posiadają kodów źródłowych. Wszystko co trzeba co zrobić, to zastąpić zasoby tekstowe ich przetłumaczonymi wersjami, a następnie zmienić rozmiar przycisków, formularzy itp.
  • Środowiska wirtualne – może być używane do analizy nieznanych/podejrzanych programów. Uruchomienie nieznanego programu w niekontrolowanym środowisku może spowodować nieodwracalne szkody, jeśli program uruchomi coś w tle. Korzystanie z wirtualnego środowiska jest koniecznością, gdy mamy do czynienia z nieznanym oprogramowaniem, abyśmy mogli bezpiecznie działać analizując go w odizolowanym środowisku.

Gotowe narzędzia

Istnieją gotowe narzędzia wspomagające proces inżynierii odwrotnej. Należą do nich:

  • IDA (The Interactive Dissambler) – najbardziej popularne narzędzie, podstawowa darmowa wersja wysposażona jest w deasembler oraz debugger, można dokupić dekompilator.
  • Binary ninja – wyposażony jest w deasembler, debugger oraz dekompilator, nie ma wersji darmowej tylko wersja demonstracyjna.
  • Ghidra – darmowe otwarte oprogramowanie, wyposażone w deasembler i dekompilator, oraz od niedawna w debugger.
  • Radare2 – oparty na licencji GNU, wyposażony w deasembler oraz debugger.
Ryc. 2 Logotypy (od lewej): IDA, Binary ninja, Ghidra, Radare2
Ryc. 2 Logotypy (od lewej): IDA, Binary ninja, Ghidra, Radare2

Hello world!

Pierwszym uruchamianym programem podczas nauki języka programowania jest zazwyczaj wyświetlenie napisu „hello, world”. Najprostszą modyfikację jaką można wprowadzić do tego klasycznego przykładu, jest zmiana wyświetlanego tekstu.

Modyfikując wyświetlany tekst, należy zwrócić szczególną uwagę na to, aby:

  • ciąg znaków zakończyć znakiem nowej linii,
  • nie przekroczyć liczby znaków, nie wiemy za co odpowiadają bajty znajdujące się za napisem.

Napis „hello, world” przedstawiony w zapisie szesnastkowym wygląda następująco:

Napis „hello, world” przedstawiony w zapisie szesnastkowym

W kodzie binarnym możemy znaleźć sekwencję znaków zawierającą napis „world” i zamienić ją na „Sii!” (Ryc. 2). W ten sposób otrzymamy nowy napis „hello, Sii!” (Ryc. 4).

Ryc. 3 Prosta modyfikacja „hello, world”
Ryc. 3 Prosta modyfikacja „hello, world”
Ryc. 4 Wyświetlanie „hello, world” przed i po modyfikacji
Ryc. 4 Wyświetlanie „hello, world” przed i po modyfikacji

Inżynieria odwrotna – legalna czy nielegalna?

Nie ma ogólnego prawa przeciwko inżynierii wstecznej. Oznacza to, że praktyka inżynierii wstecznej sama w sobie jest legalna. Jednakże stosowanie inżynierii odwrotnej może podlegać następującym prawom:

  • Prawo autorskie i prawo dozwolonego użytku.
  • Prawo tajemnicy handlowej.
  • Postanowienia wymienione w ustawie Digital Millennium Copyright Act (DMCA).
  • Prawo umów.
  • Ustawa o prywatności w komunikacji elektronicznej (ang. The Electronic Communications Privacy Act -ECPA).

Większość oprogramowania stanowi własność intelektualną firmy, która je stworzyła, tak więc jest chronione przez prawa autorskie. Korzystanie z dowolnej części kodu poddanego inżynierii wstecznej może stanowić naruszenie praw autorskich. Nawet jeśli programista w rzeczywistości nie używa kodu.

Wykorzystanie wniosków wyciągniętych z kodu poddanego inżynierii wstecznej może stanowić wykorzystanie chronionych tajemnic handlowych lub może zostać uznane za naruszenie umowy, na przykład umowy o zachowaniu poufności.

Ustawa DMCA wprowadza jeszcze większy zamęt, zakazując stosowania inżynierii wstecznej w celu obejścia „technologicznych środków ochronnych”. Chociaż często uważa się, że oznacza to ochronę zarządzania prawami cyfrowymi, wielu twierdzi, że równie łatwo może odnosić się do „technik, takich jak uwierzytelnianie, podpisywanie kodu, zaciemnianie kodu i szyfrowanie protokołu”.

Wreszcie, ECPA zabrania „przechwytywania komunikacji elektronicznej przepływającej przez sieć”. Może to obejmować pakiety sieciowe, więc jakakolwiek inżynieria wsteczna takich pakietów może stanowić naruszenie ECPA, chyba że uzyskano zgodę wszystkich odpowiednich stron.

Cracking

Obecnie na rynku oprogramowania praktycznie każda aplikacja ma zabezpieczenie, które nie pozwala na korzystanie ze wszystkich funkcji programu, jeśli nie jest się zarejestrowanym użytkownikiem. Cracking jest procesem usuwania zabezpieczeń programów i jest on zazwyczaj nielegalny. Proces ten nie jest bezpośrednio związany z inżynierią odwrotną, ale inżynieria odwrotna może być wykorzystana do zbadania części programu odpowiedzialnej za zabezpieczenia.

Przykładową metodą crackingu jest serial fishing, gdzie szukany jest właściwy numer seryjny, który jest zaszyty w kodzie, a następnie za jego pomocą dokonywana jest rejestracja produktu. Serial fishing jest metodą czystą złamania zabezpieczenia programu, nie ingeruje ona w strukturę programu. Ta metoda może również być nazywana jako cracking na żywo, ponieważ w tym przypadku właściwy numer seryjny znajdowany jest w czasie wykonywania programu.

Innym przykładem jest patching określany również jako dead cracking, będący metodą inwazyjną. Przykładowo może być wykorzystywana w przypadku pominięcia kodu sprawdzającego czy wersja próbna programu już się zakończyła. Jest miejsce w kodzie, gdzie porównywana jest liczba dni od kiedy używany jest program z jakąś stałą, przykładowo 30 dni. Jeżeli liczba dni użytkowania jest równa lub wyższa, wyświetlany jest komunikat i program jest zamykany. Można tutaj podmienić instrukcje tak, aby program wykonywał to samo niezależnie od warunku.

Sposoby ochrony przed inżynierią odwrotną w oprogramowaniu

W wielu przypadkach korzystne jest stworzenie oprogramowania odpornego na inżynierię odwrotną. Niestety nigdy nie da się całkowicie temu zapobiec. To, co jest możliwe, to utrudnianie i blokowanie procesu tak, aby trwał jak najdłużej i był trudny do przeprowadzenia, w rezultacie zniechęcając osoby przeprowadzające inżynierię wsteczną.

To, czy ktoś ostatecznie odniesie sukces, zależy od kilku czynników, takich jak ich zdolności i motywacja. Skuteczność technik utrudniających inżynierię odwrotną zależy również od tego, jaką cenę jesteśmy w stanie za nie zapłacić.

Metody ochrony

Każde podejście wiąże się z pewnym kosztem. Czasami jest to użycie procesora, czasami rozmiar kodu, a czasami ma to wpływ na niezawodność i odporność. Istnieje kilka podejść, każde z własnym zestawem zalet i wad. Aplikacje, które mają na celu zwalczanie atakujących, zazwyczaj wykorzystują kombinację więcej niż jednego podejścia. Należą do nich:

  • Eliminowanie informacji symbolicznych ­– pierwszym i najbardziej oczywistym podejściem jest wyeliminowanie z programu wszelkich oczywistych informacji tekstowych. W zwykłym skompilowanym programie nieopartym na kodzie bajtowym, oznacza to po prostu usunięcie wszystkich informacji symbolicznych z pliku wykonywalnego programu. W programach opartych na kodzie bajtowym pliki wykonywalne często zawierają duże ilości wewnętrznych informacji symbolicznych, takich jak nazwy klas, nazwy członków klas i nazwy utworzonych obiektów globalnych. Nazwy wszystkich symboli powinny być zamienione na bezsensowne sekwencje znaków.
  • Zaciemnianie programu (ang. obfuscating) – to ogólna nazwa dla wielu technik, które mają na celu zmniejszenie podatności programu na wszelkiego rodzaju analizy statyczne. Osiąga się to poprzez modyfikację układu, logiki, danych i organizacji programu w taki sposób, aby był funkcjonalnie identyczny, ale znacznie mniej czytelny. Istnieje wiele różnych podejść do zaciemniania.
  • Osadzanie kodu antydebuggera – innym powszechnym podejściem do przeciwdziałania inżynierii odwrotnej jest utrudnienie analizy na żywo, w której debuger przechodzi przez program, aby określić szczegóły dotyczące jego wewnętrznego wdrożenia. Chodzi o to, aby program celowo wykonywał operacje, które w jakiś sposób uszkodzą lub wyłączą dołączony debugger,. Niektóre z tych podejść obejmują po prostu wykrywanie obecności debugera i kończenie programu, inne obejmują bardziej wyrafinowane sposoby ingerowania w debuggery. Istnieje wiele metod antydebuggera, a wiele z nich jest specyficznych dla platformy lub nawet dla debuggera.

Prosty przykład zastosowania inżynierii odwrotnej oprogramowania

Praca z inżynierią odwrotną często wiąże się z analizą kodu assemblera. Dobra znajomość komend assemblera jest bardzo pomocna. Jednym z poleceń, na które można się natknąć, pracując z kodem, są instrukcje skoku takie jak jz (ang. jump if zero) czy  jmp (ang. unconditional jump). Instrukcje te znajdziemy w kodzie sprawdzającym parzystość liczb:

Po skompilowaniu kodu, jego plik wykonawczy można otworzyć w programie wspomagającym pracę z inżynierią odwrotną, takim jak IDA Pro. IDA Pro analizuje kod binarny pliku wykonawczego i na jego podstawie przeprowadza deasemblacje (Ryc. 5).

Ryc. 5 Deasemblacja kodu w IDA Pro
Ryc. 5 Deasemblacja kodu w IDA Pro

Program po wywołaniu funkcji sprawdzającej isOddNumber(int) wykonuje skok do pamięci (jz), gdzie wyświetlana jest informacja, że liczba jest parzysta. Jest to skok warunkowy, który wywoływany jest tylko jeżeli funkcja isOddNumber(int) zwraca false. Możliwe jest znalezienie lokalizacji, która odpowiada za skok warunkowy jest to adres 00001824 (Ryc.6).

Ryc. 6 Lokalizacja miejsca w pamięci skoku warunkowego
Ryc. 6 Lokalizacja miejsca w pamięci skoku warunkowego

Plik wykonawczy programu można otworzyć w edytorze szesnastkowym takim jak Hex Editor Neo. Pod lokalizacją 00001824 znajdziemy, że instrukcja jz jest opisana szesnastkowo jako 74. Można instrukcję jz zastąpić instrukcją jmp, która jest opisana w kodzie szesnastkowym jako eb. Podmieniając instrukcję jz na instrukcję jmp (Ryc.7), zmieniana jest logika programu w taki sposób, że zawsze wykonywany jest skok do części kodu wyświetlającego informację, że liczba jest parzysta. Wynik wykonania programu przed i po modyfikacji pokazany jest na Ryc. 8.

Ryc. 7 Podmiana instrukcji jz na jmp
Ryc. 7 Podmiana instrukcji jz na jmp
Ryc. 8 Wyświetlanie parzystości przed i po modyfikacji
Ryc. 8 Wyświetlanie parzystości przed i po modyfikacji

***

Jeśli interesują Cię inne tematy z obszaru embedded, zachęcamy do lektury artykułów naszych specjalistów m.in.: Branchless programming czyli programowanie „bezgałęziowe”, serii dot. maszyn wirtualnych oraz Practical use of cryptography on the example of instant messaging application.

4.9/5 ( głosy: 7)
Ocena:
4.9/5 ( głosy: 7)
Autor
Avatar
Kamil Kukliński

Inżynier ds. oprogramowania, pracujący jako programista C++. Obecnie zatrudniony w projekcie dla firmy z branży automatyki przemysłowej. Na co dzień prowadzący raczej osiadły tryb życia z przerwą na siłownię, aczkolwiek ostatnio coraz rzadziej.

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Może Cię również zainteresować

Pokaż więcej artykułów

Bądź na bieżąco

Zasubskrybuj naszego bloga i otrzymuj informacje o najnowszych wpisach.

Otrzymaj ofertę

Jeśli chcesz dowiedzieć się więcej na temat oferty Sii, skontaktuj się z nami.

Wyślij zapytanie Wyślij zapytanie

Natalia Competency Center Director

Get an offer

Dołącz do Sii

Znajdź idealną pracę – zapoznaj się z naszą ofertą rekrutacyjną i aplikuj.

Aplikuj Aplikuj

Paweł Process Owner

Join Sii

ZATWIERDŹ

This content is available only in one language version.
You will be redirected to home page.

Are you sure you want to leave this page?