Frida Tutorial 3
Reading time: 5 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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
이 포스트의 요약: https://joshspicer.com/android-frida-1
APK: https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk
Solution 1
https://joshspicer.com/android-frida-1을 기반으로
_exit()_ 함수를 후킹하고 decrypt function을 사용하여 verify를 누를 때 flag를 frida 콘솔에 출력하도록 하세요:
Java.perform(function () {
send("Starting hooks OWASP uncrackable1...")
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 : " + getString(ret))
var flag = ""
for (var i = 0; i < ret.length; i++) {
flag += String.fromCharCode(ret[i])
}
send("Decrypted flag: " + flag)
return ret //[B
}
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 :)")
}
send("Hooks installed.")
})
Solution 2
Based in https://joshspicer.com/android-frida-1
루트 체크를 후킹하고 decrypt 함수를 수정하여 verify를 누를 때 frida 콘솔에 플래그를 출력하게 하세요:
Java.perform(function () {
send("Starting hooks OWASP uncrackable1...")
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 : " + getString(ret))
var flag = ""
for (var i = 0; i < ret.length; i++) {
flag += String.fromCharCode(ret[i])
}
send("Decrypted flag: " + flag)
return ret //[B
}
var rootcheck1 = Java.use("sg.vantagepoint.a.c")
rootcheck1.a.overload().implementation = function () {
send("sg.vantagepoint.a.c.a()Z Root check 1 HIT! su.exists()")
return false
}
var rootcheck2 = Java.use("sg.vantagepoint.a.c")
rootcheck2.b.overload().implementation = function () {
send("sg.vantagepoint.a.c.b()Z Root check 2 HIT! test-keys")
return false
}
var rootcheck3 = Java.use("sg.vantagepoint.a.c")
rootcheck3.c.overload().implementation = function () {
send("sg.vantagepoint.a.c.c()Z Root check 3 HIT! Root packages")
return false
}
var debugcheck = Java.use("sg.vantagepoint.a.b")
debugcheck.a.overload("android.content.Context").implementation = function (
var_0
) {
send("sg.vantagepoint.a.b.a(Landroid/content/Context;)Z Debug check HIT! ")
return false
}
send("Hooks installed.")
})
Solution 3 – frida-trace (Frida ≥ 16)
손으로 훅을 작성하고 싶지 않다면 Frida가 Java 스텁을 생성하도록 하고, 그 후에 수정할 수 있습니다:
# Spawn the application and automatically trace the Java method we care about
aadb shell "am force-stop owasp.mstg.uncrackable1"
frida-trace -U -f owasp.mstg.uncrackable1 \
-j 'sg.vantagepoint.a.a.a("[B","[B")[B' \
-j 'sg.vantagepoint.a.c!*' \
--output ./trace
# The first run will create ./trace/scripts/sg/vantagepoint/a/a/a__B_B_B.js
# Edit that file and add the logic that prints the decrypted flag or
# returns a constant for the root-checks, then:
frida -U -f owasp.mstg.uncrackable1 -l ./trace/_loader.js --no-pause
Frida 16+에서는 생성된 스텁이 이미 현대적인 ES6 템플릿 구문을 사용하며 내장된 QuickJS 런타임으로 컴파일됩니다 – 더 이상 frida-compile이 필요하지 않습니다.
Solution 4 – One-liner with Objection (2024)
Objection >1.12가 설치되어 있다면 단일 명령어로 플래그를 덤프할 수 있습니다 (Objection은 내부적으로 Frida를 래핑합니다):
objection -g owasp.mstg.uncrackable1 explore \
--startup-command "android hooking watch class sg.vantagepoint.a.a method a \n && android hooking set return_value false sg.vantagepoint.a.c * \n && android hooking invoke sg.vantagepoint.a.a a '[B' '[B'"
watch class는 AES 루틴에서 반환된 평문을 출력합니다.set return_value false는 모든 루트 / 디버거 검사가 false를 보고하도록 강제합니다.invoke는 Verify를 누르지 않고 메서드를 직접 호출할 수 있게 해줍니다.
NOTE: Android 14 (API 34)에서는 seccomp-bpf 제한으로 인해 attach가 차단되므로 Objection/Frida를 spawn 모드(
-f)로 실행해야 합니다.
현대 Android 노트 (2023 - 2025)
- libsu 5.x와 Zygisk는 su를 꽤 잘 숨기지만, Level 1의 Java 기반 검사는
/system/bin/su파일이 존재하면 여전히 실패합니다. denylist를 활성화하거나 Frida로java.io.File.exists()를 훅킹해야 합니다. - Frida 16.1은 Google의 Scudo 할당기로 인해 발생한 Android 12/13의 충돌을 수정했습니다.
Abort message: 'missing SHADOW_OFFSET'가 표시되면 Frida를 업그레이드하거나 미리 빌드된 17.0 야간 버전을 사용하세요. - Play Integrity가 2023년에 SafetyNet을 대체했기 때문에 일부 최신 앱은 com.google.android.gms.tasks.Task API를 호출합니다. Level 1은 그렇지 않지만, 여기서 보여준 동일한 훅킹 전략이 작동합니다 –
com.google.android.gms.safetynet.SafetyNetClient를 훅킹하고 위조된 EvaluationType을 반환하세요.
References
- Frida 릴리스 발표 – "Frida 16.0 (2023-04-02): Android 12/13 안정성 수정 및 spawn API 개편"
- Objection 1.12 – "Android 14를 위한 Spawn-only 모드" (BlackHat USA 2024 발표 슬라이드)
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을 제출하여 해킹 트릭을 공유하세요.
HackTricks