How to get the offset in a block device of an inode in a deleted partition - linux

During a fresh installation, I accidentally formatted a disk containing datas. I have tried using some tools: testdisk, foremost, but I did not get good results. (see my unsuccessful post on superuser).
So I have decided to read some docs about ext2 filesystem structure, and I could get some results:
The deleted partition have a directory tree like that:
dev
|-scripts
|-projects
|-services
|-...
Medias
|-downloads
|-Musique
|-...
backup
...
So, based on the ext2 directory entry format:
Directory Entry
Starting_Byte Ending_Byte Size_in_Bytes Field_Description
0 3 4 Inode
4 5 2 Total size of this entry (Including all subfields)
6 6 1 Name Length least-significant 8 bits
7 7 1 Type indicator (only if the feature bit for "directory entries have file type byte" is set, else this is the most-significant 8 bits of the Name Length)
8 8+N-1 N Name characters
I tried to find some datas matching this structure.
I used this script:
var bindexOf = require('buffer-indexof');
var currentOffset=0;
var deviceReadStream = fs.createReadStream("/dev/sdb");
deviceReadStream.on('error',function(err){
console.log(err);
});
deviceReadStream.on('data',function(data){
var dirs = ["dev","scripts","services","projects","Medias","downloads","Musique","backup"];
dirs.forEach(function(dir){
dirOctetFormat = new Buffer(2);
dirOctetFormat.writeUInt8(dir.length,0);
dirOctetFormat.writeUInt8(2,1);// type is directory
dirOctetFormat= Buffer.concat( [dirOctetFormat, new Buffer(dir)]);
var offset = bindexOf( data, dirOctetFormat );
if( offset >= 0 ){
console.log( dir + " entry found at offset " + (currentOffset + offset) );
}
});
currentOffset += data.length;
});
}
I found data which seems to be the directory entry of the dev directory:
===== Current offset: 233590226944 - 217.5478515625Gio ======
scripts entry found at offset 233590227030
services entry found at offset 233590227014
projects entry found at offset 233590228106
If it is the case, I got the inode numbers of its children directories: scripts, projects, services,...
But I do not know what to do with that!
I tried to deduce the location of these inodes, based on this guide,
but as I was unable to find a superblock of the deleted filesystem, I just have to make guesses about the block size, the number of blocks, ...
and that seems a little bit fuzzy to me to hope obtaining a result.
So could you have some intervals for all values needed to obtain the offset of an inode, and a more formal formula to get this offset?

If you have only erased the partition table (or modified it) you can still get your data, if data has not been reused for something else.
ext2 filesystems have a MAGIC number in superblock, so to recover your partition you have only to search for it. I did this on one machine and was able to recover not one, but seven partitions in one disk. You have some chances to get invalid numbers, but just search for that magic. Magic number is defined in include/uapi/linux/magic.h and value is #define EXT2_SUPER_MAGIC 0xEF53 (it's found at offset #define EXT2_SB_MAGIC_OFFSET 0x38 ---from file include/linux/ext2_fs.h)
To search for the superblock, just try to find 0xef53 at offset 0x38 in one sector of the disk, it will mark the first block of the partition. Be careful, that superblock is replicated several times in one partition, so you'll find all the copies of it.
Good luck! (I had when it happened to me)
Edit (To illustrate with an example)
Just see the magic number in one of my own partitions:
# hd /dev/sda3 | head -20
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000400 40 62 08 00 00 87 21 00 26 ad 01 00 f6 30 15 00 |#b....!.&....0..|
00000410 1d 31 08 00 00 00 00 00 02 00 00 00 02 00 00 00 |.1..............|
00000420 00 80 00 00 00 80 00 00 90 1f 00 00 cf 60 af 55 |.............`.U|
00000430 fc 8a af 55 2d 00 ff ff 53 ef 01 00 01 00 00 00 |...U-...S.......|<- HERE!!!
00000440 36 38 9d 55 00 00 00 00 00 00 00 00 01 00 00 00 |68.U............|
00000450 00 00 00 00 0b 00 00 00 00 01 00 00 3c 00 00 00 |............<...|
00000460 46 02 00 00 7b 00 00 00 5a bf 87 15 12 8f 44 3b |F...{...Z.....D;|
00000470 97 e7 f3 74 4d 75 69 12 72 6f 6f 74 00 00 00 00 |...tMui.root....|
00000480 00 00 00 00 00 00 00 00 2f 00 61 72 67 65 74 00 |......../.arget.|
00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 02 |................|
000004d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000004e0 08 00 00 00 00 00 00 00 00 00 00 00 93 54 99 ab |.............T..|
000004f0 aa 64 46 b3 a6 73 94 34 a3 79 46 28 01 01 00 00 |.dF..s.4.yF(....|
00000500 0c 00 00 00 00 00 00 00 e5 61 92 55 0a f3 02 00 |.........a.U....|
00000510 04 00 00 00 00 00 00 00 00 00 00 00 ff 7f 00 00 |................|
00000520 00 80 10 00 ff 7f 00 00 01 00 00 00 ff ff 10 00 |................|
Remember it is on offset 0x38 counted from the block origin, and assume the super block is the second block (block 0 reserved for bootcode, so it will be block 1, with two sectors per block, to make 1k blocksize) in the partition, so you'll have to rewind 0x438 bytes from the beginning of the magic number to get the partition origin.
I have run the command on my whole disk, getting the following result:
# hd /dev/sda | grep " [0-9a-f][0-9a-f] 53 ef" | sed -e 's/^/ /' | head
006f05f0 ee 00 00 11 66 0a 00 00 53 ef 00 00 11 66 2d 00 |....f...S....f-.|
007c21d0 55 2a aa 7d f4 aa 89 55 53 ef a4 91 70 40 c1 00 |U*.}...US...p#..|
20100430 fc 8a af 55 2d 00 ff ff 53 ef 01 00 01 00 00 00 |...U-...S.......|
2289a910 0f 8f 4f 03 00 00 81 fe 53 ef 00 00 0f 84 ce 04 |..O.....S.......|
230d4c70 0a 00 00 00 1c 00 00 00 53 ef 01 00 00 00 00 00 |........S.......|
231b7e50 a0 73 07 00 00 00 00 00 53 ef 0d 00 00 00 00 00 |.s......S.......|
23dbd230 d5 08 ad 2b ee 71 07 8a 53 ef c2 89 d4 bb 09 1f |...+.q..S.......|
25c0c9e0 06 00 00 00 00 4f 59 c0 53 ef 32 c0 0e 00 00 00 |.....OY.S.2.....|
25d72ca0 b0 b4 7b 3d a4 f7 84 3b 53 ef ba 3c 1f 32 b9 3c |..{=...;S..<.2.<|
25f0eab0 f1 fd 02 be 28 59 67 3c 53 ef 9c bd 04 30 72 bd |....(Yg<S....0r.|
Clearly, there are much more uninteresting lines in this listing than the ones we need. To locate the one interesting here, we have to do some computing with the numbers. We have seen that sectors are 512 bytes long (this is 0x200 in hex) and we can have the superblock magic at offset 0x438, so we expect valid offsets to be at 0xXXXXXX[02468ace]38 only. Just select the lines with offsets ending in that expression, and you'll get the first superblock valid (in the third line) at offset 0x20100430.
Substract 0x430 to give the byte offset of the partition (0x20100000, and then, divide the result by 0x200, giving 0x100800, or 1050624)
# fdisk -l /dev/sda | sed -e 's/^/ /'
Disk /dev/sda: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: DF97DAD4-727D-4BB3-BD7B-3C5A584A2747
Device Start End Sectors Size Type
/dev/sda1 2048 526335 524288 256M EFI System
/dev/sda2 526336 1050623 524288 256M BIOS boot
/dev/sda3 1050624 18628607 17577984 8.4G Linux filesystem <-- HERE!!!
/dev/sda4 18628608 77221887 58593280 28G Linux filesystem
/dev/sda5 77221888 85035007 7813120 3.7G Linux filesystem
/dev/sda6 85035008 104566783 19531776 9.3G Linux filesystem
/dev/sda7 104566784 135817215 31250432 14.9G Linux swap
/dev/sda8 135817216 155348991 19531776 9.3G Linux filesystem
/dev/sda9 155348992 1953523711 1798174720 857.4G Linux filesystem

Related

std::map (Enum / CString) is triggering a memory leak in my app - why?

I have looked at similar discussions (std::map causing memory leaks?) about this issue but according to the debug build of my app this is triggering a memory leak:
void CMeetingScheduleAssistantApp::SetLocale(LanguageMSA eLang)
{
// See: https://www.microsoft.com/resources/msdn/goglobal/default.mspx#ISO2
map<LanguageMSA, CString> mapLocales;
mapLocales.emplace(LanguageMSA::Afrikaans, _T("af"));
mapLocales.emplace(LanguageMSA::Albanian, _T("sqi"));
mapLocales.emplace(LanguageMSA::Arabic, _T("ara"));
mapLocales.emplace(LanguageMSA::Aukan, _T("drk"));
mapLocales.emplace(LanguageMSA::Bulgarian, _T("bgr"));
mapLocales.emplace(LanguageMSA::ChineseSimplified, _T("chs"));
mapLocales.emplace(LanguageMSA::Croatian, _T("hrv"));
mapLocales.emplace(LanguageMSA::Czech, _T("csy"));
mapLocales.emplace(LanguageMSA::Danish, _T("dan"));
mapLocales.emplace(LanguageMSA::Dutch, _T("nld"));
mapLocales.emplace(LanguageMSA::English, _T("eng"));
mapLocales.emplace(LanguageMSA::Estonian, _T("et"));
mapLocales.emplace(LanguageMSA::Finnish, _T("fin"));
mapLocales.emplace(LanguageMSA::French, _T("fra"));
mapLocales.emplace(LanguageMSA::German, _T("deu"));
mapLocales.emplace(LanguageMSA::Greek, _T("ell"));
mapLocales.emplace(LanguageMSA::Gujarati, _T("guj"));
mapLocales.emplace(LanguageMSA::Hindi, _T("hin"));
mapLocales.emplace(LanguageMSA::Hungarian, _T("hu-HU"));
mapLocales.emplace(LanguageMSA::Indonesian, _T("ind"));
mapLocales.emplace(LanguageMSA::Italian, _T("ita"));
mapLocales.emplace(LanguageMSA::Japanese, _T("jpn"));
mapLocales.emplace(LanguageMSA::Lingala, _T("ln-CG"));
mapLocales.emplace(LanguageMSA::Maltese, _T("mt-MT"));
mapLocales.emplace(LanguageMSA::Polish, _T("plk"));
mapLocales.emplace(LanguageMSA::PortugueseBrazil, _T("ptb"));
mapLocales.emplace(LanguageMSA::PortuguesePortugal, _T("pt-PT"));
mapLocales.emplace(LanguageMSA::Punjabi, _T("pa"));
mapLocales.emplace(LanguageMSA::Romanian, _T("rom"));
mapLocales.emplace(LanguageMSA::Russian, _T("rus"));
mapLocales.emplace(LanguageMSA::Saramaccan, _T("fra")); // Special case (uses French)
mapLocales.emplace(LanguageMSA::Setswana, _T("tn-ZA"));
mapLocales.emplace(LanguageMSA::Slovenian, _T("slv"));
mapLocales.emplace(LanguageMSA::Spanish, _T("esp"));
mapLocales.emplace(LanguageMSA::Swahili, _T("swk"));
mapLocales.emplace(LanguageMSA::Swedish, _T("sve"));
mapLocales.emplace(LanguageMSA::Tagalog, _T("fil-PH"));
mapLocales.emplace(LanguageMSA::Tamil, _T("tai"));
mapLocales.emplace(LanguageMSA::Tsonga, _T("tso"));
mapLocales.emplace(LanguageMSA::Turkish, _T("trk"));
mapLocales.emplace(LanguageMSA::Ukrainian, _T("ukr"));
mapLocales.emplace(LanguageMSA::Vietnamese, _T("vit"));
mapLocales.emplace(LanguageMSA::Zulu, _T("zu-ZA"));
CString strLocale = _T("eng"); // Default (also used by some "partial" translations
if (mapLocales.find(eLang) != mapLocales.end())
strLocale = mapLocales[eLang];
_tsetlocale(LC_ALL, strLocale);
}
Please advise if there is anything I need to do to stop this memory leak being listed when the debug version closes. Or is it a red herring in this case?
LanguageMSA is an enum class:
enum class LanguageMSA
{
English = 0,
German,
Spanish,
Italian,
Polish,
French,
PortugueseBrazil,
Dutch,
Swedish,
Slovenian,
Czech,
Finnish,
Danish,
Ukrainian,
Russian,
Tagalog,
HaitianCreole,
Afrikaans,
Albanian,
ChineseSimplified,
Croatian,
Turkish,
Twi,
Swahili, // AJT v11.3.4
Estonian, // AJT v12.0.5
Romanian, // AJT v12.0.8
Greek, // AJT v13.0.0
Bulgarian, // AJT v13.0.2
Malagasy, // AJT v14.0.4‏
Arabic, // AJT v16.0.0
Indonesian, // AJT v16.0.2
Hindi, // AJT v16.0.7
Tamil, // AJT v16.1.0
Vietnamese, // AJT v16.1.1
Zulu, // AJT v16.1.6
Gun, // AJT v17.0.9
Lingala, // AJT v17.0.9
PortuguesePortugal, // AJT v17.1.0
Punjabi, // AJT v17.1.3
Maltese, // AJT v17.2.3
Hungarian, // AJT v17.2.6
Saramaccan, // AJT v18.0.0
Amharic, // AJT v18.0.6
Japanese, // AJT v18.0.6
Setswana, // AJT v18.0.8
Sranantongo,// AJT v18.1.4
Aukan, // AJT v18.1.6
Armenian, // AJT v18.2.1
Gujarati, // AJT v19.0.9
Sesotho, // AJT v20.0.3
Cebuano, // AJT v20.1.2
Tsonga, // AJT v20.1.5
PidginWestAfrica, // AJT v20.3.0
// Maintain a count of language enums
Count
} ;
Memory leak dump:
Detected memory leaks!
Dumping objects ->
{104257} normal block at 0x0000028AC8015830, 40 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 07 00 00 00 07 00 00 00
{104255} normal block at 0x0000028AC8015210, 40 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 07 00 00 00 07 00 00 00
{104253} normal block at 0x0000028AC706A920, 168 bytes long.
Data: < (R ÈŠ > 05 00 00 00 00 00 00 00 28 52 01 C8 8A 02 00 00
{104244} normal block at 0x0000028AE311F820, 34 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 04 00 00 00 04 00 00 00
{104242} normal block at 0x0000028AE311EEC0, 34 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 04 00 00 00 04 00 00 00
{104241} normal block at 0x0000028AC706A0B0, 168 bytes long.
Data: < Øî ㊠> 04 00 00 00 00 00 00 00 D8 EE 11 E3 8A 02 00 00
{104232} normal block at 0x0000028AC80152F0, 38 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 06 00 00 00 06 00 00 00
{104230} normal block at 0x0000028AC6CF9690, 54 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0E 00 00 00 0E 00 00 00
{104229} normal block at 0x0000028AC7069C00, 168 bytes long.
Data: < ¨–ÏÆŠ > 03 00 00 00 00 00 00 00 A8 96 CF C6 8A 02 00 00
{104220} normal block at 0x0000028AC8015DE0, 42 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 08 00 00 00 08 00 00 00
{104218} normal block at 0x0000028AC6CF8F10, 58 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 10 00 00 00 10 00 00 00
{104217} normal block at 0x0000028AC706B280, 168 bytes long.
Data: < ( ÏÆŠ > 02 00 00 00 00 00 00 00 28 8F CF C6 8A 02 00 00
{104208} normal block at 0x0000028AC80151A0, 46 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0A 00 00 00 0A 00 00 00
{104206} normal block at 0x0000028AC80164E0, 46 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0A 00 00 00 0A 00 00 00
{104204} normal block at 0x0000028AC706B910, 168 bytes long.
Data: < ød ÈŠ > 01 00 00 00 00 00 00 00 F8 64 01 C8 8A 02 00 00
{104195} normal block at 0x0000028AC8016A20, 52 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0D 00 00 00 0D 00 00 00
{104193} normal block at 0x0000028AC8014560, 52 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0D 00 00 00 0D 00 00 00
{104191} normal block at 0x0000028AC706A830, 168 bytes long.
Data: < xE ÈŠ > 00 00 00 00 00 00 00 00 78 45 01 C8 8A 02 00 00
{103563} normal block at 0x0000028AC80157C0, 40 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 07 00 00 00 07 00 00 00
{103561} normal block at 0x0000028AC8013B50, 40 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 07 00 00 00 07 00 00 00
{103559} normal block at 0x0000028AC706B820, 168 bytes long.
Data: < h; ÈŠ > 05 00 00 00 00 00 00 00 68 3B 01 C8 8A 02 00 00
{103550} normal block at 0x0000028AC7090340, 34 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 04 00 00 00 04 00 00 00
{103548} normal block at 0x0000028AC7090DC0, 34 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 04 00 00 00 04 00 00 00
{103547} normal block at 0x0000028AC706B730, 168 bytes long.
Data: < Ø ÇŠ > 04 00 00 00 00 00 00 00 D8 0D 09 C7 8A 02 00 00
{103538} normal block at 0x0000028AC8016BE0, 38 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 06 00 00 00 06 00 00 00
{103536} normal block at 0x0000028AC6CF8E90, 54 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0E 00 00 00 0E 00 00 00
{103535} normal block at 0x0000028AC706A290, 168 bytes long.
Data: < ¨ŽÏÆŠ > 03 00 00 00 00 00 00 00 A8 8E CF C6 8A 02 00 00
{103526} normal block at 0x0000028AC80169B0, 42 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 08 00 00 00 08 00 00 00
{103524} normal block at 0x0000028AC6CF8D10, 58 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 10 00 00 00 10 00 00 00
{103523} normal block at 0x0000028AC706A380, 168 bytes long.
Data: < ( ÏÆŠ > 02 00 00 00 00 00 00 00 28 8D CF C6 8A 02 00 00
{103514} normal block at 0x0000028AC8015F30, 46 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0A 00 00 00 0A 00 00 00
{103512} normal block at 0x0000028AC8013FB0, 46 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0A 00 00 00 0A 00 00 00
{103510} normal block at 0x0000028AC706A650, 168 bytes long.
Data: < È? ÈŠ > 01 00 00 00 00 00 00 00 C8 3F 01 C8 8A 02 00 00
{103501} normal block at 0x0000028AC8013CA0, 52 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0D 00 00 00 0D 00 00 00
{103499} normal block at 0x0000028AC8013760, 52 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0D 00 00 00 0D 00 00 00
{103497} normal block at 0x0000028AC706BA00, 168 bytes long.
Data: < x7 ÈŠ > 00 00 00 00 00 00 00 00 78 37 01 C8 8A 02 00 00
{101036} normal block at 0x0000028AC8013990, 40 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 07 00 00 00 07 00 00 00
{101034} normal block at 0x0000028AC8014640, 40 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 07 00 00 00 07 00 00 00
{101032} normal block at 0x0000028AC706B190, 168 bytes long.
Data: < XF ÈŠ > 05 00 00 00 00 00 00 00 58 46 01 C8 8A 02 00 00
{101023} normal block at 0x0000028AE311F700, 34 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 04 00 00 00 04 00 00 00
{101021} normal block at 0x0000028AE311E5C0, 34 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 04 00 00 00 04 00 00 00
{101020} normal block at 0x0000028AC706A740, 168 bytes long.
Data: < Øå ㊠> 04 00 00 00 00 00 00 00 D8 E5 11 E3 8A 02 00 00
{101011} normal block at 0x0000028AC8013680, 38 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 06 00 00 00 06 00 00 00
{101009} normal block at 0x0000028AC6CDEA80, 54 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0E 00 00 00 0E 00 00 00
{101008} normal block at 0x0000028AC706A560, 168 bytes long.
Data: < êÍÆŠ > 03 00 00 00 00 00 00 00 98 EA CD C6 8A 02 00 00
{100999} normal block at 0x0000028AC8015050, 42 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 08 00 00 00 08 00 00 00
{100997} normal block at 0x0000028AC6CDF900, 58 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 10 00 00 00 10 00 00 00
{100996} normal block at 0x0000028AC706ADD0, 168 bytes long.
Data: < ùÍÆŠ > 02 00 00 00 00 00 00 00 18 F9 CD C6 8A 02 00 00
{100987} normal block at 0x0000028AC80135A0, 46 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0A 00 00 00 0A 00 00 00
{100985} normal block at 0x0000028AC8014FE0, 46 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0A 00 00 00 0A 00 00 00
{100983} normal block at 0x0000028AC706B0A0, 168 bytes long.
Data: < øO ÈŠ > 01 00 00 00 00 00 00 00 F8 4F 01 C8 8A 02 00 00
{100974} normal block at 0x0000028AC80145D0, 52 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0D 00 00 00 0D 00 00 00
{100972} normal block at 0x0000028AC8014480, 52 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0D 00 00 00 0D 00 00 00
{100970} normal block at 0x0000028AC706B460, 168 bytes long.
Data: < D ÈŠ > 00 00 00 00 00 00 00 00 98 44 01 C8 8A 02 00 00
{12591} normal block at 0x0000028AC64B5970, 40 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 07 00 00 00 07 00 00 00
{12589} normal block at 0x0000028AC64B5740, 40 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 07 00 00 00 07 00 00 00
{12587} normal block at 0x0000028AC7F8D9D0, 168 bytes long.
Data: < XWKÆŠ > 05 00 00 00 00 00 00 00 58 57 4B C6 8A 02 00 00
{12578} normal block at 0x0000028AC7F06DB0, 34 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 04 00 00 00 04 00 00 00
{12576} normal block at 0x0000028AC7F07830, 34 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 04 00 00 00 04 00 00 00
{12575} normal block at 0x0000028AC7F8D8E0, 168 bytes long.
Data: < HxðÇŠ > 04 00 00 00 00 00 00 00 48 78 F0 C7 8A 02 00 00
{12566} normal block at 0x0000028AC64B5890, 38 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 06 00 00 00 06 00 00 00
{12564} normal block at 0x0000028AC6496AE0, 54 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0E 00 00 00 0E 00 00 00
{12563} normal block at 0x0000028AC7F8D7F0, 168 bytes long.
Data: < øjIÆŠ > 03 00 00 00 00 00 00 00 F8 6A 49 C6 8A 02 00 00
{12554} normal block at 0x0000028AC64B5820, 42 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 08 00 00 00 08 00 00 00
{12552} normal block at 0x0000028AC64965E0, 58 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 10 00 00 00 10 00 00 00
{12551} normal block at 0x0000028AC7F8E240, 168 bytes long.
Data: < øeIÆŠ > 02 00 00 00 00 00 00 00 F8 65 49 C6 8A 02 00 00
{12542} normal block at 0x0000028AC64B4E10, 46 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0A 00 00 00 0A 00 00 00
{12540} normal block at 0x0000028AC64B53C0, 46 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0A 00 00 00 0A 00 00 00
{12538} normal block at 0x0000028AC7F8D610, 168 bytes long.
Data: < ØSKÆŠ > 01 00 00 00 00 00 00 00 D8 53 4B C6 8A 02 00 00
{12529} normal block at 0x0000028AC64B4D30, 52 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0D 00 00 00 0D 00 00 00
{12527} normal block at 0x0000028AC64B4C50, 52 bytes long.
Data: < 3#^ö > 00 33 23 5E F6 7F 00 00 0D 00 00 00 0D 00 00 00
{12525} normal block at 0x0000028AC7EE7740, 168 bytes long.
Data: < hLKÆŠ > 00 00 00 00 00 00 00 00 68 4C 4B C6 8A 02 00 00
Object dump complete.

Exif TIFF field offset doesn't point to correct value

I'm trying to extract the DateTime from a JPEG file's Exif header. I did a quick hex dump to try and locate the Tiff entry. Here's a snippet of the hex dump:
00000000 ff d8 ff e1 27 19 45 78 69 66 00 00 4d 4d 00 2a |....'.Exif..MM.*|
00000010 00 00 00 08 00 0b 01 0f 00 02 00 00 00 06 00 00 |................|
.
.
00000060 00 02 00 00 00 05 00 00 00 b6 01 32 00 02 00 00 |...........2....|
00000070 00 14 00 00 00 bc 02 13 00 03 00 00 00 01 00 01 |................|
.
.
000000b0 78 00 00 00 00 48 00 00 00 01 00 00 00 48 00 00 |x....H.......H..|
000000c0 00 01 31 32 2e 32 00 00 32 30 31 39 3a 30 35 3a |..12.2..2019:05:|
000000d0 31 32 20 31 32 3a 30 32 3a 35 38 00 00 20 82 9a |12 12:02:58.. ..|
So from the hex dump, I know that:
The image is "Motorola" type byte aligned because of (0x4d4d)
The tag is DateTime 0x0132 (address 0x006a to 0x006b)
The tag type is 0x0002 which represents ascii string type (address 0x006c to 0x006d)
The number of components is 0x00000014 which is 20 in decimal(address 0x006e to 0x0071)
The value field, which is the offset to the actual value in this case, is 0x000000bc (address 0x0072 to 0x0075).
Now, if I look at the 20 bytes of value starting from address 0x00bc, it starts off with 0x00, 0x48, 0x00, 0x00, which doesn't represent anything. And it gets cut off at address 0xcf which doesn't include the entire date string. And as you can probably see, the actual date value starts at address 0x00c8 with bytes 0x32 0x30 0x31 0x39 0x3a, which is "2019:" and should continue until address 0xdb.
Can anyone explain why this is happening??
the address of any pointer calculate with base+offset and the base in this case is 0x0C because TIFF header start at 0x0C so 0xBC+0x0C=0xC8 that point to Date, also consider that the end of Date has 0x00 so total length is 20.
you can read more about it at this site.

Recover BMP image header

I am trying to recover some BMP image header, and the all information I got is this:
the bytes of the header that have been deleted are 54
the start offset is 1130 (decimal)
the width is 350 (decimal).
bits per pixel is 8
no compression
So I read little bit (mostly from here) and I saw which bytes present what, and I got the next first 54 bytes of the BMP header:
42 4D 6E 7F 0C 00 00 00 00 00 36 00 00 00 28 00 00 00 F4 01 00 00 22 02 00 00 01 00 18 00 00 00 00 00 38 7F 0C 00 13 0B 00 00 13 0B 00 00 00 00 00 00 00 00 00 00
But for some reason, when I am trying to open my all BMP images and my header, I get just a black image. Did I do something wrong? Do I build the
wrong header from the information above?

The value Address of Entry Point different in PE Explorer and UltraEdit

I wrote a basic helloworld.exe with C with the simple line printf("helloworld!\n");
Then I used UltraEdit to view the bytes of the EXE file and used also PE Explorer to see the header values. When it comes to Address of Entry Point, PE Explorer displays 0x004012c0.
Magic 010Bh PE32
Linker Version 1902h 2.25
Size of Code 00008000h
Size of Initialized Data 0000B000h
Size of Uninitialized Data 00000C00h
Address of Entry Point 004012C0h
Base of Code 00001000h
Base of Data 00009000h
Image Base 00400000h
But in UltraEdit I see 0x000012c0 after counting 16 bytes after magic 0x010B.
3F 02 00 00 E0 00 07 03 0B 01 02 19 00 80 00 00
00 B0 00 00 00 0C 00 00 C0 12 00 00 00 10 00 00
00 90 00 00 00 00 40 00 00 10 00 00 00 02 00 00
04 00 00 00 01 00 00 00 04 00 00 00 00 00 00 00
00 10 01 00 00 04 00 00 91 F6 00 00 03 00 00 00
00 00 20 00 00 10 00 00 00 00 10 00 00 10 00 00
00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00
00 E0 00 00 C0 06 00 00 00 00 00 00 00 00 00 00
Which one is correct?
simply read about IMAGE_OPTIONAL_HEADER structure
AddressOfEntryPoint
A pointer to the entry point function, relative to the image base
address. For executable files, this is the starting address. For
device drivers, this is the address of the initialization function.
The entry point function is optional for DLLs. When no entry point is
present, this member is zero.
so absolute address of EntryPoint is AddressOfEntryPoint ? ImageBase + AddressOfEntryPoint : 0
in your case AddressOfEntryPoint == 12c0 and ImageBase == 400000
as result absolute address of EntryPoint is 12c0+400000==4012c0

How to decode the section table in an ELF?

I'm analyzing this tiny ELF file:
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 3e 00 01 00 00 00 78 00 40 00 00 00 00 00 |..>.....x.#.....|
00000020 40 00 00 00 00 00 00 00 98 00 00 00 00 00 00 00 |#...............|
00000030 00 00 00 00 40 00 38 00 01 00 40 00 03 00 02 00 |....#.8...#.....|
00000040 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 |................|
00000050 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 |..#.......#.....|
00000060 7e 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 |~.......~.......|
00000070 00 00 20 00 00 00 00 00 31 c0 ff c0 cd 80 00 2e |.. .....1.......|
00000080 73 68 73 74 72 74 61 62 00 2e 74 65 78 74 00 00 |shstrtab..text..|
00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000000d0 00 00 00 00 00 00 00 00 0b 00 00 00 01 00 00 00 |................|
000000e0 06 00 00 00 00 00 00 00 78 00 40 00 00 00 00 00 |........x.#.....|
000000f0 78 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 |x...............|
00000100 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000110 00 00 00 00 00 00 00 00 01 00 00 00 03 00 00 00 |................|
00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000130 7e 00 00 00 00 00 00 00 11 00 00 00 00 00 00 00 |~...............|
00000140 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000150 00 00 00 00 00 00 00 00 |........|
00000158
I found documentation on the ELF header and the program header and decoded both of those, but I'm having problems decoding what's after this (starting with 31 c0 ff c0 cd 80 00 2e). Judging by the "shstrtab" text, I am looking at the section table, but what does 31 c0 ff c0 cd 80 00 2e mean? Where is this part documented?
OK, judging by the information in the first 16 bytes of the header:
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
E L F | | '--- Pudding :) ---'
| '--- Little-endian (ELFDATA2LSB)
'------ 64-bit (ELFCLASS64)
we're dealing with a 64-bit ELF with little-endian encoding of multi-byte numbers. So the ELF header is the first 4 rows in the hex editor. We're interested in these fields in the last two rows of it:
Prog Hdr Tab offset Sect Hdr Tab offset
.----------^----------. .----------^----------.
00000020 40 00 00 00 00 00 00 00 98 00 00 00 00 00 00 00 |#...............|
00000030 00 00 00 00 40 00 38 00 01 00 40 00 03 00 02 00 |....#.8...#.....|
'-.-' '-.-' '-.-' '-.-' '-.-'
PHT entry size ---' | | | '-- Sect names in #2
PHT num entries ----------' | '-- SHT num entries
'-------- SHT entry size
So we know that the Program Headers Table starts at offset 0x40 in the file (right after this header) and contains 1 entry of size 0x38 (56 bytes). So it ends at offset 0x40 + 1*0x38 = 0x78 (this is the first byte after this table, and this is also where your "mysterious data" begins, so keep this in mind).
The Section Headers Table starts at offset 0x98 in the file and contains 3 entries of size 0x40 (64 bytes), that is, each entry in SHT takes 4 consecutive rows in a hex editor, and the entire table is 3*4 = 12 such rows, so the offset 0x158 is the first byte after this table. But this is just the end of the file, so there's nothing more after the SHT.
The SHT entry at index 2 (the third=last one) should be a string table that contains the names for the sections.
So let's look at those sections now, shall we?
Section #2
Let's start with section #2, since it is supposed to contain the string table with the names for all the sections, so it will be very useful in further analysis. Here's its header (the last one in the table):
Name index Type=SHT_STRTAB (bingo!)
Flags .----^----. .----^----.
00000118 .----------^----------. 01 00 00 00 03 00 00 00 |........|
00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000130 7e 00 00 00 00 00 00 00 11 00 00 00 00 00 00 00 |~...............|
'----------.----------' '----------.----------'
Starting offset Size
00000140 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000150 00 00 00 00 00 00 00 00 |........|
00000158
So this is indeed a string table (0x03 = SHT_STRTAB). It starts from offset 0x7E in the file and takes 0x11 (17) consecutive bytes. The first byte after the string table is therefore 0x8F. This byte is not a part of any section (garbage).
The string table
So let's see what's in the section containing the string table, so that we could name our sections:
0000007E 00 2e |..|
00000080 73 68 73 74 72 74 61 62 00 2e 74 65 78 74 00 |shstrtab..text.|
0000008F
Here's the string table, with addresses relative to its beginning:
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
00: 00 2E 73 68 73 74 72 74 61 62 00 2e 74 65 78 74
10: 00
or the same in ASCII, with the NULL characters marked as ∎:
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
00: ∎ . s h s t r t a b ∎ . t e x t
10: ∎
So we have just 3 full string in it, with the following relative offsets:
00: "" (Just the empty string)
01: ".shstrtab" (Name for this section)
0B: ".text" (Name for the section that contains the executable code)
(Keep in mind, though, that sections can also address substrings inside those strings, if they share the common ending.)
We can now verify that this section (#2) is indeed named .shstrtab: its name index was 0x01 after all, wasn't it? ;)
Section #1
Now let's take apart section #1's header:
Name index Type=SHT_PROGBITS
Flags .----^----. .----^----.
000000d8 .----------^----------. 0b 00 00 00 01 00 00 00 |........|
000000e0 06 00 00 00 00 00 00 00 78 00 40 00 00 00 00 00 |........x.#.....|
000000f0 78 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 |x...............|
'----------.----------' '----------.----------'
Starting offset Size
00000100 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000110 00 00 00 00 00 00 00 00 |........|
00000118
So this section is named .text (note the name index 0x0B) and it is of type SHT_PROGBITS, so it contains some program-defined data; the executable code in this case. It starts from the offset 0x78 in the file and takes the next 6 bytes, so the first byte after this section is at offset 0x7E (where the string table begins). Here's its contents:
00000070 31 c0 ff c0 cd 80 |1.....|
0000007E
But wait! Remember where your "mysterious data" starts? Yes! It's the 0x78 offset! :) So this "mysterious data" is actually your executable payload :) After decoding it as Intel x86-64 opcodes we get this tiny little program:
31 C0 xor %eax,%eax ; Clear the EAX register to 0 (the short way).
FF C0 inc %eax ; Increase the EAX, so now it contains 1.
CD 80 int $0x80 ; Interrupt 0x80 is the system call on Linux.
which is basically equivalent to calling exit(0) in C ;) because the syscall interrupt expects the operation number in EAX, which in this case is sys_exit (operation number 1).
So yeah, mystery solved :) But let's continue anyway, to learn something more, and this way we'll find out where this piece of code will be loaded in memory.
Section #0
And finally section #0. It has some part missing, but I assume it was all 0s, since the first section is always a NULL section after all. Here's its (butchered) header:
00000098 00 00 00 00 00 00 00 00 | ........|
*
000000d0 00 00 00 00 00 00 00 00
But it's of no use to us. Nothing interesting here.
Program Headers Table
The last thing what's left to decode is the Program Headers Table, which – according to the information from the ELF header – starts from the offset 0x40 and takes 56 bytes, the first byte after it being at offset 0x78. Here's the dump:
Type=PHT_EXEC Flags=RX Starting offset in file
.----^----. .----^----. .----------^----------.
00000040 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 |................|
00000050 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 |..#.......#.....|
'----------.----------' '----------.----------'
Virtual address Physical address
Size in file Size in memory
.----------^----------. .----------^----------.
00000060 7e 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 |~.......~.......|
00000070 00 00 20 00 00 00 00 00
00000078 '----------.----------'
Alignment
So it says that we load the first 126 (0x7E) bytes of the file into a memory segment of the same size, and the memory segment is supposed to start from the virtual address 0x400000. Our code starts from the offset 0x78 in the file and the first byte after it has the offset 0x7E, so it basically loads the entire beginning of the file, with the ELF header and the program header table into memory, as well as our executable payload at the end of it, and stops loading afterwards, ignoring the rest of the file.
So if the beginning of the file is loaded at address 0x400000, and our program starts 120 (0x78) bytes from its beginning, it will be located at the address 0x400078 in memory :>
Now let's see what entry point is specified in the ELF header for our program:
Executable x86-64 Version=1 Program's entry point
.-^-. .-^-. .----^----. .----------^----------.
00000010 02 00 3e 00 01 00 00 00 78 00 40 00 00 00 00 00 |..>.....x.#.....|
Bingo! :> It's 0x400078, so it points at the start of our little piece of code in the memory image.
And that's all, folks! ;)

Resources