前言
undrop是一款针对mysql innodb的数据恢复工具,通过扫描文件或磁盘设备,然后解析innodb数据页进而恢复丢失的数据,对于drop、truncate以及文件损坏都很有帮助。本文介绍drop操作后表结构的恢复过程。
innodb数据字典介绍
在做恢复演示之前,首先插播一段innodb数据字典的介绍。
innodb数据字典存储在系统表空间,主要是用于记录innodb核心的对象信息,比如表、索引、字段等。字典的本质是REDUNDANT行格式的innodb表,并且对用户不可见。
为了便于用户查看,innodb提供了一系列的字典视图,视图提供的信息和字典表完全相同,这一部分内容我们可以在information_schema中找到。如下,
mysql> use information_schema -A; Database changed mysql> show tables where Tables_in_information_schema like '%innodb_sys%'; +------------------------------+ | Tables_in_information_schema | +------------------------------+ | INNODB_SYS_DATAFILES | | INNODB_SYS_VIRTUAL | | INNODB_SYS_INDEXES | | INNODB_SYS_TABLES | | INNODB_SYS_FIELDS | | INNODB_SYS_TABLESPACES | | INNODB_SYS_FOREIGN_COLS | | INNODB_SYS_COLUMNS | | INNODB_SYS_FOREIGN | | INNODB_SYS_TABLESTATS | +------------------------------+ 10 rows in set (0.00 sec)
一、mysql
题目链接:https://adworld.xctf.org.cn/task/task_list?type=misc&number=1&grade=1&page=5
题目描述:我们在Mysql数据库中存放了flag,但是黑客已经把它删除了。你能找回来flag吗?
二、答题步骤
1.下载附件
发现mysql和sql脚本
2.解题方法
2.1 strings解法
strings ib_logfile0 | grep "flag"
发现flag:71e55075163d5c6410c0d9eae499c977
2.2 Undrop for InnoDB解法
2.2.1 安装
undrop-for-innodb 在github上有,网址为:https://github.com/twindb/undrop-for-innodb
执行命令
sudo apt install -y make gcc flex bison
执行make安装:
make
到这里部署过程就结束了,这里介绍下几个重要的文件及目录:
dictionary目录。存放字典sql脚本,用于恢复表结构的几张核心字典表的DDL语句
sakila目录。测试schema
stream_parser。可执行文件,用于扫描文件或者磁盘设备,目的是找出符合innodb格式的数据页,按照index_id进行组织
c_parser。可执行文件,用于解析innodb数据页,获取行记录
sys_parser。可执行文件,通过字典表记录恢复目标表的表结构
2.2.2 还原必要条件
一份ibdata1数据文件,一份要恢复的数据库的表结构
1.表结构
在structure.sql中看到了表的结构:
CREATE TABLE `user` ( `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL, `password` varchar(32) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
2.ibdata1数据文件
2.2.3 解析数据文件
./stream_parser -f 01/ibdata1
解析完成后,可以看到同目录下生成一个pages-ibdata1目录,其中包含两个子目录,一个是包含按索引排序的数据页目录,另一个是包含相关类型的数据目录:
我们下面将主要关注的是第一个子目录即索引好的数据页目录,因为我们要恢复的数据就在里面,其中第一个页文件(0000000000000001.page)里包含所有数据库的表信息和相关的表索引信息,类似一个数据字典,可以使用项目提供的一个脚本recover_dictionary.sh将其内容放到一个test数据库里详细的查看。
2.2.4 解析页文件
既然第一个页文件包含所有数据库表的索引信息,我们就需要先解析它,以模拟mysql查询数据的过程,最终才能找到要恢复的数据。c_parser工具可以用来解析页文件,不过需要提供该页文件的一个内部结构(表结构)。
项目根目录下有个dictionary目录,里面就包含数据字典用到相关表结构,如用来解析第一个页文件的表结构在SYS_TABLES.sql文件
./c_parser -4Df pages-ibdata1/FIL_PAGE_INDEX/0000000000000001.page -t dictionary/SYS_TABLES.sql | grep ctf
该命令使用c_parser工具解析数据库表索引信息并过滤出我们想要恢复的有关ctf的文件
我们看到 user这个表的索引值为 13,通过这个索引值,再到另外一张表去查询该user表所有的索引信息
该表的结构在"dictionary/SYS_INDEXES.sql"文件中可以看到,而此表对应的数据页文件是第三个数据页0000000000000003.page
./c_parser -4Df pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page -t dictionary/SYS_INDEXES.sql | grep 13
这里找到一条user 的索引信息,其在mysql 存储中的索引值为 15,此索引值编号对应的数据页文件中,即存储了该索引的全部数据
此处我们选择的是主键索引对应的数据页文件进行解析(另外一个索引键应该也可以,只不过方法可能需要有所区别),终于顺利解析见到了激动人心的数据:
./c_parser -5f pages-ibdata1/FIL_PAGE_INDEX/0000000000000015.page -t 01/structure.sql | more
发现flag:71e55075163d5c6410c0d9eae499c977
总结
mysql
strings
Undrop for InnoDB