From 790f837e4fedd53c4ba39eb0b2ea3e9464ca5d50 Mon Sep 17 00:00:00 2001 From: Jozef Izso Date: Thu, 23 Mar 2023 08:59:59 +0100 Subject: [PATCH] patterns/dsstore: Added `.DS_Store` pattern (#90) * Initial format for Buddy Allocator structures in `.DS_Store` files * Add list of entries for files in `.DS_Store` * Add root block, offsets, toc and free lists structures * Add parsing of block data * Document `.DS_Store` pattern and add test file --- README.md | 1 + patterns/dsstore.hexpat | 113 ++++++++++++++++++ .../patterns/test_data/dsstore.hexpat.dsstore | Bin 0 -> 10244 bytes 3 files changed, 114 insertions(+) create mode 100644 patterns/dsstore.hexpat create mode 100644 tests/patterns/test_data/dsstore.hexpat.dsstore diff --git a/README.md b/README.md index aa04b2f..f294792 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ Hex patterns, include patterns and magic files for the use with the ImHex Hex Ed | PIF | `image/pif` | [`patterns/pif.hexpat`](patterns/pif.hexpat) | PIF Image Format | | JPEG | `image/jpeg` | [`patterns/jpeg.hexpat`](patterns/jpeg.hexpat) | JPEG Image Format | | DEX | | [`patterns/dex.hexpat`](patterns/dex.hexpat) | Dalvik EXecutable Format | +| DS_Store | `application/octet-stream` | [`patterns/dsstore.hexpat`](patterns/dsstore.hexpat) | .DS_Store file format | ### Scripts diff --git a/patterns/dsstore.hexpat b/patterns/dsstore.hexpat new file mode 100644 index 0000000..0ff36c5 --- /dev/null +++ b/patterns/dsstore.hexpat @@ -0,0 +1,113 @@ +// Apple macOS .DS_Store format +#pragma endian big +#include + +struct RecordEntry { + u32 length; + char16 filename[length]; + + char id[4]; + // either blob or length + char type[4]; + + if (type == "blob") { + u32 blobCount; + u8 blobData[blobCount]; + } + else if (type == "long") { + u32 value; + } + else if (type == "shor") { + u32 value; + } + else if (type == "bool") { + u8 value; + } +}; + +struct TreeBlock { + u32 mode; + u32 count; + RecordEntry entries[count]; +}; + +struct BuddyRootBlockOffsets { + u32 count; + u8 reserved[4]; + u32 addresses[count]; + padding[(1024 - (count * 4))]; +}; + +struct BuddyTableOfContentEntry { + u8 count; + char name[count]; + u32 value; +}; + +struct BuddyTableOfContents { + u32 count; + BuddyTableOfContentEntry toc[count]; +}; + +struct BuddyFreeList { + u32 count; + u32 offsets[count]; +}; + +struct BuddyRootBlock { + BuddyRootBlockOffsets offsets; + BuddyTableOfContents toc; + BuddyFreeList freelists[32]; +}; + +struct BuddyBlock { + u32 blockCount; + u8 reserved[4]; + // padding for next multiple of 256 entries (1024 bytes) + u32 addresses[blockCount]; + + // u8 padding[paddingCount]; + u32 directoryCount; + + // directory entries + u8 count; + u8 name[count]; + u32 blockNumber; + + // free lists + // 32 free lists + BuddyRootBlockOffsets off[32]; +}; + +struct BlocksList { + u32 blockId [[color("E57373")]]; + u32 internalBlocks [[color("80CBC4")]]; + u32 countRecords [[color("ffeb3b")]]; + u32 countBlocks [[color("64b5f6")]]; + u32 reserved [[color("a1887f")]]; +}; + +struct BuddyAllocator { + char header[4]; + u32 offsetBookkeeping; + u32 sizeBookkeeping; + u32 offsetBookkeeping2; + u32 offsetData; + u8 reserved[12]; + + BuddyRootBlock root @ offsetBookkeeping + 4; + + std::print("TOC {} address 0x{:08x}", + root.toc.toc[0].value, + root.offsets.addresses[root.toc.toc[0].value] >> 0x5 << 0x5); + + BlocksList blocks @ (root.offsets.addresses[root.toc.toc[0].value] >> 0x5 << 0x5) + 4; + + std::print("Blocks start at address 0x{:08x}, size 0x{:04x}", + root.offsets.addresses[blocks.blockId] >> 0x5 << 0x5, + 1 << (root.offsets.addresses[blocks.blockId] & 0x1f)); + + TreeBlock entries @ (root.offsets.addresses[blocks.blockId] >> 0x5 << 0x5) + 4; +}; + +BuddyAllocator buddy @0x04; diff --git a/tests/patterns/test_data/dsstore.hexpat.dsstore b/tests/patterns/test_data/dsstore.hexpat.dsstore new file mode 100644 index 0000000000000000000000000000000000000000..24eaeb319f9c9cc42726a5bd9e36a1a491956085 GIT binary patch literal 10244 zcmeHMYiJzT6+Tzi+G|_3Ru5OHBPRoLutUA?l@xCu*r-dPcmC@fWyL>du=LChmPxZI}keWneqOZ9997no0W3FvaE zZq^)k!|0$Rh(Hj5AOb-If(Qf=_-}{+_H1t9?H&)VK?H&b1QBRPfa`+>VxCic&Ev9k z;37W(z`M~c8*qdHxTbhc@imX*4w~?$f_qbi`os|4bo6U#Tu$*dk9*TesE-e!o-EWC zijYr-eoYQ1k@I+P4I&UkU}FTlZ}(Vf#i^If_V4#Z;$zXZsXMfJOL%KI9NrN=Gkwlp znRaz|$tmcKQ!E|T-E$>{XKdSSV!d>%W~|Ic1}ALG)oYf~kdtc_14B+9uUQp)rC={v z6-Vls_HM`r%|?bUTu3GkXqmCh>H+P-XaX3Q)zxr#=%M7dr{)&VKXc*P)gQdzIU`g- zpx$-Py$D%QtX5uDo`rto{W6hAT#NKJecQIZXUERoNMGMTWH7R8*Vl&b`}*$tXCnh8 zy}VFuu#FS8X*UYyk}(_Ub>Q_>*|v^0jAeLu#?(uOdBiH%u4^xzaErpPI^-iBYZ!)gs@kYkj?B+HhI^t7pFAy}>>7(x*1Qe<{PZJrw`N<; zF{9ytpVS)--KrXe^Btz`Md2!pibtJdngORQg zKbGN$n6YfjIMTQ2D)-@v!h3&Fhril!yRlF=^|GNQ6R}Jz9ZQamq^@QD{Qlu@PzZa% z^`XjQHR>4Ve6(gcu5OxmV61LceeGY(yKg|>hyJ*Kq7m&-rQh$R?XgxQdHcaua4qxE z+qmDS@K1r|PSbrI_UGLyJa9XpT_^lm;bf6k7RiiN>g(_Qu=Hi{Ht* z0ooToW}8ckh7-S|t5Kxx7}1~?OkDB5=LyaU*LKcnhl|bdwm_jsg4f`|#!5^oZe~Dq ztpR4UGbCvVfrOC968rHNfsk7u8DkmT9YQq8Pnzh_tr$fxWI z($7H_8(Ekg^-_>wzG_%*R%M*duZWt+>arV6Zzit{iL`$weV6uPZC0=btrgq2UeUX* zS4?F{FYTrtdP1%-X9%ypL+7yChoQZnEa_cbdKXvT#hc#6Ti!90-o@L!Qxn;{_&s?y zKq5}G3oG8k?-SEVuHuD$BzID+L6{zkzS*>=;w5qKBwQ)mtu<;5W`}R zctGqE4~vvYi&2pc?GCBR(dAd=;f@uh&;iJ(%Jo7a;q5nK_~s^WjHVIoSI0SKo46m< zsfi)_nAH!01op2>s5MtWpD51w67GG8wBm6mAoJ$XjiceS;M_vMA9#==z_%360pC=Z zG@{>PF1IcXwkaF}-ph*7A{y~9+4=z1RDVD4oWcXZb%izHHx$kRUr|{6nrK+z2r&Dp znis7FFIu6iCEH&3f_H8Blkmsfjbp4IHLSR{1!H;7R0RSh$&_&*bp`S^)z_*pUJO~UUuyV|LM*pe9E4c* zamn%hyO+wdpXVVTK7qbJfW82Q;p;Fc0m^~6e+GOGiv!50=YdW{dK^)G`DDfJ{{eBHjD9659j|ce^Xq8 z?61wC@zmt#c)AeHOdd)_GsWUq^kAxxkLJ^3nM67{IWd+z=;z)KF%OTY^|{A=oCnxB z=n9CdE9W6MUJb6U7vVQIuCAxyFSqs8^`h$U(ohdLk