抱歉,Xposed真的可以為所欲為——你的表白撤不回了

一句話概括本文

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

萬一小姐姐是向我表白,然後害羞又撤回了,我不就虧了是吧~

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

好吧,開個玩笑,不過能看到別人撤回的東西內心會莫名的偷(愉)稅(悅),而且有些老司機喜歡 發車然後撤回,圖還沒加載完,就撤回了,褲子他麼都脫了你TM撤回?

抱歉,Xposed真的可以為所欲為——你的表白撤不回了


1.胡亂分析第一波

圖1

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

先不具體去看源碼,如果是讓你來做這個消息撤回,流程會是怎樣? 首先,信息肯定是持久化到本地的,一般會保存在數據庫裡,不然怎麼每次打開。

撤回操作 -> 根據某一個標記檢索數據庫裡的記錄 -> 刪除記錄 -> 更新頁面 -> 發送信息到服務器更新其他用戶的撤回狀態。

Maybe是這樣,接著就開始跟代碼了,依舊是撈比的逆向套路:方法跟蹤 + 反編譯源碼 + 日誌定位。 從點下撤銷開始跟蹤,直到頁面顯示撤銷成功~,入手關鍵詞SQLite,然後依次涉及到這幾個類:

com.tencent.wcdb.database.SQLiteCursorcom.tencent.wcdb.database.SQLiteQuerycom.tencent.wcdb.database.SQLiteSessioncom.tencent.wcdb.database.SQLiteConnectioncom.tencent.wcdb.database.SQLiteDatabasecom.tencent.wcdb.database.SQLiteProgramcom.tencent.wcdb.database.SQLiteStatementcom.tencent.wcdb.database.SQLiteQueryBuilder

接下來就要一個個看這個類大概是幹嘛的了,用AS打開反編譯的項目,然後打開這些類,左側選擇

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

一個個結構看,限於篇幅這裡就不一一列舉了,最終定位類應該是SQLiteDatabase,它的結構裡看到了這些方法:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

接著就細化關鍵詞再搜索,進行方法跟蹤。

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

進去代碼看下這個update方法~

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

好吧,update調用的是**updateWithOnConflict()**方法,把參數打印出來看看?

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

可以,那麼分別來看看自己發信息撤回別人發信息撤回 的兩種情況:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

不難發現,第一個參數應該是一個代表信息類型的東西,普通信息是rconversation,而撤回信息類型是message,然後是第二個參數,類型是ContentValue,這個類用於存取鍵值對的數據,每個鍵值對錶示一列的列名和該列的數據,撤回類型的信息除了上面的content外還有後面一塊:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

我們先要明確防止撤回的是別人發的信息而不是自己的,所以先要過濾掉自己的,對比兩種情況得出這樣的結論:

-> 判斷第一個參數是否為message -> 獲取第二個參數中的type判斷是否等於10000(自己撤回是10002)

修改下程序,只處理別人發的信息的情況,打Log驗證下,

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

看Log卻意外發現了一個問題:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

所以判斷條件還要加上這個過濾條件,所以代碼就變成:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

繼續看Log:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

行吧,是個聰明人都知道msgId這個字段裡面有東西。

圖2


2.胡亂分析第二波

圖3

先從第一波跳出來,想想怎麼我們到底要幹嘛?信息處理簡單流程是這樣的:

收到信息會插入到數據庫裡,然後撤回就是移除數據庫裡對應的這條信息!

那麼我們可以:

  • 1.找個東西把所有接收到的信息存起來;
  • 2.當觸發了撤回操作,然後通過一個標識找到我們存起來的信息;
  • 3.把這條信息當做一個新的信息插入到數據庫裡;
  • 4.更改撤回的提示

強調一點,搬運,一開始我還想著去處理找個信息,然後拿點什麼,加點什麼。 後面發現改動的成本非常大,而且不知道會引發什麼樣的問題,所以拿到信息直接 傳就好,不要加特技進去!

然後是找個標識,猜測是第一波分析出來的msgId,等等還需要我們驗證下! 繼續跟方法,另一個賬號發送一條信息,然後全局搜insert,定位到了一個數據庫插入的方法!

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

不會直接跟這個bt.f類,因為參數一樣,而且執行插入操作肯定是不止調用一個方法的,跟下該方法的父方法,

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

繼續跟

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

可以,參數不一樣,說明信息是從這裡構造的,然後也調用了好幾個方法,打開源碼查看這個類: com.tencent.mm.storage.be 還有這個b方法,從左側的類結構可以看到,b方法有好幾個,但是第一個參數都是一樣的(bd bdVa) 進去這個bd類看看 com.tencent.mm.storage.bd

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

好複雜的類,加上混淆,看死個人,上面講了,搬運,而不是對信息做處理,我們要做的只是找到這個信息裡和msgId一樣的標記而已。全局搜msgId

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

恩,就是這個field_msgId了,我們通過Xposed拿到這個變量的值,然後做下對比,驗證下我們的猜想! 然後寫出這樣的程序:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

懷著忐忑的心情重啟手機,發信息,撤回信息,看下日誌

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

臥槽,屌,猜對了,接下來我們整個Map來存鍵值對,然後試試在觸發撤回操作的時候,根據msgId取出 對應的信息然後調用插入數據的方法,所以上面的代碼改一下,我們要拿到調用b方法的那個對象。 然後就有了這樣的代碼:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

運行下看看效果~

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

可以,儘管提示XX撤回了一條消息,但是信息並沒有真的被撤回,所以說Hook成功了~ 接著我們進行一些細節的優化,還有改下撤回的信息。把能打印的都打印出來吧,把Content內容修改下:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

打印下:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

感覺是type類型的問題,改改,改成撤回信息那個type?

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

嗯,信息是看到了,但是不應該是這樣的啊,後面排查了一下是updateWithOnConflict方法返回值是0, 才這樣,把返回值設置為1,就可以了(param.result = 1)

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

嗯,正常是正常了,不過這順序有點不對勁啊,撤回的提示信息比我們插入的信息快了一些,那就加點吧。

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

運行看看:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

想著大概差不多的時候,今早老同學發的一個鏈接,然後撤回,撤回信息提示變成這樣了:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

後來想想還是拼接成這樣的提示信息就算了,不要再在提示信息裡顯示具體內容:

小豬攔截到 XXX 撤回的信息

最終效果如下,可以,很贊:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

3.胡亂分析第三波

圖4

在我以為一切大功告成,膨脹得沾沾自喜的時候,測試小哥發現了意外的發現了一個Bug, 發語音,圖片,視頻,雖然沒撤回,但是打開失敗,估計就是文件被刪除了。

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

而Android裡刪除文件調用的是File類的delete方法,跟一波方法,直接搜File.delete看下是否真的有調用:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

依次發送語音,圖片,視頻,然後撤回,對應的刪除記錄:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

然後發現只有語音能夠正常打開,圖片和視頻都無法正常打開,跟了下路徑,

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

用ES瀏覽器來到這個路徑下:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

這就很奇怪了,明明圖片存在,但是就是不能正確加載,而且每次點開都會執行一次刪除的操作, 就是說數據庫裡還保存著這個記錄,撤銷信息無非 刪數據庫記錄+刪文件,刪文件肯定是沒問題的, 那麼問題肯定就出在刪數據庫記錄那裡了。跟蹤一下SQLiteDatabase裡的delete()方法,把參數和返回值打印下:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

依次做:發送語音,發送圖片,發送視頻然後撤回的日誌跟蹤。

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

結合delete方法一起看:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

結合上面的日誌和delete方法的代碼,可以得這樣的結論:

  • 1.音頻相關放在voiceinfo表裡,圖片相關放在ImgInfo2表裡,而視頻相關則放在videoinfo2表裡。
  • 2.還有個WxFileIndex2表,從刪除語句可以知道就是根據msgId去刪除對應的文件記錄,但是返回值卻有1,6,2,0?

跟下返回值的代碼:executeUpdateDelete()方法,在SQLiteStatement類

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

改變的行的數目?一般來說刪除一條數據,正確執行完,受影響的行數會是1。 而只有語音能正常播放,難道是這個原因?hook下這個方法,如果第一個參數是這四個表, 直接把返回值設置成1試試~

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

發下信息然後撤回下試試~

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

行吧,視頻和圖片都能打開了,到此總算完美解決的,真的是一波三折。 接著改下UI頁面,補上上次下廚房Hook Xposed檢測的開光和防撤回開關。 最後的界面如下:

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

小結

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

這就是我不喜歡折騰Xposed的原因,太多未知,總要去猜測,去驗證自己的猜測,不斷安裝重啟, 當你以為可以了,然後又出新的問題,如果不是 設計小姐姐的原因,真不想去碰這個東西。

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

附:因為代碼比較長,而且改動了下廚房,還有王者榮耀相關的代碼,所以就不貼代碼了,

直接給出倉庫鏈接自取 github.com/coder-pig/C…

抱歉,Xposed真的可以為所欲為——你的表白撤不回了

作者有一系列Xposed相關文章,可以在掘金關注。


分享到:


相關文章: