Android ์ํฐ ์ธ์คํธ๋ฃจ๋ฉํ ์ด์ & SSL Pinning ์ฐํ (Frida/Objection)
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์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
์ด ํ์ด์ง๋ Android ์ฑ์ด instrumentation์ ๊ฐ์ง/์ฐจ๋จํ๊ฑฐ๋ TLS pinning์ ์ ์ฉํ ๋ dynamic analysis๋ฅผ ๋ณต๊ตฌํ๊ธฐ ์ํ ์ค์ฉ์ ์ธ ์ํฌํ๋ก์ฐ๋ฅผ ์ ๊ณตํฉ๋๋ค. ๋น ๋ฅธ ๋ถ๋ฅ, ์ผ๋ฐ์ ์ธ ๊ฐ์ง ๊ธฐ๋ฒ, ๊ฐ๋ฅํ ๊ฒฝ์ฐ ์ฌํจํค์ง ์์ด ์ฐํํ ์ ์๋ ๋ณต์ฌยท๋ถ์ฌ๋ฃ๊ธฐ ๊ฐ๋ฅํ ํ /์ ์ ์ ์ค์ ์ ๋ก๋๋ค.
Detection Surface (์ฑ์ด ๊ฒ์ฌํ๋ ํญ๋ชฉ)
- Root checks: su binary, Magisk paths, getprop values, common root packages
- Frida/debugger checks (Java): Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), scanning /proc, classpath, loaded libs
- Native antiโdebug: ptrace(), syscalls, antiโattach, breakpoints, inline hooks
- Early init checks: Application.onCreate() or process start hooks that crash if instrumentation is present
- TLS pinning: custom TrustManager/HostnameVerifier, OkHttp CertificatePinner, Conscrypt pinning, native pins
Step 1 โ Quick win: Magisk DenyList๋ก ๋ฃจํธ ์จ๊ธฐ๊ธฐ
- Magisk์์ Zygisk ํ์ฑํ
- DenyList ํ์ฑํํ๊ณ ๋์ ํจํค์ง ์ถ๊ฐ
- ์ฌ๋ถํ ํ ์ฌ๊ฒ์ฆ
๋ง์ ์ฑ์ ๋ช ๋ฐฑํ ์งํ(su/Magisk ๊ฒฝ๋ก/getprop)๋ง ํ์ธํฉ๋๋ค. DenyList๋ ๋๊ฐ ๋จ์ํ ๊ฒ์ฌ๋ค์ ๋ฌด๋ ฅํํฉ๋๋ค.
References:
- Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk
Step 2 โ 30โsecond Frida Codeshare ํ ์คํธ
์ฌ์ธต ๋ถ์์ ๋ค์ด๊ฐ๊ธฐ ์ ์ ํํ ์ฌ์ฉํ๋ dropโin ์คํฌ๋ฆฝํธ๋ฅผ ์๋ํด๋ณด์ธ์:
- anti-root-bypass.js
- anti-frida-detection.js
- hide_frida_gum.js
Example:
frida -U -f com.example.app -l anti-frida-detection.js
์ด๋ค์ ์ผ๋ฐ์ ์ผ๋ก Java์ root/debug ์ฒดํฌ, ํ๋ก์ธ์ค/์๋น์ค ์ค์บ, ๊ทธ๋ฆฌ๊ณ ๋ค์ดํฐ๋ธ ptrace()๋ฅผ ์คํ ์ฒ๋ฆฌํฉ๋๋ค. ๋ณดํธ ์์ค์ด ๋ฎ์ ์ฑ์์๋ ์ ์ฉํ์ง๋ง, ๊ฐํ๋ ๋์์ ๋ง์ถคํ ํ ์ด ํ์ํ ์ ์์ต๋๋ค.
- Codeshare: https://codeshare.frida.re/
Medusa๋ก ์๋ํ (Frida framework)
Medusa๋ SSL unpinning, root/emulator detection bypass, HTTP comms logging, crypto key interception ๋ฑ์์ ์ฌ์ฉํ ์ ์๋ 90๊ฐ ์ด์์ ๊ธฐ์ฑ ๋ชจ๋์ ์ ๊ณตํฉ๋๋ค.
git clone https://github.com/Ch0pin/medusa
cd medusa
pip install -r requirements.txt
python medusa.py
# Example interactive workflow
show categories
use http_communications/multiple_unpinner
use root_detection/universal_root_detection_bypass
run com.target.app
ํ: Medusa๋ custom hooks๋ฅผ ์์ฑํ๊ธฐ ์ ์ ๋น ๋ฅธ ์ฑ๊ณผ๋ฅผ ์ป๊ธฐ์ ๋งค์ฐ ์ข์ต๋๋ค. ๋ชจ๋์ ์ ๋ณ(cherry-pick)ํ์ฌ ์์ฒด ์คํฌ๋ฆฝํธ์ ๊ฒฐํฉํ ์๋ ์์ต๋๋ค.
Step 3 โ ๋ฆ๊ฒ attachํ์ฌ init-time detectors๋ฅผ ์ฐํ
๋ง์ ํ์ง๋ค์ process spawn/onCreate() ๋์์๋ง ๋์ํฉ๋๋ค. Spawnโtime injection (-f)์ด๋ gadgets๋ ํ์ง๋ ์ ์๊ณ , UI๊ฐ ๋ก๋๋ ์ดํ์ attachingํ๋ฉด ์ฐํํ ์ ์์ต๋๋ค.
# Launch the app normally (launcher/adb), wait for UI, then attach
frida -U -n com.example.app
# Or with Objection to attach to running process
aobjection --gadget com.example.app explore # if using gadget
Step 4 โ Jadx์ string hunting์ ํตํด ํ์ง ๋ก์ง ๋งคํ
Jadx์์์ ์ ์ ๋ถ๋ฅ ํค์๋:
- โfridaโ, โgumโ, โrootโ, โmagiskโ, โptraceโ, โsuโ, โgetpropโ, โdebuggerโ
์ผ๋ฐ์ ์ธ Java ํจํด:
public boolean isFridaDetected() {
return getRunningServices().contains("frida");
}
๊ฒํ /ํํนํ ์ผ๋ฐ์ ์ธ API:
- android.os.Debug.isDebuggerConnected
- android.app.ActivityManager.getRunningAppProcesses / getRunningServices
- java.lang.System.loadLibrary / System.load (native bridge)
- java.lang.Runtime.exec / ProcessBuilder (probing commands)
- android.os.SystemProperties.get (root/emulator heuristics)
5๋จ๊ณ โ Frida (Java)๋ฅผ ์ฌ์ฉํ ๋ฐํ์ ์คํ ์ ์ฉ
repacking ์์ด ์ปค์คํ ๊ฐ๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ์ฌ ์์ ํ ๊ฐ์ ๋ฐํ:
Java.perform(() => {
const Checks = Java.use('com.example.security.Checks');
Checks.isFridaDetected.implementation = function () { return false; };
// Neutralize debugger checks
const Debug = Java.use('android.os.Debug');
Debug.isDebuggerConnected.implementation = function () { return false; };
// Example: kill ActivityManager scans
const AM = Java.use('android.app.ActivityManager');
AM.getRunningAppProcesses.implementation = function () { return java.util.Collections.emptyList(); };
});
์ด๊ธฐ ํฌ๋์๋ฅผ ๋ถ๋ฅ ์ค์ธ๊ฐ์? ์ข ๋ฃ ์ง์ ์ ํด๋์ค๋ฅผ ๋คํํ์ฌ ํ์ง ๊ฐ๋ฅ์ฑ์ด ๋์ ๋ค์์คํ์ด์ค๋ฅผ ์ฐพ์๋ณด์ธ์:
Java.perform(() => {
Java.enumerateLoadedClasses({
onMatch: n => console.log(n),
onComplete: () => console.log('Done')
});
});
// Quick root detection stub example (adapt to target package/class names) Java.perform(() => { try { const RootChecker = Java.use(โcom.target.security.RootCheckโ); RootChecker.isDeviceRooted.implementation = function () { return false; }; } catch (e) {} });
์คํ ํ๋ฆ์ ํ์ธํ๋ ค๋ฉด ์์ฌ์ค๋ฌ์ด ๋ฉ์๋๋ฅผ ๊ธฐ๋กํ๊ณ ๋ฌด๋ ฅํํ์ธ์:
Java.perform(() => {
const Det = Java.use('com.example.security.DetectionManager');
Det.checkFrida.implementation = function () {
console.log('checkFrida() called');
return false;
};
});
์๋ฎฌ๋ ์ดํฐ/VM ํ์ง ์ฐํ (Java stubs)
์ผ๋ฐ์ ์ธ ํด๋ฆฌ์คํฑ: Build.FINGERPRINT/MODEL/MANUFACTURER/HARDWARE ํ๋์ generic/goldfish/ranchu/sdk ํฌํจ; QEMU ์ํฐํฉํธ ์: /dev/qemu_pipe, /dev/socket/qemud; ๊ธฐ๋ณธ MAC 02:00:00:00:00:00; 10.0.2.x NAT; telephony/sensors๊ฐ ์์.
Build ํ๋์ ๋น ๋ฅธ ์คํธํ:
Java.perform(function(){
var Build = Java.use('android.os.Build');
Build.MODEL.value = 'Pixel 7 Pro';
Build.MANUFACTURER.value = 'Google';
Build.BRAND.value = 'google';
Build.FINGERPRINT.value = 'google/panther/panther:14/UP1A.231105.003/1234567:user/release-keys';
});
ํ์ผ ์กด์ฌ ๊ฒ์ฌ ๋ฐ ์๋ณ์ (TelephonyManager.getDeviceId/SubscriberId, WifiInfo.getMacAddress, SensorManager.getSensorList)์ ๋ํ ์คํ ์ ์ถ๊ฐํ์ฌ ํ์ค์ ์ธ ๊ฐ์ ๋ฐํํ๋๋ก ๋ณด์ํ์ธ์.
SSL pinning bypass quick hook (Java)
์ฌ์ฉ์ ์ ์ TrustManagers๋ฅผ ๋ฌด๋ ฅํํ๊ณ permissive SSL contexts๋ฅผ ๊ฐ์ ํ์ธ์:
Java.perform(function(){
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
var SSLContext = Java.use('javax.net.ssl.SSLContext');
// No-op validations
X509TrustManager.checkClientTrusted.implementation = function(){ };
X509TrustManager.checkServerTrusted.implementation = function(){ };
// Force permissive TrustManagers
var TrustManagers = [ X509TrustManager.$new() ];
var SSLContextInit = SSLContext.init.overload('[Ljavax.net.ssl.KeyManager;','[Ljavax.net.ssl.TrustManager;','java.security.SecureRandom');
SSLContextInit.implementation = function(km, tm, sr){
return SSLContextInit.call(this, km, TrustManagers, sr);
};
});
์ฐธ๊ณ
- OkHttp ํ์ฅ: ํ์์ ๋ฐ๋ผ okhttp3.CertificatePinner์ HostnameVerifier๋ฅผ hookํ๊ฑฐ๋ CodeShare์ universal unpinning script๋ฅผ ์ฌ์ฉํ์ธ์.
- ์คํ ์์:
frida -U -f com.target.app -l ssl-bypass.js --no-pause
Step 6 โ Java hooks๊ฐ ์คํจํ ๋ JNI/native ํ์ ์ ๋ฐ๋ผ๊ฐ์ธ์
JNI ์ํธ๋ฆฌ ํฌ์ธํธ๋ฅผ ์ถ์ ํด native loaders์ detection init์ ์ฐพ์๋ณด์ธ์:
frida-trace -n com.example.app -i "JNI_OnLoad"
๋ฒ๋ค๋ .so ํ์ผ์ ๋น ๋ฅธ ๋ค์ดํฐ๋ธ ์ ๋ณ:
# List exported symbols & JNI
nm -D libfoo.so | head
objdump -T libfoo.so | grep Java_
strings -n 6 libfoo.so | egrep -i 'frida|ptrace|gum|magisk|su|root'
์ธํฐ๋ํฐ๋ธ/๋ค์ดํฐ๋ธ ๋ฆฌ๋ฒ์ฑ:
- Ghidra: https://ghidra-sre.org/
- r2frida: https://github.com/nowsecure/r2frida
์: ptrace๋ฅผ ๋ฌด๋ ฅํํ์ฌ libc์ ๊ฐ๋จํ antiโdebug๋ฅผ ์ฐํ:
const ptrace = Module.findExportByName(null, 'ptrace');
if (ptrace) {
Interceptor.replace(ptrace, new NativeCallback(function () {
return -1; // pretend failure
}, 'int', ['int', 'int', 'pointer', 'pointer']));
}
์ฐธ๊ณ : Reversing Native Libraries
๋จ๊ณ 7 โ Objection patching (embed gadget / strip basics)
runtime hooks ๋์ repacking์ ์ ํธํ๋ค๋ฉด, ์๋ํด๋ณด์ธ์:
objection patchapk --source app.apk
Notes:
- apktool ํ์; ๋น๋ ๋ฌธ์ ๋ฅผ ํผํ๋ ค๋ฉด ๊ณต์ ๊ฐ์ด๋์์ ์ต์ ๋ฒ์ ์ ์ฌ์ฉํ์ธ์: https://apktool.org/docs/install
- Gadget injection์ ๋ฃจํธ ์์ด instrumentation์ ๊ฐ๋ฅํ๊ฒ ํ์ง๋ง, ์ฌ์ ํ ๋ ๊ฐ๋ ฅํ initโtime ๊ฒ์ฌ์ ์ํด ํ์ง๋ ์ ์์ต๋๋ค.
์ ํ์ ์ผ๋ก LSPosed ๋ชจ๋๊ณผ Shamiko๋ฅผ ์ถ๊ฐํ์ฌ Zygisk ํ๊ฒฝ์์ ๋ ๊ฐ๋ ฅํ๊ฒ ๋ฃจํธ ์จ๊น์ ํ๊ณ , DenyList๋ฅผ ์กฐ์ ํ์ฌ ์์ ํ๋ก์ธ์ค๊น์ง ํฌํจํ์ธ์.
For a complete workflow including script-mode Gadget configuration and bundling your Frida 17+ agent into the APK, see:
Frida Tutorial โ Self-contained agent + Gadget embedding
References:
- Objection: https://github.com/sensepost/objection
Step 8 โ ํด๋ฐฑ: ๋คํธ์ํฌ ๊ฐ์์ฑ ํ๋ณด๋ฅผ ์ํ TLS pinning ํจ์น
instrumentation์ด ์ฐจ๋จ๋๋ฉด, pinning์ ์ ์ ์ผ๋ก ์ ๊ฑฐํ์ฌ ํธ๋ํฝ์ ์ฌ์ ํ ๊ฒ์ฌํ ์ ์์ต๋๋ค:
apk-mitm app.apk
# Then install the patched APK and proxy via Burp/mitmproxy
- ๋๊ตฌ: https://github.com/shroudedcode/apk-mitm
- ๋คํธ์ํฌ ๊ตฌ์ฑ CAโtrust ํธ๋ฆญ(๋ฐ Android 7+ user CA trust)์ ๋ํด์๋ ๋ค์์ ์ฐธ์กฐ:
Make APK Accept CA Certificate
์ ์ฉํ ๋ช ๋ น์ด ์นํธ์ํธ
# List processes and attach
frida-ps -Uai
frida -U -n com.example.app
# Spawn with a script (may trigger detectors)
frida -U -f com.example.app -l anti-frida-detection.js
# Trace native init
frida-trace -n com.example.app -i "JNI_OnLoad"
# Objection runtime
objection --gadget com.example.app explore
# Static TLS pinning removal
apk-mitm app.apk
๋ฒ์ฉ proxy ๊ฐ์ ํ + TLS unpinning (HTTP Toolkit Frida hooks)
์ต์ ์ฑ๋ค์ ์ข ์ข system proxies๋ฅผ ๋ฌด์ํ๊ณ pinning(Java + native)์ ์ฌ๋ฌ ๋ ์ด์ด๋ฅผ ์ ์ฉํด, user/system CAs๊ฐ ์ค์น๋์ด ์์ด๋ ํธ๋ํฝ ์บก์ฒ๊ฐ ๋งค์ฐ ์ด๋ ค์์ง๋๋ค. ์ค๋ฌด์ ์ผ๋ก๋ ๋ฒ์ฉ TLS unpinning๊ณผ ์ค๋น๋ Frida hooks๋ฅผ ํตํ proxy ๊ฐ์ ํ๋ฅผ ๊ฒฐํฉํ๊ณ ๋ชจ๋ ํธ๋ํฝ์ mitmproxy/Burp๋ก ๋ผ์ฐํ ํ๋ ๋ฐฉ๋ฒ์ด ํจ๊ณผ์ ์ ๋๋ค.
Workflow
- ํธ์คํธ์์ mitmproxy(๋๋ Burp)๋ฅผ ์คํํฉ๋๋ค. ๋๋ฐ์ด์ค๊ฐ ํธ์คํธ IP/ํฌํธ์ ์ ๊ทผ ๊ฐ๋ฅํ์ง ํ์ธํ์ธ์.
- HTTP Toolkit์ ํตํฉ Frida hooks๋ฅผ ๋ก๋ํ์ฌ TLS unpinning๊ณผ OkHttp/OkHttp3, HttpsURLConnection, Conscrypt, WebView ๋ฑ ์ผ๋ฐ ์คํ ์ ๋ฐ์ ๋ํ proxy ์ฌ์ฉ ๊ฐ์ ํ๋ฅผ ์ํํฉ๋๋ค. ์ด ์คํฌ๋ฆฝํธ๋ CertificatePinner/TrustManager ๊ฒ์ฌ๋ฅผ ์ฐํํ๊ณ proxy selectors๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ๋ฏ๋ก, ์ฑ์ด ๋ช ์์ ์ผ๋ก proxy๋ฅผ ๋นํ์ฑํํด๋ ํธ๋ํฝ์ด ํญ์ ๋น์ ์ proxy๋ฅผ ํตํด ์ ์ก๋ฉ๋๋ค.
- Frida์ ํ ์คํฌ๋ฆฝํธ๋ก ๋์ ์ฑ์ ์์ํ ๋ค mitmproxy์์ ์์ฒญ์ ์บก์ฒํ์ธ์.
Example
# Device connected via ADB or over network (-U)
# See the repo for the exact script names & options
frida -U -f com.vendor.app \
-l ./android-unpinning-with-proxy.js \
--no-pause
# mitmproxy listening locally
mitmproxy -p 8080
๋ ธํธ
- ๊ฐ๋ฅํ ๊ฒฝ์ฐ ์์คํ
์ ์ฒด ํ๋ก์์ ํจ๊ป ์ฌ์ฉํ์ธ์:
adb shell settings put global http_proxy <host>:<port>. Frida ํํฌ๋ ์ฑ์ด ๊ธ๋ก๋ฒ ์ค์ ์ ์ฐํํ ๋์๋ ํ๋ก์ ์ฌ์ฉ์ ๊ฐ์ ํฉ๋๋ค. - ์ด ๊ธฐ์ ์ pinning/proxy ํํผ๊ฐ ํํ ๋ชจ๋ฐ์ผโIoT ์จ๋ณด๋ฉ ํ๋ก์ฐ๋ฅผ MITMํด์ผ ํ ๋ ์ด์์ ์ ๋๋ค.
- Hooks: https://github.com/httptoolkit/frida-interception-and-unpinning
References
- Reversing Android Apps: Bypassing Detection Like a Pro
- Frida Codeshare
- Objection
- apk-mitm
- Jadx
- Ghidra
- r2frida
- Apktool install guide
- Magisk
- Medusa (Android Frida framework)
- Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa
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์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


