#include #include #include #include "fold/binary/r2_backend.hpp" #include "fold/ir/binary_expr.hpp" #include "fold/report/finding.hpp" namespace { fold::ir::BinaryIRTree treeWithStrings(std::vector values) { fold::ir::BinaryIRTree tree; std::uint64_t addr = 0x1000; for (auto& value : values) { fold::ir::BinaryExprNode node; node.kind = fold::ir::BinaryExprKind::HardcodedString; node.address = addr; node.string_value = std::move(value); node.section_name = "__cstring"; tree.nodes.push_back(std::move(node)); addr += 0x10; } return tree; } std::vector hardcodedFindings(std::vector values) { auto tree = treeWithStrings(std::move(values)); std::size_t index = 0; return fold::binary::detectHardcodedStringsFromTree(tree, "test.bin", index); } bool hasBase64Blob(const std::vector& findings, const std::string& token) { for (const auto& f : findings) { if (f.evidence.detector_name == "hardcoded-string" && f.message.find("base64-blob") != std::string::npos && f.message.find(token) != std::string::npos) { return true; } } return false; } } // namespace TEST_CASE("binary hardcoded strings: base64 accepts padded and unpadded blobs", "[binary][hardcoded-string][base64]") { const auto findings = hardcodedFindings({ "y3IKctR47tYlFxOynj04JNC66g==", // padded random bytes "lfLEZS6y7TSgjjTq60IBZzph", // valid unpadded random bytes }); REQUIRE(hasBase64Blob(findings, "y3IKctR47tYlFxOynj04JNC66g==")); REQUIRE(hasBase64Blob(findings, "lfLEZS6y7TSgjjTq60IBZzph")); } TEST_CASE("binary hardcoded strings: base64 suppresses alphabet tables and build paths", "[binary][hardcoded-string][base64]") { const auto findings = hardcodedFindings({ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", "/var/folders/build/ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnop", }); REQUIRE_FALSE(hasBase64Blob(findings, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); }