macOS Apps - Inspecting, debugging and Fuzzing
Last updated
Last updated
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Możesz pobrać disarm stąd.
Możesz pobrać jtool2 tutaj lub zainstalować go za pomocą brew
.
jtool jest przestarzały na rzecz disarm
Codesign
można znaleźć w macOS, podczas gdy ldid
można znaleźć w iOS
SuspiciousPackage to narzędzie przydatne do inspekcji plików .pkg (instalatorów) i zobaczenia, co się w nich znajduje przed ich zainstalowaniem.
Te instalatory mają skrypty bash preinstall
i postinstall
, które autorzy złośliwego oprogramowania zazwyczaj nadużywają, aby utrzymać złośliwe oprogramowanie.
To narzędzie pozwala na zamontowanie obrazów dysków Apple (.dmg) w celu ich inspekcji przed uruchomieniem czegokolwiek:
It will be mounted in /Volumes
Sprawdź wysoką entropię
Sprawdź ciągi (jeśli prawie nie ma zrozumiałego ciągu, spakowane)
Packer UPX dla MacOS generuje sekcję o nazwie "__XHDR"
Zauważ, że programy napisane w Objective-C zachowują swoje deklaracje klas po skompilowaniu do binariów Mach-O. Takie deklaracje klas zawierają nazwę i typ:
Zdefiniowane interfejsy
Metody interfejsu
Zmienne instancji interfejsu
Zdefiniowane protokoły
Zauważ, że te nazwy mogą być zafałszowane, aby utrudnić odwracanie binariów.
Gdy funkcja jest wywoływana w binarium, które używa Objective-C, skompilowany kod zamiast wywoływać tę funkcję, wywoła objc_msgSend
. Który wywoła finalną funkcję:
Parametry, których ta funkcja oczekuje, to:
Pierwszy parametr (self) to "wskaźnik, który wskazuje na instancję klasy, która ma otrzymać wiadomość". Mówiąc prościej, jest to obiekt, na którym wywoływana jest metoda. Jeśli metoda jest metodą klasy, będzie to instancja obiektu klasy (jako całość), natomiast dla metody instancji, self będzie wskazywać na zainstancjonowaną instancję klasy jako obiekt.
Drugi parametr (op) to "selekcja metody, która obsługuje wiadomość". Mówiąc prościej, to po prostu nazwa metody.
Pozostałe parametry to wszelkie wartości wymagane przez metodę (op).
Zobacz, jak łatwo uzyskać te informacje za pomocą lldb
w ARM64 na tej stronie:
x64:
Argument | Rejestr | (dla) objc_msgSend |
1. argument | rdi | self: obiekt, na którym wywoływana jest metoda |
2. argument | rsi | op: nazwa metody |
3. argument | rdx | 1. argument do metody |
4. argument | rcx | 2. argument do metody |
5. argument | r8 | 3. argument do metody |
6. argument | r9 | 4. argument do metody |
7. i więcej | rsp+ (na stosie) | 5. i więcej argumentów do metody |
Dynadump to narzędzie do zrzucania klas binariów Objective-C. Github określa dyliby, ale działa to również z plikami wykonywalnymi.
W momencie pisania, to jest aktualnie to, co działa najlepiej.
class-dump to oryginalne narzędzie do generowania deklaracji dla klas, kategorii i protokołów w kodzie sformatowanym w ObjectiveC.
Jest stare i nieutrzymywane, więc prawdopodobnie nie będzie działać poprawnie.
iCDump to nowoczesny i wieloplatformowy zrzut klas Objective-C. W porównaniu do istniejących narzędzi, iCDump może działać niezależnie od ekosystemu Apple i udostępnia powiązania Pythona.
Z binariów Swift, ponieważ istnieje kompatybilność z Objective-C, czasami można wyodrębnić deklaracje za pomocą class-dump, ale nie zawsze.
Za pomocą poleceń jtool -l
lub otool -l
można znaleźć kilka sekcji, które zaczynają się od prefiksu __swift5
:
Możesz znaleźć więcej informacji na temat informacji przechowywanych w tej sekcji w tym poście na blogu.
Ponadto, binarne pliki Swift mogą mieć symbole (na przykład biblioteki muszą przechowywać symbole, aby ich funkcje mogły być wywoływane). Symbole zazwyczaj zawierają informacje o nazwie funkcji i atrybucie w nieczytelny sposób, więc są bardzo przydatne i istnieją "demanglery", które mogą uzyskać oryginalną nazwę:
Zauważ, że aby debugować binaria, SIP musi być wyłączony (csrutil disable
lub csrutil enable --without debug
) lub skopiować binaria do tymczasowego folderu i usunąć podpis za pomocą codesign --remove-signature <binary-path>
lub zezwolić na debugowanie binariów (możesz użyć tego skryptu)
Zauważ, że aby instrumentować binaria systemowe, (takie jak cloudconfigurationd
) na macOS, SIP musi być wyłączony (same usunięcie podpisu nie zadziała).
macOS udostępnia kilka interesujących API, które dostarczają informacji o procesach:
proc_info
: To główne API, które dostarcza wiele informacji o każdym procesie. Musisz być rootem, aby uzyskać informacje o innych procesach, ale nie potrzebujesz specjalnych uprawnień ani portów mach.
libsysmon.dylib
: Umożliwia uzyskanie informacji o procesach za pomocą funkcji XPC, jednak potrzebne jest posiadanie uprawnienia com.apple.sysmond.client
.
Stackshotting to technika używana do uchwycenia stanu procesów, w tym stosów wywołań wszystkich działających wątków. Jest to szczególnie przydatne do debugowania, analizy wydajności i zrozumienia zachowania systemu w określonym momencie. Na iOS i macOS, stackshotting można przeprowadzić za pomocą kilku narzędzi i metod, takich jak narzędzia sample
i spindump
.
To narzędzie (/usr/bini/ysdiagnose
) zasadniczo zbiera wiele informacji z twojego komputera, wykonując dziesiątki różnych poleceń, takich jak ps
, zprint
...
Musi być uruchomione jako root, a demon /usr/libexec/sysdiagnosed
ma bardzo interesujące uprawnienia, takie jak com.apple.system-task-ports
i get-task-allow
.
Jego plist znajduje się w /System/Library/LaunchDaemons/com.apple.sysdiagnose.plist
, który deklaruje 3 MachServices:
com.apple.sysdiagnose.CacheDelete
: Usuwa stare archiwa w /var/rmp
com.apple.sysdiagnose.kernel.ipc
: Specjalny port 23 (jądro)
com.apple.sysdiagnose.service.xpc
: Interfejs trybu użytkownika przez klasę Obj-C Libsysdiagnose
. Można przekazać trzy argumenty w słowniku (compress
, display
, run
)
MacOS generuje wiele logów, które mogą być bardzo przydatne podczas uruchamiania aplikacji, próbując zrozumieć co ona robi.
Co więcej, są pewne logi, które będą zawierać tag <private>
, aby ukryć niektóre informacje identyfikowalne użytkownika lub komputera. Jednak możliwe jest zainstalowanie certyfikatu, aby ujawnić te informacje. Postępuj zgodnie z wyjaśnieniami tutaj.
W lewym panelu Hopper można zobaczyć symbole (Labels) binariów, listę procedur i funkcji (Proc) oraz ciągi (Str). To nie są wszystkie ciągi, ale te zdefiniowane w różnych częściach pliku Mac-O (takich jak cstring lub objc_methname
).
W środkowym panelu można zobaczyć zdekompilowany kod. Można go zobaczyć jako surowy dekompilat, jako graf, jako zdekompilowany i jako binarne klikając na odpowiednią ikonę:
Klikając prawym przyciskiem myszy na obiekt kodu, można zobaczyć odniesienia do/od tego obiektu lub nawet zmienić jego nazwę (to nie działa w zdekompilowanym pseudokodzie):
Co więcej, w dolnej części środkowego panelu można pisać polecenia Pythona.
W prawym panelu można zobaczyć interesujące informacje, takie jak historia nawigacji (aby wiedzieć, jak dotarłeś do obecnej sytuacji), graf wywołań, w którym można zobaczyć wszystkie funkcje, które wywołują tę funkcję oraz wszystkie funkcje, które ta funkcja wywołuje, oraz informacje o zmiennych lokalnych.
Umożliwia użytkownikom dostęp do aplikacji na niezwykle niskim poziomie i zapewnia sposób dla użytkowników na śledzenie programów i nawet zmianę ich przepływu wykonania. Dtrace używa probes, które są umieszczane w całym jądrze i znajdują się w miejscach takich jak początek i koniec wywołań systemowych.
DTrace używa funkcji dtrace_probe_create
, aby utworzyć sondę dla każdego wywołania systemowego. Te sondy mogą być uruchamiane w punkcie wejścia i wyjścia każdego wywołania systemowego. Interakcja z DTrace odbywa się przez /dev/dtrace, który jest dostępny tylko dla użytkownika root.
Aby włączyć Dtrace bez całkowitego wyłączania ochrony SIP, możesz wykonać w trybie odzyskiwania: csrutil enable --without dtrace
Możesz również dtrace
lub dtruss
binaria, które skompilowałeś.
Dostępne sondy dtrace można uzyskać za pomocą:
Nazwa sondy składa się z czterech części: dostawcy, modułu, funkcji i nazwy (fbt:mach_kernel:ptrace:entry
). Jeśli nie określisz jakiejś części nazwy, Dtrace zastosuje tę część jako symbol wieloznaczny.
Aby skonfigurować DTrace do aktywacji sond i określenia, jakie działania wykonać, gdy zostaną uruchomione, będziemy musieli użyć języka D.
Bardziej szczegółowe wyjaśnienie i więcej przykładów można znaleźć w https://illumos.org/books/dtrace/chp-intro.html
Uruchom man -k dtrace
, aby wyświetlić dostępne skrypty DTrace. Przykład: sudo dtruss -n binary
W linii
skrypt
To jest funkcja śledzenia jądra. Udokumentowane kody można znaleźć w /usr/share/misc/trace.codes
.
Narzędzia takie jak latency
, sc_usage
, fs_usage
i trace
używają go wewnętrznie.
Aby zintegrować się z kdebug
, używa się sysctl
w przestrzeni nazw kern.kdebug
, a MIB-y do użycia można znaleźć w sys/sysctl.h
, mając funkcje zaimplementowane w bsd/kern/kdebug.c
.
Aby interagować z kdebug za pomocą niestandardowego klienta, zazwyczaj wykonuje się następujące kroki:
Usuń istniejące ustawienia za pomocą KERN_KDSETREMOVE
Ustaw śledzenie za pomocą KERN_KDSETBUF i KERN_KDSETUP
Użyj KERN_KDGETBUF, aby uzyskać liczbę wpisów w buforze
Wyciągnij własnego klienta z śledzenia za pomocą KERN_KDPINDEX
Włącz śledzenie za pomocą KERN_KDENABLE
Odczytaj bufor, wywołując KERN_KDREADTR
Aby dopasować każdy wątek do jego procesu, wywołaj KERN_KDTHRMAP.
Aby uzyskać te informacje, można użyć narzędzia Apple trace
lub niestandardowego narzędzia kDebugView (kdv).
Uwaga: Kdebug jest dostępny tylko dla 1 klienta na raz. Więc tylko jedno narzędzie zasilane k-debug może być uruchomione w tym samym czasie.
API ktrace_*
pochodzi z libktrace.dylib
, które opakowuje te z Kdebug
. Następnie klient może po prostu wywołać ktrace_session_create
i ktrace_events_[single/class]
, aby ustawić wywołania zwrotne dla konkretnych kodów, a następnie rozpocząć je za pomocą ktrace_start
.
Możesz używać tego nawet z aktywnym SIP
Możesz używać jako klientów narzędzia ktrace
:
Or tailspin
.
To narzędzie służy do profilowania na poziomie jądra i jest zbudowane przy użyciu wywołań Kdebug
.
W zasadzie, globalna zmienna kernel_debug_active
jest sprawdzana, a jeśli jest ustawiona, wywołuje kperf_kdebug_handler
z kodem Kdebug
i adresem ramki jądra, która wywołuje. Jeśli kod Kdebug
pasuje do jednego z wybranych, otrzymuje "akcje" skonfigurowane jako bitmapa (sprawdź osfmk/kperf/action.h
dla opcji).
Kperf ma również tabelę MIB sysctl: (jako root) sysctl kperf
. Te kody można znaleźć w osfmk/kperf/kperfbsd.c
.
Ponadto, podzbiór funkcjonalności Kperf znajduje się w kpc
, który dostarcza informacji o licznikach wydajności maszyny.
ProcessMonitor to bardzo przydatne narzędzie do sprawdzania działań związanych z procesami, które dany proces wykonuje (na przykład, monitorowanie, które nowe procesy tworzy dany proces).
SpriteTree to narzędzie do wyświetlania relacji między procesami.
Musisz monitorować swojego maca za pomocą polecenia sudo eslogger fork exec rename create > cap.json
(terminal uruchamiający to wymaga FDA). A następnie możesz załadować json w tym narzędziu, aby zobaczyć wszystkie relacje:
FileMonitor pozwala monitorować zdarzenia związane z plikami (takie jak tworzenie, modyfikacje i usunięcia), dostarczając szczegółowych informacji o takich zdarzeniach.
Crescendo to narzędzie GUI, które wygląda i działa jak znane użytkownikom Windows narzędzie Microsoft Sysinternal’s Procmon. To narzędzie pozwala na rozpoczęcie i zatrzymanie nagrywania różnych typów zdarzeń, umożliwia filtrowanie tych zdarzeń według kategorii, takich jak plik, proces, sieć itp., oraz zapewnia funkcjonalność zapisywania nagranych zdarzeń w formacie json.
Apple Instruments są częścią narzędzi deweloperskich Xcode – używane do monitorowania wydajności aplikacji, identyfikowania wycieków pamięci i śledzenia aktywności systemu plików.
Pozwala śledzić działania wykonywane przez procesy:
Taskexplorer jest przydatny do zobaczenia bibliotek używanych przez binarny plik, plików, które wykorzystuje oraz połączeń sieciowych. Sprawdza również procesy binarne w stosunku do virustotal i pokazuje informacje o binarnym pliku.
W tym wpisie na blogu można znaleźć przykład, jak debugować działający demon, który używał PT_DENY_ATTACH
, aby zapobiec debugowaniu, nawet jeśli SIP był wyłączony.
lldb jest de facto narzędziem do debugowania binarnych plików macOS.
Możesz ustawić smak intel podczas używania lldb, tworząc plik o nazwie .lldbinit
w swoim katalogu domowym z następującą linią:
Wewnątrz lldb, zrzutuj proces za pomocą process save-core
(lldb) Komenda | Opis |
run (r) | Rozpoczęcie wykonania, które będzie kontynuowane, aż do osiągnięcia punktu przerwania lub zakończenia procesu. |
process launch --stop-at-entry | Rozpocznij wykonanie zatrzymując się w punkcie wejścia |
continue (c) | Kontynuuj wykonanie debugowanego procesu. |
nexti (n / ni) | Wykonaj następną instrukcję. Ta komenda pominie wywołania funkcji. |
stepi (s / si) | Wykonaj następną instrukcję. W przeciwieństwie do komendy nexti, ta komenda wejdzie w wywołania funkcji. |
finish (f) | Wykonaj resztę instrukcji w bieżącej funkcji (“ramce”), zwróć i zatrzymaj. |
control + c | Wstrzymaj wykonanie. Jeśli proces był uruchomiony (r) lub kontynuowany (c), spowoduje to zatrzymanie procesu ...gdziekolwiek aktualnie się wykonuje. |
breakpoint (b) |
breakpoint delete <num> |
help | help breakpoint #Uzyskaj pomoc dotyczącą komendy punktu przerwania help memory write #Uzyskaj pomoc w zapisywaniu do pamięci |
reg | |
x/s <reg/adres pamięci> | Wyświetl pamięć jako łańcuch zakończony znakiem null. |
x/i <reg/adres pamięci> | Wyświetl pamięć jako instrukcję asemblera. |
x/b <reg/adres pamięci> | Wyświetl pamięć jako bajt. |
print object (po) | To wydrukuje obiekt wskazywany przez parametr po $raw
Należy zauważyć, że większość API lub metod Objective-C firmy Apple zwraca obiekty, a zatem powinny być wyświetlane za pomocą komendy “print object” (po). Jeśli po nie produkuje sensownego wyniku, użyj |
memory | memory read 0x000.... memory read $x0+0xf2a memory write 0x100600000 -s 4 0x41414141 #Zapisz AAAA w tym adresie memory write -f s $rip+0x11f+7 "AAAA" #Zapisz AAAA w adresie |
disassembly | dis #Disas bieżącą funkcję dis -n <funcname> #Disas funkcję dis -n <funcname> -b <basename> #Disas funkcję dis -c 6 #Disas 6 linii dis -c 0x100003764 -e 0x100003768 # Od jednego adresu do drugiego dis -p -c 4 # Rozpocznij w bieżącym adresie disassembling |
parray | parray 3 (char **)$x1 # Sprawdź tablicę 3 komponentów w rejestrze x1 |
image dump sections | Wydrukuj mapę pamięci bieżącego procesu |
image dump symtab <library> |
|
Podczas wywoływania funkcji objc_sendMsg
, rejestr rsi zawiera nazwę metody jako łańcuch zakończony znakiem null (“C”). Aby wydrukować nazwę za pomocą lldb, wykonaj:
(lldb) x/s $rsi: 0x1000f1576: "startMiningWithPort:password:coreCount:slowMemory:currency:"
(lldb) print (char*)$rsi:
(char *) $1 = 0x00000001000f1576 "startMiningWithPort:password:coreCount:slowMemory:currency:"
(lldb) reg read $rsi: rsi = 0x00000001000f1576 "startMiningWithPort:password:coreCount:slowMemory:currency:"
Komenda sysctl hw.model
zwraca "Mac", gdy host to MacOS, ale coś innego, gdy jest to VM.
Bawiąc się wartościami hw.logicalcpu
i hw.physicalcpu
, niektóre złośliwe oprogramowanie próbują wykryć, czy to VM.
Niektóre złośliwe oprogramowanie mogą również wykrywać, czy maszyna jest oparta na VMware na podstawie adresu MAC (00:50:56).
Możliwe jest również sprawdzenie czy proces jest debugowany za pomocą prostego kodu, takiego jak:
if(P_TRACED == (info.kp_proc.p_flag & P_TRACED)){ //proces jest debugowany }
Może również wywołać wywołanie systemowe ptrace
z flagą PT_DENY_ATTACH
. To zapobiega dołączeniu i śledzeniu przez debuger.
Możesz sprawdzić, czy funkcja sysctl
lub ptrace
jest importowana (ale złośliwe oprogramowanie mogłoby zaimportować ją dynamicznie)
Jak zauważono w tym artykule, “Defeating Anti-Debug Techniques: macOS ptrace variants” : “Wiadomość Process # exited with status = 45 (0x0000002d) jest zazwyczaj oznaką, że cel debugowania używa PT_DENY_ATTACH”
Zrzuty rdzenia są tworzone, jeśli:
kern.coredump
sysctl jest ustawiony na 1 (domyślnie)
Jeśli proces nie był suid/sgid lub kern.sugid_coredump
jest 1 (domyślnie 0)
Limit AS_CORE
pozwala na operację. Możliwe jest stłumienie tworzenia zrzutów rdzenia, wywołując ulimit -c 0
i ponowne włączenie ich za pomocą ulimit -c unlimited
.
W tych przypadkach zrzuty rdzenia są generowane zgodnie z kern.corefile
sysctl i zazwyczaj przechowywane w /cores/core/.%P
.
ReportCrash analizuje procesy, które uległy awarii i zapisuje raport o awarii na dysku. Raport o awarii zawiera informacje, które mogą pomóc programiście zdiagnozować przyczynę awarii.
Dla aplikacji i innych procesów uruchamianych w kontekście launchd dla użytkownika, ReportCrash działa jako LaunchAgent i zapisuje raporty o awariach w ~/Library/Logs/DiagnosticReports/
użytkownika.
Dla demonów, innych procesów uruchamianych w kontekście launchd systemu i innych procesów z uprawnieniami, ReportCrash działa jako LaunchDaemon i zapisuje raporty o awariach w /Library/Logs/DiagnosticReports
systemu.
Jeśli obawiasz się, że raporty o awariach są wysyłane do Apple, możesz je wyłączyć. Jeśli nie, raporty o awariach mogą być przydatne do ustalenia, jak serwer uległ awarii.
Podczas fuzzingu w MacOS ważne jest, aby nie pozwolić Macowi na uśpienie:
systemsetup -setsleep Never
pmset, Preferencje systemowe
Jeśli fuzzujesz przez połączenie SSH, ważne jest, aby upewnić się, że sesja nie zostanie zakończona. Zmień więc plik sshd_config na:
TCPKeepAlive Yes
ClientAliveInterval 0
ClientAliveCountMax 0
Sprawdź następującą stronę, aby dowiedzieć się, która aplikacja jest odpowiedzialna za obsługę określonego schematu lub protokołu:
macOS File Extension & URL scheme app handlersTo interesujące, aby znaleźć procesy, które zarządzają danymi sieciowymi:
Lub użyj netstat
lub lsof
Działa z narzędziami CLI
To "po prostu działa" z narzędziami GUI macOS. Należy zauważyć, że niektóre aplikacje macOS mają specyficzne wymagania, takie jak unikalne nazwy plików, odpowiednie rozszerzenie, konieczność odczytu plików z piaskownicy (~/Library/Containers/com.apple.Safari/Data
)...
Kilka przykładów:
Ucz się i ćwicz hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Ucz się i ćwicz hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)