[Android] [PokemonGO] 我也來inverse engineering一下
Posted on 週四 25 八月 2016 in Archive
其實大部分的分析就靠這篇神文就可以了XD 但其中對於Sensor/Location資訊是如何利用的著墨較少,所以只好自己來一下 亂猜的部分很多,還請不吝指教<( )>
Use dex2jar & JD-GUI to decompile .dex files
(Update: 原文有附整理過的source code了--雖然是剛出的時候的版本,不想自己做的可以跳過這段:P) 因為我的目標不是創一個可build的專案,只要看懂裡面在幹麻就好 所以就使用原文第一階段的方法,先用dex2jar把.dex轉成.jar file,然後用JD-GUI去讀
Compile dex2jar
RRRR 因為現在找不到prebuilt版的,只好從source開始
目前已經是用gradle build,還有gradle wrapper
所以只要解壓縮,點兩下gradlew.bat
就可以惹
會在src外面產生dex-tools-2.1-SNAPSHOT.zip
這個壓縮檔,裡面就是dex2jar全部的工具了
(如果沒有在外面找到,也可以在dex-tools/build/distributions/找到)
Refs:
https://sourceforge.net/p/dex2jar/wiki/BuildFromSource/
Pull out Pokemon GO apk
找一支有root過的手機,從play上下載最新的程式 (本文使用2016/8/25的版本)
再用adb pull下來
(adb安裝方法可參考這篇)
通常production buildl的load都不能直接pull /data/app
底下的東西
所以我都會先copy到sdcard裡
cp -r /data/app/com.nianticlabs.pokemongo-2 /sdcard/pkgo
//結尾不一定是2 看你更新了幾次 : P
adb pull /sdcard/pkgo
拉下來之後,可以看到這裡面有一個base.apk
和其他prebuilt的native lib
(都只有arm的,x86的phone繼續哭哭XD)
因為我們只需要看Android Location/Sensor API的部分
所以就只要把base.apk
用7zip之類的解壓縮之後
拿裡面的classes.dex
Turn .dex to .jar file
dex-tools-2.1-SNAPSHOT.zip
解壓縮之後
用裡面的d2j-dex2jar.bat
把base.apk轉成.classes檔
\> dex-tools-2.1-SNAPSHOT\d2j-dex2jar.bat classes.dex
dex2jar classes.dex -> .\classes-dex2jar.jar
Download JD-GUI
官網有各種平台的prebuilt程式,直接下載來用就對了~
http://jd.benow.ca/
打開剛剛gen出來的.jar檔就可以看到裡面的class啦~
Location/Sensor related analysis
核心功能部分幾乎都放在com.nianticlabs.nia這個package底下
幾個簡單的conclusion: - 好險還是沒有用Proguard XD - 使用了Android的三種location來源: GPS, Network, Google的Fused location - Location update的min period都滿短的: GPS 1 sec, Network 5 sec (很噴電不意外 : / - 直接call Sensor API的部分主要是拿來偵測手機旋轉or取得玩家面向的方位 - 有使用到Google的ActivityRecognition
Location part
package: com.nianticlabs.nia.location
在NianticLocationManager.java
裡面可以看到有三個Location provider
``` java NianticLocationManager.java
addProvider("fused", new FusedLocationProvider(this.context, this.gpsUpdateTimeMs, this.gpsUpdateDistanceM));
addProvider("gps", new LocationManagerProvider(this.context, "gps", this.gpsUpdateTimeMs, this.gpsUpdateDistanceM));
addProvider("network", new LocationManagerProvider(this.context, "network", this.netUpdateTimeMs, this.netUpdateDistanceM));
其中`LocationManagerProvider.java`就是個wrapper
三個provider裡面分別用Android `LocationManager`這個system service去拿GPS和Network location
和使用Google Mobile Service(GMS)的Fused location
"gps" 這個應該是`LocationManager.GPS_PROVIDER`, "network" 是`LocationManager.NETWORK_PROVIDER`
``` java LocationMangerProvider.java
this.locationManager = ((LocationManager)this.context.getSystemService("location"));
實際拿location的方法是呼叫requestLocationUpdates(String, long, float, LocationListener)註冊更新location時的listener 其中最小更新時間&距離的參數就是上面constructor帶入的 ``` java NianticLocationManager.java private float gpsUpdateDistanceM = 0.0F; private int gpsUpdateTimeMs = 1000; private float netUpdateDistanceM = 0.0F; private int netUpdateTimeMs = 5000;
更新時的listener則是統一使用`NianticLocationManager.java`裡建立的listener
這個listener最後會call到native lib,未看先猜應該是接到unity遊戲引擎
## Sensor
主要都在`NianticSensorManager.java`
接了一堆sensor service,但感覺最終目標都是要偵測手機旋轉和方位
最後接回native lib給遊戲引擎使用,未看先猜用來進省電模式和update地圖畫面使用
尤其是角色在地圖上的方向旋轉部分
``` java
public NianticSensorManager(Context paramContext, long paramLong)
{
super(paramContext, paramLong);
this.display = ((WindowManager)paramContext.getSystemService("window")).getDefaultDisplay();
this.sensorManager = ((SensorManager)paramContext.getSystemService("sensor"));
this.gravity = this.sensorManager.getDefaultSensor(9);
this.gyroscope = this.sensorManager.getDefaultSensor(4);
this.accelerometer = this.sensorManager.getDefaultSensor(1);
this.magnetic = this.sensorManager.getDefaultSensor(2);
this.rotation = this.sensorManager.getDefaultSensor(11);
this.linearAcceleration = this.sensorManager.getDefaultSensor(10);
}
Activity Recognition
最後,他居然有用Google 的Acitivity Recognition API! 看起來一樣也是接到Activity之後直接call native function。
瞄一下目前Google AR可以detect到的activity 可以偵測到的Activity有以下幾項:
int IN_VEHICLE The device is in a vehicle, such as a car.
int ON_BICYCLE The device is on a bicycle.
int ON_FOOT The device is on a user who is walking or running.
int RUNNING The device is on a user who is running.
int STILL The device is still (not moving).
int TILTING The device angle relative to gravity changed significantly.
int UNKNOWN Unable to detect the current activity.
int WALKING The device is on a user who is walking.
可能是拿來偵測玩家是否在跑動和是否在開車 (雖然專家指出,因為他目前實做似乎只有拿三軸資料,IN_VEHICLE ON_BICYCLE都很不準...)
Conclusion
只是decompile .dex看code能知道的還是有限 有試著用ELF tools decompile .so檔,但是大部分的symbol都mangled過不好分析
目前看不出來有做其他的省電機制(e.g. 玩家靜止就降低或停止location query) 想想這款遊戲核心技術部分本來就不在終端裝置,還沒有做多少優化也是滿合理的 : P
至於剩下有關網路的部分還是看原本的神文就好XD API實作方法應該不會改動太大
以上~