xxapp
打卡。要想本身打卡, 那麼我抓包獲取接口和參數,本身組裝,本身訪問接口便可。 說幹就幹,我開始在登陸界面進行抓包:從圖上能夠發現:web
herades
裏面有一些參數,包括了custom-device-id
,custom-version
,custom-os
,custom-company-id
,x-json-web-token
等,這些內容是自定義header
加上去的,後期調用接口時可能會用到https
鏈接既然XXX採用https
方式,咱們沒有證書,就沒法攔截獲取信息,接口調用基本行不通了,那麼咱們採用AccessibilityService
輔助功能的方式進行打卡如何呢?json
思路是:將一臺手機放到公司,鏈接網絡,另外一臺手機遠程
app
是在運行的,而後經過AccessibilityService
進行輔助點擊從而進行打卡。或者直接設置定時器,時間到以後自動觸發以上過程並打卡。但這種思路對進程保活有至關高的要求,不太好實現。數組
使用https
以前的XXX,確定是http
,那麼http
接口今安在?bash
竟然200
,並且從返回的json
來看,登陸接口對於服務器的邏輯來講是沒問題的,應該是在使用中,那麼下一步咱們只須要拿到入參就行。服務器
下一步,反編譯xxxx.apk
,用到的工具是AndroidCrakTool
:網絡
這裏要提一下,反編譯後咱們能拿到資源文件們,資源文件對於定位頁面,控件,以及此控件接下來的邏輯是相當重要頗有幫助的。app
AndroidManifest.xml
和res
文件夾留下,其餘的刪除便可,由於咱們這次不對smali
進行分析接下來,咱們將XXX.apk
後綴名改成zip
,而後解壓,獲得以下內容:ide
能夠看到,獲得了兩個dex
文件,一個classes.dex
和classes2.dex
,這是由於他的方法數超過了65536
,進行multidex
的結果。如今咱們使用AndroidCrakTool
對這兩個dex
進行dex2jar
,目的是將dex
轉成jar
包,方便咱們閱讀源碼。工具
獲得jar
包以後,咱們用JD-GUI
打開閱讀,也可使用AS
或者IDEA
進行源碼閱讀。這裏採用JD-GUI
。佈局
打開這兩個jar
以下圖:
如今來理一理思路,咱們剛纔測試的是登陸接口,咱們目的是打卡,那麼咱們就須要登陸後,獲得
token
,而後帶上token
和一大堆參數進行打卡接口的訪問,因此第一步,咱們須要獲得登陸接口的參數。
咱們經過使用TopActivity
,在手機上找到登陸界面的Activity
名字:
從圖中左上角能夠知道這個界面的名字和包名,因此咱們在JD-GUI
中找到對應的包名進入尋找登陸界面。因爲咱們有兩個jar
,因此就先挨個找吧。但從順序來講,這個登陸界面通常會在dex1
中,固然這也是猜想,不過通常按照代碼量和順序來看的話是這樣的。果不其然,以下圖:
從界面上看,咱們是點擊了
button
以後進行網絡請求的,因此咱們當作員變量,發現一個button
,變量名i
,而後緊接着下面有個b()
方法,內部將i
初始化了,findviewbyid()
內部傳入的正是這個button
的id
在R
文件中的靜態常量值。這裏插一句,若是有須要對界面和id
進行分析的話,就須要從這些dex
中找到R
文件,而後將這個id
的數值拿去尋找匹配,就能在R
文件中反向獲得這個控件的id
,而後將這個id
拿到以前反編譯後的res
文件夾中搜索匹配,從而獲得佈局文件,控件id
等。固然也能經過AS
的DDMS
進行佈局分析,從而獲得id
,不過那個id
是混淆後的,在jar
中是沒法找到的,由於jar
中使用的id
是int
靜態常量。
接下來咱們將i
變量的id
值2131362755
用來進行搜索,獲得設置點擊事件的地方。這裏爲什麼不直接用變量i
呢?由於i
是混淆後的,搜出來可能會有不少,很差排除。
從圖上能夠看到,咱們找到了onClick()
回調,而且找到了點擊後的邏輯。圖中有個方法,叫executeOnExecutor()
,看起來像是AsyncTask
的線程池執行方法,咱們看看是否是,這時候點擊前面new b()
,看看這個b
對象是啥,以下圖:
能夠看到果真是AsyncTask
。那麼結果就顯而易見了,這次請求使用AsyncTask
發起,因此咱們在AsynctTask
內部就能找到網絡請求的相關內容了。先看第一個:
protected Void a(Void... paramVarArgs){
this.b = b.w(this.d, this.e);
return null;
}
複製代碼
此方法一看就知道,他是doInBackground
方法混淆後的,由於他的返回值是Void
而不是void
。在這個AsyncTask
實現的時候,泛型定義以下:
private class b extends AsyncTask<Void, Void, Void>{}
複製代碼
三個Void
,因此能夠判定第一個a()
方法是doInBackground
。那麼網絡請求就在這裏面了。再來看第二個a()
方法。
protected void a(Void paramVoid){}
複製代碼
從返回值和參數來看,多是onCancelled()
和onPoseExcute()
,可是從總體代碼和代碼量來看,能夠判定是onPoseExcute()
:
如今回過頭來分析doInBackground()
。
this.b = b.w(this.d, this.e);
複製代碼
咱們點擊w()
進入看看:
能夠看到,這個b
對象的w()
方法,就是組裝登陸接口所需參數的,登陸接口須要2
個參數,最下面
那個是接口地址,紅色部分
是一串字符串。而經過大碼部分的字符串,咱們能夠知道第二個參數是密碼,那麼後面跟一串字符串是什麼呢?是否是加密?,咱們點擊e.a()
中的a()
方法去看看:
從圖上能夠看到a()
方法接收一個參數,聯繫剛纔組裝數據的地方,能夠知道,密碼是由明文加後面紅色部分字符串
,再總體通過MD5
加密以後的。至於爲什麼知道是明文密碼,咱們返回到LoginActivity
,在AsyncTask
實例化的時候傳入了兩個參數,後者就是密碼。這個密碼字符串的獲取方式是反推出來的,以下圖:
因此,如今咱們有了接口地址,參數,加密方式,咱們試試看可否訪問成功。
通過調試,登錄成功,server
返回了一堆數據,其中包括了token
,id
等:
咱們如今至關於完成了50%
。
接下來的步驟要比以前簡單太多了。經過抓包,獲取到打卡接口的大概路徑,而後在剛纔組裝登陸接口參數的
b
類中,查詢匹配這個接口地址,因而獲得了打卡的完整接口地址。而且獲得了入參。剩下的就是慢慢組裝數據了。咱們須要打卡,那麼就須要經緯度。經過反編譯發現他是用的是高德地圖,因而咱們使用高德的地理位置反編碼,將咱們想打卡的位置的經緯度獲得,而後傳入參數體,從而實現登陸並打卡。
其實整個過程走下來,最主要的幾個點:
https
後,原http
接口未關閉,多是爲了兼容老版本apk
未進行更深層的保護,僅僅只是混淆最後,此次嘗試主要是利用了http
接口未關閉的漏洞,其實說到底也就是一次抓包分析數據的過程。
app
名字也替換成了XXX