本發(fā)明涉及計(jì)算機(jī)取證領(lǐng)域,主要涉及對SQLite數(shù)據(jù)庫的數(shù)據(jù)恢復(fù),尤其涉及一種基于SQLite文件結(jié)構(gòu)與刪除、重組機(jī)制的數(shù)據(jù)庫恢復(fù)方法。
背景技術(shù):
根據(jù)Trend Force研究報(bào)告指出,僅2016年第三季度,智能手機(jī)的生產(chǎn)數(shù)量達(dá)到3.5億部,并保持增長趨勢。電子取證中,智能機(jī)取證十分重要,數(shù)據(jù)提取是取證工作展開的基礎(chǔ)。大量的用戶信息如短信、瀏覽記錄、通訊錄等均存儲在SQLite中,如何提取出被刪除的數(shù)據(jù)對取證工作有著重要意義。
自1983年以來,許多學(xué)者都對SQLite中被刪除數(shù)據(jù)的恢復(fù)進(jìn)行了研究?,F(xiàn)有研究主要集中在四個方面。首先,從輔助文件的角度,可以分析事務(wù)文件,WAL與索引文件。該方法可以不依賴數(shù)據(jù)庫文件,從輔助文件中提取被刪除的數(shù)據(jù)。另外,從具體應(yīng)用結(jié)合SQLite刪除機(jī)制的角度,限制在某種特定的應(yīng)用中,可詳細(xì)分析其邏輯存儲結(jié)構(gòu),可以取得比較好的恢復(fù)效率,但是這種方法嚴(yán)重依賴特定的應(yīng)用,適用范圍不廣泛。第三,從文件系統(tǒng)級別的角度,可以獲得歷史版本的數(shù)據(jù)庫文件,針對各個歷史文件進(jìn)行數(shù)據(jù)提取,甚至可以構(gòu)建用戶操作時(shí)間軸。最后,最為基礎(chǔ)的研究則是從SQLite文件結(jié)構(gòu)與存儲空間分配機(jī)制的角度,分析其二進(jìn)制結(jié)構(gòu)與刪除、重組機(jī)制,提出廣泛使用的恢復(fù)方法。
對二進(jìn)制結(jié)構(gòu)與機(jī)制分析,可以分析存儲數(shù)據(jù)的機(jī)制,直接提取數(shù)據(jù)。也可以分析空閑塊與單元的轉(zhuǎn)換原理,進(jìn)行類型估計(jì)。然而在大多數(shù)情況下,非整型主鍵的表中單元被刪除后類型的關(guān)鍵信息丟失,該信息需要被精確確定。另外隨著刪除進(jìn)行,B+tree會重新組織,導(dǎo)致可用空閑塊合并與數(shù)量減少。
因此,如何綜合考慮并解決上述問題,提出一種綜合的,高恢復(fù)率的SQLite數(shù)據(jù)恢復(fù)方案對計(jì)算機(jī)取證有重要意義。
技術(shù)實(shí)現(xiàn)要素:
本發(fā)明旨在解決以上現(xiàn)有技術(shù)的問題。提出了一種彌補(bǔ)了現(xiàn)有方法對非主鍵類型數(shù)據(jù)解析能力不足的問題,也考慮到了拆分空閑塊提高恢復(fù)率的情況,并且綜合考慮了空閑頁數(shù)量增加這一影響恢復(fù)率的現(xiàn)象、提高SQLite被刪除數(shù)據(jù)的恢復(fù)率方法。本發(fā)明的技術(shù)方案如下:
一種適用于非整型主鍵與空閑塊合并的SQLite數(shù)據(jù)恢復(fù)方法,其包括以下步驟:
步驟1:獲取欲恢復(fù)數(shù)據(jù)的SQLite文件,根據(jù)其包含的系統(tǒng)表sqlite_master確定欲恢復(fù)數(shù)據(jù)表的根頁號以及表的字段結(jié)構(gòu)信息,從根頁與文件頭出發(fā),搜集所有空閑塊與空閑頁;
步驟2、假設(shè)每個空閑塊在被刪除之前包含一條被刪除的數(shù)據(jù)庫記錄的單元分析整型主鍵與非整型主鍵的單元布局區(qū)別與每個字節(jié)的意義,計(jì)算被覆蓋的字段類型信息,解析類型信息與數(shù)據(jù)域,進(jìn)行數(shù)據(jù)恢復(fù),判斷單個空閑塊是否能恢復(fù)出有效數(shù)據(jù);
步驟3:對于不能通過步驟2恢復(fù)出有效數(shù)據(jù)的空閑塊,認(rèn)定其包含多個被刪除的單元,則基于拆分與驗(yàn)證法得出臨時(shí)空閑塊集,判斷臨時(shí)空閑塊能否恢復(fù)出有效數(shù)據(jù),若能則刪除所有兄弟臨時(shí)空閑塊,然后將數(shù)據(jù)加入恢復(fù)結(jié)果集,繼續(xù)判斷下一個臨時(shí)空閑塊;否則繼續(xù)判斷下一個臨時(shí)空閑塊,直到臨時(shí)空閑塊集合為空;
步驟4:通過空閑頁鏈表獲得空閑頁集合,遍歷每一個空閑頁,將該頁所有的存儲數(shù)據(jù)庫記錄的單元加入單元集合。對于單元集合中的每個單元,根據(jù)Type信息解析數(shù)據(jù)域獲得數(shù)據(jù),加入恢復(fù)結(jié)果集。
進(jìn)一步的,所述步驟2)對于包含一個被刪除的單元的情況的處理步驟為:對于Type被覆蓋的情況,采用基于估計(jì)與驗(yàn)證的計(jì)算被覆蓋信息值的方法。
假定每個空閑塊恰包含一個被刪除的單元,對當(dāng)前空閑塊進(jìn)行判斷,由于payloadsize,rowId與headersizes最少一共占3個字節(jié),單元轉(zhuǎn)變?yōu)榭臻e塊后前四個字節(jié)被覆蓋,因此Type域第一個字節(jié)有可能被覆蓋,分為兩種情況討論,即記錄第一個字段的類型信息的Type1被覆蓋的情況與未被覆蓋的情況,假定Type域起點(diǎn)為i,分別以第四個到最后一個字節(jié)為起點(diǎn)i,進(jìn)行判斷,若i=4,認(rèn)為Type1數(shù)據(jù)丟失,則進(jìn)行單獨(dú)判斷,若i>=5,認(rèn)為所有Type信息完整,跳轉(zhuǎn)步驟2.2;
步驟2.1、若起點(diǎn)為第四個字節(jié),令第四個字節(jié)的值從0x00到0xFF遞增,對于當(dāng)前空閑塊獲得的256個值中的每一個值對應(yīng)的狀態(tài),執(zhí)行步驟2.2-2.2.4,任意一個值對應(yīng)的狀態(tài)通過驗(yàn)證獲得被刪除的單元數(shù)據(jù),則將恢復(fù)出來的數(shù)據(jù)加入恢復(fù)結(jié)果集,終止該空閑塊判斷,繼續(xù)判斷下一個空閑塊;
步驟2.2、以i為第一個Type的起始位置,按照Type的可變長整型存儲規(guī)則,解析所有Type,并根據(jù)其值計(jì)算理論的數(shù)據(jù)長度
步驟2.3、根據(jù)步驟2.2結(jié)果,可得Type域所占字節(jié)數(shù)len(T),可得本空閑塊剩余字節(jié)數(shù)realDLen,如果readlDLen=theoryDLen,則根據(jù)Type-Data對應(yīng)關(guān)系提取數(shù)據(jù),恢復(fù)出來的數(shù)據(jù)通過驗(yàn)證后加入恢復(fù)結(jié)果集,跳轉(zhuǎn)步驟2.5,否則,執(zhí)行步驟2.4;
步驟2.4,令i=i+1,跳轉(zhuǎn)步驟2.1,若i為空閑塊最后一個字節(jié)位置,則將該空閑塊加入失敗空閑塊集,執(zhí)行步驟2.5;
步驟2.5,繼續(xù)判斷下一個空閑塊,跳轉(zhuǎn)到步驟2.1,直到當(dāng)前為最后一個空閑塊。
可以適用于任意類型的主鍵的表;基于此方法,獲得被刪除的數(shù)據(jù)。
進(jìn)一步的,所述步驟3)基于拆分與驗(yàn)證的方法進(jìn)行數(shù)據(jù)恢復(fù)失敗空閑塊集進(jìn)行的恢復(fù)操作包括步驟:
S31:首先通過循環(huán)獲得臨時(shí)空閑塊集:(1)從估計(jì)的空閑塊長度len=4開始,截取當(dāng)前失敗空閑塊,加入臨時(shí)空閑塊集。len++;(2)如果len等于當(dāng)前失敗空閑塊長度,則判斷下一個失敗空閑塊,跳轉(zhuǎn)(1),若當(dāng)前為最后一個失敗空閑塊,結(jié)束當(dāng)前循環(huán),獲得臨時(shí)空閑塊集;
S32:對每一個臨時(shí)空閑塊執(zhí)行進(jìn)行數(shù)據(jù)恢復(fù),若未獲得恢復(fù)數(shù)據(jù),繼續(xù)判斷下一個臨時(shí)空閑塊;若獲得恢復(fù)的數(shù)據(jù),則刪除該臨時(shí)空閑塊與其源自同一個失敗空閑塊的兄弟臨時(shí)空閑塊,然后將數(shù)據(jù)加入恢復(fù)結(jié)果集,繼續(xù)判斷下一個臨時(shí)空閑塊,直到臨時(shí)空閑塊為空;
本發(fā)明的優(yōu)點(diǎn)及有益效果如下:
本發(fā)明可以適用多種主鍵類型的表被刪除的情況,也適用于B+tree重組后,空閑塊合并與數(shù)量減少的情況。本方法彌補(bǔ)了現(xiàn)有方法對非主鍵類型數(shù)據(jù)解析能力不足的問題,也考慮到了拆分空閑塊提高恢復(fù)率的情況,并且綜合考慮了空閑頁數(shù)量增加這一影響恢復(fù)率的現(xiàn)象。本方法從字節(jié)級別進(jìn)行恢復(fù)驗(yàn)證,綜合考慮多種情況,可以提高SQLite被刪除數(shù)據(jù)的恢復(fù)率。
附圖說明
圖1是本發(fā)明提供優(yōu)選實(shí)施例收集空閑塊并對其未拆分狀態(tài)進(jìn)行恢復(fù)的整體流程圖。
圖2為本發(fā)明中對每個空閑塊進(jìn)行未拆分恢復(fù)的操作流程圖。
圖3為本發(fā)明中對每個空閑塊的每個起始位置i的基本恢復(fù)操作的流程圖。
圖4為本發(fā)明中對失敗空閑塊集進(jìn)行的恢復(fù)操作的流程圖。
圖5是本發(fā)明優(yōu)選實(shí)施例的流程圖。
具體實(shí)施方式
下面將結(jié)合本發(fā)明實(shí)施例中的附圖,對本發(fā)明實(shí)施例中的技術(shù)方案進(jìn)行清楚、詳細(xì)地描述。所描述的實(shí)施例僅僅是本發(fā)明的一部分實(shí)施例。
本發(fā)明解決上述技術(shù)問題的技術(shù)方案是,
針對空閑塊類型關(guān)鍵信息丟失的問題,本方法注意到,對于整型主鍵與非整型主鍵,單元的二進(jìn)制布局與每個字節(jié)的意義不同,提出了估計(jì)與驗(yàn)證相結(jié)合的數(shù)值計(jì)算方法。針對空閑塊合并與減少的情況,研究了引起B(yǎng)+tree重新組織,空閑塊合并以及空閑塊數(shù)量減少的defragment機(jī)制,提出了一種基于拆分空閑塊與空閑頁數(shù)據(jù)提取的恢復(fù)方法。
本發(fā)明建立一種適用于非整型主鍵與空閑塊合并的SQLite數(shù)據(jù)恢復(fù)方法,其方法包括以下四個實(shí)施步驟:
步驟1、從移動設(shè)備中獲取欲恢復(fù)數(shù)據(jù)的SQLite文件,根據(jù)其包含的系統(tǒng)表sqlite_master確定欲恢復(fù)數(shù)據(jù)表的根頁號以及表的字段結(jié)構(gòu)信息。結(jié)合SQLite文件的存儲結(jié)構(gòu),從根頁號與文件頭開始,對B+tree進(jìn)行遍歷,收集其中所有的空閑頁與空閑塊,對于每一個空閑塊執(zhí)行步驟2。
步驟2、本步驟中假定每個空閑塊恰包含一個被刪除的單元。對當(dāng)前空閑塊進(jìn)行判斷。由于payloadsize,rowId與headersizes最少一共占3個字節(jié),單元轉(zhuǎn)變?yōu)榭臻e塊覆蓋前4個字節(jié),因此Type域第一個字節(jié)有可能被覆蓋。分為兩種情況討論,即Type1被覆蓋的情況與未被覆蓋的情況。由于本方法對Type1進(jìn)行了判斷,因此適用于任意主鍵類型的表。假定Type域起點(diǎn)為i。分別以第四個到最后一個字節(jié)為起點(diǎn)i,進(jìn)行判斷。若i=4,認(rèn)為Type1數(shù)據(jù)丟失,跳轉(zhuǎn)步驟2.1,若i>=5,認(rèn)為所有Type信息完整,跳轉(zhuǎn)步驟2.2。
步驟2.1、若起點(diǎn)為第四個字節(jié),令第四個字節(jié)的值從0x00到0xFF遞增,對于當(dāng)前空閑塊獲得的256個值中的每一個值對應(yīng)的狀態(tài),執(zhí)行步驟2.2-2.2.4,任意一個值對應(yīng)的狀態(tài)通過驗(yàn)證獲得被刪除的單元數(shù)據(jù),則將恢復(fù)出來的數(shù)據(jù)加入恢復(fù)結(jié)果集,終止該空閑塊判斷,繼續(xù)判斷下一個空閑塊。若256個值對應(yīng)的狀態(tài)均無法通過驗(yàn)證,則令i=4,執(zhí)行步驟2。
步驟2.2、以i為第一個Type的起始位置,按照Type的可變長整型存儲規(guī)則,解析所有Type,并根據(jù)其值計(jì)算理論的數(shù)據(jù)長度
步驟2.3、根據(jù)步驟2.2結(jié)果,可得Type域所占字節(jié)數(shù)len(T)??傻帽究臻e塊剩余字節(jié)數(shù)realDLen。如果readlDLen=theoryDLen,則根據(jù)Type-Data對應(yīng)關(guān)系提取數(shù)據(jù),恢復(fù)出來的數(shù)據(jù)通過驗(yàn)證后加入恢復(fù)結(jié)果集,跳轉(zhuǎn)步驟2.5。否則,執(zhí)行步驟2.4。
步驟2.4,令i=i+1,跳轉(zhuǎn)步驟2。若i為空閑塊最后一個字節(jié)位置,則將該空閑塊加入失敗空閑塊集,執(zhí)行步驟2.5。
步驟2.5繼續(xù)判斷下一個空閑塊,跳轉(zhuǎn)到步驟2,若當(dāng)前為最后一個空閑塊,執(zhí)行步驟3。
步驟3、本步驟為對步驟2中失敗空閑塊集的拆分判斷,令估計(jì)的數(shù)據(jù)長度j從4遞增到空閑塊長度len(fb),一個空閑塊對每個j值均截取j個字節(jié)長度的數(shù)據(jù),產(chǎn)生一個長度為j的臨時(shí)空閑塊,每個失敗空閑塊可生成len-3個臨時(shí)空閑塊。通過失敗空閑塊集獲得臨時(shí)空閑塊集,以臨時(shí)空閑塊集執(zhí)行如下操作。
步驟3.1、將步驟2.5替換為步驟3.2。對每一個臨時(shí)空閑塊執(zhí)行步驟2。
步驟3.2、從臨時(shí)空閑塊集中刪除與當(dāng)前臨時(shí)空閑塊及兄弟臨時(shí)空閑塊(即由同一個失敗空閑塊映射得到的臨時(shí)空閑塊)。繼續(xù)判斷下一個臨時(shí)空閑塊,跳轉(zhuǎn)到步驟3.1,若當(dāng)前為最后一個臨時(shí)空閑塊,執(zhí)行步驟4。
步驟4、對于每一個步驟1搜集到的空閑頁集,根據(jù)頁第一個字節(jié)的值,刷選出葉子頁,即0x0D的頁。對于每一個葉子頁,提取其中的單元值。一般情況下,該單元的值并未被覆蓋,可以直接提取數(shù)據(jù),加入到恢復(fù)結(jié)果集中。
參見圖1,為本發(fā)明中收集空閑塊并對其未拆分狀態(tài)進(jìn)行恢復(fù)的整體流程圖,包括以下步驟。
S1:根據(jù)sqlite_master與數(shù)據(jù)庫文件頭,收集所有的空閑塊與空閑頁。獲得所有空閑塊集合Setfbs={fbi|i=1,2,…,n}。
S2:進(jìn)一步,對每一個空閑塊執(zhí)行圖2。如果該操作恢復(fù)出數(shù)據(jù),則將結(jié)果加入恢復(fù)結(jié)果集,然后繼續(xù)判斷下一個空閑塊。
S3:如果當(dāng)前為最后一個空閑塊,則結(jié)束算法,繼續(xù)執(zhí)行圖3的操作,即步驟3的內(nèi)容。
參見圖2,是本發(fā)明中對每個空閑塊的數(shù)據(jù)恢復(fù)操作流程圖。為S2的具體實(shí)施步驟。
從i=4開始,即Type1之前的字節(jié)數(shù)為pre=3開始進(jìn)行判定與恢復(fù)。如果i=4,pre=3,則執(zhí)行RC(fb,i),即如下循環(huán),j=0x00:
S21:(1)令空閑塊第i個字節(jié)的值為j;(2)執(zhí)行rc(fb,3)即圖3,若成功恢復(fù)數(shù)據(jù),輸出該數(shù)據(jù),結(jié)束當(dāng)前空閑塊。(3)若未成功,則j++,如果j<=0xFF,跳轉(zhuǎn)(1),否則,結(jié)束本循環(huán),令i=5。
S22:如果i>=5,pre>=4,做如下循環(huán):(1)執(zhí)行rc(fb,pre)(2)若成功恢復(fù)數(shù)據(jù),輸出該數(shù)據(jù),則結(jié)束當(dāng)前空閑塊。(3)否則,若i是空閑塊最后一個位置,則將當(dāng)前空閑塊加入失敗空閑塊集,結(jié)束當(dāng)前空閑塊判斷。否則,令i++,pre++,跳轉(zhuǎn)(1)。
參見圖3,為本發(fā)明中對每個空閑塊的每個起始位置i的基本恢復(fù)操作的流程圖,為數(shù)據(jù)恢復(fù)中最基本的操作。即一次rc(fb,pre)。
S23:在該操作中,以傳入的i為起點(diǎn),逐字節(jié),按照可變長整型的規(guī)則解析所有的Type,可得Type域字節(jié)數(shù)量??捎?jì)算出理論的數(shù)據(jù)域Data的長度和實(shí)際的Data的長度。
S24:如果理論長度與實(shí)際長度相等,則認(rèn)為此空閑塊原單元數(shù)據(jù)可被恢復(fù)?;謴?fù)數(shù)據(jù),并輸出正確數(shù)據(jù)。若不可,不輸出,結(jié)束當(dāng)前操作。待下一個輸入i繼續(xù)。
S3:參見圖4,為本發(fā)明中對失敗空閑塊集進(jìn)行的恢復(fù)操作的流程圖,屬于合并空閑塊提取模塊內(nèi)容。通過前置算法,可得失敗空閑塊集。
S31:首先通過循環(huán)獲得臨時(shí)空閑塊集:(1)從len=4開始截取當(dāng)前失敗空閑塊,加入臨時(shí)空閑塊集。len++。(2)如果len等于當(dāng)前失敗空閑塊長度,則判斷下一個失敗空閑塊,跳轉(zhuǎn)(1)。若當(dāng)前為最后一個失敗空閑塊,結(jié)束當(dāng)前循環(huán)。
S32:對每一個臨時(shí)空閑塊執(zhí)行圖2所示操作,如果未獲得恢復(fù)數(shù)據(jù),繼續(xù)判斷下一個臨時(shí)空閑塊。如獲得恢復(fù)的數(shù)據(jù),則刪除所有兄弟臨時(shí)空閑塊(由同一失敗空閑塊映射得到),然后將數(shù)據(jù)加入恢復(fù)結(jié)果集,繼續(xù)判斷下一個臨時(shí)空閑塊。
S4:最后,利用收集到的所有空閑頁,篩選出所有的葉子頁,進(jìn)一步根據(jù)數(shù)據(jù)庫文件結(jié)構(gòu),讀取其中存在的單元數(shù)據(jù),一并加入到恢復(fù)數(shù)據(jù)集中。
恢復(fù)數(shù)據(jù)集即為本方法最終的恢復(fù)數(shù)據(jù)輸出結(jié)果。
以上這些實(shí)施例應(yīng)理解為僅用于說明本發(fā)明而不用于限制本發(fā)明的保護(hù)范圍。在閱讀了本發(fā)明的記載的內(nèi)容之后,技術(shù)人員可以對本發(fā)明作各種改動或修改,這些等效變化和修飾同樣落入本發(fā)明權(quán)利要求所限定的范圍。