libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

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 */