Closed s3rvac closed 6 years ago
I looked into this for a bit and here is what I found. PeFormat::calculateDigest()
computes the hash by iterating over all ranges returned by getDigestRanges()
and adding the data into the hashing context:
1334 auto digestRanges = getDigestRanges();
1335 for (const auto& range : digestRanges)
1336 {
1337 const std::uint8_t* data = std::get<0>(range);
1338 std::size_t size = std::get<1>(range);
1339
1340 if (!hashCtx.addData(data, size))
1341 return {};
1342 }
For the attached file, it reports the following ranges (data
and size
from the above code):
0x7f3b8231b010 352
0x7f3b8231b174 60
0x7f3b8231b1b8 1566296
0x7f3c8247fff8 18446744069414693120
The last range is clearly off and should not be there. In more detail, if you subtract 0x7f3c8247fff8
(the beginning of the last alleged range) and 0x7f3b8231b010
(the beginning of the loaded file data in memory), you get 4296429544
, which is approx. 4 GB. The file has 1.5 MB, which is nowhere near 4 GB.
This fact and the size of the last range suggests that there is an overflow somewhere inside getDigestRanges()
. And there is indeed an overflow. The last range is added in the following code:
1316 // Finish off the data if the last offset didn't end at the end of of all data
1317 if (lastOffset != bytes.size())
1318 result.emplace_back(bytes.data() + lastOffset, bytes.size() - lastOffset);
In our case, lastOffset
reports 4296429544
and bytes.size()
is 1571048
. The actual reason why lastOffset
is that big is that formatParser->getSecurityDirSize()
returns 4294862824
:
1287 std::size_t secDirSize = formatParser->getSecurityDirSize();
The secDirSize
variable is then used to compute the end of the last range:
1293 std::vector<std::pair<...>> offsets = { [..], std::make_pair(secDirOffset, secDirSize) };
The size of the security directory is obtained from pelib
in include/pelib/PeHeader.h
:
1911 /**
1912 * Returns the size of the current file's security directory.
1913 * @return The size of the Security directory.
1914 **/
1915 template<int x>
1916 dword PeHeaderT<x>::getIddSecuritySize() const
1917 {
1918 return m_inthHeader.dataDirectories[PELIB_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
1919 }
1920
This function indeed returns 4294862824
. So, either there is a bug in pelib
, or the binary contains an invalid value. However, it seems to be the latter as pefile
also reports this value:
[IMAGE_DIRECTORY_ENTRY_SECURITY]
0x1A0 0x0 VirtualAddress: 0x17E800
0x1A4 0x4 Size: 0xFFFE67E8
Fixed in 714d69c824ec99585fd15bb005030c86c3466bc6.
fileinfo
crashes when computing the SHA-1 hash of a digital signature of the attached PE file.Input
Run
where
FILE
is:Output
Expected output
fileinfo
does not crash during the analysis.Output from valgrind
Notes
This issue may be related to #87, but there are several differences:
verifySignature()
, but in this case, it crashes when verifying the digest by computing the SHA-1 hash.retdec-fileinfo --verbose
is able to parse the certificate table in this case:Certificate #0 Subject name : Systweak Inc ...
Certificate #1 Subject name : VeriSign Time Stamping Services Signer - G2 ..
Certificate #2 Subject name : VeriSign Time Stamping Services CA ...