Certutil是Windows系统上用于管理证书的内置工具。但是,certutil可用于base64编码/解码,计算文件哈希并从互联网下载文件。在这篇博客中,我们将看看 certutil 在下载文件(特别是元数据文件)时生成的工件,分析其结构并为其编写解析器。
原文连接:https://u0041.co/blog/post/3
分析
在此示例中,我们将使用 certutil 下载一个文件并观察写入系统的文件。以下命令将从 github 下载 mimkatz 并将其保存到当前目录 (C:\windows\temp):
certutil.exe -urlcache -split -f “https://github.com/gentilkiwi/mimikatz/releases/download/2.2.0-20200816/mimikatz_trunk.7z” m.7z
执行上述命令后,我们可以在 procmon 中看到它正在写入两个文件:
这两个文件具有相同的名称,但位于不同的目录中。文件名 BC456035A9E2885290EDC953764CC761 是 URL UTF-16LE 编码的 MD5 哈希:
位于 C:\Users\u0041\AppData\LocalLow\Microsoft\CryptnetUrlCache\Content\BC456035A9E2885290EDC953764CC761 上的文件包含实际文件:
但是,C:\Users\u0041\AppData\LocalLow\Microsoft\CryptnetUrlCache\MetaData\BC456035A9E2885290EDC953764CC761 除了一些二进制数据外,还包含下载文件的 UTF-16LE 编码 URL 和 MD5 哈希:
URL和MD5哈希可以很容易地提取,但是标头(116字节)呢?下面总结了我的发现:
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:MD5SHA1SHA256Unkown 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. |
如您所见,元数据文件包含许多有用的信息,但是还有更多未知的数据(用红色突出显示)。我仍在研究这些数据可能是什么,如果您想提供帮助,请在此博客上发表评论或在推特@A__ALFAIFI上向我发送DM。
CryptnetURLCacheParser
我编写了一个解析器,以可读格式(CSV,JSON或JSONL)输出上述数据。你可以在这里找到Python版本的CryptnetURLCacheParser和Rust版本的CryptnetURLCacheParser-rs。以下是 JSON 格式的解析器输出:
1 2 3 4 5 6 7 8 |
{ "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" } |
编辑 1
我已经在元数据结构中确定了几个东西,上表已更新为最新发现。以下是汇总:
- MetadataHash 字段实际上是来自 HTTP 响应的 E-Tag 标头。
- 记录另一个时间戳,它是HTTP响应中的LastModificationTime标头(感谢Twitter上的@mrAn61指出这一点)。
- 在 Rust 中为这个工件创建了另一个解析器!你可以在这里找到它 CryptnetURLCacheParser-rs.