hacktricks/reversing-and-exploiting/reversing-tools-basic-methods
2024-04-06 19:35:05 +00:00
..
angr GitBook: No commit message 2024-04-06 19:35:05 +00:00
blobrunner.md GitBook: No commit message 2024-04-06 19:35:05 +00:00
cheat-engine.md GitBook: No commit message 2024-04-06 19:35:05 +00:00
README.md GitBook: No commit message 2024-04-06 19:35:05 +00:00
satisfiability-modulo-theories-smt-z3.md GitBook: No commit message 2024-04-06 19:35:05 +00:00

Reversing Tools & Basic Methods

Zacznij od zera i stań się ekspertem od hakowania AWS dzięki htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Try Hard Security Group

{% embed url="https://discord.gg/tryhardsecurity" %}


Narzędzia do Odwracania Inżynieryjnego oparte na ImGui

Oprogramowanie:

Dekompilator Wasm / Kompilator Wat

Online:

Oprogramowanie:

Dekompilator .NET

dotPeek

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.

.NET Reflector

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.

ILSpy & dnSpy

Plugin ILSpy dla Visual Studio Code: Możesz go mieć w dowolnym systemie operacyjnym (możesz zainstalować go 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 w 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, co może spowodować, ż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ć opcję 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 załadowanego DLL? 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 punkcie DLL, w pewnym momencie zatrzymasz się w DLL Entry twojego DLL. Następnie wyszukaj miejsca, 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 interesującym cię DLL.

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:

{% content-ref url="cheat-engine.md" %} cheat-engine.md {% endcontent-ref %}

ARM & MIPS

{% embed url="https://github.com/nongiach/arm_now" %}

Shellkody

Debugowanie shellkodu za pomocą blobrunner

Blobrunner przydzieli shellkod w przestrzeni pamięci, wskaże adres pamięci, w którym shellkod został przydzielony, 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, a następnie wznów wykonanie. W ten sposób będziesz debugować shellkod.

Na stronie wydań na GitHubie znajdziesz archiwa zip zawierające skompilowane wersje: 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ć.

{% content-ref url="blobrunner.md" %} blobrunner.md {% endcontent-ref %}

Debugowanie shellkodu za pomocą jmp2it

jmp2it jest bardzo podobny do blobrunner. Przydzieli shellkod w przestrzeni pamięci i rozpocznie wieczną pętlę. Następnie musisz dołączyć debugger do procesu, rozpocząć działanie, poczekać 2-5 sekund i nacisnąć stop, aby znaleźć się w wiecznej pętli. Przejdź do następnej instrukcji wiecznej pętli, która będzie wywołaniem do 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 zrzutu szesnastkowego:

Deobfuskacja shellkodu i uzyskiwanie funkcji wykonywanych

Spróbuj scdbg.
Program wskaże, które funkcje wykorzystuje shellkod i czy shellkod jest dekodowany 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żna wybrać żądane opcje i wykonać shellcode

Opcja Create Dump spowoduje zrzucenie ostatecznego shellcode, jeśli w pamięci dynamicznie zostaną dokonane jakiekolwiek zmiany w 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)

Movfuscator

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

Jeśli masz szczęście, demovfuscator zdeobfuskuje 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 w:

W tym przypadku plik binarny nosił nazwę authenticator, więc jest dość oczywiste, że to jest interesująca funkcja główna.
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 plików binarnych Delphi można użyć https://github.com/crypto2011/IDR

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

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

Ta wtyczka będzie wykonywać binarny plik i dynamicznie rozwiązywać nazwy funkcji na początku debugowania. Po rozpoczęciu debugowania ponownie naciśnij przycisk Start (zielony lub f9), a przerwa zostanie ustawiona na początku prawdziwego 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 odwrócić binarny plik Golang, sugeruję użycie wtyczki IDA https://github.com/sibears/IDAGolangHelper

Wystarczy nacisnąć ATL+f7 (importuj 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:

{% content-ref url="../../generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md" %} .pyc.md {% endcontent-ref %}

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

Naciśnięcie każdego przycisku ma wartość identyfikacyjną:

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 wprowadzone przez 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 tym wyzwaniu ten przycisk czyści ekran.
  • Następnie porównujemy go z wartością 8 (przycisk START): W tym 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, wykonywane są działania polegające na dodawaniu wartości do zmiennej DAT_030000d8 (w zasadzie dodawane są wartości naciśniętych klawiszy do tej zmiennej, dopóki cont jest mniejszy niż 8).

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.