Frida ํŠœํ† ๋ฆฌ์–ผ

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 ์ง€์›ํ•˜๊ธฐ

์„ค์น˜

๋‹ค์Œ์œผ๋กœ frida tools๋ฅผ ์„ค์น˜ํ•˜์„ธ์š”:

pip install frida-tools
pip install frida

๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ์„ค์น˜ํ•˜์„ธ์š” Android์—์„œ frida server (Download the latest release).
adb๋ฅผ root ๋ชจ๋“œ๋กœ ์žฌ์‹œ์ž‘ํ•˜๊ณ , ์—ฐ๊ฒฐํ•œ ๋’ค frida-server๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ  ์‹คํ–‰ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•œ ๋‹ค์Œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰ํ•˜๋Š” ํ•œ ์ค„ ๋ช…๋ น:

adb root; adb connect localhost:6000; sleep 1; adb push frida-server /data/local/tmp/; adb shell "chmod 755 /data/local/tmp/frida-server"; adb shell "/data/local/tmp/frida-server &"

ํ™•์ธ ์ด๊ฒƒ์ด ์ž‘๋™ํ•˜๋Š”์ง€:

frida-ps -U #List packages and processes
frida-ps -U | grep -i <part_of_the_package_name> #Get all the package name

frida-ui (๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ฐ˜ Frida ์ปจํŠธ๋กค๋Ÿฌ)

frida-ui๋Š” http://127.0.0.1:8000์—์„œ ์žฅ์น˜/์•ฑ์„ ๋‚˜์—ดํ•˜๊ณ  ์Šคํฌ๋ฆฝํŠธ๋กœ ๋Œ€์ƒ์— attachํ•˜๊ฑฐ๋‚˜ spawnํ•  ์ˆ˜ ์žˆ๋Š” ์›น UI๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค (CLI ๋ถˆํ•„์š”).

  • ์„ค์น˜ (device server ๋ฒ„์ „์— ๋งž์ถฐ frida๋ฅผ ๊ณ ์ •):
uv tool install frida-ui --with frida==16.7.19
# pipx install frida-ui
# pip install frida-ui
  • ์‹คํ–‰:
frida-ui
frida-ui --host 127.0.0.1 --port 8000 --reload
  • ๊ธฐ๋Šฅ: USB/๋กœ์ปฌ ์žฅ์น˜๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ , ์›๊ฒฉ ์„œ๋ฒ„ (192.168.1.x:27042)๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉฐ, Attach, Spawn, Spawn & Run์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค(์ดˆ๊ธฐ onCreate() ๋กœ์ง ์ด์ „์— ํ›…์„ ๊ฑธ๊ธฐ ์œ„ํ•ด).
  • ์Šคํฌ๋ฆฝํŒ…: ์—๋””ํ„ฐ, .js ํŒŒ์ผ ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ, CodeShare ๊ฐ€์ ธ์˜ค๊ธฐ, ์Šคํฌ๋ฆฝํŠธ ๋ฐ ์„ธ์…˜ ๋กœ๊ทธ ๋‹ค์šด๋กœ๋“œ.
  • ์›๊ฒฉ ์„œ๋ฒ„: ./frida-server -l 0.0.0.0:27042 -D๋Š” ๋„คํŠธ์›Œํฌ์— ๋…ธ์ถœ์‹œ์ผœ frida-ui๊ฐ€ ADB ์—†์ด ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

Frida server vs. Gadget (root vs. no-root)

Frida๋กœ Android ์•ฑ์„ ๊ณ„์ธกํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•:

  • Frida server (rooted devices): ๋ชจ๋“  ํ”„๋กœ์„ธ์Šค์— attachํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ๋ฐ๋ชฌ์„ ํ‘ธ์‹œํ•˜๊ณ  ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • Frida Gadget (no root): Frida๋ฅผ APK ๋‚ด๋ถ€์— ๊ณต์œ  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋ฒˆ๋“คํ•˜์—ฌ ๋Œ€์ƒ ํ”„๋กœ์„ธ์Šค์—์„œ ์ž๋™์œผ๋กœ ๋กœ๋“œ๋˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

Frida server (rooted)

# Download the matching frida-server binary for your device's arch
# https://github.com/frida/frida/releases
adb root
adb push frida-server-<ver>-android-<arch> /data/local/tmp/frida-server
adb shell chmod 755 /data/local/tmp/frida-server
adb shell /data/local/tmp/frida-server &    # run at boot via init/magisk if desired

# From host, list processes and attach
frida-ps -Uai
frida -U -n com.example.app

Frida Gadget (no-root)

  1. APK์„ ์–ธํŒฉํ•˜๊ณ  gadget .so์™€ ์„ค์ •์„ ์ถ”๊ฐ€:
  • libfrida-gadget.so๋ฅผ lib/<abi>/ (์˜ˆ: lib/arm64-v8a/)์— ๋ฐฐ์น˜
  • assets/frida-gadget.config๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์Šคํฌ๋ฆฝํŠธ ๋กœ๋”ฉ ์„ค์ •์„ ๋„ฃ์œผ์„ธ์š”

Example frida-gadget.config

{
"interaction": { "type": "script", "path": "/sdcard/ssl-bypass.js" },
"runtime": { "logFile": "/sdcard/frida-gadget.log" }
}
  1. ๊ฐ€์ ฏ์„ ์ฐธ์กฐ/๋กœ๋“œํ•˜์—ฌ ์กฐ๊ธฐ์— ์ดˆ๊ธฐํ™”๋˜๋„๋ก:
  • ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•: Application.onCreate()์— System.loadLibrary(โ€œfrida-gadgetโ€)๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ž‘์€ Java stub์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜, ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•˜์„ธ์š”.
  1. Repackํ•˜๊ณ  APK์— ์„œ๋ช…ํ•œ ๋‹ค์Œ ์„ค์น˜ํ•˜์„ธ์š”:
apktool d app.apk -o app_m
# ... add gadget .so and config ...
apktool b app_m -o app_gadget.apk
uber-apk-signer -a app_gadget.apk -o out_signed
adb install -r out_signed/app_gadget-aligned-debugSigned.apk
  1. host์—์„œ gadget process์— Attach:
frida-ps -Uai
frida -U -n com.example.app

์ฐธ๊ณ 

  • ์ผ๋ถ€ ๋ณดํ˜ธ ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ Gadget์„ ๊ฐ์ง€ํ•˜๋ฏ€๋กœ, ํ•„์š”ํ•˜๋ฉด ์ด๋ฆ„/๊ฒฝ๋กœ๋ฅผ ์€ํํ•˜๊ณ  ๋Šฆ๊ฒŒ ๋˜๋Š” ์กฐ๊ฑด๋ถ€๋กœ ๋กœ๋“œํ•˜์„ธ์š”.
  • ๊ฐ•ํ™”๋œ ์•ฑ์˜ ๊ฒฝ์šฐ ๋ฃจํŒ…๋œ ์ƒํƒœ์—์„œ server + late attach๋กœ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•˜๊ฑฐ๋‚˜ Magisk/Zygisk ์€ํ์™€ ๊ฒฐํ•ฉํ•˜์„ธ์š”.

JDWP ๊ธฐ๋ฐ˜ Frida injection without root/repackaging (frida-jdwp-loader)

APK๊ฐ€ ๋””๋ฒ„๊น… ๊ฐ€๋Šฅ(android:debuggable=โ€œtrueโ€)ํ•˜๋ฉด, JDWP๋กœ ์—ฐ๊ฒฐํ•ด Java breakpoint์—์„œ ๋„ค์ดํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฃจํŠธ๋‚˜ APK ์žฌํŒจํ‚ค์ง• ๋ถˆํ•„์š”.

  • Repo: https://github.com/frankheat/frida-jdwp-loader
  • ์š”๊ตฌ์‚ฌํ•ญ: ADB, Python 3, USB/๋ฌด์„  ๋””๋ฒ„๊น…. ์•ฑ์€ ๋””๋ฒ„๊ทธ ๊ฐ€๋Šฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค (์—๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ro.debuggable=1, ๋ฃจํŒ…๋œ ๊ธฐ๊ธฐ์—์„œ resetprop, ๋˜๋Š” ๋งค๋‹ˆํŽ˜์ŠคํŠธ ์žฌ๋นŒ๋“œ).

๋น ๋ฅธ ์‹œ์ž‘

git clone https://github.com/frankheat/frida-jdwp-loader.git
cd frida-jdwp-loader
# Inject frida-gadget.so into a debuggable target
python frida-jdwp-loader.py frida -n com.example.myapplication
# Keep the breakpoint thread suspended for early hooks
python frida-jdwp-loader.py frida -n com.example.myapplication -s
# Networkless: run a local agent script via Gadget "script" mode
python frida-jdwp-loader.py frida -n com.example.myapplication -i script -l script.js

๋…ธํŠธ

  • ๋ชจ๋“œ: spawn (break at Application.onCreate) or attach (break at Activity.onStart). ํŠน์ • Java ๋ฉ”์„œ๋“œ๋ฅผ ์„ค์ •ํ•˜๋ ค๋ฉด -b๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , Gadget ๋ฒ„์ „/๊ฒฝ๋กœ๋ฅผ ์„ ํƒํ•˜๋ ค๋ฉด -g, JDWP ํฌํŠธ๋ฅผ ์„ ํƒํ•˜๋ ค๋ฉด -p๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
  • ๋ฆฌ์Šค๋‹ ๋ชจ๋“œ: ํ•„์š”ํ•œ ๊ฒฝ์šฐ Gadget(๊ธฐ๋ณธ๊ฐ’ 127.0.0.1:27042)๋ฅผ ํฌ์›Œ๋“œํ•˜์„ธ์š”: adb forward tcp:27042 tcp:27042; ๊ทธ๋Ÿฐ ๋‹ค์Œ frida-ps -H 127.0.0.1:27042.
  • ์ด๋Š” JDWP ๋””๋ฒ„๊น…์„ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค. ์œ„ํ—˜: debuggable ๋นŒ๋“œ๋ฅผ ๋ฐฐํฌํ•˜๊ฑฐ๋‚˜ JDWP๋ฅผ ๋…ธ์ถœ์‹œํ‚ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋…๋ฆฝํ˜• ์—์ด์ „ํŠธ + Gadget ์ž„๋ฒ ๋”ฉ (Frida 17+; Objection์œผ๋กœ ์ž๋™ํ™”๋จ)

Frida 17์€ GumJS์—์„œ ๋‚ด์žฅ๋œ Java/ObjC bridges๋ฅผ ์ œ๊ฑฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๊ฐ€ Java๋ฅผ ํ›…(hook)ํ•œ๋‹ค๋ฉด, Java bridge๋ฅผ ๋ฒˆ๋“ค์— ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  1. Frida ์—์ด์ „ํŠธ(TypeScript)๋ฅผ ์ƒ์„ฑํ•˜๊ณ  Java bridge๋ฅผ ํฌํ•จํ•˜์„ธ์š”
# Scaffolding
frida-create -t agent -o mod
cd mod && npm install
# Install the Java bridge for Frida 17+
npm install frida-java-bridge
# Dev loop (optional live-reload via REPL)
npm run watch

์ตœ์†Œํ•œ์˜ Java hook (์ฃผ์‚ฌ์œ„ ๊ตด๋ฆผ์„ 1๋กœ ๊ฐ•์ œํ•จ):

import Java from "frida-java-bridge";

Java.perform(function () {
var dicer = Java.use("org.secuso.privacyfriendlydicer.dicer.Dicer");
dicer.rollDice.implementation = function (numDice: number, numFaces: number) {
return Array(numDice).fill(1);
};
});

์ž„๋ฒ ๋”ฉ์šฉ ๋‹จ์ผ ๋ฒˆ๋“ค ๋นŒ๋“œ:

npm run build    # produces _agent.js via frida-compile

๋น ๋ฅธ USB ํ…Œ์ŠคํŠธ (์„ ํƒ ์‚ฌํ•ญ):

frida -U -f org.secuso.privacyfriendlydicer -l _agent.js
  1. Gadget๊ฐ€ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž๋™์œผ๋กœ ๋กœ๋“œํ•˜๋„๋ก ๊ตฌ์„ฑ Objection์˜ patcher๋Š” Gadget config๋ฅผ ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค; script mode๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” APK lib dir ๋‚ด๋ถ€์˜ on-disk path๋ฅผ ์ง€์ •ํ•˜์„ธ์š”:
{
"interaction": {
"type": "script",
"path": "libfrida-gadget.script.so"
}
}
  1. Objection์œผ๋กœ APK ํŒจ์น˜ ์ž๋™ํ™”
# Embed Gadget, config, and your compiled agent into the APK; rebuild and sign
objection patchapk -s org.secuso.privacyfriendlydicer.apk \
-c gadget-config.json \
-l mod/_agent.js \
--use-aapt2

What patchapk does (high level):

  • patchapk๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…(๊ฐœ์š”):
  • Detects device ABI (e.g., arm64-v8a) and fetches matching Gadget
  • ๋””๋ฐ”์ด์Šค ABI(์˜ˆ: arm64-v8a)๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์ผ์น˜ํ•˜๋Š” Gadget์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค
  • Optionally adds android.permission.INTERNET when needed
  • ํ•„์š”ํ•œ ๊ฒฝ์šฐ android.permission.INTERNET์„ ์„ ํƒ์ ์œผ๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค
  • Injects a static class initializer calling System.loadLibrary(โ€œfrida-gadgetโ€) into the launch activity
  • launch activity์— System.loadLibrary(โ€œfrida-gadgetโ€)๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ •์  ํด๋ž˜์Šค ์ดˆ๊ธฐํ™”์ž(static class initializer)๋ฅผ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค
  • Places the following under lib/<abi>/:
  • lib/<abi>/ ์•„๋ž˜์— ๋‹ค์Œ์„ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค:
  • libfrida-gadget.so
  • libfrida-gadget.config.so (serialized config)
  • libfrida-gadget.config.so (์ง๋ ฌํ™”๋œ config)
  • libfrida-gadget.script.so (your _agent.js)
  • libfrida-gadget.script.so (์‚ฌ์šฉ์ž์˜ _agent.js)

Example injected smali (static initializer): ์‚ฝ์ž…๋œ smali ์˜ˆ์ œ (์ •์  ์ดˆ๊ธฐํ™”์ž):

.method static constructor <clinit>()V
.locals 1
const-string v0, "frida-gadget"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
return-void
.end method
  1. repack์„ ๊ฒ€์ฆ
apktool d org.secuso.privacyfriendlydicer.apk
apktool d org.secuso.privacyfriendlydicer.objection.apk
# Inspect differences
diff -r org.secuso.privacyfriendlydicer org.secuso.privacyfriendlydicer.objection

์˜ˆ์ƒ๋˜๋Š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ:

  • AndroidManifest.xml์—๋Š” <uses-permission android:name="android.permission.INTERNET"/>๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
  • ์œ„์™€ ๊ฐ™์ด lib/<abi>/ ์•„๋ž˜์— ์ƒˆ๋กœ์šด ๋„ค์ดํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค
  • Launchable activity smali์—๋Š” System.loadLibrary(โ€œfrida-gadgetโ€)๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ •์  <clinit>๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค
  1. Split APKs
  • ๊ธฐ๋ณธ APK(MAIN/LAUNCHER activity๋ฅผ ์„ ์–ธํ•œ ๊ฒƒ)๋ฅผ ํŒจ์น˜ํ•ฉ๋‹ˆ๋‹ค
  • ๋‚˜๋จธ์ง€ split๋“ค์„ ๋™์ผํ•œ ํ‚ค๋กœ ์žฌ์„œ๋ช…ํ•ฉ๋‹ˆ๋‹ค:
objection signapk split1.apk split2.apk ...
  • splits๋ฅผ ํ•จ๊ป˜ ์„ค์น˜:
adb install-multiple split1.apk split2.apk ...
  • ๋ฐฐํฌ๋ฅผ ์œ„ํ•ด, APKEditor๋กœ split APK๋“ค์„ ํ•˜๋‚˜์˜ APK๋กœ ๋ณ‘ํ•ฉํ•œ ๋‹ค์Œ align/sign ํ•˜์„ธ์š”

๋™์  ๋ถ„์„ ์ค‘ FLAG_SECURE ํ•ด์ œ

getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE)๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์•ฑ์€ ์Šคํฌ๋ฆฐ์ƒท, ์›๊ฒฉ ๋””์Šคํ”Œ๋ ˆ์ด, ์‹ฌ์ง€์–ด Android์˜ ์ตœ๊ทผ ์ž‘์—… ์Šค๋ƒ…์ƒท๊นŒ์ง€ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค. Freedom Chat์ด ์ด ํ”Œ๋ž˜๊ทธ๋ฅผ ๊ฐ•์ œํ–ˆ์„ ๋•Œ leaks๋ฅผ ๋ฌธ์„œํ™”ํ•˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ ๋Ÿฐํƒ€์ž„์— ์œˆ๋„์šฐ๋ฅผ ๋ณ€์กฐํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ํŒจํ„ด์€:

  • ํ”Œ๋ž˜๊ทธ๋ฅผ ๋‹ค์‹œ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  Window ์˜ค๋ฒ„๋กœ๋“œ(setFlags, addFlags, setAttributes)๋ฅผ ํ›…ํ•˜๊ณ  ๋น„ํŠธ 0x00002000 (WindowManager.LayoutParams.FLAG_SECURE)๋ฅผ ๋งˆ์Šคํ‚นํ•˜์„ธ์š”.
  • ๊ฐ activity๊ฐ€ resume๋œ ํ›„์—๋Š” UI ์Šค๋ ˆ๋“œ์—์„œ clearFlags(FLAG_SECURE)๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ์˜ˆ์•ฝํ•˜์—ฌ ์ดํ›„ ์ƒ์„ฑ๋˜๋Š” Dialogs/Fragments๊ฐ€ ํ•ด์ œ๋œ ์ƒํƒœ๋ฅผ ์ƒ์†๋ฐ›๋„๋ก ํ•˜์„ธ์š”.
  • React Native / Flutter๋กœ ๋นŒ๋“œ๋œ ์•ฑ์€ ์ค‘์ฒฉ๋œ ์œˆ๋„์šฐ๋ฅผ ์ž์ฃผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค; ์ค‘์ฒฉ ์œˆ๋„์šฐ๊ฐ€ ๊ณ„์† ๊ฒ€์€ ํ™”๋ฉด์œผ๋กœ ๋ณด์ด๋ฉด android.app.Dialog/android.view.View ํ—ฌํผ๋ฅผ ํ›…ํ•˜๊ฑฐ๋‚˜ getWindow().peekDecorView()๋ฅผ ์ˆœํšŒํ•˜์„ธ์š”.
Frida hook clearing Window.FLAG_SECURE ```javascript Java.perform(function () { var LayoutParams = Java.use("android.view.WindowManager$LayoutParams"); var FLAG_SECURE = LayoutParams.FLAG_SECURE.value; var Window = Java.use("android.view.Window"); var Activity = Java.use("android.app.Activity");

function strip(value) { var masked = value & (~FLAG_SECURE); if (masked !== value) { console.log(โ€œ[-] Stripped FLAG_SECURE from 0xโ€ + value.toString(16)); } return masked; }

Window.setFlags.overload(โ€˜intโ€™, โ€˜intโ€™).implementation = function (flags, mask) { return this.setFlags.call(this, strip(flags), strip(mask)); };

Window.addFlags.implementation = function (flags) { return this.addFlags.call(this, strip(flags)); };

Window.setAttributes.implementation = function (attrs) { attrs.flags.value = strip(attrs.flags.value); return this.setAttributes.call(this, attrs); };

Activity.onResume.implementation = function () { this.onResume(); var self = this; Java.scheduleOnMainThread(function () { try { self.getWindow().clearFlags(FLAG_SECURE); console.log(โ€œ[+] Cleared FLAG_SECURE on โ€œ + self.getClass().getName()); } catch (err) { console.log(โ€[!] clearFlags failed: โ€œ + err); } }); }; });

</details>

`frida -U -f <package> -l disable-flag-secure.js --no-pause`๋กœ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  UI์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋ฉด ์Šคํฌ๋ฆฐ์ƒท/๋…นํ™”๊ฐ€ ๋‹ค์‹œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์ด UI ์Šค๋ ˆ๋“œ์—์„œ ๋ฐœ์ƒํ•˜๋ฏ€๋กœ ๊นœ๋นก์ž„์ด ์—†๊ณ , HTTP Toolkit/Burp์™€ ํ›…์„ ๊ฒฐํ•ฉํ•ด `/channel` PIN leak๋ฅผ ์œ ๋ฐœํ•œ ํŠธ๋ž˜ํ”ฝ์„ ์บก์ฒ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

## ํŠœํ† ๋ฆฌ์–ผ

### [Tutorial 1](frida-tutorial-1.md)

**์ถœ์ฒ˜**: [https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1](https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1)\
**APK**: [https://github.com/t0thkr1s/frida-demo/releases](https://github.com/t0thkr1s/frida-demo/releases)\
**์†Œ์Šค ์ฝ”๋“œ**: [https://github.com/t0thkr1s/frida-demo](https://github.com/t0thkr1s/frida-demo)

**์ฝ์œผ๋ ค๋ฉด [์ด ๋งํฌ](frida-tutorial-1.md)๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.**

### [Tutorial 2](frida-tutorial-2.md)

**์ถœ์ฒ˜**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (Parts 2, 3 & 4)\
**APKs ๋ฐ ์†Œ์Šค ์ฝ”๋“œ**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples)

**์ฝ์œผ๋ ค๋ฉด [์ด ๋งํฌ](frida-tutorial-2.md)๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.**

### [Tutorial 3](owaspuncrackable-1.md)

**์ถœ์ฒ˜**: [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1)\
**APK**: [https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk](https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk)

**์ฝ์œผ๋ ค๋ฉด [์ด ๋งํฌ](owaspuncrackable-1.md)๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.**

**๋” ๋งŽ์€ Awesome Frida ์Šคํฌ๋ฆฝํŠธ๋Š” ์—ฌ๊ธฐ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:** [**https://codeshare.frida.re/**](https://codeshare.frida.re)

## ๋น ๋ฅธ ์˜ˆ์ œ

### ๋ช…๋ น์ค„์—์„œ Frida ํ˜ธ์ถœํ•˜๊ธฐ
```bash
frida-ps -U

#Basic frida hooking
frida -l disableRoot.js -f owasp.mstg.uncrackable1

#Hooking before starting the app
frida -U --no-pause -l disableRoot.js -f owasp.mstg.uncrackable1
#The --no-pause and -f options allow the app to be spawned automatically,
#frozen so that the instrumentation can occur, and the automatically
#continue execution with our modified code.

๊ธฐ๋ณธ Python ์Šคํฌ๋ฆฝํŠธ

import frida, sys

jscode = open(sys.argv[0]).read()
process = frida.get_usb_device().attach('infosecadventures.fridademo')
script = process.create_script(jscode)
print('[ * ] Running Frida Demo application')
script.load()
sys.stdin.read()

Hooking ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋Š” ํ•จ์ˆ˜

ํด๋ž˜์Šค sg.vantagepoint.a.c์˜ ํ•จ์ˆ˜ a()๋ฅผ Hookํ•˜์„ธ์š”.

Java.perform(function () {
rootcheck1.a.overload().implementation = function () {
return false;
};
});

java์˜ exit() ํ›„ํ‚น

var sysexit = Java.use("java.lang.System")
sysexit.exit.overload("int").implementation = function (var_0) {
send("java.lang.System.exit(I)V  // We avoid exiting the application  :)")
}

Hook MainActivity .onStart() & .onCreate()

var mainactivity = Java.use("sg.vantagepoint.uncrackable1.MainActivity")
mainactivity.onStart.overload().implementation = function () {
send("MainActivity.onStart() HIT!!!")
var ret = this.onStart.overload().call(this)
}
mainactivity.onCreate.overload("android.os.Bundle").implementation = function (
var_0
) {
send("MainActivity.onCreate() HIT!!!")
var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0)
}

Hook android .onCreate()

var activity = Java.use("android.app.Activity")
activity.onCreate.overload("android.os.Bundle").implementation = function (
var_0
) {
send("Activity HIT!!!")
var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0)
}

Hooking๋œ ํ•จ์ˆ˜์—์„œ ํŒŒ๋ผ๋ฏธํ„ฐ ํ™•์ธ ๋ฐ ๋ฐ˜ํ™˜๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ

decryption function์„ Hookingํ•ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅ๊ฐ’์„ ์ถœ๋ ฅํ•˜๊ณ , ์›๋ณธ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด ์ž…๋ ฅ๊ฐ’์„ decryptํ•œ ๋’ค, ์ตœ์ข…์ ์œผ๋กœ ํ‰๋ฌธ ๋ฐ์ดํ„ฐ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค:

decryption function (Java) โ€” ์ž…๋ ฅ/์ถœ๋ ฅ ๋ณด๊ธฐ ```javascript function getString(data) { var ret = "" for (var i = 0; i < data.length; i++) { ret += data[i].toString() } return ret } var aes_decrypt = Java.use("sg.vantagepoint.a.a") aes_decrypt.a.overload("[B", "[B").implementation = function (var_0, var_1) { send("sg.vantagepoint.a.a.a([B[B)[B doFinal(enc) // AES/ECB/PKCS7Padding") send("Key : " + getString(var_0)) send("Encrypted : " + getString(var_1)) var ret = this.a.overload("[B", "[B").call(this, var_0, var_1) send("Decrypted : " + ret)

var flag = โ€œโ€ for (var i = 0; i < ret.length; i++) { flag += String.fromCharCode(ret[i]) } send(โ€œDecrypted flag: โ€œ + flag) return ret //[B }

</details>

### Hooking functions ๋ฐ ์šฐ๋ฆฌ ์ž…๋ ฅ์œผ๋กœ ํ˜ธ์ถœํ•˜๊ธฐ

string์„ ๋ฐ›๋Š” function์„ Hookํ•˜๊ณ  ๋‹ค๋ฅธ string์œผ๋กœ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค (from [here](https://11x256.github.io/Frida-hooking-android-part-2/))
```javascript
var string_class = Java.use("java.lang.String") // get a JS wrapper for java's String class

my_class.fun.overload("java.lang.String").implementation = function (x) {
//hooking the new function
var my_string = string_class.$new("My TeSt String#####") //creating a new String by using `new` operator
console.log("Original arg: " + x)
var ret = this.fun(my_string) // calling the original function with the new String, and putting its return value in ret variable
console.log("Return value: " + ret)
return ret
}

์ด๋ฏธ ์ƒ์„ฑ๋œ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด ๊ฐ€์ ธ์˜ค๊ธฐ

์ด๋ฏธ ์ƒ์„ฑ๋œ ๊ฐ์ฒด์˜ ์†์„ฑ ์ผ๋ถ€๋ฅผ ์ถ”์ถœํ•˜๋ ค๋ฉด ์ด๊ฒƒ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์˜ˆ์ œ์—์„œ๋Š” ํด๋ž˜์Šค my_activity์˜ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ , ๊ฐ์ฒด์˜ ๋น„๊ณต๊ฐœ ์†์„ฑ์„ ์ถœ๋ ฅํ•˜๋Š” .secret() ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค:

Java.choose("com.example.a11x256.frida_test.my_activity", {
onMatch: function (instance) {
//This function will be called for every instance found by frida
console.log("Found instance: " + instance)
console.log("Result of secret func: " + instance.secret())
},
onComplete: function () {},
})

๊ธฐํƒ€ Frida ํŠœํ† ๋ฆฌ์–ผ

์ฐธ๊ณ ์ž๋ฃŒ

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 ์ง€์›ํ•˜๊ธฐ