Alexey Chubar, Technical Project Lead, BIT.GAMES
As your mobile game grows, it’s a matter of time until someone decides to hack it. A so-called «hacker» can impact your profits even without having any technical experience. We’ll talk about the most common threats and how to protect against them.
12. Подпись приложения: runtime-проверка
Вместо обращения к PackageManager вставляются обращения к
классу-заглушке Fix. Он возвращает оригинальные подписи, и наша
проверка проходит:
Hacker’s
public
key
Hacked
Signed
APK
1ceb00b5
Fix:
1ceb00b5
13. Подпись приложения: проверка в нативном коде
● Используя JNI, проверку можно вынести в С++. Машинный код
сложнее модифицировать, чем smali- и dll-файлы.
● Можно проверять в коде С# и выбрать Scripting Backend: IL2CPP.
string pkid = "your.package.id";
int flags = 0x00000040;//GET_SIGNATURES
using(var up = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
using(var ca = up.GetStatic<AndroidJavaObject>("currentActivity"))
using(var pm = ca.Call<AndroidJavaObject>("getPackageManager"))
using(var pi = pm.Call<AndroidJavaObject>("getPackageInfo", pkid, flags))
{
var signatures = pi.Get<AndroidJavaObject[]>("signatures");
…
14. Подпись приложения: проверка в нативном коде
● Простота
● Нет зависимостей от сторонних библиотек и сервисов
● Работает без интернета
● Сборка С++ отдельно под каждую архитектуру (ARM, x86, MIPS)
● Не панацея - машинный код можно дизассемблировать
bit.ly/PatchingBin
● На некоторых площадках нельзя заранее знать подписи:
○ Google Play при использовании Google Play App Signing
○ Amazon AppStore
15. Защита целостности: сторонние сервисы
SafetyNet - утилита Play Services для выявления угроз безопасности.
Onegini “Mobile Security Platform”
● Высокая степень защиты
● Широкий спектр доступных проверок
● Сложнее в реализации
● Зависимость от Google Play Services и/или других SDK
● Требуется доступ в интернет
● Не панацея, а дополнительное средство защиты
16. Защита целостности: обфускаторы
● Встроенные: Proguard
○ бесплатно
○ доступно в Android Studio, Unity, …
● Коммерческие:
● DexGuard, DexProtector, DashO
● iXGuard
○ стоят денег
○ много умеют
23. Обфускация данных в RAM
2347 3143
5760
● Числа в виде строк
● Числа в виде (перемешанного) массива байтов
● Произвольная арифметика над числами
● ...
“5”=53 “7”=55 “6”=54 “0”=48
5760
5 0 6 7
5760
24. Обфускация в RAM: v1 (Anti-Cheat Toolkit)
struct ObscuredInt {
private int bait, hiddenVal, key = 8713;
public void set(int value) {
bait = value;
hiddenVal = value XOR key;
}
public int get() {
int value = hiddenVal XOR key;
if(value != bait)
error(“Not so fast, dirty cheater!”)
return value;
}
...
25. Обфускация в RAM: v40968623587
struct ObscuredInt {
private static Random rnd = new Random();
//now static; new random key each session
private static int key = rnd.NextInt();
//split value in 2 memory cells, added checksum
private int hiddenVal0, hiddenVal1, checksum;
//random split on each “set” call:
private int storeHiddenVal(int val) {
int part = rnd.Range(0, val);
hiddenVal0 = part;
hiddenVal1 = val - part;
checksum = crc32(mem0, mem1);
}
26. Обфускация данных в RAM: v40968623587
● Значение “наживки”, которое видно пользователю (в окрестности
которого есть реальные данные), больше не используется.
● Отсев невозможен, так как каждое присвоение значения меняет
разбиение между ячейками и контрольную сумму случайным
образом.
● Ключ лежит в другой области данных.
● Каждую сессию создаётся новый ключ.
● Сохраняется возможность обнаружить изменение ячейки путём
проверки контрольной суммы.
● Хорошая производительность.
27. Манипуляции с сохранёнными данными
Сохранённые локально данные приложения на Android-устройствах
можно найти и модифицировать/заменить даже без root-доступа. Их
стоит шифровать.
Пример пути: /storage/emulated/0/Android/data/app.package.id/files
Game
Money = 100
Save
Editor
Money = 999
Edit
Game
Money = 999
Load
28. Манипуляции с сохранёнными данными
Unity-класс PlayerPrefs позволяет хранить данные между сессиями
● SharedPreferences /data/data/pkg_id/shared_prefs/pkg_id.xml
● plist file /Apps/app_folder/Library/Preferences/app_name.plist
● Нет доступа извне без root/jailbreak.
● Удобно пользоваться
● Только некоторые типы данных: int, float, string, bool*, string array*
● Редко: спонтанная очистка SharedPreferences при обновлении
игры или ОС
29. Манипуляции с сохранёнными данными
Игровые сервисы торговых площадок предоставляют API для
защищённого облачного хранения данных:
● Google Play Games (Saved Games API, Games.Snapshots)
● iOS Game Center/GameKit (GKSavedGame)
● Amazon GameCircle (Whispersync)
● Защита
● Возможность восстановления прогресса из облака
● Интеграция с Unity и другими платформами для разработки
● Зависимость от сервисов каждой конкретной платформы
30. Защита от перевода часов
Пользователи могут переводить
время или изменять часовой пояс
на устройстве, чтобы пропустить
ожидание в игре.
31. Защита от перевода часов: монотонные часы
Time server
Valid current time
GetUptime()
- Uptime delta
1. Sync
rebooted?
2. Get time
GetUptime()
Yes
No
Time
+
● SystemClock.elapsedRealtime()
● sysctl call
● “Time-cheat prevention by Vasilij", etc...
32. Защита от перевода часов: монотонные часы
rebooted?
2. Get time
HackedUptime()
No
Time + 10h
+Uptime delta
Хакер может вмешаться в работу монотонных
часов на устройстве и перемотать время
33. Итоги
1. Модификация и перепаковка приложений. Проверка подписей и
другой критичный функционал - в нативном коде. Сервисы
проверки целостности.
34. Итоги
1. Модификация и перепаковка приложений. Проверка подписей и
другой критичный функционал - в нативном коде. Сервисы
проверки целостности.
2. Манипуляции с данными приложения. Шифрование сохраняемых
данных. Облачное сохранение. Обфускация данных в памяти.
35. Итоги
1. Модификация и перепаковка приложений. Проверка подписей и
другой критичный функционал - в нативном коде. Сервисы
проверки целостности.
2. Манипуляции с данными приложения. Шифрование сохраняемых
данных. Облачное сохранение. Обфускация данных в памяти.
3. Манипуляции со временем и перевод часов. Использовать
монотонные часы и синхронизацию.