Table of Contents

Output Formats

The CILFI command-line utility can be easily integrated into other applications or analysis pipelines by configuring how it should output its results. By default, output is emitted directly to the standard output, but it can also be redirected to a file when the -o <filepath> flag is specified.

Flat Key-Value Mapping

When no format is specified, CILFI by default outputs as a flat key-value mapping that pairs metadata tokens to matched signatures.

$ cilfi match Binary.dll --signatures signatures.cilfi
Binary.dll@06000051: KoiVM_OpCodes_ADD_DWORD_Run
Binary.dll@06000054: KoiVM_OpCodes_ADD_QWORD_Run
Binary.dll@06000057: KoiVM_OpCodes_ADD_R32_Run
Binary.dll@0600005A: KoiVM_OpCodes_ADD_R64_Run
Binary.dll@0600005D: KoiVM_OpCodes_CALL_Run
Binary.dll@06000060: KoiVM_OpCodes_CMP_DWORD_Run
Binary.dll@06000063: KoiVM_OpCodes_CMP_QWORD_Run
Binary.dll@06000066: KoiVM_OpCodes_CMP_R32_Run
...

When multiple binaries are specified, they will appear in sequence.

$ cilfi match Binary1.dll Binary2.dll --signatures signatures.cilfi
Binary1.dll@06000051: KoiVM_OpCodes_ADD_DWORD_Run
Binary1.dll@06000054: KoiVM_OpCodes_ADD_QWORD_Run
Binary1.dll@06000057: KoiVM_OpCodes_ADD_R32_Run
...
Binary2.dll@06000032: KoiVM_OpCodes_CALL_Run
Binary2.dll@06000035: KoiVM_OpCodes_VCALL_Run
Binary2.dll@06000038: KoiVM_OpCodes_SUB_DWORD_Run
...

Adding the verbose flag (-v or --verbose) while outputting to the console will also emit a colorized output for every signature the matched instructions, which can be helpful when debugging signatures.

$ cilfi match Binary.dll --signatures signatures.cilfi --verbose
Binary.dll@06000051: KoiVM_OpCodes_ADD_DWORD_Run

    .method public instance final virtual void 51e04e98(
            class 9d71b5a9 A_1,
            [out] valuetype 440acd51& A_2
        ) cil managed
    {
        ... (57 instructions) ...

        IL_00B2: callvirt    instance class 5396d719 5396d719::d8a4b515(uint32)
        IL_00B7: call        instance void 39e7839::8cee83f(object)
        IL_00BC: br.s        IL_00D4
        IL_00BE: ldloca.s    V_3
        IL_00C0: ldloca.s    V_2
        IL_00C2: call        instance uint32 39e7839::5cfc2a16()
        IL_00C7: ldloca.s    V_1
        IL_00C9: call        instance uint32 39e7839::5cfc2a16()
        IL_00CE: add
        IL_00CF: call        instance void 39e7839::8a27da7d(uint32)
        IL_00D4: ldarg.1
        IL_00D5: ldfld       class e3a8984e 9d71b5a9::3a454c46
        IL_00DA: ldloc.0

        ... (38 instructions) ...
    }

JSON

CILFI can also be used within a pipeline by having it output its results in JSON format instead:

$ cilfi match Binary.dll --signatures signatures.cilfi --format json

The output, after prettifying, will look similar to the following:

{
  "file_name": "C:\\Path\\To\\Binary.dll",
  "total_matches": 85,
  "matched_methods": {
    "100663322": [
      {
        "signature": "KoiVM_VCalls_BOX_Run",
        "body_rva": 4682,
        "cil_base_file_offset": 4693,
        "cil_base_rva": 12373,
        "blocks": {
          "$block1": {
            "cil_offsets": [
              100,
              102,
              103,
              108,
              113,
              115,
              120,
              125
            ]
          },
          "$block2": {
            "cil_offsets": [
              132,
              134,
              136,
              137,
              142
            ]
          }
        }
      }
    ],

    /* ... */
  }
}

Matched methods are keyed by their metadata token, each mapping to a list of matched signatures. Within each entry, various extra properties are stored that may help in finding the exact location. This includes cil_base_file_offset and cil_base_rva indicate the exact file offset and RVA of the first instruction of the body within the PE file itself. To calculate the file offsets and RVAs of the matching instructions, add cil_base_file_offset or cil_base_rva to the offsets in cil_offsets.