李寧
摘 要:MS SQL SERVER的數(shù)據(jù)庫恢復(fù)的案件實(shí)例和恢復(fù)還原的方法和原理。筆者在2011年曾經(jīng)協(xié)助我院自偵部門辦理過一件貪污案件,在案件中涉及恢復(fù)一個(gè)MS SQL SERVER的數(shù)據(jù)庫。在經(jīng)過常規(guī)的數(shù)據(jù)恢復(fù)方法無法正?;謴?fù)的情況下,經(jīng)專家指點(diǎn)使用數(shù)據(jù)庫逆向還原的方法恢復(fù)了數(shù)據(jù)。
關(guān)鍵詞:MS SQL SERVER 數(shù)據(jù)庫;恢復(fù);還原
一、恢復(fù)數(shù)據(jù)的過程
筆者拿到證據(jù)硬盤后首先對(duì)硬盤做了鏡像拷貝,保證證據(jù)硬盤沒有收到污染和破壞。其次,使用常用數(shù)據(jù)恢復(fù)軟件對(duì)鏡像硬盤進(jìn)行掃描,試圖恢復(fù)數(shù)據(jù)庫的MDF文件或者備份文件。但是掃描結(jié)果是多個(gè)備份文件已經(jīng)被刪除,并在硬盤上找不到任何刪除的數(shù)據(jù)庫的文件名和存儲(chǔ)位置信息。顯然常規(guī)方法行不通,筆者經(jīng)過多方查找資料和聯(lián)系專家,經(jīng)專家指點(diǎn)找到一種恢復(fù)數(shù)據(jù)庫的方法即利用數(shù)據(jù)庫MDF文件的數(shù)據(jù)硬盤頁式存儲(chǔ)結(jié)構(gòu)信息,逆向還原MDF 文件。實(shí)際做法如下:
1、首先定義數(shù)據(jù)頁特征:MDF文件的數(shù)據(jù)頁大小為8K,應(yīng)該符合以下幾個(gè)條件:第0字節(jié)為1, 0x40字節(jié)至0x60字節(jié)全為0。當(dāng)數(shù)據(jù)庫只有一個(gè)mdf文件時(shí),屬于該mdf文件的頁0x24字節(jié)為1, 0x25字節(jié)為0, 頁號(hào)記錄在0x20 處,從0開始。
2、建立一個(gè)日志文件1.log,對(duì)鏡像硬盤進(jìn)行遍歷. 然后讀取每一個(gè)扇區(qū),檢查是否符合數(shù)據(jù)頁要求。如符合,輸出0x20處,長度為4的頁id, 同時(shí)輸出當(dāng)前扇區(qū)號(hào)到1.log文件。到這樣就能夠得到一個(gè)記錄了格式符合SQL數(shù)據(jù)頁的位置和頁號(hào)的日志。
3、對(duì)1.log中,上下兩行頁號(hào)的差等于扇區(qū)的差除以16(數(shù)據(jù)頁大小為16個(gè)扇區(qū))的話, 可以認(rèn)為這兩個(gè)數(shù)據(jù)頁連續(xù)。這樣,當(dāng)遇到數(shù)據(jù)頁不連續(xù)時(shí),可以將上一頁作為一個(gè)文件碎片的結(jié)束,而不連續(xù)的那個(gè)頁作為下一個(gè)文件碎片的開始。記錄下每一個(gè)碎片的開始扇區(qū), 結(jié)束扇區(qū),開始數(shù)據(jù)頁號(hào),結(jié)束數(shù)據(jù)頁號(hào), 以及包含頁數(shù)量。將這些信息記錄在2.log文件中。
4、第0號(hào)頁中包含了數(shù)據(jù)庫文件的總頁數(shù), 其位置在0xAF到0xB2中。根據(jù)這個(gè)長度創(chuàng)建一個(gè)空文件1.mdf。
5、如果鏡像硬盤中只包含一個(gè)數(shù)據(jù)庫,2.log中的數(shù)據(jù)可以直接使用,將記錄的對(duì)應(yīng)扇區(qū)中的數(shù)據(jù)頁拷貝到1.mdf中。如果包含多個(gè)數(shù)據(jù)庫,可以手工調(diào)整,例如只保留其中物理位置比較接近,較完整,且能夠逆向還原整個(gè)數(shù)據(jù)庫。
二、逆向還原數(shù)據(jù)庫的原理
(一)數(shù)據(jù)庫文件數(shù)據(jù)頁結(jié)構(gòu)分析
SQL Server的MDF文件是頁式存儲(chǔ)格式。文件被劃分成若干數(shù)據(jù)頁。數(shù)據(jù)頁是包含所有非文本或圖像的數(shù)據(jù)的結(jié)構(gòu)。就像使用SQL Server中的其他類型的頁面一樣,數(shù)據(jù)頁面具有8KB(或8192字節(jié))的固定大小。它們由三個(gè)主要部分組成:頁面標(biāo)題、數(shù)據(jù)行和行偏移量數(shù)組,在每個(gè)數(shù)據(jù)頁中,頁面標(biāo)題占用了前96個(gè)字節(jié)(剩下的8096字節(jié)用于數(shù)據(jù)和行偏移量)數(shù)據(jù)頁的頁號(hào)pageID是從0開始, 順序排列。
(二)文件RAW恢復(fù)方法
通過對(duì)整個(gè)磁盤按扇區(qū)逐一掃描,找出文件頭和文件腳信息的這種恢復(fù)技術(shù)叫做RAW文件恢復(fù)。RAW文件恢復(fù)方式可恢復(fù)一些特定類型的文件,也經(jīng)常用于恢復(fù)SQL Server 數(shù)據(jù)庫 .MDF文件。
RAW文件恢復(fù)程序按以下工作步驟;
在硬盤上按扇區(qū)同步搜索一種或多種文件類型的文件頭。如果找到任何一個(gè)文件頭,則保存這些數(shù)據(jù)到一個(gè)文件,同時(shí)檢查下面4個(gè)條件,關(guān)閉和保存該文件。
1、找到該文件的文件頭;
2、找到相同文件類型的另一個(gè)文件頭;
3、找到另一個(gè)文件類型的一個(gè)文件頭;
4、當(dāng)找不到文件腳或其他此類文件頭時(shí),計(jì)算文件長度(某些類型的文件,其長度保存在文件前部或按預(yù)先設(shè)定的文件長度的最大值)。
(三)基于數(shù)據(jù)庫文件頁式存儲(chǔ)格式的恢復(fù)方法
利用數(shù)據(jù)庫文件的頁式存儲(chǔ)格式重建.mdf文件,首先確定要恢復(fù)的數(shù)據(jù)庫文件在硬盤上的第0頁的位置,即查找pageType = 0F的頁。在第0頁可獲取文件的總頁數(shù),根據(jù)總頁數(shù)創(chuàng)建一個(gè)與要重建的文件等長度的空文件(文件的內(nèi)容全為0)。遍歷整個(gè)硬盤,根據(jù)頁號(hào)pageID提取數(shù)據(jù)頁,將數(shù)據(jù)頁寫入已經(jīng)創(chuàng)建好的空文件的對(duì)應(yīng)位置。寫入所有的頁數(shù)據(jù)或硬盤遍歷完畢后,文件的重建即可完成。設(shè)新創(chuàng)建的空文件為 F,
則 F =(n=總頁數(shù))
Fi 為新建空文件的第i頁,用 Si 表示在硬盤上查找到的pageID = i的數(shù)據(jù)頁,
令 Fi = Si ,文件F 將被重建成數(shù)據(jù)庫文件。
但在實(shí)際恢復(fù)過程中將會(huì)遇到以下兩種情況:
1、Si = { },即Si 不存在;
2、Si 不唯一;
(四)數(shù)據(jù)庫文件的低層恢復(fù)
重建的數(shù)據(jù)庫文件可能不能直接使用,主要原因是由于數(shù)據(jù)庫文件有缺頁。如果有缺頁Si在文件的用戶表的位置上,可以通過修改 Si-1 和 Si+1 的 nextPage 和 prePage修復(fù),即 Si-1 的 nextPage = i+1, Si+1 的prePage = i-1, 當(dāng)然這是有損修復(fù)。
如果重建的數(shù)據(jù)庫文件缺頁太多或缺頁在文件的系統(tǒng)表的位置上,數(shù)據(jù)庫文件就不可能被數(shù)據(jù)庫直接使用,因此必須通過直接提取用戶表的數(shù)據(jù)。SQL Server 主要有4張系統(tǒng)表記錄了數(shù)據(jù)文件的頭信息、系統(tǒng)表信息和用戶表信息,它們是 sysobjects、sysindexes、syscolumns 和systypes, 通過這4張表記錄的信息再結(jié)合數(shù)據(jù)頁的objID 就能將指定的用戶表的數(shù)據(jù)完整的或部分的提取出來,轉(zhuǎn)換成文本文件格式或其他數(shù)據(jù)格式。endprint