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.
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:
|Unknown. x70x00x00x00 might be the header length (112 bytes).
|The size for the UTF-16LE encoded URL
|The last time the file was downloaded in FILETIME format.
The file last modification time header from the reponse (Thanks to @mrAn61 on Twitter for pointing that out)
|The size for the UTF-16LE encode hash
|The downloaded file size in bytes
|The URL from where the file was downloaded
|x74 + urlSize
The hash for the downloaded file. The following are some of the hashing algorithms observed during analysis:
In some cases the hash value is empty.
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 leave a comment on this blog or send me a DM on twitter @A__ALFAIFI.
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:
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: