refactor: make code work with mingw

This commit is contained in:
鲁树人 2024-12-21 03:41:38 +09:00
parent 929acfab04
commit f364acaec3
3 changed files with 34 additions and 26 deletions

View File

@ -4,7 +4,11 @@
#include <endian_helper.h> #include <endian_helper.h>
#include <md5.h> #include <md5.h>
#include <sqlite3.h> #include <sqlite3.h>
#include <algorithm>
#include <array>
#include <fstream> #include <fstream>
#include <vector>
namespace Infra { namespace Infra {
@ -18,15 +22,15 @@ inline bool is_valid_page_1_header(const uint8_t* page1) {
} }
void derive_page_key(uint8_t* aes_key, uint8_t* aes_iv, const uint8_t* p_master_key, const uint32_t page_no) { void derive_page_key(uint8_t* aes_key, uint8_t* aes_iv, const uint8_t* p_master_key, const uint32_t page_no) {
uint8_t buffer[0x18]; std::array<uint8_t, 0x18> buffer{};
// Setup buffer // Setup buffer
memcpy(buffer, p_master_key, 0x10); std::copy_n(p_master_key, 0x10, buffer.begin());
Endian::le_write(&buffer[0x10], page_no); Endian::le_write(&buffer[0x10], page_no);
Endian::le_write(&buffer[0x14], 0x546C4173); Endian::le_write(&buffer[0x14], 0x546C4173);
// Derive Key // Derive Key
md5(aes_key, buffer, 24); md5(aes_key, buffer.data(), buffer.size());
// Derive IV // Derive IV
for (uint32_t ebx{page_no + 1}, i = 0; i < 16; i += 4) { for (uint32_t ebx{page_no + 1}, i = 0; i < 16; i += 4) {
@ -38,10 +42,10 @@ void derive_page_key(uint8_t* aes_key, uint8_t* aes_iv, const uint8_t* p_master_
ebx = ecx; ebx = ecx;
Endian::le_write(&buffer[i], ebx); Endian::le_write(&buffer[i], ebx);
} }
md5(aes_iv, buffer, 16); md5(aes_iv, buffer.data(), 0x10);
// Cleanup // Cleanup
memset(buffer, 0xCC, sizeof(buffer)); std::ranges::fill(buffer, 0xcc);
} }
static const uint8_t kDefaultMasterKey[0x10] = { static const uint8_t kDefaultMasterKey[0x10] = {
@ -49,8 +53,8 @@ static const uint8_t kDefaultMasterKey[0x10] = {
0x3d, 0x18, 0x96, 0x72, 0x14, 0x4f, 0xe4, 0xbf, // 0x3d, 0x18, 0x96, 0x72, 0x14, 0x4f, 0xe4, 0xbf, //
}; };
static constexpr uint8_t kSQLiteDatabaseHeader[0x10] = {'S', 'Q', 'L', 'i', 't', 'e', ' ', 'f', static constexpr std::array<uint8_t, 0x10> kSQLiteDatabaseHeader = { //
'o', 'r', 'm', 'a', 't', ' ', '3', 0}; 'S', 'Q', 'L', 'i', 't', 'e', ' ', 'f', 'o', 'r', 'm', 'a', 't', ' ', '3', 0};
int load_db(std::vector<uint8_t>& db_data, const std::filesystem::path& db_path) { int load_db(std::vector<uint8_t>& db_data, const std::filesystem::path& db_path) {
using namespace AES; using namespace AES;
@ -87,25 +91,25 @@ int load_db(std::vector<uint8_t>& db_data, const std::filesystem::path& db_path)
} }
if (page_no == 1) [[unlikely]] { if (page_no == 1) [[unlikely]] {
if (memcmp(p_page, kSQLiteDatabaseHeader, 0x10) == 0) { if (std::equal(kSQLiteDatabaseHeader.cbegin(), kSQLiteDatabaseHeader.cend(), p_page)) {
ifs_db.read(reinterpret_cast<char*>(p_page + kPageSize), ifs_db.read(reinterpret_cast<char*>(p_page + kPageSize),
static_cast<std::streamsize>(db_size - kPageSize)); static_cast<std::streamsize>(db_size - kPageSize));
return SQLITE_OK; // no encryption return SQLITE_OK; // no encryption
} }
if (!is_valid_page_1_header(p_page)) [[unlikely]] { if (!is_valid_page_1_header(p_page)) {
db_data.clear(); db_data.clear();
return SQLITE_CORRUPT; // header validation failed return SQLITE_CORRUPT; // header validation failed
} }
uint8_t backup[0x08]; // backup magic numbers std::array<uint8_t, 8> backup{}; // backup magic numbers
memcpy(&backup, &p_page[0x10], 0x08); std::copy_n(&p_page[0x10], 0x08, backup.begin());
memcpy(&p_page[0x10], &p_page[0x08], 0x08); std::copy_n(&p_page[0x08], 0x08, &p_page[0x10]);
AES_CBC_decrypt_buffer(&ctx_aes, p_page + 0x10, kPageSize - 0x10); AES_CBC_decrypt_buffer(&ctx_aes, p_page + 0x10, kPageSize - 0x10);
if (memcmp(backup, &p_page[0x10], 0x08) != 0) { if (!std::equal(backup.cbegin(), backup.cend(), &p_page[0x10])) {
db_data.clear(); db_data.clear();
return SQLITE_CORRUPT; // header validation failed return SQLITE_CORRUPT; // header validation failed
} }
memcpy(p_page, kSQLiteDatabaseHeader, 0x10); std::ranges::copy(kSQLiteDatabaseHeader, p_page);
} else { } else {
AES_CBC_decrypt_buffer(&ctx_aes, p_page, kPageSize); AES_CBC_decrypt_buffer(&ctx_aes, p_page, kPageSize);
} }

View File

@ -1,31 +1,35 @@
#pragma once #pragma once
#include <windows.h> #include "qmc2/qmc2.h"
#include <windows.h>
#include <array> #include <array>
#include <condition_variable>
#include <filesystem> #include <filesystem>
#include <format>
#include <fstream> #include <fstream>
#include <mutex> #include <mutex>
#include <queue> #include <queue>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <thread>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "qmc2/qmc2.h"
class KggTask { class KggTask {
public: public:
explicit KggTask(std::filesystem::path kgg_path, std::filesystem::path out_dir) explicit KggTask(std::filesystem::path kgg_path, std::filesystem::path out_dir)
: kgg_path_(std::move(kgg_path)), out_dir_(std::move(out_dir)) {} : kgg_path_(std::move(kgg_path)), out_dir_(std::move(out_dir)) {}
void warning(const wchar_t* msg) const { fwprintf(stderr, L"[WARN] %s (%s)\n", msg, kgg_path_.filename().c_str()); } static void log(const std::wstring& msg) { fputws(msg.c_str(), stderr); }
void warning(const std::wstring& msg) const { warning(msg.c_str()); } void warning(const std::wstring& msg) const {
log(std::format(L"[WARN] {} ({})\n", msg, kgg_path_.filename().wstring()));
void error(const wchar_t* msg) const { fwprintf(stderr, L"[ERR ] %s (%s)\n", msg, kgg_path_.filename().c_str()); } }
void error(const std::wstring& msg) const { error(msg.c_str()); } void error(const std::wstring& msg) const {
log(std::format(L"[ERR ] {} ({})\n", msg, kgg_path_.filename().wstring()));
void info(const wchar_t* msg) const { fwprintf(stderr, L"[INFO] %s (%s)\n", msg, kgg_path_.filename().c_str()); } }
void info(const std::wstring& msg) const { info(msg.c_str()); } void info(const std::wstring& msg) const {
log(std::format(L"[INFO] {} ({})\n", msg, kgg_path_.filename().wstring()));
}
void Execute(const Infra::kgm_ekey_db_t& ekey_db, const std::wstring_view suffix) const { void Execute(const Infra::kgm_ekey_db_t& ekey_db, const std::wstring_view suffix) const {
constexpr static std::array<uint8_t, 16> kMagicHeader{0x7C, 0xD5, 0x32, 0xEB, 0x86, 0x02, 0x7F, 0x4B, constexpr static std::array<uint8_t, 16> kMagicHeader{0x7C, 0xD5, 0x32, 0xEB, 0x86, 0x02, 0x7F, 0x4B,

View File

@ -29,7 +29,7 @@ void WalkFileOrDir(KggTaskQueue& queue, const std::filesystem::path& input_path,
continue; continue;
} }
fwprintf(stderr, L"[WARN] invalid path: %s\n", target_path.c_str()); fputws(std::format(L"[WARN] invalid path: {}\n", target_path.wstring()).c_str(), stderr);
} }
} }