test_diskimage.c (9318B)
1 /* 2 This file is part of libextractor. 3 Copyright (C) 2026 Vidyut Samanta and Christian Grothoff 4 5 libextractor is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published 7 by the Free Software Foundation; either version 3, or (at your 8 option) any later version. 9 10 libextractor is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with libextractor; see the file COPYING. If not, write to the 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 Boston, MA 02110-1301, USA. 19 */ 20 /** 21 * @file plugins/test_diskimage.c 22 * @brief testcase for the diskimage plugin 23 * @author Christian Grothoff 24 * 25 * The three inputs come from contrib/gen_diskimage_testdata.sh; read 26 * its header for what each of them is and where it was truncated. 27 * The VHDX is only the file identifier block, because [MS-VHDX] puts 28 * the region table at a fixed 192 KiB offset and there is no way to 29 * make a conformant VHDX small enough for a test corpus -- so the 30 * items the plugin reads out of the metadata region cannot be asserted 31 * here. 32 */ 33 #include "platform.h" 34 #include "test_lib.h" 35 36 37 /** 38 * Main function for the diskimage testcase. 39 * 40 * @param argc number of arguments (ignored) 41 * @param argv arguments (ignored) 42 * @return 0 on success 43 */ 44 int 45 main (int argc, char *argv[]) 46 { 47 struct SolutionData qcow2_sol[] = { 48 { 49 EXTRACTOR_METATYPE_MIMETYPE, 50 EXTRACTOR_METAFORMAT_UTF8, 51 "text/plain", 52 "application/x-qemu-disk", 53 strlen ("application/x-qemu-disk") + 1, 54 0 55 }, 56 { 57 EXTRACTOR_METATYPE_FORMAT, 58 EXTRACTOR_METAFORMAT_UTF8, 59 "text/plain", 60 "QCOW2", 61 strlen ("QCOW2") + 1, 62 0 63 }, 64 { 65 EXTRACTOR_METATYPE_FORMAT_VERSION, 66 EXTRACTOR_METAFORMAT_UTF8, 67 "text/plain", 68 "3", 69 strlen ("3") + 1, 70 0 71 }, 72 { 73 EXTRACTOR_METATYPE_VOLUME_SIZE, 74 EXTRACTOR_METAFORMAT_UTF8, 75 "text/plain", 76 "1048576", 77 strlen ("1048576") + 1, 78 0 79 }, 80 { 81 EXTRACTOR_METATYPE_BLOCK_SIZE, 82 EXTRACTOR_METAFORMAT_UTF8, 83 "text/plain", 84 "512", 85 strlen ("512") + 1, 86 0 87 }, 88 /* the point of the whole file: a differencing image names the 89 image it depends on, so the investigator knows to go find it */ 90 { 91 EXTRACTOR_METATYPE_PARENT_IMAGE, 92 EXTRACTOR_METAFORMAT_UTF8, 93 "text/plain", 94 "diskimage_base.qcow2", 95 strlen ("diskimage_base.qcow2") + 1, 96 0 97 }, 98 { 99 EXTRACTOR_METATYPE_ENTRY_COUNT, 100 EXTRACTOR_METAFORMAT_UTF8, 101 "text/plain", 102 "0", 103 strlen ("0") + 1, 104 0 105 }, 106 { 107 EXTRACTOR_METATYPE_ATTRIBUTES, 108 EXTRACTOR_METAFORMAT_UTF8, 109 "text/plain", 110 "lazy refcounts", 111 strlen ("lazy refcounts") + 1, 112 0 113 }, 114 { 115 EXTRACTOR_METATYPE_COMMENT, 116 EXTRACTOR_METAFORMAT_UTF8, 117 "text/plain", 118 "compression type: zstd", 119 strlen ("compression type: zstd") + 1, 120 0 121 }, 122 { 0, 0, NULL, NULL, 0, -1 } 123 }; 124 struct SolutionData vmdk_sol[] = { 125 { 126 EXTRACTOR_METATYPE_MIMETYPE, 127 EXTRACTOR_METAFORMAT_UTF8, 128 "text/plain", 129 "application/x-vmdk", 130 strlen ("application/x-vmdk") + 1, 131 0 132 }, 133 { 134 EXTRACTOR_METATYPE_FORMAT, 135 EXTRACTOR_METAFORMAT_UTF8, 136 "text/plain", 137 "VMDK", 138 strlen ("VMDK") + 1, 139 0 140 }, 141 { 142 EXTRACTOR_METATYPE_FORMAT_VERSION, 143 EXTRACTOR_METAFORMAT_UTF8, 144 "text/plain", 145 "1", 146 strlen ("1") + 1, 147 0 148 }, 149 { 150 EXTRACTOR_METATYPE_VOLUME_SIZE, 151 EXTRACTOR_METAFORMAT_UTF8, 152 "text/plain", 153 "1048576", 154 strlen ("1048576") + 1, 155 0 156 }, 157 { 158 EXTRACTOR_METATYPE_BLOCK_SIZE, 159 EXTRACTOR_METAFORMAT_UTF8, 160 "text/plain", 161 "65536", 162 strlen ("65536") + 1, 163 0 164 }, 165 /* from the text descriptor embedded in the sparse extent header */ 166 { 167 EXTRACTOR_METATYPE_VOLUME_SERIAL, 168 EXTRACTOR_METAFORMAT_UTF8, 169 "text/plain", 170 "1f2e3d4c", 171 strlen ("1f2e3d4c") + 1, 172 0 173 }, 174 { 175 EXTRACTOR_METATYPE_FORMAT, 176 EXTRACTOR_METAFORMAT_UTF8, 177 "text/plain", 178 "monolithicSparse", 179 strlen ("monolithicSparse") + 1, 180 0 181 }, 182 { 183 EXTRACTOR_METATYPE_PARENT_IMAGE, 184 EXTRACTOR_METAFORMAT_UTF8, 185 "text/plain", 186 "diskimage_base.vmdk", 187 strlen ("diskimage_base.vmdk") + 1, 188 0 189 }, 190 { 191 EXTRACTOR_METATYPE_FILENAME, 192 EXTRACTOR_METAFORMAT_UTF8, 193 "text/plain", 194 "diskimage_test.vmdk", 195 strlen ("diskimage_test.vmdk") + 1, 196 0 197 }, 198 { 199 EXTRACTOR_METATYPE_ENTRY_COUNT, 200 EXTRACTOR_METAFORMAT_UTF8, 201 "text/plain", 202 "1", 203 strlen ("1") + 1, 204 0 205 }, 206 { 207 EXTRACTOR_METATYPE_SOFTWARE_VERSION, 208 EXTRACTOR_METAFORMAT_UTF8, 209 "text/plain", 210 "virtual hardware version 4", 211 strlen ("virtual hardware version 4") + 1, 212 0 213 }, 214 { 215 EXTRACTOR_METATYPE_SOFTWARE_VERSION, 216 EXTRACTOR_METAFORMAT_UTF8, 217 "text/plain", 218 "VMware Tools version 2147483647", 219 strlen ("VMware Tools version 2147483647") + 1, 220 0 221 }, 222 { 223 EXTRACTOR_METATYPE_COMMENT, 224 EXTRACTOR_METAFORMAT_UTF8, 225 "text/plain", 226 "adapter type: ide", 227 strlen ("adapter type: ide") + 1, 228 0 229 }, 230 { 231 EXTRACTOR_METATYPE_COMMENT, 232 EXTRACTOR_METAFORMAT_UTF8, 233 "text/plain", 234 "geometry: 2 cylinders, 16 heads, 63 sectors per track", 235 strlen ("geometry: 2 cylinders, 16 heads, 63 sectors per track") + 1, 236 0 237 }, 238 { 0, 0, NULL, NULL, 0, -1 } 239 }; 240 struct SolutionData vhdx_sol[] = { 241 { 242 EXTRACTOR_METATYPE_MIMETYPE, 243 EXTRACTOR_METAFORMAT_UTF8, 244 "text/plain", 245 "application/x-vhdx", 246 strlen ("application/x-vhdx") + 1, 247 0 248 }, 249 { 250 EXTRACTOR_METATYPE_FORMAT, 251 EXTRACTOR_METAFORMAT_UTF8, 252 "text/plain", 253 "VHDX", 254 strlen ("VHDX") + 1, 255 0 256 }, 257 /* proves the 512 byte UTF-16LE creator string was decoded */ 258 { 259 EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE, 260 EXTRACTOR_METAFORMAT_UTF8, 261 "text/plain", 262 "libextractor testdata 1.0", 263 strlen ("libextractor testdata 1.0") + 1, 264 0 265 }, 266 { 0, 0, NULL, NULL, 0, -1 } 267 }; 268 struct SolutionData vhd_sol[] = { 269 { 270 EXTRACTOR_METATYPE_MIMETYPE, 271 EXTRACTOR_METAFORMAT_UTF8, 272 "text/plain", 273 "application/x-vhd", 274 strlen ("application/x-vhd") + 1, 275 0 276 }, 277 { 278 EXTRACTOR_METATYPE_FORMAT, 279 EXTRACTOR_METAFORMAT_UTF8, 280 "text/plain", 281 "VHD", 282 strlen ("VHD") + 1, 283 0 284 }, 285 /* the footer is at the *end* of the file, so getting this at all 286 proves the tail seek fired */ 287 { 288 EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE, 289 EXTRACTOR_METAFORMAT_UTF8, 290 "text/plain", 291 "qemu 5.3", 292 strlen ("qemu 5.3") + 1, 293 0 294 }, 295 { 296 EXTRACTOR_METATYPE_AUTHORING_OS, 297 EXTRACTOR_METAFORMAT_UTF8, 298 "text/plain", 299 "Windows", 300 strlen ("Windows") + 1, 301 0 302 }, 303 /* VHD counts seconds from 2000-01-01, not from the Unix epoch; 304 this value only comes out right if that offset was applied */ 305 { 306 EXTRACTOR_METATYPE_CREATION_DATE, 307 EXTRACTOR_METAFORMAT_UTF8, 308 "text/plain", 309 "2024-01-01T00:00:00Z", 310 strlen ("2024-01-01T00:00:00Z") + 1, 311 0 312 }, 313 { 314 EXTRACTOR_METATYPE_VOLUME_SIZE, 315 EXTRACTOR_METAFORMAT_UTF8, 316 "text/plain", 317 "1079296", 318 strlen ("1079296") + 1, 319 0 320 }, 321 /* a big-endian RFC 4122 UUID, unlike the mixed-endian GUIDs the 322 Windows formats use -- this asserts the other branch of 323 EXTRACTOR_forensic_emit_guid_() */ 324 { 325 EXTRACTOR_METATYPE_VOLUME_SERIAL, 326 EXTRACTOR_METAFORMAT_UTF8, 327 "text/plain", 328 "3ffb1d5a-09a4-4e1d-9c2d-7f6a1b4c8e02", 329 strlen ("3ffb1d5a-09a4-4e1d-9c2d-7f6a1b4c8e02") + 1, 330 0 331 }, 332 { 333 EXTRACTOR_METATYPE_ATTRIBUTES, 334 EXTRACTOR_METAFORMAT_UTF8, 335 "text/plain", 336 "dynamic disk", 337 strlen ("dynamic disk") + 1, 338 0 339 }, 340 { 341 EXTRACTOR_METATYPE_FORMAT_VERSION, 342 EXTRACTOR_METAFORMAT_UTF8, 343 "text/plain", 344 "1.0", 345 strlen ("1.0") + 1, 346 0 347 }, 348 /* the block size comes from the dynamic disk header, which is 349 reached through an offset stored in the footer */ 350 { 351 EXTRACTOR_METATYPE_BLOCK_SIZE, 352 EXTRACTOR_METAFORMAT_UTF8, 353 "text/plain", 354 "2097152", 355 strlen ("2097152") + 1, 356 0 357 }, 358 { 0, 0, NULL, NULL, 0, -1 } 359 }; 360 struct ProblemSet ps[] = { 361 { "testdata/diskimage_test.qcow2", 362 qcow2_sol }, 363 { "testdata/diskimage_test.vmdk", 364 vmdk_sol }, 365 { "testdata/diskimage_test.vhdx", 366 vhdx_sol }, 367 { "testdata/diskimage_test.vhd", 368 vhd_sol }, 369 { NULL, NULL } 370 }; 371 372 (void) argc; 373 (void) argv; 374 return ET_main ("diskimage", ps); 375 } 376 377 378 /* end of test_diskimage.c */