dgalpin android pirates and vampires

133

Upload: arsch777

Post on 29-Nov-2014

92 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Dgalpin Android Pirates and Vampires
Page 2: Dgalpin Android Pirates and Vampires
Page 3: Dgalpin Android Pirates and Vampires

Evading Pirates and Stopping Vampires Using License Server, In App Billing, and App Engine

Dan Galpin and Trevor JohnsMay 11, 2011

http://goo.gl/Q8SR7#Android

Page 4: Dgalpin Android Pirates and Vampires

Pirates

• Piracy is a reality on all platforms

• Dedicated pirates cannot be stopped

4

Page 5: Dgalpin Android Pirates and Vampires

Casual Pirates

Casual Pirates are potential customers.

• Make piracy inconvenient or challenging

• Use it as a marketing tool

• Allow for limited unlicensed gameplay

• Leverage new monetization models around IAPand Ads

5

Page 6: Dgalpin Android Pirates and Vampires

Casual Pirates

Casual Pirates are potential customers.

• Make piracy inconvenient or challenging

• Use it as a marketing tool

• Allow for limited unlicensed gameplay

• Leverage new monetization models around IAPand Ads

5

Page 7: Dgalpin Android Pirates and Vampires

Casual Pirates

Casual Pirates are potential customers.

• Make piracy inconvenient or challenging

• Use it as a marketing tool

• Allow for limited unlicensed gameplay

• Leverage new monetization models around IAPand Ads

5

Page 8: Dgalpin Android Pirates and Vampires

• Google provides the License Verification Library

• Application determines how to enforce the policy

• Frequency of checks is managed by the client application policy

• Private key is stored with License Server, public key is in application to verify signature

• Supported on Android 1.5 devices or abovethat have Android Market

License Verification: Your First Defense

6

Page 9: Dgalpin Android Pirates and Vampires

Android Market Licensing - Client Verification

Your Application

Market Licensing Server

Android Market Client

Licensing Service

License Verification Library

Page 10: Dgalpin Android Pirates and Vampires

Android Market Licensing - Client Verification

Your Application

Market Licensing Server Private Key

Android Market Client

Licensing Service

Public Key

License Verification Library

Page 11: Dgalpin Android Pirates and Vampires

Android Market Licensing - Client Verification

Your Application

Check License Request

Market Licensing Server Private Key

Android Market Client

Licensing Service

Public Key

License Verification Library

Page 12: Dgalpin Android Pirates and Vampires

Android Market Licensing - Client Verification

Your Application

Check License Request

Checks Purchase Information

Market Licensing Server Private Key

Android Market Client

Licensing Service

Public Key

License Verification Library

Page 13: Dgalpin Android Pirates and Vampires

Android Market Licensing - Client Verification

Your Application

Check License Request

Checks Purchase Information

Market Licensing Server Private Key

Android Market Client

Licensing Service

Response Signed with Private Key

Public Key

License Verification Library

Page 14: Dgalpin Android Pirates and Vampires

Android Market Licensing - Client Verification

Your Application

Check License Request

Checks Purchase Information

Signed Response

Market Licensing Server Private Key

Android Market Client

Licensing Service

Response Signed with Private Key

Public Key

License Verification Library

Page 15: Dgalpin Android Pirates and Vampires

Android Market Licensing - Client Attack

Your Application

Public Key

License Verification Library

• Use tools to disassemble Dalvik/native code

• Alter the response from the library to ignore the server result and always return “licensed”

• Reassemble the application package

• Sign the package with an alternate signature

Page 16: Dgalpin Android Pirates and Vampires

LVL - Strengthening our Defenses

• Use an obfuscatorhttp://proguard.sourceforge.nethttp://code.google.com/p/android-proguard-commandline/

• Modify the LVL code

– Invocation of License Check and response-handling

– Core LVL logic

– Entry/Exit Points

• Make the application tamper-resistant

Page 17: Dgalpin Android Pirates and Vampires

LVL - Invocation/Response Handling

• Don’t invoke in a non-obfuscated function such as onCreate

– Consider in a background thread

• Allow for a limited amount of gameplay when unlicensed

– Consider delaying the result of a license failure

• Implement a policy that allows for multiple background retries if the network or server are unavailable before failing

– Networks don’t always work even when the system thinks they should

• Invoke another activity rather than a dialog to inform the user of a validation failure

Page 18: Dgalpin Android Pirates and Vampires

LVL - Core Logic

Original Sample Codepublic void verify(PublicKey publicKey, int responseCode, String signedData, String

signature) {

// ... Response validation code omitted for brevity ...

switch (responseCode) {

// In bytecode, LICENSED will be converted to the

// constant 0x0

case LICENSED:

// NOT_LICENSED will be converted to the constant 0x1

case NOT_LICENSED:

handleResponse(LicenseResponse.NOT_LICENSED, data);

break;

// ... Extra response codes also removed for brevity ...

}

}

Page 19: Dgalpin Android Pirates and Vampires

LVL - Core Logic

Original Sample Codepublic void verify(PublicKey publicKey, int responseCode, String signedData, String

signature) {

// ... Response validation code omitted for brevity ...

switch (responseCode) {

// In bytecode, LICENSED will be converted to the

// constant 0x0

case LICENSED:

// NOT_LICENSED will be converted to the constant 0x1

case NOT_LICENSED:

handleResponse(LicenseResponse.NOT_LICENSED, data);

break;

// ... Extra response codes also removed for brevity ...

}

}

Example Updated Codepublic void verify(PublicKey publicKey, int responseCode, String signedData, String

signature) {

// ... Response validation code omitted for brevity …

java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();

crc32.update(responseCode);

int transformedResponseCode = crc32.getValue();

// crc32(LICENSED) == 3523407757

if (transformedResponseCode == 3523407757) {

LicenseResponse limiterResponse =

mDeviceLimiter.isDeviceAllowed(userId);

handleResponse(limiterResponse, data);

}

// ... put unrelated application code here ...

// crc32(NOT_LICENSED) == 2768625435

if (transformedResponseCode == 2768625435) {

userIsntLicensed();

}

}

Page 20: Dgalpin Android Pirates and Vampires

LVL - Core Logic

Original Sample Codepublic void verify(PublicKey publicKey, int responseCode, String signedData, String

signature) {

// ... Response validation code omitted for brevity ...

switch (responseCode) {

// In bytecode, LICENSED will be converted to the

// constant 0x0

case LICENSED:

// NOT_LICENSED will be converted to the constant 0x1

case NOT_LICENSED:

handleResponse(LicenseResponse.NOT_LICENSED, data);

break;

// ... Extra response codes also removed for brevity ...

}

}

Example Updated Codepublic void verify(PublicKey publicKey, int responseCode, String signedData, String

signature) {

// ... Response validation code omitted for brevity …

java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();

crc32.update(responseCode);

int transformedResponseCode = crc32.getValue();

// crc32(LICENSED) == 3523407757

if (transformedResponseCode == 3523407757) {

LicenseResponse limiterResponse =

mDeviceLimiter.isDeviceAllowed(userId);

handleResponse(limiterResponse, data);

}

// ... put unrelated application code here ...

// crc32(NOT_LICENSED) == 2768625435

if (transformedResponseCode == 2768625435) {

userIsntLicensed();

}

}

Compute response code value using a hash function

Page 21: Dgalpin Android Pirates and Vampires

LVL - Core Logic

Original Sample Codepublic void verify(PublicKey publicKey, int responseCode, String signedData, String

signature) {

// ... Response validation code omitted for brevity ...

switch (responseCode) {

// In bytecode, LICENSED will be converted to the

// constant 0x0

case LICENSED:

// NOT_LICENSED will be converted to the constant 0x1

case NOT_LICENSED:

handleResponse(LicenseResponse.NOT_LICENSED, data);

break;

// ... Extra response codes also removed for brevity ...

}

}

Example Updated Codepublic void verify(PublicKey publicKey, int responseCode, String signedData, String

signature) {

// ... Response validation code omitted for brevity …

java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();

crc32.update(responseCode);

int transformedResponseCode = crc32.getValue();

// crc32(LICENSED) == 3523407757

if (transformedResponseCode == 3523407757) {

LicenseResponse limiterResponse =

mDeviceLimiter.isDeviceAllowed(userId);

handleResponse(limiterResponse, data);

}

// ... put unrelated application code here ...

// crc32(NOT_LICENSED) == 2768625435

if (transformedResponseCode == 2768625435) {

userIsntLicensed();

}

}

Use separate if statements separated by unrelated application code

Compute response code value using a hash function

Page 22: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance

• Check that your application signature matches

!"#$%&'()*+"#+,-*.*#)&/%01%#)2%$%#)(345#)&/%01%#)6$783#)&/%01%#)9%:)34;*/%01%#)2%$%#)(5<=>?!6<9@>AB=!45+"#$%&'()+C"7*3*+"#+,D-5E%+EF8G)34*..*:H!"#$%&'()I%+E*4*

Page 23: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance

• Check that your application signature matches

• Make sure your application is not debuggable

!"#$%&'()*+"#+,-*.*#)&/%01%#)2%$%#)(345#)&/%01%#)6$783#)&/%01%#)9%:)34;*/%01%#)2%$%#)(5<=>?!6<9@>AB=!45+"#$%&'()+C"7*3*+"#+,D-5E%+EF8G)34*..*:H!"#$%&'()I%+E*4*

boolean isDebuggable = !( 0 != ( getApplicationInfo().flags &=

ApplicationInfo.FLAG_DEBUGGABLE ) );

Page 24: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance

• Check that your application signature matches

• Make sure your application is not debuggable

• CRC code files and compare

!"#$%&'()*+"#+,-*.*#)&/%01%#)2%$%#)(345#)&/%01%#)6$783#)&/%01%#)9%:)34;*/%01%#)2%$%#)(5<=>?!6<9@>AB=!45+"#$%&'()+C"7*3*+"#+,D-5E%+EF8G)34*..*:H!"#$%&'()I%+E*4*

boolean isDebuggable = !( 0 != ( getApplicationInfo().flags &=

ApplicationInfo.FLAG_DEBUGGABLE ) );

zf = new ZipFile(getApplicationInfo().sourceDir);

" " " ZipEntry ze = zf.getEntry("classes.dex");

" " " if ( null != ze ) {

" " " " ze.getCrc();

" " " }

Page 25: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance

• Check that your application certificate matches

public Certificate[] GetApplicationCertificates() {

" InputStream is = null;

" try {

" " JarFile jf = new JarFile(getApplicationInfo().sourceDir);

" " JarEntry je = jf.getJarEntry("classes.dex");

" " is = jf.getInputStream(je);

" " System.out.println("Got InputStream");

" " while ((is.read()) != -1) {} // whole stream is read

" " return je.getCertificates();

" } catch (Exception e) {" "

" } finally {

" " if ( null != is) {

" " " try { "is.close(); }

catch (IOException e) { e.printStackTrace(); }

" " }

" }

" return null;

}"

Page 26: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance - Adding Reflection

• Our previous example, which gets the hash of the first signature

!"#$%&'()*+"#+,-*.*#)&/%01%#)2%$%#)(345#)&/%01%#)6$783#)&/%01%#)9%:)34;*/%01%#)2%$%#)(5<=>?!6<9@>AB=!45+"#$%&'()+C"7*3*+"#+,D-5E%+EF8G)34*..*:H!"#$%&'()I%+E*4*

Page 27: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance - Adding Reflection

• Our previous example, which gets the hash of the first signature

• Using reflection

!"#$%&'()*+"#+,-*.*#)&/%01%#)2%$%#)(345#)&/%01%#)6$783#)&/%01%#)9%:)34;*/%01%#)2%$%#)(5<=>?!6<9@>AB=!45+"#$%&'()+C"7*3*+"#+,D-5E%+EF8G)34*..*:H!"#$%&'()I%+E*4*

!&("$#*#)&/2*.*$)J*!&("$#3K%+)LM5G)08G)3NOPQDA<RS%PR$OATEU:R$OV6.W$N;*D44C!&("$#*#)&/6*.*$)J*!&("$#3K%+)LM5G)08G)3NOPQDA<RS%PR$OAX'O:Y.W$N;*D44C2)&E8G*#Z:2)&E8G*.*#)&FX%++345#)&2)&E8G3#)&/24C[US)0&*#Z:[US)0&*.*#Z:2)&E8G5"$\81)3&E"+4C2)&E8G*#Z"2)&E8G*.*#Z:[US)0&5#)&FX%++345#)&2)&E8G3#)&/6;*!&("$#50X%++;*"$&50X%++4C[US)0&*Z"*.*#Z"2)&E8G5"$\81)3#Z:[US)0&;*#)&/%01%#)9%:)34;*/%01%#)2%$%#)(5<=>?!6<9@>AB=!4C"7*333/%01%#)6$784Z"45+"#$%&'()+,D-5E%+EF8G)34*..*:H!"#$%&'()I%+E4

Page 28: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance - Adding JNI

S0X%++*%0&"\"&HFX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*%0&"\"&H[US)0&4C

S:)&E8G6a*#)&/%01%#)2%$%#)(2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;*N#)&/%01%#)2%$%#)(N;*N34b%$G(8"Gc

08$&)$&cZ:c/%01%#)2%$%#)(CN4C

S:)&E8G6a*#)&/%01%#)9%:)2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;*N#)&/%01%#)9%:)N;*N34bS%\%cX%$#c

!&("$#CN4C

S8US)0&*Z%01%#)2%$%#)([US)0&*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*%0&"\"&H[US)0&;*#)&/%01%#)2%$%#)(2"G4C

S0X%++*Z%01%#)2%$%#)(FX%++*.*3]Z^96=$\4_`R"$GFX%++3Z^96=$\;*N%$G(8"Gc08$&)$&cZ:c/%01%#)2%$%#)(N4C

S:)&E8G6a*#)&/%01%#)6$782"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*N#)&/%01%#)6$78N;*N3bS%\%c

X%$#c!&("$#C64b%$G(8"Gc08$&)$&cZ:c/%01%#)6$78CN4C

S+&("$#*Z%01%#)9%:)!&("$#*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*%0&"\"&H[US)0&;*#)&/%01%#)9%:)2"G4C

S7")XG6a*#)&!"#$%&'()+R"G*.*3]Z^96=$\4_`<)&!&%&"0R")XG6a3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*N<=>?!6<9@>AB=!N;*N6N4C

S"$&*<=>?!6<9@>AB=!*.*3]Z^96=$\4_`<)&!&%&"06$&R")XG3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*#)&!"#$%&'()+R"G4C

S8US)0&*Z%01%#)6$78[US)0&*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*Z%01%#)2%$%#)([US)0&;*#)&/%01%#)6$782"G;*

Z%01%#)9%:)!&("$#;*<=>?!6<9@>AB=!4C

S0X%++*Z%01%#)6$78FX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*Z%01%#)6$78[US)0&4C

S7")XG6a*+"#$%&'()R"G*.*3]Z^96=$\4_`<)&R")XG6a3Z^96=$\;*Z%01%#)6$78FX%++;

* * * N+"#$%&'()+N;*N,b%$G(8"Gc08$&)$&cZ:c!"#$%&'()CN4C

S8US)0&*+"#$%&'()@((%H[US)0&*.*3]Z^96=$\4_`<)&[US)0&R")XG3Z^96=$\;*Z%01%#)6$78[US)0&;*+"#$%&'()R"G4C

S"$&*X)$*.*3]Z^96=$\4_`<)&@((%Hb)$#&E3Z^96=$\;*+"#$%&'()@((%H[US)0&4C

S8US)0&*+"#$%&'()[US)0&*.*3]Z^96=$\4_`<)&[US)0&@((%H=X):)$&3Z^96=$\;*+"#$%&'()@((%H[US)0&;*D4C

S0X%++*+"#$%&'()FX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*+"#$%&'()[US)0&4C

S:)&E8G6a*E%+EF8G)2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*+"#$%&'()FX%++;*NE%+EF8G)N;*N346N4C

"7*3*3]Z^96=$\4_`F%XX6$&2)&E8G3Z^96=$\;*+"#$%&'()[US)0&;*E%+EF8G)2"G4*..*:H!"#$%&'()I%+E*4

Page 29: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance - Adding JNI

S0X%++*%0&"\"&HFX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*%0&"\"&H[US)0&4C

S:)&E8G6a*#)&/%01%#)2%$%#)(2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;*N#)&/%01%#)2%$%#)(N;*N34b%$G(8"Gc

08$&)$&cZ:c/%01%#)2%$%#)(CN4C

S:)&E8G6a*#)&/%01%#)9%:)2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;*N#)&/%01%#)9%:)N;*N34bS%\%cX%$#c

!&("$#CN4C

S8US)0&*Z%01%#)2%$%#)([US)0&*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*%0&"\"&H[US)0&;*#)&/%01%#)2%$%#)(2"G4C

S0X%++*Z%01%#)2%$%#)(FX%++*.*3]Z^96=$\4_`R"$GFX%++3Z^96=$\;*N%$G(8"Gc08$&)$&cZ:c/%01%#)2%$%#)(N4C

S:)&E8G6a*#)&/%01%#)6$782"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*N#)&/%01%#)6$78N;*N3bS%\%c

X%$#c!&("$#C64b%$G(8"Gc08$&)$&cZ:c/%01%#)6$78CN4C

S+&("$#*Z%01%#)9%:)!&("$#*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*%0&"\"&H[US)0&;*#)&/%01%#)9%:)2"G4C

S7")XG6a*#)&!"#$%&'()+R"G*.*3]Z^96=$\4_`<)&!&%&"0R")XG6a3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*N<=>?!6<9@>AB=!N;*N6N4C

S"$&*<=>?!6<9@>AB=!*.*3]Z^96=$\4_`<)&!&%&"06$&R")XG3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*#)&!"#$%&'()+R"G4C

S8US)0&*Z%01%#)6$78[US)0&*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*Z%01%#)2%$%#)([US)0&;*#)&/%01%#)6$782"G;*

Z%01%#)9%:)!&("$#;*<=>?!6<9@>AB=!4C

S0X%++*Z%01%#)6$78FX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*Z%01%#)6$78[US)0&4C

S7")XG6a*+"#$%&'()R"G*.*3]Z^96=$\4_`<)&R")XG6a3Z^96=$\;*Z%01%#)6$78FX%++;

* * * N+"#$%&'()+N;*N,b%$G(8"Gc08$&)$&cZ:c!"#$%&'()CN4C

S8US)0&*+"#$%&'()@((%H[US)0&*.*3]Z^96=$\4_`<)&[US)0&R")XG3Z^96=$\;*Z%01%#)6$78[US)0&;*+"#$%&'()R"G4C

S"$&*X)$*.*3]Z^96=$\4_`<)&@((%Hb)$#&E3Z^96=$\;*+"#$%&'()@((%H[US)0&4C

S8US)0&*+"#$%&'()[US)0&*.*3]Z^96=$\4_`<)&[US)0&@((%H=X):)$&3Z^96=$\;*+"#$%&'()@((%H[US)0&;*D4C

S0X%++*+"#$%&'()FX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*+"#$%&'()[US)0&4C

S:)&E8G6a*E%+EF8G)2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*+"#$%&'()FX%++;*NE%+EF8G)N;*N346N4C

"7*3*3]Z^96=$\4_`F%XX6$&2)&E8G3Z^96=$\;*+"#$%&'()[US)0&;*E%+EF8G)2"G4*..*:H!"#$%&'()I%+E*4

S0X%++*%0&"\"&HFX%++*.*3]Z^96=$\4_`R"$GFX%++3Z^96=$\;*N%$G(8"Gc%ZZc@0&"\"&HN4CS:)&E8G6a*#)&/%01%#)2%$%#)(2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;*N#)&/%01%#)2%$%#)(N;*N34b%$G(8"Gc08$&)$&cZ:c/%01%#)2%$%#)(CN4CS:)&E8G6a*#)&/%01%#)9%:)2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;*N#)&/%01%#)9%:)N;*N34bS%\%cX%$#c!&("$#CN4CS0X%++*Z%01%#)2%$%#)(FX%++*.*3]Z^96=$\4_`R"$GFX%++3Z^96=$\;*N%$G(8"Gc08$&)$&cZ:c/%01%#)2%$%#)(N4CS:)&E8G6a*#)&/%01%#)6$782"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*N#)&/%01%#)6$78N;*N3bS%\%cX%$#c!&("$#C64b%$G(8"Gc08$&)$&cZ:c/%01%#)6$78CN4CS7")XG6a*#)&!"#$%&'()+R"G*.*3]Z^96=$\4_`<)&!&%&"0R")XG6a3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*N<=>?!6<9@>AB=!N;*N6N4CS"$&*<=>?!6<9@>AB=!*.*3]Z^96=$\4_`<)&!&%&"06$&R")XG3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*#)&!"#$%&'()+R"G4CS0X%++*Z%01%#)6$78FX%++*.*3]Z^96=$\4_`R"$GFX%++3Z^96=$\;*N%$G(8"Gc08$&)$&cZ:c/%01%#)6$78N4CS7")XG6a*+"#$%&'()R"G*.*3]Z^96=$\4_`<)&R")XG6a3Z^96=$\;*Z%01%#)6$78FX%++;* * * N+"#$%&'()+N;*N,b%$G(8"Gc08$&)$&cZ:c!"#$%&'()CN4CS0X%++*+"#$%&'()FX%++*.*3]Z^96=$\4_`R"$GFX%++3Z^96=$\;*N%$G(8"Gc08$&)$&cZ:c!"#$%&'()N4CS:)&E8G6a*E%+EF8G)2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*+"#$%&'()FX%++;*NE%+EF8G)N;*N346N4C

Page 30: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance - Adding JNI

S0X%++*%0&"\"&HFX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*%0&"\"&H[US)0&4C

S:)&E8G6a*#)&/%01%#)2%$%#)(2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;*N#)&/%01%#)2%$%#)(N;*N34b%$G(8"Gc

08$&)$&cZ:c/%01%#)2%$%#)(CN4C

S:)&E8G6a*#)&/%01%#)9%:)2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;*N#)&/%01%#)9%:)N;*N34bS%\%cX%$#c

!&("$#CN4C

S8US)0&*Z%01%#)2%$%#)([US)0&*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*%0&"\"&H[US)0&;*#)&/%01%#)2%$%#)(2"G4C

S0X%++*Z%01%#)2%$%#)(FX%++*.*3]Z^96=$\4_`R"$GFX%++3Z^96=$\;*N%$G(8"Gc08$&)$&cZ:c/%01%#)2%$%#)(N4C

S:)&E8G6a*#)&/%01%#)6$782"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*N#)&/%01%#)6$78N;*N3bS%\%c

X%$#c!&("$#C64b%$G(8"Gc08$&)$&cZ:c/%01%#)6$78CN4C

S+&("$#*Z%01%#)9%:)!&("$#*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*%0&"\"&H[US)0&;*#)&/%01%#)9%:)2"G4C

S7")XG6a*#)&!"#$%&'()+R"G*.*3]Z^96=$\4_`<)&!&%&"0R")XG6a3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*N<=>?!6<9@>AB=!N;*N6N4C

S"$&*<=>?!6<9@>AB=!*.*3]Z^96=$\4_`<)&!&%&"06$&R")XG3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*#)&!"#$%&'()+R"G4C

S8US)0&*Z%01%#)6$78[US)0&*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*Z%01%#)2%$%#)([US)0&;*#)&/%01%#)6$782"G;*

Z%01%#)9%:)!&("$#;*<=>?!6<9@>AB=!4C

S0X%++*Z%01%#)6$78FX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*Z%01%#)6$78[US)0&4C

S7")XG6a*+"#$%&'()R"G*.*3]Z^96=$\4_`<)&R")XG6a3Z^96=$\;*Z%01%#)6$78FX%++;

* * * N+"#$%&'()+N;*N,b%$G(8"Gc08$&)$&cZ:c!"#$%&'()CN4C

S8US)0&*+"#$%&'()@((%H[US)0&*.*3]Z^96=$\4_`<)&[US)0&R")XG3Z^96=$\;*Z%01%#)6$78[US)0&;*+"#$%&'()R"G4C

S"$&*X)$*.*3]Z^96=$\4_`<)&@((%Hb)$#&E3Z^96=$\;*+"#$%&'()@((%H[US)0&4C

S8US)0&*+"#$%&'()[US)0&*.*3]Z^96=$\4_`<)&[US)0&@((%H=X):)$&3Z^96=$\;*+"#$%&'()@((%H[US)0&;*D4C

S0X%++*+"#$%&'()FX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*+"#$%&'()[US)0&4C

S:)&E8G6a*E%+EF8G)2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*+"#$%&'()FX%++;*NE%+EF8G)N;*N346N4C

"7*3*3]Z^96=$\4_`F%XX6$&2)&E8G3Z^96=$\;*+"#$%&'()[US)0&;*E%+EF8G)2"G4*..*:H!"#$%&'()I%+E*4

S0X%++*%0&"\"&HFX%++*.*3]Z^96=$\4_`R"$GFX%++3Z^96=$\;*N%$G(8"Gc%ZZc@0&"\"&HN4CS:)&E8G6a*#)&/%01%#)2%$%#)(2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;*N#)&/%01%#)2%$%#)(N;*N34b%$G(8"Gc08$&)$&cZ:c/%01%#)2%$%#)(CN4CS:)&E8G6a*#)&/%01%#)9%:)2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;*N#)&/%01%#)9%:)N;*N34bS%\%cX%$#c!&("$#CN4CS0X%++*Z%01%#)2%$%#)(FX%++*.*3]Z^96=$\4_`R"$GFX%++3Z^96=$\;*N%$G(8"Gc08$&)$&cZ:c/%01%#)2%$%#)(N4CS:)&E8G6a*#)&/%01%#)6$782"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*N#)&/%01%#)6$78N;*N3bS%\%cX%$#c!&("$#C64b%$G(8"Gc08$&)$&cZ:c/%01%#)6$78CN4CS7")XG6a*#)&!"#$%&'()+R"G*.*3]Z^96=$\4_`<)&!&%&"0R")XG6a3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*N<=>?!6<9@>AB=!N;*N6N4CS"$&*<=>?!6<9@>AB=!*.*3]Z^96=$\4_`<)&!&%&"06$&R")XG3Z^96=$\;*Z%01%#)2%$%#)(FX%++;*#)&!"#$%&'()+R"G4CS0X%++*Z%01%#)6$78FX%++*.*3]Z^96=$\4_`R"$GFX%++3Z^96=$\;*N%$G(8"Gc08$&)$&cZ:c/%01%#)6$78N4CS7")XG6a*+"#$%&'()R"G*.*3]Z^96=$\4_`<)&R")XG6a3Z^96=$\;*Z%01%#)6$78FX%++;* * * N+"#$%&'()+N;*N,b%$G(8"Gc08$&)$&cZ:c!"#$%&'()CN4CS0X%++*+"#$%&'()FX%++*.*3]Z^96=$\4_`R"$GFX%++3Z^96=$\;*N%$G(8"Gc08$&)$&cZ:c!"#$%&'()N4CS:)&E8G6a*E%+EF8G)2"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*+"#$%&'()FX%++;*NE%+EF8G)N;*N346N4CS8US)0&*Z%01%#)2%$%#)([US)0&*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*%0&"\"&H[US)0&;*#)&/%01%#)2%$%#)(2"G4C

S+&("$#*Z%01%#)9%:)!&("$#*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*%0&"\"&H[US)0&;*#)&/%01%#)9%:)2"G4CS8US)0&*Z%01%#)6$78[US)0&*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*Z%01%#)2%$%#)([US)0&;*#)&/%01%#)6$782"G;*Z%01%#)9%:)!&("$#;*<=>?!6<9@>AB=!4CS8US)0&*+"#$%&'()@((%H[US)0&*.*3]Z^96=$\4_`<)&[US)0&R")XG3Z^96=$\;*Z%01%#)6$78[US)0&;*+"#$%&'()R"G4CS"$&*X)$*.*3]Z^96=$\4_`<)&@((%Hb)$#&E3Z^96=$\;*+"#$%&'()@((%H[US)0&4CS8US)0&*+"#$%&'()[US)0&*.*3]Z^96=$\4_`<)&[US)0&@((%H=X):)$&3Z^96=$\;*+"#$%&'()@((%H[US)0&;*D4C"7*3*3]Z^96=$\4_`F%XX6$&2)&E8G3Z^96=$\;*+"#$%&'()[US)0&;*E%+EF8G)2"G4*..*:H!"#$%&'()I%+E*4

Page 31: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance - Obfuscating

• The latest version of the Android tools has built-in support for Proguard and the LVLhttp://developer.android.com/guide/developing/tools/proguard.html

• With one minor change to the LVL, you can obfuscate much better (remove ILicensingService from the Proguard cfg)

Page 32: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance - Obfuscating

• The latest version of the Android tools has built-in support for Proguard and the LVLhttp://developer.android.com/guide/developing/tools/proguard.html

• With one minor change to the LVL, you can obfuscate much better (remove ILicensingService from the Proguard cfg)

Change:

boolean!bindResult =!mContext.bindService(

!new!Intent(ILicensingService.class.getName()),

To:

boolean bindResult = mContext.bindService(

new Intent("com.android.vending.licensing.ILicensingService")

Page 33: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance - Obfuscating

• The latest version of the Android tools has built-in support for Proguard and the LVLhttp://developer.android.com/guide/developing/tools/proguard.html

• With one minor change to the LVL, you can obfuscate much better (remove ILicensingService from the Proguard cfg)

Change:

boolean!bindResult =!mContext.bindService(

!new!Intent(ILicensingService.class.getName()),

To:

boolean bindResult = mContext.bindService(

new Intent("com.android.vending.licensing.ILicensingService")

Consider performing a transform on “com.android.vending.licensing.ILicensingService” to make the code less obvious.

Page 34: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance - NDK

• Put checks in C/C++ code^96=V/[B>*SX8$#*^96F@bb*#)&FX%++)+FBF*3^96=$\*]*Z^96=$\;*S8US)0&*%0&"\"&H[US)0&4*d**SX8$#*()&\%X')*.*_TC**S0X%++*%0&"\"&HFX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*%0&"\"&H[US)0&4C**S:)&E8G6a*#)&@ZZX"0%&"8$6$782"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;******N#)&@ZZX"0%&"8$6$78N;*N34b%$G(8"Gc08$&)$&cZ:c@ZZX"0%&"8$6$78CN4C**S8US)0&*%ZZX"0%&"8$6$78*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*%0&"\"&H[US)0&;*#)&@ZZX"0%&"8$6$782"G4C**S7")XG6a*Z%&ER")XG*.*3]Z^96=$\4_`<)&R")XG6a3Z^96=$\;*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*%ZZX"0%&"8$6$784;* *N+8'(0)a"(N;*NbS%\%cX%$#c!&("$#CN4C**S8US)0&*+&(@ZZX"0%&"8$/%&E*.*3]Z^96=$\4_`<)&[US)0&R")XG3Z^96=$\;*%ZZX"0%&"8$6$78;*Z%&ER")XG4C**08$+&*SUH&)*]*%ZZX"0%&"8$/%&E*.*3]Z^96=$\4_`<)&!&("$#A>RFE%(+3Z^96=$\;*+&(@ZZX"0%&"8$/%&E;*9Abb4C**'$eR"X)*'7*.**'$e[Z)$3%ZZX"0%&"8$/%&E4C**"7*3'$eb80%&)R"X)3'7;N0X%++)+5G)fN;F@!=!=9!6>6Q6>g4..A9O?[h4*d****'$e?7"X)?"$78*]*7"X)6$78*.*:%XX803+"e)873'$e?7"X)?"$7844C**"7*3*A9O?[h*..*'$e<)&F'(()$&R"X)6$78*3'7;*7"X)6$78;*9Abb;*D;*9Abb;*D;*9Abb;*D4*4*d* *()&\%X')*.*7"X)6$78_`0(0C*****i***i**'$eFX8+)3'74C**3]Z^96=$\4_`B)X)%+)!&("$#A>RFE%(+3Z^96=$\;*+&(@ZZX"0%&"8$/%&E;*%ZZX"0%&"8$/%&E4C**()&'($*()&\%X')Ci

Page 35: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance - NDK

• Put checks in C/C++ code^96=V/[B>*SX8$#*^96F@bb*#)&FX%++)+FBF*3^96=$\*]*Z^96=$\;*S8US)0&*%0&"\"&H[US)0&4*d**SX8$#*()&\%X')*.*_TC**S0X%++*%0&"\"&HFX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*%0&"\"&H[US)0&4C**S:)&E8G6a*#)&@ZZX"0%&"8$6$782"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;******N#)&@ZZX"0%&"8$6$78N;*N34b%$G(8"Gc08$&)$&cZ:c@ZZX"0%&"8$6$78CN4C**S8US)0&*%ZZX"0%&"8$6$78*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*%0&"\"&H[US)0&;*#)&@ZZX"0%&"8$6$782"G4C**S7")XG6a*Z%&ER")XG*.*3]Z^96=$\4_`<)&R")XG6a3Z^96=$\;*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*%ZZX"0%&"8$6$784;* *N+8'(0)a"(N;*NbS%\%cX%$#c!&("$#CN4C**S8US)0&*+&(@ZZX"0%&"8$/%&E*.*3]Z^96=$\4_`<)&[US)0&R")XG3Z^96=$\;*%ZZX"0%&"8$6$78;*Z%&ER")XG4C**08$+&*SUH&)*]*%ZZX"0%&"8$/%&E*.*3]Z^96=$\4_`<)&!&("$#A>RFE%(+3Z^96=$\;*+&(@ZZX"0%&"8$/%&E;*9Abb4C**'$eR"X)*'7*.**'$e[Z)$3%ZZX"0%&"8$/%&E4C**"7*3'$eb80%&)R"X)3'7;N0X%++)+5G)fN;F@!=!=9!6>6Q6>g4..A9O?[h4*d****'$e?7"X)?"$78*]*7"X)6$78*.*:%XX803+"e)873'$e?7"X)?"$7844C**"7*3*A9O?[h*..*'$e<)&F'(()$&R"X)6$78*3'7;*7"X)6$78;*9Abb;*D;*9Abb;*D;*9Abb;*D4*4*d* *()&\%X')*.*7"X)6$78_`0(0C*****i***i**'$eFX8+)3'74C**3]Z^96=$\4_`B)X)%+)!&("$#A>RFE%(+3Z^96=$\;*+&(@ZZX"0%&"8$/%&E;*%ZZX"0%&"8$/%&E4C**()&'($*()&\%X')Ci

^96=V/[B>*SX8$#*^96F@bb*#)&FX%++)+FBF*3^96=$\*]*Z^96=$\;*S8US)0&*%0&"\"&H[US)0&4*d

**SX8$#*()&\%X')*.*_TC

**S0X%++*%0&"\"&HFX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*%0&"\"&H[US)0&4C

**S:)&E8G6a*#)&@ZZX"0%&"8$6$782"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;*

*****N#)&@ZZX"0%&"8$6$78N;*N34b%$G(8"Gc08$&)$&cZ:c@ZZX"0%&"8$6$78CN4C

**S8US)0&*%ZZX"0%&"8$6$78*.*

****3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*%0&"\"&H[US)0&;*#)&@ZZX"0%&"8$6$782"G4C

**S7")XG6a*Z%&ER")XG*.*3]Z^96=$\4_`<)&R")XG6a3Z^96=$\;*

****3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*%ZZX"0%&"8$6$784;

* **N+8'(0)a"(N;*NbS%\%cX%$#c!&("$#CN4C

**S8US)0&*+&(@ZZX"0%&"8$/%&E*.*

*****3]Z^96=$\4_`<)&[US)0&R")XG3Z^96=$\;*%ZZX"0%&"8$6$78;*Z%&ER")XG4C

**08$+&*SUH&)*]*%ZZX"0%&"8$/%&E*.*

*****3]Z^96=$\4_`<)&!&("$#A>RFE%(+3Z^96=$\;*+&(@ZZX"0%&"8$/%&E;*9Abb4C

Page 36: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance - NDK

• Put checks in C/C++ code^96=V/[B>*SX8$#*^96F@bb*#)&FX%++)+FBF*3^96=$\*]*Z^96=$\;*S8US)0&*%0&"\"&H[US)0&4*d**SX8$#*()&\%X')*.*_TC**S0X%++*%0&"\"&HFX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*%0&"\"&H[US)0&4C**S:)&E8G6a*#)&@ZZX"0%&"8$6$782"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;******N#)&@ZZX"0%&"8$6$78N;*N34b%$G(8"Gc08$&)$&cZ:c@ZZX"0%&"8$6$78CN4C**S8US)0&*%ZZX"0%&"8$6$78*.*3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*%0&"\"&H[US)0&;*#)&@ZZX"0%&"8$6$782"G4C**S7")XG6a*Z%&ER")XG*.*3]Z^96=$\4_`<)&R")XG6a3Z^96=$\;*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*%ZZX"0%&"8$6$784;* *N+8'(0)a"(N;*NbS%\%cX%$#c!&("$#CN4C**S8US)0&*+&(@ZZX"0%&"8$/%&E*.*3]Z^96=$\4_`<)&[US)0&R")XG3Z^96=$\;*%ZZX"0%&"8$6$78;*Z%&ER")XG4C**08$+&*SUH&)*]*%ZZX"0%&"8$/%&E*.*3]Z^96=$\4_`<)&!&("$#A>RFE%(+3Z^96=$\;*+&(@ZZX"0%&"8$/%&E;*9Abb4C**'$eR"X)*'7*.**'$e[Z)$3%ZZX"0%&"8$/%&E4C**"7*3'$eb80%&)R"X)3'7;N0X%++)+5G)fN;F@!=!=9!6>6Q6>g4..A9O?[h4*d****'$e?7"X)?"$78*]*7"X)6$78*.*:%XX803+"e)873'$e?7"X)?"$7844C**"7*3*A9O?[h*..*'$e<)&F'(()$&R"X)6$78*3'7;*7"X)6$78;*9Abb;*D;*9Abb;*D;*9Abb;*D4*4*d* *()&\%X')*.*7"X)6$78_`0(0C*****i***i**'$eFX8+)3'74C**3]Z^96=$\4_`B)X)%+)!&("$#A>RFE%(+3Z^96=$\;*+&(@ZZX"0%&"8$/%&E;*%ZZX"0%&"8$/%&E4C**()&'($*()&\%X')Ci

^96=V/[B>*SX8$#*^96F@bb*#)&FX%++)+FBF*3^96=$\*]*Z^96=$\;*S8US)0&*%0&"\"&H[US)0&4*d

**SX8$#*()&\%X')*.*_TC

**S0X%++*%0&"\"&HFX%++*.*3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*%0&"\"&H[US)0&4C

**S:)&E8G6a*#)&@ZZX"0%&"8$6$782"G*.*3]Z^96=$\4_`<)&2)&E8G6a3Z^96=$\;*%0&"\"&HFX%++;*

*****N#)&@ZZX"0%&"8$6$78N;*N34b%$G(8"Gc08$&)$&cZ:c@ZZX"0%&"8$6$78CN4C

**S8US)0&*%ZZX"0%&"8$6$78*.*

****3]Z^96=$\4_`F%XX[US)0&2)&E8G3Z^96=$\;*%0&"\"&H[US)0&;*#)&@ZZX"0%&"8$6$782"G4C

**S7")XG6a*Z%&ER")XG*.*3]Z^96=$\4_`<)&R")XG6a3Z^96=$\;*

****3]Z^96=$\4_`<)&[US)0&FX%++3Z^96=$\;*%ZZX"0%&"8$6$784;

* **N+8'(0)a"(N;*NbS%\%cX%$#c!&("$#CN4C

**S8US)0&*+&(@ZZX"0%&"8$/%&E*.*

*****3]Z^96=$\4_`<)&[US)0&R")XG3Z^96=$\;*%ZZX"0%&"8$6$78;*Z%&ER")XG4C

**08$+&*SUH&)*]*%ZZX"0%&"8$/%&E*.*

*****3]Z^96=$\4_`<)&!&("$#A>RFE%(+3Z^96=$\;*+&(@ZZX"0%&"8$/%&E;*9Abb4C

**'$eR"X)*'7*.**'$e[Z)$3%ZZX"0%&"8$/%&E4C

**"7*3'$eb80%&)R"X)3'7;N0X%++)+5G)fN;F@!=!=9!6>6Q6>g4..A9O?[h4*d

****'$e?7"X)?"$78*]*7"X)6$78*.*:%XX803+"e)873'$e?7"X)?"$7844C

**"7*3*A9O?[h*..*'$e<)&F'(()$&R"X)6$78*

****3'7;*7"X)6$78;*9Abb;*D;*9Abb;*D;*9Abb;*D4*4*d

* ****()&\%X')*.*7"X)6$78_`0(0C*

****i*

**i

**'$eFX8+)3'74C

**3]Z^96=$\4_`B)X)%+)!&("$#A>RFE%(+3Z^96=$\;*

*****+&(@ZZX"0%&"8$/%&E;*%ZZX"0%&"8$/%&E4C

**()&'($*()&\%X')C

i

Page 37: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance - NDK

• Get native signatures from class file with javap -s

– S%\%Z*_+*_Z("\%&)*08:5%$G(8"G5#XPS$"5<bP^96b"U

+&%&"0*^969%&"\)2)&E8G*:)&E8G+,-*.*d**d*N"$"&N;*N3664QN;*3\8"G]4*$%&"\)<%:)6$"&*i;***d*N+&)ZN;*N34QN;*3\8"G]4*$%&"\)!&)Z*iiC

**0E%(]*0X%++9%:)*.*N08:c%$G(8"Gc#XPS$"c<bP^96b"UNC**S0X%++*0X%ee*.*)$\_`R"$GFX%++30X%++9%:)4C**"7*30X%ee*..*9Abb4*d****??%$G(8"G?X8#?Z("$&3@9aB[6a?b[<?=BB[B;*N@J)+8:)<%:)N;******N9%&"\)*()#"+&(%&"8$*'$%UX)*&8*7"$G*0X%++*jk+jW$N;*0X%++9%:)4C**()&'($*^96?R@b!=C**i**"7*3)$\_`B)#"+&)(9%&"\)+30X%ee;*#2)&E8G+;*$':2)&E8G+4*l*D4*d* ??%$G(8"G?X8#?Z("$&3@9aB[6a?b[<?=BB[B;*N@J)+8:)<%:)N;* **NB)#"+&)(9%&"\)+*7%"X)G*78(*jk+jW$N;*0X%++9%:)4C**()&'($*^96?R@b!=C**i

Page 38: Dgalpin Android Pirates and Vampires

LVL - Tamper Resistance - Advanced Ideas

• Store LVL and other application binaries as encrypted resources. Decrypt to the filesystem and use the class loader to call the LVL

• Make direct calls to the Binder interface, eliminating the entire RPC shell class

Page 39: Dgalpin Android Pirates and Vampires

When Pirates Become Vampires

Page 40: Dgalpin Android Pirates and Vampires

When Pirates Become Vampires

Page 41: Dgalpin Android Pirates and Vampires

When Pirates Become Vampires

• Games often have server components

• Android games often have asset downloads

• Running an unlicensed title can turn a pirate into a vampire that feeds off your bandwidth

• Since you have a server component, you canstop vampires with server-side validation

Page 42: Dgalpin Android Pirates and Vampires

Android Market Licensing - Server Validation

Market Licensing Server

Android Market Client

Licensing Service

Your Server

Your Application License Verification Library

Page 43: Dgalpin Android Pirates and Vampires

Android Market Licensing - Server Validation

Market Licensing Server Private Key

Android Market Client

Licensing Service

Your Server Public Key

Your Application License Verification Library

Page 44: Dgalpin Android Pirates and Vampires

Android Market Licensing - Server Validation

Check License Request

Market Licensing Server Private Key

Android Market Client

Licensing Service

Your Server Public Key

Your Application License Verification Library

Page 45: Dgalpin Android Pirates and Vampires

Android Market Licensing - Server Validation

Check License Request

Checks Purchase Information

Market Licensing Server Private Key

Android Market Client

Licensing Service

Your Server Public Key

Your Application License Verification Library

Page 46: Dgalpin Android Pirates and Vampires

Android Market Licensing - Server Validation

Check License Request

Checks Purchase Information

Market Licensing Server Private Key

Android Market Client

Licensing Service

Response Signed with Private Key

Your Server Public Key

Your Application License Verification Library

Page 47: Dgalpin Android Pirates and Vampires

Android Market Licensing - Server Validation

Check License Request

Checks Purchase Information

Signed Response

Market Licensing Server Private Key

Android Market Client

Licensing Service

Response Signed with Private Key

Your Server Public Key

Your Application License Verification Library

Page 48: Dgalpin Android Pirates and Vampires

Android Market Licensing - Server Validation

Check License Request

Checks Purchase Information

Signed Response

Market Licensing Server Private Key

Android Market Client

Licensing Service

Response Signed with Private Key

Your Server Public Key

Delivered to Serverfor Validation

Your Application License Verification Library

Page 49: Dgalpin Android Pirates and Vampires

Android Market Licensing - Server Validation

Check License Request

Checks Purchase Information

Signed Response

Market Licensing Server Private Key

Android Market Client

Licensing Service

Response Signed with Private Key

Your Server Public Key

Delivered to Serverfor Validation

Your Application License Verification LibrarySession

Page 50: Dgalpin Android Pirates and Vampires

Android Market Licensing - Server Validation

Your Application License Verification Library

SessionToken

Your Server

Page 51: Dgalpin Android Pirates and Vampires

Android Market Licensing - Server Validation

Request Contentwith Session

Your Application License Verification Library

SessionToken

Your Server

Page 52: Dgalpin Android Pirates and Vampires

Android Market Licensing - Server Validation

Request Contentwith Session

Your Application License Verification Library

SessionToken Return Content

Your Server

Page 53: Dgalpin Android Pirates and Vampires

Server-Side LVL - Replay Attacks

Replay

Page 54: Dgalpin Android Pirates and Vampires

Server-Side LVL - Replay Attacks

Rely on the Nonce

• Generating the nonce on your server simplifies the server, as only nonces “in progress” must be tracked - but this adds an extra round trip to your server

• Generating the nonce on the client means the server must store all nonces

Replay

Page 55: Dgalpin Android Pirates and Vampires

Change the Monetization Model

• Consider a free version of the game that can be upgraded

• Use game mechanics that trade money for time

• Provide add-on content that extends play

Page 56: Dgalpin Android Pirates and Vampires

Android Market In-App Billing

• Purchase Virtual Goods (Managed Items)

• Purchase Consumables (Unmanaged Items)

• Client-side or Server-side Validation

Page 57: Dgalpin Android Pirates and Vampires

Android Market In-App Billing

• Purchase Virtual Goods (Managed Items)

• Purchase Consumables (Unmanaged Items)

• Client-side or Server-side Validation

Page 58: Dgalpin Android Pirates and Vampires

In-App Billing - Managed Items

• SKU’s in Market - like your application

• Can only be purchased once

• Applications can ask to replay all managed item purchases

Page 59: Dgalpin Android Pirates and Vampires

In-App Billing - Unmanaged Items

• SKU’s in Market - like your application

• Can be purchased multiple times

• Applications cannot ask for a replay

Page 60: Dgalpin Android Pirates and Vampires

In-App Billing - Client Version

Your Application

Market Server

Android Market Client

BillingReceiver Security

Market Billing Service

BillingService

Page 61: Dgalpin Android Pirates and Vampires

In-App Billing - Client Version

Your Application

Market Server Private Key

Android Market Client

BillingReceiver Security Public Key

Market Billing Service

BillingService

Page 62: Dgalpin Android Pirates and Vampires

In-App Billing - Client Version

Your Application

Billing Request

Market Server Private Key

Android Market Client

BillingReceiver Security Public Key

Market Billing Service

BillingService

Page 63: Dgalpin Android Pirates and Vampires

In-App Billing - Client Version

Your Application

Billing Request

Billing Request

Market Server Private Key

Android Market Client

BillingReceiver Security Public Key

Market Billing Service

BillingService

Page 64: Dgalpin Android Pirates and Vampires

In-App Billing - Client Version

Your Application

Billing Request

Billing Request

Market Server Private Key

Android Market Client

Response Signed with Private Key

BillingReceiver Security Public Key

Market Billing Service

BillingService

Page 65: Dgalpin Android Pirates and Vampires

In-App Billing - Client Version

Your Application

Billing Request

Billing Request

Signed Response (onReceive())

Market Server Private Key

Android Market Client

Response Signed with Private Key

BillingReceiver Security Public Key

Market Billing Service

BillingService

Page 66: Dgalpin Android Pirates and Vampires

In-App Billing - Client Version

Your Application

Billing Request

Billing Request

Signed Response (onReceive())

Market Server Private Key

Android Market Client

Response Signed with Private Key

BillingReceiver Security Public Key

Market Billing Service

BillingService

Page 67: Dgalpin Android Pirates and Vampires

In-App Billing - Server Version

Your Application

Market Server

Android Market Client

BillingReceiver

Market Billing Service

BillingService

Your Server Security

Page 68: Dgalpin Android Pirates and Vampires

In-App Billing - Server Version

Your Application

Market Server Private Key

Android Market Client

BillingReceiver

Market Billing Service

BillingService

Your Server Security Public Key

Page 69: Dgalpin Android Pirates and Vampires

In-App Billing - Server Version

Your Application

Billing Request

Market Server Private Key

Android Market Client

BillingReceiver

Market Billing Service

BillingService

Your Server Security Public Key

Page 70: Dgalpin Android Pirates and Vampires

In-App Billing - Server Version

Your Application

Billing Request

Billing Request

Market Server Private Key

Android Market Client

BillingReceiver

Market Billing Service

BillingService

Your Server Security Public Key

Page 71: Dgalpin Android Pirates and Vampires

In-App Billing - Server Version

Your Application

Billing Request

Billing Request

Market Server Private Key

Android Market Client

Response Signed with Private Key

BillingReceiver

Market Billing Service

BillingService

Your Server Security Public Key

Page 72: Dgalpin Android Pirates and Vampires

In-App Billing - Server Version

Your Application

Billing Request

Billing Request

Signed Response (onReceive())

Market Server Private Key

Android Market Client

Response Signed with Private Key

BillingReceiver

Market Billing Service

BillingService

Your Server Security Public Key

Page 73: Dgalpin Android Pirates and Vampires

In-App Billing - Server Version

Your Application

Billing Request

Billing Request

Signed Response (onReceive())

Market Server Private Key

Android Market Client

Response Signed with Private Key

BillingReceiver

Market Billing Service

BillingService

Your Server Security Public Key

AddCredentials

Page 74: Dgalpin Android Pirates and Vampires

In-App Billing - Server Version

Your Application

Billing Request

Billing Request

Signed Response (onReceive())

Market Server Private Key

Android Market Client

Response Signed with Private Key

BillingReceiver

Market Billing Service

BillingServiceSessionToken

Your Server Security Public Key

AddCredentials

Page 75: Dgalpin Android Pirates and Vampires

In-App Billing - Server Version

Your Application

BillingReceiver

BillingService

Your Server Security Public Key

Page 76: Dgalpin Android Pirates and Vampires

In-App Billing - Server Version

SessionToken

Your Application

BillingReceiver

BillingService

Your Server Security Public Key

Page 77: Dgalpin Android Pirates and Vampires

In-App Billing - Server Version

SessionToken

Request Contentwith Session

Your Application

BillingReceiver

BillingService

Your Server Security Public Key

Page 78: Dgalpin Android Pirates and Vampires

In-App Billing - Server Version

SessionToken

Request Contentwith Session

Return Content

Your Application

BillingReceiver

BillingService

Your Server Security Public Key

Page 79: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

Android Market

Application Activity

Page 80: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

Request Purchase

Android Market

Application Activity

Page 81: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

BundleResponse Code Purchase Intent

Request ID

Request Purchase

Android Market

Application Activity

Page 82: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

BundleResponse Code Purchase Intent

Request ID

Request Purchase

InvokeStartIntentSender

Android Market

Application Activity

Page 83: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

BundleResponse Code Purchase Intent

Request ID

Request Purchase

InvokeStartIntentSender

Display Checkout UI

Android Market

Application Activity

Page 84: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

BundleResponse Code Purchase Intent

Request ID

Request Purchase

InvokeStartIntentSender

Display Checkout UI

Android Market

Activity onPause()

Application Activity

Page 85: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

BundleResponse Code Purchase Intent

Request ID

Request Purchase

InvokeStartIntentSender

Display Checkout UI

Android Market

ActivityonResume()

Activity onPause()

Application Activity

Page 86: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

BundleResponse Code Purchase Intent

Request ID

Request Purchase

InvokeStartIntentSender

Display Checkout UI

Android Market

ActivityonResume()

Activity onPause()

BroadcastResult Code

Application Activity

Page 87: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

BundleResponse Code Purchase Intent

Request ID

Request Purchase

InvokeStartIntentSender

Display Checkout UI

Android Market

ActivityonResume()

Activity onPause()

BroadcastResult Code

Application Activity

Get Purchase Information

Page 88: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

BundleResponse Code Purchase Intent

Request ID

Request Purchase

InvokeStartIntentSender

Display Checkout UI

BroadcastResponse Code

Request ID

Android Market

ActivityonResume()

Activity onPause()

BroadcastResult Code

Application Activity

Get Purchase Information

Page 89: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

InvokeStartIntentSender

Display Checkout UI

BroadcastResponse Code

Request ID

Android Market

ActivityonResume()

Activity onPause()

BroadcastResult Code

Application Activity

Get Purchase Information

Page 90: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

InvokeStartIntentSender

Display Checkout UI

BroadcastResponse Code

Request ID

BroadcastPurchase State

Changed

Android Market

ActivityonResume()

Activity onPause()

BroadcastResult Code

Application Activity

Get Purchase Information

Page 91: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

InvokeStartIntentSender

Display Checkout UI

BroadcastResponse Code

Request ID

Confirm Notifications

BroadcastPurchase State

Changed

Android Market

ActivityonResume()

Activity onPause()

BroadcastResult Code

Application Activity

Get Purchase Information

Page 92: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase

InvokeStartIntentSender

Display Checkout UI

BroadcastResponse Code

Request ID

Confirm Notifications

BroadcastPurchase State

Changed

BroadcastResponse Code

Request ID

Android Market

ActivityonResume()

Activity onPause()

BroadcastResult Code

Application Activity

Get Purchase Information

Page 93: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase with Server

BundleResponse Code Purchase Intent

Request ID

Request Purchase

InvokeStartIntentSender

Display Checkout UI

BroadcastResponse Code

Request ID

ActivityonResume()

Activity onPause()

BroadcastResult Code

Application Activity

Get Purchase Information

Server Android Market

Page 94: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase with Server

BundleResponse Code Purchase Intent

Request ID

Request Purchase

InvokeStartIntentSender

Display Checkout UI

BroadcastResponse Code

Request ID

ActivityonResume()

Activity onPause()

BroadcastResult Code

Application Activity

Get Purchase Information

Request Nonce

Server Android Market

Page 95: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase with Server

BundleResponse Code Purchase Intent

Request ID

Request Purchase

InvokeStartIntentSender

Display Checkout UI

BroadcastResponse Code

Request ID

ActivityonResume()

Activity onPause()

BroadcastResult Code

Application Activity

Get Purchase Information

Request Nonce

Server

Return Session &

Nonce

Android Market

Page 96: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase with Server

BroadcastResponse Code

Request ID

Confirm Notifications

BroadcastPurchase State

Changed

BroadcastResponse Code

Request ID

ActivityonResume()

BroadcastResult Code

Get Purchase Information

Android MarketServer

Application Activity

Page 97: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase with Server

BroadcastResponse Code

Request ID

Confirm Notifications

BroadcastPurchase State

Changed

BroadcastResponse Code

Request ID

ActivityonResume()

BroadcastResult Code

Get Purchase Information

Android Market

Perform Server Billing Auth

Server

Application Activity

Page 98: Dgalpin Android Pirates and Vampires

In-App Billing - Request Purchase with Server

BroadcastResponse Code

Request ID

Confirm Notifications

BroadcastPurchase State

Changed

BroadcastResponse Code

Request ID

ActivityonResume()

BroadcastResult Code

Get Purchase Information

Android Market

Perform Server Billing Auth

Server

Validate Billing Response

Application Activity

Page 99: Dgalpin Android Pirates and Vampires

App Engine can be Your Server

Runs your Java servlet or Python code on our infrastructure

• Validate license responses

• Secure In-App-Billing Transactions

• Serve files from BlobStore

• App Engine is useful as an example. This can be run easily on any Java-capable server.

Page 100: Dgalpin Android Pirates and Vampires

Creating an AppEngine Project

Page 101: Dgalpin Android Pirates and Vampires

Creating an AppEngine Project

Page 102: Dgalpin Android Pirates and Vampires

Creating an AppEngine Project

Page 103: Dgalpin Android Pirates and Vampires

Creating an AppEngine Project

Page 104: Dgalpin Android Pirates and Vampires

Manage your AppEngine Server

Page 105: Dgalpin Android Pirates and Vampires

Server-Side License Validation

Z'UX"0*\8"G*G8/8+&3I&&Z!)(\X)&B)m')+&*()m;*I&&Z!)(\X)&B)+Z8$+)*()+Z4

* &E(8J+*6[=f0)Z&"8$*d

* * cc*[U&%"$*+"#$)G*X"0)$+)*+)(\)(*G%&%*%+*%*/[!>*Z%(%:)&)(

* * !&("$#*X"0)$+)*.*()m5#)&/%(%:)&)(3NX"0)$+)N4C

* * !&("$#*+"#$%&'()*.*()m5#)&/%(%:)&)(3N+"#$%&'()N4C

* * !&("$#*\)(+"8$F8G)*.*()m5#)&/%(%:)&)(3N\)(+"8$_08G)N4C

* * * *

* * cc*=f&(%0&*$8$0)*7(8:*+)++"8$

* * I&&Z!)++"8$*+)++"8$*.*()m5#)&!)++"8$3&(')4C

* * [US)0&*$8$0)[US)0&*.*+)++"8$5#)&@&&("U'&)3N$8$0)N4C

* * +)++"8$5+)&@&&("U'&)3N$8$0)N;*$'XX4C*cc*FX)%(*$8$0)*+8*"&j+*8$XH*\%X"G*8$0)

* *

* * "$&*$8$0)*.*336$&)#)(4*$8$0)[US)0&45"$&Q%X')34C

* * cc*Q)("7H*+"#$%&'()*78(*X"0)$+)

* * b"0)$+)Q%X"G%&8(*X\*.*$)J*b"0)$+)Q%X"G%&8(3$)J*9'XXa)\"0)b":"&)(34;*$8$0);*:/%01%#)9%:);*\)(+"8$F8G)4C

* * b"0)$+)!&%&'+*+&%&'+*.*X\5\)("7H3:/'UX"0h)H;*X"0)$+);*+"#$%&'()4C

* *

* * +)++"8$5+)&@&&("U'&)3N+&%&'+N;*+&%&'+4C

* * "7*3+&%&'+*..*b"0)$+)!&%&'+5b6F=9!=a4*d*()+Z5#)&['&Z'&!&()%:345Z("$&3N81N4C*i*

)X+)*"7*3+&%&'+*..*b"0)$+)!&%&'+59[>?b6F=9!=a4*d*()+Z5+)$G=((8(3MDn;*NA+)(*$8&*X"0)$+)GN4C*i*

)X+)*"7*3+&%&'+*..*b"0)$+)!&%&'+569Q@b6a?!6<9@>AB=4*d*()+Z5+)$G=((8(3MDD;*N6$\%X"G*+"#$%&'()N4C*i*

)X+)*d*()+Z5+)$G=((8(3oDD;*N=((8(*G)08G"$#*X"0)$+)*G%&%N4C*i

* i

Page 106: Dgalpin Android Pirates and Vampires

Android Cloud Services

Your Application

Page 107: Dgalpin Android Pirates and Vampires

Android Cloud Services

Cloud to Device Messaging

Your Application

Page 108: Dgalpin Android Pirates and Vampires

Android Cloud Services

Cloud to Device Messaging

Google Talk

GMail

Your Application

Page 109: Dgalpin Android Pirates and Vampires

Android Cloud Services

Cloud to Device Messaging

Google Talk

Backup

GMail

Your Application

Page 110: Dgalpin Android Pirates and Vampires

Android Cloud Services

Cloud to Device Messaging

Google Talk

Android Market

Backup

GMail

Your Application

Billing

Licensing

Page 111: Dgalpin Android Pirates and Vampires

Cloud to Device Messaging

• Sends lightweight messages to Android applications

• Queues and delivers messages to the target device

• Launches the application if it is not running

• Leverages the network connection being used for Google services

Page 112: Dgalpin Android Pirates and Vampires

Cloud to Device Messaging Basic Flows

Your Application

C2DM Server

C2DM Service

Your Server

Page 113: Dgalpin Android Pirates and Vampires

Cloud to Device Messaging Basic Flows

Sends REGISTER Intent

Your Application

C2DM Server

C2DM Service

Your Server

Page 114: Dgalpin Android Pirates and Vampires

Cloud to Device Messaging Basic Flows

Sends REGISTER Intent

Sends REGISTER Intent

Your Application

C2DM Server

C2DM Service

Your Server

Page 115: Dgalpin Android Pirates and Vampires

Cloud to Device Messaging Basic Flows

Sends REGISTER Intent

Sends REGISTER Intent Responds with REGISTRATION

Your Application

C2DM Server

C2DM Service

Your Server

Page 116: Dgalpin Android Pirates and Vampires

Cloud to Device Messaging Basic Flows

Sends REGISTER Intent

Sends REGISTER Intent Responds with REGISTRATION

REGISTRATION intent contains ID

Your Application

C2DM Server

C2DM Service

Your Server

Page 117: Dgalpin Android Pirates and Vampires

Cloud to Device Messaging Basic Flows

Sends REGISTER Intent

Sends REGISTER Intent Responds with REGISTRATION

REGISTRATION intent contains ID

Forwards Registration ID to Server

Your Application

C2DM Server

C2DM Service

Your Server

Page 118: Dgalpin Android Pirates and Vampires

Cloud to Device Messaging Basic Flows

Sends REGISTER Intent

Sends REGISTER Intent Responds with REGISTRATION

REGISTRATION intent contains ID

Forwards Registration ID to Server

Your Application

C2DM Server

C2DM Service

Your Server

Page 119: Dgalpin Android Pirates and Vampires

Cloud to Device Messaging Basic Flows

Sends REGISTER Intent

Sends REGISTER Intent Responds with REGISTRATION

REGISTRATION intent contains ID

Forwards Registration ID to Server

Your Application

Creates and Stores Session

C2DM Server

C2DM Service

Your Server

Page 120: Dgalpin Android Pirates and Vampires

Cloud to Device Messaging Basic Flows

Sends REGISTER Intent

Sends REGISTER Intent Responds with REGISTRATION

REGISTRATION intent contains ID

Forwards Registration ID to Server

Your Application

Creates and Stores Session

C2DM Server

C2DM Service

Your Server

Page 121: Dgalpin Android Pirates and Vampires

Cloud to Device Messaging Basic Flows

Sends REGISTER Intent

Sends REGISTER Intent Responds with REGISTRATION

REGISTRATION intent contains ID

Forwards Registration ID to Server

Your Application

Creates and Stores Session

Sends C2DM

C2DM Server

C2DM Service

Your Server

Page 122: Dgalpin Android Pirates and Vampires

Cloud to Device Messaging Basic Flows

Sends REGISTER Intent

Sends REGISTER Intent Responds with REGISTRATION

REGISTRATION intent contains ID

Forwards Registration ID to Server

Your Application

Creates and Stores Session

Sends C2DM

Sends Message to Service

C2DM Server

C2DM Service

Your Server

Page 123: Dgalpin Android Pirates and Vampires

Cloud to Device Messaging Basic Flows

Sends REGISTER Intent

Sends REGISTER Intent Responds with REGISTRATION

REGISTRATION intent contains ID

Forwards Registration ID to Server

Your Application

Creates and Stores Session

Sends C2DM

Sends Message to Service

C2DM Server

Sends C2DM Intent to Application

C2DM Service

Your Server

Page 124: Dgalpin Android Pirates and Vampires

Application Data Backup

• Copies application data to cloud

• Backup is requested by application

• Automatically restored when application is installed

• Application Registers itself with Backup Service (server) and Backup Manager (client)

Page 125: Dgalpin Android Pirates and Vampires

Android Cloud Backup - Backing Up

Android Backup Server

Your Application

Android Backup Manager

Backup Agent

Page 126: Dgalpin Android Pirates and Vampires

Android Cloud Backup - Backing Up

Android Backup Server

DataChanged()

Your Application

Android Backup Manager

Backup Agent

Page 127: Dgalpin Android Pirates and Vampires

Android Cloud Backup - Backing Up

Android Backup Server

DataChanged()

Your Application

Android Backup Manager

onBackup()

Backup Agent

Page 128: Dgalpin Android Pirates and Vampires

Android Cloud Backup - Backing Up

Android Backup Server

DataChanged()

Your Application

Android Backup Manager

onBackup()

Backup Agent

Data Backed up to Cloud

Page 129: Dgalpin Android Pirates and Vampires

Android Cloud Backup - Restoring

Application Installed

onBackup()

Backup Agent

Android Backup Server

Android Backup Manager

Page 130: Dgalpin Android Pirates and Vampires

Android Cloud Backup - Restoring

Application Installed

onBackup()

Backup Agent

Is Data Backed Up?

Android Backup Server

Android Backup Manager

Page 131: Dgalpin Android Pirates and Vampires

Android Cloud Backup - Restoring

Application Installed

onBackup()

Backup Agent

Is Data Backed Up?

Android Backup Server

Android Backup Manager

OnRestore()

Page 132: Dgalpin Android Pirates and Vampires

Like the Androids in this Presentation? Androidify Yourself

http://www.androidify.com

Page 133: Dgalpin Android Pirates and Vampires

Questions?

http://goo.gl/Q8SR7#Android