feat: add built-in magicblob parser support.
This commit is contained in:
70
src/data_format/magic_blob.cpp
Normal file
70
src/data_format/magic_blob.cpp
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#include "magic_blob.h"
|
||||||
|
|
||||||
|
#define XXH_INLINE_ALL
|
||||||
|
#include "xxhash.h"
|
||||||
|
|
||||||
|
#ifndef HIDWORD
|
||||||
|
#define HIDWORD(x) (*((int32_t*)&(x) + 1))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// copy from ida F5.
|
||||||
|
constexpr uint64_t unk_hash(uint64_t a1) {
|
||||||
|
unsigned int v1; // eax
|
||||||
|
int v2; // edx
|
||||||
|
int64_t v3; // rdx
|
||||||
|
|
||||||
|
v1 = ((33
|
||||||
|
* ((4097 * HIDWORD(a1) + 2127912214)
|
||||||
|
^ ((unsigned int)(4097 * HIDWORD(a1) + 2127912214) >> 19)
|
||||||
|
^ 0xC761C23C)
|
||||||
|
+ 374761393)
|
||||||
|
<< 9)
|
||||||
|
^ (33
|
||||||
|
* ((4097 * HIDWORD(a1) + 2127912214)
|
||||||
|
^ ((unsigned int)(4097 * HIDWORD(a1) + 2127912214) >> 19)
|
||||||
|
^ 0xC761C23C)
|
||||||
|
- 369570787);
|
||||||
|
v2 = 33
|
||||||
|
* ((4097 * a1 + 2127912214)
|
||||||
|
^ ((unsigned int)(4097 * a1 + 2127912214) >> 19) ^ 0xC761C23C);
|
||||||
|
v3 = (((v2 + 374761393) << 9) ^ (v2 - 369570787))
|
||||||
|
+ 8 * (((v2 + 374761393) << 9) ^ (unsigned int)(v2 - 369570787))
|
||||||
|
- 42973499;
|
||||||
|
return (v3 ^ (((unsigned int)v3 ^ 0xB55A4F090000uLL) >> 16))
|
||||||
|
| ((((v1 + 8 * v1 - 42973499) & 0xFFFF0000)
|
||||||
|
^ (((v1 + 8 * v1 - 42973499) ^ 0xFFFFFFFFB55A4F09uLL) << 16))
|
||||||
|
<< 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace di::data_format {
|
||||||
|
|
||||||
|
void MagicBlob::read(const fs::path& path) {
|
||||||
|
StreamedIO::read(path);
|
||||||
|
|
||||||
|
m_stored_seed = eat<uint64_t>();
|
||||||
|
m_query_seed = unk_hash(m_stored_seed);
|
||||||
|
|
||||||
|
rva_t n_rva{};
|
||||||
|
|
||||||
|
while (next() != EOF) {
|
||||||
|
auto flags = eat_varint<uint64_t>();
|
||||||
|
auto rva = eat_varint<rva_t>();
|
||||||
|
auto hash = eat<hash_t>();
|
||||||
|
|
||||||
|
// see comments in magic_entry.h
|
||||||
|
n_rva += rva;
|
||||||
|
rva = n_rva;
|
||||||
|
|
||||||
|
m_entities.emplace(hash, std::make_unique<MagicEntry>(flags, rva));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MagicEntry const* MagicBlob::query(std::string_view symbol) const {
|
||||||
|
auto query_hash = XXH64(symbol.data(), symbol.size(), m_query_seed);
|
||||||
|
if (m_entities.contains(query_hash)) {
|
||||||
|
return m_entities.at(query_hash).get();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace di::data_format
|
||||||
25
src/data_format/magic_blob.h
Normal file
25
src/data_format/magic_blob.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "data_format/io/streamed_io.h"
|
||||||
|
#include "data_format/type/magic_entry.h"
|
||||||
|
|
||||||
|
namespace di::data_format {
|
||||||
|
|
||||||
|
class MagicBlob : public StreamedIO {
|
||||||
|
public:
|
||||||
|
void read(const fs::path& path) override;
|
||||||
|
|
||||||
|
constexpr size_t count() const { return m_entities.size(); }
|
||||||
|
|
||||||
|
MagicEntry const* query(std::string_view symbol) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<hash_t, std::unique_ptr<MagicEntry>> m_entities;
|
||||||
|
|
||||||
|
// MagicBlob uses a custom algorithm to transform the stored seed. When
|
||||||
|
// querying, you should use m_query_seed.
|
||||||
|
uint64_t m_stored_seed{};
|
||||||
|
uint64_t m_query_seed{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace di::data_format
|
||||||
21
src/data_format/type/magic_entry.h
Normal file
21
src/data_format/type/magic_entry.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace di {
|
||||||
|
|
||||||
|
struct MagicEntry {
|
||||||
|
std::bitset<64> flags;
|
||||||
|
// What is stored in the original format is not the RVA itself, but the
|
||||||
|
// difference with the previous entry (in MagicBlob, RVA is sorted from
|
||||||
|
// small to large)
|
||||||
|
// But here, we still store the "real" RVA.
|
||||||
|
rva_t rva;
|
||||||
|
// Do not put the original hash in the entry yet.
|
||||||
|
// hash_t hash;
|
||||||
|
|
||||||
|
constexpr bool is_function() { return flags[0]; }
|
||||||
|
constexpr bool _unk2() { return flags[1]; }
|
||||||
|
constexpr bool is_verbose() { return flags[2]; }
|
||||||
|
constexpr bool _unk4() { return flags[3]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace di
|
||||||
Reference in New Issue
Block a user