京東H5小遊戲《瘋狂足球》Android外掛實現
前言
首先宣告,此文僅用於技術交流,若用於牟利,後果自負!由於這個小遊戲高分者可獲得實體獎勵,通過外掛作弊取得高分獲取獎勵實屬詐騙,相信遊戲團隊也有辨別作弊的實力,請大家不要拿自己的信用作賭注,三思後行!
正文
最近,相信大家也被《瘋狂足球》這個小遊戲刷屏了,得分前三名送手機啊,再便宜也要上千塊一部吧。我也玩了幾天,得分最高只能取得280分,再也上不去了。看來我還是不適合玩遊戲,我還是迴歸本行繼續寫我的Bug吧…  ̄□ ̄||
所以,就有了今天的這篇分享…
言歸正傳,我們開始分析遊戲。這個遊戲和微信《跳一跳》的玩法很相識,都是用按壓的時間長度來控制力度。但是《瘋狂足球》還得控制方向,就是手指按下時的點指向手指擡起時的點。
力度控制
按壓的時間非常好控制,都是同一個值,觸控式螢幕幕固定的毫秒數後力度會達到正中間,這樣我們就能保證力度控制不會失誤了。
方向控制
方向控制就稍微麻煩了點,我們可以通過判斷截圖的畫素來獲取球門的位置;也可以在球門位置上加一層透明的視窗,手動指示球門的位置;甚至可以人肉計算球門的位置,這個就看大家喜歡了。
實現
知道了按壓時間、球門位置,再通過人肉測量足球的初始位置,那實現簡直不是事。Swipe就可以搞定了。
假設球的初始位置是x:100,y:200
球門的位置是x:300,y400
按壓時間250ms
那麼實現程式碼為:
adb shell input swipe 100 200 300 400 250
搞定!So easy!終於可以像姚明一樣踢足球了!
等等!~好像哪裡不對!
如果這樣做的話,我們每次踢球都是劃出一條完美的直線,如果防作弊系統記錄了我們的觸控座標,我們豈不是一秒就被紅牌警告?
所以不行,我們還得想想辦法解決這個問題。
手指觸控移動座標問題
要解決這個問題,我們還得模擬出真實的手指觸控移動座標,試問生成技術哪家強?出門左拐找Deep Learning。但是生成模擬座標我們需要大量的訓練資料啊,資料去哪裡找?所以,生成模擬座標這一項我們就放棄吧…
既然無法模擬,那我們就用真人手指去操作吧。那麼問題又來了,真人操作怎麼做到精準的控制時間?考驗我們變通能力的時候到了~
我們可以監聽手指的觸控事件,在手指按下的瞬間開始計時,250毫秒之後向系統傳送手指擡起的事件啊~我簡直是太聰明瞭,就這麼幹。
上程式碼,人生苦短,我用python,5行程式碼搞定:
import subprocess
import time
import random
for ii in range(20):
output = subprocess.getstatusoutput('adb shell getevent -c 1')
time.sleep(random.uniform(0.150,0.155))
output = subprocess.getstatusoutput('adb shell "cat /sdcard/up_event > /dev/input/event1"')
time.sleep(2)
但是,執行下來你會發現,功能是ok了,但是時間控制得不準啊。好吧,又要建立shell又要執行adb,是無法控制好時間的了,那我們先看看程式碼吧。後面再說說怎麼改進這個問題。
首先,adb shell getevent –c 1。getevent大家應該都知道了,這個命令可以打印出android裝置的所有事件,觸控式螢幕事件只是其一,這裡我們不考慮其他事件的影響。-c 1這個引數一定要加,否則getevent會一直處於列印狀態,無法返回,我們的程式就會卡在這一行程式碼上。然後cat /sdcard/up_event > /dev/input/event1這段程式碼是模擬手指擡起事件的。up_event中的資料如下圖所示,16進位制,可以通過cat /dev/input/event1 > /sdcard/events獲得,然後擷取最後一段手指擡起事件的資料就行了。/dev/input/event1是我手機的觸控式螢幕裝置,在其他手機上可能是event0或者其他。
時間控制不准問題
前面我們還遺留了一個問題,就是python程式碼時間控制不準。那我們可以將程式碼轉移到手機內去執行,這樣就可以避免啟動shell和adb時間的不確定性了。如果把這個過程做成一個APP,你會發現APP完全沒有許可權呼叫getevent,即使是系統級APP也不行。所以我把這段程式改用Java寫並編譯成dex檔案,chmod 777 crack.dex後,就可以執行了,當然,需要root許可權。雖然時間上還是有些偏差,但是沒有大問題。
Java程式碼:
public class Main {
public static void main(String args[]) {
for (int i = 0; i < 20; i++) {
runOperation();
}
}
static Random r = new Random();
static DataOutputStream dos = null;
static Process p;
private static void runOperation() {
try {
p = Runtime.getRuntime().exec("sh");
// 監聽觸控式螢幕事件
dos = new DataOutputStream(p.getOutputStream());
dos.write("getevent -c 1 /dev/input/event1".getBytes());
dos.writeBytes("\n");
dos.writeBytes("exit\n");
dos.flush();
BufferedReader successResult = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader errorResult = new BufferedReader(new InputStreamReader(p.getErrorStream()));
// 輸出錯誤資訊
String s = null;
StringBuilder errorMsg = new StringBuilder();
while ((s = errorResult.readLine()) != null) errorMsg.append(s);
if (errorMsg.toString().length() > 0)
System.out.println("fail getevent : " + errorMsg.toString());
int ignore = successResult.read();
// 關閉輸入輸出
successResult.close();
errorResult.close();
dos.close();
//利用sleep時間,在另一個執行緒中開啟sh
new Thread(new Runnable() {
@Override
public void run() {
try {
p = Runtime.getRuntime().exec("sh");
dos = new DataOutputStream(p.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(240 + r.nextInt(20));
// 模擬手指擡起事件
dos.write("cat /sdcard/up_event >> /dev/input/event1".getBytes());
dos.writeBytes("\n");
dos.writeBytes("exit\n");
dos.flush();
errorResult = new BufferedReader(new InputStreamReader(p.getErrorStream()));
// 輸出錯誤資訊
errorMsg = new StringBuilder();
while ((s = errorResult.readLine()) != null) errorMsg.append(s);
if (errorMsg.toString().length() > 0)
System.out.println("fail cat : " + errorMsg.toString());
//關閉輸入輸出
errorResult.close();
dos.close();
Thread.sleep(2000);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
執行dex檔案:dalvik –cp /sdcard/crack.dex packagename.Main
其他問題
即便做到了這種程度,還是無法躲過作弊檢測的。一是我們這種做法的缺陷,在我們模擬了up事件之後,由於手指還沒有離開,系統又會產生一個down事件和一系列move事件及up事件,如果遊戲檢測了這一部分觸控事件,那我們一秒就穿幫了。還有就是遊戲製作方可以記錄我們每一次遊戲的得分,再通過概率分佈的相關演算法來檢測我們是否作弊。
當然,這兩個問題完全可以通過深度學習解決,如果有人能完美的模擬人的操作和得分的概率分佈,那麼防作弊檢測將無法判斷是不是人在玩遊戲。除非他們也用上深度學習技術,GAN技術瞭解一下,哈哈。
謝謝觀賞~