SlideShare une entreprise Scribd logo
1  sur  42
Télécharger pour lire hors ligne
Protecting your Android content
Erik Hemming
Unity Technologies
Mobile Mechanic & Lead Android Developer
4 Apr 2013 Page
About me
• Developer at Unity / Sweden
• 3 years of Unity for Android
• Used to make games
• Battlefield series
• Focus on mobiles and consoles
• Android / PSM / VITA & PS4
2
4 Apr 2013 Page
Agenda
• Unity on Android - what does it mean?
• Authentication with Google Play Licensing
• Application tampering detection
• Code Obfuscation
• Encryption of
• PlayerPrefs
• Scripts
• Assets
• Conclusion / Q&A
3
4 Apr 2013 Page
Unity on Android
4
4 Apr 2013 Page
Unity on Android (overview)
5
Linux Kernel
Android / Dalvik VM
Unity on Android
Mono VM
User script / “Game”
OS
App
4 Apr 2013 Page
Unity on Android (detail)
6
C# / Scripts
Dalvik (Java)
4 Apr 2013 Page
Unity on Android (detail)
7
AndroidJavaObject
java.lang.Object
4 Apr 2013 Page
AndroidJavaObject et al
• Script objects wrap Java objects
• AndroidJavaObject → java.lang.Object
• AndroidJavaClass → java.lang.Class
• AndroidJavaRunnable → java.lang.Runnable
• AndroidJavaProxy → java.lang.reflect.Proxy (in Unity 4.2)
• Automatically maps / instantiates Classes by name
• Methods / Fields are handled through reflection lookups
8
4 Apr 2013 Page 9
java.lang.String str = new java.lang.String("some string");
int hash = str.hashCode();
AndroidJavaObject jo =
        new AndroidJavaObject("java.lang.String", "some string");
int hash = jo.Call<int>("hashCode");
Java
C#
AndroidJavaObject (example)
4 Apr 2013 Page
Authentication with
Google Play Licensing
10
4 Apr 2013 Page
Authentication with
Google Play Licensing
• Provided by Google
• Only available for applications published on Play Store
• Online verification of purchase records
• If the device is offline the verification will “fail”
• Example code (LVL) provided by Google
• Don’t use as-is - very easy to find and hack
11
4 Apr 2013 Page
Verification Flow
• Application → {random number} → Google
• Google → {message, signature} → Application
• message = purchase status + random number + timestamp + (..)
• signature = RSA(message, private key)
• Verify that RSA(signature, public key) is a match for ‘message’
12
4 Apr 2013 Page
How to handle the offline case
• “Online check” == “Internet access”
• Don’t require constant internet access
• that would ruin the game experience while flying / roaming / etc.
• Instead do the checks only if network is available
• allow the app be used a week (or so) without being verified
• trust the app/user during that time.
• If your app has game elements that require internet connection,
make sure you also do a license check at that point.
13
4 Apr 2013 Page
Server Side Verification
• Application → {some number / data request} → Google
• Google → {message, signature} → Application
• Application → {message, signature} → Server
• Server → {application data} → Application
• Server only fulfill Client requests that have correct ‘signature’
14
4 Apr 2013 Page
Unity Plugin :
Google Play License Verification
• Written in C#
• Except for the small Service Binder (Java) - loaded dynamically
• Easy to embed / hide anywhere in your project
• Available on the Unity Asset Store
• Ready to be included into an existing project
• Original project hosted on GitHub
• Feel free to fork and improve
15
4 Apr 2013 Page
Application tampering
detection
16
4 Apr 2013 Page
Application tampering detection
• Why?
• A hacker would have to remove and/or alter licensing checks
• and thus change the code in your application
• Also possible to change code to gain in-game advantages
• Like changing the physics so that a car drives faster
• In general a very easy way to determine if you’ve been hacked
17
4 Apr 2013 Page
Application tampering detection
• Make sure the application is signed with your key
• Make sure the Java code (classes.dex) isn’t altered
• Make sure the Mono class library (mscorlib.dll) isn’t altered
• if the License check is done in C# we will rely on it
• Make sure your script code (Assembly-CSharp.dll) isn’t altered
• Needs to be done from Assembly-UnityScript.dll, or v.v.
• Make sure your native code (libunity.so / libmono.so / etc) isn’t
altered
18
4 Apr 2013 Page
Check the APK signature (Java)
19
// Retrieve the PackageManager and packageName (i.e. 'com.Company.Product')
Activity activity = com.unity3d.player.UnityPlayer.currentActivity;
PackageManager manager = activity.getPackageManager();
String name = activity.getPackageName();
// Fetch APK signature(s)
PackageInfo packageInfo = manager.getPackageInfo(name, PackageManager.GET_SIGNATURES);
Signature[] signatures = packageInfo.signatures;
// Process signatures (i.e. check their validity)
for (Signature signature : signatures)
{
    Log.i("signature", signature.toCharsString());
    Log.i("signature hash", Integer.toHexString(signature.hashCode()));
}
4 Apr 2013 Page
Check the APK signature (UnityScript)
20
// Retrieve the PackageManager and packageName (i.e. 'com.Company.Product')
var unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
var activity = unity.GetStatic.<AndroidJavaObject>("currentActivity");
var manager = activity.Call.<AndroidJavaObject>("getPackageManager");
var name = activity.Call.<String>("getPackageName");
// Fetch APK signature(s)
var GET_SIGNATURES = 64;    // PackageManager.GET_SIGNATURES
var packageInfo = manager.Call.<AndroidJavaObject>("getPackageInfo", name, GET_SIGNATURES);
var signatures = packageInfo.Get.<AndroidJavaObject[]>("signatures");
// Process signatures (i.e. check their validity)
for (var i = 0; i < signatures.length; ++i)
{
    Debug.Log("signature = " + signatures[i].Call.<String>("toCharsString"));
    Debug.Log("signature hash = " + signatures[i].Call.<int>("hashCode").ToString("X"));
}
4 Apr 2013 Page
Detect changes to ‘classes.dex’ (C#)
21
// Unity's WWW class supports reading 'jar:{archive-url}!/{entry}' on Android
string urlScheme = "jar:file://";
string apkPath = Application.dataPath;
string separator = "!/";
string entry = "classes.dex";
string url = urlScheme + apkPath + separator + entry;
// Read classes.dex inside package.apk
WWW www = new WWW(url);
yield return www;
// Calculate the MD5 sum of classes.dex contents
MD5 md5 = new MD5CryptoServiceProvider();
byte[] hash = md5.ComputeHash(www.bytes);
// Print MD5 sum
System.Text.StringBuilder sb = new System.Text.StringBuilder();
for (int i = 0; i < hash.Length; i++)
    sb.Append(hash[i].ToString("x2"));
Debug.Log("md5sum(classes.dex) = " + sb.ToString());
4 Apr 2013 Page
Native libs check (UnityScript)
22
// Retrieve main Activity
var unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
var activity = unity.GetStatic.<AndroidJavaObject>("currentActivity");
// Retrieve ApplicationInfo and nativeLibraryDir (N.B. API-9 or newer only!)
var info = activity.Call.<AndroidJavaObject>("getApplicationInfo");
var nativeLibraryDir = info.Get.<String>("nativeLibraryDir");
var unityPath = Path.Combine(nativeLibraryDir, "libunity.so");
var file = new FileStream(unityPath, FileMode.Open, FileAccess.Read);
var sha1 = new SHA1CryptoServiceProvider();
var hash = sha1.ComputeHash(file);
file.Close();
// Print SHA1 sum
var sb = new System.Text.StringBuilder();
for (var i = 0; i < hash.Length; i++)
    sb.Append(hash[i].ToString("x2"));
Debug.Log("sha1sum(libunity.so) = " + sb.ToString());
4 Apr 2013 Page
Code Obfuscation
23
4 Apr 2013 Page
Code Obfuscation
• Java Obfuscation
• Proguard
• C# Obfuscation
• Obfuscar
• Hides method/variable names
• but still very much readable code
• False sense of security
24
4 Apr 2013 Page
Java Obfuscation (before)
25
private void playVideo()
{
    doCleanUp();
    try
    {
        mMediaPlayer = new MediaPlayer();
        if (mIsURL)
        {
            mMediaPlayer.setDataSource(mContext, Uri.parse(mFileName));
        }
        else if (mVideoLength != 0)
        {
            FileInputStream file = new FileInputStream(mFileName);
            mMediaPlayer.setDataSource(file.getFD(), mVideoOffset, mVideoLength);
            file.close();
        }
        else
        {
(...)
4 Apr 2013 Page
Java Obfuscation (after)
26
private void a()
{
    b();
    try
    {
        this.r = new MediaPlayer();
        if (this.h)
        {
            this.r.setDataSource(this.b, Uri.parse(this.e));
        }
        else
        {
            if (this.j != 0L)
            {
                Object localObject = new FileInputStream(this.e);
                this.r.setDataSource(((FileInputStream)localObject).getFD(), this.i, this.j);
                ((FileInputStream)localObject).close();
            }
            else
            {
(...)
4 Apr 2013 Page
Encryption
27
4 Apr 2013 Page
Encryption of PlayerPrefs
• Why?
• Prevent simple cheating
• Prevent cracking IAB purchases (if you cache anything locally)
• In general good practice for sensitive data (like game progression)
• How?
• Encrypt key/values before inserting them in the PlayerPrefs
• Use a user-specific encryption, so prefs cannot be copied, but still shared
in a cloud
28
4 Apr 2013 Page
SetString(key, value, secret)
29
// Hide 'key' string
string key_string = MD5(key);
// Convert 'value' into a byte array
byte[] bytes = UTF8Encoding.UTF8.GetBytes(value);
// Encrypt 'value' with 3DES('secret')
TripleDES des = new TripleDESCryptoServiceProvider();
des.Key = secret;
des.Mode = CipherMode.ECB;
ICryptoTransform xform = des.CreateEncryptor();
byte[] encrypted = xform.TransformFinalBlock(bytes, 0, bytes.Length);
// Convert encrypted array into a "readable" string
string encrypted_string = Convert.ToBase64String(encrypted, 0, encrypted.Length);
// Set the { key, encrypted value } pair in regular PlayerPrefs
PlayerPrefs.SetString(key_string, encrypted_string);
4 Apr 2013 Page
value GetString(key, secret)
30
// Hide 'key' string
string key_string = MD5(key);
// Retrieve encrypted 'value' and Base64 decode it
string value = PlayerPrefs.GetString(key_string);
byte[] bytes = Convert.FromBase64String(value);
// Decrypt 'value' with 3DES('secret')
TripleDES des = new TripleDESCryptoServiceProvider();
des.Key = secret;
des.Mode = CipherMode.ECB;
ICryptoTransform xform = des.CreateDecryptor();
byte[] decrypted = xform.TransformFinalBlock(bytes, 0, bytes.Length);
// Return decrypted value as a proper string
return UTF8Encoding.UTF8.GetString(decrypted);
4 Apr 2013 Page
Encrypted SetString() / GetString()
31
// Generate a secret based on 'username'
string username = "Turrican II";
MD5 md5 = new MD5CryptoServiceProvider();
byte[] secret = md5.ComputeHash(UTF8Encoding.UTF8.GetBytes(username));
// Game progress { key, value } pair
string key = "unlocked levels";
string value = "the desert rocks,traps,secret dungeons,the wall,the final challenge,the final fight";
// Insert { key, value } pair
SetString(key, value, secret);
// Retrieve { key, value }
string ret = GetString(key, secret);
// Output to the logcat
Debug.Log("secret = " + username);
Debug.Log(key + " = " + ret);
4 Apr 2013 Page
Encryption of Scripts
• Why?
• Scripts are generally insecure
• Gameplay could be altered
• Security checks could be disabled
• Code needs to be “hidden” for some reason (i.e. IAB logic)
32
4 Apr 2013 Page
Encryption of Scripts
• How?
• Compile scripts outside Unity
• Run a symmetric / asymmetric encryption on the Script.dll
• Choose a delivery mechanism
• Embed in the application, or
• Download it from a trusted server
• Decrypt the Script.dll in memory
• Load it through Assembly.Load(byte[])
33
4 Apr 2013 Page
Compile scripts outside Unity
• Download Mono (www.mono-project.com)
• Compile the script (Plugin.cs) with ‘gmcs’
• Reference the UnityEngine.dll assembly to access to Unity
34
$ gmcs
-target:library
-out:Script.dll
-r:AndroidPlayer/Managed/UnityEngine.dll
Plugin.cs
4 Apr 2013 Page
Encrypt the assembly
• Using OpenSSL
• Converted to ‘text’ using Base64 encoding
• Result can be embedded in Unity as a TextAsset
35
$ openssl rc2 -nosalt -p -in Script.dll -out Encrypted.bin
key=...
iv =...
$ base64 Encrypted.bin > ~/UnityProject/Assets/Encrypted.txt
4 Apr 2013 Page
Plugin.cs
36
using UnityEngine;
public class SomeImportantGameClass
{
    static SomeImportantGameClass()
    {
        const int GET_SIGNATURES = 64;
        AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer")
.GetStatic<AndroidJavaObject>("currentActivity");
        AndroidJavaObject manager = activity.Call<AndroidJavaObject>("getPackageManager");
        string packageName = activity.Call<string>("getPackageName");
        AndroidJavaObject packageInfo =
                manager.Call<AndroidJavaObject>("getPackageInfo", packageName, GET_SIGNATURES);
        AndroidJavaObject[] signatures = packageInfo.Get<AndroidJavaObject[]>("signatures");
        foreach (AndroidJavaObject signature in signatures)
        {
            Debug.Log("signature hash = " + signature.Call<int>("hashCode").ToString("X"));
        }
    }
(...)
}
4 Apr 2013 Page
Decrypt and run assembly
37
public TextAsset assembly;
void Start () {
    // Load encrypted data and decryption keys
    byte[] bytes = Convert.FromBase64String(assembly.text);
    byte[] key = new byte[] { <key from encryption step> };
    byte[] iv = new byte[] { <iv from encryption step> };
    // Decrypt assembly
    RC2 rc2 = new RC2CryptoServiceProvider();
    rc2.Mode = CipherMode.CBC;
    ICryptoTransform xform = rc2.CreateDecryptor(key, iv);
    byte[] decrypted = xform.TransformFinalBlock(bytes, 0, bytes.Length);
    // Load assembly and instantiate 'SomeImportantGameClass' to trigger static constructor
    Assembly asm = Assembly.Load(decrypted);
    Type SomeClass = asm.GetType("SomeImportantGameClass");
    SomeClass.GetConstructor(Type.EmptyTypes).Invoke(null);
}
4 Apr 2013 Page
Encryption of Assets
• Why?
• Some assets might need to be protected from tampering.
• “Assets” doesn’t necessarily mean just “textures”; could be
• Game logic
• Dalvik bytecode
• Script code
• Native code
• .. “anything”
38
4 Apr 2013 Page
Encryption of Assets
• How?
• Create an AssetBundle from the “secret” assets.
• Run a symmetric / asymmetric encryption on the AssetBundle.unity3d
• Choose a delivery mechanism
• Embed in the application, or
• Download it from a trusted server
• Decrypt the AssetBundle.unity3d in memory
• Load it through AssetBundle.CreateFromMemory(Byte[])
39
4 Apr 2013 Page
Conclusion
• Be imaginative
• APK integrity checks are so simple everyone should have them.
• Sensitive code must be protected
• Combine the different approaches, and create new ones
• Finally: Don’t spend too much time on this
• Instead update the logic for each new release.
40
4 Apr 2013 Page
Questions?
41
4 Apr 2013 Page
Thanks!
42
Twitter: @_eriq_

Contenu connexe

Tendances

constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだconstexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Genya Murakami
 
[NDC07] 게임 개발에서의 클라이언트 보안 - 송창규
[NDC07] 게임 개발에서의 클라이언트 보안 - 송창규[NDC07] 게임 개발에서의 클라이언트 보안 - 송창규
[NDC07] 게임 개발에서의 클라이언트 보안 - 송창규
ChangKyu Song
 
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
Yoji Kanno
 
JavaScriptとWebGLで圧倒的な3D空戦バトルを再現。「編隊少女 -フォーメーションガールズ-」における3Dレンダリング技術解説 ~Babylo...
JavaScriptとWebGLで圧倒的な3D空戦バトルを再現。「編隊少女 -フォーメーションガールズ-」における3Dレンダリング技術解説 ~Babylo...JavaScriptとWebGLで圧倒的な3D空戦バトルを再現。「編隊少女 -フォーメーションガールズ-」における3Dレンダリング技術解説 ~Babylo...
JavaScriptとWebGLで圧倒的な3D空戦バトルを再現。「編隊少女 -フォーメーションガールズ-」における3Dレンダリング技術解説 ~Babylo...
Katsushi Suzuki
 

Tendances (20)

[IGC 2016] 골드로쉬 김현석 - 왜 항상 기획자는 욕을 들어야만 하는 걸까? –게임 기획의 포지션 변화-
[IGC 2016] 골드로쉬 김현석 - 왜 항상 기획자는 욕을 들어야만 하는 걸까? –게임 기획의 포지션 변화-[IGC 2016] 골드로쉬 김현석 - 왜 항상 기획자는 욕을 들어야만 하는 걸까? –게임 기획의 포지션 변화-
[IGC 2016] 골드로쉬 김현석 - 왜 항상 기획자는 욕을 들어야만 하는 걸까? –게임 기획의 포지션 변화-
 
5分でわかるWebRTCの仕組み - html5minutes vol.01
5分でわかるWebRTCの仕組み - html5minutes vol.015分でわかるWebRTCの仕組み - html5minutes vol.01
5分でわかるWebRTCの仕組み - html5minutes vol.01
 
Unityでオニオンアーキテクチャ
UnityでオニオンアーキテクチャUnityでオニオンアーキテクチャ
Unityでオニオンアーキテクチャ
 
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだconstexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
 
【Unite Tokyo 2019】Unity Test Runnerを活用して内部品質を向上しよう
【Unite Tokyo 2019】Unity Test Runnerを活用して内部品質を向上しよう【Unite Tokyo 2019】Unity Test Runnerを活用して内部品質を向上しよう
【Unite Tokyo 2019】Unity Test Runnerを活用して内部品質を向上しよう
 
ゲーム開発とデザインパターン
ゲーム開発とデザインパターンゲーム開発とデザインパターン
ゲーム開発とデザインパターン
 
カスタムROM開発者の視点から見たAndroid
カスタムROM開発者の視点から見たAndroidカスタムROM開発者の視点から見たAndroid
カスタムROM開発者の視点から見たAndroid
 
ドメイン駆動設計をゲーム開発に活かす
ドメイン駆動設計をゲーム開発に活かすドメイン駆動設計をゲーム開発に活かす
ドメイン駆動設計をゲーム開発に活かす
 
DeClang 誕生!Clang ベースのハッキング対策コンパイラ【DeNA TechCon 2020 ライブ配信】
DeClang 誕生!Clang ベースのハッキング対策コンパイラ【DeNA TechCon 2020 ライブ配信】DeClang 誕生!Clang ベースのハッキング対策コンパイラ【DeNA TechCon 2020 ライブ配信】
DeClang 誕生!Clang ベースのハッキング対策コンパイラ【DeNA TechCon 2020 ライブ配信】
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
 
Python 게임서버 안녕하십니까 : RPC framework 편
Python 게임서버 안녕하십니까 : RPC framework 편Python 게임서버 안녕하십니까 : RPC framework 편
Python 게임서버 안녕하십니까 : RPC framework 편
 
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
 
Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)
 
[NDC 2010] 그럴듯한 랜덤 생성 컨텐츠 만들기
[NDC 2010] 그럴듯한 랜덤 생성 컨텐츠 만들기[NDC 2010] 그럴듯한 랜덤 생성 컨텐츠 만들기
[NDC 2010] 그럴듯한 랜덤 생성 컨텐츠 만들기
 
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
 
[NDC07] 게임 개발에서의 클라이언트 보안 - 송창규
[NDC07] 게임 개발에서의 클라이언트 보안 - 송창규[NDC07] 게임 개발에서의 클라이언트 보안 - 송창규
[NDC07] 게임 개발에서의 클라이언트 보안 - 송창규
 
Observableで非同期処理
Observableで非同期処理Observableで非同期処理
Observableで非同期処理
 
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
 
JavaScriptとWebGLで圧倒的な3D空戦バトルを再現。「編隊少女 -フォーメーションガールズ-」における3Dレンダリング技術解説 ~Babylo...
JavaScriptとWebGLで圧倒的な3D空戦バトルを再現。「編隊少女 -フォーメーションガールズ-」における3Dレンダリング技術解説 ~Babylo...JavaScriptとWebGLで圧倒的な3D空戦バトルを再現。「編隊少女 -フォーメーションガールズ-」における3Dレンダリング技術解説 ~Babylo...
JavaScriptとWebGLで圧倒的な3D空戦バトルを再現。「編隊少女 -フォーメーションガールズ-」における3Dレンダリング技術解説 ~Babylo...
 
[보안PARTNERDAY] 모바일 리소스 보안 - 김동민
[보안PARTNERDAY] 모바일 리소스 보안 - 김동민[보안PARTNERDAY] 모바일 리소스 보안 - 김동민
[보안PARTNERDAY] 모바일 리소스 보안 - 김동민
 

Similaire à [UniteKorea2013] Protecting your Android content

Android Scripting
Android ScriptingAndroid Scripting
Android Scripting
Juan Gomez
 
Building Grails Plugins - Tips And Tricks
Building Grails Plugins - Tips And TricksBuilding Grails Plugins - Tips And Tricks
Building Grails Plugins - Tips And Tricks
Mike Hugo
 

Similaire à [UniteKorea2013] Protecting your Android content (20)

OWASP ZAP Workshop for QA Testers
OWASP ZAP Workshop for QA TestersOWASP ZAP Workshop for QA Testers
OWASP ZAP Workshop for QA Testers
 
Attacking and Defending Mobile Applications
Attacking and Defending Mobile ApplicationsAttacking and Defending Mobile Applications
Attacking and Defending Mobile Applications
 
Webinar: Extend The Power of The ForgeRock Identity Platform Through Scripting
Webinar: Extend The Power of The ForgeRock Identity Platform Through ScriptingWebinar: Extend The Power of The ForgeRock Identity Platform Through Scripting
Webinar: Extend The Power of The ForgeRock Identity Platform Through Scripting
 
Android application analyzer
Android application analyzerAndroid application analyzer
Android application analyzer
 
Fastlane
FastlaneFastlane
Fastlane
 
Android Scripting
Android ScriptingAndroid Scripting
Android Scripting
 
Securing TodoMVC Using the Web Cryptography API
Securing TodoMVC Using the Web Cryptography APISecuring TodoMVC Using the Web Cryptography API
Securing TodoMVC Using the Web Cryptography API
 
Webinar–Mobile Application Hardening Protecting Business Critical Apps
Webinar–Mobile Application Hardening Protecting Business Critical AppsWebinar–Mobile Application Hardening Protecting Business Critical Apps
Webinar–Mobile Application Hardening Protecting Business Critical Apps
 
Android lessons you won't learn in school
Android lessons you won't learn in schoolAndroid lessons you won't learn in school
Android lessons you won't learn in school
 
Mitigating data theft_in_android
Mitigating data theft_in_androidMitigating data theft_in_android
Mitigating data theft_in_android
 
Automated malware analysis
Automated malware analysisAutomated malware analysis
Automated malware analysis
 
TDC2018SP | Trilha Mobile - Case VC+: Como tornar seguro um aplicativo mobile...
TDC2018SP | Trilha Mobile - Case VC+: Como tornar seguro um aplicativo mobile...TDC2018SP | Trilha Mobile - Case VC+: Como tornar seguro um aplicativo mobile...
TDC2018SP | Trilha Mobile - Case VC+: Como tornar seguro um aplicativo mobile...
 
Case VC+: Como tornar seguro um aplicativo mobile payment sem penalizar a exp...
Case VC+: Como tornar seguro um aplicativo mobile payment sem penalizar a exp...Case VC+: Como tornar seguro um aplicativo mobile payment sem penalizar a exp...
Case VC+: Como tornar seguro um aplicativo mobile payment sem penalizar a exp...
 
Overview of DroidCon UK 2015
Overview of DroidCon UK 2015 Overview of DroidCon UK 2015
Overview of DroidCon UK 2015
 
Pwning mobile apps without root or jailbreak
Pwning mobile apps without root or jailbreakPwning mobile apps without root or jailbreak
Pwning mobile apps without root or jailbreak
 
Hacking your Droid (Aditya Gupta)
Hacking your Droid (Aditya Gupta)Hacking your Droid (Aditya Gupta)
Hacking your Droid (Aditya Gupta)
 
Building Grails Plugins - Tips And Tricks
Building Grails Plugins - Tips And TricksBuilding Grails Plugins - Tips And Tricks
Building Grails Plugins - Tips And Tricks
 
Rapid Android Application Security Testing
Rapid Android Application Security TestingRapid Android Application Security Testing
Rapid Android Application Security Testing
 
Null mumbai-Android-Insecure-Data-Storage-Exploitation
Null mumbai-Android-Insecure-Data-Storage-ExploitationNull mumbai-Android-Insecure-Data-Storage-Exploitation
Null mumbai-Android-Insecure-Data-Storage-Exploitation
 
Android pentesting the hackers-meetup
Android pentesting the hackers-meetupAndroid pentesting the hackers-meetup
Android pentesting the hackers-meetup
 

Plus de William Hugo Yang (7)

[UniteKorea2013] Serialization in Depth
[UniteKorea2013] Serialization in Depth[UniteKorea2013] Serialization in Depth
[UniteKorea2013] Serialization in Depth
 
[UniteKorea2013] Memory profiling in Unity
[UniteKorea2013] Memory profiling in Unity[UniteKorea2013] Memory profiling in Unity
[UniteKorea2013] Memory profiling in Unity
 
[UniteKorea2013] Unity Hacks
[UniteKorea2013] Unity Hacks[UniteKorea2013] Unity Hacks
[UniteKorea2013] Unity Hacks
 
[UniteKorea2013] Butterfly Effect DX11
[UniteKorea2013] Butterfly Effect DX11[UniteKorea2013] Butterfly Effect DX11
[UniteKorea2013] Butterfly Effect DX11
 
[UniteKorea2013] The Unity Rendering Pipeline
[UniteKorea2013] The Unity Rendering Pipeline[UniteKorea2013] The Unity Rendering Pipeline
[UniteKorea2013] The Unity Rendering Pipeline
 
[UniteKorea2013] Art tips and tricks
[UniteKorea2013] Art tips and tricks[UniteKorea2013] Art tips and tricks
[UniteKorea2013] Art tips and tricks
 
[UniteKorea2013] 2D content workflows
[UniteKorea2013] 2D content workflows[UniteKorea2013] 2D content workflows
[UniteKorea2013] 2D content workflows
 

Dernier

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Dernier (20)

Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 

[UniteKorea2013] Protecting your Android content

  • 1. Protecting your Android content Erik Hemming Unity Technologies Mobile Mechanic & Lead Android Developer
  • 2. 4 Apr 2013 Page About me • Developer at Unity / Sweden • 3 years of Unity for Android • Used to make games • Battlefield series • Focus on mobiles and consoles • Android / PSM / VITA & PS4 2
  • 3. 4 Apr 2013 Page Agenda • Unity on Android - what does it mean? • Authentication with Google Play Licensing • Application tampering detection • Code Obfuscation • Encryption of • PlayerPrefs • Scripts • Assets • Conclusion / Q&A 3
  • 4. 4 Apr 2013 Page Unity on Android 4
  • 5. 4 Apr 2013 Page Unity on Android (overview) 5 Linux Kernel Android / Dalvik VM Unity on Android Mono VM User script / “Game” OS App
  • 6. 4 Apr 2013 Page Unity on Android (detail) 6 C# / Scripts Dalvik (Java)
  • 7. 4 Apr 2013 Page Unity on Android (detail) 7 AndroidJavaObject java.lang.Object
  • 8. 4 Apr 2013 Page AndroidJavaObject et al • Script objects wrap Java objects • AndroidJavaObject → java.lang.Object • AndroidJavaClass → java.lang.Class • AndroidJavaRunnable → java.lang.Runnable • AndroidJavaProxy → java.lang.reflect.Proxy (in Unity 4.2) • Automatically maps / instantiates Classes by name • Methods / Fields are handled through reflection lookups 8
  • 9. 4 Apr 2013 Page 9 java.lang.String str = new java.lang.String("some string"); int hash = str.hashCode(); AndroidJavaObject jo =         new AndroidJavaObject("java.lang.String", "some string"); int hash = jo.Call<int>("hashCode"); Java C# AndroidJavaObject (example)
  • 10. 4 Apr 2013 Page Authentication with Google Play Licensing 10
  • 11. 4 Apr 2013 Page Authentication with Google Play Licensing • Provided by Google • Only available for applications published on Play Store • Online verification of purchase records • If the device is offline the verification will “fail” • Example code (LVL) provided by Google • Don’t use as-is - very easy to find and hack 11
  • 12. 4 Apr 2013 Page Verification Flow • Application → {random number} → Google • Google → {message, signature} → Application • message = purchase status + random number + timestamp + (..) • signature = RSA(message, private key) • Verify that RSA(signature, public key) is a match for ‘message’ 12
  • 13. 4 Apr 2013 Page How to handle the offline case • “Online check” == “Internet access” • Don’t require constant internet access • that would ruin the game experience while flying / roaming / etc. • Instead do the checks only if network is available • allow the app be used a week (or so) without being verified • trust the app/user during that time. • If your app has game elements that require internet connection, make sure you also do a license check at that point. 13
  • 14. 4 Apr 2013 Page Server Side Verification • Application → {some number / data request} → Google • Google → {message, signature} → Application • Application → {message, signature} → Server • Server → {application data} → Application • Server only fulfill Client requests that have correct ‘signature’ 14
  • 15. 4 Apr 2013 Page Unity Plugin : Google Play License Verification • Written in C# • Except for the small Service Binder (Java) - loaded dynamically • Easy to embed / hide anywhere in your project • Available on the Unity Asset Store • Ready to be included into an existing project • Original project hosted on GitHub • Feel free to fork and improve 15
  • 16. 4 Apr 2013 Page Application tampering detection 16
  • 17. 4 Apr 2013 Page Application tampering detection • Why? • A hacker would have to remove and/or alter licensing checks • and thus change the code in your application • Also possible to change code to gain in-game advantages • Like changing the physics so that a car drives faster • In general a very easy way to determine if you’ve been hacked 17
  • 18. 4 Apr 2013 Page Application tampering detection • Make sure the application is signed with your key • Make sure the Java code (classes.dex) isn’t altered • Make sure the Mono class library (mscorlib.dll) isn’t altered • if the License check is done in C# we will rely on it • Make sure your script code (Assembly-CSharp.dll) isn’t altered • Needs to be done from Assembly-UnityScript.dll, or v.v. • Make sure your native code (libunity.so / libmono.so / etc) isn’t altered 18
  • 19. 4 Apr 2013 Page Check the APK signature (Java) 19 // Retrieve the PackageManager and packageName (i.e. 'com.Company.Product') Activity activity = com.unity3d.player.UnityPlayer.currentActivity; PackageManager manager = activity.getPackageManager(); String name = activity.getPackageName(); // Fetch APK signature(s) PackageInfo packageInfo = manager.getPackageInfo(name, PackageManager.GET_SIGNATURES); Signature[] signatures = packageInfo.signatures; // Process signatures (i.e. check their validity) for (Signature signature : signatures) {     Log.i("signature", signature.toCharsString());     Log.i("signature hash", Integer.toHexString(signature.hashCode())); }
  • 20. 4 Apr 2013 Page Check the APK signature (UnityScript) 20 // Retrieve the PackageManager and packageName (i.e. 'com.Company.Product') var unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); var activity = unity.GetStatic.<AndroidJavaObject>("currentActivity"); var manager = activity.Call.<AndroidJavaObject>("getPackageManager"); var name = activity.Call.<String>("getPackageName"); // Fetch APK signature(s) var GET_SIGNATURES = 64;    // PackageManager.GET_SIGNATURES var packageInfo = manager.Call.<AndroidJavaObject>("getPackageInfo", name, GET_SIGNATURES); var signatures = packageInfo.Get.<AndroidJavaObject[]>("signatures"); // Process signatures (i.e. check their validity) for (var i = 0; i < signatures.length; ++i) {     Debug.Log("signature = " + signatures[i].Call.<String>("toCharsString"));     Debug.Log("signature hash = " + signatures[i].Call.<int>("hashCode").ToString("X")); }
  • 21. 4 Apr 2013 Page Detect changes to ‘classes.dex’ (C#) 21 // Unity's WWW class supports reading 'jar:{archive-url}!/{entry}' on Android string urlScheme = "jar:file://"; string apkPath = Application.dataPath; string separator = "!/"; string entry = "classes.dex"; string url = urlScheme + apkPath + separator + entry; // Read classes.dex inside package.apk WWW www = new WWW(url); yield return www; // Calculate the MD5 sum of classes.dex contents MD5 md5 = new MD5CryptoServiceProvider(); byte[] hash = md5.ComputeHash(www.bytes); // Print MD5 sum System.Text.StringBuilder sb = new System.Text.StringBuilder(); for (int i = 0; i < hash.Length; i++)     sb.Append(hash[i].ToString("x2")); Debug.Log("md5sum(classes.dex) = " + sb.ToString());
  • 22. 4 Apr 2013 Page Native libs check (UnityScript) 22 // Retrieve main Activity var unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); var activity = unity.GetStatic.<AndroidJavaObject>("currentActivity"); // Retrieve ApplicationInfo and nativeLibraryDir (N.B. API-9 or newer only!) var info = activity.Call.<AndroidJavaObject>("getApplicationInfo"); var nativeLibraryDir = info.Get.<String>("nativeLibraryDir"); var unityPath = Path.Combine(nativeLibraryDir, "libunity.so"); var file = new FileStream(unityPath, FileMode.Open, FileAccess.Read); var sha1 = new SHA1CryptoServiceProvider(); var hash = sha1.ComputeHash(file); file.Close(); // Print SHA1 sum var sb = new System.Text.StringBuilder(); for (var i = 0; i < hash.Length; i++)     sb.Append(hash[i].ToString("x2")); Debug.Log("sha1sum(libunity.so) = " + sb.ToString());
  • 23. 4 Apr 2013 Page Code Obfuscation 23
  • 24. 4 Apr 2013 Page Code Obfuscation • Java Obfuscation • Proguard • C# Obfuscation • Obfuscar • Hides method/variable names • but still very much readable code • False sense of security 24
  • 25. 4 Apr 2013 Page Java Obfuscation (before) 25 private void playVideo() {     doCleanUp();     try     {         mMediaPlayer = new MediaPlayer();         if (mIsURL)         {             mMediaPlayer.setDataSource(mContext, Uri.parse(mFileName));         }         else if (mVideoLength != 0)         {             FileInputStream file = new FileInputStream(mFileName);             mMediaPlayer.setDataSource(file.getFD(), mVideoOffset, mVideoLength);             file.close();         }         else         { (...)
  • 26. 4 Apr 2013 Page Java Obfuscation (after) 26 private void a() {     b();     try     {         this.r = new MediaPlayer();         if (this.h)         {             this.r.setDataSource(this.b, Uri.parse(this.e));         }         else         {             if (this.j != 0L)             {                 Object localObject = new FileInputStream(this.e);                 this.r.setDataSource(((FileInputStream)localObject).getFD(), this.i, this.j);                 ((FileInputStream)localObject).close();             }             else             { (...)
  • 27. 4 Apr 2013 Page Encryption 27
  • 28. 4 Apr 2013 Page Encryption of PlayerPrefs • Why? • Prevent simple cheating • Prevent cracking IAB purchases (if you cache anything locally) • In general good practice for sensitive data (like game progression) • How? • Encrypt key/values before inserting them in the PlayerPrefs • Use a user-specific encryption, so prefs cannot be copied, but still shared in a cloud 28
  • 29. 4 Apr 2013 Page SetString(key, value, secret) 29 // Hide 'key' string string key_string = MD5(key); // Convert 'value' into a byte array byte[] bytes = UTF8Encoding.UTF8.GetBytes(value); // Encrypt 'value' with 3DES('secret') TripleDES des = new TripleDESCryptoServiceProvider(); des.Key = secret; des.Mode = CipherMode.ECB; ICryptoTransform xform = des.CreateEncryptor(); byte[] encrypted = xform.TransformFinalBlock(bytes, 0, bytes.Length); // Convert encrypted array into a "readable" string string encrypted_string = Convert.ToBase64String(encrypted, 0, encrypted.Length); // Set the { key, encrypted value } pair in regular PlayerPrefs PlayerPrefs.SetString(key_string, encrypted_string);
  • 30. 4 Apr 2013 Page value GetString(key, secret) 30 // Hide 'key' string string key_string = MD5(key); // Retrieve encrypted 'value' and Base64 decode it string value = PlayerPrefs.GetString(key_string); byte[] bytes = Convert.FromBase64String(value); // Decrypt 'value' with 3DES('secret') TripleDES des = new TripleDESCryptoServiceProvider(); des.Key = secret; des.Mode = CipherMode.ECB; ICryptoTransform xform = des.CreateDecryptor(); byte[] decrypted = xform.TransformFinalBlock(bytes, 0, bytes.Length); // Return decrypted value as a proper string return UTF8Encoding.UTF8.GetString(decrypted);
  • 31. 4 Apr 2013 Page Encrypted SetString() / GetString() 31 // Generate a secret based on 'username' string username = "Turrican II"; MD5 md5 = new MD5CryptoServiceProvider(); byte[] secret = md5.ComputeHash(UTF8Encoding.UTF8.GetBytes(username)); // Game progress { key, value } pair string key = "unlocked levels"; string value = "the desert rocks,traps,secret dungeons,the wall,the final challenge,the final fight"; // Insert { key, value } pair SetString(key, value, secret); // Retrieve { key, value } string ret = GetString(key, secret); // Output to the logcat Debug.Log("secret = " + username); Debug.Log(key + " = " + ret);
  • 32. 4 Apr 2013 Page Encryption of Scripts • Why? • Scripts are generally insecure • Gameplay could be altered • Security checks could be disabled • Code needs to be “hidden” for some reason (i.e. IAB logic) 32
  • 33. 4 Apr 2013 Page Encryption of Scripts • How? • Compile scripts outside Unity • Run a symmetric / asymmetric encryption on the Script.dll • Choose a delivery mechanism • Embed in the application, or • Download it from a trusted server • Decrypt the Script.dll in memory • Load it through Assembly.Load(byte[]) 33
  • 34. 4 Apr 2013 Page Compile scripts outside Unity • Download Mono (www.mono-project.com) • Compile the script (Plugin.cs) with ‘gmcs’ • Reference the UnityEngine.dll assembly to access to Unity 34 $ gmcs -target:library -out:Script.dll -r:AndroidPlayer/Managed/UnityEngine.dll Plugin.cs
  • 35. 4 Apr 2013 Page Encrypt the assembly • Using OpenSSL • Converted to ‘text’ using Base64 encoding • Result can be embedded in Unity as a TextAsset 35 $ openssl rc2 -nosalt -p -in Script.dll -out Encrypted.bin key=... iv =... $ base64 Encrypted.bin > ~/UnityProject/Assets/Encrypted.txt
  • 36. 4 Apr 2013 Page Plugin.cs 36 using UnityEngine; public class SomeImportantGameClass {     static SomeImportantGameClass()     {         const int GET_SIGNATURES = 64;         AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer") .GetStatic<AndroidJavaObject>("currentActivity");         AndroidJavaObject manager = activity.Call<AndroidJavaObject>("getPackageManager");         string packageName = activity.Call<string>("getPackageName");         AndroidJavaObject packageInfo =                 manager.Call<AndroidJavaObject>("getPackageInfo", packageName, GET_SIGNATURES);         AndroidJavaObject[] signatures = packageInfo.Get<AndroidJavaObject[]>("signatures");         foreach (AndroidJavaObject signature in signatures)         {             Debug.Log("signature hash = " + signature.Call<int>("hashCode").ToString("X"));         }     } (...) }
  • 37. 4 Apr 2013 Page Decrypt and run assembly 37 public TextAsset assembly; void Start () {     // Load encrypted data and decryption keys     byte[] bytes = Convert.FromBase64String(assembly.text);     byte[] key = new byte[] { <key from encryption step> };     byte[] iv = new byte[] { <iv from encryption step> };     // Decrypt assembly     RC2 rc2 = new RC2CryptoServiceProvider();     rc2.Mode = CipherMode.CBC;     ICryptoTransform xform = rc2.CreateDecryptor(key, iv);     byte[] decrypted = xform.TransformFinalBlock(bytes, 0, bytes.Length);     // Load assembly and instantiate 'SomeImportantGameClass' to trigger static constructor     Assembly asm = Assembly.Load(decrypted);     Type SomeClass = asm.GetType("SomeImportantGameClass");     SomeClass.GetConstructor(Type.EmptyTypes).Invoke(null); }
  • 38. 4 Apr 2013 Page Encryption of Assets • Why? • Some assets might need to be protected from tampering. • “Assets” doesn’t necessarily mean just “textures”; could be • Game logic • Dalvik bytecode • Script code • Native code • .. “anything” 38
  • 39. 4 Apr 2013 Page Encryption of Assets • How? • Create an AssetBundle from the “secret” assets. • Run a symmetric / asymmetric encryption on the AssetBundle.unity3d • Choose a delivery mechanism • Embed in the application, or • Download it from a trusted server • Decrypt the AssetBundle.unity3d in memory • Load it through AssetBundle.CreateFromMemory(Byte[]) 39
  • 40. 4 Apr 2013 Page Conclusion • Be imaginative • APK integrity checks are so simple everyone should have them. • Sensitive code must be protected • Combine the different approaches, and create new ones • Finally: Don’t spend too much time on this • Instead update the logic for each new release. 40
  • 41. 4 Apr 2013 Page Questions? 41
  • 42. 4 Apr 2013 Page Thanks! 42 Twitter: @_eriq_