倪雪莉,梁廣俊
1.江蘇警官學(xué)院 計(jì)算機(jī)信息與網(wǎng)絡(luò)安全系,南京 210031
2.江蘇省電子數(shù)據(jù)取證分析工程研究中心,南京 210031
3.江蘇省公安廳 數(shù)字取證重點(diǎn)實(shí)驗(yàn)室,南京 210031
根據(jù)微信團(tuán)隊(duì)發(fā)布的《2019年微信數(shù)據(jù)報(bào)告》統(tǒng)計(jì),2019年微信平均月活躍賬戶數(shù)達(dá)到11.5億,位居新型即時(shí)通信平臺(tái)的首位[1]。作為一種廣受用戶青睞的網(wǎng)絡(luò)傳媒工具,微信整合了電子郵件、網(wǎng)上聊天、博客、網(wǎng)上購物、網(wǎng)絡(luò)支付等眾多通信功能,其功能越來越豐富,應(yīng)用范圍越來越廣泛。與此同時(shí),從信息安全的角度考慮,尤其針對(duì)電子數(shù)據(jù)取證,微信無疑成為一個(gè)龐大的證據(jù)庫[2]。2019年12月26日,《最高人民法院關(guān)于修改<關(guān)于民事訴訟證據(jù)的若干規(guī)定>的決定》頒布并從2020年5月1日起生效,標(biāo)志著國家最高審判機(jī)關(guān)正式在司法解釋中確認(rèn)了微信微博聊天記錄的證據(jù)位,微信聊天記錄等信息在訴訟中作為證據(jù)出現(xiàn)的頻率將會(huì)越來越高。
相對(duì)于傳統(tǒng)形式的證據(jù),微信聊天記錄作為一種電子數(shù)據(jù)要想具有相應(yīng)的證明效力,成為認(rèn)定案件事實(shí)的依據(jù),必須滿足真實(shí)性、合法性和關(guān)聯(lián)性等基本要求[3]。微信自2014年發(fā)布的v5.3.1版本開始,便推出了消息撤回功能,用戶可以選擇撤回在2分鐘內(nèi)發(fā)送的消息,該特征在方便了用戶的同時(shí),卻降低了微信證據(jù)內(nèi)容的完整性,在訴訟中可能難以達(dá)到證據(jù)真實(shí)性的要求[4]。
近年來,研究人員開始從存儲(chǔ)介質(zhì)、事件日志、文件系統(tǒng)、數(shù)據(jù)庫等方向著手研究微信消息的恢復(fù)方法。文獻(xiàn)[5]提出了一種基于SQLite3文件格式的刪除數(shù)據(jù)恢復(fù)方法,通過識(shí)別SQLite3文件格式,收集數(shù)據(jù)頁中的自由塊和未使用空間,最后選擇不同類別的恢復(fù)算法實(shí)現(xiàn)了刪除數(shù)據(jù)的恢復(fù);文獻(xiàn)[6]通過獲取Android手機(jī)中的數(shù)據(jù)庫文件和解密密鑰,在SQLite數(shù)據(jù)庫環(huán)境中提取出用戶的微信信息,其中包括聊天記錄、聯(lián)系人列表等,但該方法無法還原被刪除的聊天記錄;文獻(xiàn)[7]提出了一種基于KNN(K-Nearest Neighbor)算法的Android微信取證方法,該方法引入詞語相似度計(jì)算會(huì)話間的距離,將會(huì)話表示成特征詞的向量,用KNN算法對(duì)會(huì)話進(jìn)行分類,迅速找到有關(guān)的聊天內(nèi)容,但同樣無法找到被刪除或撤回的消息記錄;文獻(xiàn)[8]通過逆向分析技術(shù)研究,獲知了微信等熱門應(yīng)用的密鑰生成算法以期破解加密的SQLite數(shù)據(jù)庫;類似的,文獻(xiàn)[9]分析了微信數(shù)據(jù)庫的加密算法和密鑰推導(dǎo)原理,并給出了不同取證環(huán)境下的數(shù)據(jù)庫解密過程,最終實(shí)現(xiàn)了語音和刪除消息的恢復(fù);文獻(xiàn)[10]對(duì)微信內(nèi)存文件中的特征變化進(jìn)行分析,在一定程度上能夠通過特征值盲搜恢復(fù)部分文字、表情類消息,但并未對(duì)撤回消息的存儲(chǔ)原理進(jìn)行研究,同時(shí),該研究成果只適用于文本類消息,未實(shí)現(xiàn)圖片類消息的恢復(fù)。
傳統(tǒng)的移動(dòng)智能終端即時(shí)通信應(yīng)用的取證研究主要集中在取證流程和基礎(chǔ)數(shù)據(jù)的提取上,這類取證分析存在流程規(guī)范不嚴(yán)謹(jǐn)、提取數(shù)據(jù)不完整等問題[11]。在微信取證技術(shù)的研究中,基于本地微信數(shù)據(jù)庫的研究占據(jù)了主流,而對(duì)微信運(yùn)行過程中動(dòng)態(tài)內(nèi)存的研究成果較少[12]。對(duì)于微信聊天記錄恢復(fù)的研究,目前的討論也大多集中在如何盡可能多地恢復(fù)被刪除的記錄,而對(duì)于被撤回消息恢復(fù)的理論研究和技術(shù)實(shí)踐,目前尚未形成完善的體系。在針對(duì)微信平臺(tái)的取證實(shí)踐過程中,僅通過本地微信數(shù)據(jù)庫恢復(fù)方法提取到的聊天記錄往往是不完整的,其中并不包含用戶的撤回消息,這顯然無法滿足訴訟中對(duì)于證據(jù)完整性、真實(shí)性的要求。
經(jīng)研究發(fā)現(xiàn),內(nèi)存中存在大量的緩存應(yīng)用數(shù)據(jù),這些數(shù)據(jù)具有極大的取證價(jià)值[13]。通過實(shí)踐發(fā)現(xiàn)用戶的撤回消息在微信內(nèi)存中有跡可循。因此,本文通過對(duì)微信內(nèi)存的獲取和分析技術(shù)展開研究,基于PC版微信撤回消息在動(dòng)態(tài)內(nèi)存中的存儲(chǔ)原理,提出了一種針對(duì)微信文本、表情、圖片等多種類型撤回消息進(jìn)行恢復(fù)的方法,并通過Python語言開發(fā)的工具,驗(yàn)證了該方法的有效性和可行性。同時(shí),該工具可直接應(yīng)用于微信取證場(chǎng)景。
內(nèi)存分析在數(shù)字取證分析中扮演著越來越重要的角色,可以用來檢索加密密鑰或分析僅駐留在RAM中的惡意軟件。一般情況下,在分析之前需要獲取內(nèi)存中的信息[14]。
針對(duì)微信內(nèi)存鏡像數(shù)據(jù)提取,目前通用的方法主要有兩類:一是使用ProcDump工具提取,二是使用Windows操作系統(tǒng)自帶的管理工具提取。將兩種工具提取到的鏡像文件進(jìn)行對(duì)比分析,以確保提取到完整的動(dòng)態(tài)內(nèi)存文件。
ProcDump是一個(gè)輕量級(jí)的命令行工具,可以嵌入到其他腳本中進(jìn)行進(jìn)程內(nèi)存鏡像的轉(zhuǎn)儲(chǔ)。使用該工具通過微信的進(jìn)程號(hào)對(duì)微信進(jìn)程進(jìn)行轉(zhuǎn)儲(chǔ),具體實(shí)現(xiàn)步驟如下:
(1)在命令提示符界面中輸入“tasklist”命令,找到微信應(yīng)用的PID(Process ID,進(jìn)程ID號(hào)),如圖1所示。
圖1 微信進(jìn)程號(hào)Fig.1 PID of WeChat
(2)使用ProcDump的“-ma”參數(shù),創(chuàng)建一個(gè)進(jìn)程的轉(zhuǎn)儲(chǔ)文件,包括該進(jìn)程所有線程以及句柄等信息,如圖2所示,此時(shí)ProcDump程序已經(jīng)為微信創(chuàng)建了內(nèi)存文件,存儲(chǔ)在D盤Procdump目錄下。
圖2 微信內(nèi)存轉(zhuǎn)儲(chǔ)文件Fig.2 Memory dump of WeChat
Windows 10操作系統(tǒng)中自帶的任務(wù)管理器也提供了轉(zhuǎn)儲(chǔ)程序內(nèi)存、生成鏡像文件的功能,其轉(zhuǎn)儲(chǔ)微信內(nèi)存步驟如下:
(1)打開任務(wù)管理器并轉(zhuǎn)到詳細(xì)信息,選中需要轉(zhuǎn)儲(chǔ)的應(yīng)用,右擊創(chuàng)建微信內(nèi)存轉(zhuǎn)儲(chǔ)文件。
(2)轉(zhuǎn)儲(chǔ)完成后微信內(nèi)存文件的默認(rèn)存放地址為C:Users[Administrator]AppDataLocalTemp,其中[Administrator]字段為當(dāng)前計(jì)算機(jī)用戶名,該文件的名稱為WeChat.DMP。
將分別用ProcDump和Windows自帶工具提取到的文件進(jìn)行對(duì)比,發(fā)現(xiàn)利用Windows任務(wù)管理器創(chuàng)建的內(nèi)存鏡像比ProcDump創(chuàng)建的鏡像文件略大一些,分別如圖3(a)和(b)所示。究其原因,內(nèi)存提取所使用的Windows操作系統(tǒng)為64位,該系統(tǒng)自帶的任務(wù)管理器創(chuàng)建的轉(zhuǎn)儲(chǔ)文件也是64位,其中包含了WoW64子系統(tǒng)的信息。但是,ProcDump工具創(chuàng)建的內(nèi)存轉(zhuǎn)儲(chǔ)文件默認(rèn)為32位,不包含WoW64子系統(tǒng)的信息。而PC版微信是一個(gè)32位程序,在用兩種方式創(chuàng)建內(nèi)存轉(zhuǎn)儲(chǔ)文件時(shí)會(huì)產(chǎn)生差異,因而任務(wù)管理器創(chuàng)建的包含WoW64子系統(tǒng)信息的內(nèi)存轉(zhuǎn)儲(chǔ)文件比ProcDump創(chuàng)建的不包含WoW64子系統(tǒng)信息的內(nèi)存轉(zhuǎn)儲(chǔ)文件略大一些。
圖3 三個(gè)鏡像文件對(duì)比Fig.3 Comparison of three image files
使用ProcDump的“-64”參數(shù)再創(chuàng)建一個(gè)轉(zhuǎn)儲(chǔ)文件,如圖3(c)所示,該文件為微信64位的轉(zhuǎn)儲(chǔ)文件。圖3(a)和(c)對(duì)比略有差異,主要是因?yàn)閯?chuàng)建轉(zhuǎn)儲(chǔ)文件的時(shí)間不同而致,由于內(nèi)存的變化非常快,細(xì)小的時(shí)間差異產(chǎn)生的內(nèi)存轉(zhuǎn)儲(chǔ)可能包含不一致的數(shù)據(jù),如果同時(shí)創(chuàng)建,兩個(gè)文件之間將不會(huì)存在差異[15]。
因此可見,文獻(xiàn)[10]直接通過ProcDump得到的微信內(nèi)存鏡像文件并不完整,會(huì)對(duì)后續(xù)內(nèi)存的分析和消息的恢復(fù)產(chǎn)生影響,本文對(duì)采用ProcDump創(chuàng)建的微信64位內(nèi)存鏡像文件進(jìn)行分析。
不同應(yīng)用程序的數(shù)據(jù)具有異構(gòu)性,但在內(nèi)存中以一種通用的與應(yīng)用程序無關(guān)的方式表示,因此可以跨各種應(yīng)用程序?qū)?nèi)存鏡像進(jìn)行通用分析[16]。使用WinHex十六進(jìn)制編輯器打開上述DMP內(nèi)存鏡像文件,查看其16進(jìn)制數(shù)據(jù),具體如圖4所示。其中,文件頭為MDMP,對(duì)應(yīng)的十六進(jìn)制值為“4D 44 4D 50”。
圖4 內(nèi)存鏡像十六進(jìn)制數(shù)據(jù)Fig.4 Hexadecimal content of image file
在微信安裝目錄下有一個(gè)動(dòng)態(tài)鏈接庫文件WeChat-Win.dll,其中包含了消息撤回的函數(shù),用于執(zhí)行用戶相關(guān)的撤回操作,撤回函數(shù)相關(guān)的關(guān)鍵詞為“revokemsg”,如圖5所示。
圖5 “revokemsg”關(guān)鍵詞Fig.5 Keyword“revokemsg”
因此,在微信的內(nèi)存鏡像文件中,撤回消息的特征字符為“revokemsg”,也就是說,每一段撤回消息在內(nèi)存中的位置都與一對(duì)特征字符標(biāo)簽“<revokemsg>”“</revokemsg>”相關(guān),如圖6所示。
圖6 特征字符在內(nèi)存中的體現(xiàn)Fig.6 Representation of characters in memory
撤回消息在內(nèi)存中的具體字段結(jié)構(gòu)如圖7所示,分為消息頭與消息體。其中消息頭中存放該條撤回消息的一些屬性信息,如,消息的撤回方、ID、撤回狀態(tài)等,消息體中則直接存放該消息的內(nèi)容。
圖7 撤回消息字段結(jié)構(gòu)Fig.7 Field structure of revoking message
每段撤回消息都伴隨<revokemsg>和</revokemsg>標(biāo)簽對(duì)出現(xiàn),該標(biāo)簽對(duì)中間內(nèi)容為消息撤回后用戶的聊天窗口顯示的提示消息。若為本用戶撤回,則內(nèi)容為:“<![CDATA[你撤回了一條消息<a href=“weixin://revoke_edit_click”>重新編輯</a>]]>”,其中“重新編輯”是一條指向性的鏈接,給本用戶提供重新編輯撤回消息的接口。若消息為聊天對(duì)方用戶撤回,則內(nèi)容為:“"xxx(微信昵稱)"撤回了一條消息”。因此,可以根據(jù)該字段內(nèi)容的不同形式判斷該消息是由本用戶撤回還是他人撤回,尤其在微信群中,能直接定位群中的某個(gè)成員(昵稱),如圖8所示。
圖8 revokemsg標(biāo)簽對(duì)間的消息解析Fig.8 Message parsing between revokemsg tag pairs
在<revokemsg>標(biāo)簽之前的字段為通信對(duì)方的微信ID或所在微信群的群ID,個(gè)人微信ID以字符“wxid”為開始標(biāo)志,而微信群ID以字符“@chatroom”為結(jié)束標(biāo)志,通常這個(gè)ID占18~20位。通過該字段的解析,能夠獲知該撤回消息屬于哪個(gè)聊天對(duì)話窗口。
若為微信群,在</revokemsg>標(biāo)簽之后依次為消息撤回者的微信ID,及群屬性信息,如該群中設(shè)置消息屏蔽的人數(shù)、該群的總?cè)藬?shù)等。若為聊天個(gè)人,在</revokemsg>標(biāo)簽之后直接為一段固定的32位Hash密文的字符串。其中對(duì)于消息撤回者微信ID的解析尤為重要,能準(zhǔn)確定位到該群中的某個(gè)成員(較之昵稱ID辨識(shí)性更高、更準(zhǔn)確)。
值得注意的是,在微信內(nèi)存中以字符“1A”為分隔符(見圖9),分隔撤回消息的各字段,“1A”后一個(gè)字節(jié)表示該字段的總長(zhǎng)度,單位為字節(jié)。其后為該字段含義的標(biāo)志位,具體含義如表1所示,字段標(biāo)志位后一個(gè)字節(jié)表示該字段內(nèi)容的長(zhǎng)度,單位為字節(jié)。由此,可得知每個(gè)字段的開始結(jié)束位置,如“08 04 12”標(biāo)志后即為撤回消息的長(zhǎng)度及內(nèi)容。
圖9 分隔符及標(biāo)志位Fig.9 Separators and flag bits
表1 字段標(biāo)志位含義Table 1 Meanings of flag bits
微信聊天記錄主要包含的消息類型有:文本、表情、圖片等,而不同類型的撤回消息,在內(nèi)存中的體現(xiàn)形式不一。
2.3.1 文本消息
對(duì)于文本類消息,微信在通信過程中使用UTF-8的編碼方式編碼文本字符。如圖10中劃線的十六進(jìn)制字符:“E4 BA BA E7 94 9F E5 AE 9E E5 A6 82 E9 92 9F E6 91 86 EF BC 8C E5 9C A8 E7 97 9B E8 8B A6 E4 B8 8E E5 80 A6 E6 80 A0 E4 B9 8B E9 97 B4 E6 91 86 E5 8A A8 E3 80 82”,通過UTF-8解碼得到中文字符“人生實(shí)如鐘擺,在痛苦與倦怠之間擺動(dòng)?!保鐖D11所示。
圖10 撤回的中文字符在內(nèi)存中的體現(xiàn)形式Fig.10 Representation of Chinese revoking message in memory
圖11 撤回消息的UTF-8解碼Fig.11 UTF-8 of revoking message
2.3.2 表情消息
對(duì)于表情類消息,微信將資源內(nèi)部的表情轉(zhuǎn)換為文本進(jìn)行存儲(chǔ),轉(zhuǎn)換形式為文本“[表情名字]”,如“[奸笑]”,再將此文本以UTF-8的編碼方式編碼。如圖12所示,十六進(jìn)制表情消息內(nèi)容經(jīng)過UTF-8解碼后為“[奸笑][奸笑][奸笑]”,即為表情消息。
圖12 撤回的表情消息在內(nèi)存中的體現(xiàn)形式Fig.12 Representation of revoking emojis in memory
2.3.3 圖片消息
對(duì)于圖片類消息,與文本和表情類消息的存儲(chǔ)方式完全不同,圖片消息一經(jīng)發(fā)送即以DAT數(shù)據(jù)文件形式存放在計(jì)算機(jī)本地文件中,而在內(nèi)存相應(yīng)字段位置僅僅存放著指向該本地文件的路徑,如圖13。
圖13 撤回的圖片消息在內(nèi)存中的體現(xiàn)形式Fig.13 Representation of revoking pictures in memory
因此,根據(jù)內(nèi)存相應(yīng)字段中的路徑找到該圖片的DAT數(shù)據(jù)文件即可。經(jīng)研究分析發(fā)現(xiàn),微信在通信過程中對(duì)接收到的圖片文件按字節(jié)進(jìn)行了異或加密處理,然后保存為DAT文件。異或加密算法是密碼學(xué)中一種簡(jiǎn)單的對(duì)稱加密算法,當(dāng)需要進(jìn)行解密時(shí),只需將加密后的結(jié)果與密鑰再次進(jìn)行異或運(yùn)算即可,加解密過程如公式(1)所示:
其中,M為原文,K密鑰,E為密文。
每一個(gè)微信賬號(hào)對(duì)應(yīng)的密鑰不同,可以嘗試通過已知明文攻擊來獲得密鑰。具體方法為:將明文JPEG圖片的文件頭“FF D8”與加密后的DAT文件(如圖14)的前兩字節(jié)“B6 91”,通過按位異或操作得到兩個(gè)字節(jié)“4949”,由此可以判斷出該DAT文件是使用字節(jié)“49”作為密鑰進(jìn)行圖片加密處理的,此后該微信賬號(hào)下所有的撤回圖片消息的DAT文件,都可使用該密鑰進(jìn)行解密。
圖14 密文DAT文件的部分?jǐn)?shù)據(jù)Fig.14 Part of ciphertext of DAT file
經(jīng)研究發(fā)現(xiàn),該內(nèi)存字段中指向的路徑中存放的為圖片的縮略圖,完整的圖片數(shù)據(jù)存儲(chǔ)位置和撤回機(jī)制對(duì)發(fā)送方與接收方來說略有不同。
作為發(fā)送方,會(huì)在本地的WeChat Files[wxid]FileStorageImage[date]和WeChat Files[wxid]FileStorageImageThumb[date]文件夾下(其中[wxid]是以用戶微信ID命名的文件夾,[date]是以日期命名的一個(gè)文件夾)各產(chǎn)生一個(gè)DAT文件,經(jīng)過字節(jié)異或操作,前者會(huì)恢復(fù)為發(fā)送的原圖,后者為縮略圖。當(dāng)用戶在聊天框中點(diǎn)開這張圖片時(shí),會(huì)在WeChat Files[wxid]FileStorageTemp臨時(shí)文件夾下生成一個(gè)DAT文件,而當(dāng)用戶點(diǎn)開下一張圖片時(shí),該臨時(shí)文件下的DAT文件會(huì)被圖片文件覆蓋。當(dāng)用戶發(fā)起撤回操作時(shí),三個(gè)文件夾下產(chǎn)生的文件均無變化。
作為接收方,圖片的存儲(chǔ)方式與上述相同,但當(dāng)對(duì)方用戶發(fā)起撤回操作時(shí),WeChat Files[wxid]FileStorageImage[date]和WeChat Files[wxid]FileStorageImageThumb[date]文件夾下的DAT文件會(huì)消失,而WeChat Files[wxid]FileStorageTemp文件下產(chǎn)生的DAT文件無變化。
根據(jù)微信撤回消息數(shù)據(jù)的存儲(chǔ)和恢復(fù)原理,本文提出了一種基于動(dòng)態(tài)內(nèi)存結(jié)構(gòu)分析的撤回消息恢復(fù)方法,其恢復(fù)流程為(如圖15所示):
(1)遍歷內(nèi)存鏡像文件數(shù)據(jù),提取所有特征碼<revokemsg>的索引值,每出現(xiàn)一次特征碼<revokemsg>則表示出現(xiàn)了一條撤回消息,提取該特征碼后的各字段標(biāo)志位的索引值,如標(biāo)志位“08 04 12”的索引值為lenghIndex,后面的內(nèi)容為撤回消息的長(zhǎng)度及撤回消息。
(2)定位<revokemsg>之前的內(nèi)容,即為通信對(duì)方的微信ID或所在微信群的群ID,提取該ID。
(3)讀取<revokemsg>和</revokemsg>標(biāo)簽之間的內(nèi)容,即為用戶聊天面板上的提示消息。解碼該消息,形式為“<![CDATA[你撤回了一條消息<a href="weixin://revoke_edit_click">重新編輯</a>]]>”或“"xxx"撤回了一條消息”,根據(jù)該消息形式來判斷該條消息是由本用戶撤回還是對(duì)方用戶撤回。
(4)標(biāo)志位“08 04 12”后面的一個(gè)字節(jié)為撤回消息的長(zhǎng)度,單位為字節(jié),計(jì)算每條撤回消息的長(zhǎng)度length-Message。
圖15 撤回消息的恢復(fù)流程圖Fig.15 Flow chart of recovery of revoking message
(5)根據(jù)標(biāo)志位“08 04 12”的索引值lengthIndex及消息長(zhǎng)度lengthMessage計(jì)算消息的結(jié)束位置message-End,如公式(2)。將提取到的原消息字符段進(jìn)行UTF-8解碼操作即得到原消息內(nèi)容。
(6)判斷得到的該原消息字符串表示的是否為路徑,若為路徑,則表示該條撤回消息為圖片,打開該路徑指向的本地文件。
(7)將該本地DAT數(shù)據(jù)文件的前兩個(gè)字節(jié)分別與“FF D8”進(jìn)行異或操作,即得到圖片加密的字節(jié)密鑰,對(duì)DAT文件的每個(gè)字節(jié)與密鑰進(jìn)行異或操作解密,最后保存為JPG文件,即為成功恢復(fù)后的圖片文件。
本章通過具體程序的實(shí)現(xiàn)來驗(yàn)證本文提出的恢復(fù)方法的可行性和有效性。由于本文的恢復(fù)方法基于微信內(nèi)存鏡像文件,而鏡像文件在所有操作系統(tǒng)上都是二進(jìn)制一致的,因此,本文提出的恢復(fù)方法與操作系統(tǒng)類型無關(guān)。
針對(duì)微信內(nèi)存鏡像的獲取以及撤回消息批量恢復(fù)的實(shí)驗(yàn)程序設(shè)計(jì),選用了Python編程語言,在集成開發(fā)環(huán)境PyCharm中完成程序的設(shè)計(jì)與調(diào)試。Python版本號(hào)為3.8.2,PyCharm的版本號(hào)為PyCharm 2019.3.3(Professional Edition),PC版微信的版本號(hào)為微信2.9.5.41。
在獲取微信內(nèi)存之前,首先進(jìn)行對(duì)話測(cè)試,其中撤回消息類型包含文字、表情及圖片,如圖16所示。
圖16 撤回消息的對(duì)話測(cè)試Fig.16 Dialogue test for revoking message
4.2.1 微信內(nèi)存鏡像獲取
微信內(nèi)存鏡像獲取首先需要獲取到當(dāng)前計(jì)算機(jī)中微信的進(jìn)程號(hào)。導(dǎo)入psutil模塊,使用其中的pids方法獲取到當(dāng)前所有進(jìn)程的進(jìn)程號(hào),結(jié)合微信的進(jìn)程名稱“WeChat.exe”進(jìn)行判斷,獲取微信的進(jìn)程號(hào)。
使用Python3的subprocess模塊中的call方法,調(diào)用外部的ProcDump可執(zhí)行程序,對(duì)微信運(yùn)行內(nèi)存進(jìn)行轉(zhuǎn)儲(chǔ)。
4.2.2 提取所有的特征碼索引值
根據(jù)圖7撤回消息的字段結(jié)構(gòu),先獲?。紃evokemsg>標(biāo)簽在內(nèi)存文件中的索引值,再根據(jù)<revokemsg>標(biāo)簽之前出現(xiàn)的微信ID以及<revokemsg>標(biāo)簽之后出現(xiàn)的</revokemsg>標(biāo)簽進(jìn)行特征結(jié)構(gòu)篩選,從而獲取到微信內(nèi)存文件中所有撤回消息特征字段的索引值。借助Python中提供的find方法,通過循環(huán)的方式(即每次找到特定字符串在原字符串中第一次出現(xiàn)的索引值,然后將索引下標(biāo)進(jìn)行加一操作,進(jìn)入下一輪索引,直至索引下標(biāo)到達(dá)原字符串中最后一個(gè)字符)找到特定字符串在原字符串中所有的索引值。
4.2.3 提取并解碼撤回消息字段
每段撤回消息的內(nèi)容前會(huì)出現(xiàn)唯一字段標(biāo)志位“08 04 12”,根據(jù)特征結(jié)構(gòu)中是否出現(xiàn)了標(biāo)志位“08 04 12”對(duì)特征結(jié)構(gòu)進(jìn)行二次判斷,如果其中沒有出現(xiàn)標(biāo)志位,則此特征結(jié)構(gòu)不符合撤回文字和表情消息恢復(fù)條件。
在特征結(jié)構(gòu)中如果出現(xiàn)了標(biāo)志位“08 04 12”,則根據(jù)其后的一個(gè)字節(jié)獲取撤回消息在內(nèi)存中的長(zhǎng)度,利用公式(2)提取出該消息。使用utf-8編碼的解碼方式對(duì)提取到的撤回消息字段進(jìn)行解碼處理,從而得到原始的撤回消息。
4.2.4 讀取消息的撤回狀態(tài)等信息
類似地,可以獲得微信ID、微信群ID、微信群屬性等。如可以找到<revokemsg>和</revokemsg>標(biāo)簽之間的內(nèi)容,定義flagMessage列表,存放消息撤回的提示字符,由此可以判斷該消息是由發(fā)送方撤回還是接收方撤回,最后返回一個(gè)由提示字符值組成列表。
4.2.5 解密加密圖片密鑰并恢復(fù)圖片數(shù)據(jù)
若撤回消息為圖片,讀取該路徑指向的本地DAT數(shù)據(jù)文件,將DAT文件的前兩字節(jié)與圖片頭特征字節(jié)進(jìn)行異或操作,得到加密的密鑰字節(jié),并對(duì)DAT文件全部字節(jié)用密鑰進(jìn)行異或操作解密,最后保存為JPG文件。
上述實(shí)驗(yàn)程序的測(cè)試恢復(fù)結(jié)果如圖17所示,可以得到完整的撤回消息,并可以得到發(fā)起消息撤回的用戶微信ID等信息。
圖17 程序運(yùn)行結(jié)果Fig.17 Running result of program
經(jīng)過多次實(shí)驗(yàn)發(fā)現(xiàn),內(nèi)存中雖然沒有記錄每條撤回消息的時(shí)間,但按照撤回時(shí)間的先后,內(nèi)存中的數(shù)據(jù)按地址偏移量依次遞增分布。成功恢復(fù)撤回消息后,根據(jù)撤回方信息(如微信(群)ID、昵稱等),將撤回消息與微信聊天窗口中的聊天記錄消息作順序比對(duì),即可獲得完整的用戶聊天記錄。
本節(jié)主要從微信撤回信息的類型(文本、表情、圖片)、撤回狀態(tài)和撤回方微信ID等多個(gè)方面,對(duì)本文方法與文獻(xiàn)[10]提出方法進(jìn)行綜合對(duì)比分析,表2、表3列出了兩種方法的性能比較。
表2 不同方法的恢復(fù)范圍比較Table 2 Comparison of recovery range between different methods
表3 文本類消息的恢復(fù)性能比較Table 3 Comparison of recovery performance for text messages
由表2可知,文獻(xiàn)[10]只能恢復(fù)文本、表情類撤回消息,而本文提出的恢復(fù)方法適用的撤回消息類型范圍更廣,恢復(fù)結(jié)果更全面。
以均能恢復(fù)的文本類消息為例,實(shí)驗(yàn)共撤回100條文本消息,綜合考慮時(shí)間對(duì)于兩種恢復(fù)方法的恢復(fù)率影響。由表3可知,在24小時(shí)內(nèi),隨著撤回時(shí)間的推移,兩種方法的恢復(fù)率均有所下降,但本文方法總體恢復(fù)率均高于文獻(xiàn)[10]。
綜上,本文提出的恢復(fù)方法在恢復(fù)范圍及恢復(fù)率方面都具有顯著優(yōu)勢(shì),這是因?yàn)楸疚木C合考慮了以下內(nèi)容:(1)考慮了撤回消息在內(nèi)存中的字段結(jié)構(gòu),由此得出消息的撤回狀態(tài)及撤回方信息。(2)考慮了微信個(gè)人聊天以及群聊的不同情況,群聊中的撤回消息在內(nèi)存中的結(jié)構(gòu)更為復(fù)雜,由此得到的內(nèi)容更為豐富。(3)考慮了圖片類消息與文本、表情類消息在內(nèi)存中的體現(xiàn)的異同:①圖片類消息在內(nèi)存中僅存放指向本地的路徑;②發(fā)送方和接收方發(fā)送、撤回的圖片消息在本地的存儲(chǔ)方式不同;③微信在通信過程中將圖片文件進(jìn)行了異或加密操作。
自2019年12月26日最高法確認(rèn)微信聊天記錄可作為法庭證據(jù)以來,法律界和取證界針對(duì)哪些聊天記錄可作電子證據(jù)、聊天記錄如何提取等方面展開了熱烈討論??梢钥闯?,今后微信微博記錄等作為電子證據(jù)出現(xiàn)在訴訟過程中的概率將會(huì)越來越高[17]。但目前提取微信通信信息的方法主要以拍照、截圖為主,電子數(shù)據(jù)檢驗(yàn)、鑒定等專業(yè)技術(shù)方法使用較少[18]。本文通過分析微信運(yùn)行的動(dòng)態(tài)內(nèi)存,研究了撤回消息在內(nèi)存中的特征字符和字段結(jié)構(gòu),根據(jù)文本、表情、圖片等類型的數(shù)據(jù)在內(nèi)存中的不同體現(xiàn)形式,提出了一種基于動(dòng)態(tài)內(nèi)存分析的PC版微信撤回消息的恢復(fù)方法。該方法除了可以恢復(fù)不同類型的撤回消息外,還可以通過分析撤回狀態(tài),獲知消息的撤回方微信ID等信息。
本文方法還存在一些不足:(1)僅僅恢復(fù)了PC版微信中被撤回的文本、表情和圖片類消息,對(duì)于移動(dòng)端的恢復(fù)尚未取得有效的研究成果;(2)微信內(nèi)存動(dòng)態(tài)變化,實(shí)際的恢復(fù)效果根據(jù)撤回的時(shí)間長(zhǎng)短存在差異。