Skip to content
API Documentation
BastionGuard™
signature_scanner.cpp
Go to the documentation of this file.
2#include "i18n.hpp"
3
4#include <array>
5#include <string>
6
7namespace {
8constexpr uint64_t MiB = 1024ull * 1024ull;
9constexpr uint64_t GiB = 1024ull * 1024ull * 1024ull;
10
11uint64_t adaptive_stride(uint64_t disk_size) {
12 if (disk_size <= 64ull * GiB) return MiB;
13 if (disk_size <= 512ull * GiB) return 4ull * MiB;
14 if (disk_size <= 2ull * 1024ull * GiB) return 16ull * MiB;
15 return 32ull * MiB;
16}
17
18bool is_ntfs(const std::array<unsigned char, 512>& b) {
19 return std::string(reinterpret_cast<const char*>(b.data() + 3), 8) == "NTFS ";
20}
21
22bool is_fat32(const std::array<unsigned char, 512>& b) {
23 return std::string(reinterpret_cast<const char*>(b.data() + 82), 8) == "FAT32 ";
24}
25
26bool is_exfat(const std::array<unsigned char, 512>& b) {
27 return std::string(reinterpret_cast<const char*>(b.data() + 3), 8) == "EXFAT ";
28}
29
30bool looks_ext4(DiskReader& reader, uint64_t offset) {
31 std::array<unsigned char, 2> sig{};
32 return reader.read_at(offset + 1024 + 56, sig.data(), sig.size()) && sig[0] == 0x53 && sig[1] == 0xEF;
33}
34
35bool looks_btrfs(DiskReader& reader, uint64_t offset) {
36 std::array<char, 8> sig{};
37 return reader.read_at(offset + 0x10040, sig.data(), sig.size()) && std::string(sig.data(), sig.size()) == "_BHRfS_M";
38}
39}
40
41std::vector<ScanResult> SignatureScanner::scan(DiskReader& reader, std::vector<std::string>& logs) {
42 std::vector<ScanResult> out;
43 const uint64_t max_scan = reader.size() > 8 * GiB ? 8 * GiB : reader.size();
44 const uint64_t stride = adaptive_stride(reader.size());
45 logs.push_back(trs("Signature scan: starting filesystem signature scan."));
46 logs.push_back(trs("Signature scan stride:") + std::string(" ") + std::to_string(stride / MiB) + " MiB");
47
48 for (uint64_t offset = 0; offset + 4096 < max_scan; offset += stride) {
49 std::array<unsigned char, 512> sector{};
50 if (!reader.read_at(offset, sector.data(), sector.size())) {
51 continue;
52 }
53 if (is_ntfs(sector)) {
54 out.push_back({ResultKind::FilesystemCandidate, offset, 0, "NTFS candidate", "Signature scan", trs("NTFS boot sector detected"), 0.80});
55 }
56 if (is_fat32(sector)) {
57 out.push_back({ResultKind::FilesystemCandidate, offset, 0, "FAT32 candidate", "Signature scan", trs("FAT32 boot sector detected"), 0.78});
58 }
59 if (is_exfat(sector)) {
60 out.push_back({ResultKind::FilesystemCandidate, offset, 0, "exFAT candidate", "Signature scan", trs("exFAT boot sector detected"), 0.82});
61 }
62 if (looks_ext4(reader, offset)) {
63 out.push_back({ResultKind::FilesystemCandidate, offset, 0, "ext4 candidate", "Signature scan", trs("ext4 superblock detected"), 0.76});
64 }
65 if (looks_btrfs(reader, offset)) {
66 out.push_back({ResultKind::FilesystemCandidate, offset, 0, "Btrfs candidate", "Signature scan", trs("Btrfs superblock detected"), 0.79});
67 }
68 }
69
70 logs.push_back(trs("Signature scan: completed."));
71 return out;
72}
bool read_at(uint64_t offset, void *buffer, size_t len)
uint64_t size() const
static std::vector< ScanResult > scan(DiskReader &reader, std::vector< std::string > &logs)
std::string trs(const char *msgid)
Definition i18n.cpp:22
@ FilesystemCandidate
Definition models.hpp:10
bool looks_btrfs(DiskReader &reader, uint64_t offset)
bool is_ntfs(const std::array< unsigned char, 512 > &b)
bool is_fat32(const std::array< unsigned char, 512 > &b)
bool is_exfat(const std::array< unsigned char, 512 > &b)
bool looks_ext4(DiskReader &reader, uint64_t offset)