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.