This project covers Microsoft SQL Server (MSSQL) forensics.
Series of Articles
I have written some articles. It has especially focused on MDF file.
- MSSQL forensics (1) - MDF fundamentals
- MSSQL forensics (2) - Record Structure
- MSSQL forensics (3) - Slot Array & Deleted Record
- MSSQL forensics (4) - LOB data structure
Sample Data
Sample&simple MDF database is available. It has 1 table named pictures and the table contains several records including JPG binaries.
- 4n6ist_sample.zip (4n6ist_sample.mdf): inserted 3 records then deleted 1 record
- 4n6ist_sample2.zip (4n6ist_sample2.mdf): inserted 3 records, deleted 1 record then inserted 1 record
Program
Complied Windows binaries are available:
Source code is available at Github.
Usage
Here is descriptions of each program.
mdf_parse_pageheader
mdf_parse_pageheader parses each page header in MDF file, then output as CSV format. It is similar to DBCC IND command. The program shows some important values such as type, pminlen, slotCnt, freeCnt, and freeData. These values are useful for us to decide on which page we should focus.
Example
> mdf_parse_pageheader.exe -i 4n6ist_sample.mdf pageId,type,typeFlag,level,flag,pminlen,slotCnt,freeCnt,freeData,reservedCnt,ghostRecCnt 0,15,0,0,512,0,1,6971,1219,0,0 1,11,0,0,512,0,1,2,8188,0,0 2,8,0,0,512,90,2,6,8182,0,0 ...
mdf_parse_datapage_record
mdf_parse_datapage_record parses specific page by -p option. It is similar to DBCC PAGE command, but the script attempts to show information including deleted record. The program checks both each slot manually and slot array which is located the end of the page, then judges whether each record is deleted or not. Currently the script doesn’t parse database/table schema.
Example
> mdf_parse_datapage_record.exe -i 4n6ist_sample.mdf -p 368 -d slotCnt: 3, freeData 399, slotArray: 3, actualSlots: 3 [DELETED] Offset:298, Slot:2 000000 30 00 30 00 03 00 00 00 32 30 31 39 31 32 31 35 0.0.....20191215 000010 48 00 6f 00 72 00 73 00 65 00 73 00 20 00 20 00 H.o.r.s.e.s..... 000020 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 ................ 000030 05 00 00 02 00 55 00 65 80 50 00 49 00 58 00 4e .....U.e.P.I.X.N 000040 00 49 00 4f 00 2d 00 32 00 33 00 31 00 35 00 36 .I.O.-.2.3.1.5.6 000050 00 36 00 31 00 00 00 d3 07 00 00 00 00 08 01 00 .6.1............ 000060 00 01 00 03 00 .....
mdf_parse_LOB_LARGE
mdf_parse_LOB_LARGE parses tree structure for LOB data whose record type is 5 (LARGE_ROOT_YUKON), then saved to a file specified by -o option. The program requires page (-p option) and slot (-s option) value, which can be got by mdf_parse_datapage_record.
Example
> mdf_export_LOB_LARGE.exe -i 4n6ist_sample.mdf -p 264 -s 1 -o PIXIO-1941113.jpg Page 264, Slot 1 => Offset 6335 RecordHeader Status: 8 Length: 84 BlobId: 131137536 Type: 5 LargeRoot MaxLinks: 5 CurLinks: 1 Level: 1 Size: 215265 Page: 265 Slot: 0 RecordHeader Status: 8 Length: 452 BlobId: 131137536 Type: 2 Child MaxLinks: 501 CurLinks: 27 Level: 0 Wrote 215265 bytes
mdf_export_LOB_SMALL
mdf_export_LOB_SMALL parses LOB data whose record type is 0 (SMALL_ROOT), then display information to stdout. The program requires page (-p option) and slot (-s option) value, which can be got by mdf_parse_datapage_record.