Files
ctf/2026/kalmar/rev/oracle/solve.cpp
2026-04-15 01:05:54 +02:00

80 lines
2.2 KiB
C++

#include <iostream>
#include <string>
#include <vector>
#include <stdint.h>
#include <future>
const uint32_t BASIS = 0x811c9dc5;
const uint32_t PRIME = 0x1000193;
const std::string CHARSET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
uint32_t fnv1a(const std::string& s) {
uint32_t hash = BASIS;
for (unsigned char c : s) {
hash ^= c;
hash *= PRIME;
}
return hash;
}
// Recursive cracker for a specific segment
std::string crack(int length, uint32_t target) {
std::string current(length, CHARSET[0]);
auto backtrack = [&](auto self, int depth) -> bool {
if (depth == length) {
return fnv1a(current) == target;
}
for (char c : CHARSET) {
current[depth] = c;
if (self(self, depth + 1)) return true;
}
return false;
};
if (backtrack(backtrack, 0)) return current;
return "?????";
}
int main() {
struct Segment {
int id;
int len;
uint32_t hash;
};
std::vector<Segment> segments = {
{1, 4, 0x1fdb82eb}, // 7:11
{2, 3, 0xc498c8a6}, // 12:15
{3, 5, 0xd451383b}, // 16:21
{4, 3, 0xf1d1bdc9}, // 22:25
{5, 5, 0x5768cca7}, // 26:31
{6, 3, 0xe25d1966}, // 32:35
{7, 4, 0x45b2772b} // 36:40
};
std::vector<std::future<std::string>> workers;
std::cout << "[*] Launching 7 parallel threads for FNV-1a brute-force..." << std::endl;
for (const auto& s : segments) {
workers.push_back(std::async(std::launch::async, crack, s.len, s.hash));
}
std::vector<std::string> results;
for (size_t i = 0; i < workers.size(); ++i) {
std::string found = workers[i].get();
results.push_back(found);
std::cout << "[+] Segment " << i + 1 << " (" << segments[i].len << " chars): " << found << std::endl;
}
std::cout << "\n==========================================" << std::endl;
std::cout << "FINAL FLAG: kalmar{";
for (size_t i = 0; i < results.size(); ++i) {
std::cout << results[i] << (i == results.size() - 1 ? "" : "_");
}
std::cout << "}" << std::endl;
std::cout << "==========================================" << std::endl;
return 0;
}