Flutter detection
Lorsque l’on décompile l'apk
à l’aide de jadx
, on voit clairement dans le MANIFEST.MF
la présence de libflutter.so
, indiquant que l’application utilise flutter
.
Lorsque l’on run l'apk
, seul un bouton cliquable est présent.
reFlutter
reFlutter permet de patcher l’app et d’utiliser une version patchée de la lib Flutter. L’objectif est de pouvoir intercepter le traffique HTTP/HTTPS en utilisant par exemple Burp Suite.
L'IP
correspond à votre IP locale.
Il faut par la suite ajouter aux Proxy Settings
le port correspondant (8083
) et cocher Support invisible proxying
.
Une fois l'apk
patchée, il ne manque plus qu’à la signer, pour cela il est possible d’utiliser apk-uber
Il ne manque plus qu’à installer à nouveau l’app patchée. Lorsque l’on relance l’application et que l’on clique à nouveau, rien ne se passe..
Penchons nous côté reverse.
B(l)utter
Blutter (https://github.com/worawit/blutter) est un outil permettant de directement reverse le libapp.so
(arm64
) de l’apk. Ce fichier contient les libs natives compilées, ainsi que le code Flutter et les dependencies nécessaire à l’execution de l’app.
Le fichier libapp.so
est récupérable après décompilation par le biais de jadx
(jadx OwnAppV2.apk -d $PWD/jadx
), il se situe dans /resources/lib/
.
On retouve dans /asm/own_app_version_2/
le main.dart
décompilé. En cherchant un peu, on tombe rapidement sur un endpoint explicite.
Si la valeur 42
(0x2A
) est atteinte, alors le code charge l’URL https://ownappv2.ctf.bzh/score_from_user_app_android?score=42
dans un registre, la convertit en un objet Uri avec Uri.parse
, puis envoie une requête GET à l’URL en utilisant http.get
Puisqu’on à la flemme de cliquer 42 fois, on utilise pyautogui
..
import pyautogui
import time
delay = 5
print(f"[+] Place your mouse. Waiting {delay} secondes")
time.sleep(delay)
x, y = pyautogui.position()
number_of_clicks = 42
for _ in range(number_of_clicks):
pyautogui.click(x, y)
print("Done")
On récupère directement dans burp la requête, il ne manque plus qu’à ajouter le score (+1 pour battre Kaluche ahah)
Solve without emulation
Il était aussi possible de récupérer le flag sans même lancer l'apk
. Dans le main.dart
récupéré après avoir reverse le libapp.so
, on avait directement l’endpoint en clair.
La réponse indique que les webbers ne sont pas trusted.. Il suffisait simplement de modifier le User-Agent
par celui d’une application Dart, avec la bonne version. User-Agent: Dart/2.18 (dart:io)
Bonus point: zygisk-reflutter
J’ai trouvé ce module vraiment sympa pour Magisk
, permettant d’implémenter reFlutter
sur un android physique root. (https://github.com/yohanes/zygisk-reflutter)
Remerciements
Merci aux organisateurs, ainsi qu’à @Worty pour les challs android ⋆。゚☁︎ 。⋆
Special thanks a notre team ▯▯▯ aka 🪬🪬🪬(sympa les char non-ascii ahah)