10 lutego, 2022

oprogramowanie chronione kluczem inżynierii odwrotnej

byłem młody, internet dopiero się zaczął i mogliśmy uzyskać mnóstwo oprogramowania za darmo. To było za darmo, ponieważ ktoś tam był” miły ” na tyle, aby złamać / łatać .plik exe.

wstawiłem „miły” między cytaty, bo taki widok miałem jak byłem dzieckiem. Teraz jestem inżynierem oprogramowania i wiem, ile wysiłku potrzeba, aby zbudować oprogramowanie. Więc proszę, nie pobieraj pękniętego oprogramowania. Wesprzyj dewelopera i Kup licencję!

stosując taki crack, łatając exe, zawsze chciałem wiedzieć jak to zrobić. Okazuje się, że musisz zrozumieć assembler, język maszynowy, który rozumie tylko twój procesor (i kilku innych kujonów). Ponieważ było to zbyt trudne, nigdy się go nie nauczyłem. Do niedawna (np. 20 lat później).

Zdjęcie Patrick Hendry na Unsplash

rok temu kupiłem oprogramowanie (z licencją!), który do działania potrzebuje klucza USB. Posiadanie tego klucza sprzętowego przez cały czas jest naprawdę uciążliwe. Zwłaszcza, gdy jesteś w drodze. Więc szukałem sposobów na obejście tego. Pierwszą rzeczą, na którą natknąłem się, był ten emulator kluczy o nazwie MultiKey. Zrzuca pamięć klucza sprzętowego do rejestru, a następnie emuluje klucz sprzętowy, czytając z rejestru. To działało OK, dopóki nie chciałem go uruchomić w systemie Windows 10. Najwyraźniej Microsoft nie jest tak wielkim fanem MultiKey. W rzeczywistości nie jest wielkim fanem niepodpisanych sterowników, a MultiKey używa niepodpisanego sterownika. Potrzebowałem więc innego rozwiązania. Czas zanurzyć się w tym czymś zwanym kodem montażowym!

zawsze wiedziałem, że istnieje narzędzie do inżynierii odwrotnej, zwane IDA. Jest w stanie zdekompilować Twoje .plik exe i pokazać, co się dzieje. Niestety interfejs jest naprawdę trudny do zrozumienia. Wiedziałem też o OllyDbg. To debugger. Debugger pozwala na przejście przez kod asemblera podczas działania programu! Oznacza to, na przykład, jeśli debugujesz aplikację kalkulatora, możesz zobaczyć, jak obsługuje naciśnięcie przycisku, wykonuje obliczenia i wyświetla wynik na ekranie. Cholera, można nawet pauze I zmienić jego pamięć, dzięki czemu Kalkulator zwraca 5, gdy pyta, co to jest 2 + 2!

ale nie jestem tu po to, żeby zmieniać rachunek (choć byłoby fajnie). Chcę być wolny od klucza sprzętowego. Więc otworzyłem moją aplikację z OllyDbg.

OllyDbg

to było naprawdę przytłaczające. Nie miałem pojęcia, co oznaczają te kody. Nie mówiąc już o tym, od czego zacząć. Więc wróciłem do deski kreślarskiej. Okazuje się, że istnieje coś o nazwie RetDec, dekompiler, który próbuje zrobić kod C z kodu maszynowego. Trochę czasu zajęło mi skonfigurowanie go i uruchomienie dekompilacji, ale wysiłek się opłacił. Wynik był ogromny .plik c, ponad 2 miliony linii kodu z częściowo czytelnym kodem.

w rzeczywistości mogłem znaleźć kod odczytujący bajty klucza dość łatwo:

wyjście RetDec: zmieniłem już niektóre nazwy zmiennych na coś bardziej czytelnego.

Dzięki tej informacji wróciłem do mojego debugera. W międzyczasie dowiedziałem się, że OllyDbg jest naprawdę stary (od roku 2000) i nie był aktualizowany od 2013. Znalazłem więc nowy, ulepszony debugger o nazwie x64dbg. Jest open source i ma dużą społeczność programistów pracujących nad nim.

odczyt języka maszynowego

w języku maszynowym każda instrukcja ma adres pamięci. Więc z adresami znalezionymi w kodzie RetDec, zwróciłem się do x64dbg i oto kod, który odczytuje klucz sprzętowy:

Kod asemblera odczytujący 2 bajty pamięci klucza sprzętowego.

w kodzie złożenia argumenty funkcji są ładowane do pamięci za pomocą wskaźnika stosu esp. W naszym kodzie dzieje się to tuż przed wywołaniem funkcji. (instrukcje 3 mov wskazują, że wywołanie przyjmuje 3 argumenty). Po wywołaniu nasz wskaźnik stosu jest resetowany i sprawdzany (test), czy wywołanie funkcji powiodło się. Jeśli nie, widzimy kod wykonujący skok (jne). Ten skok wskazuje na fragment kodu wskazujący, że klucz sprzętowy nie jest obecny.

jak widać, istnieje wywołanie określonej funkcji do odczytu klucza sprzętowego. Przejrzałem przewodnik referencyjny, aby dowiedzieć się, co ta funkcja robi:

funkcja odczytuje 2 bajty pamięci (słowo) z klucza sprzętowego. Jak się domyślamy, funkcja pobiera 3 argumenty, gdzie ostatnim argumentem jest wskaźnik na 2 bajty, który będzie zawierał dane z klucza sprzętowego.

w kodzie złożenia argumenty są ładowane w odwrotnej kolejności. Podanie ostatniego argumentu to ten:

ostatni argument wskazuje na esi, co oznacza, że dane z klucza sprzętowego będą przechowywane pod adresem pamięci, na który wskazuje esi.

rzeczywiście, kiedy pauzujemy tuż po wykonaniu połączenia, możemy zobaczyć wynik w pamięci:

0x74. To jest to, co jest odczytywane z klucza sprzętowego i przechowywane w pamięci głównego programu.

aby pominąć to połączenie, muszę tylko napisać 0x74 do pamięci, do której wskazuje esi. Jest to tak proste, jak zastąpienie powyższych 7 linii:

jak widać, nie edytowałem również reszty instrukcji asemblera, w tym testu, czy wywołanie funkcji było poprawne. Oznacza to, że skok nie zostanie wykonany, a program będzie nadal działał bez sprawdzenia.

po załataniu wszystkich połączeń z kluczem sprzętowym zapisałem nowy .exe. Wyciągnąłem klucz, sprawdziłem swój zwyczaj .exe i ku mojemu zdziwieniu zadziałało! Udało mi się złamać oprogramowanie.

kolejna rzecz, którą krzyżuję z mojej listy rzeczy do zrobienia 😊

Ps: większość rzeczy była zamaskowana, jak 0x74 i nazwa aplikacji. Nie jest to szkodliwe dla ciężko pracujących programistów, którzy stworzyli to oprogramowanie w żaden sposób. Miałem również szczęście, że klucz sprzętowy zwrócił tylko bajty i nie zrobił żadnego szyfrowania na własną rękę.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.