feat: Ryujin pdb parsing

Finishing the Ryujin PDB parsing feature implementation.
This commit is contained in:
keowu
2025-05-24 09:19:01 -03:00
parent 82a15d5358
commit 8d91117554
4 changed files with 155 additions and 16 deletions

View File

@@ -10,7 +10,32 @@ m_strInputFilePath(strInputFilePath), m_strOutputFilePath(strOutputFilePath), m_
if (!m_isInitialized) {
OutputDebugStringA("Ryujin::Ryujin: failed to initilize.\n");
::OutputDebugStringA(
_In_ "Ryujin::Ryujin: failed to initilize.\n"
);
}
m_ryujinProcedures = RyujinPdbParsing::ExtractProceduresFromPdb(
reinterpret_cast<uintptr_t>(m_mappedPE.get()),
m_szFile,
m_strInputFilePath,
m_strPdbFilePath
);
if (m_ryujinProcedures.size() == 0) {
m_isInitialized = FALSE;
::OutputDebugStringA(
_In_ "Ryujin::Ryujin: No Associate PDB file found for the input binary.."
);
}
@@ -22,7 +47,7 @@ bool Ryujin::run() {
if (imgDos->e_magic != IMAGE_DOS_SIGNATURE) {
OutputDebugStringA(
::OutputDebugStringA(
_In_ "Ryujin::run: Invalid PE File.\n"
@@ -35,7 +60,7 @@ bool Ryujin::run() {
if (imgNt->Signature != IMAGE_NT_SIGNATURE) {
OutputDebugStringA(
::OutputDebugStringA(
_In_ "Ryujin::run: Invalid NT headers for the input PE File.\n"
@@ -46,7 +71,7 @@ bool Ryujin::run() {
if (!m_isInitialized) {
OutputDebugStringA(
::OutputDebugStringA(
_In_ "Ryujin::Ryujin: not initilized.\n"
@@ -55,14 +80,26 @@ bool Ryujin::run() {
return FALSE;
}
auto syms = RyujinPdbParsing::ExtractProceduresFromPdb(
reinterpret_cast<uintptr_t>(m_mappedPE.get()),
m_szFile,
m_strInputFilePath,
m_strPdbFilePath
);
}
void Ryujin::listRyujinProcedures() {
if (!m_isInitialized) {
::OutputDebugStringA(
_In_ "Ryujin::Ryujin: not initilized.\n"
);
return;
}
for (auto& procedure : m_ryujinProcedures) {
std::printf("%s - 0x%llx - 0x%llx\n", procedure.name.c_str(), procedure.address, procedure.size);
}
}

View File

@@ -16,10 +16,12 @@ private:
const std::string& m_strOutputFilePath;
uintptr_t m_szFile;
BOOL m_isInitialized;
std::vector<RyujinProcedure> m_ryujinProcedures;
public:
Ryujin(const std::string& strInputFilePath, const std::string& strPdbFilePath, const std::string& strOutputFilePath);
bool run();
void listRyujinProcedures();
~Ryujin();
};

View File

@@ -7,6 +7,8 @@ auto main() -> int {
std::unique_ptr<Ryujin> ryujin = std::make_unique<Ryujin>("C:\\Users\\Keowu\\Documents\\GitHub\\MoFei\\x64\\Debug\\DemoObfuscation.exe", "C:\\Users\\Keowu\\Documents\\GitHub\\MoFei\\x64\\Debug\\DemoObfuscation.pdb", "C:\\Users\\Keowu\\Documents\\GitHub\\MoFei\\x64\\Debug\\DemoObfuscation2.exe");
ryujin.get()->listRyujinProcedures();
ryujin.get()->run();
ryujin.reset();

View File

@@ -1,18 +1,116 @@
#pragma once
#include <windows.h>
#include <dbghelp.h>
#pragma comment(lib, "DbgHelp.lib")
#include "RyujinProcedure.hh"
//#include <dbghelp.h>
//#pragma comment(lib, "DbgHelp.lib")
#define SymTagFunction 5
class RyujinPdbParsing {
private:
static BOOL CALLBACK EnumSymbolsCallback(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext) {
auto* vecSymbols = reinterpret_cast<std::vector<RyujinProcedure>*>(UserContext);
//Daddy, is this symbol a function entry ?!
if (pSymInfo->Tag == SymTagFunction) {
RyujinProcedure proc;
proc.name = pSymInfo->Name;
proc.address = pSymInfo->Address;
proc.size = pSymInfo->Size;
vecSymbols->emplace_back(proc);
}
return TRUE;
}
public:
static std::vector<RyujinProcedure> ExtractProceduresFromPdb(uintptr_t mappedPebase, uintptr_t m_szFile, const std::string& m_strInputFilePath, const std::string& m_strPdbFilePath) {
static std::vector<RyujinProcedure> ExtractProceduresFromPdb(uintptr_t mappedPebase, uintptr_t szFile, const std::string& strInputFilePath, const std::string& strPdbFilePath) {
std::vector<RyujinProcedure> procs;
::SymSetOptions(
_In_ SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME
);
if (!::SymInitialize(
_In_ ::GetCurrentProcess(),
_In_opt_ nullptr,
_In_ NULL
)) {
::OutputDebugStringA(
_In_ "RyujinPdbParsing::ExtractProceduresFromPdb: SymInitialize failed..\n"
);
return procs;
}
auto strPdbDirectory = strPdbFilePath.substr(0, strPdbFilePath.find_last_of("\\/"));
::SymSetSearchPath(
::GetCurrentProcess(),
strPdbDirectory.c_str()
);
auto loadedModuleBase = ::SymLoadModule64(
_In_ ::GetCurrentProcess(),
_In_opt_ nullptr,
_In_opt_ strInputFilePath.c_str(),
_In_opt_ nullptr,
_In_ mappedPebase,
_In_ szFile
);
if (loadedModuleBase == 0) {
::OutputDebugStringA(
_In_ "RyujinPdbParsing::ExtractProceduresFromPdb: Failed to load SymLoadModule64..\n"
);
::SymCleanup(
_In_ ::GetCurrentProcess()
);
return procs;
}
::SymEnumSymbols(
_In_ ::GetCurrentProcess(),
_In_ loadedModuleBase,
_In_opt_ nullptr,
_In_ RyujinPdbParsing::EnumSymbolsCallback,
_In_opt_ &procs
);
::SymCleanup(
_In_::GetCurrentProcess()
);
return procs;
}