Narzędzia do Reversingu i Podstawowe Metody
Reading time: 13 minutes
tip
Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Wsparcie HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegram lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów github.
Narzędzia do Reversingu oparte na ImGui
Oprogramowanie:
- ReverseKit: https://github.com/zer0condition/ReverseKit
Dekompilator Wasm / Kompilator Wat
Online:
- Użyj https://webassembly.github.io/wabt/demo/wasm2wat/index.html, aby dekompilować z wasm (binarnego) do wat (czystego tekstu)
- Użyj https://webassembly.github.io/wabt/demo/wat2wasm/, aby skompilować z wat do wasm
- możesz także spróbować użyć https://wwwg.github.io/web-wasmdec/, aby dekompilować
Oprogramowanie:
Dekompilator .NET
dotPeek
dotPeek to dekompilator, który dekompiluje i bada wiele formatów, w tym biblioteki (.dll), pliki metadanych Windows (.winmd) oraz wykonywalne (.exe). Po dekompilacji, zestaw można zapisać jako projekt Visual Studio (.csproj).
Zaletą jest to, że jeśli utracony kod źródłowy wymaga przywrócenia z przestarzałego zestawu, ta akcja może zaoszczędzić czas. Ponadto, dotPeek zapewnia wygodną nawigację po dekompilowanym kodzie, co czyni go jednym z idealnych narzędzi do analizy algorytmów Xamarin.
.NET Reflector
Dzięki kompleksowemu modelowi dodatków i API, które rozszerza narzędzie, aby dostosować je do Twoich dokładnych potrzeb, .NET Reflector oszczędza czas i upraszcza rozwój. Przyjrzyjmy się bogactwu usług inżynierii odwrotnej, które to narzędzie oferuje:
- Zapewnia wgląd w to, jak dane przepływają przez bibliotekę lub komponent
- Zapewnia wgląd w implementację i użycie języków i frameworków .NET
- Znajduje nieudokumentowane i nieujawnione funkcjonalności, aby uzyskać więcej z używanych API i technologii.
- Znajduje zależności i różne zestawy
- Śledzi dokładne miejsce błędów w Twoim kodzie, komponentach i bibliotekach stron trzecich.
- Debuguje źródło całego kodu .NET, z którym pracujesz.
ILSpy i dnSpy
Plugin ILSpy dla Visual Studio Code: Możesz go mieć w każdym systemie operacyjnym (możesz zainstalować go bezpośrednio z VSCode, nie ma potrzeby pobierania gita. Kliknij na Rozszerzenia i wyszukaj ILSpy).
Jeśli potrzebujesz dekompilować, modyfikować i ponownie kompilować, możesz użyć dnSpy lub aktywnie utrzymywanego forka, dnSpyEx. (Kliknij prawym przyciskiem -> Modyfikuj metodę, aby zmienić coś w funkcji).
Logowanie DNSpy
Aby DNSpy logował 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");
DNSpy Debugging
Aby debugować kod za pomocą DNSpy, musisz:
Najpierw zmienić atrybuty Assembly związane z debugowaniem:
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
I'm sorry, but it seems that there is no content provided for translation. Please provide the text you would like me to translate.
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default |
DebuggableAttribute.DebuggingModes.DisableOptimizations |
DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints |
DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
I kliknij na kompiluj:
Następnie zapisz nowy plik za pomocą Plik >> Zapisz moduł...:
Jest to konieczne, ponieważ jeśli tego nie zrobisz, w czasie wykonywania kilka optymalizacji zostanie zastosowanych do kodu i może się zdarzyć, że podczas debugowania punkt przerwania nigdy 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ą zrestartować za pomocą:
iisreset /noforce
Aby rozpocząć debugowanie, powinieneś zamknąć wszystkie otwarte pliki, a następnie w Debug Tab wybrać Attach to Process...:
Następnie wybierz w3wp.exe, aby dołączyć do serwera IIS i kliknij attach:
Teraz, gdy debugujemy proces, czas go zatrzymać i załadować wszystkie moduły. Najpierw kliknij na Debug >> Break All, a następnie kliknij na Debug >> Windows >> Modules:
Kliknij dowolny moduł w Modules i wybierz Open All Modules:
Kliknij prawym przyciskiem myszy dowolny moduł w Assembly Explorer i kliknij Sort Assemblies:
Decompiler Java
https://github.com/skylot/jadx
https://github.com/java-decompiler/jd-gui/releases
Debugowanie DLL
Używając 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 DLL oraz funkcję, którą chcesz wywołać:
Następnie, gdy rozpoczniesz debugowanie, wykonanie zostanie zatrzymane, gdy każda DLL zostanie załadowana, a gdy rundll32 załaduje twoją DLL, wykonanie zostanie zatrzymane.
Ale jak możesz dotrzeć do kodu DLL, która została załadowana? Używając tej metody, nie wiem jak.
Używając 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 dll oraz 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ę w każdej głównej DLL, w pewnym momencie zatrzymasz się w wejściu DLL twojej DLL. Stamtąd po prostu poszukaj punktów, w których chcesz ustawić punkt przerwania.
Zauważ, że gdy wykonanie zostanie zatrzymane z jakiegokolwiek powodu w win64dbg, możesz zobaczyć w którym kodzie jesteś, patrząc na górę okna win64dbg:
Następnie, patrząc na to, możesz zobaczyć, kiedy wykonanie zostało zatrzymane w DLL, którą chcesz debugować.
Aplikacje GUI / Gry wideo
Cheat Engine to przydatny program do znajdowania, gdzie ważne wartości są zapisywane w pamięci działającej gry i ich zmiany. Więcej informacji w:
{{#ref}} cheat-engine.md {{#endref}}
PiNCE to narzędzie front-end/odwróconego inżynierii dla GNU Project Debugger (GDB), skoncentrowane na grach. Może być jednak używane do wszelkich związanych z odwróconym inżynierią rzeczy.
Decompiler Explorer to internetowy front-end dla wielu dekompilatorów. Ta usługa internetowa pozwala porównywać wyniki różnych dekompilatorów na małych plikach wykonywalnych.
ARM & MIPS
{{#ref}} https://github.com/nongiach/arm_now {{#endref}}
Shellcodes
Debugowanie shellcode z blobrunner
Blobrunner alokuje shellcode w przestrzeni pamięci, wskaże ci adres pamięci, w którym shellcode został alokowany i zatrzyma wykonanie.
Następnie musisz dołączyć debugger (Ida lub x64dbg) do procesu i ustawić punkt przerwania w wskazanym adresie pamięci oraz wznowić wykonanie. W ten sposób będziesz debugować shellcode.
Strona z wydaniami na githubie zawiera zips z skompilowanymi wydaniami: https://github.com/OALabs/BlobRunner/releases/tag/v0.0.5
Możesz znaleźć nieco zmodyfikowaną wersję Blobrunner w następującym linku. Aby ją skompilować, po prostu stwórz projekt C/C++ w Visual Studio Code, skopiuj i wklej kod i zbuduj go.
{{#ref}} blobrunner.md {{#endref}}
Debugowanie shellcode z jmp2it
jmp2it jest bardzo podobny do blobrunner. Alokuje shellcode w przestrzeni pamięci i rozpoczyna wieczną pętlę. Następnie musisz dołączyć debugger do procesu, uruchomić, 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 do shellcode, a na końcu znajdziesz się w trakcie wykonywania shellcode.
Możesz pobrać skompilowaną wersję jmp2it na stronie wydań.
Debugowanie shellcode przy użyciu Cutter
Cutter to GUI radare. Używając cutter, możesz emulować shellcode i dynamicznie go badać.
Zauważ, że Cutter pozwala na "Otwórz plik" i "Otwórz shellcode". W moim przypadku, gdy otworzyłem shellcode jako plik, poprawnie go dekompilował, ale gdy otworzyłem go jako shellcode, nie:
Aby rozpocząć emulację w miejscu, w którym chcesz, ustaw tam punkt przerwania, a Cutter automatycznie rozpocznie emulację stamtąd:
Możesz zobaczyć stos na przykład w zrzucie heksadecymalnym:
Deobfuskacja shellcode i uzyskiwanie wykonywanych funkcji
Powinieneś spróbować scdbg.
Powie ci rzeczy takie jak które funkcje używa shellcode i czy shellcode 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 dysponuje również graficznym uruchamiaczem, w którym możesz wybrać opcje, które chcesz, i wykonać shellcode.
Opcja Create Dump zrzuci końcowy shellcode, jeśli jakiekolwiek zmiany zostaną wprowadzone do shellcode dynamicznie w pamięci (przydatne do pobrania zdekodowanego shellcode). Start offset może być przydatny do rozpoczęcia shellcode w określonym przesunięciu. Opcja Debug Shell jest przydatna do debugowania shellcode za pomocą terminala scDbg (jednak uważam, że żadna z wcześniej wyjaśnionych opcji nie jest lepsza w tej kwestii, ponieważ będziesz mógł używać Ida lub x64dbg).
Disassembling using CyberChef
Prześlij swój plik shellcode jako wejście i użyj następującego przepisu, aby go dekompilować: https://gchq.github.io/CyberChef/#recipe=To_Hex('Space',0)Disassemble_x86('32','Full%20x86%20architecture',16,0,true,true)
Movfuscator
Ten obfuscator modyfikuje wszystkie instrukcje dla mov
(tak, naprawdę fajne). Używa również przerwań do zmiany przepływów wykonania. Aby uzyskać więcej informacji na temat tego, jak to działa:
- https://www.youtube.com/watch?v=2VF_wPkiBJY
- https://github.com/xoreaxeaxeax/movfuscator/blob/master/slides/domas_2015_the_movfuscator.pdf
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, to obejście w celu znalezienia flagi może być bardzo przydatne: https://dustri.org/b/defeating-the-recons-movfuscator-crackme.html
Rust
Aby znaleźć punkt wejścia, przeszukaj funkcje według ::main
, jak w:
W tym przypadku binarka nazywała się authenticator, więc jest dość oczywiste, że to jest interesująca funkcja główna.
Mając nazwy wywoływanych funkcji, przeszukaj je w Internecie, aby dowiedzieć się o ich wejściach i wyjściach.
Delphi
Dla skompilowanych binarek Delphi możesz użyć https://github.com/crypto2011/IDR
Jeśli musisz zrewersować binarkę Delphi, sugeruję użycie wtyczki IDA https://github.com/Coldzer0/IDA-For-Delphi
Po prostu naciśnij ATL+f7 (importuj wtyczkę python w IDA) i wybierz wtyczkę python.
Ta wtyczka wykona binarkę i dynamicznie rozwiąże nazwy funkcji na początku debugowania. Po rozpoczęciu debugowania naciśnij ponownie przycisk Start (zielony lub f9), a punkt przerwania zatrzyma się 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 wywołanej przez ten przycisk.
Golang
Jeśli musisz zrewersować binarkę Golang, sugeruję użycie wtyczki IDA https://github.com/sibears/IDAGolangHelper
Po prostu naciśnij ATL+f7 (importuj wtyczkę python w IDA) i wybierz wtyczkę python.
To rozwiąże nazwy funkcji.
Skompilowany Python
Na tej stronie możesz znaleźć, jak uzyskać kod python z binarki ELF/EXE skompilowanej w pythonie:
{{#ref}} ../../generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md {{#endref}}
GBA - Game Body Advance
Jeśli zdobędziesz binarkę gry GBA, możesz użyć różnych narzędzi do emulacji i debugowania:
- no$gba (Pobierz wersję debugującą) - Zawiera debugger z interfejsem
- mgba - Zawiera debugger CLI
- gba-ghidra-loader - Wtyczka Ghidra
- GhidraGBA - Wtyczka Ghidra
W no$gba, w Options --> Emulation Setup --> Controls** ** możesz zobaczyć, jak nacisnąć przyciski Game Boy Advance buttons
Po naciśnięciu każdy klawisz ma wartość do jego identyfikacji:
A = 1
B = 2
SELECT = 4
START = 8
RIGHT = 16
LEFT = 32
UP = 64
DOWN = 128
R = 256
L = 256
W takim programie interesującą częścią będzie jak program traktuje dane wejściowe użytkownika. Pod adresem 0x4000130 znajdziesz powszechnie występującą funkcję: KEYINPUT.
Na poprzednim obrazku możesz zobaczyć, że funkcja jest wywoływana z FUN_080015a8 (adresy: 0x080015fa i 0x080017ac).
W tej funkcji, po kilku operacjach inicjalizacyjnych (bez większego 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) {
Ostatni warunek sprawdza, czy uVar4
znajduje się w ostatnich kluczach i nie jest aktualnym kluczem, nazywanym również zwolnieniem przycisku (aktualny 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 widać, że porównujemy uVar1 (miejsce, w którym znajduje się wartość naciśniętego przycisku) z pewnymi wartościami:
- Najpierw porównywana jest z wartością 4 (przycisk SELECT): W wyzwaniu ten przycisk czyści ekran.
- Następnie porównywana jest z wartością 8 (przycisk START): W wyzwaniu sprawdza, czy kod jest ważny, 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 innych przypadkach sprawdzana jest zmienna cont (
DAT_030000d4
). To jest cont, ponieważ dodaje 1 zaraz po wejściu w kod.
Jeśli jest mniejsza niż 8, wykonywane jest coś, co polega na dodawaniu wartości do **DAT_030000d8
** (w zasadzie dodaje wartości naciśniętych klawiszy do tej zmiennej, o ile cont jest mniejszy niż 8).
Tak więc, w tym wyzwaniu, znając wartości przycisków, musiałeś nacisnąć kombinację o długości mniejszej niż 8, której suma wynosi 0xf3.
Referencja do tego samouczka: https://exp.codes/Nostalgia/
Game Boy
{{#ref}} https://www.youtube.com/watch?v=VVbRe7wr3G4 {{#endref}}
Kursy
- https://github.com/0xZ0F/Z0FCourse_ReverseEngineering
- https://github.com/malrev/ABD (deobfuskacja binarna)
tip
Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Wsparcie HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegram lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów github.