Slide 1

Slide 1 text

Reverse-Engineering on the Device:
 How Far Can We Go? Jeb Ware American Express

Slide 2

Slide 2 text

Reverse-Engineering on the Device:
 How Far Can We Go? Jeb Ware American Express

Slide 3

Slide 3 text

Views expressed here are my own 
 and do not necessarily reflect 
 the views of my employer.

Slide 4

Slide 4 text

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 5

Slide 5 text

/data/app/com.example.yourapp-1/base.apk

Slide 6

Slide 6 text

/data/app/com.example.yourapp-1/base.apk context.packageManager .getInstalledApplications(...) .map { it.publicSourceDir }

Slide 7

Slide 7 text

/data/app/com.example.yourapp-1/base.apk context.packageManager .getInstalledApplications(...) .map { it.publicSourceDir }

Slide 8

Slide 8 text

APK • AndroidManifest.xml • assets/ • … • classes.dex • classes2.dex • res/ • anim/ • color/ • drawable/ • layout/ • raw/ • …

Slide 9

Slide 9 text

val zip = ZipFile(appInfo.publicSourceDir)
 zip.entries().toList() .map { zip.getInputStream(it) } .onEach { ... }

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

val appId = “com.example.yourapp" val res: Resources = packageManager.getResourcesForApplication(appId)

Slide 12

Slide 12 text

val res: Resources = packageManager.getResourcesForApplication(appId) res.getString(0x7f0e0003)

Slide 13

Slide 13 text

val res: Resources = packageManager.getResourcesForApplication(appId) res.getString(0x7f0e0003) “Hello, World!”

Slide 14

Slide 14 text

val res: Resources = packageManager.getResourcesForApplication(appId) res.getString(0x7f0e0003) “Hello, World!” ???

Slide 15

Slide 15 text

Resource IDs 0x7f0e0003

Slide 16

Slide 16 text

Resource IDs 0x7f0e0003 ??? ??? ???

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

Resource IDs 0x7f0e0003

Slide 20

Slide 20 text

0e Resource IDs { const 0x7f 0003

Slide 21

Slide 21 text

0e Resource IDs { { const type 0x7f 0003

Slide 22

Slide 22 text

0e Resource IDs { { { const type identifier 0x7f 0003

Slide 23

Slide 23 text

Enumerating Resources 0x7f 0000 01

Slide 24

Slide 24 text

Enumerating Resources 0x7f 0001 01

Slide 25

Slide 25 text

Enumerating Resources 0x7f 0002 01

Slide 26

Slide 26 text

Enumerating Resources 0x7f 0003 01

Slide 27

Slide 27 text

Enumerating Resources 0x7f 0003 01 ResourceNotFoundException

Slide 28

Slide 28 text

Enumerating Resources 0x7f 0000 02

Slide 29

Slide 29 text

Enumerating Resources val res: Resources = packageManager.getResourcesForApplication(appId) val name = res.getResourceName(0x7f0e0003) val type = res.getResourceTypeName(0x7f0e0003) val entry = res.getResourceEntryName(0x7f0e0003)

Slide 30

Slide 30 text

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 31

Slide 31 text

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 32

Slide 32 text

Live demo!

Slide 33

Slide 33 text

Enumerating Assets val res: Resources = packageManager.getResourcesForApplication(appId) val fileNames = res.assets.list("")

Slide 34

Slide 34 text

Enumerating Assets val res: Resources = packageManager.getResourcesForApplication(appId) val fileNames = res.assets.list("") AMobileConfig.json bar.properties fonts html settings.json

Slide 35

Slide 35 text

Enumerating Assets val inputStream = res.assets.open(path) // for image val bitmap = BitmapFactory.decodeStream(inputStream) // for text file val text = inputStream.reader().readLines()

Slide 36

Slide 36 text

Live demo?

Slide 37

Slide 37 text

DEX files

Slide 38

Slide 38 text

DEX files

Slide 39

Slide 39 text

DEX files val apk = ZipFile(appInfo.publicSourceDir) val dexEntries = apk.entries().toList() .filter { it.name.startsWith("classes") && it.name.endsWith(".dex") }

Slide 40

Slide 40 text

DexClassLoader classLoader = DexClassLoader( targetFile.absolutePath, null, null, classLoader)

Slide 41

Slide 41 text

val clazz = classLoader.loadClass("com.example.MyClass")

Slide 42

Slide 42 text

implementation 'com.jakewharton.dex:dex-member-list:3.3.0'

Slide 43

Slide 43 text

implementation 'com.jakewharton.dex:dex-member-list:3.3.0' implementation('androidx.appcompat:appcompat:1.0.2') { exclude group: 'com.google.guava', module: 'listenablefuture' }

Slide 44

Slide 44 text

Enumerating Classes val members: List = DexParser.fromFile(dexFile).list() member.declaringType

Slide 45

Slide 45 text

val clazz = classLoader.loadClass(fqcn)
 val modifiers = clazz.getDeclaredField(fieldName).modifiers val public: Boolean = Modifier.isPublic(modifiers)

Slide 46

Slide 46 text

val field = clazz.getDeclaredField(fieldName) val instance = clazz.newInstance() 
 val value = field.get(instance)

Slide 47

Slide 47 text

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 48

Slide 48 text

Live demo?!

Slide 49

Slide 49 text

Loading Layouts

Slide 50

Slide 50 text

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 51

Slide 51 text

val flags = CONTEXT_INCLUDE_CODE val targetContext = createPackageContext("com.example.app", flags)

Slide 52

Slide 52 text

val flags = CONTEXT_INCLUDE_CODE val targetContext = createPackageContext("com.example.app", flags) SecurityException

Slide 53

Slide 53 text

val flags = CONTEXT_INCLUDE_CODE or CONTEXT_IGNORE_SECURITY val targetContext = createPackageContext("com.example.app", flags)

Slide 54

Slide 54 text

val flags = CONTEXT_INCLUDE_CODE or CONTEXT_IGNORE_SECURITY val targetContext = createPackageContext(targetPackageName, flags)

Slide 55

Slide 55 text

val targetLayoutInflater = layoutInflater .cloneInContext(targetContext)

Slide 56

Slide 56 text

val targetLayout = targetLayoutInflater .inflate(targetLayoutId, null) setContentView(targetLayout)

Slide 57

Slide 57 text

Live Demo!!

Slide 58

Slide 58 text

Takeaways • Sandbox protects private data, keys, etc. • Not code, resources, assets.

Slide 59

Slide 59 text

Questions? Jeb Ware
 American Express
 
 @jebstuart