亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

解剖SQLSERVER 第二篇 對數據頁面頭進行逆向(譯)

2024-07-21 02:48:59
字體:
來源:轉載
供稿:網友
解剖SQLSERVER 第二篇 對數據頁面頭進行逆向(譯)解剖SQLSERVER 第二篇 對數據頁面頭進行逆向(譯)

http://imPRove.dk/reverse-engineering-sql-server-page-headers/

在開發OrcaMDF 的時候第一個挑戰就是解析數據頁面頭部,我們知道數據頁面分兩部分,96字節的頁面頭部和8096字節的數據行

大神Paul Randal 寫了一篇文章很好的描述了頁頭結構,然而,即使文章描述得很詳細,但是我還是找不出任何關于頁頭存儲的格式

每一個字段的數據類型和他們的順序

我們可以使用DBCC PAGE命令,我填充一些隨機數據進去數據頁面,然后把頁面dump出來

頁面號是(1:101):

DBCC TRACEON (3604)DBCC PAGE (TextTest, 1, 101, 2)

結果分兩部分,首先,我們獲得DBCC PAGE已經格式化好的頁面內容,dump出來的內容的第二部分是96字節的頁面頭

開始動手了,我們需要找出頁面頭部的這些數據值對應的數據類型是什么

為了簡單,我們需要關注一些唯一值以便我們不會獲取到某些存在含糊的數值

我們從m_freeCnt這個字段開始,我們看到m_freeCnt的值是4066,而數據行大小是8060,所以很明顯,m_freeCnt的數據類型不可能是tinyint

m_freeCnt不太可能使用int類型,一種有依據的猜測是m_freeCnt有可能使用smallint類型,這讓數據行足夠容納0-8060 字節空間的數據

smallint:從-2^15(-32,768)到2^15-1(32,767)的整數數據存儲大小為 2 個字節,本人也覺得m_freeCnt這個字段的值不可能太大

現在,4066這個十進制數換成十六進制是0x0FE2. 字節交換,變成0xE20F,現在我們知道,我們已經匹配到m_freeCnt的數據類型了

另外,我們已經知道頁頭里面第一個字段的數據類型和位置

/*    Bytes    Content    -----    -------    00-27    ?    28-29    FreeCnt (smallint)    30-95    ?*/

繼續我們的查找,我們看到m_freeData =3895,換算成十六進制是0x0F37 字節交換后0x370F

我們發現m_freeCnt這個字段存儲在m_freeCnt的后面

使用這個技巧,我們能匹配存儲在頁頭的并且沒有含糊的唯一數據值

不過 ,對于m_level這個字段,他跟m_xactReserved字段,m_reservedCnt字段,m_GhostRecCnt字段的值是一樣的

我們怎麼知道0這個值哪個才屬于m_level字段? 并且我們怎麼找出他的數據類型呢?這有可能是tinyint 到bigint類型

我們請出Visual Studio大神,然后shutdown SQLSERVER

把mdf文件拖入VS,VS會打開hex編輯器,我們根據頁面偏移算出頁面位置

101 * 8192 = 827,392

看著紅色框給我們標出的字節內容,他已經標識出我們的頁面頭內容,并且確定了我們已經跳轉到正確的位置

現在我們會填一些數值進去mdf文件里面然后保存文件,請不要胡亂在生產數據庫上進行測試

現在我們啟動SQLSERVER,然后再次運行DBCC PAGE命令

DBCC TRACEON (3604)DBCC PAGE (TextTest, 1, 101, 2)

可以注意到,現在頁面頭變成了這樣

有幾個數值變了,m_xactReserved 字段先前的數值是0,現在變成了30806,將這個數字轉換成十六進制并進行字節交換得到0x5678

看一下頁面頭,現在我們已經識別出另外一個字段的值和數據類型(smallint)

我們更新一下我們頁頭表格

/*    Bytes    Content    -----    -------    00-27    ?    28-29    FreeCnt (smallint)    30-49    ?    50-51    XactReserved (smallint)    30-95    ?*/

沿著這種方法繼續,把頁頭進行混亂修改,將修改后的頁頭和DBCC PAGE的輸出進行關聯,有可能找出這些字段的數據類型

如果你看到下面的消息,你就知道已經把頁面頭部搞混亂了

你應該覺得自豪的,沒有人能修好你胡亂修改出來的錯誤

我已經編好了一個頁頭結構表

/*    Bytes    Content    -----    -------    00    HeaderVersion (tinyint)    01    Type (tinyint)    02    TypeFlagBits (tinyint)    03    Level (tinyint)    04-05    FlagBits (smallint)    06-07    IndexID (smallint)    08-11    PreviousPageID (int)    12-13    PreviousFileID (smallint)    14-15    Pminlen (smallint)    16-19    NextPageID (int)    20-21    NextPageFileID (smallint)    22-23    SlotCnt (smallint)    24-27    ObjectID (int)    28-29    FreeCnt (smallint)    30-31    FreeData (smallint)    32-35    PageID (int)    36-37    FileID (smallint)    38-39    ReservedCnt (smallint)    40-43    Lsn1 (int)    44-47    Lsn2 (int)    48-49    Lsn3 (smallint)    50-51    XactReserved (smallint)    52-55    XdesIDPart2 (int)    56-57    XdesIDPart1 (smallint)    58-59    GhostRecCnt (smallint)    60-95    ?*/

我不確定頁頭的其他字節跟DBCC PAGE輸出的字段對應關系,我測試過的所有頁面這些字節似乎都存儲為0

我認為這些應該都是為將來某種用途使用的保留字節。好了, 我們已經獲得頁頭格式,讀取每個字段就很簡單了

HeaderVersion = header[0];Type = (PageType)header[1];TypeFlagBits = header[2];Level = header[3];FlagBits = BitConverter.ToInt16(header, 4);IndexID = BitConverter.ToInt16(header, 6);PreviousPage = new PagePointer(BitConverter.ToInt16(header, 12), BitConverter.ToInt32(header, 8));Pminlen = BitConverter.ToInt16(header, 14);NextPage = new PagePointer(BitConverter.ToInt16(header, 20), BitConverter.ToInt32(header, 16));SlotCnt = BitConverter.ToInt16(header, 22);ObjectID = BitConverter.ToInt32(header, 24);FreeCnt = BitConverter.ToInt16(header, 28);FreeData = BitConverter.ToInt16(header, 30);Pointer = new PagePointer(BitConverter.ToInt16(header, 36), BitConverter.ToInt32(header, 32));ReservedCnt = BitConverter.ToInt16(header, 38);Lsn = "(" + BitConverter.ToInt32(header, 40) + ":" + BitConverter.ToInt32(header, 44) + ":" + BitConverter.ToInt16(header, 48) + ")";XactReserved = BitConverter.ToInt16(header, 50);XdesID = "(" + BitConverter.ToInt16(header, 56) + ":" + BitConverter.ToInt32(header, 52) + ")";GhostRecCnt = BitConverter.ToInt16(header, 58);

大家可以看一下我寫的pageheader類

using System;using System.Text;namespace OrcaMDF.Core.Engine.Pages{public class PageHeader{public short FreeCnt { get; private set; }public short FreeData { get; private set; }public short FlagBits { get; private set; }public string Lsn { get; private set; }public int ObjectID { get; private set; }public PageType Type { get; private set; }public short Pminlen { get; private set; }public short IndexID { get; private set; }public byte TypeFlagBits { get; private set; }public short SlotCnt { get; private set; }public string XdesID { get; private set; }public short XactReserved { get; private set; }public short ReservedCnt { get; private set; }public byte Level { get; private set; }public byte HeaderVersion { get; private set; }public short GhostRecCnt { get; private set; }public PagePointer NextPage { get; private set; }public PagePointer PreviousPage { get; private set; }public PagePointer Pointer { get; private set; }public PageHeader(byte[] header){if (header.Length != 96)throw new ArgumentException("Header length must be 96.");/*                Bytes    Content                -----    -------                00        HeaderVersion (tinyint)                01        Type (tinyint)                02        TypeFlagBits (tinyint)                03        Level (tinyint)                04-05    FlagBits (smallint)                06-07    IndexID (smallint)                08-11    PreviousPageID (int)                12-13    PreviousFileID (smallint)                14-15    Pminlen (smallint)                16-19    NextPageID (int)                20-21    NextPageFileID (smallint)                22-23    SlotCnt (smallint)                24-27    ObjectID (int)                28-29    FreeCnt (smallint)                30-31    FreeData (smallint)                32-35    PageID (int)                36-37    FileID (smallint)                38-39    ReservedCnt (smallint)                40-43    Lsn1 (int)                44-47    Lsn2 (int)                48-49    Lsn3 (smallint)                50-51    XactReserved (smallint)                52-55    XdesIDPart2 (int)                56-57    XdesIDPart1 (smallint)                58-59    GhostRecCnt (smallint)                60-63    Checksum/Tornbits (int)                64-95    ?            */HeaderVersion = header[0];Type = (PageType)header[1];TypeFlagBits = header[2];Level = header[3];FlagBits = BitConverter.ToInt16(header, 4);IndexID = BitConverter.ToInt16(header, 6);PreviousPage = new PagePointer(BitConverter.ToInt16(header, 12), BitConverter.ToInt32(header, 8));Pminlen = BitConverter.ToInt16(header, 14);NextPage = new PagePointer(BitConverter.ToInt16(header, 20), BitConverter.ToInt32(header, 16));SlotCnt = BitConverter.ToInt16(header, 22);ObjectID = BitConverter.ToInt32(header, 24);FreeCnt = BitConverter.ToInt16(header, 28);FreeData = BitConverter.ToInt16(header, 30);Pointer = new PagePointer(BitConverter.ToInt16(header, 36), BitConverter.ToInt32(header, 32));ReservedCnt = BitConverter.ToInt16(header, 38);Lsn = "(" + BitConverter.ToInt32(header, 40) + ":" + BitConverter.ToInt32(header, 44) + ":" + BitConverter.ToInt16(header, 48) + ")";XactReserved = BitConverter.ToInt16(header
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
热久久美女精品天天吊色| 日韩av在线精品| 欧美高清电影在线看| 亚洲最大中文字幕| 在线观看欧美日韩国产| 欧美视频免费在线观看| 中文字幕精品www乱入免费视频| 欧美主播福利视频| 91精品国产网站| 日本一区二区三区在线播放| 另类天堂视频在线观看| 亚洲精品国产电影| 97精品在线观看| 欧美精品videosex性欧美| 午夜精品理论片| 久久久久久久久久久免费| 国产精品a久久久久久| 欧美激情一区二区三区高清视频| 欧美激情视频一区二区| 韩国v欧美v日本v亚洲| 91在线观看免费高清完整版在线观看| 尤物99国产成人精品视频| 欧美日本在线视频中文字字幕| 欧美精品亚州精品| 欧美激情第三页| 久久高清视频免费| 亚洲丁香婷深爱综合| 国产97免费视| 久热国产精品视频| 色偷偷av亚洲男人的天堂| 国产精品极品美女粉嫩高清在线| 中文字幕在线看视频国产欧美在线看完整| 国产丝袜一区二区三区| 亚洲国产高清自拍| 国产精品成人va在线观看| 国产成人aa精品一区在线播放| 亲子乱一区二区三区电影| 成人在线播放av| 最新国产成人av网站网址麻豆| 欧美黑人狂野猛交老妇| 久久久www成人免费精品张筱雨| 91精品视频在线免费观看| 国产成人高潮免费观看精品| 国产成人精品久久二区二区| 97福利一区二区| 精品成人久久av| 日韩精品视频在线免费观看| 精品日韩视频在线观看| 欧美大尺度电影在线观看| 日韩在线中文视频| 久久久亚洲欧洲日产国码aⅴ| 91av在线精品| 国产中文欧美精品| 狠狠躁天天躁日日躁欧美| 国产精品欧美日韩| 国产精品三级久久久久久电影| 国产69久久精品成人看| 国产日韩精品入口| 欧美极品少妇xxxxx| 97精品免费视频| 亚洲第一精品夜夜躁人人爽| 日韩视频中文字幕| 日韩在线欧美在线国产在线| 久久久久国产精品免费网站| 欧美三级欧美成人高清www| 亚洲人在线观看| 欧美日韩美女在线观看| 日韩av电影中文字幕| 欧美性猛交xxxx免费看| 久久九九热免费视频| 国产精品稀缺呦系列在线| 日韩中文字幕亚洲| 日韩免费黄色av| 欧美日韩亚洲高清| 国产精品久久久亚洲| 国模私拍一区二区三区| 日韩美女视频免费在线观看| 欧美一级大片在线观看| 国产精品美女久久| 久久九九有精品国产23| 国产精品自产拍在线观看中文| 性色av一区二区三区| 91精品美女在线| 青青草精品毛片| 在线性视频日韩欧美| 欧美成人高清视频| 国产精品对白刺激| 亚洲人成在线免费观看| 国产欧美精品久久久| www.美女亚洲精品| 久久久久国产精品免费网站| 日韩av在线播放资源| 上原亚衣av一区二区三区| 国产精品久久久久9999| 久久在线免费观看视频| 国产亚洲福利一区| 亚洲国产毛片完整版| 精品国产一区二区在线| 亚洲 日韩 国产第一| 欧美丝袜美女中出在线| 日韩高清免费观看| 欧美精品国产精品日韩精品| 国产亚洲精品日韩| 91九色精品视频| 91国产在线精品| 另类天堂视频在线观看| 亚洲欧美中文日韩在线| 91欧美日韩一区| 5566成人精品视频免费| 精品呦交小u女在线| 在线观看国产成人av片| 亚洲精品suv精品一区二区| 日韩电影免费观看在线观看| 久久久久久久色| 亚洲午夜小视频| 国产在线拍揄自揄视频不卡99| 538国产精品视频一区二区| 精品国产一区二区三区久久久狼| 欧美日韩国产一区二区三区| 国产99久久精品一区二区 夜夜躁日日躁| 2021国产精品视频| 51色欧美片视频在线观看| 欧美日韩国产精品| 国产精品女视频| 自拍偷拍免费精品| 中文字幕欧美国内| 久久精品视频网站| 欧美激情视频一区二区三区不卡| 国内精品中文字幕| 亚洲码在线观看| 96国产粉嫩美女| 亚洲成av人片在线观看香蕉| 亚洲自拍另类欧美丝袜| 国产色视频一区| 久久资源免费视频| 成人黄色午夜影院| 久久免费视频在线| 国产精品美乳在线观看| 伦理中文字幕亚洲| 色综合久久中文字幕综合网小说| 日韩在线中文字幕| 欧美亚洲国产日本| 中文字幕久热精品在线视频| 欧美日韩亚洲精品一区二区三区| 欧美性生交xxxxx久久久| 国产精品美女免费| 91色琪琪电影亚洲精品久久| www.亚洲免费视频| 欧美另类极品videosbestfree| 亚洲精品国产品国语在线| 欧美在线激情网| 国产原创欧美精品| 国产亚洲美女久久| 黑人巨大精品欧美一区二区一视频| 在线观看国产欧美| 97精品伊人久久久大香线蕉| 性色av一区二区三区免费| 日韩在线资源网| 国产精品吴梦梦| 日本一区二区在线免费播放| 欧美影院久久久| 久久久久久中文字幕| 91精品美女在线| yw.139尤物在线精品视频|