Translated ['', 'src/mobile-pentesting/android-app-pentesting/android-an

This commit is contained in:
Translator 2025-09-08 01:58:29 +00:00
parent 625ef25b4e
commit 3c9e5d80e5
5 changed files with 611 additions and 403 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2,9 +2,9 @@
{{#include ../../banners/hacktricks-training.md}}
이 페이지는 instrumentation을 탐지/차단하거나 TLS pinning을 적용하는 Android 앱에 대해 dynamic analysis를 다시 수행할 수 있도록 실용적인 워크플로우를 제공합니다. 빠른 분류, 흔한 탐지 기법, 그리고 가능하면 repacking 없이 우회할 수 있는 복사·붙여넣기 가능한 hooks/전술에 중점을 둡니다.
이 페이지는 instrumentation을 탐지하거나 루트 차단을 수행하거나 TLS pinning을 강제하는 Android 앱에 대해 dynamic analysis를 복원하기 위한 실용적인 워크플로를 제공합니다. 가능한 경우 재패키징 없이 우회할 수 있는 빠른 분류, 일반적인 탐지 항목, 복사-붙여넣기 가능한 hooks/tactics에 중점을 둡니다.
## Detection Surface (what apps check)
## 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
@ -18,14 +18,14 @@
- Enable DenyList, add the target package
- Reboot and retest
많은 앱은 su/Magisk 경로/getprop 같은 명확한 지표만 확인합니다. DenyList는 종종 이런 단순한 검사들을 무력화합니다.
많은 앱은 su/Magisk 경로/getprop 같은 명백한 지표만 확인합니다. DenyList는 종종 단순한 검사들을 무력화합니다.
References:
- Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk
## Step 2 — 30second Frida Codeshare tests
딥다이브 전에 흔히 쓰이는 dropin 스크립트를 먼저 시도해 보세요:
심층 분석에 들어가기 전에 자주 쓰이는 dropin 스크립트를 먼저 시도해보세요:
- anti-root-bypass.js
- anti-frida-detection.js
@ -35,33 +35,50 @@ Example:
```bash
frida -U -f com.example.app -l anti-frida-detection.js
```
이들은 일반적으로 Java의 root/debug checks, process/service scans, 그리고 native ptrace()를 스텁 처리합니다. 경미하게 보호된 앱에서 유용하지만, 강화된 대상은 맞춤형 훅이 필요할 수 있습니다.
이들은 일반적으로 Java의 root/debug checks, process/service scans, 그리고 네이티브 ptrace()를 스텁합니다. 보호가 약한 앱에서는 유용하지만, 강화된 대상은 맞춤형 hooks가 필요할 수 있습니다.
- Codeshare: https://codeshare.frida.re/
## Step 3 — init-time detectors를 늦게 attach하여 우회하기
## Medusa로 자동화하기 (Frida framework)
많은 탐지들은 process spawn/onCreate() 동안에만 동작합니다. Spawntime injection (-f)이나 gadgets는 차단되므로, UI가 로드된 이후에 attach하면 우회할 수 있습니다.
Medusa는 SSL unpinning, root/emulator detection bypass, HTTP comms logging, crypto key interception 등 90개 이상의 기성 모듈을 제공합니다.
```bash
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는 커스텀 hooks를 작성하기 전에 빠른 성과를 얻기에 좋습니다. 모듈을 선별해서 자신의 scripts와 결합할 수도 있습니다.
## Step 3 — init-time 탐지기를 늦게 attach하여 우회하기
많은 탐지는 process spawn/onCreate() 동안에만 실행됩니다. Spawntime injection (-f)이나 gadgets는 잡히기 쉽고, UI가 로드된 이후에 attach하면 우회할 수 있습니다.
```bash
# 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
```
이 방법이 작동하면 세션을 안정적으로 유지한 뒤 map 및 stub checks로 진행하세요.
이 방법이 작동하면 세션을 안정적으로 유지하고 매핑 및 스텁 검사로 진행하세요.
## Step 4 — Jadx와 string hunting을 통해 탐지 로직 매핑
## 단계 4 — Jadx 및 문자열 검색을 통한 탐지 로직 매핑
Static triage keywords in Jadx:
Jadx에서의 정적 트리아지 키워드:
- "frida", "gum", "root", "magisk", "ptrace", "su", "getprop", "debugger"
Typical Java patterns:
일반적인 Java 패턴:
```java
public boolean isFridaDetected() {
return getRunningServices().contains("frida");
}
```
검토/hook할 공통 API:
검토/hook할 일반 API:
- android.os.Debug.isDebuggerConnected
- android.app.ActivityManager.getRunningAppProcesses / getRunningServices
- java.lang.System.loadLibrary / System.load (native bridge)
@ -70,7 +87,7 @@ return getRunningServices().contains("frida");
## 5단계 — Runtime stubbing with Frida (Java)
repacking 없이 안전한 값을 반환하도록 커스텀 가드를 오버라이드:
커스텀 가드를 오버라이드하여 리패킹 없이 안전한 값을 반환하도록:
```js
Java.perform(() => {
const Checks = Java.use('com.example.security.Checks');
@ -85,7 +102,7 @@ const AM = Java.use('android.app.ActivityManager');
AM.getRunningAppProcesses.implementation = function () { return java.util.Collections.emptyList(); };
});
```
초기 크래시를 분류하고 있나요? 앱이 죽기 직전에 classes를 덤프해서 탐지 가능성이 높은 네임스페이스를 찾아보세요:
초기 crashes를 분류하고 있나요? 종료되기 직전에 Dump classes를 해서 잠재적 detection namespaces를 찾아보세요:
```js
Java.perform(() => {
Java.enumerateLoadedClasses({
@ -94,6 +111,14 @@ 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) {}
});
실행 흐름을 확인하기 위해 의심스러운 메서드를 로깅하고 무력화하세요:
```js
Java.perform(() => {
@ -104,24 +129,65 @@ return false;
};
});
```
## Step 6 — Java hooks가 실패할 때 JNI/native 경로를 따라가세요
## 에뮬레이터/VM 탐지 우회 (Java stubs)
JNI entry points를 추적하여 native loaders와 detection init을 찾아보세요:
일반적인 휴리스틱:
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 필드를 빠르게 spoof:
```js
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를 강제합니다:
```js
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);
};
});
```
Notes
- OkHttp에 대해 확장: 필요에 따라 hook okhttp3.CertificatePinner 및 HostnameVerifier를 적용하거나, CodeShare의 범용 unpinning script를 사용하세요.
- 실행 예: `frida -U -f com.target.app -l ssl-bypass.js --no-pause`
## 단계 6 — Java hooks가 실패할 때 JNI/native 트레일을 추적
JNI 진입점을 추적하여 native 로더와 탐지 초기화(detection init)를 찾아보세요:
```bash
frida-trace -n com.example.app -i "JNI_OnLoad"
```
번들된 .so 파일의 빠른 네이티브 분류:
번들된 .so 파일의 빠른 네이티브 선별:
```bash
# 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'
```
인터랙티브/네이티브 reversing:
Interactive/native reversing:
- Ghidra: https://ghidra-sre.org/
- r2frida: https://github.com/nowsecure/r2frida
예시: ptrace를 무력화하여 libc의 간단한 antidebug를 무력화:
: neuter ptrace to defeat simple antidebug in libc:
```js
const ptrace = Module.findExportByName(null, 'ptrace');
if (ptrace) {
@ -137,26 +203,28 @@ reversing-native-libraries.md
## 7단계 — Objection patching (embed gadget / strip basics)
repacking을 runtime hooks보다 선호한다면, 시도해보세요:
repacking을 runtime hooks 대신 선호한다면, 다음을 시도해보세요:
```bash
objection patchapk --source app.apk
```
참고:
- apktool 필요합니다; 빌드 문제를 피하려면 공식 가이드에서 최신 버전을 사용하세요: https://apktool.org/docs/install
- Gadget injection은 root 없이 instrumentation을 가능하게 하지만 더 강력한 inittime 검사에는 여전히 감지될 수 있습니다.
Notes:
- apktool 필요; 빌드 문제를 피하려면 공식 가이드에서 최신 버전을 사용하십시오: https://apktool.org/docs/install
- Gadget injection은 root 없이 instrumentation을 가능하게 하지만 더 강력한 inittime 검사에 의해 여전히 탐지될 수 있습니다.
참조:
선택적으로, Zygisk 환경에서 더 강력한 root 숨김을 위해 LSPosed 모듈과 Shamiko를 추가하고, 자식 프로세스를 포함하도록 DenyList를 조정하세요.
References:
- Objection: https://github.com/sensepost/objection
## Step 8 — 대체 방법: 네트워크 가시성 확보를 위해 TLS pinning 패치
## Step 8 — Fallback: Patch TLS pinning for network visibility
instrumentation이 차단된 경우, pinning을 정적으로 제거해서 트래픽을 여전히 검사할 수 있습니다:
If instrumentation is blocked, you can still inspect traffic by removing pinning statically:
```bash
apk-mitm app.apk
# Then install the patched APK and proxy via Burp/mitmproxy
```
- 도구: https://github.com/shroudedcode/apk-mitm
- 네트워크 구성 CAtrust tricks (및 Android 7+ user CA trust)에 대해서는 다음을 참조:
- 네트워크 구성 CAtrust 트릭(및 Android 7+ user CA trust)은 다음을 참조하세요:
{{#ref}}
make-apk-accept-ca-certificate.md
@ -186,10 +254,10 @@ apk-mitm app.apk
```
## 팁 및 주의사항
- 앱이 실행 시 crash할 경우 spawning 대신 attaching을 늦게 적용하는 것을 권장합니
- 일부 detections는 결제(payment), 인증(auth) 같은 중요한 흐름에서 재실행됩니다 — navigation 동안 hooks를 활성 상태로 유지하세요
- static과 dynamic을 혼합하세요: Jadx에서 string hunt로 shortlist classes를 찾아낸 뒤 hook methods로 runtime에서 검증하세요
- 하드닝된 앱은 packers와 native TLS pinning을 사용할 수 있으므로 native code를 reverse해야 할 것으로 예상하세요
- 앱이 런치 시 크래시할 경우 spawn하기보다 늦게 attach하는 것이 좋
- 일부 detections는 중요한 흐름(예: payment, auth)에서 다시 실행될 수 있으므로 navigation 중에는 hooks를 활성 상태로 유지하라
- static과 dynamic을 혼합하라: Jadx에서 string을 찾아 클래스를 추려낸 다음, runtime에서 검증하기 위해 메서드에 hook를 걸어라
- 보안이 강화된 앱은 packers와 native TLS pinning을 사용할 수 있으므로 native 코드를 리버스해야 할 것으로 예상하라
## References
@ -202,5 +270,7 @@ apk-mitm app.apk
- [r2frida](https://github.com/nowsecure/r2frida)
- [Apktool install guide](https://apktool.org/docs/install)
- [Magisk](https://github.com/topjohnwu/Magisk)
- [Medusa (Android Frida framework)](https://github.com/Ch0pin/medusa)
- [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,25 +2,25 @@
{{#include ../../banners/hacktricks-training.md}}
이 콘텐츠를 만드는 데 도움을 주신 [**@offsecjay**](https://twitter.com/offsecjay)에게 매우 감사드립니다.
이 콘텐츠 작성에 도움을 주신 [**@offsecjay**](https://twitter.com/offsecjay)께 감사드립니다.
## What is
## 무엇인가
Android Studio는 **APK를 테스트하는 데 사용할 수 있는 Android의 가상 머신을 실행할 수 있게 해줍니다**. 이를 사용하기 위해서는 다음이 필요합니다:
Android Studio는 Android 가상 머신을 **실행할 수 있게 해주며, 이를 통해 APKs를 테스트할 수 있습니다**. 이를 사용하려면 다음이 필요합니다:
- **Android SDK 도구** - [여기에서 다운로드](https://developer.android.com/studio/releases/sdk-tools).
- 또는 **Android Studio** (Android SDK 도구 포함) - [여기에서 다운로드](https://developer.android.com/studio).
- The **Android SDK tools** - [Download here](https://developer.android.com/studio/releases/sdk-tools).
- Or **Android Studio** (with Android SDK tools) - [Download here](https://developer.android.com/studio).
Windows에서는 (제 경우) **Android Studio를 설치한 후** **SDK 도구가**: `C:\Users\<UserName>\AppData\Local\Android\Sdk\tools`에 설치되었습니다.
Windows(제 경우)에서 **Android Studio를 설치한 후** **SDK Tools는 다음 경로에 설치되어 있었습니다**: `C:\Users\<UserName>\AppData\Local\Android\Sdk\tools`
mac에서는 **SDK 도구를 다운로드**하고 PATH에 추가할 수 있습니다:
mac에서는 **SDK tools를 다운로드**하고 PATH에 추가하려면 다음을 실행하세요:
```bash
brew tap homebrew/cask
brew install --cask android-sdk
```
**Android Studio GUI**에서 [https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a](https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a)에서 언급된 대로 설치하면 `~/Library/Android/sdk/cmdline-tools/latest/bin/` `~/Library/Android/sdk/platform-tools/``~/Library/Android/sdk/emulator/`에 설치됩니다.
또는 **Android Studio GUI**에서 [https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a](https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a)에 표시된 것처럼 설치할 수 있으며, 이는 `~/Library/Android/sdk/cmdline-tools/latest/bin/` `~/Library/Android/sdk/platform-tools/``~/Library/Android/sdk/emulator/`에 설치됩니다
Java 문제에 대한:
Java 문제의 경우:
```java
export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jbr/Contents/Home
```
@ -28,7 +28,7 @@ export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jbr/Contents/Home
### 가상 머신 준비
Android Studio를 설치했다면, 메인 프로젝트 뷰를 열고 다음 경로로 접근할 수 있습니다: _**Tools**_ --> _**AVD Manager.**_
Android Studio를 설치했다면, 메인 프로젝트 뷰를 열고 다음로 접근할 수 있습니다: _**Tools**_ --> _**AVD Manager.**_
<div align="center" data-full-width="false">
@ -36,38 +36,38 @@ Android Studio를 설치했다면, 메인 프로젝트 뷰를 열고 다음 경
</div>
그런 다음, _**Create Virtual Device**_를 클릭합니다.
그런 다음 _**Create Virtual Device**_ 를 클릭하세요
<figure><img src="../../images/image (1143).png" alt="" width="188"><figcaption></figcaption></figure>
_**사용할** 전화기를 선택_하고 _**Next.**_를 클릭합니다.
_**사용할 phone을 선택하세요**_ 그리고 _**Next.**_ 를 클릭하세요
> [!WARNING]
> Play Store가 설치된 전화기가 필요하다면 Play Store 아이콘이 있는 것을 선택하세요!
> Play Store가 설치된 phone이 필요하면 Play Store 아이콘이 있는 항목을 선택하세요!
>
> <img src="../../images/image (1144).png" alt="" data-size="original">
현재 뷰에서 **전화기가 실행할 Android 이미지를 선택하고 다운로드**할 수 있습니다:
현재 화면에서 **폰이 실행할 Android image를 선택하고 다운로드**할 수 있습니다:
<figure><img src="../../images/image (1145).png" alt="" width="375"><figcaption></figcaption></figure>
따라서 선택하고 다운로드되지 않았다면 이름 옆의 _**Download**_ 기호를 클릭하세요 (**이제 이미지가 다운로드될 때까지 기다리세요).**\
이미지가 다운로드되면 **`Next`****`Finish`**를 선택합니다.
이미지를 선택하고 아직 다운로드되지 않은 경우 이름 옆의 _**Download**_ 아이콘을 클릭하세요 (**이미지가 다운로드될 때까지 기다리세요).**\
이미지가 다운로드되면 **`Next`****`Finish`** 를 선택하면 됩니다.
가상 머신이 생성됩니다. 이제 **AVD 관리자를 접근할 때마다 항상 존재할 것입니다**.
가상 머신이 생성됩니다. 이제 **AVD Manager에 접근할 때마다 해당 가상 머신이 표시됩니다**.
### 가상 머신 실행
**실행**하려면 _**Start button**_을 누르세요.
실행하려면 _**Start button**_ 을 누르기만 하면 됩니다.
![](<../../images/image (518).png>)
## 명령줄 도구
> [!WARNING]
> macOS의 경우 `avdmanager` 도구는 `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager`에, `emulator``/Users/<username>/Library/Android/sdk/emulator/emulator`에 있습니다. 설치되어 있다면 찾을 수 있습니다.
> macOS의 경우 `avdmanager` 도구는 `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager`에, `emulator``/Users/<username>/Library/Android/sdk/emulator/emulator`에 있습니다(설치된 경우).
먼저 **사용할 전화기를 결정**해야 합니다. 가능한 전화기 목록을 보려면 다음을 실행하세요:
먼저 **어떤 phone을 사용할지 결정**해야 하므로, 사용 가능한 phone 목록을 보려면 실행하세요:
```
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list device
@ -95,16 +95,16 @@ Name: Nexus 10
OEM : Google
[...]
```
장치의 이름을 결정한 후, **이 장치에서 실행할 Android 이미지를 결정해야 합니다.**\
`sdkmanager`를 사용하여 모든 옵션을 나열할 수 있습니다:
사용할 디바이스의 이름을 결정했으면, 이 디바이스에서 어떤 Android 이미지를 실행할지 **결정해야 합니다.**\
모든 옵션은 `sdkmanager`를 사용해 나열할 수 있습니다:
```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat --list
```
그리고 **다운로드** 하세요 사용하고 싶은 것(또는 모두)을:
그리고 사용하려는 것(또는 모두)을 다음 명령으로 **다운로드**하세요:
```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat "platforms;android-28" "system-images;android-28;google_apis;x86_64"
```
다운로드한 Android 이미지를 사용하려면 다음 명령어로 **다운로드한 모든 Android 이미지를 나열할 수 있습니다**:
원하는 Android 이미지를 다운로드한 후 다음 명령어로 **다운로드된 모든 Android 이미지를 나열**할 수 있습니다:
```
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list target
----------
@ -120,12 +120,12 @@ Type: Platform
API level: 29
Revision: 4
```
이제 사용하려는 장치를 결정하고 Android 이미지를 다운로드했으므로 **다음과 같이 가상 머신을 생성할 수 있습니다**:
이제 사용할 디바이스를 결정하고 Android 이미지를 다운로드했으므로, **다음 방법으로 가상 머신을 생성할 수 있습니다**:
```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat -v create avd -k "system-images;android-28;google_apis;x86_64" -n "AVD9" -d "Nexus 5X"
```
마지막 명령어에서 **"_AVD9_"라는 이름의 VM을 생성했습니다** **"_Nexus 5X_"** **장치**와 **"_system-images;android-28;google_apis;x86_64_"** **안드로이드 이미지**를 사용하여.\
이제 다음 명령어로 생성한 가상 머신을 **목록화할 수 있습니다**:
이전 명령에서 **VM 이름을 _AVD9_로 생성했습니다** **장치** "_Nexus 5X_" 및 **Android image** "_system-images;android-28;google_apis;x86_64_"를 사용하여.\
이제 **생성한 virtual machines를 나열**하려면:
```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list avd
@ -143,73 +143,128 @@ Error: Google pixel_2 no longer exists as a device
### 가상 머신 실행
> [!WARNING]
> macOS의 경우 `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager`에서 `avdmanager` 도구를 찾을 수 있으며, 설치되어 있다면 `/Users/<username>/Library/Android/sdk/emulator/emulator`에서 `emulator` 찾을 수 있습니다.
> macOS의 경우, 설치되어 있다면 `avdmanager` 도구를 `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager`에서, `emulator` `/Users/<username>/Library/Android/sdk/emulator/emulator`에서 찾을 수 있습니다.
우리는 이미 생성된 가상 머신을 나열하는 방법을 보았지만, **다음과 같이 나열할 수도 있습니다**:
생성된 가상 머신을 나열하는 방법은 이미 살펴보았지만, **다음 명령을 사용해 나열할 수도 있습니다**:
```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -list-avds
AVD9
Pixel_2_API_27
```
당신은 다음을 사용하여 **생성된 모든 가상 머신을 간단히 실행할 수 있습니다**:
다음을 사용하여 생성된 **모든 가상 머신을 간단히 실행할 수 있습니다**:
```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "VirtualMachineName"
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9"
```
더 고급 옵션을 사용하여 다음과 같은 가상 머신을 실행할 수 있습니다:
또는 더 고급 옵션을 사용하면 다음과 같은 가상 머신을 실행할 수 있습니다:
```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system
```
### Command line options
### 명령줄 옵션
그러나 **가상 머신을 시작하는 데 유용한 다양한 명령줄 옵션이 많이 있습니다**. 아래에서 몇 가지 흥미로운 옵션을 찾을 수 있지만 [**여기에서 전체 목록을 찾을 수 있습니다**](https://developer.android.com/studio/run/emulator-commandline)
하지만 VM을 시작할 때 사용할 수 있는 **다양한 유용한 명령줄 옵션이 많이 있습니다**. 아래에 몇 가지 흥미로운 옵션을 찾을 수 있으며, 전체 목록은 [**여기**](https://developer.android.com/studio/run/emulator-commandline)에서 확인할 수 있습니다.
**Boot**
- `-snapshot name` : VM 스냅샷 시작
- `-snapshot name` : VM 스냅샷 시작
- `-snapshot-list -snapstorage ~/.android/avd/Nexus_5X_API_23.avd/snapshots-test.img` : 기록된 모든 스냅샷 나열
**Network**
- `-dns-server 192.0.2.0, 192.0.2.255` : VM에 DNS 서버를 쉼표로 구분하여 지정할 수 있습니다.
- **`-http-proxy 192.168.1.12:8080`** : 사용할 HTTP 프록시를 지정할 수 있습니다 (Burp를 사용하여 트래픽을 캡처하는 데 매우 유용함).
- 프록시 설정이 어떤 이유로 작동하지 않는 경우, 내부적으로 구성하거나 "Super Proxy" 또는 "ProxyDroid"와 같은 애플리케이션을 사용해 보십시오.
- `-netdelay 200` : 밀리초 단위로 네트워크 지연 에뮬레이션 설정.
- `-port 5556` : 콘솔 adb에 사용되는 TCP 포트 번호 설정.
- `-ports 5556,5559` : 콘솔 및 adb에 사용되는 TCP 포트 설정.
- **`-tcpdump /path/dumpfile.cap`** : 파일에 모든 트래픽 캡처
- `-dns-server 192.0.2.0, 192.0.2.255` : 쉼표로 구분된 DNS 서버를 VM에 지정할 수 있음.
- **`-http-proxy 192.168.1.12:8080`** : 사용할 HTTP 프록시를 지정할 수 있음 (Burp로 트래픽을 캡처할 때 매우 유용)
- 프록시 설정이 어떤 이유로 작동하지 않으면, 내부에서 구성하거나 "Super Proxy"나 "ProxyDroid" 같은 애플리케이션을 사용해보세요.
- `-netdelay 200` : 네트워크 지연(에뮬레이션)을 밀리초 단위로 설정.
- `-port 5556` : 콘솔 adb에 사용되는 TCP 포트 번호 설정.
- `-ports 5556,5559` : 콘솔과 adb에 사용되는 TCP 포트들 설정.
- **`-tcpdump /path/dumpfile.cap`** : 모든 트래픽을 파일로 캡처
**System**
- `-selinux {disabled|permissive}` : Linux 운영 체제에서 보안 강화 Linux 보안 모듈을 비활성화 또는 허용 모드로 설정.
- `-timezone Europe/Paris` : 가상 장치의 시간대 설정
- `-selinux {disabled|permissive}` : Linux 운영체제에서 Security-Enhanced Linux 보안 모듈을 disabled 또는 permissive 모드로 설정.
- `-timezone Europe/Paris` : 가상 디바이스의 시간대 설정
- `-screen {touch(default)|multi-touch|o-touch}` : 에뮬레이션된 터치 스크린 모드 설정.
- **`-writable-system`** : 에뮬레이션 세션 동안 쓰기 가능한 시스템 이미지를 갖기 위해 이 옵션을 사용하십시오. `adb root; adb remount`도 실행해야 합니다. 이는 시스템에 새 인증서를 설치하는 데 매우 유용합니다.
- **`-writable-system`** : 에뮬레이션 세션 동안 시스템 이미지를 쓰기 가능하게 하려면 이 옵션을 사용하세요. 또한 `adb root; adb remount`를 실행해야 합니다. 시스템에 새 인증서를 설치할 때 매우 유용합니다.
## Rooting a Play Store device
## Linux CLI setup (SDK/AVD quickstart)
Play Store가 있는 장치를 다운로드한 경우 직접 루트 권한을 얻을 수 없으며, 다음과 같은 오류 메시지가 표시됩니다.
공식 CLI 도구를 사용하면 Android Studio 없이도 빠르고 디버깅 가능한 에뮬레이터를 쉽게 만들 수 있습니다.
```bash
# Directory layout
mkdir -p ~/Android/cmdline-tools/latest
# Download commandline tools (Linux)
wget https://dl.google.com/android/repository/commandlinetools-linux-13114758_latest.zip -O /tmp/cmdline-tools.zip
unzip /tmp/cmdline-tools.zip -d ~/Android/cmdline-tools/latest
rm /tmp/cmdline-tools.zip
# Env vars (add to ~/.bashrc or ~/.zshrc)
export ANDROID_HOME=$HOME/Android
export PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator:$PATH
# Install core SDK components
sdkmanager --install "platform-tools" "emulator"
# Install a debuggable x86_64 system image (Android 11 / API 30)
sdkmanager --install "system-images;android-30;google_apis;x86_64"
# Create an AVD and run it with a writable /system & snapshot name
avdmanager create avd -n PixelRootX86 -k "system-images;android-30;google_apis;x86_64" -d "pixel"
emulator -avd PixelRootX86 -writable-system -snapshot PixelRootX86_snap
# Verify root (debuggable images allow `adb root`)
adb root
adb shell whoami # expect: root
```
노트
- System image flavors: google_apis (디버그 가능, allows `adb root`), google_apis_playstore (not rootable), aosp/default (lightweight).
- Build types: userdebug often allows `adb root` on debug-capable images. Play Store images are production builds and block root.
- On x86_64 hosts, full-system ARM64 emulation is unsupported from API 28+. For Android 11+ use Google APIs/Play images that include per-app ARM-to-x86 translation to run many ARM-only apps quickly.
### CLI에서의 스냅샷
```bash
# Save a clean snapshot from the running emulator
adb -s emulator-5554 emu avd snapshot save my_clean_setup
# Boot from a named snapshot (if it exists)
emulator -avd PixelRootX86 -writable-system -snapshot my_clean_setup
```
## ARM→x86 바이너리 변환 (Android 11+)
Android 11+의 Google APIs 및 Play Store images는 시스템의 나머지 부분은 네이티브 x86/x86_64로 유지하면서 프로세스별로 ARM 앱 바이너리를 번역할 수 있습니다. 이는 데스크탑에서 많은 ARM 전용 앱을 테스트하기에 대체로 충분히 빠릅니다.
> 팁: pentests 동안 Google APIs x86/x86_64 images를 사용하는 것이 좋습니다. Play images는 편하지만 `adb root`을 차단합니다; Play services가 꼭 필요하고 root가 없는 것을 받아들일 때만 사용하세요.
## Play Store 기기 루팅
Play Store가 포함된 기기를 다운로드했다면 직접 root를 얻을 수 없으며 다음과 같은 오류 메시지가 나타납니다
```
$ adb root
adbd cannot run as root in production builds
```
Using [rootAVD](https://github.com/newbit1/rootAVD) with [Magisk](https://github.com/topjohnwu/Magisk) I was able to root it (follow for example [**this video**](https://www.youtube.com/watch?v=Wk0ixxmkzAI) **or** [**this one**](https://www.youtube.com/watch?v=qQicUW0svB8)).
Using [rootAVD](https://github.com/newbit1/rootAVD) with [Magisk](https://github.com/topjohnwu/Magisk) [rootAVD]와 [Magisk]를 사용하여 루팅할 수 있었습니다 (예: [**this video**](https://www.youtube.com/watch?v=Wk0ixxmkzAI) **또는** [**this one**](https://www.youtube.com/watch?v=qQicUW0svB8)).
## Burp 인증서 설치
사용자 정의 CA 인증서를 설치하는 방법을 배우려면 다음 페이지를 확인하세요:
사용자 정의 CA 인증서를 설치하는 방법 다음 페이지를 확인하세요:
{{#ref}}
install-burp-certificate.md
{{#endref}}
## 멋진 AVD 옵션
## 유용한 AVD 옵션
### 스냅샷 찍기
언제든지 VM의 스냅샷을 찍으려면 **GUI를 사용할 수 있습니다**:
언제든지 VM의 스냅샷을 **GUI를 사용하여** 찍을 수 있습니다:
![](<../../images/image (234).png>)
## 참고자료
- [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools)
- [Android Emulator command line](https://developer.android.com/studio/run/emulator-commandline)
- [Run ARM apps on the Android Emulator (x86 translation)](https://android-developers.googleblog.com/2020/03/run-arm-apps-on-android-emulator.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,54 +1,107 @@
# Frida Tutorial
# Frida 튜토리얼
{{#include ../../../banners/hacktricks-training.md}}
## Installation
## 설치
**frida tools**를 설치하세요:
다음 항목을 설치하세요: **frida tools**
```bash
pip install frida-tools
pip install frida
```
**안드로이드에** **frida server**를 **다운로드하고 설치**하세요 ([최신 릴리스 다운로드](https://github.com/frida/frida/releases)).\
adb를 루트 모드로 재시작하고, 연결하고, frida-server를 업로드하고, 실행 권한을 부여한 후 백그라운드에서 실행하는 원라이너:
**다운로드 및 설치** 안드로이드에 **frida server** ([Download the latest release](https://github.com/frida/frida/releases)).\
adb를 root 모드로 재시작하고 연결한 뒤 frida-server를 업로드하고 실행 권한을 부여한 다음 백그라운드에서 실행하는 원라이너:
```bash
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 &"
```
**작동하는지 확인하세요**:
**확인**: 이것이 **작동**하는지:
```bash
frida-ps -U #List packages and processes
frida-ps -U | grep -i <part_of_the_package_name> #Get all the package name
```
## 튜토리얼
## Frida server vs. Gadget (root vs. no-root)
### [튜토리얼 1](frida-tutorial-1.md)
Frida로 Android 앱을 계측하는 두 가지 일반적인 방법:
- Frida server (rooted devices): 네이티브 daemon을 push하고 실행하여 어떤 process에도 attach할 수 있게 해줍니다.
- Frida Gadget (no root): Frida를 shared library로 APK 내부에 번들하고 target process 내에서 자동으로 로드합니다.
Frida server (rooted)
```bash
# 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와 config를 추가:
- libfrida-gadget.so를 lib/<abi>/에 배치하세요 (예: lib/arm64-v8a/)
- 스크립트 로딩 설정을 포함한 assets/frida-gadget.config 파일을 생성하세요
Example frida-gadget.config
```json
{
"interaction": { "type": "script", "path": "/sdcard/ssl-bypass.js" },
"runtime": { "logFile": "/sdcard/frida-gadget.log" }
}
```
2) gadget을 참조/로드하여 조기에 초기화되도록 합니다:
- 가장 쉬운 방법: Application.onCreate()에 System.loadLibrary("frida-gadget")를 호출하는 작은 Java 스텁을 추가하거나, 이미 존재하는 네이티브 라이브러리 로딩을 사용하세요.
3) APK를 재패키징하고 서명한 다음 설치:
```bash
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
```
4) host에서 gadget process에 Attach:
```bash
frida-ps -Uai
frida -U -n com.example.app
```
참고
- Gadget은 일부 보호 기능에 의해 탐지됩니다; 필요하면 이름/경로를 은폐하고 늦게/조건부로 로드하세요.
- 보호가 강화된 앱에서는 rooted testing을 server + late attach로 수행하거나 Magisk/Zygisk 숨김과 결합하는 것을 권장합니다.
## Tutorials
### [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)
**Source Code**: [https://github.com/t0thkr1s/frida-demo](https://github.com/t0thkr1s/frida-demo)
**[링크를 따라 읽어보세요](frida-tutorial-1.md).**
**읽으려면 [link to read it](frida-tutorial-1.md)를 따라가세요.**
### [튜토리얼 2](frida-tutorial-2.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/) (파트 2, 3 & 4)\
**APK 및 소스 코드**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples)
**출처**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (Parts 2, 3 & 4)\
**APKs and Source code**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples)
**[링크를 따라 읽어보세요.](frida-tutorial-2.md)**
**읽으려면[ link to read it.](frida-tutorial-2.md)**
### [튜토리얼 3](owaspuncrackable-1.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).**
**읽으려면 [link to read it](owaspuncrackable-1.md)를 따라가세요.**
**더 많은 멋진 Frida 스크립트를 여기에서 찾을 수 있습니다:** [**https://codeshare.frida.re/**](https://codeshare.frida.re)
**You can find more Awesome Frida scripts here:** [**https://codeshare.frida.re/**](https://codeshare.frida.re)
## 빠른 예제
### 명령줄에서 Frida 호출하기
### 커맨드라인에서 Frida 호출
```bash
frida-ps -U
@ -61,7 +114,7 @@ frida -U --no-pause -l disableRoot.js -f owasp.mstg.uncrackable1
#frozen so that the instrumentation can occur, and the automatically
#continue execution with our modified code.
```
### 기본 Python 스크립트
### 기본 Python Script
```python
import frida, sys
@ -72,9 +125,9 @@ print('[ * ] Running Frida Demo application')
script.load()
sys.stdin.read()
```
### 매개변수 없이 함수 훅킹
### Hooking functions — 매개변수 없음
클래스 `sg.vantagepoint.a.c`의 함수 `a()`훅킹합니다.
클래스 `sg.vantagepoint.a.c`의 함수 `a()`Hook하세요.
```javascript
Java.perform(function () {
; rootcheck1.a.overload().implementation = function() {
@ -84,14 +137,14 @@ return false;
};
});
```
자바 `exit()` 후킹
java `exit()` 후킹
```javascript
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 :)")
}
```
MainActivity `.onStart()``.onCreate()`
Hook MainActivity `.onStart()``.onCreate()`
```javascript
var mainactivity = Java.use("sg.vantagepoint.uncrackable1.MainActivity")
mainactivity.onStart.overload().implementation = function () {
@ -105,7 +158,7 @@ send("MainActivity.onCreate() HIT!!!")
var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0)
}
```
안드로이드 `.onCreate()`
android `.onCreate()`
```javascript
var activity = Java.use("android.app.Activity")
activity.onCreate.overload("android.os.Bundle").implementation = function (
@ -115,9 +168,9 @@ send("Activity HIT!!!")
var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0)
}
```
### 매개변수가 있는 함수 후킹 및 값 검색
### Hooking 함수의 매개변수와 반환값 가져오기
복호화 함수를 후킹합니다. 입력을 출력하고, 원래 함수를 호출하여 입력을 복호화한 다음, 평문 데이터를 출력합니다:
복호화 함수에 Hooking하기. 입력을 출력하고, 원본 함수를 호출해 입력을 복호화한 다음, 평문 데이터를 출력합니다:
```javascript
function getString(data) {
var ret = ""
@ -142,9 +195,9 @@ send("Decrypted flag: " + flag)
return ret //[B
}
```
### 함수 후킹 및 입력으로 호출하기
### Hooking functions 및 우리 입력으로 호출하기
문자열을 받는 함수를 후킹하고 다른 문자열로 호출하기 (from [here](https://11x256.github.io/Frida-hooking-android-part-2/))
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
@ -157,11 +210,11 @@ console.log("Return value: " + ret)
return ret
}
```
### 이미 생성된 클래스 객체 가져오기
### 이미 생성된 클래스 객체 가져오기
생성된 객체의 일부 속성을 추출하려면 다음을 사용할 수 있습니다.
이미 생성된 객체의 속성 일부를 추출하려면 이 방법을 사용할 수 있습니다.
이 예제에서는 my_activity 클래스의 객체를 가져오는 방법과 객체의 비공개 속성을 출력하는 .secret() 함수를 호출하는 방법을 보여줍니다:
이 예제에서는 클래스 my_activity의 객체를 얻는 방법과, 해당 객체의 private 속성을 출력하는 .secret() 함수를 호출하는 방법을 보여줍니다:
```javascript
Java.choose("com.example.a11x256.frida_test.my_activity", {
onMatch: function (instance) {
@ -172,10 +225,16 @@ console.log("Result of secret func: " + instance.secret())
onComplete: function () {},
})
```
## 다른 Frida 튜토리얼
## 기타 Frida 튜토리얼
- [https://github.com/DERE-ad2001/Frida-Labs](https://github.com/DERE-ad2001/Frida-Labs)
- [고급 Frida 사용 블로그 시리즈 1부: IOS 암호화 라이브러리](https://8ksec.io/advanced-frida-usage-part-1-ios-encryption-libraries-8ksec-blogs/)
- [Part 1 of Advanced Frida Usage blog series: IOS Encryption Libraries](https://8ksec.io/advanced-frida-usage-part-1-ios-encryption-libraries-8ksec-blogs/)
## 참고 자료
- [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools)
- [Frida Gadget documentation](https://frida.re/docs/gadget/)
- [Frida releases (server binaries)](https://github.com/frida/frida/releases)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -3,18 +3,30 @@
{{#include ../../banners/hacktricks-training.md}}
## ADB를 통한 시스템 전체 프록시
전역 HTTP 프록시를 구성하여 모든 앱이 트래픽을 interceptor (Burp/mitmproxy)를 통해 라우팅하도록 합니다:
```bash
# Set proxy (device/emulator must reach your host IP)
adb shell settings put global http_proxy 192.168.1.2:8080
# Clear proxy
adb shell settings put global http_proxy :0
```
팁: Burp에서 리스너를 0.0.0.0에 바인드하면 LAN의 디바이스들이 연결할 수 있습니다 (Proxy -> Options -> Proxy Listeners).
## 가상 머신에서
먼저 Burp에서 Der 인증서를 다운로드해야 합니다. 이는 _**Proxy**_ --> _**Options**_ --> _**Import / Export CA certificate**_에서 할 수 있습니다.
먼저 Burp에서 Der 인증서를 다운로드해야 합니다. _**Proxy**_ --> _**Options**_ --> _**Import / Export CA certificate**_에서 할 수 있습니다.
![](<../../images/image (367).png>)
**Der 형식으로 인증서를 내보내고** 이를 **Android**가 **이해할 수 있는 형태로 변환**합시다. **AVD의 Android 머신에서 burp 인증서를 구성하려면** 이 머신을 **`-writable-system`** 옵션과 함께 **실행해야 합니다.**\
**Der 형식으로 인증서를 내보내기**한 다음 **변환**하여 **Android**가 **이해할 수 있는** 형태로 만듭니다. **AVD의 Android 머신에 burp 인증서를 구성하려면** 이 머신을 **`-writable-system`** 옵션과 **함께** **실행**해야 한다는 점을 유의하세요.\
예를 들어 다음과 같이 실행할 수 있습니다:
```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system
```
그런 다음 **burp의 인증서를 구성하려면**:
그런 다음, **burps 인증서를 구성하려면**:
```bash
openssl x509 -inform DER -in burp_cacert.der -out burp_cacert.pem
CERTHASHNAME="`openssl x509 -inform PEM -subject_hash_old -in burp_cacert.pem | head -1`.0"
@ -25,39 +37,43 @@ adb shell mv /sdcard/$CERTHASHNAME /system/etc/security/cacerts/ #Move to correc
adb shell chmod 644 /system/etc/security/cacerts/$CERTHASHNAME #Assign privileges
adb reboot #Now, reboot the machine
```
기계가 **재부팅을 마치면** burp 인증서가 사용됩니다!
머신이 **재부팅을 마치면** Burp certificate가 사용됩니다!
## Magisc 사용하기
장치를 **Magisc로 루팅한 경우** (아마도 에뮬레이터일 수 있음) 이전 **단계를 따라할 수 없다면** Burp 인증서를 설치하기 위해 **파일 시스템이 읽기 전용**이고 이를 쓰기 가능으로 다시 마운트할 수 없는 경우, 다른 방법이 있습니다.
만약 당신이 **Magisc로 기기를 루트(root)화했다**(에뮬레이터일 수 있음)면, 이전에 Burp cert를 설치하는 **단계들**을 따라할 수 없고 그 이유가 **파일시스템이 읽기 전용(read-only)**이라 remount로 쓰기 가능하게 만들 수 없다면, 다른 방법이 있습니다.
[**이 비디오**](https://www.youtube.com/watch?v=qQicUW0svB8)에서 설명된 대로 다음을 수행해야 합니다:
[**this video**](https://www.youtube.com/watch?v=qQicUW0svB8)에 설명된 것처럼, 다음을 수행해야 합니다:
1. **CA 인증서 설치**: DER Burp 인증서를 **드래그 앤 드롭**하여 모바일에서 **확장자를** `.crt`로 변경하여 Downloads 폴더에 저장하고 `Install a certificate` -> `CA certificate`로 이동합니다.
1. **CA certificate 설치**: DER Burp certificate 파일의 확장자를 `.crt`**변경한 후** 모바일로 **드래그&드롭**하여 Downloads 폴더에 저장하고 `Install a certificate` -> `CA certificate`로 이동합니다
<figure><img src="../../images/image (53).png" alt="" width="164"><figcaption></figcaption></figure>
- `Trusted credentials` -> `USER`로 이동하여 인증서가 올바르게 저장되었는지 확인합니다.
- 인증서가 제대로 저장되었는지 `Trusted credentials` -> `USER`로 이동해 확인하세요
<figure><img src="../../images/image (54).png" alt="" width="334"><figcaption></figcaption></figure>
2. **시스템 신뢰로 만들기**: Magisc 모듈 [MagiskTrustUserCerts](https://github.com/NVISOsecurity/MagiskTrustUserCerts) (zip 파일)를 다운로드하고, **드래그 앤 드롭**하여 전화기에 넣고, 전화기의 **Magics 앱**에서 **`Modules`** 섹션으로 이동하여 **`Install from storage`**를 클릭하고, `.zip` 모듈을 선택한 후 설치가 완료되면 **재부팅**합니다:
2. **System trusted로 만들기**: Magisc 모듈 [MagiskTrustUserCerts](https://github.com/NVISOsecurity/MagiskTrustUserCerts) (.zip 파일)를 다운로드한 뒤, 폰에 **드래그&드롭**하고 폰의 **Magics app**에서 **`Modules`** 섹션으로 들어가 **`Install from storage`**를 클릭해 `.zip` 모듈을 선택하여 설치한 다음 폰을 **재부팅**합니다:
<figure><img src="../../images/image (55).png" alt="" width="345"><figcaption></figcaption></figure>
- 재부팅 후 `Trusted credentials` -> `SYSTEM`으로 이동하여 Postswigger 인증서가 있는지 확인합니다.
- 재부팅 후 `Trusted credentials` -> `SYSTEM`로 이동해 Postswigger cert가 있는지 확인하세요
<figure><img src="../../images/image (56).png" alt="" width="314"><figcaption></figcaption></figure>
### Magisc 모듈 만드는 법 배우기
다음 링크를 확인하세요: https://medium.com/@justmobilesec/magisk-for-mobile-pentesting-rooting-android-devices-and-building-custom-modules-part-ii-22badc498437
## Android 14 이후
최신 Android 14 릴리스에서는 시스템 신뢰 CA 인증서 처리 방식에 중대한 변화가 관찰되었습니다. 이전에는 이러한 인증서가 **`/system/etc/security/cacerts/`**에 저장되어 루트 권한을 가진 사용자가 접근하고 수정할 수 있었으며, 이를 통해 시스템 전반에 즉시 적용할 수 있었습니다. 그러나 Android 14에서는 저장 위치가 **`/apex/com.android.conscrypt/cacerts`**로 이동하였으며, 이는 본질적으로 변경 불가능한 **`/apex`** 경로 내의 디렉토리입니다.
최신 Android 14 릴리스에서는 system-trusted Certificate Authority (CA) 인증서 처리 방식에 큰 변화가 있었습니다. 이전에는 이 인증서들이 **`/system/etc/security/cacerts/`**에 위치해 있어 root 권한이 있는 사용자가 접근·수정할 수 있었고 시스템 전체에 즉시 적용되었습니다. 그러나 Android 14에서는 저장 위치가 **`/apex/com.android.conscrypt/cacerts`**로 이동했으며, 이는 **`/apex`** 경로 내의 디렉토리로 본질적으로 변경 불가능(immutable)합니다.
**APEX cacerts 경로**를 쓰기 가능으로 다시 마운트하려는 시도는 실패로 돌아가며, 시스템은 이러한 작업을 허용하지 않습니다. 임시 파일 시스템(tmpfs)으로 디렉토리를 언마운트하거나 오버레이하려는 시도조차 불변성을 우회하지 못하며, 애플리케이션은 파일 시스템 수준의 변경과 관계없이 원래 인증서 데이터에 계속 접근합니다. 이러한 회복력은 **`/apex`** 마운트가 PRIVATE 전파로 구성되어 있어 **`/apex`** 디렉토리 내의 수정이 다른 프로세스에 영향을 미치지 않도록 보장합니다.
**APEX cacerts path**를 쓰기 가능하도록 remount하려는 시도는 시스템에서 허용되지 않아 실패합니다. 디렉토리를 언마운트하거나 tmpfs로 오버레이해도 불변성을 우회하지 못하며, 파일시스템 수준에서 변경을 가해도 애플리케이션은 여전히 원본 인증서 데이터를 참조합니다. 이는 **`/apex`** 마운트가 PRIVATE propagation으로 설정되어 있어 **`/apex`** 내의 변경이 다른 프로세스에 영향을 주지 않도록 하기 때문입니다.
Android 초기화는 `init` 프로세스를 포함하며, 운영 체제를 시작할 때 Zygote 프로세스도 시작됩니다. 이 프로세스는 새로운 마운트 네임스페이스를 포함하여 애플리케이션 프로세스를 시작하는 역할을 하며, 여기에는 개인 **`/apex`** 마운트가 포함되어 있어 이 디렉토리의 변경 사항이 다른 프로세스와 격리됩니다.
Android 초기화는 `init` 프로세스가 운영체제를 시작하면서 Zygote 프로세스를 기동하는 과정을 포함합니다. Zygote는 새로운 마운트 네임스페이스를 가진 애플리케이션 프로세스를 시작하는 역할을 하며, 이 네임스페이스에는 private **`/apex`** 마운트가 포함되어 있어 해당 디렉토리에 대한 변경이 다른 프로세스와 격리됩니다.
그럼에도 불구하고 **`/apex`** 디렉토리 내의 시스템 신뢰 CA 인증서를 수정해야 하는 경우 우회 방법이 존재합니다. 이는 PRIVATE 전파를 제거하기 위해 **`/apex`**를 수동으로 다시 마운트하여 쓰기 가능하게 만드는 것을 포함합니다. 이 과정은 **`/apex/com.android.conscrypt`**의 내용을 다른 위치로 복사하고, 읽기 전용 제약을 제거하기 위해 **`/apex/com.android.conscrypt`** 디렉토리를 언마운트한 후, 내용을 원래 위치인 **`/apex`**로 복원하는 것을 포함합니다. 이 접근 방식은 시스템 충돌을 피하기 위해 신속한 조치를 요구합니다. 이러한 변경 사항이 시스템 전반에 적용되도록 하려면 `system_server`를 재시작하는 것이 좋으며, 이는 모든 애플리케이션을 효과적으로 재시작하고 시스템을 일관된 상태로 만듭니다.
그럼에도 불구하고 **`/apex`** 디렉토리 내의 system-trusted CA 인증서를 수정해야 하는 경우에 대한 우회 방법이 있습니다. 이 방법은 **`/apex`**의 PRIVATE propagation을 제거하기 위해 수동으로 remount하는 것으로, 이렇게 하면 쓰기가 가능해집니다. 절차는 **`/apex/com.android.conscrypt`**의 내용을 다른 위치로 복사하고, **`/apex/com.android.conscrypt`** 디렉토리를 언마운트하여 읽기 전용 제약을 제거한 뒤, 내용을 원래의 **`/apex`** 위치로 복원하는 것입니다. 이 과정은 시스템 크래시를 피하기 위해 빠르게 진행해야 합니다. 변경사항을 시스템 전반에 적용하려면 모든 애플리케이션을 사실상 재시작하는 `system_server`를 재시작하는 것이 권장됩니다.
```bash
# Create a separate temp directory, to hold the current certificates
# Otherwise, when we add the mount we can't read the current certs anymore.
@ -115,28 +131,28 @@ wait # Launched in parallel - wait for completion here
echo "System certificate injected"
```
### Bind-mounting through NSEnter
### NSEnter를 통한 Bind-mounting
1. **쓰기 가능한 디렉토리 설정**: 처음에, 기존의 비-APEX 시스템 인증서 디렉토리 위에 `tmpfs`를 마운트하여 쓰기 가능한 디렉토리를 설정합니다. 이는 다음 명령어로 수행됩니다:
1. **쓰기 가능한 디렉터리 설정**: 처음에는 기존의 non-APEX 시스템 인증서 디렉터리 위에 `tmpfs`를 마운트하여 쓰기 가능한 디렉터리를 생성합니다. 이는 다음 명령어로 수행됩니다:
```bash
mount -t tmpfs tmpfs /system/etc/security/cacerts
```
2. **CA 인증서 준비**: 쓰기 가능한 디렉토리를 설정한 후, 사용하려는 CA 인증서를 이 디렉토리에 복사해야 합니다. 이는 `/apex/com.android.conscrypt/cacerts/`에서 기본 인증서를 복사하는 것을 포함할 수 있습니다. 이러한 인증서의 권한 및 SELinux 레이블을 적절히 조정하는 것이 중요합니다.
3. **Zygote에 대한 바인드 마운트**: `nsenter`를 사용하여 Zygote의 마운트 네임스페이스에 들어갑니다. Zygote는 Android 애플리케이션을 시작하는 프로세스이므로, 이후 시작되는 모든 애플리케이션이 새로 구성된 CA 인증서를 사용하도록 이 단계를 수행해야 합니다. 사용되는 명령은:
2. **CA 인증서 준비**: 쓰기 가능한 디렉터리 설정 후, 사용하려는 CA 인증서를 이 디렉터리로 복사해야 합니다. 여기에는 `/apex/com.android.conscrypt/cacerts/`에서 기본 인증서를 복사하는 작업이 포함될 수 있습니다. 이러한 인증서들의 권한과 SELinux 라벨을 적절히 조정하는 것이 필수적입니다.
3. **Zygote를 위한 바인드 마운트**: `nsenter`를 사용하여 Zygote의 마운트 네임스페이스로 들어갑니다. Zygote는 Android 애플리케이션을 실행하는 프로세스이므로, 이후 시작되는 모든 애플리케이션이 새로 구성한 CA 인증서를 사용하도록 하기 위해 이 단계가 필요합니다. 사용되는 명령은:
```bash
nsenter --mount=/proc/$ZYGOTE_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
```
것은 시작되는 모든 새로운 앱이 업데이트된 CA 인증서 설정을 준수하도록 보장합니다.
렇게 하면 새로 시작되는 모든 앱이 업데이트된 CA 인증서 설정을 따르도록 보장됩니다.
4. **실행 중인 앱에 변경 사항 적용**: 이미 실행 중인 애플리케이션에 변경 사항을 적용하기 위해, `nsenter`를 다시 사용하여 각 앱의 네임스페이스에 개별적으로 들어가 유사한 바인드 마운트를 수행합니다. 필요한 명령은:
4. **실행 중인 앱에 변경사항 적용**: 이미 실행 중인 애플리케이션에 변경사항을 적용하려면, `nsenter`를 다시 사용하여 각 앱의 네임스페이스에 개별적으로 들어가 유사한 bind mount를 수행합니다. 필요한 명령은 다음과 같습니다:
```bash
nsenter --mount=/proc/$APP_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
```
5. **대체 접근법 - 소프트 재부팅**: 대체 방법은 `init` 프로세스(PID 1)에서 바인드 마운트를 수행한 다음 `stop && start` 명령어로 운영 체제를 소프트 재부팅하는 것입니다. 이 접근법은 모든 네임스페이스에 걸쳐 변경 사항을 전파하여 각 실행 중인 앱을 개별적으로 처리할 필요가 없습니다. 그러나 이 방법은 재부팅의 불편함으로 인해 일반적으로 덜 선호됩니다.
5. **대체 방법 - 소프트 리부트**: 대체 방법으로는 `init` 프로세스 (PID 1)에 bind mount를 수행한 후 `stop && start` 명령으로 운영체제를 소프트 리부트하는 방식이 있습니다. 이 방법은 변경사항을 모든 네임스페이스에 전파하여 실행 중인 각 앱을 개별적으로 처리할 필요를 없애줍니다. 그러나 재부팅의 불편함 때문에 일반적으로 선호되지는 않습니다.
## References
- [https://httptoolkit.com/blog/android-14-install-system-ca-certificate/](https://httptoolkit.com/blog/android-14-install-system-ca-certificate/)
## 참고 자료
- [Android 14: Install a system CA certificate on a rooted device](https://httptoolkit.com/blog/android-14-install-system-ca-certificate/)
- [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools)
{{#include ../../banners/hacktricks-training.md}}