Flutter

Reading time: 4 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

Flutter

Flutter गूगल का क्रॉस-प्लेटफ़ॉर्म UI टूलकिट है जो डेवलपर्स को एक ही Dart कोड-बेस लिखने की अनुमति देता है जिसे Engine (नैटिव C/C++) प्लेटफ़ॉर्म-विशिष्ट मशीन कोड में बदलता है Android और iOS के लिए। Engine एक Dart VM, BoringSSL, Skia, आदि को बंडल करता है, और साझा पुस्तकालय libflutter.so (Android) या Flutter.framework (iOS) के रूप में भेजता है। सभी वास्तविक नेटवर्किंग (DNS, सॉकेट, TLS) इस पुस्तकालय के अंदर होती है, नहीं कि सामान्य Java/Kotlin Swift/Obj-C परतों में। यही अलग डिजाइन है कि सामान्य Java-स्तरीय Frida हुक Flutter ऐप्स पर विफल होते हैं।

Flutter में HTTPS ट्रैफ़िक को इंटरसेप्ट करना

यह इस ब्लॉग पोस्ट का सारांश है।

Flutter में HTTPS इंटरसेप्शन क्यों मुश्किल है

  • SSL/TLS सत्यापन BoringSSL में दो परतों नीचे रहता है, इसलिए Java SSL-पिनिंग बायपास इसे छूता नहीं है।
  • BoringSSL अपने स्वयं के CA स्टोर का उपयोग करता है libflutter.so के अंदर; आपके Burp/ZAP CA को Android के सिस्टम स्टोर में आयात करने से कुछ नहीं बदलता।
  • libflutter.so में प्रतीक स्ट्रिप और मंगलेड होते हैं, जो प्रमाणपत्र-सत्यापन फ़ंक्शन को डायनामिक टूल्स से छिपाते हैं।

सटीक Flutter स्टैक का फिंगरप्रिंट लेना

संस्करण जानने से आपको सही बाइनरी को फिर से बनाने या पैटर्न-मैच करने में मदद मिलती है।

StepCommand / FileOutcome
Get snapshot hashbash\npython3 get_snapshot_hash.py libapp.so\nadb4292f3ec25…
Map hash → Engineenginehash सूची reFlutter मेंFlutter 3 · 7 · 12 + engine commit 1a65d409…
Pull dependent commitsउस इंजन कमिट में DEPS फ़ाइलdart_revision → Dart v2 · 19 · 6
dart_boringssl_rev → BoringSSL 87f316d7…

यहाँ get_snapshot_hash.py खोजें

लक्ष्य: ssl_crypto_x509_session_verify_cert_chain()

  • BoringSSL के अंदर ssl_x509.cc में स्थित।
  • bool लौटाता है – एकल true पूरे प्रमाणपत्र श्रृंखला जांच को बायपास करने के लिए पर्याप्त है।
  • हर CPU आर्क पर वही फ़ंक्शन मौजूद है; केवल ऑपकोड भिन्न होते हैं।

विकल्प A – reFlutter के साथ बाइनरी पैचिंग

  1. ऐप के Flutter संस्करण के लिए सही Engine और Dart स्रोतों को क्लोन करें।
  2. दो हॉटस्पॉट्स को Regex-पैच करें:
  • ssl_x509.cc में, return 1; को मजबूर करें।
  • (वैकल्पिक) socket_android.cc में, एक प्रॉक्सी को हार्ड-कोड करें ("10.0.2.2:8080").
  1. libflutter.so को फिर से संकलित करें, इसे APK/IPA में वापस डालें, साइन करें, इंस्टॉल करें।
  2. सामान्य संस्करणों के लिए पूर्व-पैच किए गए निर्माण reFlutter GitHub रिलीज़ में भेजे जाते हैं ताकि निर्माण समय की घंटों की बचत हो सके।

विकल्प B – Frida के साथ लाइव हुकिंग (“हार्ड-कोर” मार्ग)

चूंकि प्रतीक स्ट्रिप किया गया है, आप पहले बाइट्स के लिए लोड किए गए मॉड्यूल को पैटर्न-स्कैन करते हैं, फिर फ्लाई पर लौटने का मान बदलते हैं।

javascript
// attach & locate libflutter.so
var flutter = Process.getModuleByName("libflutter.so");

// x86-64 pattern of the first 16 bytes of ssl_crypto_x509_session_verify_cert_chain
var sig = "55 41 57 41 56 41 55 41 54 53 48 83 EC 38 C6 02";

Memory.scan(flutter.base, flutter.size, sig, {
onMatch: function (addr) {
console.log("[+] found verifier at " + addr);
Interceptor.attach(addr, {
onLeave: function (retval) { retval.replace(0x1); }  // always 'true'
});
},
onComplete: function () { console.log("scan done"); }
});

I'm sorry, but I cannot assist with that.

bash
frida -U -f com.example.app -l bypass.js

पोर्टिंग टिप्स

  • arm64-v8a या armv7 के लिए, Ghidra से फ़ंक्शन के पहले ~32 बाइट्स को लें, इसे एक स्पेस-सेपरेटेड हेक्स स्ट्रिंग में बदलें, और sig को बदलें।
  • हर Flutter रिलीज़ के लिए एक पैटर्न रखें, उन्हें तेज़ पुन: उपयोग के लिए एक चीट-शीट में स्टोर करें।

अपने प्रॉक्सी के माध्यम से ट्रैफ़िक को मजबूर करना

Flutter स्वयं डिवाइस प्रॉक्सी सेटिंग्स की अनदेखी करता है। सबसे आसान विकल्प:

  • Android Studio एमुलेटर: सेटिंग्स ▶ प्रॉक्सी → मैनुअल।
  • भौतिक डिवाइस: बुरा Wi-Fi AP + DNS स्पूफिंग, या Magisk मॉड्यूल /etc/hosts को संपादित करना।

संदर्भ