Note to self 2022-09-15: if you are looking for a “firmware analyzer” or a tool that finds magic file headers at all locations inside of a file (and looks for embedded files). You need to look for your binwalk article.

INTRO

This method can be used to mount iso files and disk images (block device files) locally without burning them to drives. If they are iscsi luns you wont need to initiate to them, you can just mount them as if they were a disk image. The method covered here uses losetup to mount the disk image at the offsets where the partitions begin (so we need to use sgdisk and sfdisk to find out where the partitions start and end). At the end I throw in a bonus, using kpartx method, which will do everything automatically: it will mount all of the partitions in a disk image, without needing to parse the partition tables.

USING LOSETUP

If you have a file that is used as an iscsi_target, or perhaps its an iso of a disk, such a dd image of a drive sda, which had several partitions sda1, sda2, sda3. You can use this method to mount any partition, or to mount the iscsi_target. Note that an iscsi_target is no more than a simple disk, so an iscsi_target is like sda. In our example we have a file called lunfile, and lets assume this lunfile is like 10 gigs big (or however big your iscsi file is). This lunfile was either a dd image of drive that was partitioned using a local unix/linux system, or maybe it was initiated to with Windows initiator and has an NTFS filesystem on it – in the end it doesnt matter, all luns are just luns.

To mount ISCSI or a lun locally (which has partitions or no partitions), we just need to treat lunfile as a disk. So lunfile is like “sda”, its either MBR or GPT (depending on how you initialized the disk in windows), also it usually has partitions (usually just 1 if you set it up in windows). So the whole lunfile is “sda”, and at a certain offset begins “sda1”. A program called losetup can take an iso image of a disk (thats usually a burned cd) and associate that to a device called loop0 (or loop#, any number – or as many loop devices as your system allows). We can ask losetup to point lunfile to “loop0”, and then we can try to mount that “loop0” to /mnt, but that would FAIL. Why would it fail? because lunfile has partitions, it would be like trying to mount “sda” (instead of “sda1”). So instead we tell losetup to point at only a specific subsection of lunfile, and we call that subsection loop0, we can specify a start byte (using -o for offset, so like partition 1 starts at byte X), then usually it can autodetect how big that partition needs to be (if it cant detect how big it is, we can tell it that the partition is Y bytes big). Then loop0 is like sda1, instead of sda (or any other partition of sda), then we simply ask to mount loop0 to /mnt and it should work (granted you have the right mount tools – such as ntfs-3g for ntfs filesystems)

# losetup --help
-a list all used loop devices
-o, --offset <num> start at offset <num> into file
--sizelimit <num> loop limited to only <num> bytes of the file

(STEP 0) cd to folder where lunfile is

cd /where/lun/file/is/

(STEP 1 – IF MBR) If MBR – Get the START and SIZE BYTES

# fdisk -lu lunfile
You must set cylinders.
You can do this from the extra functions menu.
Disk disk.img: 0 MB, 0 bytes
255 heads, 63 sectors/track, 0 cylinders, total 0 sectors
Units = sectors of 1 * 512 = 512 bytes
      Device Boot      Start         End      Blocks   Id  System
disk.imgp1   *          63       96389       48163+  83  Linux
disk.imgp2           96390     2056319      979965   82  Linux swap / Solaris
disk.imgp3         2056320    78140159    38041920    5  Extended
disk.imgp5         2056383     3052349      497983+  83  Linux
disk.imgp6         3052413    10859939     3903763+  83  Linux
disk.imgp7        10860003    68372639    28756318+  83  Linux
disk.imgp8        68372703    76180229     3903763+  83  Linux
disk.imgp9        76180293    78140159      979933+  83  Linux

NOTE: output above is from another system. So ignore that your seeing disk.imgp1, it should be lunfilep1 (or something of that sort)

We need to figure out the START byte for the -o argument, and optionally figure out the SIZE of the partition for the –sizelimit argument.

Imagine we wanted to mount partition 7, p7, which is the biggest (has the most blocks). Notice its start sector 10860003. So we need to convert that bytes. We notice in that listing that 1 sector is 512 bytes. So the start location is 10860003*512 which is some big number (we dont need to calculate it, we will have linux/bash calculate for us).

Like I said in the intro, the SIZE of the partition doesnt really matter as much as the start point because it can guess the Size. But the Size would be something like (END-START)+1 to get the number of sectors. Dont forget to add 1 (unless it already adds one for us). Then multiply by 512 (bytes per sector) to get the number of bytes. 68372639-10860003+1. 57512637 sectors. Or 57512637*512 bytes. Note if we didnt add 1 it would be 57512636*512 bytes.

Why do we add 1? Well sometimes you have to try with adding it, and sometime without adding it. It depending on how they did the calcuation. Here is why – and simple math to throw off all the math you ever learned. How many fingers are you holding up when you hold up your 2nd thru 10th finger. The quick and wrong answer is 10-2 which is 8. The right answer is 10-2+1, which is 9. Try it: 2,3,4,5,6,7,8,9,10 (there are 9 digits there).

So here are the 2 numbers we need:
START BYTE: 10860003*512
SIZE (in BYTES): 57512637*512 or 57512636*512

(STEP 1 – IF GPT) If GPT – Get the START and SIZE BYTES

# sgdisk -p lunfile
Disk lunfile: 23068672 sectors, 11.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 583A4103-15CA-488F-A159-FD887273A850
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 23068638
Partitions will be aligned on 2-sector boundaries
Total free space is 4029 sectors (2.0 MiB)
Number  Start (sector)    End (sector)  Size       Code  Name
   1              34           65569   32.0 MiB    0C01  Microsoft reserved part
   2           67584        23066623   11.0 GiB    0700  Basic data partition

So just like the MBR case, we need the START byte of the partition, and the size of the partition.

Notice the start sector of the biggest partition (where the data is) is 67584. Now we also see that a Logical Sector size is 512 bytes. So 67584*512 will give us the start byte. (Again we dont need to do the math as linux will do that)

Size of the partition is 23066623-67584+1 sectors, or without plus one 23066623-67584. Which is 22999040 or 22999039 sectors. Or 22999040*512 bytes or 22999039*512 bytes.

START BYTE: 67584*512
SIZE (in BYTES): 22999040*512 bytes 22999039*512 bytes

(STEP 2) Point the Partition to a Loop device

Now look for an available loop device. “losetup -a” will tell you what loop devices you have used. If you dont have one used then use loop0 or loop#, where # is any number.

SIDENOTE: Note a system can usually use like 10 loop devices max, but you can ask for more like this:
http://www.tldp.org/HOWTO/CDServer-HOWTO/addloops.html
http://www.cyberciti.biz/tips/set-maximum-number-of-loop-devices.html
http://unix.stackexchange.com/questions/55356/how-do-i-setup-more-then-10-loopback-device
We dont have to worry about that since we are only going to be using 1 loop device / 1 partition.

Then run 1 of the 6 losetup commands below, depending on if your MBR or GPT and if you tried the previous losetup command before that and it didnt work. First try the simple one.

SIDENOTE: the simplest losetup command would be to point the whole lunfile to loop0, but Ive tested that and it doesnt work – it doesnt work especially for ntfs-3g mounts. (it might work for ext and xfs, as those are mounts that look for the MAGIC NUMBER of their filesystem): losetup /dev/loop0 lunfile

*** FROM MBR CASE: ***
Recall the numbers were this:

START BYTE: 10860003*512
SIZE (in BYTES): 57512637*512 or 57512636*512

So the losetup command will be this:

losetup /dev/loop0 lunfile -o $((10860003*512))

If that doesnt work for step 3, we can try specifying the sizelimit (the size of the partition)

losetup /dev/loop0 lunfile -o $((10860003*512)) --sizelimit $((57512637*512))

Or this one (where we didnt add the +1):

losetup /dev/loop0 lunfile -o $((10860003*512)) --sizelimit $((57512636*512))

Most likely, the very first one will work. Either way one of those will work

*** FROM GPT CASE: ***

Recall the numbers were this:

START BYTE: 67584*512
SIZE (in BYTES): 22999040*512 bytes 22999039*512 bytes

So the losetup command will be this:

losetup /dev/loop0 lunfile -o $((67584*512))

If that doesnt work for step 4, we can try specifying the sizelimit (the size of the partition)

losetup /dev/loop0 lunfile -o $((67584*512)) --sizelimit $((22999040*512))

Or this one (where we didnt add the +1):

losetup /dev/loop0 lunfile -o $((67584*512)) --sizelimit $((22999039*512))

Most likely, the very first one will work. Either way one of those will work

(STEP 3) Mount the Loop device

mount /dev/loop0 /mnt

Or if its NTFS

apt-get update
apt-get install ntfs-3g
ntfs-3g /dev/loop0 /mnt

SIDENOTE: if your ISCSI is in use right now by its initiator, try mounting the filesystem as readonly with -o ro.

mount -o ro /dev/loop0 /mnt

or

ntfs-3g -o ro /dev/loop0 /mnt

To undo everything:

You will need to do this if you want to try other losetup commands

To detach everything. First unmount the filesystem:

umount /mnt

Then detach the loop device.

losetup -d /dev/loop0

Check its detached with losetup -a:

losetup -a

USING KPARTX

KpartX uses the loop block devices to mount the disk images from different offsets. Each loop can be pointed to 1 file @ specific offset. KpartX points loop at whole file. Then dev mapper breaks appart each loop file into the partitions and then you see the partitions in /dev/mapper folder.

NOTE: I show examples using various different disk images, I dont just stick to showing disk image.

First download kpartx

apt-get install kpartx

SIDENOTE: to mount ntfs, download ntfs-3g: apt-get install ntfs-3g  & to mount vmfs download vmfs-tools: apt-get install vmfs-tools

Find the disk image and run this command to see how the partitions will be split up:

# kpartx -l /data/somediskimg0.img
GPT:Primary header thinks Alt. header is not at the end of the disk.
GPT:Alternate GPT header not at the end of the disk.
GPT: Use GNU Parted to correct GPT errors.
loop1p1 : 0 4294963200 /dev/loop1 2048

Find the disk image and run this command to mount somedisk.img:

# kpartx -v -a /data/somedisk.img

-v for verbose output, -a to attach the somedisk.img to the loop files and split up its partitions into /dev/mapper.

It will then make /dev/loop0 pointed at somedisk.img. Then its 3 partitions will be in

# ls -1 /dev/mapper
control
loop0p1
loop0p2
loop0p3

Ignore the control file.

Now you can use file -s /dev/loop0p1  to find out the filesystem type and continue to mount them.

# mount /dev/mapper/loop0p1 /mnt/p1
# ntfs-3g /dev/mapper/loop0p1 /mnt/p2
# vmfs-fuse /dev/mapper/loop0p1 /mnt/p3

## ex: 1st partition was ext3, 2nd partition was ntfs, 3rd partition was vmfs

If you then point kpartx -a at another file it will create loop1 and loop1

To recap all of your loop points

# to list the loop devices and what they are attached to
losetup -a 
# to see the partitions it found
ls -lisah /dev/mapper

Example:

# losetup -a
/dev/loop0: [0011]:258 (/data/disk3.img)
/dev/loop1: [001e]:258 (/data/disk4.img)

# ls -lisah /dev/mapper
total 0
 371 0 drwxr-xr-x 2 root root      100 Jul  8 18:55 .
1102 0 drwxr-xr-x 7 root root     2.3K Jul  8 18:55 ..
 372 0 crw-rw---- 1 root root  10, 236 Jul  8 09:04 control
1613 0 brw-r--r-- 1 root root 253,   0 Jul  8 18:54 loop0p1
1616 0 brw-r--r-- 1 root root 253,   1 Jul  8 18:55 loop1p1

# summary: so we know disk3.img made loop0 with 1 partition (loop0p1). disk4.img made loop1 with 1 partition (loop1p1)

Now you can mount loop0p1 or loop1p1 using your mount commands: mount, ntfs-3g, vmfs-fuse

Now how do you undo all of this, and get the loop devices back to an unused state? Well we simply have to use kpartx to delete the loop devices.

## STEP1) I want to undo /dev/loop1. First find out the filename of the disk image you want to undo, using losetup -a

# losetup -a
/dev/loop0: [0011]:258 (/data/disk3.img)
/dev/loop1: [001e]:258 (/data/disk4.img)

## STEP2) We see loop1 is /data/disk4.img. So now we delete the loop device with kpartx.

kpartx -d /data/disk4.img

NOTE: you first need to unmount all of the loop devices partitions.
NOTE: you cant use losetup -d to remove the loop devices, it will say its in use (as its in use by dev mapper to make the partitions in /dev/mapper). you have to remove the loop devices with kpartx

The end.

One thought on “Mount/Initiate to Iscsi Luns Locally – Mount Luns – Mount Partitioned ISOs

Leave a Reply

Your email address will not be published. Required fields are marked *