Android逆向之旅--免Root實現微信訊息同步原理解析

編碼美麗發表於2018-06-22

感謝「珍惜」同學投稿,也熱烈歡迎其他同學來投稿,分析是一種快樂,也是一種精神!


現在很多應用有一些需求需要獲取監聽微信訊息,然後做一些事情,有的會把當前微信聊天資訊直接同步到服務端進行分析使用者行為,這麼做可能為了更好的使用者體驗,但是這樣是很不安全的對於使用者來說,因為微信官方都說不會儲存使用者聊天資訊的,不過本文單純從技術討論一下有沒有免Root進行操作,當然Root之後就不多說了方法太多了。

 

第一種:通過輔助功能和截圖功能

因為是免root所以用到的東西全都是系統api做出來的效果下面說一下具體實現原理,本功能主要用到了AccessibilityService+MediaProjectionManager+文字識別。

第一、輔助功能AccessibilityService無障礙類最初的設計理念是幫助殘疾人的但是在國內被做成黑科技 ,比如自動搶紅包,自動安裝 app,等一些實現場景,這個類可以對每個APP進行監聽獲取一些view的控制元件資訊! 

第二、MediaProjectionManager這個是5.0以上谷歌開放的API主要功能就是截圖當然需要使用者開啟許可權!

  

在這之前讀者們可以百度看看這幾個相關的API,網上的帖子說的都很不錯,不然的話看下面可能會有一些吃力,如果想做到訊息同步就首選要確認的是使用者是否傳送了訊息?筆者之前尋思用傳送按鈕的監聽方式 進行get 訊息處理,但是發現如果這樣的話不可以對對方傳送的訊息進行獲取。

 

也是想了很久,後來發現一件事,我可以對微信聊天頁面的ListView 的事件進行監聽操作, 在AccessibilityService裡面有一個方法可以處理每個 View 各種事件比如單機長按滑動狀態變更等,都有很明確的記錄,我只需要做到當聊天頁面的ListView 的控制元件進行滑動監聽即可獲取  有人傳送了訊息因為微信聊天頁面整體是一個ListView (可以通過 DDMS檢視對應的控制元件節點資訊 )可以通過DDMS 的方式拿到對應控制元件資訊如下圖所示:

640?wx_fmt=png

 

拿到指定的資訊以後通過AccessibilityService 提供的 findAccessibilityNodeInfosByViewId(ID)或者ByName方式拿到對應的控制元件,  返回的是一個List<AccessibilityNodeInfo> 因為一個節點裡面可能會有多個節點,簡單介紹一下 AccessibilityNodeInfo也是有助於下面的學習,這個是相當於獲取每個節點的詳細資訊,裡面有一些常用方法,getText() 獲取View的文字內容,getChildCount(),獲取控制元件子View的個數等,在WX裡面ListView裡面是一些自定義的View,如果直接對聊天的View 進行獲取  進行getText()返回的是NULL 微信在這個方面做了處理 ,在抓狂的時候,筆者發現在 一個方法:info.getBoundsInScreen(rect);這個方法的大概意思是獲取view在螢幕中的位置,需要傳入的是一個Rect有過一些開發經驗的可以知道一個 Rect可以定位到一個 View的具體位置如下圖所示:

640?wx_fmt=png


而info.getBoundsInScreen(rect);傳入的 view 經過處理以後返回的正是一個view的具體位置 ,筆者是先用了MediaProjectionManager(網上有很多寫好的程式碼筆者就不在這裡列舉了)對螢幕進行截圖然後獲取 Rect以後在在對截圖返回的 Bitmap 在根據 Rect  在對 Bitmap的進行擷取,效果圖如下:

第一次截圖

640?wx_fmt=png


第二次截圖

640?wx_fmt=png

 

最終結果就如上圖,下來就可以利用文字識別 Bitmap文字內容即可,在Github上面有很多好的文字識別整合進去即可,然後用文字識別拿到的資訊通過推送傳送到另一端即可,大概實現原理。如上所述以上實現以後還有很多問題 

問題1:如何拿到和誰聊天?

這個只需要對聯絡人的ID進行獲取,然後通過上述方法找到位置,然後截圖文字識別拿到,就可以拿到,這裡需要注意每次切換到聊天頁面都不一定是同一個聯絡人所以,每一次進入聊天頁面都需要進行處理。


問題2:怎麼判斷是否是聊天頁面?

大傢伙可以用 DDMS 的方式去找找相關的控制元件資訊,在聊天頁面的話有一個返回的按鈕,左上角的小箭頭而主頁面沒有可以根據這個view 是否存在判斷是否在聊天頁面還是主頁面。


問題3:怎麼判斷是誰傳送的訊息是自己還是對方?

可以獲取頭像的 View然後 getBoundsInScreen返回的Rect的右進行處理如果在左半螢幕就是對方發的訊息右半螢幕就是自己傳送的訊息。


問題4:微信的每個版本的ID都不一樣怎麼對全部的微信版本進行操作?

這個筆者也沒啥好的辦法,最後的辦法是在後臺做一張對映表 對應著每個版本控制元件的id,每次開啟輔助功能的時候獲取一下微信版本指定的ID。


問題5:如果在聊天頁面的時候別人也傳送了訊息應該怎麼辦?

因為是免root做的所以只能獲取當前螢幕所以不支援  如果有興趣的可以研究研究對螢幕的狀態進行監聽獲取傳送訊息的通知欄也是可以的。


問題6:如果之前和這個聯絡人有聊天內容,那獲取ListView的 getChildCount不準確怎麼辦?

因為需要對最後一條訊息進行獲取,所以需要獲取ListView的子view的最後一條訊息內容,筆者發現如果你和別人有100條記錄,ListView只能顯示20條最多(getChildCount返回的是20)如果有新訊息就是21,我們可以每次進入聊天頁面獲取ListView 的子孩子個數,這樣就可以拿到最後一條。


下面來分析這種方式有哪些問題和限制以及安全問題,我們從上面的原理知道,大致通過輔助功能和截圖功能實現的,那麼這兩個都是需要使用者授權的,而且這兩個許可權在之前也提到安全性是要值得關注的:

第一、輔助功能,我們可以監聽到當前應用開啟頁面,如果有惡意應用在後臺監聽到是社交或者支付應用的登入頁面,就偽造一個釣魚頁面,然後讓你輸入使用者名稱和密碼是他的釣魚頁面,這樣就被竊取到了使用者資訊,非常危險!

第二、截圖功能,這個之前介紹一個漏洞問題說到了,本身截圖功能就非常危險,比如金融類應用要是被偷偷的截圖了,那麼使用者的財產敏感資訊就被獲取到了非常危險!而對於這種情況,我們做應用開發的時候如果有一些頁面非常需要保護,可以設定一個安全屬性:WindowManager.LayoutParams.FLAG_SECURE

640?wx_fmt=png

比如上面的微信可以把聊天頁面加上這個屬性,這樣截圖就失敗了:

640?wx_fmt=png


所以使用者在使用應用的時候一定要注意正規應用,然後就是有哪些許可權是必須要開啟的,不要隨便開啟一些許可權,否則後果不堪設想。


下面繼續來看,上面是通過截圖然後圖片轉換成文字獲取訊息的,那麼假如不在聊天頁面怎麼辦呢?比如鎖屏或者在使用其他應用的時候,這個就需要藉助通知欄監聽服務NotificationListenerService了,這個也是需要使用者自己開啟許可權的,這個服務具體用法就不多介紹了,感興趣的同學自己網上搜尋看看,可以監聽到通知欄的訊息內容,這樣微信在後臺就可以獲取到資訊了,但是這種方式有個問題就是假如使用者把微信的通知欄功能關閉了就沒辦法了,不過一般很少人會關閉微信的通知欄訊息功能。


嚴重說明

本文的目的只有一個就是學習逆向分析技巧,如果有人利用本文技術進行非法操作帶來的後果都是操作者自己承擔,和本文以及本文作者沒有任何關係,本文涉及到的程式碼專案可以去編碼美麗小密圈自取,長按下方二維碼加入小密圈一起學習探討技術

640?wx_fmt=png


通過上面的兩種方式可以監聽到微信的聊天資訊,通過輔助功能和截圖功能以及圖片識別文字做的,還有通知欄監聽等方式,當然還有其他方式都可以做到,不過本文的目的不是讓你們去監聽微信訊息,畢竟微信自己都不做訊息上傳,本文的目的是通過這個案例告訴大家不要隨便的開啟任何危險性高的許可權,不要從不正規渠道下載非法應用!

 

手機檢視文章不方便,可以網頁看

http://www.520monkey.com


《Android應用安全防護和逆向分析》 

 點選檢視圖書詳情

640?wx_fmt=jpeg

長按下面

相關文章