Slide 1

Slide 1 text

@jebstuart — ware.to/reverse Reverse-Engineering on the Device:
 How Far Can We Go? Jeb Ware American Express

Slide 2

Slide 2 text

@jebstuart — ware.to/reverse Reverse-Engineering on the Device:
 How Far Can We Go? Jeb Ware American Express

Slide 3

Slide 3 text

@jebstuart — ware.to/reverse Views expressed here are my own 
 and do not necessarily reflect 
 the views of my employer.

Slide 4

Slide 4 text

@jebstuart — ware.to/reverse Reverse-Engineering on Device? APK

Slide 5

Slide 5 text

@jebstuart — ware.to/reverse Reverse-Engineering on Device? APK

Slide 6

Slide 6 text

@jebstuart — ware.to/reverse # Reverse-Engineering on Device? APK

Slide 7

Slide 7 text

@jebstuart — ware.to/reverse Reverse-Engineering on Device! APK APK

Slide 8

Slide 8 text

@jebstuart — ware.to/reverse App Sandboxing APK Sandbox res dex so asset files db shared pref keys APK Sandbox res dex so asset files db shared pref keys APK Sandbox res dex so asset files db shared pref keys

Slide 9

Slide 9 text

@jebstuart — ware.to/reverse /data/app/com.example.yourapp-1/base.apk

Slide 10

Slide 10 text

@jebstuart — ware.to/reverse /data/app/com.example.yourapp-1/base.apk context.packageManager .getInstalledApplications(...) .map { it.publicSourceDir }

Slide 11

Slide 11 text

@jebstuart — ware.to/reverse /data/app/com.example.yourapp-1/base.apk context.packageManager .getInstalledApplications(...) .map { it.publicSourceDir }

Slide 12

Slide 12 text

@jebstuart — ware.to/reverse APK • AndroidManifest.xml • assets/ • … • classes.dex • classes2.dex • res/ • anim/ • color/ • drawable/ • layout/ • raw/ • …

Slide 13

Slide 13 text

@jebstuart — ware.to/reverse val zip = ZipFile(appInfo.publicSourceDir)
 zip.entries().toList() .map { zip.getInputStream(it) } .onEach { ... }

Slide 14

Slide 14 text

@jebstuart — ware.to/reverse Compiled XML ? @.;FP}?
 interpolatordurationshareInterpolator fromYDeltatoYDeltaandroid**http:// schemas.android.com/apk/res/androidset translate?A????????8????????????t???????????? ?????????????????????????????????

Slide 15

Slide 15 text

@jebstuart — ware.to/reverse val appId = “com.example.yourapp" val res: Resources = packageManager.getResourcesForApplication(appId)

Slide 16

Slide 16 text

@jebstuart — ware.to/reverse val res: Resources = packageManager.getResourcesForApplication(appId) res.getString(0x7f0e0003)

Slide 17

Slide 17 text

@jebstuart — ware.to/reverse val res: Resources = packageManager.getResourcesForApplication(appId) res.getString(0x7f0e0003) “Hello, World!”

Slide 18

Slide 18 text

@jebstuart — ware.to/reverse val res: Resources = packageManager.getResourcesForApplication(appId) res.getString(0x7f0e0003) “Hello, World!” ???

Slide 19

Slide 19 text

@jebstuart — ware.to/reverse Resource IDs 0x7f0e0003

Slide 20

Slide 20 text

@jebstuart — ware.to/reverse Resource IDs 0x7f0e0003 ??? ??? ???

Slide 21

Slide 21 text

@jebstuart — ware.to/reverse

Slide 22

Slide 22 text

@jebstuart — ware.to/reverse

Slide 23

Slide 23 text

@jebstuart — ware.to/reverse Resource IDs 0x7f0e0003

Slide 24

Slide 24 text

@jebstuart — ware.to/reverse 0e Resource IDs { const 0x7f 0003

Slide 25

Slide 25 text

@jebstuart — ware.to/reverse 0e Resource IDs { { const type 0x7f 0003

Slide 26

Slide 26 text

@jebstuart — ware.to/reverse 0e Resource IDs { { { const type identifier 0x7f 0003

Slide 27

Slide 27 text

@jebstuart — ware.to/reverse Enumerating Resources 0x7f 0000 01

Slide 28

Slide 28 text

@jebstuart — ware.to/reverse Enumerating Resources 0x7f 0001 01

Slide 29

Slide 29 text

@jebstuart — ware.to/reverse Enumerating Resources 0x7f 0002 01

Slide 30

Slide 30 text

@jebstuart — ware.to/reverse Enumerating Resources 0x7f 0003 01

Slide 31

Slide 31 text

@jebstuart — ware.to/reverse Enumerating Resources 0x7f 0003 01 ResourceNotFoundException

Slide 32

Slide 32 text

@jebstuart — ware.to/reverse Enumerating Resources 0x7f 0000 02

Slide 33

Slide 33 text

@jebstuart — ware.to/reverse Enumerating Resources val res: Resources = packageManager.getResourcesForApplication(appId) val name = res.getResourceName(0x7f0e0003) val type = res.getResourceTypeName(0x7f0e0003) val entry = res.getResourceEntryName(0x7f0e0003)

Slide 34

Slide 34 text

@jebstuart — ware.to/reverse Enumerating Resources val res: Resources = packageManager.getResourcesForApplication(appId) val name = res.getResourceName(0x7f0e0003) val type = res.getResourceTypeName(0x7f0e0003) val entry = res.getResourceEntryName(0x7f0e0003) “anim” “abc_slide_out_top” “com.example:anim/abc_slide_out_top”

Slide 35

Slide 35 text

@jebstuart — ware.to/reverse Loading Resource Values val res: Resources = packageManager.getResourcesForApplication(appId) res.getBoolean(0x7f0e0123) res.getColor(0x7f0e0123, null) res.getDimension(0x7f0e0123) res.getDrawable(0x7f0e0123, null) res.getInteger(0x7f0e0123) res.getString(0x7f0e0123)

Slide 36

Slide 36 text

@jebstuart — ware.to/reverse Live demo!

Slide 37

Slide 37 text

@jebstuart — ware.to/reverse Enumerating Assets val res: Resources = packageManager.getResourcesForApplication(appId) val fileNames = res.assets.list("")

Slide 38

Slide 38 text

@jebstuart — ware.to/reverse Enumerating Assets val res: Resources = packageManager.getResourcesForApplication(appId) val fileNames = res.assets.list("") AMobileConfig.json bar.properties fonts html settings.json

Slide 39

Slide 39 text

@jebstuart — ware.to/reverse Enumerating Assets val inputStream = res.assets.open(path) // for image val bitmap = BitmapFactory.decodeStream(inputStream) // for text file val text = inputStream.reader().readLines()

Slide 40

Slide 40 text

@jebstuart — ware.to/reverse Live demo?

Slide 41

Slide 41 text

@jebstuart — ware.to/reverse DEX files

Slide 42

Slide 42 text

@jebstuart — ware.to/reverse DEX files

Slide 43

Slide 43 text

@jebstuart — ware.to/reverse DEX files val apk = ZipFile(appInfo.publicSourceDir) val dexEntries = apk.entries().toList() .filter { it.name.startsWith("classes") && it.name.endsWith(".dex") }

Slide 44

Slide 44 text

@jebstuart — ware.to/reverse

Slide 45

Slide 45 text

@jebstuart — ware.to/reverse .class files

Slide 46

Slide 46 text

@jebstuart — ware.to/reverse .dex file .class files

Slide 47

Slide 47 text

@jebstuart — ware.to/reverse .dex file

Slide 48

Slide 48 text

@jebstuart — ware.to/reverse .dex file header

Slide 49

Slide 49 text

@jebstuart — ware.to/reverse .dex file header strings table

Slide 50

Slide 50 text

@jebstuart — ware.to/reverse .dex file header strings table code ’n’ stuff

Slide 51

Slide 51 text

@jebstuart — ware.to/reverse .dex file header strings table code ’n’ stuff

Slide 52

Slide 52 text

@jebstuart — ware.to/reverse implementation 'com.jakewharton.android.repackaged:dalvik-dx:9.0.0_r3'

Slide 53

Slide 53 text

@jebstuart — ware.to/reverse import com.android.dex.Dex val strings = dexFiles.flatMap { val dex = Dex(it.readBytes()) dex.strings() }

Slide 54

Slide 54 text

@jebstuart — ware.to/reverse import com.android.dex.Dex val strings = dexFiles.flatMap { val dex = Dex(it.readBytes()) dex.strings() }

Slide 55

Slide 55 text

@jebstuart — ware.to/reverse import com.android.dex.Dex val strings = dexFiles.flatMap { val dex = Dex(it.readBytes()) dex.strings() }

Slide 56

Slide 56 text

@jebstuart — ware.to/reverse import com.android.dex.Dex val strings = dexFiles.flatMap { val dex = Dex(it.readBytes()) dex.strings() }

Slide 57

Slide 57 text

@jebstuart — ware.to/reverse ¡Live demo!

Slide 58

Slide 58 text

@jebstuart — ware.to/reverse .dex file header strings table code ’n’ stuff

Slide 59

Slide 59 text

@jebstuart — ware.to/reverse implementation 'org.smali:baksmali:2.3.4'

Slide 60

Slide 60 text

@jebstuart — ware.to/reverse val dexFile = DexFileFactory.loadDexEntry( File(appInfo.publicSourceDir), // APK file "classes.dex", // name of dex file within true, // exactMatch null // opcodes )

Slide 61

Slide 61 text

@jebstuart — ware.to/reverse val dexFile = DexFileFactory.loadDexEntry( File(appInfo.publicSourceDir), // APK file "classes.dex", // name of dex file within true, // exactMatch null // opcodes )

Slide 62

Slide 62 text

@jebstuart — ware.to/reverse val dexFile = DexFileFactory.loadDexEntry( File(appInfo.publicSourceDir), // APK file "classes.dex", // name of dex file within true, // exactMatch null // opcodes )

Slide 63

Slide 63 text

@jebstuart — ware.to/reverse val dexFile = DexFileFactory.loadDexEntry( File(appInfo.publicSourceDir), // APK file "classes.dex", // name of dex file within true, // exactMatch null // opcodes )

Slide 64

Slide 64 text

@jebstuart — ware.to/reverse val dexFile = DexFileFactory.loadDexEntry( File(appInfo.publicSourceDir), // APK file "classes.dex", // name of dex file within true, // exactMatch null // opcodes )

Slide 65

Slide 65 text

@jebstuart — ware.to/reverse val dexFile = DexFileFactory.loadDexEntry( File(appInfo.publicSourceDir), // APK file "classes.dex", // name of dex file within true, // exactMatch null // opcodes ) Baksmali.disassembleDexFile( dexFile, outputDir, 10, // jobs BaksmaliOptions() )

Slide 66

Slide 66 text

@jebstuart — ware.to/reverse val dexFile = DexFileFactory.loadDexEntry( File(appInfo.publicSourceDir), // APK file "classes.dex", // name of dex file within true, // exactMatch null // opcodes ) Baksmali.disassembleDexFile( dexFile, outputDir, 10, // jobs BaksmaliOptions() )

Slide 67

Slide 67 text

@jebstuart — ware.to/reverse val dexFile = DexFileFactory.loadDexEntry( File(appInfo.publicSourceDir), // APK file "classes.dex", // name of dex file within true, // exactMatch null // opcodes ) Baksmali.disassembleDexFile( dexFile, outputDir, 10, // jobs BaksmaliOptions() )

Slide 68

Slide 68 text

@jebstuart — ware.to/reverse val dexFile = DexFileFactory.loadDexEntry( File(appInfo.publicSourceDir), // APK file "classes.dex", // name of dex file within true, // exactMatch null // opcodes ) Baksmali.disassembleDexFile( dexFile, outputDir, 10, // jobs BaksmaliOptions() )

Slide 69

Slide 69 text

@jebstuart — ware.to/reverse val dexFile = DexFileFactory.loadDexEntry( File(appInfo.publicSourceDir), // APK file "classes.dex", // name of dex file within true, // exactMatch null // opcodes ) Baksmali.disassembleDexFile( dexFile, outputDir, 10, // jobs BaksmaliOptions() )

Slide 70

Slide 70 text

@jebstuart — ware.to/reverse val dexFile = DexFileFactory.loadDexEntry( File(appInfo.publicSourceDir), // APK file "classes.dex", // name of dex file within true, // exactMatch null // opcodes ) Baksmali.disassembleDexFile( dexFile, outputDir, 10, // jobs BaksmaliOptions() )

Slide 71

Slide 71 text

@jebstuart — ware.to/reverse ¿Live demo?

Slide 72

Slide 72 text

@jebstuart — ware.to/reverse DexClassLoader classLoader = DexClassLoader( targetFile.absolutePath, null, null, classLoader)

Slide 73

Slide 73 text

@jebstuart — ware.to/reverse val clazz = classLoader.loadClass("com.example.MyClass")

Slide 74

Slide 74 text

@jebstuart — ware.to/reverse implementation 'com.jakewharton.dex:dex-member-list:3.3.0'

Slide 75

Slide 75 text

@jebstuart — ware.to/reverse Enumerating Classes val members: List = DexParser.fromFile(dexFile).list() member.declaringType

Slide 76

Slide 76 text

@jebstuart — ware.to/reverse val clazz = classLoader.loadClass(fqcn)
 val modifiers = clazz.getDeclaredField(fieldName).modifiers val public: Boolean = Modifier.isPublic(modifiers)

Slide 77

Slide 77 text

@jebstuart — ware.to/reverse val field = clazz.getDeclaredField(fieldName) val instance = clazz.newInstance() 
 val value = field.get(instance)

Slide 78

Slide 78 text

@jebstuart — ware.to/reverse val clazz = targetClassLoader.loadClass(declaringType) val instance = clazz.newInstance() val method = clazz.getDeclaredMethod(methodName, String::class.java, Boolean::class.java) val result = method.invoke(instance, "arg1", true)

Slide 79

Slide 79 text

@jebstuart — ware.to/reverse Live demo?!

Slide 80

Slide 80 text

@jebstuart — ware.to/reverse Loading Layouts

Slide 81

Slide 81 text

@jebstuart — ware.to/reverse java.lang.ClassNotFoundException: Didn't find class "android.support.v7.widget.ActivityChooserView$InnerLayout" on path: DexPathList[ [zip file “/data/app/com.jebware.appspy-A_W1…2Q==/base.apk”], nativeLibraryDirectories=[ /data/app/com.jebware.appspy-A_W1…2Q==/lib/arm64, /system/lib64
 ] ]

Slide 82

Slide 82 text

@jebstuart — ware.to/reverse val flags = CONTEXT_INCLUDE_CODE val targetContext = createPackageContext("com.example.app", flags)

Slide 83

Slide 83 text

@jebstuart — ware.to/reverse val flags = CONTEXT_INCLUDE_CODE val targetContext = createPackageContext("com.example.app", flags) SecurityException

Slide 84

Slide 84 text

@jebstuart — ware.to/reverse val flags = CONTEXT_INCLUDE_CODE or CONTEXT_IGNORE_SECURITY val targetContext = createPackageContext("com.example.app", flags)

Slide 85

Slide 85 text

@jebstuart — ware.to/reverse val flags = CONTEXT_INCLUDE_CODE or CONTEXT_IGNORE_SECURITY val targetContext = createPackageContext(targetPackageName, flags)

Slide 86

Slide 86 text

@jebstuart — ware.to/reverse val targetLayoutInflater = layoutInflater .cloneInContext(targetContext)

Slide 87

Slide 87 text

@jebstuart — ware.to/reverse val targetLayout = targetLayoutInflater .inflate(targetLayoutId, null) setContentView(targetLayout)

Slide 88

Slide 88 text

@jebstuart — ware.to/reverse Live Demo!!

Slide 89

Slide 89 text

@jebstuart — ware.to/reverse APK Sandbox res dex so asset files db shared pref keys APK Sandbox res dex so asset files db shared pref keys APK Sandbox res dex so asset files db shared pref keys

Slide 90

Slide 90 text

@jebstuart — ware.to/reverse APK Sandbox res dex so asset files db shared pref keys APK Sandbox res dex so asset files db shared pref keys APK Sandbox res dex so asset files db shared pref keys uid 10001 uid 10002 uid 10003

Slide 91

Slide 91 text

@jebstuart — ware.to/reverse APK Sandbox res dex so asset files db shared pref keys APK Sandbox res dex so asset files db shared pref keys APK Sandbox res dex so asset files db shared pref keys uid 10001 uid 10002 uid 10003 APK

Slide 92

Slide 92 text

@jebstuart — ware.to/reverse “external” storage

Slide 93

Slide 93 text

@jebstuart — ware.to/reverse “external” storage Context.getExternalFilesDir()

Slide 94

Slide 94 text

@jebstuart — ware.to/reverse “external” storage Context.getExternalFilesDir() 
 
 
 /storage/emulated/0/Android/data/com.example/files 
 
 
 
 


Slide 95

Slide 95 text

@jebstuart — ware.to/reverse “external” storage Context.getExternalFilesDir() 
 Environment.getExternalStoragePublicDirectory(
 Environment.DIRECTORY_PICTURES) 
 
 /storage/emulated/0/Android/data/com.example/files 
 
 
 /storage/emulated/0/Pictures
 


Slide 96

Slide 96 text

@jebstuart — ware.to/reverse “external” storage Context.getExternalFilesDir() 
 Environment.getExternalStoragePublicDirectory(
 Environment.DIRECTORY_PICTURES) 
 Environment.getExternalStorageDirectory() 
 /storage/emulated/0/Android/data/com.example/files 
 
 
 /storage/emulated/0/Pictures
 
 
 /storage/emulated/0
 


Slide 97

Slide 97 text

@jebstuart — ware.to/reverse “external” storage Context.getExternalFilesDir() 
 Environment.getExternalStoragePublicDirectory(
 Environment.DIRECTORY_PICTURES) 
 Environment.getExternalStorageDirectory() 
 System.getenv("EXTERNAL_STORAGE") /storage/emulated/0/Android/data/com.example/files 
 
 
 /storage/emulated/0/Pictures
 
 
 /storage/emulated/0
 
 
 /sdcard

Slide 98

Slide 98 text

@jebstuart — ware.to/reverse “external” storage Context.getExternalFilesDir() 
 (no permission) 
 Environment.getExternalStorageDirectory() 
 android.Manifest.permission.READ_EXTERNAL_STORAGE /storage/emulated/0/Android/data/com.example/files 
 
 
 
 
 
 /storage/emulated/0
 
 


Slide 99

Slide 99 text

@jebstuart — ware.to/reverse val path = file.toPath() // java.nio.file.Path

Slide 100

Slide 100 text

@jebstuart — ware.to/reverse val path = file.toPath() // java.nio.file.Path val uid = Files.getAttribute(path, "unix:uid") as Int

Slide 101

Slide 101 text

@jebstuart — ware.to/reverse val path = file.toPath() // java.nio.file.Path val uid = Files.getAttribute(path, "unix:uid") as Int // String[] val packages = packageManager.getPackagesForUid(uid)
 packageManager.getApplicationInfo(packages.first(), 0)

Slide 102

Slide 102 text

@jebstuart — ware.to/reverse Live Demo!!

Slide 103

Slide 103 text

@jebstuart — ware.to/reverse Takeaways • Sandbox protects private data, keys, etc. • Not code, resources, assets. • “External” storage is (effectively) world-readable • Many RE tools available - some will run inside another app

Slide 104

Slide 104 text

@jebstuart — ware.to/reverse Questions? Jeb Ware
 American Express
 
 @jebstuart
 http://ware.to/reverse