<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          偷偷告訴你如何一臺電腦開多個微信!

          共 2928字,需瀏覽 6分鐘

           ·

          2024-04-30 16:27

          大家好,我是軒轅。

          前幾天在粉絲群里,有人問我是怎么在一臺電腦上同時登錄兩個微信的?

          正好之前寫過一篇文章,分析過原理,分享給沒看過的小伙伴學(xué)習(xí)一下。

          手機端多開微信估計很多人都知道,像華為、小米等手機系統(tǒng)都對此做了支持,不過在運行Windows系統(tǒng)的電腦上怎么啟動兩個微信呢?

          其實很簡單,你只需要寫一個批處理:

          start D:\WeChat\WeChat.exe
          start D:\WeChat\WeChat.exe

          然后直接雙擊批處理文件,就能啟動兩個微信進程。

          如果你再多加一行,甚至還能啟動3個:

          但如果你不用批處理腳本,而是一個個啟動,第二次雙擊的時候,就會直接把之前的微信窗口彈出來,根本沒法啟動第二個。

          那為什么用批處理腳本就能實現(xiàn)微信多開呢?接下來我們來進行技術(shù)分析一下。

          微信的單例模式

          正常情況下,直接手動雙擊微信圖標(biāo)啟動,后面啟動的進程會進行全局單例模式檢查,如果發(fā)現(xiàn)已經(jīng)存在微信進程,就會直接把對應(yīng)進程的微信窗口激活,定位到桌面最前面,隨后自己退出。

          但為什么用上面的方式就能啟動倆呢?我們來一探究竟。

          首先,分析一下上面描述的微信單個實例是如何實現(xiàn)的。

          做過Windows平臺應(yīng)用程序開發(fā)的朋友可能對此比較熟悉,一般是進程啟動后創(chuàng)建一個全局唯一名字的互斥體,創(chuàng)建成功則正常啟動,創(chuàng)建失敗則判斷一下是否這個互斥體已經(jīng)存在。如果已經(jīng)存在則說明已經(jīng)有對應(yīng)程序之前啟動。

          帶著這種猜想,用工具procexp查看一下微信進程打開的所有內(nèi)核對象,并找到互斥體部分:

          果然,這其中有一個名字叫_WeChat_App_Instance_Identity_Mutex_Name的互斥體,從這個名字可以猜出,這個跟微信的單例模式絕對有關(guān)系。

          接著,啟動神器APIMonitor,它可以幫你監(jiān)控指定進程的API調(diào)用情況,勾選上CreateMutexGetLastError這兩個Windows API函數(shù)。在已經(jīng)有微信在運行的情況下,用這個工具再啟動一個微信進程,看一下函數(shù)調(diào)用情況:

          可以看到,創(chuàng)建這個名字的互斥體后,隨后又調(diào)用了GetLastError函數(shù),并返回了0x000000b7,查看手冊,其含義:

          表示已經(jīng)存在。

          來看一下,這個CreateMutex調(diào)用的堆棧,看看是哪個地方的代碼在創(chuàng)建這個全局互斥體:

          從堆棧看出,調(diào)用來自于微信目錄下的一個動態(tài)庫WeChatWin.dll。具體位置在偏移0x8e271b處的前一條指令。

          接下來就要祭出神器中的神器,大名鼎鼎的反匯編軟件IDA,這家伙支持x86、x64、ARM、MIPS等多種處理器架構(gòu)和Windows、Linux、Android、MacOS、JVM等多種系統(tǒng)平臺的程序分析。

          用IDA打開這個WeChatWin.dll文件,并定位到偏移0x8e271b處:

          如上圖所示,創(chuàng)建互斥體的動作,發(fā)生在函數(shù)sub_108e26d0。

          上層是sub_108e2660函數(shù)在調(diào)用它:

          上面這張圖反映了創(chuàng)建互斥體后的判斷邏輯:

          • 如果sub_108e26d0的返回值為0,表示沒有錯誤,當(dāng)前函數(shù)也直接返回0。
          • 如果sub_108e26d0的返回值不為0,表示出現(xiàn)了錯誤,則依次判斷WeChatMainWndForPCWeChatLoginWndForPC兩個窗口是否存在,如果存在則使用BringWindowToTop函數(shù)將其置頂彈出。這兩個窗口分別代表的是微信的主界面窗口和登陸界面窗口,如果一個微信實例已經(jīng)存在,則勢必處于這兩種狀態(tài)之一。

          問題就出在上面這個判斷中,匯編代碼看起來有點辣眼睛,咱們F5來還原一下C代碼(還原效果只能湊合看,能看清楚邏輯就行):

          上面圖片的注解已經(jīng)說明了,函數(shù)sub_108e2660的返回值將決定是否啟動微信實例進程,還是直接退出。

          真相只有一個

          事情到這里就真相大白了,來總結(jié)一下。

          微信判斷是否啟動的2個條件:

          • 如果能成功創(chuàng)建互斥體對象,則啟動微信
          • 如果不能創(chuàng)建互斥體:
            • 如果找到對應(yīng)窗口,則置頂之,自己退出
            • 如果沒有找到,則啟動微信

          用偽代碼來表示一下:

          if (CreateMutex() == SUCCESS) {
            啟動微信
          else {
            if (FindWindow() == SUCCESS) {
              將已有窗口置頂
            } else {
              啟動微信
            }
          }

          而直接使用腳本啟動的多個進程,雖然操作系統(tǒng)內(nèi)核層面保證了互斥體的唯一,但由于啟動速度相差不大,相應(yīng)的窗口還沒有來得及創(chuàng)建出來,導(dǎo)致走入上面的第二個啟動邏輯,從而可以啟動多個實例。

          小發(fā)現(xiàn)

          在分析的過程中,發(fā)現(xiàn)了一個有趣的事情:

          在WeChatWin.dll中,上面的創(chuàng)建互斥體再上一級函數(shù)名字叫StartWaChat,也是作為導(dǎo)出函數(shù)被該DLL導(dǎo)出:

          這里不知道是故意還是不小心把微信的WeChat寫成了WaChat,如果是筆誤,這位程序員同學(xué)看到了趕緊偷偷去改一下吧。

          PS: 2024年,我再來看的時候,發(fā)現(xiàn)確實已經(jīng)修改好了:

          這樣看來當(dāng)初那個確實是某位程序員小哥哥手抖了~


          馬上就是五一假期了,今年五一因為天氣原因,很多小伙伴都沒有安排出游計劃。

          那不如趁著假期時間,來跟著軒轅學(xué)習(xí)逆向吧!

          我的從零開始學(xué)逆向隊伍已經(jīng)突破400+人,目前已經(jīng)更新到30課,微信群學(xué)習(xí)氛圍濃厚,沒有劃水都是干貨,距離群滿500人名額已經(jīng)不多了,歡迎想學(xué)習(xí)逆向的小伙伴抓緊機會,跟著隊伍一起學(xué)習(xí)不孤單!

          想了解關(guān)于逆向?qū)W習(xí)課程和群更詳細信息的可以點擊查看我之前發(fā)的文章:程序員賽道太卷,逆向工程師怎么樣?

          也可以直接添加我的個人微信咨詢:


          瀏覽 54
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄a免费视频在线观看 | 精品三级在线 | 伊人色色综合网 | 国产网站在线 | 尻屄视频播放 |