首先聲明,這絕不是接鍋,只是因?yàn)榉莱坊氐脑髡?fkzhang)不更新了,而我又非常需要防撤回,某些開車群總是喜歡開后撤回,于是...
在我決定做防撤回之前,我仔細(xì)研究了 fkzhang 開源的源碼,只可惜他那份源碼已經(jīng)年久失修,我特地下載了他最后支持的微信 6.3.13 版本,發(fā)現(xiàn)與現(xiàn)在所使用的 6.5.3 版本之間,代碼上的差距不是一星半點(diǎn),這直接讓我斷了在他的源碼上進(jìn)行維護(hù)的念頭。
既然不再想維護(hù),那必然是要自己起一套了,按之前折騰 mac 版微信的經(jīng)驗(yàn),我決定先找到revoke字樣所對(duì)應(yīng)的代碼,很幸運(yùn)的,搜索結(jié)果并不多,大概 10 多個(gè)類會(huì)涉及到 revoke,而經(jīng)過分析,大部分的類都是在寫 log,真正執(zhí)行 revoke 操作的是 com.tencent.mm.model.bo,截取關(guān)鍵代碼如下:

看起來是不是覺得很亂并且看不出邏輯?沒關(guān)系,我們?cè)谶@里需要做的只是取出數(shù)據(jù)而已,一開始的邏輯很明確的告訴了我們,如果str變量的值是revokemsg,那么就會(huì)走下面真實(shí)的撤回的代碼。
另一方面,通過抓取微信/data/data/com.tencent.mm內(nèi)的數(shù)據(jù)庫(kù),經(jīng)分析可知,微信的撤回的原理是修改數(shù)據(jù)庫(kù),將原本的信息改為『撤回了一條消息』。所以我們要做的,是在發(fā)生撤回的時(shí)候,先保持原先那條數(shù)據(jù)不被刪除,并插入一條『撤回被阻止』的信息。
好了,那么繼續(xù)分析代碼,首先要知道str變量的值是怎么來的,往上翻一下可以看到以下代碼:

很明顯我們應(yīng)當(dāng)跟蹤bf.q這個(gè)方法,看一下這個(gè)方法里做了什么:

好了,里頭邏輯做了些啥不需要管了,只需要管它的返回值,結(jié)合上面的代碼,我們很容易能知道,在這個(gè)返回的map內(nèi)包含以下數(shù)據(jù):
.sysmsg.$type = revokemsg
.sysmsg.revokemsg.session = 發(fā)送消息的人
.sysmsg.revokemsg.replacemsg = 原始消息要替換的文本(也就是『XX撤回了一條消息』)
.sysmsg.revokemsg.newmsgid = 消息ID
那么,只需要將.sysmsg.$type和.sysmsg.revokemsg.replacemsg的內(nèi)容改掉就行了,把這個(gè)過程變成以下步驟:
1. 修改 .sysmsg.$type 為 null,以使其不觸發(fā) update 數(shù)據(jù)庫(kù)的流程
2. 將 .sysmsg.revokemsg.replacemsg 的內(nèi)容改為『撤回被阻止』
3. 將被改寫過的數(shù)據(jù)寫入數(shù)據(jù)庫(kù)
下面的代碼完成了這一系列步驟:

當(dāng)然這里還有一個(gè)數(shù)據(jù)庫(kù)操作的問題,我們必須有辦法得到微信內(nèi)的數(shù)據(jù)庫(kù),然后才能進(jìn)行操作,此時(shí)需要在微信內(nèi)找到數(shù)據(jù)庫(kù)相關(guān)的類,還需要知道庫(kù)的結(jié)構(gòu),當(dāng)然庫(kù)結(jié)構(gòu)是非常容易得到的。具體如何查找的不再贅述,直接看代碼:

這樣就可以得到一個(gè)數(shù)據(jù)庫(kù)對(duì)象,凡是遇到數(shù)據(jù)庫(kù)操作,都可以從這個(gè)對(duì)象里進(jìn)行方法的調(diào)用。
到此為止,微信的防撤回就基本上完成了,再補(bǔ)上一些基礎(chǔ)代碼,掛到 Xposed 框架就可以成功運(yùn)行。
新的防撤回已完成并且已開源,請(qǐng)大家移步至我的 Github,歡迎關(guān)注這個(gè)項(xiàng)目,我將持續(xù)更新。覺得有用的話,給個(gè) Star 怎么樣?