mssql_4n6

This project covers Microsoft SQL Server (MSSQL) forensics.

Series of Articles

I have written some articles. It has especially focused on MDF file.

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.