refactor: make code work with mingw
This commit is contained in:
parent
929acfab04
commit
f364acaec3
@ -4,7 +4,11 @@
|
||||
#include <endian_helper.h>
|
||||
#include <md5.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
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) {
|
||||
uint8_t buffer[0x18];
|
||||
std::array<uint8_t, 0x18> 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[0x14], 0x546C4173);
|
||||
|
||||
// Derive Key
|
||||
md5(aes_key, buffer, 24);
|
||||
md5(aes_key, buffer.data(), buffer.size());
|
||||
|
||||
// Derive IV
|
||||
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;
|
||||
Endian::le_write(&buffer[i], ebx);
|
||||
}
|
||||
md5(aes_iv, buffer, 16);
|
||||
md5(aes_iv, buffer.data(), 0x10);
|
||||
|
||||
// Cleanup
|
||||
memset(buffer, 0xCC, sizeof(buffer));
|
||||
std::ranges::fill(buffer, 0xcc);
|
||||
}
|
||||
|
||||
static const uint8_t kDefaultMasterKey[0x10] = {
|
||||
@ -49,8 +53,8 @@ static const uint8_t kDefaultMasterKey[0x10] = {
|
||||
0x3d, 0x18, 0x96, 0x72, 0x14, 0x4f, 0xe4, 0xbf, //
|
||||
};
|
||||
|
||||
static constexpr uint8_t kSQLiteDatabaseHeader[0x10] = {'S', 'Q', 'L', 'i', 't', 'e', ' ', 'f',
|
||||
'o', 'r', 'm', 'a', 't', ' ', '3', 0};
|
||||
static constexpr std::array<uint8_t, 0x10> kSQLiteDatabaseHeader = { //
|
||||
'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) {
|
||||
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 (memcmp(p_page, kSQLiteDatabaseHeader, 0x10) == 0) {
|
||||
if (std::equal(kSQLiteDatabaseHeader.cbegin(), kSQLiteDatabaseHeader.cend(), p_page)) {
|
||||
ifs_db.read(reinterpret_cast<char*>(p_page + kPageSize),
|
||||
static_cast<std::streamsize>(db_size - kPageSize));
|
||||
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();
|
||||
return SQLITE_CORRUPT; // header validation failed
|
||||
}
|
||||
uint8_t backup[0x08]; // backup magic numbers
|
||||
memcpy(&backup, &p_page[0x10], 0x08);
|
||||
memcpy(&p_page[0x10], &p_page[0x08], 0x08);
|
||||
std::array<uint8_t, 8> backup{}; // backup magic numbers
|
||||
std::copy_n(&p_page[0x10], 0x08, backup.begin());
|
||||
std::copy_n(&p_page[0x08], 0x08, &p_page[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();
|
||||
return SQLITE_CORRUPT; // header validation failed
|
||||
}
|
||||
memcpy(p_page, kSQLiteDatabaseHeader, 0x10);
|
||||
std::ranges::copy(kSQLiteDatabaseHeader, p_page);
|
||||
} else {
|
||||
AES_CBC_decrypt_buffer(&ctx_aes, p_page, kPageSize);
|
||||
}
|
||||
|
26
src/jobs.hpp
26
src/jobs.hpp
@ -1,31 +1,35 @@
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
#include "qmc2/qmc2.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <array>
|
||||
#include <condition_variable>
|
||||
#include <filesystem>
|
||||
#include <format>
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "qmc2/qmc2.h"
|
||||
|
||||
class KggTask {
|
||||
public:
|
||||
explicit KggTask(std::filesystem::path kgg_path, std::filesystem::path 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()); }
|
||||
void warning(const std::wstring& msg) const { warning(msg.c_str()); }
|
||||
|
||||
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 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()); }
|
||||
static void log(const std::wstring& msg) { fputws(msg.c_str(), stderr); }
|
||||
void warning(const std::wstring& msg) const {
|
||||
log(std::format(L"[WARN] {} ({})\n", msg, kgg_path_.filename().wstring()));
|
||||
}
|
||||
void error(const std::wstring& msg) const {
|
||||
log(std::format(L"[ERR ] {} ({})\n", msg, kgg_path_.filename().wstring()));
|
||||
}
|
||||
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 {
|
||||
constexpr static std::array<uint8_t, 16> kMagicHeader{0x7C, 0xD5, 0x32, 0xEB, 0x86, 0x02, 0x7F, 0x4B,
|
||||
|
@ -29,7 +29,7 @@ void WalkFileOrDir(KggTaskQueue& queue, const std::filesystem::path& input_path,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user