这篇我来介绍一个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命令,查看下三条记录的数据页情况,如下图:

  1. DBCC TRACEON(3604)
  2. DBCC IND(Ctrip,Person,-1)
  3. DBCC PAGE(Ctrip,1,78,2)
  1. DATA:
  2.  
  3. Memory Dump @0x00000000100EA000
  4.  
  5. 00000000100EA000: 01010400 00800001 00000000 00000c00 †................
  6. 00000000100EA010: 00000000 00000300 3f000000 551fa500 †........?...U...
  7. 00000000100EA020: 4e000000 01000000 8e000000 66000000 N...........f...
  8. 00000000100EA030: 03000000 00000000 00000000 00000000 †................
  9. 00000000100EA040: 01000000 00000000 00000000 00000000 †................
  10. 00000000100EA050: 00000000 00000000 00000000 00000000 †................
  11. 00000000100EA060: 30000c00 01000000 14000000 03000001 0...............
  12. 00000000100EA070: 00160061 6d793000 0c000200 00001900 †...amy0.........
  13. 00000000100EA080: 00000300 00010017 00616e6e 6130000c †.........anna0..
  14. 00000000100EA090: 00030000 001c0000 00030000 01001800 †................
  15. 00000000100EA0A0: 736d6172 74000000 00000000 00000000 smart...........
  16. 00000000100EA0B0: 00000000 00000000 00000000 00000000 †................
  17.  
  18. ....
  19.  
  20. 00000000100EBFC0: 20202020 20202020 20202020 20202020
  21. 00000000100EBFD0: 20202020 20200000 00000000 00000000 ..........
  22. 00000000100EBFE0: 00000000 00000000 00000000 00000000 †................
  23. 00000000100EBFF0: 00000000 00000000 1f0b8d00 76006000 †............v.`.
  24.  
  25. OFFSET TABLE:
  26.  
  27. Row - Offset
  28. 2 (0x2) - 141 (0x8d)
  29. 1 (0x1) - 118 (0x76)
  30. 0 (0x0) - 96 (0x60)

  我想大家现在都清楚了,数据页中的一条条存储记录都是通过页尾的槽位指向的,具体可以参见前几篇对数据页的介绍,比如你看到页尾的:

8d00了吗?要注意,这些都是按照字节逆序来的。

  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)
  1. PAGE: (1:78)
  2.  
  3. BUFFER:
  4.  
  5. BUF @0x0000000083FD8E00
  6.  
  7. bpage = 0x0000000083ADC000 bhash = 0x0000000000000000 bpageno = (1:78)
  8. bdbid = 8 breferences = 0 bUse1 = 2495
  9. bstat = 0x1c0000b blog = 0xbbbbbbbb bnext = 0x0000000000000000
  10.  
  11. PAGE HEADER:
  12.  
  13. Page @0x0000000083ADC000
  14.  
  15. m_pageId = (1:78) m_headerVersion = 1 m_type = 1
  16. m_typeFlagBits = 0x4 m_level = 0 m_flagBits = 0x8000
  17. m_objId (AllocUnitId.idObj) = 63 m_indexId (AllocUnitId.idInd) = 256
  18. Metadata: AllocUnitId = 72057594042056704
  19. Metadata: PartitionId = 72057594041204736 Metadata: IndexId = 0
  20. Metadata: ObjectId = 341576255 m_prevPage = (0:0) m_nextPage = (0:0)
  21. pminlen = 12 m_slotCnt = 3 m_freeCnt = 8021
  22. m_freeData = 165 m_reservedCnt = 0 m_lsn = (142:102:3)
  23. m_xactReserved = 0 m_xdesId = (0:0) m_ghostRecCnt = 0
  24. m_tornBits = 0
  25.  
  26. Allocation Status
  27.  
  28. GAM (1:2) = ALLOCATED SGAM (1:3) = ALLOCATED
  29. PFS (1:1) = 0x61 MIXED_EXT ALLOCATED 50_PCT_FULL DIFF (1:6) = CHANGED
  30. ML (1:7) = NOT MIN_LOGGED
  31.  
  32. DATA:
  33.  
  34. Slot 0, Offset 0x60, Length 22, DumpStyle BYTE
  35.  
  36. Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
  37. Record Size = 22
  38. Memory Dump @0x000000000F7FC060
  39.  
  40. 0000000000000000: 30000c00 01000000 14000000 03000001 0...............
  41. 0000000000000010: 001600 6d79††††††††††††††††††††††††...amy
  42.  
  43. Slot 1, Offset 0x76, Length 23, DumpStyle BYTE
  44.  
  45. Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
  46. Record Size = 23
  47. Memory Dump @0x000000000F7FC076
  48.  
  49. 0000000000000000: 30000c00 02000000 19000000 03000001 0...............
  50. 0000000000000010: 001700 6e6e61††††††††††††††††††††††...anna
  51.  
  52. Slot 2, Offset 0x8d, Length 24, DumpStyle BYTE
  53.  
  54. Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
  55. Record Size = 24
  56. Memory Dump @0x000000000F7FC08D
  57.  
  58. 0000000000000000: 30000c00 03000000 1c000000 03000001 0...............
  59. 0000000000000010: 001800 6d617274 †††††††††††††††††††...smart
  60.  
  61. OFFSET TABLE:
  62.  
  63. Row - Offset
  64. 2 (0x2) - 141 (0x8d)
  65. 1 (0x1) - 118 (0x76)
  66. 0 (0x0) - 96 (0x60)
  67.  
  68. DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

仔细观察下上面的蓝色字体,有没有总结出各个slot槽位对应的记录内容,比如:

slot0槽位指向的记录内容:  amy =>  616d79。

slot1槽位指向的记录内容:  anna => 616e6e61。

slot2槽位指向的记录内容:  smart => 736d617274。

这里你要知道,这里都是16进制表示的,所以2个16进制对应一个字节。

二:使用WinHex修改数据

  我们大家都知道,sqlserver引擎会通过扫描slot槽位来呈现数据,就像上面的记录那样,依次扫描slot0...slot1....slot2...来呈现数据,如下图:

上面这个截图没什么稀奇的地方,大家也觉得见怪不怪的,那下面就有一个想法来了,如果我通过winHex来交换slot0和slot1的顺序,那效果会是

怎样???按照常理说,这时候引擎还是按照slot槽位依次扫描,这时候应该会将ID=2的记录先喷出来,然后再喷出ID=1,ID=3。。。事实是不是

这样子呢?好奇吧,我们来看看。。。

三:相关步骤

1.  我们知道Ctrip数据库是联机的,我们要修改它必须先脱机,然后再关掉数据页的一致性校验(这个也是数据库的保护机制,防止第三方恶意的去篡

改数据),这个应该大家都明白,如下图:

2.  从网上下载一个破解版的winhex,然后打开本地的Ctrip.mdf文件,调整winhex的编辑模式为默认的可读写,如图:

3. 我们知道一个数据页的大小是8KB=8192B,那么第78号数据页的起始位置的偏移量应该就是:78*8192=638976,然后通过快捷键

Alt+G打开偏移量列表,键入638976,如下图:

找到记录的内容之后,我们再来找槽位,槽位的开始位置在78号数据页的末尾,那怎么算呢?这个算法也很简单,offset=79*8192-1=647167。

说干就干。

当你真的找到了偏移量,是不是很兴奋呢?下面要做的就是把60和76交换一下,也就是将slot0和slot1交换,看看怎么样????

4. 交换完毕后,ctrl+s保存,然后让Ctrip数据库联机,并使用Sql语句查看下现在的效果???

当你看到这张图的时候,是不是已经疯了。。。。这样我就非常肯定的论证了,引擎真的就是通过依次扫描slot的槽位来指向记录的,如果你

大概理解了上面的操作,现在你可以修改任意数据页的数据了,只要你找得到数据页的偏移量,然后任由你发挥啦~~~~感谢感谢。。。

Sql Server之旅——第六站 使用winHex利器加深理解数据页的更多相关文章

  1. Sql Server之旅——第五站 确实不得不说的DBCC命令

    原文:Sql Server之旅--第五站 确实不得不说的DBCC命令 今天研发中心办年会,晚上就是各自部门聚餐了,我个人喜欢喝干红,在干红中你可以体味到那种酸甜苦辣...人生何尝不是这样呢???正好 ...

  2. (转)Sql Server之旅——第八站 复合索引和include索引到底有多大区别?

    索引和锁,这两个主题对我们开发工程师来说,非常的重要...只有理解了这两个主题,我们才能写出高质量的sql语句,在之前的博客中,我所说的 索引都是单列索引...当然数据库不可能只认单列索引,还有我这篇 ...

  3. Sql Server之旅——第四站 你必须知道的非聚集索引扫描

    非聚集索引,这个是大家都非常熟悉的一个东西,有时候我们由于业务原因,sql写的非常复杂,需要join很多张表,然后就泪流满面了...这时候就 有DBA或者资深的开发给你看这个猥琐的sql,通过执行计划 ...

  4. Sql Server之旅——第十站 看看DML操作对索引的影响

    我们都知道建索引是需要谨慎的,当只有利大于弊的时候才适合建,我们也知道建索引是需要维护成本的,这个维护也就在于DML操作了, 下面我们具体看看到底DML对索引都有哪些内幕.... 一:delete操作 ...

  5. Sql Server之旅——第八站 复合索引和include索引到底有多大区别?

    周末终于搬进出租房了,装了宽带....才发现没网的日子...那是一个怎样的与世隔绝呀...再也受不了那样的日子了....好了,既然网 安上去了,还得继续我的这个系列. 索引和锁,这两个主题对我们开发工 ...

  6. Sql Server之旅——第七站 为什么都说状态少的字段不能建索引

    我们在学sqlserver的时候,大多教科书和前辈们都说状态少的字段不要建索引,由此带来的开销还不如不建索引,但是这句话有多少人真的知道, 或者说有多少人真的对此有比较深刻的理解,而不是听别人道听途说 ...

  7. Sql Server之旅——第十一站 简单说说sqlserver的执行计划

    我们知道sql在底层的执行给我们上层人员开了一个窗口,那就是执行计划,有了执行计划之后,我们就清楚了那些烂sql是怎么执行的,这样 就可以方便的找到sql的缺陷和优化点. 一:执行计划生成过程 说到执 ...

  8. Sql Server之旅——第十三站 对锁的初步认识

    终于这个系列快结束了,马上又要过年了,没什么心情写博客...作为一个开发人员,锁机制也是我们程序员必须掌握的东西,很久之前 在学习锁的时候,都是教科书上怎么说,然后我怎么背,缺少一个工具让我们眼见为实 ...

  9. Sql Server之旅——第五站 确实不得不说的DBCC命令(文后附年会福利)

    今天研发中心办年会,晚上就是各自部门聚餐了,我个人喜欢喝干红,在干红中你可以体味到那种酸甜苦辣...人生何尝不是这样呢???正好 ceo从美国带了干红回来,然后我就顺道开心的过了把瘾....一个字.. ...

随机推荐

  1. 2016 大连网赛---Weak Pair(dfs+树状数组)

    题目链接 http://acm.split.hdu.edu.cn/showproblem.php?pid=5877 Problem Description You are given a rooted ...

  2. Visual C++中的一些编程小技巧

    在应用程序的任意地方实现窗体的最大化.最小化.正常窗口等功能 // 设置Windows窗体的状态void CMinWindowsDlg::SetWindowState(int nWindowSize) ...

  3. CI框架源码阅读笔记1 - 环境准备、基本术语和框架流程

    最开始使用CI框架的时候,就打算写一个CI源码阅读的笔记系列,可惜虎头蛇尾,一直没有行动.最近项目少,总算是有了一些时间去写一些东西.于是准备将之前的一些笔记和经验记录下来,一方面权作备忘,另一方面时 ...

  4. windows的IIS下的负载均衡

    来自http://www.cnblogs.com/allen0118/p/4294066.html 在大型Web应用系统中,由于请求的数据量过大以及并发的因素,导致Web系统会出现宕机的现象,解决这一 ...

  5. C#实现类似"hello $world"的格式化字符串方法

    C#自带的string.Format可以格式化字符串,但是还是不太好用,由于格式的字符占位符都是数字,当数目较多时容易混淆.其实可以扩展string的方法,让C#的字符串具备其他的方法,下面介绍一个实 ...

  6. Bootstrap源码分析之nav、collapse

    导航分析(nav): 源码文件:_navs.scss:导航模块Mixins/_nav-divider.scss:分隔线Mixins/_nav-vertical-align.scss:垂直对齐 1.只是 ...

  7. 【初窥javascript奥秘之事件机制】论“点透”与“鬼点击”

    前言 最近好好的研究了一番移动设备的点击响应速度,期间不断的被自己坑,最后搞得焦头烂额,就是现在可能还有一些问题,但是过程中感觉自己成长不少, 最后居然感觉对javascript事件机制有了更好的认识 ...

  8. sharepoint2010如何本地化WebPart的Category、WebDisplayName 和 WebDescription 属性

    在项目中经常需要实现多语言其中包括webpart的属性也需要.那么如何实现呢? 首先需要资源文件,利用资源文件实现语言的翻译,如下图: 创建好资源后,下面我们来实现webpart属性的多语言.方法代码 ...

  9. Web安全攻防-----TCP/IP安全篇

    知识点: 掌握TCP/IP的体系分层结构 掌握TCP/IP的各一层功能特点 掌握TCP/IP的数据在各层的名称 掌握TCP/IP的体系数据的封装和解封装 1.TCP/IP协议的历史 TCP/IP的起源 ...

  10. 将自己写的库上传到cocoapods(2015)

    2015年以前上传到cocoapods的方式相较于现在比较麻烦,现在用不上在此也就不提了.现在上传到cocoapods只需要简单的几步即可. 1.首先你需要有一个自我感觉写的差不多的库. 2.注册tr ...