Certutil Artifacts Analysis

Certutil Artifacts Analysis

certutil is a build-in tool on windows systems that is used to manage certificates. However certutil could be used to base64 encode/decode, calculate file hashes and download files from the internet. In this blog we will take a look at the artifacts generated by certutil when downloading a file, specifically the metadata file, analyze it’s structure and write a parser for it.

Analysis

In this example we will download a file using certutil and observe the files written to the system. The following command will downloadĀ mimkatzĀ fromĀ githubĀ and save it to the current directory (C:\windows\temp):

certutil.exe -urlcache -split -f "https://github.com/gentilkiwi/mimikatz/releases/download/2.2.0-20200816/mimikatz_trunk.7z" m.7z

After executing the above command we can see inĀ procmonĀ that is writing to two files: Both files have the same name but on different directories. The file nameĀ BC456035A9E2885290EDC953764CC761 is the MD5 hash for the URL UTF-16LE encode: The file located onĀ C:\Users\u0041\AppData\LocalLow\Microsoft\CryptnetUrlCache\Content\BC456035A9E2885290EDC953764CC761Ā contains the actual file: HoweverĀ C:\Users\u0041\AppData\LocalLow\Microsoft\CryptnetUrlCache\MetaData\BC456035A9E2885290EDC953764CC761Ā contains UTF-16LE encode URL and MD5 hash for the downloaded file in addition to some binary data: The URL and the MD5 hash can be extracted easily, But what about the header (116 bytes) ? the following summarize my findings:

Field Name Offset Size Type Description
- x00 x0C byte Unknown. x70x00x00x00 might be the header length (112 bytes).
urlSize x0C x04 uint32 The size for the UTF-16LE encoded URL
Timestamp x10 x08 uint64 The last time the file was downloaded in FILETIME format.
- x18 x4C byte Unknown
LastModificationTimeHeader x58 x08 uint64 EDIT 1:

The file last modification time header from the reponse (Thanks toĀ @mrAn61Ā on Twitter for pointing that out)
hashSize x64 x04 uint32 The size for the UTF-16LE encode hash
- x68 x08 byte Unknown
fileSize x70 x04 uint32 The downloaded file size in bytes
URL x74 urlSize UTF-16LE String The URL from where the file was downloaded
E-Tag x74 + urlSize hashSize UTF-16LE String The hash for the downloaded file. The following are some of the hashing algorithms observed during analysis:

- MD5
- SHA1
- SHA256
- Unkown hash (ex. 57f3c9cf-1514ce)Ā 

In some cases the hash value is empty.

EDIT 1:

This is the E-Tag header of the file from the HTTP response. E-Tag is used to identify a specific version of a file, If the file changes then theĀ E-Tag changes.

As you can see the metadata file contains a lot of useful information, However there is a lot more data that is unknown (highlighted with red color). I am still researching what that data might be, If you want to help please send me a DM on twitterĀ @A__ALFAIFI.

CryptnetURLCacheParser

I wrote a parser that output the above data in readable format (CSV, JSON or JSONL). You can find it here for the Python versionĀ CryptnetURLCacheParserĀ and hereĀ CryptnetURLCacheParser-rsĀ for the Rust version. The following is the parser output in JSON format:

{
    "Timestamp": "2020-09-11T16:53:07.297208",
    "URL": "https://github.com/gentilkiwi/mimikatz/releases/download/2.2.0-20200816/mimikatz_trunk.7z",
    "FileSize": 875252,
    "MetadataHash": "5abdd836d4458370a804f2974431c993",
    "FullPath": "C:\\Users\\u0041\\AppData\\LocalLow\\Microsoft\\CryptnetUrlCache\\MetaData\\BC456035A9E2885290EDC953764CC761",
    "MD5": "5abdd836d4458370a804f2974431c993"
}

Edit 1

I have identified a couple of stuff in the metadata structure, the table above is updated to the latest findings. The following is the summery:

  • TheĀ MetadataHashĀ field is actually theĀ E-TagĀ header from the HTTP response.
  • Another timestamp is recorded which is theĀ LastModificationTimeĀ header from the HTTP response (Thanks toĀ @mrAn61Ā on Twitter for pointing that out).
  • Created another parser for this artifact bu in Rust! you can find it hereĀ CryptnetURLCacheParser-rs.

References