Reversing Tools & Basic Methods

Dowiedz się, jak hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Try Hard Security Group


Narzędzia do Odwracania Inżynieryjnego oparte na ImGui

Oprogramowanie:

Dekompilator Wasm / Kompilator Wat

Online:

Oprogramowanie:

Dekompilator .NET

dotPeek to dekompilator, który dekompiluje i analizuje wiele formatów, w tym biblioteki (.dll), pliki metadanych systemu Windows (.winmd) i pliki wykonywalne (.exe). Po dekompilacji zestawu można zapisać jako projekt Visual Studio (.csproj).

Zaletą jest to, że jeśli utracony kod źródłowy wymaga przywrócenia z archiwalnego zestawu, ta czynność może zaoszczędzić czas. Ponadto dotPeek zapewnia wygodną nawigację po zdekompilowanym kodzie, co czyni go jednym z doskonałych narzędzi do analizy algorytmów Xamarin.

Dzięki kompleksowemu modelowi dodatków i interfejsowi API rozszerzającemu narzędzie, .NET Reflector oszczędza czas i upraszcza rozwój. Przejrzyjmy mnogość usług inżynierii wstecznej, które oferuje to narzędzie:

  • Zapewnia wgląd w sposób przepływu danych przez bibliotekę lub komponent

  • Zapewnia wgląd w implementację i użycie języków i platform .NET

  • Znajduje funkcjonalności nieudokumentowane i nieujawnione, aby uzyskać więcej z używanych interfejsów API i technologii.

  • Znajduje zależności i różne zestawy

  • Namierza dokładne miejsce błędów w twoim kodzie, komponentach innych firm i bibliotekach.

  • Debuguje źródło całego kodu .NET, z którym pracujesz.

Wtyczka ILSpy dla Visual Studio Code: Możesz ją mieć w dowolnym systemie operacyjnym (możesz zainstalować ją bezpośrednio z VSCode, nie trzeba pobierać z git. Kliknij Extensions i szukaj ILSpy). Jeśli musisz dekompilować, modyfikować i ponownie kompilować, możesz użyć dnSpy lub aktywnie rozwijanej gałęzi, dnSpyEx. (Kliknij prawym przyciskiem -> Modify Method aby zmienić coś wewnątrz funkcji).

Logowanie DNSpy

Aby sprawić, że DNSpy zaloguje pewne informacje do pliku, możesz użyć tego fragmentu:

using System.IO;
path = "C:\\inetpub\\temp\\MyTest2.txt";
File.AppendAllText(path, "Password: " + password + "\n");

Debugowanie za pomocą DNSpy

Aby debugować kod za pomocą DNSpy, musisz:

Po pierwsze, zmień Atrybuty zestawu związane z debugowaniem:

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]

Do:

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default |
DebuggableAttribute.DebuggingModes.DisableOptimizations |
DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints |
DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]

I kliknij skompiluj:

Następnie zapisz nowy plik za pomocą Plik >> Zapisz moduł...:

Jest to konieczne, ponieważ jeśli tego nie zrobisz, podczas uruchamiania kodu zostanie zastosowanych kilka optymalizacji i może się zdarzyć, że podczas debugowania punkt przerwania nie zostanie osiągnięty lub niektóre zmienne nie istnieją.

Następnie, jeśli twoja aplikacja .NET jest uruchamiana przez IIS, możesz ją ponownie uruchomić za pomocą:

iisreset /noforce

Następnie, aby rozpocząć debugowanie, należy zamknąć wszystkie otwarte pliki i w zakładce Debug wybrać Attach to Process...:

Następnie wybierz w3wp.exe, aby dołączyć do serwera IIS i kliknij attach:

Teraz, gdy debugujemy proces, nadszedł czas, aby go zatrzymać i załadować wszystkie moduły. Najpierw kliknij Debug >> Break All, a następnie kliknij Debug >> Windows >> Modules:

Kliknij dowolny moduł w Modules i wybierz Open All Modules:

Kliknij prawym przyciskiem myszy dowolny moduł w Assembly Explorer i wybierz Sort Assemblies:

Dekompilator Java

https://github.com/skylot/jadx https://github.com/java-decompiler/jd-gui/releases

Debugowanie plików DLL

Korzystanie z IDA

  • Załaduj rundll32 (64 bity w C:\Windows\System32\rundll32.exe i 32 bity w C:\Windows\SysWOW64\rundll32.exe)

  • Wybierz debugger Windbg

  • Wybierz "Suspend on library load/unload"

  • Skonfiguruj parametry wykonania, podając ścieżkę do pliku DLL i funkcję, którą chcesz wywołać:

Następnie, gdy rozpoczniesz debugowanie, wykonanie zostanie zatrzymane po załadowaniu każdego DLL, a gdy rundll32 załaduje twoje DLL, wykonanie zostanie zatrzymane.

Ale jak uzyskać dostęp do kodu DLL, który został załadowany? Korzystając z tej metody, nie wiem jak.

Korzystanie z x64dbg/x32dbg

  • Załaduj rundll32 (64 bity w C:\Windows\System32\rundll32.exe i 32 bity w C:\Windows\SysWOW64\rundll32.exe)

  • Zmień linię poleceń ( File --> Change Command Line ) i ustaw ścieżkę do pliku DLL i funkcję, którą chcesz wywołać, na przykład: "C:\Windows\SysWOW64\rundll32.exe" "Z:\shared\Cybercamp\rev2\\14.ridii_2.dll",DLLMain

  • Zmień Options --> Settings i wybierz "DLL Entry".

  • Następnie rozpocznij wykonanie, debugger zatrzyma się przy każdym głównym elemencie DLL, w pewnym momencie zatrzymasz się w wejściu DLL twojego DLL. Następnie wyszukaj punkty, w których chcesz ustawić punkt przerwania.

Zauważ, że gdy wykonanie zostanie zatrzymane z jakiegokolwiek powodu w win64dbg, możesz zobaczyć w jakim kodzie się znajdujesz patrząc na górę okna win64dbg:

Następnie, patrząc na to, możesz zobaczyć, kiedy wykonanie zostało zatrzymane w DLL, które chcesz debugować.

Aplikacje GUI / Gry wideo

Cheat Engine to przydatny program do znajdowania ważnych wartości zapisanych w pamięci działającej gry i ich zmiany. Więcej informacji znajdziesz w:

pageCheat Engine

PiNCE to narzędzie do inżynierii wstecznej dla GNU Project Debugger (GDB), skupione na grach. Może być jednak używane do różnych zadań związanych z inżynierią wsteczną.

Decompiler Explorer to interfejs internetowy do wielu dekompilatorów. Ta usługa internetowa pozwala porównać wyniki różnych dekompilatorów na małych plikach wykonywalnych.

ARM & MIPS

Shellkody

Debugowanie shellkodu za pomocą blobrunner

Blobrunner zaalokuje shellkod w przestrzeni pamięci, wskaże adres pamięci, w którym został zaalokowany shellkod, a następnie zatrzyma wykonanie. Następnie musisz dołączyć debugger (Ida lub x64dbg) do procesu i ustawić punkt przerwania na wskazanym adresie pamięci i wznowić wykonanie. W ten sposób będziesz debugować shellkod.

Strona wydań na githubie zawiera skompresowane wersje wydań: https://github.com/OALabs/BlobRunner/releases/tag/v0.0.5 Możesz znaleźć nieco zmodyfikowaną wersję Blobrunner pod następującym linkiem. Aby ją skompilować, wystarczy utworzyć projekt C/C++ w Visual Studio Code, skopiować i wkleić kod oraz go skompilować.

pageBlobrunner

Debugowanie shellkodu za pomocą jmp2it

jmp2it jest bardzo podobny do blobrunner. Alokuję shellkod w przestrzeni pamięci i uruchamia wieczną pętlę. Następnie musisz dołączyć debugger do procesu, rozpocząć działanie, poczekać 2-5 sekund i nacisnąć stop, a znajdziesz się w wiecznej pętli. Przejdź do następnej instrukcji wiecznej pętli, ponieważ będzie to wywołanie shellkodu, a ostatecznie będziesz wykonywać shellkod.

Możesz pobrać skompilowaną wersję jmp2it ze strony wydań.

Debugowanie shellkodu za pomocą Cutter

Cutter to interfejs graficzny radare. Za pomocą Cuttera możesz emulować shellkod i dynamicznie go analizować.

Zauważ, że Cutter pozwala na "Otwarcie pliku" i "Otwarcie shellkodu". W moim przypadku, gdy otworzyłem shellkod jako plik, został on poprawnie zdekompilowany, ale gdy otworzyłem go jako shellkod, nie:

Aby rozpocząć emulację w wybranym miejscu, ustaw tam punkt przerwania, a Cutter automatycznie rozpocznie emulację od tego miejsca:

Możesz zobaczyć stos na przykład w postaci wydruku szesnastkowego:

Odszyfrowywanie shellkodu i uzyskiwanie funkcji wykonywanych

Spróbuj scdbg. Pokaże ci, które funkcje używa shellkod i czy shellkod dekoduje się w pamięci.

scdbg.exe -f shellcode # Get info
scdbg.exe -f shellcode -r #show analysis report at end of run
scdbg.exe -f shellcode -i -r #enable interactive hooks (file and network) and show analysis report at end of run
scdbg.exe -f shellcode -d #Dump decoded shellcode
scdbg.exe -f shellcode /findsc #Find offset where starts
scdbg.exe -f shellcode /foff 0x0000004D #Start the executing in that offset

scDbg posiada również graficzny uruchamiacz, w którym możesz wybrać opcje, których chcesz użyć i wykonać shellcode

Opcja Create Dump spowoduje zrzucenie ostatecznego shellcode, jeśli jakakolwiek zmiana zostanie dokonana dynamicznie w pamięci shellcode (przydatne do pobrania zdekodowanego shellcode). Start offset może być przydatny do uruchomienia shellcode w określonym przesunięciu. Opcja Debug Shell jest przydatna do debugowania shellcode za pomocą terminala scDbg (jednak uważam, że któreś z opcji wyjaśnionych wcześniej są lepsze w tej kwestii, ponieważ będziesz mógł użyć Ida lub x64dbg).

Rozkładanie za pomocą CyberChef

Prześlij plik ze swoim shellcodem jako dane wejściowe i użyj następującego przepisu, aby go zdekompilować: https://gchq.github.io/CyberChef/#recipe=To_Hex('Space',0)Disassemble_x86('32','Full%20x86%20architecture',16,0,true,true)

Ten obfuskator modyfikuje wszystkie instrukcje dla mov (tak, naprawdę fajne). Wykorzystuje również przerwania do zmiany przepływów wykonań. Aby uzyskać więcej informacji na temat jego działania:

Jeśli masz szczęście, demovfuscator zdeobfuskowuje binarny plik. Ma kilka zależności

apt-get install libcapstone-dev
apt-get install libz3-dev

I zainstaluj keystone (apt-get install cmake; mkdir build; cd build; ../make-share.sh; make install)

Jeśli bierzesz udział w CTF, ta metoda znajdowania flagi może być bardzo przydatna: https://dustri.org/b/defeating-the-recons-movfuscator-crackme.html

Rust

Aby znaleźć punkt wejścia, wyszukaj funkcje za pomocą ::main jak tutaj:

W tym przypadku plik binarny nosił nazwę authenticator, więc jest dość oczywiste, że ta funkcja main jest interesująca. Mając nazwę funkcji, które są wywoływane, wyszukaj je w Internecie, aby dowiedzieć się o ich wejściach i wyjściach.

Delphi

Dla skompilowanych binariów Delphi można użyć https://github.com/crypto2011/IDR

Jeśli musisz zreversować binarny plik Delphi, sugeruję użycie wtyczki IDA https://github.com/Coldzer0/IDA-For-Delphi

Wystarczy nacisnąć ATL+f7 (zaimportuj wtyczkę python w IDA) i wybierz wtyczkę python.

Ta wtyczka uruchomi plik binarny i dynamicznie rozwiąże nazwy funkcji na początku debugowania. Po rozpoczęciu debugowania ponownie naciśnij przycisk Start (zielony lub f9), a przerwa zostanie osiągnięta na początku rzeczywistego kodu.

Jest to również bardzo interesujące, ponieważ jeśli naciśniesz przycisk w aplikacji graficznej, debugger zatrzyma się w funkcji wykonywanej przez ten przycisk.

Golang

Jeśli musisz zreversować binarny plik Golang, sugeruję użycie wtyczki IDA https://github.com/sibears/IDAGolangHelper

Wystarczy nacisnąć ATL+f7 (zaimportuj wtyczkę python w IDA) i wybierz wtyczkę python.

To rozwiąże nazwy funkcji.

Skompilowany Python

Na tej stronie znajdziesz, jak uzyskać kod pythona z binarnego pliku skompilowanego w formacie ELF/EXE:

pageDecompile compiled python binaries (exe, elf) - Retreive from .pyc

GBA - Game Body Advance

Jeśli masz binarny plik gry GBA, możesz użyć różnych narzędzi do emulacji i debugowania:

W no$gba, w Opcje --> Konfiguracja Emulacji --> Kontrole** ** możesz zobaczyć, jak nacisnąć przyciski Game Boy Advance

Gdy są naciśnięte, każdy klawisz ma wartość, aby go zidentyfikować:

A = 1
B = 2
SELECT = 4
START = 8
RIGHT = 16
LEFT = 32
UP = 64
DOWN = 128
R = 256
L = 256

Więc w tego rodzaju programie interesującą częścią będzie sposób, w jaki program traktuje dane wejściowe użytkownika. W adresie 0x4000130 znajdziesz często spotykaną funkcję: KEYINPUT.

Na poprzednim obrazku możesz zobaczyć, że funkcja jest wywoływana z FUN_080015a8 (adresy: 0x080015fa i 0x080017ac).

W tej funkcji, po pewnych operacjach inicjalizacyjnych (bez znaczenia):

void FUN_080015a8(void)

{
ushort uVar1;
undefined4 uVar2;
undefined4 uVar3;
ushort uVar4;
int iVar5;
ushort *puVar6;
undefined *local_2c;

DISPCNT = 0x1140;
FUN_08000a74();
FUN_08000ce4(1);
DISPCNT = 0x404;
FUN_08000dd0(&DAT_02009584,0x6000000,&DAT_030000dc);
FUN_08000354(&DAT_030000dc,0x3c);
uVar4 = DAT_030004d8;

Znaleziono ten kod:

do {
DAT_030004da = uVar4; //This is the last key pressed
DAT_030004d8 = KEYINPUT | 0xfc00;
puVar6 = &DAT_0200b03c;
uVar4 = DAT_030004d8;
do {
uVar2 = DAT_030004dc;
uVar1 = *puVar6;
if ((uVar1 & DAT_030004da & ~uVar4) != 0) {

Ostatnie if sprawdza, czy uVar4 znajduje się w ostatnich kluczach i nie jest to bieżący klucz, zwany również puśczeniem przycisku (bieżący klucz jest przechowywany w uVar1).

if (uVar1 == 4) {
DAT_030000d4 = 0;
uVar3 = FUN_08001c24(DAT_030004dc);
FUN_08001868(uVar2,0,uVar3);
DAT_05000000 = 0x1483;
FUN_08001844(&DAT_0200ba18);
FUN_08001844(&DAT_0200ba20,&DAT_0200ba40);
DAT_030000d8 = 0;
uVar4 = DAT_030004d8;
}
else {
if (uVar1 == 8) {
if (DAT_030000d8 == 0xf3) {
DISPCNT = 0x404;
FUN_08000dd0(&DAT_02008aac,0x6000000,&DAT_030000dc);
FUN_08000354(&DAT_030000dc,0x3c);
uVar4 = DAT_030004d8;
}
}
else {
if (DAT_030000d4 < 8) {
DAT_030000d4 = DAT_030000d4 + 1;
FUN_08000864();
if (uVar1 == 0x10) {
DAT_030000d8 = DAT_030000d8 + 0x3a;

W poprzednim kodzie można zobaczyć, że porównujemy uVar1 (miejsce, gdzie znajduje się wartość naciśniętego przycisku) z pewnymi wartościami:

  • Po pierwsze, porównujemy go z wartością 4 (przycisk SELECT): W wyzwaniu ten przycisk czyści ekran.

  • Następnie porównujemy go z wartością 8 (przycisk START): W wyzwaniu sprawdzane jest, czy kod jest poprawny, aby uzyskać flagę.

  • W tym przypadku zmienna DAT_030000d8 jest porównywana z 0xf3, a jeśli wartość jest taka sama, wykonywany jest pewien kod.

  • W pozostałych przypadkach sprawdzane jest cont (DAT_030000d4). Jest to cont, ponieważ dodaje 1 zaraz po wpisaniu kodu. Jeśli jest mniejszy niż 8, coś związanego z dodawaniem wartości do DAT_030000d8 jest wykonywane (w zasadzie dodawane są wartości naciśniętych klawiszy do tej zmiennej, dopóki cont jest mniejszy niż 8).

Więc w tym wyzwaniu, znając wartości przycisków, musisz nacisnąć kombinację o długości mniejszej niż 8, tak aby wynikowe dodawanie było równe 0xf3.

Odnośnik do tego samouczka: https://exp.codes/Nostalgia/

Game Boy

Kursy

Try Hard Security Group

Zacznij od zera i zostań ekspertem AWS w dziedzinie hakingu dzięki htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Last updated