一個方向,你能否改變世界?
先來看看效果圖:
由於 Pay 的效果圖被遮蔽,這裡以刷文章的方式呈上。注意:開啟「某度」,輸入地址,瀏覽,點選廣告等操作都是手機自動完成,非人為手指控制,同時手機非 Root 非無障礙並沒有連線 usb。
親測還能自動 Pay,自動回覆,自動 Play Music 等等,用句誇大詞說:只有你想不到,沒有做不到。
前言
說來話長,那我就長話短說,在去年有個朋友讓我幫忙刷某度文章閱讀量,作為一名程式設計師,首先想到模擬介面訪問,經常一番折騰就放棄了,大廠的網路傳輸加密不是那麼好破解的,嘗試了幾種抓包,攔截,改變引數,再次傳送的方式,測試並沒有成功。
同許多程式設計師一樣,喜歡一條路走到黑,不見南牆不回頭,通過網上搜尋大量資料來破解加密,一次次失敗,最終還是失敗了,不得不佩服某度的網路安全體系,不是我一個「嫩頭青」可以破解的。
那麼問題還是回到起點,既然不能改變介面環境,那麼只剩下一個笨辦法,手動輸入地址,查閱文章,來達到閱讀量的增加。不過接下來的問題就讓人太尷尬了,那就是效率問題,手動查閱太枯燥效率太低了,那能不能手機自動完成查閱文章的動作,並不需要人工操作呢。
答案是肯定的,雖然效率低了點,依舊是一種解決方案。說好的長話短說,這話又說多了。
實踐
大家都知道 Android 除錯橋 (adb) 是一個通用命令列工具,其允許您與模擬器例項或連線的 Android 裝置進行通訊。它可為各種裝置操作提供便利,如安裝和除錯應用,並提供對 Unix shell(可用來在模擬器或連線的裝置上執行各種命令)的訪問。
比如模擬按鍵點選:
adb shell input tap 460 410
複製程式碼
點選螢幕 (460 410) 這點,模擬輸入文字:
adb shell input text hello
複製程式碼
輸入文字「hello」,模擬滑動:
adb shell input swipe 300 1000 300 500
複製程式碼
引數 300 1000 300 500 分別表示起始點 x 座標,起始點 y 座標,結束點 x 座標,結束點 y 座標。模擬回車,返回鍵:
adb shell input keyevent 66
adb shell input keyevent 4
複製程式碼
66 表示回車,4 表示返回鍵。還有常見的 adb install ,adb push 錄屏截圖等等。想檢視更多 adb 命令,請連結 awesome-adb。好了,具體看案例。
「某度」自動瀏覽文章
「某度」自動瀏覽文章為了以下幾步:
- 開啟「某度」app
- 點選頂部輸入框
- 輸入瀏覽的文章地址
- 回車,搜尋文章
- 滑動(瀏覽)
- 點選推薦廣告
- 點選返回鍵退出
第一步,啟動應用 / 調起 Activity 的命令如下:
adb shell am start [options] <INTENT>
複製程式碼
例如:
adb shell am start -n com.tencent.mm/.ui.LauncherUI
複製程式碼
表示開啟「微信」主介面。引數 com.tencent.mm 表示微信包名 .ui.LauncherUI 表示開啟的 Activity 的名稱。檢視當前介面 Activity 名稱的方式有許多,這裡推薦 android-TopActivity。如下圖左上角:
獲取到「某度」的包名與主介面的名稱為,com.baidu.searchbox 與 .MainActivity ,那麼開啟「某度」的 adb 命令如下: adb shell am start -n com.baidu.searchbox/com.baidu.searchbox.MainActivity
複製程式碼
第二步,點選頂部輸入框區域,那麼需要獲取到點選點的座標位置,可以藉助「開發者選擇」的「指標位置」來獲取:
那麼我們通過模擬點選 (431 380) 來模擬點選輸入框: adb shell input tap 431 380
複製程式碼
第三步,輸入瀏覽文章的地址,adb 命令如下:
adb shell input text 'https://na.mbd.baidu.com/je3rqk2?f=cp'
複製程式碼
注意:如果你安裝了第三方輸入法,可能會導致輸入錯亂,請在「設定」「語言與輸入法」「虛擬鍵盤」下關閉第三方輸入法。
第四步,回車搜尋,adb 命令如下:
adb shell input keyevent 66
複製程式碼
注意:文章搜尋是非同步,需延遲後續操作,在後文中會講到。
第五步,模擬滑動,adb 命令如下:
adb shell input swipe 200 1800 200 0
複製程式碼
起點 y 座標 1800 與結束點 y 座標 0 ,相差越大滑動越大,在每個機型上需要調整,同時滑動到廣告出現在螢幕內的次數可能也不一樣。具體請在真機上模擬調整。
第六步,點選推薦廣告,同上獲取到廣告區域的座標點:
對應的 adb 命令如下: adb shell input tap 583 339
複製程式碼
第七步,點選返回鍵的 adb 命令:
adb shell input keyevent 4
複製程式碼
總共七步就完成了一次自動瀏覽文章,有小夥伴肯定會有疑問,不會每步都執行 DOS 命令吧,這樣比手動點選還慢呢,那有沒有指令碼可以批處理。
bat (批處理檔案型別)就是解決這樣的問題。新建 xx.bat 檔案,把以下程式碼拷入:
ping 127.0.0.1 -n 2
adb shell am start -n com.baidu.searchbox/com.baidu.searchbox.MainActivity
ping 127.0.0.1 -n 3
adb shell input tap 431 380
adb shell input text https://na.mbd.baidu.com/je3rqk2?f=cp
ping 127.0.0.1 -n 1
adb shell input keyevent 66
ping 127.0.0.1 -n 3
adb shell input swipe 200 1800 200 0
ping 127.0.0.1 -n 2
adb shell input swipe 200 1800 200 0
ping 127.0.0.1 -n 2
adb shell input swipe 200 1800 200 0
ping 127.0.0.1 -n 2
adb shell input swipe 200 1200 200 0
ping 127.0.0.1 -n 2
adb shell input tap 583 339
ping 127.0.0.1 -n 5
複製程式碼
儲存,確保手機連上電腦,雙擊 xx.bat 檔案,發現手機自動開啟百度,輸入地址,瀏覽文章,哈哈,這樣方便多了。但還有一個小小的不足,瀏覽完一次文章 xx.bat 就結束了,能不能加個迴圈語句,讓文章間斷性被瀏覽。由於並不熟悉 .bat 的寫法,研究了一下,功夫不負有心人,我們可以這麼做:
:start
ping 127.0.0.1 -n 2
adb shell am start -n com.baidu.searchbox/com.baidu.searchbox.MainActivity
ping 127.0.0.1 -n 3
adb shell input tap 431 380
adb shell input text https://na.mbd.baidu.com/je3rqk2?f=cp
ping 127.0.0.1 -n 1
adb shell input keyevent 66
ping 127.0.0.1 -n 3
adb shell input swipe 200 1800 200 0
ping 127.0.0.1 -n 2
adb shell input swipe 200 1800 200 0
ping 127.0.0.1 -n 2
adb shell input swipe 200 1800 200 0
ping 127.0.0.1 -n 2
adb shell input swipe 200 1200 200 0
ping 127.0.0.1 -n 2
adb shell input tap 583 339
ping 127.0.0.1 -n 5
adb shell input keyevent 4
adb shell input keyevent 4
adb shell input keyevent 4
adb shell input keyevent 4
adb shell input keyevent 4
goto start
pause
複製程式碼
ping 127.0.0.1 -n 1
用於延遲執行,由於每步操作都是非同步,延時時間你可以根據具體情況而定。emmm,大功告成,文章被無限週期性瀏覽,但還是有兩個小小的瑕疵,一是要執行 bat 指令碼;二是手機必須連上電腦。針對第一種情況,可不可以在 app 內執行 adb shell 命令,最初嘗試提示「permission denied」許可權被拒絕,需要 Root 許可權,Root 太麻煩,而且使用者也不會同意,那麼我們可不可以繞過 Root 許可權?
這個問題一直困擾著我,在這裡非常感謝 gtf 同學的免Root實現靜默安裝和點選任意位置(非無障礙)文章,這裡引用他的一段話:
我來問大家個新問題,怎樣讓 app 獲取 root 許可權?這個問題答案已經有不少了,網上一查便可知其實是獲取「Runtime.getRuntime().exec」的流,在裡面用su提權,然後就可以執行需要 root 許可權的 shell 命令,比如掛載 system 讀寫,訪問 data 分割槽,用 shell 命令靜默安裝,等等。話說回來,是不是和我們今天的主題有點像,如何使 app 獲取 shell 許可權?嗯,其實差不多,思路也類似,因為本來 root 啦, shell 啦,根本就不是 Android 應用層的名詞呀,他們本來就是 Linux 裡的名詞,只不過是 Android 框架執行於 Linux 層之上, 我們可以呼叫 shell 命令,也可以在shell 裡呼叫 su 來使shell 獲取 root 許可權,來繞過 Android 層做一些被限制的事。然而在 app 裡呼叫 shell 命令,其程式還是 app 的,許可權還是受限。所以就不能在 app 裡執行 shell 命令,那麼問題來了,不在 app 裡執行在哪執行?答案是在 pc 上執行。當然不可能是 pc 一直連著手機啦,而是 pc 上在 shell 裡執行獨立的一個 java 程式,這個程式因為是在 shell 裡啟動的,所以具有 shell 許可權。我們想一下,這個 Java 程式在 shell 裡執行,建立本地 socket 伺服器,和 app 通訊,遠端執行 app 下發的程式碼。因為即使拔掉了資料線,這個 Java 程式也不會停止,只要不重啟他就一直活著,執行我們的命令,這不就是看起來 app 有了 shell 許可權?現在真相大白,飛智和黑域用 usb 除錯啟用的那一下,其實是啟動那個 Java 程式,飛智是執行模擬按鍵,黑域是監聽系統事件,你想幹啥就任你開發了。「注:黑域和飛智由於程式管理的需要,其實是先用 shell 啟動一個 so ,然後再用 so 做跳板啟動 Java 程式,而且 so 也充當守護程式,當 Java 意外停止可以重新啟動,讀著有興趣可以自行研究,在此不多做說明」
這裡有一句話說的非常好,「你想幹啥就任你開發了。」 如果調整好引數,我可以拿到「某信」的付款二維碼,並能截圖上傳,就問你怕不怕?
gtf
同學的思路,讓我醍醐灌頂,並不是繞過 Root 許可權,而是在 pc 上在 shell 裡執行獨立的一個 java 程式,,這個程式因為是在 shell 裡啟動的,所以具有 shell 許可權。這個 Java 程式在 shell 裡執行,建立本地 socket 伺服器,和 app 通訊,遠端執行 app 下發的程式碼。因為即使拔掉了資料線,這個 Java 程式也不會停止,只要不重啟他就一直活著,執行我們的命令,這不就是看起來 app 有了 shell 許可權?
大家想一想,如果我把 Java 程式部署到遠端伺服器上,那麼我能隨時隨地都可以建立 socket ,從而控制手機自動完成想做的事情。
還得再次感謝 gtf
同學分享了一個簡單的 socket 程式,親測後的效果圖如下:
細節一,通過 javac
執行多個 .java
檔案:
D:\>cd D:\AndroidSpace\app_process-shell-use\app\src\main\java\shellService
D:\AndroidSpace\app_process-shell-use\app\src\main\java\shellService>javac -encoding UTF-8 Main.java Service.java ServiceShellUtils.java ServiceThread.java
複製程式碼
首先 cd 到 java 目錄,然後執行 javac 命令。注意:指定編碼格式為 UTF-8 ,不然中文亂碼會導致編譯不通過。編譯過的目錄如下圖:
細節二,多個.class
檔案生成 .dex
檔案
D:\AndroidSpace\app_process-shell-use\app\src\main\java\shellService>cd..
D:\AndroidSpace\app_process-shell-use\app\src\main\java>dx --dex --output=D:\hello.dex shellService/Main.class shellService/Service.class shellService/Service$CreateServerThread.class shellService/Service$ServiceGetText.class shellService/ServiceShellUtils.class shellService/ServiceShellUtils$ServiceShellCommandResult.class shellService/ServiceThread.class shellService/ServiceThread$1.class
複製程式碼
注意,首先需要 cd 到 java 目錄,不然會提示類檔案找不到,然後通過 dx --dex 命令生成 .dex 檔案,所生成的所有 .class 檔案都需要加到命令中。生成的 .dex 檔案如下圖:
細節三,app_process 執行 java 程式:D:\AndroidSpace>cd..
D:\>adb push hello.dex /data/local/tmp
hello.dex: 1 file pushed. 1.5 MB/s (8096 bytes in 0.005s)
D:\>adb shell app_process -Djava.class.path=/data/local/tmp/hello.dex /data/local/tmp shellService.Main
>>>>>>Shell鏈嶅姟絝▼搴忚璋冪敤<<<<<<
鏈嶅姟絝繍琛屽湪4521絝彛
複製程式碼
首先 cd 到 .dex 目錄,接著把 .dex 檔案推到手機 /data/local/tmp
目錄下,最後執行 app_process 命令,因為 utf8 在 Windows shell 裡有問題,所以亂碼了,但是還是說明我們成功了。
由於 adb shell 需要 usb 連上手機才能執行,那麼我們可以通過 ADB WiFi 來連線手機,執行 app ,DOS 的執行情況如下:
鍏抽棴Socket
鐩戝惉璇鋒眰鍒版潵鍒欎駭鐢熶竴涓猄ocket瀵矽薄錛屽苟緇х畫鎵ц
鍒涘緩浜嗕竴涓柊鐨勮繛鎺ョ嚎紼?
鐢盨ocket瀵矽薄寰楀埌杈撳靉嫻侊紝騫舵瀯閫犵溮搴旂殑BufferedReader瀵矽薄
鐢盨ocket瀵矽薄寰楀埌杈撳嚭嫻侊紝騫舵瀯閫燩rintWriter瀵矽薄
while寰幆錛氳幏鍙栦粠瀹㈡埛絝鍏ョ殑瀛楃涓?
while寰幆錛氬鎴風榪斿洖 : adb shell input tap 545 980
while寰幆錛氭湇鍔″櫒灝嗚繑鍥烇細###ShellError#sh: <stdin>[1]: adb: not found
while寰幆錛氬噯澶囧埛鏂拌繑鍥?
while寰幆錛氬凡鍒鋒柊榪斿洖
複製程式碼
報了 adb: not found
,缺少 adb 的執行環境。那麼我們可以在手機上搭建 adb 執行環境,具體可以參考手機對手機進行adb指令(OTG),本篇並不會講解如何在手機上搭建 adb 環境,因為在多數情況下我們並不會把 Socket 的服務端部署在手機上,而是部署在 pc 上,步驟如下。
執行這個服務端:
public class Main {
public static void main(String[] args){
new ServiceThread().start();
while (true);
}
}
複製程式碼
執行客戶端,建立連線。注意:HOST = "192.168.xxx.xx" 換成區域網 ip 地址。在 MainActivity 類中直接呼叫:
runShell("adb shell am start -n com.baidu.searchbox/com.baidu.searchbox.MainActivity");
Thread.sleep(1000);
runShell("adb shell input tap 460 410");
...... 省略其他
複製程式碼
手機自動瀏覽「某度」文章,當這個時候拔去 usb 連線,會提示 no devices/emulators found
表明無裝置連線,在上文中已經提到,這個時候可以通過 ADB WIFI 連線。
總結,思考
總結,手機自動操作操作還不夠成熟,還有一些技術需要攻破,同時也存在了安全隱患。思考,汽車有了自動駕駛,為啥安卓不能有「自動操作」。
如果覺得本篇文章對你有用,別忘記給小編控制元件庫點 star ,點 star,點 star
原始碼如下:
如果對「自動操作」感興趣的小夥伴,點選下面二維碼,關注:控制元件人生