Aplikacje Xamarin

Tip

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) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks

Informacje podstawowe

Xamarin jest otwartoźródłową platformą zaprojektowaną dla deweloperów do tworzenia aplikacji na iOS, Android i Windows z użyciem frameworków .NET i C#. Platforma ta oferuje dostęp do wielu narzędzi i rozszerzeń, umożliwiając efektywne tworzenie nowoczesnych aplikacji.

Architektura Xamarin

  • Dla Android, Xamarin integruje się z przestrzeniami nazw Android i Java poprzez .NET bindings, działając w środowisku wykonawczym Mono obok Android Runtime (ART). Managed Callable Wrappers (MCW) i Android Callable Wrappers (ACW) ułatwiają komunikację między Mono a ART, z których oba są zbudowane na kernelu Linux.
  • Dla iOS, aplikacje działają pod runtime Mono, wykorzystując pełną kompilację Ahead of Time (AOT) do konwersji kodu .NET C# na ARM assembly language. Proces ten działa obok Objective-C Runtime na systemie podobnym do UNIX.

.NET Runtime i Mono Framework

Framework .NET zawiera assemblies, klasy i przestrzenie nazw do tworzenia aplikacji, a .NET Runtime zarządza wykonywaniem kodu. Oferuje on niezależność platformową i kompatybilność wsteczną. Mono Framework to otwartoźródłowa implementacja .NET, zapoczątkowana w 2005 w celu rozszerzenia .NET na Linux, obecnie wspierana przez Microsoft i prowadzona przez Xamarin.

Reverse Engineering Xamarin Apps

Decompilation of Xamarin Assemblies

Decompilation przekształca skompilowany kod z powrotem w kod źródłowy. Na Windows, okno Modules w Visual Studio może zidentyfikować moduły do dekompilacji, co pozwala na bezpośredni dostęp do kodu firm trzecich i ekstrakcję kodu źródłowego do analizy.

JIT vs AOT Compilation

  • Android wspiera Just-In-Time (JIT) oraz Ahead-Of-Time (AOT) compilation, z trybem Hybrid AOT dla optymalnej prędkości wykonywania. Full AOT jest dostępne tylko w licencjach Enterprise.
  • iOS używa wyłącznie kompilacji AOT z powodu ograniczeń Apple dotyczących dynamic code execution.

Extracting dll Files from APK/IPA

Aby uzyskać dostęp do assemblies w APK/IPA, rozpakuj plik i przejrzyj katalog assemblies. Dla Android można użyć narzędzi takich jak XamAsmUnZ i xamarin-decompress do rozpakowania plików dll.

python3 xamarin-decompress.py -o /path/to/decompressed/apk

W przypadkach, gdy po zdekompilowaniu APK widać folder unknown/assemblies/ z plikami .dll w środku, można użyć dnSpy bezpośrednio na tych .dlls w celu ich analizy. Jednak czasami pliki assemblies.blob i assemblies.manifest znajdują się w folderze unknown/assemblies/. Narzędzie pyxamstore potrafi rozpakować plik assemblies.blob w Xamarin apps, umożliwiając dostęp do .NET assemblies do dalszej analizy:

pyxamstore unpack -d /path/to/decompressed/apk/assemblies/
# After patching DLLs, rebuild the store
pyxamstore pack

.NET MAUI 9 / .NET for Android — składowiska assembly wewnątrz ELF .so

Najnowsze buildy Android MAUI 9 nie udostępniają już bezpośrednio assemblies.blob. Zamiast tego każda ABI zawiera kontener ELF, np. lib/arm64-v8a/libassemblies.arm64-v8a.blob.so. To jest prawidłowa biblioteka współdzielona z niestandardową sekcją payload, która zawiera składowisko zarządzanych assembly.

Szybki przebieg:

unzip app.apk -d app_unpacked
llvm-readelf --section-headers app_unpacked/lib/arm64-v8a/libassemblies.arm64-v8a.blob.so
llvm-objcopy --dump-section=payload=payload.bin \
app_unpacked/lib/arm64-v8a/libassemblies.arm64-v8a.blob.so
hexdump -c -n 4 payload.bin   # XABA

Jeśli llvm-readelf pokazuje sekcję payload, zrzuc ją i sprawdź, czy wyodrębniony blob zaczyna się od XABA (0x41424158). Ten payload to assembly store opisany przez .NET dla Androida, a nie pojedynczy DLL.

Układ store’a jest przydatny, gdy trzeba ręcznie wyodrębnić assemblies lub zweryfikować extractor:

  • Nagłówek: struct.unpack('<5I', ...) dla magic, version, entry_count, index_entry_count, index_size
  • Deskryptory: entry_count rekordów struct.unpack('<7I', ...) z data_offset / data_size i opcjonalnymi offsetami debug/config
  • Index: pomiń index_size bajtów
  • Names: uint32 length + UTF-8 bytes
  • Data: przesuń się do każdego data_offset i zapisz data_size bajtów jako <name>.dll

Niektóre wyodrębnione pozycje nadal nie otworzą się bezpośrednio w dnSpy/ILSpy/dotPeek, ponieważ są dodatkowo opakowane w XALZ. W takim wypadku:

  • Sprawdź pierwsze 4 bajty każdego wyodrębnionego pliku pod kątem XALZ
  • Odczytaj rozmiar po dekompresji z bajtów 8:12 jako little-endian uint32
  • Dekompresuj bajty 12: za pomocą lz4.block.decompress(...)

Minimalna logika dekompresji:

import struct
import lz4.block

def decompress_xalz(data):
size = struct.unpack('<I', data[8:12])[0]
return lz4.block.decompress(data[12:], uncompressed_size=size)

Jeśli nie chcesz ręcznie parsować store, pymauistore automatyzuje ELF payload extraction, XABA store parsing i XALZ decompression dla MAUI 9 APKs.

Niektóre starsze Xamarin/MAUI buildy przechowują skompresowane assemblies używając formatu XALZ wewnątrz /assemblies.blob lub /resources/assemblies. Możesz je szybko zdekompresować za pomocą biblioteki xamarout:

from xamarout import xalz
import os
for root, _, files in os.walk("."):
for f in files:
if open(os.path.join(root, f), 'rb').read(4) == b"XALZ":
xa = xalz.XamarinCompressedAssembly(os.path.join(root, f))
xa.write("decompressed/" + f)

Pliki .dll dla iOS są łatwo dostępne do dekompilacji, ujawniając znaczne części kodu aplikacji, które często mają wspólną bazę między różnymi platformami.

AOT on iOS: zarządzany IL jest kompilowany do natywnych plików *.aotdata.*. Łatanie samej DLL nie zmieni logiki; trzeba podpiąć się do natywnych stubów (np. za pomocą Frida), ponieważ ciała IL są pustymi zastępcami.

Analiza statyczna

Gdy uzyskamy .dll-y, można statycznie analizować kod .Net przy użyciu narzędzi takich jak dnSpy lub ILSpy, które pozwalają modyfikować kod aplikacji. Może to być bardzo przydatne do manipulowania aplikacją, np. w celu obejścia zabezpieczeń.
Uwaga: po zmodyfikowaniu aplikacji trzeba ją ponownie spakować i ponownie podpisać.

dnSpy jest archiwizowany; utrzymywane forki takie jak dnSpyEx nadal działają z assembly .NET 8/MAUI i zachowują symbole debugowania przy ponownym zapisie.

Analiza dynamiczna

Analiza dynamiczna obejmuje sprawdzanie SSL pinning i używanie narzędzi takich jak Fridax do modyfikacji binarki .NET w czasie działania w aplikacjach Xamarin. Skrypty Frida są dostępne do obejścia detekcji root lub SSL pinning, zwiększając możliwości analizy.

Other interesting Frida scripts:

Zaktualizowany Frida-xamarin-unpin (Mono >=6) hookuje System.Net.Http.HttpClient.SendAsync i zamienia handler na permisywny, dzięki czemu działa nawet gdy pinning jest zaimplementowany w niestandardowych handlerach. Uruchom go po starcie aplikacji:

frida -U -l dist/xamarin-unpin.js com.target.app --no-pause

Szybki szablon do hook managed methods za pomocą dołączonego frida-mono-api:

const mono = require('frida-mono-api');
Mono.ensureInitialized();
Mono.enumerateLoadedImages().forEach(i => console.log(i.name));
const klass = Mono.classFromName("Namespace", "Class");
const m = Mono.methodFromName(klass, "Method", 2);
Mono.intercept(m, { onEnter(args){ console.log(args[1].toInt32()); } });

Ponowne podpisywanie

Narzędzie Uber APK Signer upraszcza podpisywanie wielu plików APK przy użyciu tego samego klucza i może być użyte do ponownego podpisania aplikacji po wprowadzeniu w niej zmian.

Referencje

Tip

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) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks