NTFS: non-existing file (moved or deleted) is shown as regular allocated file
0x4d4c opened this issue · comments
In the raw image attached (fs.img
in the zip file), the file xazjlgis/ldniruft/yqntnnnb/lkrabebi/lykvvzey
has been renamed to xazjlgis/ldniruft/xyalaefy/cfipubey/blpytzyw
(sorry for the file names). However, lykvvzey
is still reported as allocated by fls
.
$ fls -r fs.img | grep -A5 -B5 lykvvzey
++++++ d/d 97-144-2: tfkzejer
+++++++ d/d 94-144-2: idilfoyx
+++++ r/r 78-128-2: kyiujdrs
+++++ r/r 112-128-2: lbcexece
+++ d/d 71-144-2: lkrabebi
++++ r/r 83-128-2: lykvvzey <---- file is presented as regular allocated file
+++ r/r 111-128-2: thkzlxxq
+ d/d 86-144-2: ovigoofn
++ r/r 118-128-2: bffpmbjg
++ d/d 87-144-2: mjmlvebp
+++ r/r 95-128-2: goezwkxo
Calling istat
with the metadata address 83-128
shows the correct new file name:
$ istat fs.img 83-128
MFT Entry Header Values:
Entry: 83 Sequence: 1
$LogFile Sequence Number: 0
Allocated File
Links: 1
$STANDARD_INFORMATION Attribute Values:
Flags: Archive
Owner ID: 0
Security ID: 0 ()
Created: 2022-08-02 17:13:19.902670700 (CEST)
File Modified: 2022-08-02 17:13:20.465722800 (CEST)
MFT Modified: 2022-08-02 17:15:20.386325300 (CEST)
Accessed: 2022-08-02 17:13:38.785556900 (CEST)
$FILE_NAME Attribute Values:
Flags: Archive
Name: blpytzyw <---- this is the correct new file name
Parent MFT Entry: 77 Sequence: 1
Allocated Size: 208896 Actual Size: 206188
Created: 2022-08-02 17:13:19.902670700 (CEST)
File Modified: 2022-08-02 17:13:20.465722800 (CEST)
MFT Modified: 2022-08-02 17:13:20.465722800 (CEST)
Accessed: 2022-08-02 17:13:38.785556900 (CEST)
Attributes:
Type: $STANDARD_INFORMATION (16-0) Name: N/A Resident size: 48
Type: $FILE_NAME (48-4) Name: N/A Resident size: 82
Type: $SECURITY_DESCRIPTOR (80-1) Name: N/A Resident size: 80
Type: $DATA (128-2) Name: N/A Non-Resident size: 206188 init_size: 206188
1077 1078 1079 1080 1081 1082 1083 1084
1085 1086 1087 1088 1089 1090 1091 1092
1093 1094 1095 1096 1097 1098 1099 1100
1101 1102 1103 1104 1105 1106 1107 1108
1109 1110 1111 1112 1113 1114 1115 1116
1117 1118 1119 1120 1121 1122 1123 1124
1125 1126 1127
If we grep for the address 83-128 as well as the corresponding parent directory addresses, we get both, the old and the new paths:
$ fls -rp fs.img | grep -E '83|77|71'
d/d 77-144-2: xazjlgis/ldniruft/xyalaefy/cfipubey
r/r 83-128-2: xazjlgis/ldniruft/xyalaefy/cfipubey/blpytzyw
d/d 71-144-2: xazjlgis/ldniruft/yqntnnnb/lkrabebi
r/r 83-128-2: xazjlgis/ldniruft/yqntnnnb/lkrabebi/lykvvzey
Looking at the directories, we can see that the $INDEX_ALLOCATION attribute of directory 71
still has entries for the old file name:
$ icat fs.img 71-160-5 | xxd
00000000: 494e 4458 2800 0900 0000 0000 0000 0000 INDX(...........
00000010: 0000 0000 0000 0000 2800 0000 a000 0000 ........(.......
00000020: e80f 0000 0000 0000 e001 d801 0000 0000 ................
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000040: 5300 0000 0000 0100 6800 5200 0000 0000 S.......h.R.....
00000050: 4700 0000 0000 0100 138e 4266 82a6 d801 G.........Bf....
00000060: 4c78 9866 82a6 d801 cd01 10ae 82a6 d801 Lx.f............
00000070: d1da 8371 82a6 d801 0030 0300 0000 0000 ...q.....0......
00000080: 6c25 0300 0000 0000 2000 0000 0000 0000 l%...... .......
00000090: 0800 6c00 7900 6b00 7600 7600 7a00 6500 ..l.y.k.v.v.z.e.
000000a0: 7900 0000 0000 0000 0000 0000 0000 0000 y...............
000000b0: 1000 0000 0200 0000 4700 0000 0000 0100 ........G.......
000000c0: 138e 4266 82a6 d801 4c78 9866 82a6 d801 ..Bf....Lx.f....
000000d0: 4c78 9866 82a6 d801 d1da 8371 82a6 d801 Lx.f.......q....
000000e0: 0030 0300 0000 0000 6c25 0300 0000 0000 .0......l%......
000000f0: 2000 0000 0000 0000 0800 6c00 7900 6b00 .........l.y.k.
00000100: 7600 7600 7a00 6500 7900 0000 0000 0000 v.v.z.e.y.......
00000110: 0000 0000 0000 0000 1000 0000 0200 0000 ................
00000120: 4700 0000 0000 0100 35b0 d76d 82a6 d801 G.......5..m....
00000130: 90b5 4c6f 82a6 d801 242b 2272 82a6 d801 ..Lo....$+"r....
00000140: 35b0 d76d 82a6 d801 00f0 0a00 0000 0000 5..m............
00000150: e5e1 0a00 0000 0000 2000 0000 0000 0000 ........ .......
00000160: 0800 7700 6600 6e00 6700 6500 7400 7800 ..w.f.n.g.e.t.x.
00000170: 7a00 0000 0000 0000 0000 0000 0000 0000 z...............
00000180: 1000 0000 0200 0000 4700 0000 0000 0100 ........G.......
00000190: 35b0 d76d 82a6 d801 90b5 4c6f 82a6 d801 5..m......Lo....
000001a0: 242b 2272 82a6 d801 35b0 d76d 82a6 d801 $+"r....5..m....
000001b0: 00f0 0a00 0000 0000 e5e1 0a00 0000 0000 ................
000001c0: 2000 0000 0000 0000 0800 7700 6600 6e00 .........w.f.n.
000001d0: 6700 6500 7400 7800 7a00 0000 0000 0000 g.e.t.x.z.......
000001e0: 0000 0000 0000 0000 1000 0000 0200 0000 ................
000001f0: 4700 0000 0000 0100 35b0 d76d 82a6 e001 G.......5..m....
00000200: 90b5 4c6f 82a6 d801 242b 2272 82a6 d801 ..Lo....$+"r....
00000210: 35b0 d76d 82a6 d801 00f0 0a00 0000 0000 5..m............
00000220: e5e1 0a00 0000 0000 2000 0000 0000 0000 ........ .......
00000230: 0800 7700 6600 6e00 6700 6500 7400 7800 ..w.f.n.g.e.t.x.
00000240: 7a00 0000 0000 0000 0000 0000 0000 0000 z...............
00000250: 1000 0000 0200 0000 0000 0000 0000 0000 ................
[...]
The $BITMAP attribute is completely zero:
$ icat fs.img 71-176-4 | xxd
00000000: 0000 0000 0000 0000 ........
I think the problem here is that TSK parses the index entries which are not part of the active tree without checking the $BITMAP attribute. While finding the index entries in the unused space is definitely desired, the found entries should be cross-checked to have their correct state. As a first quick fix (which is obviously not a complete fix), I added a patch to the zip file, which basically adds the following code to ntfs_proc_idxentry
:
fs_attr_bmap = tsk_fs_attrlist_get(a_fs_dir->fs_file->meta->attr, TSK_FS_ATTR_TYPE_NTFS_BITMAP);
if (fs_attr_bmap) {
if (fs_attr_bmap->flags & TSK_FS_ATTR_RES) {
// The following check works only when the $BITMAP attribute has no bits set.
// This is obviously not the correct way to do this...
if (*(fs_attr_bmap->rd.buf) == 0) {
fs_name->flags = TSK_FS_NAME_FLAG_UNALLOC;
}
}
else if (fs_attr_bmap->flags & TSK_FS_ATTR_NONRES) {
// TODO: implement this for non-resident $BITMAP attributes
}
}
I'm still trying to create test images for the cases not implemented in the code above, but after applying the patch, the fls output looks okay to me:
$ fls -rp fs.img | grep -E '83|77|71'
d/d 77-144-2: xazjlgis/ldniruft/xyalaefy/cfipubey
r/r 83-128-2: xazjlgis/ldniruft/xyalaefy/cfipubey/blpytzyw
d/d 71-144-2: xazjlgis/ldniruft/yqntnnnb/lkrabebi
r/r * 83-128-2(realloc): xazjlgis/ldniruft/yqntnnnb/lkrabebi/lykvvzey