๋ค์ดํฐ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ญ๋ถ์
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://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html
Android ์ฑ์ ์ผ๋ฐ์ ์ผ๋ก C ๋๋ C++๋ก ์์ฑ๋ ๋ค์ดํฐ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(.so)๋ฅผ ์ฑ๋ฅ์ด ์ค์ํ ์์
์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์
์ฑ์ฝ๋ ์ ์์๋ค๋ ์ด๋ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์
์ฉํฉ๋๋ค. ELF shared objects๋ ์ฌ์ ํ DEX/OAT ๋ฐ์ดํธ์ฝ๋๋ณด๋ค ๋์ปดํ์ผํ๊ธฐ ์ด๋ ต์ต๋๋ค.
์ด ํ์ด์ง๋ Android .so ํ์ผ์ ์ญ๋ถ์์ ๋ ์ฝ๊ฒ ๋ง๋๋ ์ค์ฉ์ ์ธ ์ํฌํ๋ก์ ์ต๊ทผ(2023โ2025) ๋๊ตฌ ๊ฐ์ ์ฌํญ์ ์ค์ ์ ๋ก๋๋ค.
๊ฐ ์ถ์ถํ libfoo.so์ ๋ํ ๋น ๋ฅธ ๋ถ๋ฅ ์ํฌํ๋ก
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ์ถ
# From an installed application
adb shell "run-as <pkg> cat lib/arm64-v8a/libfoo.so" > libfoo.so
# Or from the APK (zip)
unzip -j target.apk "lib/*/libfoo.so" -d extracted_libs/
- ์ํคํ ์ฒ ๋ฐ ๋ณดํธ ์ค์ ์๋ณ
file libfoo.so # arm64 or arm32 / x86
readelf -h libfoo.so # OS ABI, PIE, NX, RELRO, etc.
checksec --file libfoo.so # (peda/pwntools)
- ๋ด๋ณด๋ธ ์ฌ๋ณผ ๋ฐ JNI ๋ฐ์ธ๋ฉ ๋์ด
readelf -s libfoo.so | grep ' Java_' # dynamic-linked JNI
strings libfoo.so | grep -i "RegisterNatives" -n # static-registered JNI
- ๋์ปดํ์ผ๋ฌ์ ๋ก๋ (Ghidra โฅ 11.0, IDA Pro, Binary Ninja, Hopper or Cutter/Rizin) ๋ฐ ์๋ ๋ถ์ ์คํ. ์๋ก์ด Ghidra ๋ฒ์ ์ AArch64 decompiler๋ฅผ ๋์ ํ์ฌ PAC/BTI stubs์ MTE tags๋ฅผ ์ธ์ํ๋ฏ๋ก Android 14 NDK๋ก ๋น๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ถ์์ด ํฌ๊ฒ ํฅ์๋์์ต๋๋ค.
- ์ ์ vs ๋์ ์ญ๋ถ์ ๊ฒฐ์ : stripped, obfuscated ์ฝ๋๋ค์ ์ข ์ข instrumentation์ด ํ์ํฉ๋๋ค (Frida, ptrace/gdbserver, LLDB).
Dynamic Instrumentation (Frida โฅ 16)
Frida์ 16 ์๋ฆฌ์ฆ๋ ๋์์ด ์ต์ Clang/LLD ์ต์ ํ๋ฅผ ์ฌ์ฉํ ๋ ๋์์ด ๋๋ ์ฌ๋ฌ Android ์ ์ฉ ๊ฐ์ ์ฌํญ์ ๋์ ํ์ต๋๋ค:
thumb-relocator๋ ์ด์ LLD์ aggressive alignment(--icf=all)๋ก ์์ฑ๋ ์์ ARM/Thumb ํจ์๋ฅผ hookํ ์ ์์ต๋๋ค.- ELF import slots ์ด๊ฑฐ ๋ฐ ์ฌ๋ฐ์ธ๋ฉ์ด Android์์ ๋์ํ์ฌ, inline hooks๊ฐ ๊ฑฐ๋ถ๋ ๋ ๋ชจ๋๋ณ
dlopen()/dlsym()ํจ์นญ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. - Android 14์์ ์ฑ์ด
--enable-optimizations๋ก ์ปดํ์ผ๋ ๋ ์ฌ์ฉ๋๋ ์๋ก์ด ART quick-entrypoint์ ๋ํ Java hooking์ด ์์ ๋์์ต๋๋ค.
์์: RegisterNatives๋ฅผ ํตํด ๋ฑ๋ก๋ ๋ชจ๋ ํจ์๋ฅผ ์ด๊ฑฐํ๊ณ ๋ฐํ์์ ๊ทธ ์ฃผ์๋ฅผ ๋คํํ๋ ๋ฐฉ๋ฒ:
Java.perform(function () {
var Runtime = Java.use('java.lang.Runtime');
var register = Module.findExportByName(null, 'RegisterNatives');
Interceptor.attach(register, {
onEnter(args) {
var envPtr = args[0];
var clazz = Java.cast(args[1], Java.use('java.lang.Class'));
var methods = args[2];
var count = args[3].toInt32();
console.log('[+] RegisterNatives on ' + clazz.getName() + ' -> ' + count + ' methods');
// iterate & dump (JNI nativeMethod struct: name, sig, fnPtr)
}
});
});
Frida will work out of the box on PAC/BTI-enabled devices (Pixel 8/Android 14+) as long as you use frida-server 16.2 or later โ earlier versions failed to locate padding for inline hooks.
Dumping runtime-decrypted native libraries from memory (Frida soSaver)
When a protected APK keeps native code encrypted or only maps it at runtime (packers, downloaded payloads, generated libs), attach Frida and dump the mapped ELF directly from process memory.
soSaver workflow (Python host + TS/JS Frida agent):
- Hooks
dlopenandandroid_dlopen_extto detect load-time library mapping and performs an initial sweep of already loaded modules. - Periodically scans the process memory mappings for ELF headers to catch modules loaded through non-standard mappers that never hit the loader APIs.
- Reads each module in blocks from memory and streams the bytes through Frida messages to the host; if a region cannot be read, it falls back to reading from the on-disk path when available.
- Saves the reconstructed
.sofiles and prints per-module extraction stats, providing artifacts for static RE.
Run (root + frida-server, Python โฅ3.8, uv):
git clone https://github.com/TheQmaks/sosaver.git
cd sosaver && uv sync
source .venv/bin/activate # .venv\Scripts\activate on Windows
# target by package or PID; choose output/verbosity
sosaver com.example.app
sosaver 1234 -o /tmp/so-dumps --debug
์ด ๋ฐฉ๋ฒ์ โonly decrypted in RAMโ ๋ณดํธ๋ฅผ ๋ณต๊ตฌ๋ ๋ผ์ด๋ธ ๋งตํ ์ด๋ฏธ์ง๋ก ์ฐํํ์ฌ, ํ์ผ์์คํ ๋ณต์ฌ๋ณธ์ด ๋๋ ํ๋์ด ์๊ฑฐ๋ ์์ด๋ IDA/Ghidra์์ ์คํ๋ผ์ธ ๋ถ์์ด ๊ฐ๋ฅํฉ๋๋ค.
์ฌ์ ๋ก๋๋ .so๋ฅผ ํตํ ํ๋ก์ธ์ค ๋ก์ปฌ JNI ํ ๋ ๋ฉํธ๋ฆฌ (SoTap)
๊ณ ๊ธ ๊ณ์ธก(instrumentation)์ด ๊ณผํ๊ฑฐ๋ ์ฐจ๋จ๋ ๊ฒฝ์ฐ์๋, ๋์ ํ๋ก์ธ์ค ๋ด๋ถ์ ์์ ๋ก๊ฑฐ๋ฅผ ์ฌ์ ๋ก๋ํ์ฌ ๋ค์ดํฐ๋ธ ์์ค์ ๊ฐ์์ฑ์ ํ๋ณดํ ์ ์์ต๋๋ค. SoTap์ ๋์ผ ์ฑ ํ๋ก์ธ์ค ๋ด์ ๋ค๋ฅธ JNI (.so) ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฐํ์ ๋์์ ๊ธฐ๋กํ๋ ๊ฒฝ๋ Android native (.so) ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค (no root required).
Key properties:
- ์ด๊ธฐ์ ์ด๊ธฐํ๋์ด ๋ก๋ํ ํ๋ก์ธ์ค ๋ด์ JNI/native ์ํธ์์ฉ์ ๊ด์ฐฐํฉ๋๋ค.
- ์ฌ๋ฌ ์ฐ๊ธฐ ๊ฐ๋ฅํ ๊ฒฝ๋ก์ ๋ก๊ทธ๋ฅผ ์ง์ ์ ์ฅํ๊ณ ์ ์ฅ ๊ณต๊ฐ์ด ์ ํ๋ ๋๋ Logcat์ผ๋ก ์ฐ์ํ๊ฒ ํด๋ฐฑํฉ๋๋ค.
- Source-customizable: edit sotap.c to extend/adjust what gets logged and rebuild per ABI.
Setup (repack the APK):
- Drop the proper ABI build into the APK so the loader can resolve libsotap.so:
- lib/arm64-v8a/libsotap.so (for arm64)
- lib/armeabi-v7a/libsotap.so (for arm32)
- Ensure SoTap loads before other JNI libs. Inject a call early (e.g., Application subclass static initializer or onCreate) so the logger is initialized first. Smali snippet example:
const-string v0, "sotap"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
- Rebuild/sign/install, run the app, then collect logs.
Log paths (checked in order):
/data/user/0/%s/files/sotap.log
/data/data/%s/files/sotap.log
/sdcard/Android/data/%s/files/sotap.log
/sdcard/Download/sotap-%s.log
# If all fail: fallback to Logcat only
Notes and troubleshooting:
- ABI ์ ๋ ฌ์ ํ์์ ๋๋ค. ๋ถ์ผ์นํ๋ฉด UnsatisfiedLinkError๊ฐ ๋ฐ์ํ๊ณ ๋ก๊ฑฐ๊ฐ ๋ก๋๋์ง ์์ต๋๋ค.
- ํ๋ Android์์๋ ์ ์ฅ์ ์ ์ฝ์ด ํํฉ๋๋ค; ํ์ผ ์ฐ๊ธฐ๊ฐ ์คํจํ๋๋ผ๋ SoTap์ ์ฌ์ ํ Logcat์ ํตํด ์ถ๋ ฅํฉ๋๋ค.
- ๋์/์ถ๋ ฅ ์์ค(verbosity)์ ์ฌ์ฉ์ํํ๋๋ก ์ค๊ณ๋์ด ์์ต๋๋ค; sotap.c๋ฅผ ํธ์งํ ํ ์์ค์์ ์ฌ๋น๋ํ์ธ์.
์ด ์ ๊ทผ๋ฒ์ malware triage ๋ฐ JNI ๋๋ฒ๊น ์์ ์ ์ฉํฉ๋๋ค. ํ๋ก์ธ์ค ์์ ์์ ์ ๋ค์ดํฐ๋ธ ํธ์ถ ํ๋ฆ์ ๊ด์ฐฐํด์ผ ํ๊ณ ๋ฃจํธ/์์คํ ์ ์ญ ํ ์ ์ฌ์ฉํ ์ ์์ ๋ ํนํ ์ค์ํฉ๋๋ค.
See also: inโmemory native code execution via JNI
A common attack pattern is to download a raw shellcode blob at runtime and execute it directly from memory through a JNI bridge (no onโdisk ELF). Details and readyโtoโuse JNI snippet here:
In Memory Jni Shellcode Execution
Recent vulnerabilities worth hunting for in APKs
| ์ฐ๋ | CVE | Affected library | ๋ฉ๋ชจ |
|---|---|---|---|
| 2023 | CVE-2023-4863 | libwebp โค 1.3.1 | ๋ค์ดํฐ๋ธ ์ฝ๋์์ WebP ์ด๋ฏธ์ง๋ฅผ ๋์ฝ๋ํ ๋ ๋๋ฌ ๊ฐ๋ฅํ ํ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ. ์ฌ๋ฌ Android ์ฑ์ด ์ทจ์ฝํ ๋ฒ์ ์ ๋ฒ๋ค๋ก ํฌํจํฉ๋๋ค. APK ๋ด๋ถ์ libwebp.so๊ฐ ๋ณด์ด๋ฉด ๋ฒ์ ์ ํ์ธํ๊ณ ์ต์คํ๋ก์ ์๋ ๋๋ ํจ์น ์ ์ฉ์ ๊ณ ๋ คํ์ธ์. |
| 2024 | Multiple | OpenSSL 3.x series | ์ฌ๋ฌ ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ ๋ฐ ํจ๋ฉ-์ค๋ผํด ๊ณ์ด ๋ฌธ์ . ๋ง์ Flutter & ReactNative ๋ฒ๋ค๋ค์ด ์์ฒด libcrypto.so๋ฅผ ํฌํจํ์ฌ ๋ฐฐํฌ๋ฉ๋๋ค. |
APK ๋ด๋ถ์์ ์๋ํํฐ .so ํ์ผ์ ๋ฐ๊ฒฌํ๋ฉด, ํญ์ ํด๋น ํด์๋ฅผ ์
์คํธ๋ฆผ ๊ถ๊ณ ๋ฌธ๊ณผ ๊ต์ฐจ ํ์ธํ์ธ์. SCA (Software Composition Analysis)๋ ๋ชจ๋ฐ์ผ์์ ๋๋ฌผ๊ธฐ ๋๋ฌธ์ ์ค๋๋ ์ทจ์ฝํ ๋น๋๊ฐ ๋๋ฆฌ ํผ์ ธ ์์ต๋๋ค.
Anti-Reversing & Hardening trends (Android 13-15)
- Pointer Authentication (PAC) & Branch Target Identification (BTI): Android 14๋ ์ง์๋๋ ARMv8.3+ ์ค๋ฆฌ์ฝ์์ ์์คํ
๋ผ์ด๋ธ๋ฌ๋ฆฌ์ PAC/BTI๋ฅผ ํ์ฑํํฉ๋๋ค. Decompiler๋ค์ ์ด์ PAC ๊ด๋ จ ์์ฌ-๋ช
๋ น์ด๋ฅผ ํ์ํฉ๋๋ค; ๋์ ๋ถ์์์๋ Frida๊ฐ PAC๋ฅผ ์ ๊ฑฐํ ๋ค ํธ๋จํด๋ฆฐ์ ์ฃผ์
ํ์ง๋ง, ์ปค์คํ
ํธ๋จํด๋ฆฐ์ ํ์ํ ๊ฒฝ์ฐ
pacda/autibsp๋ฅผ ํธ์ถํด์ผ ํฉ๋๋ค. - MTE & Scudo hardened allocator: ๋ฉ๋ชจ๋ฆฌ ํ๊น
์ ์ตํธ์ธ(opt-in)์ด์ง๋ง ๋ง์ Play-Integrity ์ธ์ ์ฑ๋ค์ด
-fsanitize=memtag๋ก ๋น๋ํฉ๋๋ค; ํ๊ทธ ์ค๋ฅ๋ฅผ ์บก์ฒํ๋ ค๋ฉดsetprop arm64.memtag.dump 1๊ณผ ํจ๊ปadb shell am start ...๋ฅผ ์ฌ์ฉํ์ธ์. - LLVM Obfuscator (opaque predicates, control-flow flattening): ์์ฉ ํจ์ปค๋ค(์: Bangcle, SecNeo)์ ์ ์ ๋ ๋ค์ดํฐ๋ธ ์ฝ๋๋ฅผ ๋ณดํธํฉ๋๋ค.
.rodata์ ๊ฐ์ง ์ ์ด ํ๋ฆ๊ณผ ์ํธํ๋ ๋ฌธ์์ด ๋ธ๋กญ์ด ์์ ๊ฒ์ผ๋ก ์์ํ์ธ์.
Neutralizing early native initializers (.init_array) and JNI_OnLoad for early instrumentation (ARM64 ELF)
๋์ด ๋ณดํธ๋ ์ฑ๋ค์ ์ข
์ข
๋งค์ฐ ์ด๊ธฐ ๋จ๊ณ์ .init_array๋ฅผ ํตํด ์คํ๋๋ ๋ค์ดํฐ๋ธ ์์ฑ์(constructor)์ ๋ฃจํธ/์๋ฎฌ๋ ์ดํฐ/๋๋ฒ๊ทธ ๊ฒ์ฌ๋ฅผ ๋ฐฐ์นํฉ๋๋ค. ์ด๋ค์ JNI_OnLoad๋ณด๋ค ํจ์ฌ ์ด์ , Java ์ฝ๋ ์คํ ์ด์ ์ ๋์ํฉ๋๋ค. ์ด๋ฐ ์๋ฌต์ ์ด๊ธฐํ์๋ค์ ๋ช
์์ ์ผ๋ก ๋ฐ๊ฟ ์ ์ด๊ถ์ ํ๋ณตํ ์ ์์ต๋๋ค:
- DYNAMIC ํ
์ด๋ธ์์
INIT_ARRAY/INIT_ARRAYSZ๋ฅผ ์ ๊ฑฐํ์ฌ ๋ก๋๊ฐ.init_array์ํธ๋ฆฌ๋ฅผ ์๋ ์คํํ์ง ์๋๋ก ํฉ๋๋ค. - RELATIVE ์ฌ๋ฐฐ์น(relocations)์์ ์์ฑ์ ์ฃผ์๋ฅผ ํด์ํ์ฌ ์ผ๋ฐ ํจ์ ์ฌ๋ณผ(์:
INIT0)๋ก ๋ด๋ณด๋ ๋๋ค. JNI_OnLoad์ ์ด๋ฆ์JNI_OnLoad0์ผ๋ก ๋ฐ๊ฟ ART๊ฐ ์๋ฌต์ ์ผ๋ก ํธ์ถํ์ง ๋ชปํ๊ฒ ํฉ๋๋ค.
Android/arm64์์ ์ด ๋ฐฉ๋ฒ์ด ์๋ํ๋ ์ด์
- AArch64์์
.init_array์ํธ๋ฆฌ๋ ์ข ์ขR_AARCH64_RELATIVE์ฌ๋ฐฐ์น์ ์ํด ๋ก๋ ์์ ์ ์ฑ์์ง๋ฉฐ, addend๋.text๋ด๋ถ์ ๋์ ํจ์ ์ฃผ์์ ๋๋ค. .init_array์ ๋ฐ์ดํธ๋ ์ ์ ์ํ์์ ๋น์ด ๋ณด์ผ ์ ์์ต๋๋ค; ๋์ ๋ง์ปค๋ ์ฌ๋ฐฐ์น ์ฒ๋ฆฌ ์ค์ ํด์๋ ์ฃผ์๋ฅผ ์๋๋ค.
์์ฑ์ ๋์ ์๋ณ
- AArch64์์ ์ ํํ ELF ํ์ฑ์ ์ํด Android NDK ํด์ฒด์ธ์ ์ฌ์ฉํ์ธ์:
# Adjust paths to your NDK; use the aarch64-linux-android-* variants
readelf -W -a ./libnativestaticinit.so | grep -n "INIT_ARRAY" -C 4
readelf -W --relocs ./libnativestaticinit.so
.init_array๊ฐ์ ์ฃผ์ ๋ฒ์ ์์ ๋ค์ด์ค๋ ์ฌ๋ฐฐ์น๋ฅผ ์ฐพ์ผ์ธ์; ํด๋นR_AARCH64_RELATIVE์addend๊ฐ ์์ฑ์์ ๋๋ค(์:0xA34,0x954).- ํด๋น ์ฃผ์ ์ฃผ๋ณ์ ์ญ์ด์ ๋ธํ์ฌ ํ์ธํ์ธ์:
objdump -D ./libnativestaticinit.so --start-address=0xA34 | head -n 40
ํจ์น ๊ณํ
- DYNAMIC ํ๊ทธ์์
INIT_ARRAY๋ฐINIT_ARRAYSZ๋ฅผ ์ ๊ฑฐํฉ๋๋ค. ์น์ ์ ์ญ์ ํ์ง ๋ง์ธ์. - ์์ฑ์ ์ฃผ์์ GLOBAL DEFAULT FUNC ์ฌ๋ณผ
INIT0๋ฅผ ์ถ๊ฐํ์ฌ ์๋์ผ๋ก ํธ์ถํ ์ ์๊ฒ ํฉ๋๋ค. JNI_OnLoadโJNI_OnLoad0๋ก ์ด๋ฆ์ ๋ณ๊ฒฝํ์ฌ ART๊ฐ ์๋ฌต์ ์ผ๋ก ํธ์ถํ์ง ๋ชปํ๊ฒ ํฉ๋๋ค.
Validation after patch
readelf -W -d libnativestaticinit.so.patched | egrep -i 'init_array|fini_array|flags'
readelf -W -s libnativestaticinit.so.patched | egrep 'INIT0|JNI_OnLoad0'
LIEF๋ก ํจ์นํ๊ธฐ (Python)
์คํฌ๋ฆฝํธ: INIT_ARRAY/INIT_ARRAYSZ ์ ๊ฑฐ, export INIT0, JNI_OnLoadโJNI_OnLoad0 ์ด๋ฆ ๋ณ๊ฒฝ
```python import liefb = lief.parse(โlibnativestaticinit.soโ)
Locate .init_array VA range
init = b.get_section(โ.init_arrayโ) va, sz = init.virtual_address, init.size
Compute constructor address from RELATIVE relocation landing in .init_array
ctor = None for r in b.dynamic_relocations: if va <= r.address < va + sz: ctor = r.addend break if ctor is None: raise RuntimeError(โNo R_*_RELATIVE relocation found inside .init_arrayโ)
Remove auto-run tags so loader skips .init_array
for tag in (lief.ELF.DYNAMIC_TAGS.INIT_ARRAYSZ, lief.ELF.DYNAMIC_TAGS.INIT_ARRAY): try: b.remove(b[tag]) except Exception: pass
Add exported FUNC symbol INIT0 at constructor address
sym = lief.ELF.Symbol() sym.name = โINIT0โ sym.value = ctor sym.size = 0 sym.binding = lief.ELF.SYMBOL_BINDINGS.GLOBAL sym.type = lief.ELF.SYMBOL_TYPES.FUNC sym.visibility = lief.ELF.SYMBOL_VISIBILITY.DEFAULT
Place symbol in .text index
text = b.get_section(โ.textโ) for idx, sec in enumerate(b.sections): if sec == text: sym.shndx = idx break b.add_dynamic_symbol(sym)
Rename JNI_OnLoad -> JNI_OnLoad0 to block implicit ART init
j = b.get_symbol(โJNI_OnLoadโ) if j: j.name = โJNI_OnLoad0โ
b.write(โlibnativestaticinit.so.patchedโ)
</details>
๋ฉ๋ชจ ๋ฐ ์คํจํ ์ ๊ทผ๋ฒ(์ด์์ฑ)
- `.init_array` ๋ฐ์ดํธ๋ฅผ 0์ผ๋ก ๋ง๋ค๊ฑฐ๋ ์น์
๊ธธ์ด๋ฅผ 0์ผ๋ก ์ค์ ํด๋ ๋์์ด ๋์ง ์์ต๋๋ค: the dynamic linker๊ฐ relocations์ ํตํด ์ด๋ฅผ ๋ค์ ์ฑ์๋๋ค.
- `INIT_ARRAY`/`INIT_ARRAYSZ`๋ฅผ 0์ผ๋ก ์ค์ ํ๋ฉด ํ๊ทธ ๋ถ์ผ์น๋ก ์ธํด loader๊ฐ ์์๋ ์ ์์ต๋๋ค. ํด๋น DYNAMIC ํญ๋ชฉ๋ค์ ๊น๋ํ๊ฒ ์ ๊ฑฐํ๋ ๊ฒ์ด ์ ๋ขฐํ ์ ์๋ ๋ฐฉ๋ฒ์
๋๋ค.
- `.init_array` ์น์
์ ์์ ํ ์ญ์ ํ๋ฉด loader๊ฐ ์ถฉ๋ํ๋ ๊ฒฝํฅ์ด ์์ต๋๋ค.
- ํจ์น ํ์๋ ํจ์/๋ ์ด์์ ์ฃผ์๊ฐ ์ด๋ํ ์ ์์ต๋๋ค; ํจ์น๋ฅผ ๋ค์ ์คํํด์ผ ํ๋ ๊ฒฝ์ฐ ํจ์น๋ ํ์ผ์์ `.rela.dyn` addends๋ก๋ถํฐ ์์ฑ์(constructor)๋ฅผ ํญ์ ์ฌ๊ณ์ฐํ์ธ์.
์ต์ํ์ ART/JNI ์ด๊ธฐํ๋ก INIT0 ๋ฐ JNI_OnLoad0 ํธ์ถํ๊ธฐ
- JNIInvocation์ ์ฌ์ฉํด ๋
๋ฆฝ ์คํ ๋ฐ์ด๋๋ฆฌ์์ ์์ ART VM ์ปจํ
์คํธ๋ฅผ ๊ตฌ๋ํ์ธ์. ๊ทธ๋ฐ ๋ค์ ์ด๋ค Java ์ฝ๋๋ณด๋ค ๋จผ์ ์๋์ผ๋ก `INIT0()`์ `JNI_OnLoad0(vm)`๋ฅผ ํธ์ถํฉ๋๋ค.
- ํ๊น APK/classes๋ฅผ classpath์ ํฌํจ์์ผ `RegisterNatives`๊ฐ Java ํด๋์ค๋ฅผ ์ฐพ์ ์ ์๊ฒ ํ์ธ์.
<details>
<summary>์ต์ ํ๋์ค (CMake ๋ฐ C) โ INIT0 โ JNI_OnLoad0 โ Java ๋ฉ์๋ ํธ์ถ</summary>
```cmake
# CMakeLists.txt
project(caller)
cmake_minimum_required(VERSION 3.8)
include_directories(AFTER ${CMAKE_SOURCE_DIR}/include)
link_directories(${CMAKE_SOURCE_DIR}/lib)
find_library(log-lib log REQUIRED)
add_executable(caller "caller.c")
add_library(jenv SHARED "jnihelper.c")
target_link_libraries(caller jenv nativestaticinit)
// caller.c
#include <jni.h>
#include "jenv.h"
JavaCTX ctx;
void INIT0();
void JNI_OnLoad0(JavaVM* vm);
int main(){
char *jvmopt = "-Djava.class.path=/data/local/tmp/base.apk"; // include app classes
if (initialize_java_environment(&ctx,&jvmopt,1)!=0) return -1;
INIT0(); // manual constructor
JNI_OnLoad0(ctx.vm); // manual JNI init
jclass c = (*ctx.env)->FindClass(ctx.env, "eu/nviso/nativestaticinit/MainActivity");
jmethodID m = (*ctx.env)->GetStaticMethodID(ctx.env,c,"stringFromJNI","()Ljava/lang/String;");
jstring s = (jstring)(*ctx.env)->CallStaticObjectMethod(ctx.env,c,m);
const char* p = (*ctx.env)->GetStringUTFChars(ctx.env,s,NULL);
printf("Native string: %s\n", p);
cleanup_java_env(&ctx);
}
# Build (adjust NDK/ABI)
cmake -DANDROID_PLATFORM=31 \
-DCMAKE_TOOLCHAIN_FILE=$HOME/Android/Sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a ..
make
์ผ๋ฐ์ ์ธ ํจ์ :
- ์์ฑ์ ์ฃผ์๋ ๋ฆฌ๋ ์ด์์ ๋๋ฌธ์ ํจ์น ํ ๋ณ๊ฒฝ๋ฉ๋๋ค; ์ต์ข
๋ฐ์ด๋๋ฆฌ์์
.rela.dyn์ผ๋ก ํญ์ ๋ค์ ๊ณ์ฐํ์ธ์. -Djava.class.path๊ฐRegisterNativesํธ์ถ์์ ์ฌ์ฉ๋๋ ๋ชจ๋ ํด๋์ค๋ฅผ ํฌํจํ๋์ง ํ์ธํ์ธ์.- ๋์์ NDK/loader ๋ฒ์ ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง ์ ์์ต๋๋ค; ์ผ๊ด๋๊ฒ ์ ๋ขฐํ ์ ์์๋ ๋จ๊ณ๋
INIT_ARRAY/INIT_ARRAYSZDYNAMIC ํ๊ทธ๋ฅผ ์ ๊ฑฐํ๋ ๊ฒ์ด์์ต๋๋ค.
์ฐธ๊ณ ์๋ฃ
- ARM ์ด์ ๋ธ๋ฆฌ ํ์ต: Azeria Labs โ ARM Assembly Basics
- JNI ๋ฐ NDK ๋ฌธ์: Oracle JNI Spec ยท Android JNI Tips ยท NDK Guides
- ๋ค์ดํฐ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋ฒ๊น : Debug Android Native Libraries Using JEB Decompiler
- Frida 16.x ๋ณ๊ฒฝ ๋ก๊ทธ (Android hooking, tiny-function relocation) โ frida.re/news
- libwebp ์ค๋ฒํ๋ก์ฐ์ ๋ํ NVD ๊ถ๊ณ CVE-2023-4863 โ nvd.nist.gov
- SoTap: ๊ฒฝ๋ ์ธ์ฑ JNI (.so) ๋์ ๋ก๊ฑฐ โ github.com/RezaArbabBot/SoTap
- SoTap Releases โ github.com/RezaArbabBot/SoTap/releases
- SoTap ์ฌ์ฉ ๋ฐฉ๋ฒ โ t.me/ForYouTillEnd/13
- CoRPhone โ JNI memory-only execution pattern and packaging
- Patching Android ARM64 library initializers for easy Frida instrumentation and debugging
- LIEF Project
- JNIInvocation
- soSaver โ Frida ๊ธฐ๋ฐ Android
.so๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋คํผ โ github.com/TheQmaks/sosaver - soSaver Frida ์์ด์ ํธ (TypeScript/JS) โ github.com/TheQmaks/soSaver-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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


