设为首页 收藏本站
查看: 979|回复: 0

[经验分享] Sql Server之旅——第六站 使用winHex利器加深理解数据页

[复制链接]

尚未签到

发表于 2015-6-27 09:07:16 | 显示全部楼层 |阅读模式
  
  这篇我来介绍一个winhex利器,这个工具网上有介绍,用途大着呢,可以用来玩数据修复,恢复删除文件等等。。。。它能够将一个file解析成
  hex形式,这样你就可以对hex进行修改,然后你就可以看到修复后的结果,为什么要在sqlserver系列中说这个呢???很简单呀,sqlserver的DB本
  质上也是一个mdf文件,对吧,既然是文件,我就可以利用winhex对它进行随意的修改,然后你也知道sqlserver的数据都是以数据页的形式封装的,
  那我就可以修改它的数据页,对不对,这样我就可以随便改变记录的顺序,包括槽位,记录,页头等等。。。说干就干吧!!!
  
  一:准备数据
  我计划在数据库中插入三条测试数据,如图:



1 DROP TABLE dbo.Person
2
3 CREATE TABLE Person(ID INT IDENTITY,NAME VARCHAR(5),Age INT)
4
5 INSERT dbo.Person VALUES('amy',20)
6 INSERT dbo.Person VALUES('anna',25)
7 INSERT dbo.Person VALUES('smart',28)
8
9 SELECT * FROM dbo.Person
  接下来通过上一章介绍的DBCC命令,查看下三条记录的数据页情况,如下图:



DBCC TRACEON(3604)
DBCC IND(Ctrip,Person,-1)
DBCC PAGE(Ctrip,1,78,2)


1 DATA:
2
3
4 Memory Dump @0x00000000100EA000
5
6 00000000100EA000:   01010400 00800001 00000000 00000c00 †................
7 00000000100EA010:   00000000 00000300 3f000000 551fa500 †........?...U...
8 00000000100EA020:   4e000000 01000000 8e000000 66000000 †N...........f...
9 00000000100EA030:   03000000 00000000 00000000 00000000 †................
10 00000000100EA040:   01000000 00000000 00000000 00000000 †................
11 00000000100EA050:   00000000 00000000 00000000 00000000 †................
12 00000000100EA060:   30000c00 01000000 14000000 03000001 †0...............
13 00000000100EA070:   00160061 6d793000 0c000200 00001900 †...amy0.........
14 00000000100EA080:   00000300 00010017 00616e6e 6130000c †.........anna0..
15 00000000100EA090:   00030000 001c0000 00030000 01001800 †................
16 00000000100EA0A0:   736d6172 74000000 00000000 00000000 †smart...........
17 00000000100EA0B0:   00000000 00000000 00000000 00000000 †................
18
19 ....
20               
21 00000000100EBFC0:   20202020 20202020 20202020 20202020 †                 
22 00000000100EBFD0:   20202020 20200000 00000000 00000000 †      ..........
23 00000000100EBFE0:   00000000 00000000 00000000 00000000 †................
24 00000000100EBFF0:   00000000 00000000 1f0b8d00 76006000 †............v.`.
25
26 OFFSET TABLE:
27
28 Row - Offset                        
29 2 (0x2) - 141 (0x8d)                 
30 1 (0x1) - 118 (0x76)                 
31 0 (0x0) - 96 (0x60)   
  我想大家现在都清楚了,数据页中的一条条存储记录都是通过页尾的槽位指向的,具体可以参见前几篇对数据页的介绍,比如你看到页尾的:
  8d0076006000了吗?要注意,这些都是按照字节逆序来的。
  1. 6000  这个就是slot0,也就是  (0x0) - 96 (0x60)
  2. 0x76  这个就是slot1,也就是(0x1) - 118 (0x76)  
  2. 0x8d  这个就是slot2,也就是(0x2) - 141 (0x8d)  
  是不是有点意思,如果你一定要看到slot具体指向的内容,你可以继续用上一节介绍的DBCC命令,一清二楚。



1 DBCC PAGE(Ctrip,1,78,1)


PAGE: (1:78)

BUFFER:

BUF @0x0000000083FD8E00
bpage = 0x0000000083ADC000           bhash = 0x0000000000000000           bpageno = (1:78)
bdbid = 8                            breferences = 0                      bUse1 = 2495
bstat = 0x1c0000b                    blog = 0xbbbbbbbb                    bnext = 0x0000000000000000
PAGE HEADER:

Page @0x0000000083ADC000
m_pageId = (1:78)                    m_headerVersion = 1                  m_type = 1
m_typeFlagBits = 0x4                 m_level = 0                          m_flagBits = 0x8000
m_objId (AllocUnitId.idObj) = 63     m_indexId (AllocUnitId.idInd) = 256  
Metadata: AllocUnitId = 72057594042056704                                 
Metadata: PartitionId = 72057594041204736                                 Metadata: IndexId = 0
Metadata: ObjectId = 341576255       m_prevPage = (0:0)                   m_nextPage = (0:0)
pminlen = 12                         m_slotCnt = 3                        m_freeCnt = 8021
m_freeData = 165                     m_reservedCnt = 0                    m_lsn = (142:102:3)
m_xactReserved = 0                   m_xdesId = (0:0)                     m_ghostRecCnt = 0
m_tornBits = 0                       
Allocation Status
GAM (1:2) = ALLOCATED                SGAM (1:3) = ALLOCATED               
PFS (1:1) = 0x61 MIXED_EXT ALLOCATED  50_PCT_FULL                         DIFF (1:6) = CHANGED
ML (1:7) = NOT MIN_LOGGED            
DATA:

Slot 0, Offset 0x60, Length 22, DumpStyle BYTE
Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS
Record Size = 22                     
Memory Dump @0x000000000F7FC060
0000000000000000:   30000c00 01000000 14000000 03000001 †0...............
0000000000000010:   00160061 6d79††††††††††††††††††††††††...amy           
Slot 1, Offset 0x76, Length 23, DumpStyle BYTE
Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS
Record Size = 23                     
Memory Dump @0x000000000F7FC076
0000000000000000:   30000c00 02000000 19000000 03000001 †0...............
0000000000000010:   00170061 6e6e61††††††††††††††††††††††...anna         
Slot 2, Offset 0x8d, Length 24, DumpStyle BYTE
Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS
Record Size = 24                     
Memory Dump @0x000000000F7FC08D
0000000000000000:   30000c00 03000000 1c000000 03000001 †0...............
0000000000000010:   00180073 6d617274 †††††††††††††††††††...smart         
OFFSET TABLE:
Row - Offset                        
2 (0x2) - 141 (0x8d)                 
1 (0x1) - 118 (0x76)                 
0 (0x0) - 96 (0x60)                  

DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
  仔细观察下上面的蓝色字体,有没有总结出各个slot槽位对应的记录内容,比如:
  slot0槽位指向的记录内容:  amy =>  616d79。
  slot1槽位指向的记录内容:  anna => 616e6e61。
  slot2槽位指向的记录内容:  smart => 736d617274。
  这里你要知道,这里都是16进制表示的,所以2个16进制对应一个字节。
  
  二:使用WinHex修改数据
  我们大家都知道,sqlserver引擎会通过扫描slot槽位来呈现数据,就像上面的记录那样,依次扫描slot0...slot1....slot2...来呈现数据,如下图:
DSC0000.png
  上面这个截图没什么稀奇的地方,大家也觉得见怪不怪的,那下面就有一个想法来了,如果我通过winHex来交换slot0和slot1的顺序,那效果会是
  怎样???按照常理说,这时候引擎还是按照slot槽位依次扫描,这时候应该会将ID=2的记录先喷出来,然后再喷出ID=1,ID=3。。。事实是不是
  这样子呢?好奇吧,我们来看看。。。
  
  三:相关步骤
  1.  我们知道Ctrip数据库是联机的,我们要修改它必须先脱机,然后再关掉数据页的一致性校验(这个也是数据库的保护机制,防止第三方恶意的去篡
       改数据),这个应该大家都明白,如下图:
DSC0001.png
  
  2.  从网上下载一个破解版的winhex,然后打开本地的Ctrip.mdf文件,调整winhex的编辑模式为默认的可读写,如图:
DSC0002.png
  
  3. 我们知道一个数据页的大小是8KB=8192B,那么第78号数据页的起始位置的偏移量应该就是:78*8192=638976,然后通过快捷键
  Alt+G打开偏移量列表,键入638976,如下图:
DSC0003.png
  
  找到记录的内容之后,我们再来找槽位,槽位的开始位置在78号数据页的末尾,那怎么算呢?这个算法也很简单,offset=79*8192-1=647167。
  说干就干。
DSC0004.png
  当你真的找到了偏移量,是不是很兴奋呢?下面要做的就是把60和76交换一下,也就是将slot0和slot1交换,看看怎么样????
  
  4. 交换完毕后,ctrl+s保存,然后让Ctrip数据库联机,并使用Sql语句查看下现在的效果???
DSC0005.png
  当你看到这张图的时候,是不是已经疯了。。。。这样我就非常肯定的论证了,引擎真的就是通过依次扫描slot的槽位来指向记录的,如果你
  大概理解了上面的操作,现在你可以修改任意数据页的数据了,只要你找得到数据页的偏移量,然后任由你发挥啦~~~~感谢感谢。。。
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-80875-1-1.html 上篇帖子: Sql Server Compact 4.0部署注意事项 下篇帖子: T-SQL查询高级--理解SQL SERVER中非聚集索引的覆盖,连接,交叉和过滤
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表