Introduction

RAID Reconstructor © 2003-2020 by Runtime Software LLC

Phone (USA): +1-888-777-6960, Fax: +1-818-475-1741
Phone (Germany): +49-30-2180 1016
Email: info@runtime.org , Web: http://www.runtime.org

Runtime's RAID Reconstructor is a tool for both, destriping and analyzing unknown RAID arrays. RAID Reconstructor is the the only product on the market that is able to determine unknown RAID parameters, such as start sector, block size, rotation and drive order. Simply enter the RAID type (RAID-0 or RAID-5) and your drive fragments. After clicking a button a couple of times, RAID Reconstructor will come up with the RAID parameters. The only thing left to do is to mount this RAID structure in Captain Nemo or GetDataBack and copy your files. If your parameters are not found with the first try, tweaking some options might do the job. Do not hesitate to email our support at support@runtime.org.

Runtime's RAID Reconstructor will help you to recover data from a broken

  • RAID Level 5 Array consisting of 3 to 16 drives
  • RAID Level 0 Array (Striping) consisting of 2 to 16 drives

Even if you do not know the RAID parameters, such as start sector, drive order, block size and direction of rotation, RAID Reconstructor will analyze your drives and determine the correct values. You will then be able to create a copy of the reconstructed RAID in a virtual image, an image file or on a physical drive. Once you created an image you can mount it with Captain Nemo or use it for further data recovery processing with Runtime's GetDataBack. If you create the image on another physical drive, you can process it with Captain Nemo or GetDataBack too or you might even be able to directly boot from it.

RAID Reconstructor is read-only. It will not try to "fix" your RAID. It will merely create a copy of your RAID at another location. It will collect sector by sector from each single drive involved and write these sectors in the correct order to the designated destination. This process is also called "destriping".

Possible destinations for the destriping process are:

  • Virtual image: RAID Reconstructor does not write an actual image. It merely creates a small text file ("vim" file) describing the structure of the RAID. If the file system damage is minimal you can simply mount the "vim" file in Captain Nemo and copy your data. Otherwise the "vim" file should be loaded into GetDataBack in order to complete the recovery. Creating a "vim" file is the recommended method.
  • Image: RAID Reconstructor writes an image into a file or a set of files. This image can then be mounted with Captain Nemo or scanned by GetDataBack.
  • Physical drive: RAID Reconstructor writes an image directly to a disk. If the file system did not have too much damage, your operating system will be able to read the drive and access its data. If not, try to mount the drive with Captain Nemo or scan the drive with GetDataBack in order to retrieve the files.

Because one drive is redundant in RAID-5, it is sufficient to have one less than the original number of drives (N) in the array. RAID Reconstructor can recalculate the original data from the N-1 drives. For a RAID-0 (striped) array you will need all drives.

The RAID Reconstructor will recover both, hardware and software RAIDs.

IMPORTANT NOTE: DO NOT WRITE ANYTHING ONTO THE DRIVES YOU ARE RECONSTRUCTING. THIS INCLUDES THIS SOFTWARE, ANY OTHER TOOLS, FILES OR PROGRAMS.

Check out our installation hints.

There are few easy steps to follow:

(1)

Select the RAID type and number of drives

  • Select the RAID type you want recover. Supported are RAID-5 and RAID-0 (striping).
  • Enter the number of drives in the original RAID array. For RAID-5 this number includes the parity drive.

Example: RAID-5 array consisting of 3 drives.

(2)

List the drives or images to be analyzed

  • Enter the drives, the array consisted of. You can enter either a physical drive or an image file for each component. Right-click the input field to choose from a list. If you are using physical drive names, these drives must be accessible as individual drives through the BIOS. You can use image files instead of physical drives if you created these images earlier using GetDataBack or DiskExplorer. NOTE: If there are bad sectors on a physical drive you should always create an image first.

Example: RAID-5 array consisting of 3 drives, hooked up to your computer as individual physical drives HD129:, HD130:, HD131:

Example: RAID-5 array consisting of 3 image files, previously created on your local drive C:\img as drive1.img, drive2.img, and drive3.img.

You can also mix physical drives and image files.

(3)

Open the drives

Click "Open drives" and make sure the correct capacities are shown on the right side. Also, the total capacity of the RAID should be shown on the bottom:

NOTE: For RAID-5 it is possible to enter one drive less than the original array size. If you need to do this you would still set the number of drives to 3 in the example above, but leave one drive entry empty.

(4)

Analyze the RAID components and determine the correct drive order, block size and direction of rotation.

This function is the brain of RAID Reconstructor. If you know the correct parameters you can enter them here and skip the analysis, going directly to (5) Copy. Otherwise click "Analyze" and start the analysis wizard.

The Analysis Wizard

The wizard's first screen asks how you want the analysis to proceed. Select "Managed Auto (2020)". This will perform a pre-test in order to eliminate unlikely combinations. If you want to skip that pre-test and test all possible settings, select "Manual". If you want to run the pre-test and do not wish to review the parameters, select "Auto". "Managed Auto (Legacy)" mimics the pre-test used in previous versions of RAID Reconstructor.

Click "Next".

RAID Reconstructor is now going to perform the pre-test, which will take a couple of minutes. Upon completions the wizard will present you the following screen:

This screen shows the combinations that will be probed.

  • Start Sectors: Usually one or two possible start sectors will be probed. If you know your RAID's start sector, enter it here. Hardware RAIDs usually have a start sector of 0. However, other values are possible, e.g. 128. Windows software RAIDs start at the start of the partition containing the RAID fragment, e.g. 63.
  • Block sizes: Please refer to your RAID controller's manual to see which block sizes are actually supported by the controller. The most common values are already visible by default. If necessary, you can enter more customized block sizes. A block size is always a power of 2 (16, 32, 64,...). If you ran the pre-test, most likely only one parameter is checked.
  • Parity rotation: (RAID-5 only) The Parity rotation won't be found in any manual. For hardware arrays you should have at least the "Forward" and the "Backward" rotation checked. Windows' "Dynamic Disks" use the "Backward (Dynamic Disk)" rotation, so make sure you have this checked if you have a Windows Dynamic Disk set.
  • Number sectors: Determines how many sectors on your RAID are actually probed. The default of 100000 is usually sufficient, but if you entered a large customized block size you might need to increase this value to, for example, 1000000 or 10000000.
  • Drive order: When "Known" is unchecked, all permutations of the drive order will be tested. In our example with drive1.img, drive2.img, and drive3.img, this will be the combinations (1,2,3), (1,3,2), (2,1,3),(2,3,1), (3,1,2), (3,2,1). If checked, only the drive order as listed in (2), as well as its reverse, will be tested, (1,2,3) and (3,2,1).

Click "Next". Depending on the number of drives, the number of combinations to check and the number of sectors to probe the analysis can last a few seconds or several hours.

When done you will be presented a list of drive parameters with the most probable one colored in red:

Usually you will choose the recommended first entry.

Interpretation of the data:

In the example above you can see a 3-line entry for possible permutations of the following parameters:

  • Start sector, 0 was probed.

  • Drive order, possible are (1-2-3), (1-3-2), (2-1-3), (2-3-1), (3-1-2) or (3-2-1), totaling 6 possible combinations.

  • Block size, possible (chosen before) is 128, totaling 1 possible combination.

  • Parity rotation, possible are forward, backward and backward-dynamic, totaling 3 possible combinations (RAID-5 only).

The list is showing no more than 10 combinations for each start sector. These 10 combinations were found to be the most likely ones. All others had been discarded.

Each combination is checked if the resulting data "make sense". Each evaluation is given a value, called "entropy". The smaller this value is the more likely the entry represents the correct RAID parameters. The value of the best (first) entry should be at least 20% smaller than any other entry for a given start sector. If there is no such entry you will not get the recommendation above, but the warning "THIS RESULT IS NOT SIGNIFICANT!". If you get this message, most likely something is wrong.

Additional information is provided if there was a file system on the broken RAID. Just below the entropy you can see an "OS:" followed by a number. RAID Reconstructor tries to parse the master boot record found in RAID sector 0. Depending on the integrity of the file system for the given combination it assigns two digits. They have the following meaning: The left digit is the number of partitions found. The right digits is the number of partitions that actually point to a valid file system boot record.

Note: The information above is only provided if the RAID in question is a hardware RAID.

Choose the desired entry (most probably the first one) and click Finish. This copies the selected parameters into the main screen.

If you have a significantly small entropy (compared to others) and a high OS:xx value as in the example above, there is usually no doubt that this combination is the one you are looking for. If not you must look closer. If there are several combinations with almost the same values you might redo the analysis with a higher number of sample sectors (see above). You might also evaluate the "Start sector of the RAID" and run the XOR test tool. If you still do not get significant results you will have to determine the right ones with try and error: create a Virtual Image, check if you get your data with Captain Nemo or GetDataBack, try the next combination. If you still do not get your data you can order our RaidProbe service and we will determine the parameters for you.

(5)

Copy the RAID

Now you are ready to copy the RAID into a virtual image, another image file or another drive. If you choose "image file" or "drive", the destination must be large enough to hold the whole RAID. We recommend you choose the "virtual image". This is just a small text file that you will mount with Captain Nemo or load into GetDataBack in order to complete your recovery.

Alternative 1) Copy To A Virtual Image

Specify the name of the virtual image. Click on the button to the right of this field to open the file dialog and enter a virtual image name, such as "c:\img\raid.vim". The name must have the extension "vim".

Click "Copy". It takes less than a second to write the virtual image.

Alternative 2) Copy To an Image

Specify the destination in the field "Destination file". Click on the button to the right of this field to open the file dialog. Enter an image file name, such as "c:\img\raid.img".

The recommended file name extension is ".img", which will create a regular image file. A ".imc" extension will create a compressed image file. If you check the "Multi file" box the created image file be split into several files of 650 MB each. This might be necessary for file systems that do not support large file, such as FAT32.

Click "Copy". The RAID now gets reconstructed. This can take a while.

If any errors are encountered, messages are written into a file called "<program path>\log<n>.txt", where "<program path>" is the directory the RAID Reconstructor is located in and "<n>" is a number. From the main windows you can later check these messages by clicking Tools->View Log on the menu bar.

Alternative 3) Copy To a Physical Disk

IMPORTANT NOTE: DO NOT USE ANY OF THE SOURCE DRIVES AS A "TARGET". IF YOU COPY TO A PHYSICAL DRIVE, ALL DATA ON IT WILL BE DESTROYED. BE SURE YOU CHOOSE THE CORRECT DRIVE.

Specify the destination in the field "Destination disk". Click on the combo box to select a drive from a list. You will pick a physical drive name, such as "HD129:".

Offset Sector: When copying to a physical drive, you can specify an offset sector where the transfer begins. For example, choosing a value of 63 will cause the first sector of the reconstructed image to be copied to sector 63 of the destination disk, the second sector to sector 64, etc.

Skip: Number of sectors not to copy from source.

Click "Copy". Read and acknowledge the warning. The RAID now gets reconstructed. This can take a while.

If any errors are encountered, messages are written into a file called "<program path>\log<n>.txt", where "<program path>" is the directory the RAID Reconstructor is located in and "<n>" is a number. From the main windows you can later check these messages by clicking Tools->View Log on the menu bar.

(6)

What's next?

If there was little or no file system damage to your RAID, we recommend you try to mount the created virtual image, image or drive with Captain Nemo. Download a copy of Captain Nemo here: http://www.runtime.org/nemopro.zip.

If you are unable to mount the image with Captain Nemo, obtain a copy of GetDataBack at http://www.runtime.org/gdbprosetup.exe and feed it with the created virtual image, image or drive. For more information see GetDataBack's documentation.

If you copied the RAID to another drive you need to reboot your computer. If you are lucky this drive can be read from your OS without further problems.

If you have any questions about this software, contact our support!

If you need information about licensing this software click here.

See also:

  • Example 1 - RAID-5 with 3 drives on a HP 454
  • Example 2 - RAID-5 with 3 drives on a HP 454, 1 drive defect
  • Example 3 - RAID-5 with 4 drives on a Dynamic Disk set
  • Example 4 - RAID-0 (Striping) on a HP 454
  • Example 5 - RAID-5 on Iomega StorCenter IX4-200D

Introduction Entropy Test XOR Test RAID Calculator Creating an Image File Examples RaidProbe Support Drives


Installation

Do not install the RAID Reconstructor to the drive(s) you want to recover! It is strongly recommended to proceed as follows:

Install the program to a computer, which doesn't have any problems. If you have a choice, choose the computer which has the most RAM and is the fastest. Attach the drives you want to rebuild the RAID from as additional drives to this machine. You will need a controller card capable of handling several drives. Each drive must be individually accessible. If your RAID controller passes the access to individual drives through to the operating system, you can use that controller for our purpose. If it doesn't, get another non-RAID controller.

An alternative to the use of the drives is the use of image files. You would have to add one drive at a time, make the image, remove the drive, add the next drive, make the image etc. until you have images for each RAID component. Of course, you will need sufficient space to store these image files. If any of your RAID drives is having physical problems, we strongly recommend the creation of images before continuing with the recovery.

After downloading the RAID Reconstructor run the raidsetup.exe. The setup wizard will guide you through the installation process.

System Requirements: 4 GB RAM,
Windows Server 2008, 2012, Vista, Windows 7, Windows 8, Windows 10, 32 or 64-bit

See also: System requirements, License


System Requirements

  • 4 GB RAM
  • Windows Server 2008, 2012, 2016, Vista, Windows 7, Windows 8, Windows 10, 32 or 64-bit
  • One problem-free hard disk to boot from
  • Disk controller card capable of handling all the drives in your RAID individually

See also: Installation, License


License

Benefits

Licensing the software will enable you to copy the RAID to a virtual image, a file image or physical drive. Licensed users will receive free updates for the lifetime of the software. There won't be any recurring fees.

How to buy

Buy a license online on our website http://www.runtime.org and get the license key immediately. You can pay with credit card or PayPal.

If you prefer not to order online give us a call at 1-888-777-6960 (USA) or +49-30-2180 1016 (Germany).

Entering the License Key

When entering the license make sure you enter both, the name and the license key, exactly as spelled in the registration email Runtime sent to you. Name and key are related and only entering both will successfully register RAID Reconstructor. We recommend to copy and paste the information from the registration email.


License Agreement

License Agreement and Disclaimer

The following are the conditions under which 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.

If you register software by Runtime Software, we will assume that you are doing so having tested the shareware version and ascertained that it's suitable for your hardware and requirements. We cannot provide refunds for shareware registration if you subsequently change your mind.

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.

If you have downloaded this software or had it given to you on disk to try out, you are allowed to use the limited version of the software for free, in order to use the full version you have to register the software immediately.

You may distribute the software (on CD-ROMs, Books, Catalogs, Internet etc.) as long as you follow each and every one of the following:

1. You distribute only exact, unmodified copies of the original unregistered shareware version of the software incl. the DISCLAIMER.
2. You do not monetarily charge or otherwise request any compensation for any copy, however made, without prior permission from Runtime Software.
3. You include the phrase "Copyright by Runtime Software" with any copy of the software.

See also: License


XOR Test

The XOR test verifies the checksum over a drive set. For example, if you have a set of 3 drives it calculates

Drive1_Sector0    XOR    Drive2_Sector0    XOR    Drive3_Sector0
Drive1_Sector1    XOR    Drive2_Sector1    XOR    Drive3_Sector1
:
Drive1_SectorLast XOR    Drive2_SectorLast XOR    Drive3_SectorLast

The checksum must be 0 if the given drive set is a RAID-5.

Clicking Tools->XOR test brings up a window that allows you to perform some tests on a given set of drives.

Click on the Start button and after some seconds you will see a window similar to this:

Interpretation of the data

Each sector is represented by one pixel.

The "Visible area" field tells you the region on the drives you are currently looking at. The first pixel in the top left position represents the checksum of sector 0 over all three drives. The last pixel in the bottom right position represents the checksum of sector 96989 over all three drives. The percentage (0-1%) indicates the location of the visible area within the whole scope of the drives. If you wish to inspect another area you can scroll the window by clicking on the vertical scrollbar.

Each sector is colored in one of three possible ways:

: the checksum of XOR over all drives is not 0 for this sector. This sector does not meet the requirements of RAID-5.

: the checksum of XOR over all drives is 0 for this sector. This sector meets the requirements of RAID-5. In addition, the sectors involved are non-trivial (non-zero), therefore this is a very strong indication that this sector indeed belongs to a RAID-5.

: the checksum of XOR over all drives is 0 for this sector and therefore meets the requirements of RAID-5. However, the sectors involved are trivial, meaning they contain zeros only. The XOR checksums of zero-sectors are zeros. Therefore, sectors marked as ambiguous should be seen in context.

When moving the mouse over the graphic, the field "Current sector" indicates the corresponding sector number and its XOR value.

It is possible to zoom in the picture. Just click on [image]. To zoom out click on [image]. The "Pixel/Sector" value to the right of these icons tell you the current magnification.

The picture above proves that the drive set in question is indeed a RAID-5 array, probably beginning at sector 0. Let's inspect the beginning of the RAID in greater detail. Click on Zoom-in seven times until the pixel/sector ratio is 64:1.

You can see that there is just one sector failing the XOR test, sector 0 that usually contains the partition table. You might be tempted to set the "Start sector of the RAID" (in the main screen) to 1, but there are two reasons to set it to 0: First, it's a hardware RAID we are looking at and hardware RAIDs usually do not store administrative information on the drive but on the controller card. Second, 1 would be an unusual number. In software RAIDs you normally have multiples of 63 which is the number of sectors per track. Windows' "Dynamic Disk" RAIDs begin at sector 63. Other software RAIDs might have a whole partition containing administrative information and the RAID area beginning after that.

Partition tables & boot sectors

This window displays all sectors that have a boot signature (0xAA55) at offset 510. If the sector in question contains a valid partition table or boot sector its content is displayed.

In the example above you see:

A partition table found at sector 0 on image d:\raido\raido2.img. It contains an NTFS partition pointing to sector 63

A NTFS boot record at sector 31 on image d:\raido\raido1.img.

Obviously, the NTFS boot sector is the one described by the partition table. It is found on another drive at sector 31 instead of 63. This is a strong indication that these sectors are already part of a RAID-5, with a block size of 32 sectors or below.

See also:

  • Example 3 - RAID-5 with 4 drives on a Dynamic Disk set
  • Example 5 - RAID-5 on Iomega StorCenter IX4-200D

Introduction Entropy Test XOR Test RAID Calculator Creating an Image File Examples RaidProbe Support Drives


Entropy Test

Entropy is a measurement of the randomness of data. Highly repetitive data has a low entropy value close to 0, completely random data has an entropy of 1. Read more about the theory here.

RAID Reconstructor makes use of entropy values in order to find the RAID parameters. The Entropy test displays the entropy of the data of each sector.

We load 3 RAID-5 drives in the main screen and click Tools->Entropy. Then we click on Start in the lower right corner.

The x-axis represents the sectors defined in "Sample sectors", 0-10,000. The y-axis represents the entropy of the data of a sector. The graphs for the 3 drives are drawn over each other in different colors. First drive drawn is Drive 1 (red), Drive 2 (green), Drive 3 (yellow). Move left (down) with the "L" button, right (up) with the "R" button. When pressing "L" or "R", the sector numbers shift by the value set in "Shift", 1,000,000. You can zoom in and out, or reset. As the last drawn drive, Drive 3 (yellow), overlaps the other drives, you can hide a drive by un-checking its checkbox to the right of the graph.

Let's move right to sector 500,000 to 510,000, and zoom in:

The stripes we see are the RAID members' parity blocks. Those have a higher entropy because the result of an XOR operation usually has a higher entropy than the underlying values.

Even if we know nothing about the RAID yet, we immediately can make lots of amazing measurements:

  • Block size is 128 sectors
  • Period is 384 sectors
  • Number of drives is Period/Block size = 3
  • Order of drives is ...2-1-3-2-1-3....
  • A multiple (by 128) of the Start sector is 507,008
  • We see all drive are present, otherwise there would be a gap

The ability to visualize the entropy of the RAID drives is a powerful tool. You do not only see the parity, you can also guess the kind of underlying data. High-entropy sectors often belong to compressed image files (JPG). Low entropy sectors often indicate empty or highly redundant data.

See also:

  • XOR Test
  • Example 5 - RAID-5 on Iomega StorCenter IX4-200D

Introduction Entropy Test XOR Test RAID Calculator Creating an Image File Examples RaidProbe Support Drives


RAID Calculator

The RAID Calculator lets you map sectors between the RAID and its individual drives. For example if you want to know which sector on which individual member drive hosts sector 111 of a 3-drive backward RAID-5 with a block size of 128, you can find out like that:

In RAID Topology enter the RAID parameters: RAID-5, backward, 3 drives, start sector at 0, block size 128. Make sure the direction is "Global >> Local". Type "111" into the field for the Global sector. The right-hand side shows you the result: Global RAID sector 111 resides on local Drive1, sector 111.

You can reverse the direction and find out which global sector originates from a given local sector. Type "2" and "111" into the field for the Local sector. The left-hand side shows you the result, 239, which is to be expected as the first 128 sectors are on drive 1 and the next 111 on drive 2, resulting in 239.

Now try drive 3, sector 111:

As determined by the RAID topology, sector 111 on drive 3 is in a parity block and as such can not be translated into a global sector. The left-hand side signals this with "PARITY DRIVE".

Blocks, Stripes, and Cycles

Please note our terminology regarding "blocks", "stripes", and "cycles". The above defined RAID has the following characteristics:

In our example, one block consists of 128 sectors. One stripe are one block taken from each drive at the same position. Two of these blocks contain data, one is parity. One cycle is made of three stripes, which is the period it takes for the parity to make one full rotation.

Supported RAID types

The RAID Calculator supports the following RAID types:

  • RAID-0, striped array without redundancy
  • RAID-5, redundant array with 1 parity drive
  • RAID-6, redundant array with 2 parity drives
  • RAID-5 (HP), proprietary RAID scheme widely used by HP/Compaq RAID controllers

Supported Rotations

The directions of the rotation relates to the movement of the parity drive from one stripe to the next stripe within one cycle.

  • Backward (aka left-asymmetric):
    Backward
    Example: RAID-5, 3 drives, block size 128
    Local drive
    sector *) \     		Drive 1 Drive 2 Drive 3 Cycle Stripe
    0-127 | B1 **) | B2 | P | 0 | 0
    128-255 | B3 | P | B4 | 1
    256-383 | P | B5 | B6 | 2
    384-511 | B7 | B8 | P | 1 | 0
    512-639 | B9 | P | B10 | 1
    640-767 | P | B11 | B12 | 2
    : : : : : :
    *) Sectors, cycles and stripes are 0-based,
    blocks and drives are 1-based
    **) Blocks B1, B2, B3, ... are data in the
    1st 128 global sectors (0-127),
    2nd 128 global sectors (128-255),
    3rd 128 global sectors (256-383), etc.
    P is parity for the blocks within the same stripe.

    The name originates from the parity drive rotating backward (left) with each stripe until the start of a new cycle.

    This is a very common rotation scheme used by many hardware RAID controllers.

  • Back. dyn (aka left-symmetric):
    Backward dynamic
    Example: RAID-5, 3 drives, block size 128
    Local drive
    sector *) \     		Drive 1 Drive 2 Drive 3 Cycle Stripe
    0-127 | B1 **) | B2 | P | 0 | 0
    128-255 | B4 | P | B3 | 1
    256-383 | P | B5 | B6 | 2
    384-511 | B7 | B8 | P | 1 | 0
    512-639 | B10 | P | B9 | 1
    640-767 | P | B11 | B12 | 2
    : : : : : :
    *) Sectors, cycles and stripes are 0-based,
    blocks and drives are 1-based
    **) Blocks B1, B2, B3, ... are data in the
    1st 128 global sectors (0-127),
    2nd 128 global sectors (128-255),
    3rd 128 global sectors (256-383), etc.
    P is parity for the blocks within the same stripe.

    As with the backward rotation, the backward dynamic rotation gets its name from the parity drive rotating backward (left) with each stripe until the start of a new cycle. It is very similar to backward, only stripe 1 arranges the blocks differently. The block to the right of parity P is the block with that stripe's lowest number, while in backward the lowest numbered block is always the first block. The blocks start to the right of parity P, incrementing by 1 with each block, rolling over to the first block and continuing until reaching parity P from the left side. Some people call this left-symmetric.

    We call it backward dynamic because we first encountered this rotation scheme when examining Windows software RAID-5s that were created with dynamic disks partitioning. This rotation scheme is a very common and used by most software RAID-5s, under Windows and Linux.

  • Forward (aka right-asymmetric)
    Forward
    Example: RAID-5, 3 drives, block size 128
    Local drive
    sector *) \     		Drive 1 Drive 2 Drive 3 Cycle Stripe
    0-127 | P | B1 **) | B2 | 0 | 0
    128-255 | B3 | P | B4 | 1
    256-383 | B5 | B6 | P | 2
    384-511 | P | B7 | B8 | 1 | 0
    512-639 | B9 | P | B10 | 1
    640-767 | B11 | B12 | P | 2
    : : : : : :
    *) Sectors, cycles and stripes are 0-based,
    blocks and drives are 1-based
    **) Blocks B1, B2, B3, ... are data in the
    1st 128 global sectors (0-127),
    2nd 128 global sectors (128-255),
    3rd 128 global sectors (256-383), etc.
    P is parity for the blocks within the same stripe.

    The name originates from the parity drive rotating forward (right) with each stripe until the start of a new cycle.

    This is a rare rotation scheme, used by just a few hardware RAID controllers.

  • Forw. dyn (aka right-symmetric)
    Forward dynamic
    Example: RAID-5, 3 drives, block size 128
    Local drive
    sector *) \     		Drive 1 Drive 2 Drive 3 Cycle Stripe
    0-127 | P | B1 **) | B2 | 0 | 0
    128-255 | B4 | P | B3 | 1
    256-383 | B5 | B6 | P | 2
    384-511 | P | B7 | B8 | 1 | 0
    512-639 | B10 | P | B9 | 1
    640-767 | B11 | B12 | P | 2
    : : : : : :
    *) Sectors, cycles and stripes are 0-based,
    blocks and drives are 1-based
    **) Blocks B1, B2, B3, ... are data in the
    1st 128 global sectors (0-127),
    2nd 128 global sectors (128-255),
    3rd 128 global sectors (256-383), etc.
    P is parity for the blocks within the same stripe.

    As with the forward rotation, the forward dynamic rotation gets its name from the parity drive rotating forward (right) with each stripe until the start of a new cycle. It is very similar to forward, only stripe 1 arranges the blocks differently. The block to the right of parity P is the block with that stripe's lowest number, while in forward the lowest numbered block is always the first block. The blocks start to the right of parity P, incrementing by 1 with each block, rolling over to the first block and continuing until reaching parity P from the left side. Some people call this right-symmetric.

    This rotation scheme is very rare.

Mapping

You can write the mapping of a chosen RAID topology into a text file. Click on Mapping on the bottom. Confirm the file name and the number of sectors in the following dialog:

Press Ok.

The mapping file will look like this:

>
RAID Mapping Report - Sectors 0 to 10000 - 4/11/2020 11:23:07 PM

RAID-5, 3 drives, Rotation: Backward, Block size: 128, Start sector: 0

1 stripe has 3 blocks (384 sectors) with data in 2 blocks (256 sectors) and parity in 1 blocks (128 sectors)
1 cycle has 3 stripes, 9 blocks (1152 sectors) with data in 6 blocks (768 sectors) and parity in 3 blocks (384 sectors)

LOCAL    \  DRIVE-1     DRIVE-2     DRIVE-3
SECTOR #  \ ----------- ----------- -----------
           \Global sector #
0          |0           128         PARITY
1          |1           129         PARITY
2          |2           130         PARITY
:
126        |126         254         PARITY
127        |127         255         PARITY
-----------+----------- ----------- -----------
128        |256         PARITY      384
129        |257         PARITY      385
:
254        |382         PARITY      510
255        |383         PARITY      511
-----------+----------- ----------- -----------
256        |PARITY      512         640
257        |PARITY      513         641
:
382        |PARITY      638         766
383        |PARITY      639         767
Start of cycle 1
-----------+----------- ----------- -----------
384        |768         896         PARITY
385        |769         897         PARITY
:
510        |894         1022        PARITY
511        |895         1023        PARITY
-----------+----------- ----------- -----------
512        |1024        PARITY      1152
513        |1025        PARITY      1153
:
514        |1026        PARITY      1154
515        |1027        PARITY      1155
638        |1150        PARITY      1278
639        |1151        PARITY      1279
-----------+----------- ----------- -----------
640        |PARITY      1280        1408
641        |PARITY      1281        1409
:
766        |PARITY      1406        1534
767        |PARITY      1407        1535
Start of cycle 2
-----------+----------- ----------- -----------
768        |1536        1664        PARITY
769        |1537        1665        PARITY
:
:
:
5374       |PARITY      10622       10750
5375       |PARITY      10623       10751

This is very helpful for research purposes.

Introduction Entropy Test XOR Test RAID Calculator Creating an Image File Examples RaidProbe Support Drives


MFT Report

If your RAID was NTFS-formatted, the MFT Report provides you another investigation tool. MFT records in NTFS are 1 KB (2 sectors) data blocks containing file metadata such as timestamps, allocation information, security attributes, etc. MFT records are well known and, best of all, they are numbered. We will show how we can use that characteristic for finding an unknown RAID's parameters.

We will use the 3 image files from RAID example 1. Open these files in the main window, then click Tools->MFT report to bring up this window:

Click on Search until and wait for the program to collect 100,000 MFT records. Once done, it will provide a side-by-side view of the MFT records found on the drives:

The drive names head the columns and the sector numbers head the rows. From the lines we see, there are big gaps between MFT records. We want to find a continuous area. Simply scroll down:

Here we see a continuous area of 64 MFT records with 2 sectors each = 128 sectors. We have found the RAID block size is 128. Put this value into the field "Coloring width", along with the start sector 0 for the field "Coloring start sector". Then click on Cycle down to position the window at a cycle start.

You see the empty space for drive 3. This empty space is 128 sectors long. When you scroll down, you will see the empty space for drive 2, 128 sectors long, and then for drive 1, also 128 sectors long. This is obviously a Backward RAID rotation. It is not dynamic because the MFT numbers for drive 1 are smaller then the ones for drive 3.

The drive order is drive1, drive2, drive3.

Thus, we have successfully found this RAID's parameters, simply by looking at its MFT records.


File System Report

The File System Report generates lists of file system structures found on the open drives. Structures captured include:

  • Partition tables
  • NTFS boot records
  • NTFS MFT records
  • NTFS INDX records
  • EXT superblocks
  • XFS superblocks
  • XFS inodes

This report is intended to give an overview of the content of unknown drives.


RaidProbe

Let us find the correct RAID parameters for you

A RaidProbe can be taken if you do not find your RAID's correct parameters with RAID Reconstructor or if you simply do not have the time to work through RAID Reconstructor yourself.

Take advantage of our experience. Since introduction of the RaidProbe service we have helped recover over 500 RAID systems.

If your RAID is recoverable, we will find the parameters!

Here is how it works: RAID Reconstructor will create a probe of your RAID drives which you would send to us by FTP or upload to our server. This probe contains statistical data and file names only. It usually does not contain any file contents.

We will analyze this probe and attempt to find the parameters for you, usually within 24 hours. Don't hesitate to contact us at support@runtime.org if you have further questions.

This is a manual service which we charge $299 for. You will only be charged if we find the parameters. To initiate a RaidProbe now, go to our order page and select the "RaidProbe" service.

What you will get back

Once we determined the RAID parameters, usually within 24 hours, we will send you the following information:

  • Plain English information detailing your RAID's kind, block size, start sector, drive order, and rotation.
  • A virtual image file (.vim file) containing a ready-to-use formal description of your RAID. You can use this .vim file to mount the RAID in Captain Nemo or GetDataBack, or to create a physical image for third-party processing.
  • Detailed instructions on how to proceed.

Supported Systems

  • Windows NTFS
  • Linux EXTFS2/EXTFS3
  • Linux XFS
  • Mac HFS+, APFS
  • Work stations
  • Servers
  • NAS
  • SAS
  • RAID-0, RAID-3, RAID-5, RAID-6, RAID-10, RAID-50, Compaq RAIDs
  • Software RAIDs
  • Hardware RAIDs.

Instructions

  1. Hook up all RAID members, including eventual hot spares, to your machine and make sure physical access to the individual drives is granted. Verify this in Windows Disk Management. If any of your drives has physical problems you should make an image of that drive first. You can mix physical drives and images.
  2. If you have not yet done so, download and install RAID Reconstructor.
  3. Set the RAID type and the number of drives. If you do not know the actual kind of RAID, enter RAID-0. If you do not know that actual number of drives enter the number of drives you have at hand.
  4. Click on "Open drives", then click on "Tools->Create RAID probe". Follow the on-screen instructions.
  5. Order the RaidProbe service and upload the file raidprobe.zip (and raidprobe.001, raidprobe.002, etc., if applicable).

See also: Drives, Image Files

Introduction Entropy Test XOR Test RAID Calculator Creating an Image File Examples RaidProbe Support Drives


Scripting

Scripting (experimental)

Scripting is a powerful extension of RAID Reconstructor's capabilities. Based on the PASCAL programming language, scripts allow you to access your drives and process them with all the elements available in a higher programming language.

In order to take full advantage of this feature, knowledge of PASCAL is required.

NOTE: Scripting is experimental and at this time no integral part of RAID Reconstructor. Use at your own discretion. No support is provided on script writing.

Load and Run a Script

To load a script into the editor, double-click an entry on the left side or click on File->Load. To run a loaded script press F9.

Example Scripts

Please inspect the sample scripts (*.scr) that come with RAID Reconstructor.

Script Name | Purpose
copy_drive_to_image.scr | Demonstrates how to copy a drive to an image file
drive_info.scr | Shortest demo
drive_info_partitiontable.scr | Display a drives partition table
iterate_through_drive.scr | Go through each sector
list_mfts.scr | Extract sector numbers of MFT locations into an external file
raid0_destripe.scr | Reconstruct a 2 drive RAID-0
raid0_3drives_destripe.scr | Reconstruct a 3 drive RAID-0

Reference - Special Functions

Function | Purpose | Example
class TBinData | Basic buffer structure, used to store sector data
function TBinData.CreateZero(Cnt: integer): TBinData; | Creates a TBinData with Cnt bytes. All bytes are initialized to 0 | BD := TBinData.CreateZero(512);
function TBinData.CreateFromString(S: string[; Encoding: string=BYTES|ANSI|UTF8|OEM|UNICODE|HEX]): TBinData; Creates a TBinData from a string;
Encoding can be:
BYTES (uninterpreted 1-byte characters) (Default),
ANSI (interpreted 1-byte characters),
UTF8 (interpreted multi-byte UTF8 characters),
UNICODE (uninterpreted 2-byte characters),
OEM (interpreted as 1-byte OEM characters),
HEX? (as 1-byte hex values with ? as delimiter) 		BD := TBinData.CreateFromString('ABC');
BD := TBinData.CreateFromString('414243', 'HEX');
//creates TBinData with 3 bytes: $41,$42,$43
BD := TBinData.CreateFromString('ABC', 'UNICODE');
//create 6 bytes: $41,$00,$42,$00,$43,$00
function TBinData.Copy(Offset, Len: integer): TBinData; Duplicates the TBinData, with bytes beginning at Offset, with a length of Len. BD := TBinData.CreateFromString('ABC');
BD2 := BD.Copy(2,1);
//BD2 contains 'C'
function TBinData.String(Offset: integer[; Len: integer[; Encoding: string=BYTES|ANSI|UTF8|OEM|UNICODE|HEX]]): string Creates a string from TBinData.
Encoding can be:
BYTES (uninterpreted 1-byte characters) (Default),
ANSI (interpreted 1-byte characters),
UTF8 (interpreted multi-byte UTF8 characters),
UNICODE (uninterpreted 2-byte characters),
OEM (interpreted as 1-byte OEM characters),
HEX? (as 1-byte hex values with ? as delimiter) 		BD := TBinData.CreateFromString('410042004300', 'HEX');
S := BD.String(0, maxint, 'UNICODE');
//S contains 'ABC'
procedure TBinData.SetByte(Offset, B: integer); Set byte at Offset to B BD := TBinData.CreateFromString('ABC');
BD.SetByte(0, 64);
//BD now contains '@BC'
function TBinData.Bytes(Offset, Len: integer; Signed: string): int64; Returns the number at Offset, Len in Little-Endian notation. Maximum for Len is 8. If Signed is 'SIGNED' the two-complement of the number will be returned. BD := TBinData.CreateFromString('FFFFFFFF','HEX');
I := BD.Bytes(0, 4);
//I is 4294967295
I := BD.Bytes(0, 4, 'SIGNED');
//I is -1
function TBinData.BytesAsStr(Offset, Len: integer; Signed: string): int64; | Same as Bytes but returns the number as string
function TBinData.BytesAsStrT(Offset, Len: integer; Signed: string): int64; | Same as Bytes but returns the number as string with thousand delimiters
function TBinData.BytesAsHex(Offset, Len: integer; Signed: string): int64; Same as Bytes but returns the hex representation of the number. BD := TBinData.CreateFromString('FFFFFFFF','HEX');
S := BD.BytesAsHex(0,4);
//S contains 'FFFFFFFF'
S := BD.BytesAsHex(0,4,'SIGNED');
//S contains 'FFFFFFFFFFFFFFFF' (-1 in int64)
function TBinData.BEBytes(Offset, Len: integer; Signed: string): int64; | As Bytes, but using Big-Endian notation
function TBinData.BEBytesAsStr(Offset, Len: integer; Signed: string): int64; | As BytesAsStr, but using Big-Endian notation
function TBinData.BEBytesAsStrT(Offset, Len: integer; Signed: string): int64; | As BytesAsStrT, but using Big-Endian notation
function TBinData.BEBytesAsHex(Offset, Len: integer; Signed: string): int64; | As BytesAsHex, but using Big-Endian notation
property TBinData.Count: integer; Get or set the number of bytes in the TBinData structure. Existing bytes lower than Count are being preserved. New bytes are initialized to 0 BD := TBinData.CreateFromString('ABC');
I := BD.Count;
//I is 3
BD.Count := 4;
//BD is $41,$42,$43,$00
function TBinData.GetPointer: pointer; Returns a pointer to the buffer containing the data of the TBinData structure BD := TBinData.CreateFromString('ABC');
P := BD.GetPointer;
//P now points to a memory area containing $41,$42,$43
procedure TBinData.Append(BD: TBinData); Appends an existing TBinData structure with another one BD := TBinData.CreateFromString('ABC');
BD2 := TBinData.CreateFromString('DEF');
BD.Append(BD2);
//BD now contains 'ABCDEF'
procedure TBinData.SetUpcase; Upcases all bytes in the TBinData structure, if possible BD := TBinData.CreateFromString('abc');
BD.SetUpcase;
//BD now contains 'ABC'
function TBinData.Pos(Needle: TBinData; Index: integer): integer; Searches for Needle bytes in a TBinData, beginning at Index. First index is 0. Returns -1 if not found, otherwise the offset in the TBinData structure BD := TBinData.CreateFromString('ABCDEF');
Needle := TBinData.CreateFromString('CD');
I := BD.Pos(Needle);
//I is 2
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: int64; | Capacity of the drive in sectors, returns an int64. | ShowMessage(IntToStr(Drive.TotalSectors));
function Drive.ReadAsPointer(LBAStart, Count: int64; 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: int64; var Error: integer): TBinData; Read from the drive into a TBinData structure Sector := Read(0, 1, ErrCode);
SomeStream.WriteBuffer(Sector.GetPointer, Sector.Count);
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: int64)]; | Move to the next sector
function Drive.EndOfDrive: boolean; | Test if end of drive is reached
function Drive.GetSector: TBinData; | Read current sector into a TBinData buffer
function Drive.CurrentSector: int64; | Determine the current sector (int64)
procedure Drive.LastSector; | Set drive to the last sector | Drive.LastSector;
procedure Drive.GotoSector(Sec: int64); | 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): TBinData; | Read NumSec sectors into a TBinData buffer, starting with the current sector | BD := Drive.ReadSectors(128):
function Drive.String(Ofs: integer[; Len: integer[; Encoding: string=BYTES|ANSI|UTF8|OEM|UNICODE|HEX[; Sec: int64]]]): string;

 Returns the string starting at Ofs, length Len of the current sector, or, sector Sec if provided. If Len is not provided, the data from the current offset to the end of the sector is used.
Encoding can be:
BYTES (uninterpreted 1-byte characters) (Default),
ANSI (interpreted 1-byte characters),
UTF8 (interpreted multi-byte UTF8 characters),
UNICODE (uninterpreted 2-byte characters),
OEM (interpreted as 1-byte OEM characters),
HEX? (as 1-byte hex values with ? as delimiter) 		S :=Drive.String(0, 4, 'BYTES', 0);
//S is 'NTFS'
S :=Drive.String(0, 4, 'ANSI', 0);
//S is 'NTFS'
S :=Drive.String(0, 4, 'UTF8', 0);
//S is 'NTFS'
S :=Drive.String(0, 4, 'UNICODE', 0);
//S is '??'
S :=Drive.String(0, 4, 'HEX-', 0);
//S is '4E-54-46-53'
function Drive.Bytes(Ofs, Len: integer[; Sec: int64]): int64; Returns the value starting at Ofs, length Len of the current sector, or, sector Sec if provided. I := Drive.Bytes(8, 5);
//I is 123456890
function Drive.BytesAsStr(Ofs, Len: integer[; Sec: int64]): int64; same as Drive.Bytes but returning a string representation of the value S := Drive.BytesAsStr(8, 5);
//S is '1234567890'
function Drive.BytesAsStrT(Ofs, Len: integer[; Sec: int64]): int64; same as Drive.Bytes but returning a string representation with thousand delimiters of the value S := Drive.BytesAsStrT(8, 5);
//S is '1,234,567,890'
function Drive.BytesAsHex(Ofs, Len: integer[; Sec: int64]): int64; same as Drive.Bytes but returning a string representation of the value S := Drive.BytesAsHex(8, 5);
//S is '499602D2'
function Drive.Entropy: float Shannon entropy of current sector F := Drive.Entropy;
//f is between 0.00 and 1.00
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: int64; | This partition's start sector on the drive | I := Drive.Partition(1).StartSector;
function PartItem.Sectors: int64; | Length in sectors of this partition | I := Drive.Partition(1).Sectors;
function PartItem.Type: integer; | Type of this partition, e.g. NTFS | I := Drive.Partition(1).Type;
Memory functions
procedure GetMem(var P: pointer; MemSize: integer); Allocate a buffer GetMem(P, 1024);
//do something with P
FreeMem(P);
procedure FreeMem(P: pointer); | Free a buffer
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
class TFileStream
function TFileStream.Create(FileName: string; FileMode: integer): TFileStream; Create new file FStrm := TFileStream.Create('somefile', fmCreate);
try
Sectors := Drive.GetSector;
FStrm.WriteBuffer(Sectors.GetPointer, Sectors.Count);
finally
FStrm.Free;
end;
procedure TFileStream.WriteBuffer(P: pointer; Size: integer); | Write to TFileStream
procedure TFileStream.Free; | Free the object
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 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 FmtSignificanceByte(i: int64; digits: integer): string; Converts a byte number S := FmtSignificanceByte(1000000, 4);
//returns '976.6 KB'
function IntToStr(i: int64): string; Converts an int64 to a string S := IntToStr(12345);
//returns '12345'
function IntToStrT(i: int64): string; Converts an int64 to a string with thousand delimiters S := IntToStrT(12345);
//returns '12,345'
function IntToHex(i: int64[; MinDigits, MaxDigits: integer]): string; Converts an int64 to a hex string S := IntToHex(12345);
//returns '3039'
S := IntToHex(12345, 8);
//returns '00003039'
S := IntToHex(12345, 4, 2);
//returns '39'
function IntToDual(i: int64[; MinDigits: integer]): string; Converts an int64 to a binary string S := IntToDual(12345);
//returns '11000000111001'
S := IntToDual(12345, 16);
//returns '0011000000111001'
function StrToInt(s: string): int64; Converts a string to an int64 I := StrToInt('12345678901234');
//returns 12345678901234
Bit operations
function Int32OR(i1, i2: integer): integer; Returns i1 OR i2. Use instead of bug with OR operator. i := Int32OR(1, 2);
//returns 3
function Int32AND(i1, i2: integer): integer; Returns i1 AND i2. Use instead of bug with AND operator. i := Int32AND(1, 3);
//returns 1
function Int32SHL(i1, i2: integer): integer; Returns i1 SHL i2. Use instead of bug with SHL operator. i := Int32SHL(1, 2);
//returns 4
function Int32SHR(i1, i2: integer): integer; Returns i1 SHR i2. Use instead of bug with SHR operator. i := Int32SHR(7, 2);
//returns 1
function Int64DIV(i1, i2: int64): int64; Divide two int64 numbers I := Int64DIV(10,3);
//returns 3
function Int64MOD(i1, i2: int64): int64; Modulo of two int64 numbers I := Int64MOD(10,3);
//returns 1
function Int64SHL(i1, i2: int64): integer; Returns i1 SHL i2. i := Int64SHL(1, 2);
//returns 4
String routines
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; var 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', I is 13
ShowMessage(ParseTag(S, 'Drive ', ':', I));
//returns 'HD129'
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
function Reverse(s: string): string; Reverses a astring S := Reverse('123');
//returns '321'
function GroupString(s: string; CharsPerGroup: integer; Delimiter: string): string; Groups a string into of groups of CharsPerGroup characters each. Groups are delimited with Delimiter S := GroupString('EF1C77', 2, ' ');
//returns 'EF 1C 77'
function HexStringToGUID(s: string): string; Returns a 32-character Hex string formatted as a GUID S := HexStringToGUID('1234567890abcdef1234567890abcdef')
//returns '78563412-AB90-EFCD-1234-567890ABCDEF'
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);
function HFSDateToDateTime(i: integer): float; | Convert HFS file timestamps to TDateTime | dt := HFSDateToDateTime(i);
function APFSDateToDateTime(i: int64): float; | Convert APFS file timestamps to TDateTime | dt := APFSDateToDateTime(ii);
HTML routines
function Linked(Link, Disp: string): string; Returns an <a> tag with Link being the href attribute and Disp being the display string. S := Linked('http://runtime.org', 'Runtime Software');
//returns <a href="http://runtime.org">Runtime Software</a>
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: int64; 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');
Miscellaneous 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);
function iifarr(Needle: variant; HayArr, ThenArr: variantarray; ElseValue: variant): variant If Needle is found in array HayArr, the element with the same position in ThenArr is returned. If Needle is not found in array HayArr the variant ElseValue is returned. V := iifarr(-1, [-2, '-1', 0, 1, 2], ['-two', '-one', 'zero', 'one', 'two'], 'other'); //returns '-one'
V := iifarr(3, [-2, '-1', 0, 1, 2], ['-two', '-one', 'zero', 'one', 'two'], 'other'); //returns 'other'
function FlagArr(Flags: int64; Arr: variantarray; Delimiter: string): string; If a bit in Flags is set, the corresponding element of Arr is copied to the result, separated by Delimiter. s := FlagArr(5, ['bit0', 'bit1', 'bit2', 'bit3'], '-'); //returns 'bit0-bit2'
function VarType(V: variant): integer; Returns the type of the variant V.
0 (varEmpty)
1 (varNull)
2 (varSmallInt)
3 (varInteger)
4 (varSingle)
5 (varDouble)
6 (varCurrency)
7 (varDate)
8 (varOleStr)
9 (varDispatch)
10 (varError)
11 (varBoolean)
12 (varVariant)
13 (varUnknown)
17 (varByte)
18 (varWord)
19 (varLongWord)
20 (varInt64)
72 (varStrArg)
256 (varString)
257 (varAny)
4095 (varTypeMask) 		V := 1000000;
I := VarType(V);
//returns 3''''
function VarTypeToString(V: variant): string; Returns the variant type as a string. V := 1000000;
S := VarTypeToString(V);
//returns 'varInteger'
function GlobalExists(VarName: string): boolean; Returns TRUE if the variable with the name in VarName exists B := GlobalExists('myvar');
//returns TRUE if myvar exists
procedure Swap(var X, Y: variant); Swap the contents of two variables X := 'hello';
Y := 13;
Swap(X, Y);
//X now contains 13, Y contains 'hello'
function XorSectors(Sectors: variantarray): string; | XOR sec1,sec2...secx into a string | S := XorSectors([sec1, sec2, sec3]);
Array routines
function ArrayCreate(HighBound: integer): variantarray Creates a variant array with HighBound+1 elements Arr := ArrayCreate(10);
//creates an Arr with 11 elements, addressable as Arr[0]..Arr[10]
function ArrayRedim(V: variantarray; NewHighBound: integer): variantarray; Re-dimension a variant array v := ArrayCreate(6);
//v has 7 elements
v := ArrayRedim(v, 10);
//v has 11 elements
function ArrayHigh(V: variantarray): integer; Returns the index of the last element v := ArrayCreate(6);
I := ArrayHigh(v);
//I is 6
function ArrayContains(Arr: variantarray; V: variant): boolean; Tests if V is in Arr Arr := ['abc', 'def', 123];
B := ArrayContains(Arr, '123');
//returns TRUE

t

Reference - Variables

Variable | Description
Storage Storage.AsInt['varname'] Storage.AsInt64['varname'] Storage.AsFloat['varname'] Storage.AsString['varname'] Storage.AsBinary['varname'] Storage.AsBinData['varname'] Storage.Count | Provides a data container that is accessible over all scripts.
AvailableViews | A TDictionary<string,string> with information about the available views.
AvailableViews.Items['boot_fat,VIEWNAME'] | Returns the VIEWNAME of boot_fat.scr
AvailableViews.Items['*INDEX*0'] | Returns the first available view
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
tag_br, tag_hr | '<br>', '<hr>'
DRIVE_KIND_PHYSICAL DRIVE_KIND_LOGICAL DRIVE_KIND_IMAGE DRIVE_KIND_SCHEDULE | Drive types (0,1,2,3)
maxint | Largest possible integer: 2147483647 ($7fff ffff)
maxint64 | Largest possible int64: 9223372036854775807‬ ($7fff ffff ffff ffff)
fmCreate, fmOpenRead, fmOpenWrite, fmOpenReadWrite | File mode constants for TFileStream.Create
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;


Create Image

Creating an Image File

Clicking Tools->Create single image file allows you to create an image from a single hard drive. This is recommended if there are bad sectors on the drive.

Select the drive you want to copy from and the file you want to copy to. If you check "Multi file", the image will be split in files of 650 MB.

Click Start to begin creating the image. Once the image is created you can use the image file ("driveimage.img" in the example above) in Runtime's data recovery products like a real drive.

See also: Drives, Image Files, Virtual Images

Introduction Entropy Test XOR Test RAID Calculator Creating an Image File Examples RaidProbe Support Drives


Create XOR VIM

This tiny utility creates a Virtual Image File with the current drives XOR-ed with each other.

Assume you have opened the files C:\img\drive1.img, C:\img\drive2.img, and C:\img\drive3.img. Click on Tools->Create XOR VIM. Click Save and you will have created a file C:\img\xor.vim. This file contains the following XML code:

>
<?xml version="1.0" encoding="utf-8"?>
<virtualimage>
<info>
  <Comment>NOTE: The INFO tag is not necessary for the VIM to function. It is only a comment.</Comment>
  <creator>Raid Reconstructor, Version 5.00</creator>
  <creationdate>2020-04-13T17:37:31Z</creationdate>
  <Comment>XOR of these 3 drives:
    Drive 1: C:\img\drive1.img
    Drive 2: C:\img\drive2.img
    Drive 3: C:\img\drive3.img</Comment>
</info>
<loop>
  <drive>C:\img\drive1.img:</drive>
  <drive>C:\img\drive2.img:</drive>
  <drive>C:\img\drive3.img:</drive>
  <cycle blocksize="128">
    <stripe>1x2x3</stripe>
  </cycle>
</loop>
</virtualimage>

Practically speaking, this VIM file simulates a missing RAID-5 drive from a 4-drive RAID-5 with the surviving drives drive1.img, drive2.img, and drive3.img. You can open this VIM file like any other drive with our products RAID Reconstructor, GetDataBack, Captain Nemo, or DiskExplorer.


Show Checksums

This utility shows you the checksums for currently open drives. This is helpful if you need to find out if the naming of your physical drives is still the same it was when you created a RaidProbe. Refer to the file raidinfo.txt that was created along with your RaidProbe.

Assume you previously had created a RaidProbe for the drives HD128:, HD129:, and HD130:. The RaidProbe file "raidinfo.txt" contains the checksums at that time.

>
:
:
HD128:
  Checksum: [409A77E2]
:
HD129:
  Checksum: [8280945E]
:
HD130:
  Checksum: [15B5AC53]
:
:

Compare these values with the current values. Click Tools->Show Checksums:

We see, the checksums match. If they do not, be careful with VIM files based on the earlier names. If you want to use VIM files created earlier with different names, you need to modify that VIM file in order to reflect the actual mapping.

If, for example, your raid.vim contains the drive definitions

:
<drive>HD128:</drive>
<drive>HD129:</drive>
<drive>HD130:</drive>
:

and the new checksums were

HD128:[409A77E2]
HD129:[15B5AC53]
HD130:[8280945E]

you would replace the definition for HD129: with the definition for HD130: and vice versa. You would modify the raid.vim to

:
<drive>HD128:</drive>
<drive>HD130:</drive>
<drive>HD129:</drive>
:

See also: RaidProbe, Virtual Image


Virtual images

Virtual Image

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 Captain Nemo, GetDataBack, or DiskExplorer.

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.

Example with a NULL drive:

<virtualimage>
<drive>NULL:0-8000000000</drive>
</virtualimage>

This defines a drive with 4 TB that you can open with Captain Nemo, GetDataBack, or DiskExplorer.

NULL drive example with labeled and numbered sectors:

<virtualimage>
<drive>NULL(Sector Number):0-8000000000</drive>
</virtualimage>

This creates a virtual 4 TB drive with numbered sector numbers. Look how sector 4711 would look like:

This is a great feature for research purposes. When experimenting with RAID fragments, you can see where a sector originated.

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.
NULL(LABEL): | Virtual drive, delivers labeled and numbered 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.

<cycle>

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.

The <stripe> tag can have a "repeat" attribute, e.g.

<stripe repeat="16">1,2</stripe>

This will cause a repeat of the <stripe> tag sixteen times.

<searchbootranges>
This tag does not change the Virtual Image. It is only an information for programs using the VIM file, such as Captain Nemo.

For example,

<searchbootranges>64200-64300;8450200-8450300;12643200-12643300</searchbootranges>

will instruct Captain Nemo to look for boot records at the sectors indicated.

See also: Drives, Image files


Examples

Examples and Case Studies

We have prepared five examples for you to study. They demonstrate some typical usages, as well as best practices for RAID Reconstructor.

  • Example 1 - RAID-5 with 3 drives on a HP 454
    This example demonstrates a typical recovery of a broken hardware RAID.
  • Example 2 - RAID-5 with 3 drives on a HP 454, 1 drive defect
    Recovery of a RAID-5 after the failure of one drive.
  • Example 3 - RAID-5 with 4 drives on a Dynamic Disk set
    Recovery of a Windows Software RAID-5, demonstration on using the XOR Test for finding an unknown start sector.
  • Example 4 - RAID-0 (Striping) on a HP 454
    Recovering a striped set (RAID-0)
  • Example 5 - RAID-5 on Iomega StorCenter IX4-200D
    Typical recovery of a NAS. Demonstration on finding an unknown start sector with DiskExplorer or the Entropy Test.

See also: Drives, Image Files

Introduction Entropy Test XOR Test RAID Calculator Creating an Image File Examples RaidProbe Support Drives


Example 1 - RAID-5 with 3 drives on a HP 454

Configuration:

  • 3 drives with 10,000,000 sectors (5 GB) each.
  • Originally configured as a RAID-5 with a total capacity of 20,000,000 sectors (10 GB).
  • Hardware RAID-5 on a Highpoint RocketRAID 454 controller card.
  • The 3 drives have been copied to image files:
    C:\img\drive1.img
    C:\img\drive2.img
    C:\img\drive3.img

Instructions:

Start RAID Reconstructor.

Select RAID-5 as the RAID type, set # Drives to 3, type the names of the image files into the fields labeled Drive1, Drive2 and Drive3:

Click Open drives.

Verify that all 3 drives show the size of 10,000,000 sectors and that the total size shows

(Number_Of_Drives-1) * Size_Of_Smallest_Drive = (3-1) * 10,000,000 = 20,000,000 sectors

In 4. Analyze, leave the Start sector at 0 because we have a hardware RAID that is most probably starting at sector 0.

Also, leave the Block size and the Parity rotation unchanged. These values will be determined by the analysis we are going to start.

Click Analyze.

The Analysis wizard will start:

Select Managed Auto (2020) and click Next. The wizard performs a pre-test. It determines the block size (128), and the drive order. This will greatly reduce the permutations performed next.

We want to leave the parameters and the number of sectors that we want to probe unchanged. Click Next.

The entry found is at least 60% smaller than any other entry. This is good and we get a "RECOMMENDATION: Choose entry #1". Click Finish.

The found parameters got transferred into the corresponding fields in the main screen:

  • Block size is 128
  • Rotation is backward
  • Drive order is drive1.img, drive2.img, drive3.img

Now we are ready to copy the combined array to a virtual image file. Specify a target file name and click Copy.

Immediately after clicking Copy we have a small file c:\img\raid.vim. Mount this image with Captain Nemo or scan it with GetDataBack in order to retrieve the data from it.

Click on Captain Nemo

Voilà, you are ready to copy your files off the lost RAID.

See also:

  • Example 2 - RAID-5 with 3 drives on a HP 454, 1 drive defect
  • Example 3 - RAID-5 with 4 drives on a Dynamic Disk set
  • Example 4 - RAID-0 (Striping) on a HP 454
  • Example 5 - RAID-5 on Iomega StorCenter IX4-200D


Example 2 - RAID-5 with 3 drives on a HP 454, 1 drive defect

Configuration:

  • 3 drives with 10,000,000 sectors (5 TB) each, one of these drives is non-functioning
  • Originally configured as a RAID-5 with a total capacity of 20,000,000 sectors (10 TB).
  • Hardware RAID-5 on a Highpoint RocketRAID 454 controller card.
  • The remaining 2 drives have been copied to image files:
    C:\img\drive1.img
    C:\img\drive2.img

Instructions:

Start RAID Reconstructor.

Select RAID-5 as the RAID type, set # Drives to 3, type the names of the image files into the fields labeled Drive1 and Drive2. Leave Drive3 empty:

Click Open drives.

Verify that 2 drives show the size of 10,000,000 sectors and that the total size shows

(Number_Of_Drives-1) * Size_Of_Smallest_Drive = (3-1) * 10,000,000 = 20,000,000 sectors

In 4. Analyze, leave the Start sector at 0 because we have a hardware RAID that is most probably starting at sector 0.

Also, leave the Block size and the Parity rotation unchanged. These values will be determined by the analysis we are going to start.

Click Analyze.

The Analysis wizard will start:

Select Managed Auto (2020) and click Next. The wizard performs a pre-test. It determines the block size (128), and the drive order. This will greatly reduce the permutations performed next.

We want to leave the parameters and the number of sectors that we want to probe unchanged. Click Next.

The entry found is at least 60% smaller than any other entry. This is good and we get a "RECOMMENDATION: Choose entry #1".Click Finish.

The found parameters got transferred into the corresponding fields in the main screen:

  • Block size is 128
  • Rotation is backward
  • Drive order is drive1.img, drive2.img, missing

Now we are ready to copy the combined array to a virtual image file. Specify a target file name and click Copy.

Immediately after clicking Copy we have a small file c:\img\raid.vim. Mount this image with Captain Nemo or scan it with GetDataBack in order to retrieve the data from it.

Click on Captain Nemo

Voilà, you are ready to copy your files off the lost RAID.

See also:

  • Example 1 - RAID-5 with 3 drives on a HP 454
  • Example 3 - RAID-5 with 4 drives on a Dynamic Disk set
  • Example 4 - RAID-0 (Striping) on a HP 454
  • Example 5 - RAID-5 on Iomega StorCenter IX4-200D


Example 3 - RAID-5 with 4 drives on a Dynamic Disk set

Example 3 - RAID-5 with 3 drives on a Windows Dynamic Disk set

Configuration:

  • 3 drives with 125,829,120 sectors (60 GB) each. Using GPT partition scheme.
  • Originally configured as a RAID-5 with a total capacity of 251,658,240 sectors (120 GB).
  • Software RAID-5 on a Windows Server 2019 Dynamic Disk set.
  • The 3 drives have been copied with DiskExplorer to compressed image files:
    C:\img\dyn1.imc
    C:\img\dyn2.imc
    C:\img\dyn3.imc

Instructions:

Start RAID Reconstructor.

Select RAID-5 as the RAID type, set # Drives to 3. Type the names of the image files into the fields labeled Drive1, Drive2, and Drive3.

Click Open drives.

Verify that all 3 drives show the size of 125,829,120 sectors and that the total size shows

(Number_Of_Drives-1) * Size_Of_Smallest_Drive = (3-1) * 125,829,120= 251,658,240 sectors

As this RAID is a Windows Dynamic RAID-5, we should set the Start sector to its correct value, if we only knew what that value is. Leave Start sector at 0 for now and let's look at the analysis anyways. We will show later how to find the Start sector.

Also, leave the Block size and the Parity rotation unchanged. These values will be determined by the analysis we are going to start now.

Click Analyze.

The analysis wizard will start:

Select Managed Auto (2020) and click Next. The wizard performs a pre-test. It determines the block size (128), and the drive order. This will greatly reduce the permutations performed next.

We want to leave the parameters and the number of sectors that we want to probe unchanged. Click Next.

The entry found is not significant. It has almost the same entropy as the 2nd entry. Click Cancel.

This was kind of expected, as we have not used the correct start sector yet. We will now determine the value of the start sector.

DISCOURSE: Finding the RAID start sector using the XOR test

Click Tools->XOR test, then click Start.

Click page-down until you see the green XOR-Pass color.

Zoom in to better see the green area:

We see two exciting things:

  • The first green sector is sector 264,192
  • Sector 264,192 contains a NTFS boot record

Sector 264,192 appears to be the start sector we are looking for.

Let's go back to 4. Analyze and enter 264,192 as Start sector.

Click Analyze.

The analysis wizard will start again

:

Select Managed Auto (2020) and click Next. The wizard performs a pre-test. It determines the block size (128), and the drive order. This will greatly reduce the permutations performed next.

We want to leave the parameters and the number of sectors that we want to probe unchanged. Click Next.

What we get now is much better. The entropy of 0.03 is significantly smaller than the entropy of the next entry, 0.04. We get a "RECOMMENDATION: Choose entry #1".Click Finish to move these values to the main screen.

The found parameters got transferred into the corresponding fields in the main screen:

  • Block size is 128
  • Rotation is backward (dyn. disk)
  • Drive order is dyn3.imc, dyn2.imc, dyn1.imc

Now we are ready to copy the combined array to a virtual image file. Specify a target file name and click Copy.

Immediately after clicking Copy we have a small file c:\img\raid.vim. Mount this image with Captain Nemo or scan it with GetDataBack in order to retrieve the data from it.

Click on Captain Nemo

Voilà, you are ready to copy your files off the lost RAID.

See also:

  • Example 1 - RAID-5 with 3 drives on a HP 454
  • Example 2 - RAID-5 with 3 drives on a HP 454, 1 drive defect
  • Example 4 - RAID-0 (Striping) on a HP 454
  • Example 5 - RAID-5 on Iomega StorCenter IX4-200D


Example 4 - RAID-0 (Striping) on a HP 454

Configuration:

  • 2 drives with 50000 sectors (24 MB) each.
  • Originally configured as a RAID-0 (Striping) with a total capacity of 100000 sectors (48.8 MB).
  • Hardware RAID-0 (Striping) on a Highpoint RocketRAID 454 controller card.
  • The 2 drives have been copied to image files:
    C:\img\raid0\r0_1.IMG
    C:\img\raid0\r0_2.IMG

Instructions:

Start RAID Reconstructor.

Select RAID-0 (Striping) as the RAID type. Set # Drives to 2. Enter the names of the image files into the fields labeled Drive1 and Drive2.

Click Open drives.

Verify that the 2 drives show the size of 50,000 sectors and that the total size shows

Number_Of_Drives * Size_Of_Smallest_Drive = 2 * 50,000 = 100,000 sectors

In 4. Analyze, leave the Start sector at 0 because we have a hardware RAID that is most probably starting at sector 0. Also, leave the Block size unchanged. This value will be determined by the analysis we are going to start.

Click Analyze and the analysis wizard will start:

Select Managed Auto (Legacy) and click Next. The wizard will perform a pre-test and determine the block size (128). This will greatly reduce the permutations tested next.

We want to leave the parameters and the number of sectors that we want to probe unchanged. Click Next.

The entry found is around 70% smaller than any other entry. This is good and we get a "RECOMMENDATION: Choose entry #1". Click Finish.

The found parameters got transferred into the corresponding fields in the main screen:

  • Block size is 128
  • Drive order is r0_1.img - r0_2.img

Now we are ready to copy the combined array to a virtual image file. Specify a target file name and click Copy.

Immediately after clicking Copy we have a small file c:\img\raid.vim. Mount this image with Captain Nemo or scan it with GetDataBack in order to retrieve the data from it.

Click on Captain Nemo

Voilà, you are ready to copy your files off the lost RAID.

See also:

  • Example 1 - RAID-5 with 3 drives on a HP 454
  • Example 2 - RAID-5 with 3 drives on a HP 454, 1 drive defect
  • Example 3 - RAID-5 with 4 drives on a Dynamic Disk set
  • Example 5 - RAID-5 on Iomega StorCenter IX4-200D


Example 5 - RAID-5 on Iomega StorCenter IX4-200D

Configuration:

  • NAS containing 4 drives with 1,953,525,168 sectors (1 TB) each.
  • Originally configured as a RAID-5 with a total capacity of 5,848,333,974 sectors (3 TB).
  • Software RAID-5 on a NAS Iomega StorCenter IX4-200D.
  • The 4 drives have been copied to compressed image files:
    d:\img\ix4\raid5-1.imc
    d:\img\ix4\raid5-2.imc
    d:\img\ix4\raid5-3.imc
    d:\img\ix4\raid5-4.imc

Instructions:

Start RAID Reconstructor.

Select RAID-5 as the RAID type, Set # Drives to 4, Enter the names of the image files into the fields labeled Drive1, Drive2, Drive3, and Drive4:

Click Open drives.

Verify that all 4 drives show the size of 1,953,525,168 sectors and that the total size shows

(Number_Of_Drives-1) * Size_Of_Smallest_Drive = (4-1) * 1,953,525,168 = 5,860,575,504 sectors

4. Analyze, we need to determine the start sector first, because a software RAID has one starting not at 0.

DISCOURSE: Finding the RAID start sector on a NAS

A NAS is typically configured as a small RAID-1 (mirror) for the Linux OS, followed by a large RAID-5 for the data:

SECTOR# [0................][X..............................1953525167]
DRIVE1: [Linux OS (copy 1)][Data partition (RAID member 1)           ]
DRIVE2: [Linux OS (copy 2)][Data partition (RAID member 2)           ]
DRIVE3: [Linux OS (copy 3)][Data partition (RAID member 3)           ]
DRIVE4: [Linux OS (copy 4)][Data partition (RAID member 4)           ]

We are searching for the start sector X. Using the XOR method from RAID Example-3 is not practical here, because the RAID-1 would pass the XOR test and thus obscure our observations.

We will demonstrate two other methods for finding this start sector:

METHOD 1: Examine partition table

Start DiskExplorer.

Load image raid5-1.imc

In the partition table view of sector 0, you see two partitions:

  1. Linux at sector 1, length 4,080,509 sectors
  2. Linux at sector 4,080,510, length 1,949,444,658 sectors

The first partition is most likely the small Linux OS partition with 2 GB, while the second partition appears to be a large 1 TB partition. It begins at sector 4,080,510 which is our start sector X.

If you want to see that in a neater way, you can also invoke File->Drive. After loading all four drives, you can examine them all in one screen:

All member drives of the NAS have the same partition table with the large partition being the partition used to build the RAID-5. That partition starts at sector 4,080,510 on all drives.

METHOD 2: Use Entropy test to find partition start

Click Tools->Entropy test, click Start

The graph shows the entropy (between 0 and 1) of the sectors 0..10,000 on the drives. The drives are displayed over each other. First drawn is drive 1 in red, followed by drive 2 (green), drive 3 (yellow), and drive 4 (blue). We know this area on the drives is mirrored over all drives, so the blue from drive 4 covers the other drives. Let's remove drive 4 by un-checking the checkbox to the left of the blue square followed by "Drive 4".

We see the same pattern in yellow as drive 3 is on top now. Remove drive 3 and the pattern will be green. Remove drive 2 and it will be red.

We are looking for the region on the drives were this mirror behavior changes to the drives' entropies being independent of each other and the graph displaying all colors randomly.

Please fill the screen with the values below:

Click on the "R" button near the upper-right corner. This will shift the graph by 100,000 sectors.

Click "R" repeatedly until you see all four colors. After shifting about 40 times you can see additional colors behind the top drive:

Zoom in and examine this area in detail. Click overlaying drives on and off in order to find the first un-mirrored sector. This sector turns out to be sector 4,080,510.

You can also examined this area in DiskExplorer and you will find "LABELONE" which is the signature for Linux' LVM (Logical Volume Manager).

Set the Start sector to 4,080,510.

Also, leave the Block size and the Parity rotation unchanged. These values will be determined by the analysis we are going to start.

Click Analyze.

The Analysis wizard will start:

Select Managed Auto (2020) and click Next. The wizard performs a pre-test.

We want to leave the parameters and the number of sectors that we want to probe unchanged. Click Next.

Unfortunately, we do not get a "Recommended entry". The best entry has an entropy of 0.15 while the next best has one of 0.16. The difference is less than the required threshold of 20%. However, we see all competing entries have a block size of 128. Let's go back to the previous screen and check block size 128 only. This will reduce the time needed for testing all combinations. Increase the value of "Number sectors" to 500,000.

Click "Next".

This time we are successful and get a "RECOMMENDATION". The entry found is at least 20% smaller than any other entry.

Click Finish and the found parameters get transferred into the corresponding fields in the main screen:

  • Block size is 128
  • Rotation is backward (dyn. disk)
  • Start sector is 4,080,510
  • Drive order is raid5-1.imc, raid5-2.imc, raid5-3.imc, raid5-4.imc,

Now we are ready to copy the combined array to a virtual image file. Specify a target file name and click Copy.

Immediately after clicking Copy we have a small file d:\img\ix4\raid.vim. Mount this image with Captain Nemo or scan it with GetDataBack in order to retrieve the data from it.

Click on Captain Nemo

The file system is XFS and you are ready to copy your files off the lost RAID.

See also:

  • Example 1 - RAID-5 with 3 drives on a HP 454
  • Example 2 - RAID-5 with 3 drives on a HP 454, 1 drive defect
  • Example 3 - RAID-5 with 4 drives on a Dynamic Disk set
  • Example 4 - RAID-0 (Striping) on a HP 454


Troubleshooting

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

Access denied

Could not lock drive

License required

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

See also: Support


Access Denied

Error: 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.

See also: Image files


Drive Locking Failed

Warning: Could Not Lock Drive

Locking a drive is a low-level feature for preventing several processes from accessing a physical or logical drive at the same time. You should verify no other processes are accessing the drive. If you Ignore the warning your process will possibly continue, but may cause damage to the data on the drive. Therefore, ignoring is not recommended.

See also: Drives


Support

You can contact us for support:

USA

Phone | 1-888-777-6960
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: License, Troubleshooting, License agreement

Introduction Entropy Test XOR Test RAID Calculator Creating an Image File Examples RaidProbe Support Drives


Drives

Besides physical drives, Runtime's data recovery programs also accept image files (.img) and virtual image files (.vim) as a data sources:

  • Physical drives
  • Image files
  • Virtual images

Introduction Entropy Test XOR Test RAID Calculator Creating an Image File Examples RaidProbe Support Drives


Image Files

Image files are files containing raw images of a drive. With programs like Runtime's RAID Reconstructor, GetDataBack and Captain Nemo you can process these image files like real physical drives.

Multiple Files

Image files can consist of:
  • one file (e.g. 'drive128.img')
  • multiple files (e.g. 'drive128.img', 'drive128.001', 'drive128.002', ...)
This is helpful when imaging a drive larger than the maximum file size (2GB or 4GB, depending on the operating system). Fragments of a multiple file image are about 656MB in size. A smaller size indicates the end of the file set. If there are more than 1000 fragments, the numbering switches from '001', ..., '999' to 'A00', ...'ZZZ'.

Compression

You can use compressed image files (e.g. 'drive128.imc') by selecting 'Compressed image data files (*.imc)' as file type in the file open dialog. This feature enables you to create drive images much smaller than the original. Compressed files can be multiple file images too. We recommend not to use compressed images.

See also: Drives, Physical Drives, Creating an Image File, Virtual Images


Physical Drives

Physical drives are tangible media like hard drives and diskettes. They have specific names:

FD0 | 1st diskette drive
FD1 | 2nd diskette drive
HD128, DISK0 | 1st hard drive
HD129, DISK1 | 2nd hard drive
HD130, DISK2 | 3rd hard drive
: | :

See also: Drives, Image Files


Bad sector

Bad Sectors Handling

An error was encountered during a sector block read operation.

Sectors are read in chunks of 16 sectors. If this operation fails this might be because of a single bad sector or of several bad sectors. You have the choice:

Skip sector block

All 16 sectors are considered bad. No attempt is made to retrieve possibly good sectors.

Retry accessing single sectors

The program retries reading the sectors one by one. This gives the chance to retrieve possibly good sectors in the neighborhood of a bad one. However, this can be very time consuming, especially if there are not good sectors at all.

Introduction