We need ROOT and a recovery console
Difference between cloning ( bit-stream copy ) and copying “per file”.
Per file copying is a filesystem aware method; the OS has to “know” the filesystem and only allocated data is copied. If there’s a lot of free space, this is a very efficient way to backup our data.
It is possible to copy, make an archive and compress it but it is better to copy, compress per file and THEN make an archive of compressed files.
In this way if the archive is damaged there are more chances to recover the files from the archive.
Afio is the tool that I use for this purpose:
It is also possible, with afio, cpio, pax, etc., to “copy pass”: copy from one directory/filesystem to another:
find /media/sda2/home/max/ -depth -print | cpio -pdmv /media/sda1/backup_home_max/
while a “solid” afio archive would be:
find /media/sda2/home/max/ -depth -print | afio -ovZ /media/sda1/backup_home_max/homemax.afio
There are a lot of interesting features in afio; it is possible to check the filesystem against the archive ( afio -rvZ in the above case), it is possible to check the archive contents ( afio -t ), it is possible to extract only files that match a regex, it is possible to call on an arbitrary compression software and provide it with some parameters ( for example xz -9 ).
With a bitstream copy the OS doesn’t mind what the filesystem is and doesn’t need a driver or a tool to interact with it. The filesystem is copied “bit to bit” in a file or in another filesystem.
dd if=/dev/sda of=/dev/sdb is a complete clone from one HD to another HD.
If you have lost some files or you need to inspect a drive for forensics this is the way to go.
It is also possible to do an md5sum of the HD and the clone to check whether they are exactly the same.
In addition to the old glorious dd there are a few other more specialised similar tools like ddrescue, dcfldd, dc3dd, sdd, etc.
Gnu ddrescue is the tool to use when you have a bad HD, as it is possible to recover as much data as possible “jumping” the bad sectors, then going back with multiple passes to recover more data from the damaged areas.
What do we need?
I would go with a bitstream copy, as my Samsung S4 I9505 internal memory has 29 partitions!! It would be a nightmare to make a copy per file from each partition.
With a clone I can restore the whole internal memory with just one command.
I can also recover some of the deleted data from the unallocated space.
Working in a reduced environment ( recovery ) where the unix tools are just busybox applets a bitstream copy is easier than a copy per file
In my Samsung S4 I9505 I have a Philz Recovery and it suits the purpose without any problems.
Starting the game
- Install ( or rather download and decompress ) adb.
I found the latest version here:
- Connect the phone to the pc via the usb cable
- Boot the phone in recovery mode
- If the phone asks for usb debugging say “yes”
- cd adt-bundle-linux-x86-20140702/sdk/platform-tools/
- Be sure that you have enough space to store the clone ( my GS4 has a 16G internal memory )
- launch ./adb shell
Now we should figure out the device:
cat /proc/mounts gives:
tmpfs /dev tmpfs rw,seclabel,nosuid,relatime,mode=755 0 0
devpts /dev/pts devpts rw,seclabel,relatime,mode=600 0 0
proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,seclabel,relatime 0 0
selinuxfs /sys/fs/selinux selinuxfs rw,relatime 0 0
tmpfs /tmp tmpfs rw,seclabel,relatime 0 0
tmpfs /storage tmpfs rw,seclabel,relatime,mode=050,gid=1028 0 0
tmpfs /mnt/secure tmpfs rw,seclabel,relatime,mode=700 0 0
tmpfs /mnt/fuse tmpfs rw,seclabel,relatime,mode=775,gid=1000 0 0
That is nice: the internal memory doesn’t seem to be mounted
Now lets try to find the internal memory device:
cat /proc/partitions gives:
major minor #blocks name
179 0 15388672 mmcblk0
179 1 12772 mmcblk0p1
179 2 52764 mmcblk0p2
179 3 128 mmcblk0p3
179 4 256 mmcblk0p4
179 5 512 mmcblk0p5
179 6 2048 mmcblk0p6
179 7 512 mmcblk0p7
179 8 512 mmcblk0p8
179 9 16896 mmcblk0p9
179 10 13952 mmcblk0p10
179 11 3072 mmcblk0p11
179 12 3072 mmcblk0p12
179 13 780 mmcblk0p13
179 14 780 mmcblk0p14
179 15 780 mmcblk0p15
179 16 2826240 mmcblk0p16
179 17 8192 mmcblk0p17
179 18 2119680 mmcblk0p18
179 19 6144 mmcblk0p19
179 20 10240 mmcblk0p20
179 21 10240 mmcblk0p21
179 22 10240 mmcblk0p22
179 23 6144 mmcblk0p23
179 24 3072 mmcblk0p24
179 25 8 mmcblk0p25
179 26 9216 mmcblk0p26
179 27 512000 mmcblk0p27
179 28 20480 mmcblk0p28
179 29 9728000 mmcblk0p29
179 32 30703616 mmcblk1
179 33 30699520 mmcblk1p1
mmcblk1, with mmcblk1p1 is the external microsd ( only one partition and is the second device )
mmcblk0 and its 29 partitions is the internal memory ( with 29 partitions…no doubts that this is a gpt partition table)
dd should do all the work:
./adb shell “dd if=/dev/block/mmcblk0”| dd of=/media/sda4/gs4_int_mem.dd or /adb shell “su -c dd if=/dev/block/mmcblk0”| dd of=/media/sda4/gs4_int_mem.dd if you are not root
After a couple of hours (!) I had my clone. A quick check with:
parted media/sda4/gs4.dd print
and a big disappointment!!
Error: Both the primary and backup are corrupted. Try making a fresh table, and using Parted’s rescue feature to recover partitions.
Disk /media/sda4/gs4_int_mem.dd: 15.8GB
Sector size (logical/physical): 512B/512B
Partition Table: unknown
Tried to recover the gpt with gpart…nope!
Tried to recover the gpt with testdisk…nope!
I changed the usb cable and tried with:
./adb shell "cat /dev/block/mmcblk0" | pv > mmcblk0.raw
…still corrupted GPT table
- dd is working as expected even if it is the “busybox” dd. The problem is adb which translates LF to CR-LF
The right command now is:
./adb shell 'stty raw && dd if=/dev/block/mmcblk0' > gs4_int_mem.dd
“stty raw” leaves the input and output “raw”, not translated
Now, parted gs4_int_mem.dd print gives:
Disk /media/sda4/gs4_int_mem.dd: 15.8GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: Number Start End Size File system Name Flags
1 4194kB 17.3MB 13.1MB apnhlos
2 17.3MB 71.3MB 54.0MB mdm
3 71.3MB 71.4MB 131kB sbl1
4 71.4MB 71.7MB 262kB sbl2
5 71.7MB 72.2MB 524kB sbl3
6 72.2MB 74.3MB 2097kB aboot
7 74.3MB 74.8MB 524kB rpm
8 74.8MB 75.4MB 524kB tz
9 75.4MB 92.7MB 17.3MB pad
10 92.7MB 107MB 14.3MB ext4 efs
11 107MB 110MB 3146kB modemst1
12 110MB 113MB 3146kB modemst2
13 113MB 114MB 799kB m9kefs1
14 114MB 115MB 799kB m9kefs2
15 115MB 116MB 799kB m9kefs3
16 116MB 3010MB 2894MB ext4 system
17 3010MB 3018MB 8389kB persist
18 3018MB 5189MB 2171MB ext4 cache
19 5189MB 5195MB 6291kB param
20 5195MB 5205MB 10.5MB boot
21 5205MB 5216MB 10.5MB recovery
22 5216MB 5226MB 10.5MB fota
23 5226MB 5233MB 6291kB backup
24 5233MB 5236MB 3146kB fsg
25 5236MB 5236MB 8192B ssd
26 5236MB 5245MB 9437kB ext4 persdata
27 5245MB 5770MB 524MB ext4 hidden
28 5770MB 5791MB 21.0MB carrier
29 5791MB 15.8GB 9961MB ext4 userdata
Here comes the bash
To mount one of the 29 partitions we need to calculate the offset of each one and pass it to the “mount” command:
mount -o loop,offset=xxx gs4_int_mem.dd /mount_point/
If we want to play with so many partitions we need something automatic:
###Simple ( KISS ) script to loopback mount a partition from an image
###calculate the offset
###Massimo Bollati one day in 2014
Check that we passed the file name to the command
if [ "$#" -ne "1" ]; then
echo -e "\n\n\t\t\033[01;31mYou didn’t insert the file name\n\n\t\tInsert: `basename $0` <image file>\n\n\n\033[01;33m" >&2
#Shows the partitions found
echo -e "\n\n\t\tFound these partitions:\n\n\n\t`parted $FILE print `\n\n"
echo -e "\n\n\t\tInsert the partion number and press return"
mkdir -p /media/offsetm
#Check if the partition is there
[ `parted -m $FILE print | cut -d ":" -f1|grep -v BYT|grep -v "/"|grep -w "^$PART"` ]
echo -e "\n\n\n\t\t\tMounting partition n. $PART in \033[40m\033[1;32m$DEST\033[0m\033[01;33m\n\n\n"
echo -e "\n\n\n\t\t\033[01;31mYou have inserted $PART but the partitions are:\n\n `parted $1 print` ....bye!!\033[01;33m\n\n\n"
##Enable if you want to check if parted is installed
#if ! which parted > /dev/null 2>&1; then
#echo "Can't find parted....exit" >&2
##Enable for debugging
UNITS=`parted -m $1 unit s print| grep -v "/" |cut -d ":" -f1-2|grep "^$PART:" | cut -d ":" -f2| sed -s s/s/""/`
OFFSET=`expr 512 '*' $UNITS`
###Enable below for debug
#echo -e "UNITS > $UNITS\nOFFSET $OFFSET\nDEST $DEST\nFILE $FILE"
mount -o loop,offset=$OFFSET $FILE $DEST
Don’t copy/paste the text above; this is markdown processed text…, better to download the script from here:
Now we can mount/unmount every partition in a few seconds and use our file manager to browse it! We can also extract the unallocated space with:
blkls -f filesystem -o offset disk.dd > disk.blkls
Recover deleted files with foremost/scalpel/photorec…
Here are some “real” examples:
List of the partitions found and prompt to insert the one we want to mount
Partition 29 was chosen and mounted in /media/offset
There are 5.3G of data
There is also a “hidden” partition…lets have a look…
Partition 27 ext4, hidden, is mounted in /media/offset
Hidden apps in the hidden partition ;-))
Last but not the least…lets have a look at the EFS partition!
Here are all the contents of the EFS partition, easy to backup!
There are some points that I have to improve in this script:
- manage more mount points (now one at a time )
- make a pseudo-gui with yad and strip all these unclear special characters ( bash colouring )
- make the script manage the whole process from cloning to mounting the partitions
- have a nice progress bar for the long cloning process