how to reverse engineer android applications

38
How to reverse engineer Android applications Finding Vulnerabilities through Reverse Engineering Hasso Plattner Institute, Potsdam Hubert Hesse, Lukas Pirl, Christoph Matthies, Conrad Calmez using a popular word game as an example ? ? Images: “Freepik” on flaticon.com (CC BY 3.0), Google (CC BY 3.0)

Upload: hubx

Post on 25-Jul-2015

58 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: How to reverse engineer Android applications

How to reverse engineer Android applications

Finding Vulnerabilities through Reverse Engineering

Hasso Plattner Institute, Potsdam

Hubert Hesse, Lukas Pirl,

Christoph Matthies, Conrad Calmez

using a popular word game as an example

??Images: “Freepik” on flaticon.com (CC BY 3.0), Google (CC BY 3.0)

Page 2: How to reverse engineer Android applications

1 Get the .apk

23 4Extract the .apk

5Decompilation to Smali

Debugging

6Putting it together7 8Automation

Proxy

Decompilation to Java

Page 3: How to reverse engineer Android applications

Our Example—a word game

● Top 10 word game in 145 countries (as of July 2014)

● More than 10.000.000 installs● Over 50 million players● Play online (with friends)● 14 languages● Free and premium version

Page 4: How to reverse engineer Android applications

1:58 0 points

S N B I

L U SF

E I T

T E RP

A

Page 5: How to reverse engineer Android applications

1:58 15 points

S N B I

L U SF

E I T

T E RP

A

FLUT +15

Page 6: How to reverse engineer Android applications

● APK (application package file), archive file, based on JAR format

● Similar to Deb packages (in Ubuntu) or MSI packages (in Windows)

● Contains program code, resources, assets, certificates, and manifest file

● Can’t be directly downloaded from App Store

1Get the .apk

Download using online “APK Downloader” (http://apps.evozi.com/apk-downloader/)

- or -

Install on device and download using SDK tools(adb pull <app_path> downloaded.apk)

Page 7: How to reverse engineer Android applications

2Extract the .apk

● Normal decompression using unzip fails● Special tool: APKTool

○ Standard is APKTool 1.5.2. (not able to recompress correctly) (https:

//code.google.com/p/android-apktool/downloads/list)

○ APKTool 2.0.0 Beta 9 works(http://connortumbleson.com/2014/02/apktool-2-0-0-beta-9-released/)

Decrompressing:

apktool d -d game.apk -o outdir

Page 8: How to reverse engineer Android applications

2Extract the .apk

Page 9: How to reverse engineer Android applications

2Modifying resources

● Change arbitrary resources● Repack into .apk file and install

Recrompressing:

apktool b -d outdir -o com.company.game.free_patch.apk

● Recompression works, Android fails with “can’t install”, wrong certificate○ APKTool tries to reuse as much as possible, doesn’t

recompute signature

Page 10: How to reverse engineer Android applications

2Manually sign repacked apk:

● Create custom CA● Java JAR Signing and Verification Tool

(http://docs.oracle.com/javase/7/docs/technotes/tools/windows/jarsigner.html)

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore com.company.game.free_patch.apk alias_name

Modifying resources

Page 11: How to reverse engineer Android applications
Page 12: How to reverse engineer Android applications

.apk contains compiled code

● Dalvik bytecode interpreted by the Dalvik Process virtual machine

● Stored in .dex (Dalvik EXecutable) files

APKTool translates this to “smali” (https://code.google.com/p/smali/)

● Abstraction of bytecode, closer to Java● Dalvik opcodes (http://s.android.com/tech/dalvik/dalvik-bytecode.html)

● Can be edited directly

3Decompilation to Smali

Page 13: How to reverse engineer Android applications

.class public LHelloWorld;

.super Ljava/lang/Object;

.method public static main([Ljava/lang/String;)V

.registers 2

sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;

const-string v1, "Hello World!"

invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V

return-void

.end method

3Smali Hello World

Page 14: How to reverse engineer Android applications

Interactive debugging

● Set debuggable=”true” in AndroidManifest.xml○ Repack using APKTool

● Need to connect smali sources to binary● Workaround: pretend we have valid Java code

4Debugging

<application android:allowBackup="true" android:hardwareAccelerated="true"

android:icon="@drawable/launcher_icon" android:label="@string/app_name"

android:name="com.company.game.core.GameApplication" android:theme="

@style/Theme.GameTheme" android:debuggable="true">

Page 15: How to reverse engineer Android applications

a=0;// .class public abstract La;a=0;// .super Ljava/lang/Object;a=0;// a=0;// a=0;// # instance fieldsa=0;// .field protected final a:Ljava/lang/Object;a=0;// a=0;// .field private final b:Landroid/os/Handler;a=0;//

4Debugging

Smali code in commentsPlaceholder

Java

Page 16: How to reverse engineer Android applications

Two ways to obtain java code

● Convert .dex files to .jar○ Use standard java bytecode decompilers

● Disassemble .dex directly to .java

5Decompilation to Java

Page 17: How to reverse engineer Android applications

Using dex files

● Androguard (https://code.google.com/p/androguard/)

○ Maps DEX format into full Python objects○ Works in memory (My 4GB machine wasn’t enough)

○ Doesn’t immediately dump code into Java files

5Decompilation to Java

Page 18: How to reverse engineer Android applications

Using jar files

● dex2jar (https://code.google.com/p/dex2jar/)

○ dex2jar, jar2dex, apk-sign○ Supports recreating .dex from Java

● JD-GUI (http://jd.benow.ca/)

○ Popular jar-decompiler○ Works 100% with “Hello World” app

5Decompilation to Java

Page 19: How to reverse engineer Android applications

Combining Java decompilation and Smali

● Java more readable than Smali● Unfortunately Java decompilation not

100% perfect

○ Invalid Java constructs or only

method signatures○ Cannot recompile from Java sources

6Putting it together

Page 20: How to reverse engineer Android applications

private void fixSpecialChars() { int i; char ac[]; int j; int k; i = 0; ac = tiles; j = ac.length; k = 0;_L9: if(k >= j) break MISSING_BLOCK_LABEL_161; ac[k]; JVM INSTR lookupswitch 6: default 80 // 40: 125 // 41: 137 // 47: 149 // 91: 89 // 92: 101 // 93: 113; goto _L1 _L2 _L3 _L4 _L5 _L6 _L7_L4: break MISSING_BLOCK_LABEL_149;_L1: break; /* Loop/switch isn't completed */_L5: break; /* Loop/switch isn't completed */_L10: i++; k++; if(true) goto _L9; else goto _L8_L8:

6When Decompilation failsan example

Goto not supported in Java

Bare JVM instructions

Page 21: How to reverse engineer Android applications

Combining Java decompilation and Smali

● Approach: Use multiple Java decompilers○ They tend to fail in different places

6Putting it together

1. Find interesting parts in Java source2. Check corresponding smali sources3. Edit those

Page 22: How to reverse engineer Android applications

protected void roundEnd(boolean paramBoolean){// …this.resultData.setTotalScore(this.totalScore);// … startRoundSummary(); if (!this.isPractice) { this.currentRound.setWordsInRound(this.resultData.getMoves().size()); // … this.currentRound.setPlayer1Moves(GameHelper.encodeMoves(this.resultData.getMoves())); this.currentRound.setPlayer1Score(this.totalScore); // …

6Manipulating the score

Opportunities for manipulation

● Server validation disallows this

Page 23: How to reverse engineer Android applications

a=0;// sget-boolean v0, Lcom/company/game/core/statics/Statics;->DEBUGGING:Z a=0;// a=0;// #v0=(Boolean);-a=0;// if-eqz v0, :cond_0+a=0;// #if-eqz v0, :cond_0 a=0;//

6Enable Loggingpublic class Toolkit{ // …

public static void Logw(String s, String s1) { if(Statics.DEBUGGING) Log.w(s, s1); } // …

Page 24: How to reverse engineer Android applications

a=0;// # static fields a=0;// .field public static ROUND_DURATION_IN_SECONDS_FOR_NORMAL_GAME:I a=0;// .field public static ROUND_DURATION_IN_SECONDS_FOR_TUTORIAL:I a=0;// a=0;// .method static constructor <clinit>()V a=0;// .locals 1 …-a=0;// const/16 v0, 0x78+a=0;// const/16 v0, 0x12c a=0;// a=0;// #v0=(PosByte); a=0;// sput v0, Lcom/company/game/core/statics/GameStatics;->ROUND_DURATION_IN_SECONDS_FOR_NORMAL_GAME:I

6More time per round

120s

300s

Page 25: How to reverse engineer Android applications

public static boolean allowPremiumContent(PremiumType premiumtype, Context context){ if(premiumIsPurchased(context)) return true; synchronized(lock) { if(!isLicensed(context)) break MISSING_BLOCK_LABEL_31; } return true;

6Getting Premium

a=0;// .line 129-a=0;// invoke-static {p0}, Lcom/company/game/util/PremiumCampaignHelper;->premiumIsPurchased(…;)Z+a=0;// # invoke-static {p0}, Lcom/company/game/util/PremiumCampaignHelper;->premiumIsPurchased(…;)Z a=0;// -a=0;// move-result v0+a=0;// # move-result v0 a=0;// -a=0;// #v0=(Boolean);-a=0;// if-eqz v0, :cond_0+a=0;// #v0=(One);+a=0;// # if-eqz v0, :cond_0

Page 26: How to reverse engineer Android applications

6Getting Premium

free version premium (stats unlocked, no ads)

Page 27: How to reverse engineer Android applications

7Proxy

Route all app traffic through custom proxy

● Used MitMProxy (https://github.com/mitmproxy/mitmproxy)

● Retrieve real server URL via Wireshark● Redirect app traffic via /etc/hosts on device● Custom SSL certificate

○ Install own CA in device○ No certificate pinning

● Avoid compressed responses via HTTP header○ Accept-Encoding: gzip;q=0,deflate,sdch

Page 28: How to reverse engineer Android applications

7Proxy

AES encryption

● Shared key in decompiled code● No key derivation function● AES initialization vector in HTTP header

○ Payload-session: 2e2f6a61642f7372…○ Unencrypted// file APIConnector.javaprivate static byte sharedKey[] = { 57, -116, 126, 39, 116, -25, -95, -106, -81, 48, -33, -19, 120, 118, 35, 40, 66, 126, 31, 30, -83, 76, 31, 93, 13, -122, -50, 68, -108, -114, 28, -80};

Page 29: How to reverse engineer Android applications

SSLMitMProxy SSLHTTP

Server by “aLf “, thenounproject.com (CC BY 3.0 US)Spy by “Hopstarter ”, iconarchive.com (CC BY-NC-ND 4.0)

#! python

#decrypt AES#using IV

7ProxyHeader: AES IV

AES payload

HTTP

# /etc/hosts

# redirect# to proxy

Page 30: How to reverse engineer Android applications

7Proxy{ "cacheTimestamp": "1405377910521", "userId": "0", "conversationId": "-1", "player1MostWordsInRound": "32", "id": "6602198229545556683", "player1Score": "214", "player1LongestWord": "HEAPS", "player1User": { "username": "username", "ranking": "0", "premium": "false", "recruits": "0", "deleted": "false", "newUser": "false", "bestScoreInMatch": "0", "userId": "3005807464", "bestScoreInRound": "0", "online": "false", "facebookConnected": "false", "avatarId": "0", "matchesPlayed": "0", "useFacebookImage": "false", "mostWordsInRound": "0" },

{"rounds": [ { "seed3": "14657688", "player2MoveErrors": "0", "gameId": "6602198229545556683", "player2SwipeDistance": "681", "player2Moves": "1AB2BAE2EAB216227612AEF2DA73840127652567354013DAB723673B7654EAB72", "player1MoveErrors": "19", "player2Done": "true", "seed1": "2073207065", "seed2": "680974433", "player1SwipeDistance": "1608", "board": { "bonus": [" ", " ", " ", " ", " ", " ", "D", " ", " ", " ", " ", " ", " ", " ", " ", "T" ], "board": ["A", "T", "E", "H", "E", "P", "O", "T", "H", "S", "A", "S", "T", "F", "T", "E" ], "words": [ "TATE", "SOTS", "HOST", "SAPS", "FATSOS", …

Server responserequest size up to 100kB

Page 31: How to reverse engineer Android applications

8Automation

Play the game automatically

● Generic external approach○ No modification of binary necessary○ Works for any app

Monkeyrunner (http://developer.android.com/tools/help/monkeyrunner_concepts.html)

● Test apps at the functional/framework level● Able to simulate keystrokes, take screenshots● Python bindings

Page 32: How to reverse engineer Android applications

8Obtain all possible words to play correctly

● apk contains .jet “dictionary” for each language

● Btw, also a wordlist (probably) used to check for cheaters

Automation

Page 33: How to reverse engineer Android applications

8Automation

Ruzzle .jet files

● Binary files● Trie / Radix tree structure● Optimal for the way the game

is played● No duplicate encoding

of characters● List of all excepted

words constructable

G

GA

GAM

GAME

GO

GOD GOT

G

O

D T

A

M

E

Page 34: How to reverse engineer Android applications

8Automation

Achieving the highscore

● Get all 16 letters○ Input by hand / screenshot + OCR

● Find all valid words using the extracted dictionary

● Simulate keystrokes for found words

○ Actually not enough time to enter all

valid words

Page 35: How to reverse engineer Android applications

8Automation

DEMO

Page 36: How to reverse engineer Android applications

Achievements

Found possibilities to:

✓ Enable logging✓ Unlock premium features✓ Achieve insanely high score through automation✓ Extract protocol via man-in-the-middle attack

Page 37: How to reverse engineer Android applications

Backup slides

Page 38: How to reverse engineer Android applications

Pinned certificate(installed at dev. time)

AppServer

Get current server certificate

1

Compare current and pinned certificates

2

if identical: establishconnectionelse: reject

3

Certificate Pinning