Exp10 Final 微信防撤回原理與實現

1、寫在前面java

1.爲何作免考?服務器

相較於考試,免考更能鍛鍊自身創新和探索能力,更有挑戰性。微信

2.選作微信推送防撤回緣由?session

  • 微信已經成爲平常溝通中必不可少的工具,如何知作別人在你沒看微信的狀況下偷偷說了什麼就變得很重要(嘿嘿嘿)
  • CTF我只研究過雜項、密碼學和逆向,別的部分我也不擅長因此就不作了。

2、寫在中間ide

1.什麼是防撤回?函數

  • 指對方發出撤回請求,系統應答後,對方微信顯示成功撤回,而我方微信顯示對方撤回提示但消息依然顯示在界面。

2.實驗環境工具

  • 實驗對象:wechatwin.dll (PC 2.6.7.57版本)
  • 實驗工具:
    • IDA 6.6(7.0也行,好像6.6已經下不到了,反正版本不影響)
    • windbg(Windows應用商店裏有)
    • VC2017(十二、15版不知道行不行)

3.撤回原理編碼

  • 撤回邏輯:
    • 對方在一個終端上發起撤回請求,服務端收到請求,下發命令給我方終端
    • 我方終端收到了服務端發來的撤回消息命令
    • 我方終端執行撤回消息指令
  • 撤回實現:
    • 我方終端依舊響應服務器發來的撤回消息指令
    • 我方終端執行撤回消息提醒,但不撤回消息內容

4.撤回代碼逆向分析spa

(1)將微信核心模塊放入IDA,搜索一下撤回有關的命令3d

(2)分析一哈,挺多的,但基本上邏輯順序與2、3的一致,那就動態調試找一下哪一條是服務器下的命令,很簡單就能發現是 On RevokeMsg svrId : %d ,那就好辦了 F5 一下

(3)再分析一哈,v191就應該是服務器下的命令,對應編號應該爲10002(10000+2),而後查看一下這段程序調用的函數彙編,首先是  sub_10483FE0 函數

  • 先看看如何調用
1 #對sub_10483FE0的彙編調用
2 sub     esp, 14h              
3 mov     ecx, esp;                
4 push    0
5 push    dword ptr [eax+4]
6 call    sub_10483FE0
  • 再看看函數都調用了什麼
 1 #sub_10483FE0函數的彙編
 2 push    ebp
 3 mov     ebp, esp
 4 sub     esp, 8
 5 push    esi
 6 mov     esi, ecx
 7 mov     ecx, [ebp+arg_0]
 8 push    edi
 9 mov     dword ptr [esi], 0
10 mov     dword ptr [esi+4], 0
11 mov     dword ptr [esi+8], 0
12 mov     dword ptr [esi+0Ch], 0
13 mov     dword ptr [esi+10h], 0
  • 先分析  sub_10483FE0  函數,左面就是彙編語言各類操做命令,右邊是操做對象。從第9行開始就出現了dword ,這裏是對註冊表鍵值的處理嗎?再看看後面的4和8,應該就是對字符串編碼進行操做。而後搜索了一下(問百度),在Windows開發人員中內心發現了MultiByteToWideChar 功能,具體介紹以下:

  • 搞了半天,原來 sub_10483FE0 這個類功能就是對寬字符進行操做,相似於C++裏的wstring操做,應該是考慮到消息的編碼方式應該是Unicode編碼,再結合對 sub_10483FE0  函數的調用匯編代碼,能夠看出 ecx 完成的是 wstring 操做, dword ptr [eax+4] 完成的是java new String(XXX, UTF-8) 操做
  •  雖然知道了函數是幹啥的,但也不知道具體實現過程,因此使用動態調試,將斷點設在call sub_10483FE0上, 查看此時的ecx的值
1 0:000:x86> dd 00efcb00-14
2 00efcb0c  13f0e7f0 000000d6 00000100 00000000
  • 繼續運行,當調用結束後查看ecx 以後都幹了啥
1 0:000:x86> du 13f0e7f0 
2 13f0e7f0  "<sysmsg type="revokemsg"><revoke"
3 13f0e830  "msg><session>wxid_xxxxxxxxxxxxx"
4 13f0e870  "</session><msgid>18778893426</msg"
5 13f0e8b0  "id><newmsgid>5379365542789842691"
6 13f0e8f0  "</newmsgid><replacemsg><![CDATA["
7 13f0e930  ""不知名網友" 撤回了一條消息]]></replacemsg"
8 13f0e970  "></revokemsg></sysmsg>"

(4)到這裏就顯而易見了,出現了 <replacemsg> ,這不就是咱們所想改的地方嗎!!跟以前找撤回命令同樣,找一下關於 replacemsg 在哪裏,實際上也不用那麼找,剛纔執行完 sub_10483FE0 那一部分以後看看後面調用了啥就行,上面那個不是,那就是下面這個。

      

  • 挺好的,要是搜索的話也是sub_10257570 是惟一一個處理replacemsg的函數,仔細看看發現sub_10257570 被sub_10252F80 調用 

  • 而後一步一步往下找,真的好麻煩(過程就省略一點),真的追吐血了(有時間的話大家能夠追追看)

 

  • 最後發現sub_10253250 函數,是整個處理replacemsg部分的實現函數

  • 感受離事實的真相更進一步了,查看了一下 sub_10253250  函數內部邏輯,發現有一處判斷語句

  • 分別給v69賦值0和1,發現當爲1時,有提示語而且消息沒了,可是爲0時,提示語也有,可是消息還在,聽到這裏開不開心?

(5)如何讓消息不撤回到這裏已經很清楚了,只須要在這裏給他按個補丁,一直讓他在else裏走就好,但這裏會有一個問題出現,你的微信上別人沒法撤回消息,你的消息你也撤回不了,豈不是有點尷尬,那就要找一找微信是怎麼區分本身發的撤回指令和其餘人發的指令的函數。

  • 到這裏我就有點蒙了,sub_10253250 後面有好多,根本就不知道哪裏是,直到看到了10000,是個熟悉的數字(10002爲消息撤回參數)
1 if   ( v50 == 10000 )
2   goto LABEL_46; 
  • 也就是說在這以前就完成了消息撤回的步驟,再往上找,發現sub_1025A390 函數,在其附近的代碼段找到兩句調用函數
1 sub_1004E320((int)&v46);
2 ...
3 ...
4 ...
5 v11 =  sub_1025A390 ( xmm0_0, v10, a3, a4, (int)&v46);
  • 前一句是初始化v46(後來才知道這個變量是結構體變量),後一句是對v46的具體操做,那就要動態調試一下,看看兩種撤回狀況對v46變量的影響
1 0:013> g
2 *** WARNING: Stack unwind information not available.  
3 #別人撤回時
4 012fc2e0  00000001 00000000 00000002 4cdf683f
5 #本身撤回時
6 012fc2e0  00000001 00000001 00000002 4cdf689f
  • 顯而易見,微信經過這兩個數據差別來判斷撤回的主體是誰,但也引出一個問題,當你本身撤回和別人撤回時會出現兩種提示
  • 那麼v46這個變量必定關聯着兩個函數或者一條判斷語句,那就繼續看sub_10253250 函數的後半部分,發現

  • 再去觀察 sub_102541D0 函數,能夠看出sub_102541D0 -> sub_102542A0的調用關係

  • 再去看 sub_102542A0 函數,發現當變量爲1時,就能夠觸發從新編輯功能

(6)到這裏全部撤回流程就很清楚了,當本身撤回時,就按照正常指令進行操做,當他人撤銷時,將消息撤回置位else,不讓他進入if(true)就能夠實現防撤回的功能了。

 3、寫在後面

1.防撤回實現

(1)生成彙編語言代碼,做爲補丁,放入wechatwin.dll所在的文件夾重啓微信

(2)實現:

(3)彩蛋:撤回消息提醒是否是變了,原理全在 sub_102542A0 函數,能夠本身試試。。。。嘿嘿嘿

2.感覺:

逆向是真的麻煩,搞了半天補丁製做(藉助了部分大佬的代碼),才弄出來,結果寫博客的時候微信升級了,雖然看了一下邏輯基本沒變,可是地址都變了,f**k,不想再作一遍補丁了,雖然這個功能挺好用的,可是須要電腦客戶端一直掛着微信就很麻煩,應該改進一下把撤回的消息都發給文件助手就會方便不少(網上有個大佬作過之前版本的),作到一半的時候,都想換題作個什麼CTF雜項專題來着,幸虧仍是一點點堅持下來了,努力也沒算白費(版本一換就不行o(╥﹏╥)o),終於不用寫博客了(*^▽^*)。

相關文章
相關標籤/搜索