Introduction

Disk Digger © 2010-2012 by Runtime Software LLC

75-5744 Alii Dr., Kailua Kona, HI 96740, USA
Phone (USA): 1-808-329-2202, Fax: 1-818-475-1741
Phone (Germany): +49-30-2180 1016
Email: info@runtime.org, Web: http://www.runtime.org

Runtime's Disk Digger lets you inspect and navigate any file system or on-disk structure. Details are displayed in an Internet Explorer window. Disk Digger views are driven by scripts and an integrated script interpreter. The customizable scripts determine what information and how it is displayed. The script language is Pascal, so everybody with knowledge of a higher programming language will be able to modify or create new scripts.

Over 20 Scripts

This version of Disk Digger comes with over 20 ready-to-use scripts for the following file systems:

  • NTFS
  • FAT12, FAT16, FAT32
  • EXT2FS, EXT3FS
  • XFS

These scripts show all relevant data structures, such as partition tables, boot records, and file system specific structures. The level of sophistication of those script goes to the point of you being able to retrieve individual files from the supported file systems. Disk Digger include all the script's source codes. The script editor allows you to quickly make changes to your code and test it immediately.

Write Your Own Data Recovery Software

Inside the script editor you can call the debugger and trace through your script, inspecting its flow and variables.

The Disk Digger scripts show you how to extract programmatically files from NTFS, FAT, EXT2FS, and XFS. You can use these scripts as a blueprint for customized data recoveries or forensic investigations.

With advanced programming skills you can write additional scripts for other file systems or container structures such as backup files, virtualization volumes, encrypted volumes, or surveillance disks. A rich set of build-in commands lets you access and process disks and images files. You could even develop your own data recovery software based on those scripts.

Disk Digger is the perfect tool when using a standard recovery software, such as GetDataBack, is not sufficient to accomplish your objective. You can create report scripts for data recovery or forensic purposes that no other software offers.

Software Design

Disk Digger consists of two distinguished functions:

  • A script interpreter for retrieving and formatting the desired information from the disk or image that is being inspected.
  • An Internet Explorer instance for rendering the script's output to the screen and processing user input.

The address bar of the Explorer windows tells the program the drive, sector, and view to be displayed. For example, the address http://local/partition_table/HD128:/0 tells Disk Digger to display the content of sector 0 on the first physical drive (HD128:) using the script partition table.

Scripts usually contain many links allowing the user to navigate through the file system as he would navigate a Web site.

The usage of Internet Explorer enables you to easily print your windows. You can also save the current view or all visited views into HTML documents. This facilitates documentation of, for example, forensic jobs.

See also: Installation Menu

Introduction Menu Drives Views Scripting Navigation Options Support


Installation

Do not install any software to the drive you want to recover data from!

After downloading Disk Digger run the setup.exe. The setup wizard will guide you through the installation process.

You must have Administrator rights to run this program. Right-click the program icon and select "Run as administrator".

System requirements:

  • Windows 95, Windows 98, Windows ME, Windows NT 4, Windows 2000, Windows XP, Windows Server 2003, Windows Server 2008, Windows Vista, Windows 7, or Windows 8
  • Internet Explorer 5 or above must be installed


License Agreement

License Agreement and Disclaimer

The following are the conditions under which this Runtime Software software is sold, supported and may be used. By using or registering Runtime Software software, you are agreeing to these.
This document may be augmented or superseded by conditions included with specific applications.

Neither the author(s) nor Runtime Software assume responsibility for any expense, damage or loss caused by your use of this software, however it occurs.
All the registered trademarks used herein are registered to whoever it is that owns them. This notification is given in lieu of any specific list of trademarks and their owners.

No portion of the documentation for this software or any of its attendant files may be reproduced in whole or in part in any medium or form of transmission exclusive of the archive file for the software without the express written permission of Runtime Software. You may not modify or patch the software's executable files in any way, including but not limited to decompiling, disassembling, or otherwise reverse engineering the program.

Registering this software buys you a named single-user license to use it in perpetuity, subject to the terms discussed herein. With a named single-user license you are the only user of the license, installed on one computer owned or controlled by you. If you want to have the software installed on more than one computer at the same time, you need to purchase additional licenses. If you want the software to be used by additional users, you need to purchase additional licenses. A single-user license does not permit you to make the registered software available over a network for multiple users to access, to distribute it in any form or to provide it in conjunction with any other product without the express written permission of Runtime Software. The license is not transferable to another party without written permission of Runtime Software. If you have any questions about the software license, feel free to get in touch with us.

A "Technician's License" has the same rights and restrictions as the above "named single-user license", but allows you to perform data recovery services on computers not owned or controlled by you.


Views

"Views" in Disk Digger are created by scripts in a way similar to Websites where HTML content is created with PHP scripts. At the time a view is called, e.g. by a clicking a link in a previous view, its script is executed and puts HTML code into the "result" variable. Once the script has completed, this variable is rendered by the Internet Explorer window.

Currently, Disk Digger comes with the following set of views:

View | Script name | File system | Description
Root | root.scr | none | Displays the list of used drives & images
Hex | hex.scr | none, but FS aware | Provides the hex view
Partition table | partition_table.scr | none | Shows the partition table
Dir | dir_ext2fs.scr | Ext2FS | Directory
GroupDesc | groupdesc.scr | Ext2FS | Group description
Inodes | inodes.scr | Ext2FS | Inode list
Superblock | super_ext2fs.scr | Ext2FS | Ext2FS Superblock
BootFAT | boot_fat.scr | FAT | FAT boot record
Dir | dir.scr | FAT | Directory
FAT12 | fat12.scr | FAT | 12-bit FAT
FAT16 | fat16.scr | FAT | 16-bit FAT
FAT32 | fat32.scr | FAT | 32-bit FAT
BootNT | boot_nt.scr | NTFS | NTFS boot record
Index | index.scr | NTFS | Index Allocation (NTFS directory)
MFT | mft.scr | NTFS | MFT entry
MFT list | mftlist.scr | NTFS | List of MFT entries
Dir | dir_xfs | XFS | XFS block directory
EBTree | e-bptree.scr | XFS | Extent B+Tree, BMAP
IBTree | i-bptree.scr | XFS | Inode B+Tree, IABT
Inode (XFS) | inode_xfs.scr | XFS | Inode
Inodes (XFS) | inodes_xfs.scr | XFS | Inode list
Superblock | super_xfs.scr | XFS | XFS Superblock, AGF, AGI

See also: Scripting Navigation


Script Language

Scripting

"Views" in Disk Digger are created by "scripts" in a way similar to Websites where HTML content is created with PHP scripts. At the time a view is called, e.g. by a clicking a link in a previous view, its script is executed and puts HTML code into the "result" variable. Once the script has completed, this variable is rendered by the Internet Explorer window.

Scripts are based on PASCAL, allowing you to access drives and images with all the elements available in a higher programming language. Disk Digger works with three kinds of files:

  • .SCR - Script source code
  • .PCS - Library source code
  • .PCU - Compiled SCR or PCS files

SCR files are visible from Disk Digger as "views". PCS files contain procedures that are used from other scripts. A PCS file is referenced by a "unit" declaration at the start of an SCR file. PCU files are compiled versions of source files (SCR, PCS), speeding up the processing time. In Options you can set if you want to use source files only and if you want to automatically create compiled versions.

Example:

The script partition_table.scr contains the source code of that view. partition_table.scr uses two libraries, utils and navigation. There are the files:

File name | Description
partition_table.scr | Source code of the script
partition_table.pcu | Compiled version
utils.pcs | Source code of the library utils
utils.pcu | Compiled version
navigation.pcs | Source code of the library navigation
navigation.pcu | Compiled version

Script source file (SCR) contains two constants that will cause Disk Digger to integrate the view into its menu structure:

Constant | Description
VIEWNAME | Name as it appears in the Views menu
HOTKEY | Hotkey associated with that view

Version Management

All script files must be in the same directory as the Disk Digger application (ddig.exe). Disk Digger usually tracks the versions of source and compiled files. Only changes to libraries must be compiled manually and Drive Digger must be restarted. To manually recompile all scripts click on "File->Compile all scripts".

Load and Run a Script

A script is loaded automatically when its file name is reference from another script. For example, the script partition_table is reference by an anchor in the script root.scr:

Script root.scr:

  ...
  BuildLink('partition_table', DriveList.GetDrive(i).DriveLetter, 0, DriveList.GetDrive(i).Info)
  ...

To load a script into the editor, click on File->Load script. To run a loaded script press F9. You can inspect the HTML output of the script in the box at the bottom. Clicking File->Exit will render that HTML code in the Internet Explorer window.

Debugger

Inside the script editor you can call the debugger and trace through your script, inspecting its flow and variables.

Reference - Special Functions

Function | Purpose | Example
Drive functions
function Drives(D: string): TDrive; Define a drive Drive := Drives('hd128');
Drive := Drives('c:\myimage.img');
Drive := Drives['D:');
function Drives(i: integer): TDrive; | Define a drive | Drive := Drives(128);
class TDriveList
function BuildDriveList(DriveString: string): TDriveList | Generates the DriveList | DriveList := BuildDriveList('HD128:,HD129:,C:,D:);
function DriveList.GetDrive(No: integer): TDrive; | Return a drive from the drivelist | Drive := DriveList.GetDrive(0);
function DriveList.Count: integer; | Returns number of drives in DriveList | Cnt := DriveList.Count;
class TDrive
function Drive.InfoCapaciy: string; | Capacity of the drive as string | ShowMessage(Drive.InfoCapacity);
function Drive.TotalSectors: longint; | Capacity of the drive in sectors, returns an integer. | ShowMessage(IntToStr(Drive.TotalSectors));
function Drive.TotalSectorsAsFloat: float; | Capacity of the drive in sectors, returns a float | ShowMessage(CompToStr(Drive.TotalSectorsAsString));
function Drive.ReadAsPointer(LBAStart, Count: integer; Buffer: pointer; var ErrCode: integer): boolean; Read from the drive into a buffer GetMem(Buffer, 512);
if Drive.Read(0, 1, Buffer, ErrCode) then
ShowMessage('Ok')
else
ShowMessage('Error ' + IntToStr(ErrCode));
function Drive.Read(LBAStart, Count, Error): string; Read from the drive into a string Sector := Read(0, 1, ErrCode);
WriteImage(Image, Sector);
function Drive.DriveLetter: string; | Returns the drive letter, e.g. HD128:, C:, C:\image.img | ShowMessage(Drive.DriveLetter);
procedure Drive.FirstSector; Set drive to the first sector Drive.FirstSector;
while not Drive.EndOfDrive do
begin
ShowStatus(IntToStr(Drive.CurrentSector));
WriteImage(Image, Drive.GetSector);
Drive.NextSector;
end;
procedure Drive.NextSector[(IncBy: integer)]; | Move to the next sector
function Drive.EndOfDrive: boolean; | Test if end of drive is reached
function Drive.GetSector: string; | Read one sector into a string
function Drive.CurrentSector: integer; | Determine the current sector (integer)
function Drive.CurrentSectorAsFloat: float; | Determine the current sector (float)
procedure Drive.LastSector; | Set drive to the last sector | Drive.LastSector;
procedure Drive.GotoSector(Sec: integer); | Move to a sector | Drive.GotoSector(1000);
function Drive.GetSectorAsPointer: pointer; | Read one sector into a buffer | P := Drive.GetSectorAsPointer:
function Drive.ReadSectors(NumSecs: integer): string; | Read NumSec sectors into a string | S := Drive.ReadSectors(128):
function Drive.ReadSectorsBEOF(NumSecs: integer): string; | Read NumSec sectors into a string. Same as ReadSectors but returns string shorter than 512*NumSecs if trying to read beyond EOF | S := Drive.ReadSectorsBEOF(128):
function Drive.Offset(Ofs: integer): integer; | Returns the byte at offset Ofs in the current sector | i := Drive.Offset(0);
function Drive.OffsetFloatAsString(Ofs, Len: integer): string; | Calculates a float, starting at Ofs, length Len. Then the float is converted into a string | S :=Drive.OffsetFloatAsString(8, 8);
function Drive.OffsetFloatAsString2(Ofs, Len: integer): string; | Same as Drive.OffsetFloatAsString, but includes thousand separators | S :=Drive.OffsetFloatAsString(8, 8);
function Drive.OffsetAsInt(Ofs: integer): integer; | Returns the integer at offset Ofs | I := Drive.OffsetAsInt(4);
function Drive.OffsetAsWord(Ofs: integer): integer; | Returns the word at offset Ofs | I := Drive.OffsetAsWord(2);
function Drive.OffsetAsFloat(Ofs, Len: integer): float | Returns as float, starting at Ofs, length Len | F := Drive.OffsetAsFloat(8, 5);
function Drive.OffsetAsString(Ofs, Len: integer): string; | Returns the string starting at offset Ofs, length Len | S := Drive.OffsetAsString(0, 16);
function Drive.OffsetBinAsHex(Ofs, Len: integer; Delimiter: string): string; | Returns the bytes from offset Ofs, length Len, formatted at hex. Hex numbers are separated by Delimiter | S := Drive.OffsetBinAsHex(0, 16, ' ');
function Drive.DriveKind: integer; Indicates the kind of drive:
0: Physical drive (HD128:,...)
1: Logical drive (C:,D:,...)
2: Image file (*.img, *.imc)
3: Virtual image file (*.vim)
4: Remote physcial drive 		I := Drive.DriveKind;
function Drive.Info: string; | Returns a more descriptive string for the drive, e.g. "1st hard drive 466 GB (HD128:) - ST95005620AS" | S := Drive.Info
function Drive.Partition(i: integer): TPartItem | Returns a drive's partition at index i, 0-based | Part := Drive.Partition(0);
function Drive.PartitionCount: integer; | Number of partitions on drive | I := Drive.PartitionCount;
class TPartItem
function PartItem.Info: string Descriptive string for this partition S := Drive.Partition.Info;
if Drive.Partition(1).IsExtended then
S := 'Extended ' + Drive.Partition(1).Info
else
S := 'Primary ' + Drive.Partition(1).Info;
ShowMessage(S);
function PartItem.IsExtended: booleean; | Indicates if this is a primary or extended partition
function PartItem.StartSector: float; | This partition's start sector on the drive | F := Drive.Partition(1).StartSector;
function PartItem.Sectors: float; | Length in sectors of this partition | F := Drive.Partition(1).Sectors;
function PartItem.Type: integer; | Type of this partition, e.g. NTFS | I := Drive.Partition(1).Type;
Image functions
function CreateImage(FileName: string; Compressed: boolean): integer; Create a new image file for output Image := CreateImage('c:\newimage.img', false);
Drive.FirstSector;
while not Drive.EndOfDrive do
begin
WriteImage(Image, Drive.GetSector);
Drive.NextSector;
end;
CloseImage(Image);
function WriteImage(Image: integer; Sec: string): integer; | Write a string (sector) to the image file
procedure CloseImage(Image: integer); | Close image file
GetMem(P, 1024);
//do something with P
FreeMem(P);
Memory functions
procedure GetMem(var P: pointer; MemSize: integer); | Allocate a buffer
procedure FreeMem(P: pointer); | Free a buffer
Statusline functions
procedure ShowStatus(Info: string); | Display a message in Scripter's window | ShowStatus('Current Sector' + IntToStr(Drive.CurrentSector));
procedure SetStatusRefreshRate(MS: integer); | Set the refresh rate of the status message in Millie seconds | SetStatusRefreshRate(10);
Dialogs
MessageDlg(Msg: string; DlgType; Buttons: variantarray): integer; Displays Windows' message dialog if MessageDlg('File exists. Overwrite?', mtConfirmation, [mbYes,mbNo]) = mrYes then
...
File functions
function FileExists(FileName: string): boolean; Tests if a file already exists if FileExists('c:\myimage.img') then
...
Conversion routines
function OEMToChar(s: string): string; | Convert OEM to ANSI string; | s := OEMToChar(s);
function PartTypeToString(PartType: integer): string; | Converts partition type into a string, e.g. 7 -> 'NTFS' | S := PartTypeToString(Drive.Partition(1).Type);
function PartitionGUIDToString(GUID: string): string; | Converts GPT partition GUID into a string, e.g. 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7' -> 'Windows or Linux data partition' | S := PartitionGUIDToString('EBD0A0A2-B9E5-4433-87C0-68B6B72699C7');
function CompToStr(f: float): string; Converts a float to a string after rounding S := CompToStr(10.3);
//returns string '10'
function CompToStr2(f: float): string; Same as CompToStr, but includes thousand separators S := CompToStr(10000/3);
//returns string '3333'
function CompToHex(f: float; digits: integer): string; Rounds float and converts it to a hex string with a minimal width of digit S := CompToHex(10);
//returns string '000A'
function CompToBin(f: float; digits: integer): string; Rounds float and converts it to a binary (0,1) string with a minimal width of digit. Least significant bits come first S := CompToBin(1, 64);
//returns '100000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000'
function HexToComp(s: string): float; Converts a hex string into a float f := HexToComp('a0');
//returns 160
function FmtSignificanceByte(f: float; digits: integer): string; Converts a byte number S := FmtSignificanceByte(1000000, 4);
//returns '976.6 KB'
function BinOToString(s: string; Ofs, Len: integer): string; Returns s from offset Ofs, length Len. 0-based S := BinOToString('abcd', 1, 2);
//returns string 'bc'
function BinOToWord(s: string; Ofs: integer): integer; Returns the word encoded starting at position Ofs I := BinOToWord('ABCD', 1);
//returns 17218
//ord('B') + 256*ord('C')
function BinOToInt(s: string; Ofs: integer): integer; Returns the integer encoded starting at position Ofs I := BinOToInt(#1#0#0#0, 0);
//returns 1
function BinOToFloat(s: string; Ofs, Len: integer): float; Extract the number from Ofs, Len into a float F := BinOToFloat(#1#0#0#0#0#0#0#0, 2, 5);
//returns 0
function BinOToFloatAsString(s: string; Ofs, Len: integer): integer; Same as BinOToFloat, converted to a string S := BinOToFloatAsString(#1#0#0#0#0#0#0#0, 2, 5);
//returns '0'
function BinOToByte(s: string; Ofs: integer): integer Extracts a byte at offset Ofs I := BinOToByte('ABC', 2);
//returns 67
function BinOToHex(s: string; Ofs, Len: integer; Delimiter: string): string; Extracts a string and represents it as hex S := BinOToHex('ABCD', 1, 3, '-');
//returns '66-67-68'
function BEBinOToWord(s: string; Ofs: integer): integer; Big Endian version of BinOToWord I := BEBinOToWord('ABCD', 1);
//returns 16963
//256*ord('B') + ord('C')
function BinOToInt(s: string; Ofs: integer): integer; Big Endian version of BinOToInt I := BEBinOToInt(#1#0#0#0, 0);
//returns 16777216
function BinOToFloat(s: string; Ofs, Len: integer): float; Big Endian version of BinOToFloat F := BEBinOToFloat(#1#0#0#0#0#0#0#0, 0, 2);
//returns 256
function Token(No: integer; s: string; Separator: string): string; Extracts token No. 1-based S := Token(2, 'Monday;Tuesday', ';');
//returns 'Tuesday'
function TokCount(s, Separator: string): integer; Counts the number of tokens in s I := TokCount('M,T,W,T,F,S,S', ',');
//returns 7
function ParseTag(Src, StartTag, StopTag: string; Index: integer): string; Extract tokens delimited by start/stop tags S := 'Drive HD128: 1TB'#13#10'Drive HD129: 2TB';
i := 1;
ShowMessage(ParseTag(S, 'Drive ', ':', I));
//returns 'HD128'
ShowMessage(ParseTag(S, 'Drive ', ':', I));
//returns 'HD129'
function ScanQ(Source, Search: string; Start: integer): integer; Returns the position of Search in Source beyond Start. Wildcard ? is allowed. Start is negative for ignore case I := ScanQ('table', '?ble', 1);
//returns 2
function CalculateString(Expression: string): float Compute the mathematical expression. Accepts hex prefixes $ and 0x
Supports:
+-/*^()
Ln, Exp, Abs 		F := CalculateString('5+6*2');
//returns 17
function Replace(StoDel, StoIns, s: string): string; Replace all occurrences of StoDel in s with StoIns S := Replace('ell', 'oh', 'hello');
//returns 'hoho'
function Replicate(s: string; Cnt: integer): string; Return Cnt times the string s S := Replicate('ab', 4);
//returns 'abababab'
function EnCodeStr(s: string): string; Encodes s in base64 S := EnCodeStr('abc');
ShowMessage(DeCodeStr(S));
//returns 'abc'
function DeCodeStr(s: string): string; | Decodes a base64-encoded string
Date and time routines
function FileTimeToDateTime(f: float): float; | Convert NTFS file timestamps to TDateTime | dt := FileTimeToDateTime(f);
function FileDateToDateTime(i: integer): float; | Convert DOS file timestamps to TDateTime | dt := FileDateToDateTime(i);
function LinuxTimeToDateTime(i: integer): float; | Convert Linux file timestamps to TDateTime | dt := LinuxTimeToDateTime(i);
HTML routines
function MakeTable(Params: variantarray): string; Creates HTML code for a table S := MakeTable(
[[8,4],[], [],[200,100,200,100],[], [0,2], ...8x4 elements... ]);
//8 rows, 4 columns, could get table attributes as 3rd param, e.g. width="100%"
//no flags, could be 'td-right=1', number of right-aligned columns
//no heights
//4 column widths
//no header rows
//0, 2 are header columns
//8x4 elements
function BuildLink(View, DriveLetter: string; Sector: float; Display: string): boolean; | Creates a clickable <A> tag that will load the requested sector of the requested drive into the requested view. | BuildLink('partition_table', 'HD128:', 0, '1st HD');
String routines
function iif(Condition: boolean; s1, s2: string): string; Returns s1 if condition is true, otherweise s2 S := iif(x<0, 'negative', 'positive');
ShowMessage(S);
Miscellaneous routines
function VarArrayRedim(v: variantarray; NewHighBound: integer): variantarray; Re-dimension a variant array v := VarArrayCreate([0, 5], 12);
//v has 6 elements
v := VarArrayRedim(v, 10);
//v has 11 elements
function XorSectors(Sectors: variantarray): string; | XOR sec1,sec2...secx into a string | S := XorSectors([sec1, sec2, sec3]);

Reference - Variables

Variable | Description
Storage Storage.AsInt['varname'] Storage.AsFloat['varname'] Storage.AsString['varname'] Storage.AsBin['varname'] Storage.Count | Provides a data container that is accessible over all scripts.
Drive: TDrive | Current drive
ExtendedPartitionBase: float | do not use
Sector0: float | do not use
ClusterSize: integer | do not use
DriveList: TDriveList | List of active drives
CurrentURL: string | Currently displayed URL
CurrentView: string | Currently used view

Reference - Constants

Constants | Description
DRIVE_KIND_PHYSICAL DRIVE_KIND_LOGICAL DRIVE_KIND_IMAGE DRIVE_KIND_SCHEDULE | Drive types (0,1,2,3)
maxint | Largest possible integer: 2147483647
AppDir | Application directory
TempDir | System's temp directory
mtWarning, mtError mtInformation, mtConfirmation | Message type constants
mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore, mbAll, mbNoToAll, mbYesToAll | Message dialog button constants
mrNone, mrOk, mrCancel, mrAbort, mrRetry, mrIgnore, mrYes, mrNo, mrAll, mrNoToAll, mrYesToAll | Message dialog result constants

Reference - System Functions

Abs
AnsiCompareStr
AnsiCompareText
AnsiLowerCase
AnsiUpperCase
Append
ArcTan
Assigned
AssignFile
Beep
Chdir
Chr
CloseFile
CompareStr
CompareText
Copy
Cos
CreateOleObject
Date
DateTimeToStr
DateToStr
DayOfWeek
Dec
DecodeDate
DecodeTime
Delete
EncodeDate
EncodeTime
EOF 		Exp
FilePos
FileSize
FloatToStr
Format
FormatDateTime
FormatFloat
Frac
GetActiveOleObject
High
Inc
IncMonth
InputQuery
Insert
Int
IntToHex
IntToStr
IsLeapYear
IsValidIdent
Length
Ln
Low
LowerCase
Now
Odd
Ord
Pos
Raise
Random
 ShowMessage
Sin
Sqr
Sqrt
StrToDate
StrToDateTime
StrToFloat
StrToInt
StrToIntDef
StrToTime
Time
TimeToStr
Trim
TrimLeft
TrimRight
Trunc
UpperCase
VarArrayCreate
VarArrayHighBound
VarArrayLowBound
VarIsNull
VarToStr
Write
WriteLn
ReadLn
Reset
Rewrite
Round

Reference - Basic PASCAL Syntax

begin .. end
procedure and function declarations
if .. then .. else
for .. to .. do .. step
while .. do
repeat .. until
try .. except and try .. finally blocks
case statements
array constructors (x:=[ 1, 2, 3 ];)
^ , * , / , and , + , - , or , <> , >=, <= , = , > , < , div , mod , xor , shl , shr operators
access to object properties and methods (ObjectName.SubObject.Property)
comments: // or (* *) or {}
variable declarations: var a;

See also: Views Navigation


Navigation

Disk Digger offers a variety of navigation abilities that fall into two categories, build-in controls and script-defined navigation controls.

Build-in Navigation

These controls are accessible from the "Navigation" menu:

Navigation->
Root | display the drive list as rendered by root.scr
Back | Left | show previous window
Forward | Right | show the next windows
First | Ctrl-Home | load the current drive's first sector in the current view
Prev | Ctrl-Left | load the previous sector in the current view
Jump | Ctrl-G | Jump to a different location
Next | Ctrl-Right | load the next sector in the current view
Last | Ctrl-End | load the current drive's last sector in the current view

Note that you can change the behavior of some of these navigation controls in your scripts. For example, our demo scripts regularly overwrite the number of sectors to be advanced when clicking on "Next" or "Prev".

Worth mentioning is also the "Jump" command. It allows you to quickly go to a different location on the current drive. The jump dialog accepts a wide variety of inputs. It opens showing the current sector number. You can enter a new number in 4 different ways:

Input format | Example
Decimal number | 1234
Hex number, starting with $ | $4D2
Hex number, starting with 0x | 0x4D2
Mathematical expression, build from decimal or hex numbers. Possible operators are +-*/^() Ln Exp Abs $4D2 + (8*128)
2^10

You can not only jump to sector numbers, but also to file system specific locations, such as cluster, block, and more (see below).

Script-defined Navigation

In-script navigation is realized by tagging an "address" to a link in the Internet Explorer window.

Sample address:

http://local/hex/HD128:/412572

This address will load sector 412572 on HD128: into the hex view.

The address always begins with "http://local/". It is followed by the following information:

Address element Description Example
View Script name without extension hex
partition_table
Drive or Image Drive or image where the data is retrieved from HD128:
c:\myimage.img
Sector Sector number or first sector of data being displayed 412572
0

All demo scripts contain ample navigation links, e.g. for changing the current view or for jumping to a different sector on the drive. This enables you to navigate a file system as you would navigate a Website.

The jump command can be customized by your script. Depending on the current context the following customizations are currently implemented:

Jump target | Prefix | Example | NTFS | FAT | Ext2FS | XFS
Sector | s | s 128 | x | x | x | x
Cluster | c | c $80 | x | x | x | x
Block | b | b 100+2*128 | x | x
Inode | i | i1111 | x
Mft entry | m | m 123 | x
Allocation group:Block | a | a4:1000 | x

See also: Views Scripting Search


Search

Disk Digger provides a comfortable search function. To search for certain data on the disk or image click Tools->Search.

There are four different search modes you can choose from:

Search mode Description Examples
Text Search for simple text. Wildcard ? is allowed for single character replacement.
XFS | Search for text "XFS"
X?S | Search for text "X", followed by any character, followed by "S"
Unicode text Search for simple Unicode text. May contain wildcard ? for single character replacement
$MFT | Search for Unicode text "$MFT"
?MFT | Search for any text, followed by "MFT"
Hex Search for hex code. Wildcard 3F is allowed for single character replacement
74 61 62 6C 65 | Search for hex 74-61-62-6C-65 ("table")
74 61 62 3F 65 | Search for hex 74-61-62, followed by any byte, followed by 65 ("tab?e")
Text code mix Search for a mix of simple text and characters encoded by their Ascii value, e.g. #255. Expand control code to 3 characters to avoid ambiguity with following text
#0abc | Search for Null character, followed by "abc"
#0000 | Search for Null character, followed by "0"

"Ignore case" ignores the case of the searched text. Specify "Test only at offset" to look for the search string at a certain offset only.

Once a sector containing the search string was found, it is displayed using the current view. If the current view is the Hex view, all occurrences of the search string are highlighted.

Press "Ctrl-L" to start looking for the next sector containing the search string.


Drives

Drives & Images

Besides physical and logical drives, Disk Digger accepts image files and virtual images as a data sources:

  • Physical drives
  • Logical drives
  • Image files
  • Virtual images

Physical drives are tangible media like hard drives, floppies, RAIDs, USB drives, memory sticks, flash cards, etc. In Disk Digger, they are called HD128 for the 1st drive, HD129 for the 2nd drive, etc.

Logical drives are what you usually access in Windows through a drive letter, such as C:, D:, etc.

Image files are files containing raw images of a drive. You can process an image file in the same way you can process a physical or logical drive. Image files must have been previously created, typically with Runtime's GetDataBack, DiskExplorer, or RAID Reconstructor. Disk Digger accepts whole images files and split image files. They can be uncompressed (IMG) or compressed (IMC). The format most compatible with other software is the whole and uncompressed image. Split image files consist of a set of files where the first has the extension IMG (or IMC), and the subsequent files have the extensions 001, 002, etc.

Virtual Images are short text files describing the data to be loaded. Thus, you can "glue" together different data sources. This is especially helpful if you want to recover RAID arrays. RAID Reconstructor creates virtual images that you can use here. The extension of a virtual image file is VIM. More information...

In Disk Digger, the list of used drives and images can be viewed and modified under "Tools->Manage drives & images". If you wish to add a drive to the used list, move it from the right to the left panel. You can also add image files and virtual images here. Click on "Add image" and select the image file. If you only need to add one image to the list you can also click on "File->Add image" in the main window.

See also: Virtual images


Virtual Images

Virtual Images are short text files describing the data to be loaded. Thus, you can "glue" together different data sources. This is especially helpful if you want to recover RAID arrays. RAID Reconstructor creates virtual images that you can use in Runtime's GetDataBack, DiskExplorer, Captain Nemo, and Disk Digger.

Virtual images always have the extension "vim".

You can also create your own virtual images. Virtual images are XML files with just a couple of commands ("tags"). You can put together any number of drives.

<virtualimage>

This is the root tag that encloses all other tags.

Example:

<virtualimage>
:
:(other tags)
:
</virtualimage>

<sector>

This tag sets the sector number of the virtual image to a new value. Any gaps you create by that will be filled with 0's.

Example:

<virtualimage>
:
  <sector>1000</sector>
:
</virtualimage>

<drive>

This tag describes a drive that is being used. You can also specify a certain area inside that drive.

Example:

<virtualimage>
  <drive>HD128:</drive>
</virtualimage>

This example of a virtual image uses your first hard drive (HD128:). Make sure you always append a colon to the drive's name.

Another example:

<virtualimage>
  <drive>HD128:0-999</drive>
  <drive>c:\images\myimage.img:1000-</drive>
</virtualimage>

This example maps the first 1000 sectors of HD128 to your virtual image. Sector 1000 and up of your virtual image will come from sector 1000 and up of the image file "c:\images\myimage.img". The ranges are specified by appending two numbers, separated by a dash. If you leave out the second number, the range will extend to the end of the respective drive.

Possible drives names are:

HD128:, HD129:, etc | 1st, 2nd physical drive etc.
FD0:, FD1: | 1st, 2nd floppy drive
C:, D:, etc. | Logical volume C:, D:, etc.
myfile.img, myfile.imc | Image files
NULL: | Virtual drive, delivers empty sectors. Must be followed by a range.

<loop>

Use the <loop> tag to define RAID arrays.

Example definition of a 3 drive RAID-5 with a block size of 128, backward rotation:

<virtualimage>
  <loop>
    <drive>c:\img\raid5\r1.img:</drive>
    <drive>c:\img\raid5\r2.img:</drive>
    <drive>c:\img\raid5\r3.img:</drive>
    <cycle blocksize="128">
      <stripe>1,2</stripe>
      <stripe>1,3</stripe>
      <stripe>2,3</stripe>
    </cycle>
  </loop>
</virtualimage>

After the introducing <loop> tag, specify the drives you will use in the RAID. On the syntax of the <drive> tag see the specification above.

In the <cycle> tag, define the stripes making up the RAID. Each stripe is a sequence of data taken from the previous defined drives. Define the block size as an attribute for the <cycle> tag. You would read the example above as:

  1. Take 128 sectors from the 1st drive (sectors 0-127).

  2. Take 128 sectors from the 2nd drive (sectors 0-127).

  3. Take 128 sectors from the 1st drive (sectors 128-255).

  4. Take 128 sectors from the 3rd drive (sectors 128-255).

  5. Take 128 sectors from the 2nd drive (sectors 256-383).

  6. Take 128 sectors from the 3rd drive (sectors 256-383).

This continues until the end of one drive has be reached. The smallest drive determines the size of the loop. If the smallest drive is 10000 sectors, the total size is 20000 rounded up to a full cycle, which is 20736. You can change the size of the loop in two ways:

1) Specify the number of times the loop should be repeated. You can do this by adding an attribute with the name "repeat" to the <loop> tag, e.g.: <loop repeat="27">. In the RAID example, repeating the cycle 27 times will yield 6*128*27 sectors, which is 20736.

2) Specify a range. Do this by adding the attribute "range" to the <loop> tag, e.g.: <loop range="10-20".

The "repeat" takes precedence over the implicit size as determined by the drives. The "range" takes precedence over the "repeat".

You can even define incomplete RAID-5 arrays. If, in the example above, the 3rd drive would be missing, you could describe the array like that:

<virtualimage>
  <loop>
    <drive>c:\img\raid5\r1.img:</drive>
    <drive>c:\img\raid5\r2.img:</drive>
    <cycle blocksize="128">
      <stripe>1,2</stripe>
      <stripe>1,1x2</stripe>
      <stripe>2,1x2</stripe>
    </cycle>
  </loop>
</virtualimage>

The expression 1x2 will calculate the missing sector, originally on the 3rd drive.

See also: Drives


Support

You can contact us for support:

USA

Phone | 1-808-329-2202
Fax | 1-818-475-1741
Email | support@runtime.org
Website | http://www.runtime.org

Europe (Germany)

Phone | +49-30-2180 1016
Fax | +49-30-690 88 444
Email | support_europe@runtime.org
Website | http://www.runtime.org

If you have any questions related to the use of this software, please call us or send us an email.

See also: Troubleshooting


Troubleshooting

These are the most common warnings or errors you might run into:

Error message | Description
Access denied This message is displayed if you are trying to
  • open a file that is already in exclusive use by another process or
  • open a file in read/write mode that is write-protected.
COMCTRL32 outdated | You should update your Internet Explorer to a newer version.
DRV16 not found | Under Windows 95, 98, ME this file is needed. Re-install this program.
No drives show up in Root view | You must run Disk Digger with administrator rights. Right-click the program icon and select "Run as administrator".
I/O Error The drive you are trying to read has "bad sectors". You should consider to stop working as this drive is physically damaged.
If it is a USB drive, you should attach it directly to the motherboard. Consider making an image.

If you get a runtime error, please submit a screenshot to: support@runtime.org.

See also: Support


Menu Structure

File-> |  |
 | Add image | add an image to the list of available drives
 | Load script | load the currently displayed script into the editor
 | Compile all scripts | recompile all scripts
 | Save page | save the current view into an HTML document
 | Save all pages | save all visited views into HTML documents
 | Print | print the current window
 | Exit | quit this program
Navigation-> |  |
 | Root | display the drive list as rendered by root.scr
 | Back | show previous window
 | Forward | show the next windows
 | First | load the current drive's first sector in the current view
 | Prev | load the previous sector in the current view
 | Jump | Jump to a different location
 | Next | load the next sector in the current view
 | Last | load the current drive's last sector in the current view
Views-> |  |
 | Hex | display sector in hex
 | Partition table | display sector as partition table
 | Dir | Ext2FS: show as directory
 | GroupDesc | Ext2FS: show as group description
 | Inodes | Ext2FS: show as inode list
 | Superblock | Ext2FS: show as superblock
 | BootFAT | FAT: show as FAT boot record
 | Dir | FAT: show as FAT directory
 | FAT12 | FAT: show as FAT12 file allocation table
 | FAT16 | FAT: show as FAT16 file allocation table
 | FAT32 | FAT: show as FAT32 file allocation table
 | BootNT | NTFS: show as NTFS boot record
 | Index | NTFS: show as NTFS directory (index entry list)
 | MFT | NTFS: show as Master File Table record
 | MFT list | NTFS: show as Master File Table record list
 | Dir | XFS: show as XFS directory
 | EBTree | XFS: show as data extent B+Tree
 | IBTree | XFS: show as inode B+Tree
 | Inode (XFS) | XFS: show as individual inode
 | Inodes (XFS) | XFS: show as inode list
 | Superblock | XFS: show as XFS superblock
Tools-> |  |
 | Search | search for occurrences of specified data
 | Search again | continue last search
 | Manage drives & images | Manage the list of available drives and images
 | Edit script variables | View or edit current script variables (Storage)
 | Options | change program settings
Help-> |  |
 | Content | call the integrated help (this)
 | About | displays copyright, license and version information


Options

The Options are viewed and modified in the file DDIG.INI. Click on "Tools->Options" to load this file into the editor.

The DDIG.INI is organized in section and each section can have several keys. The keys can have values.

Script editor

Show view as source: can be empty, All, or a script file name. Setting this key will cause the script to open in the script editor instead of executing it. Default is empty.

Script compilation

Use SCR files only: will call script source file even if a valid compiled version of that script exists. Can be Yes or No. Default is No.
Save compiled scripts: will save compiled scripts automatically. Can be Yes or No. Default is Yes.
Variables must be declared before use: when "yes", all used variables must be declared. Default is Yes.

Script variables

Used drives & images: this is the used drives list. You can modify that list here or in "Tools->Manage drives & images".

Key/Value pairs defined in this section will be save in the script variable Storage and can be retrieved from any script.