feat: Ryujin pdb parsing
Finishing the Ryujin PDB parsing feature implementation.
This commit is contained in:
@@ -10,7 +10,32 @@ m_strInputFilePath(strInputFilePath), m_strOutputFilePath(strOutputFilePath), m_
|
|||||||
|
|
||||||
if (!m_isInitialized) {
|
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) {
|
if (imgDos->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||||
|
|
||||||
OutputDebugStringA(
|
::OutputDebugStringA(
|
||||||
|
|
||||||
_In_ "Ryujin::run: Invalid PE File.\n"
|
_In_ "Ryujin::run: Invalid PE File.\n"
|
||||||
|
|
||||||
@@ -35,7 +60,7 @@ bool Ryujin::run() {
|
|||||||
|
|
||||||
if (imgNt->Signature != IMAGE_NT_SIGNATURE) {
|
if (imgNt->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
|
|
||||||
OutputDebugStringA(
|
::OutputDebugStringA(
|
||||||
|
|
||||||
_In_ "Ryujin::run: Invalid NT headers for the input PE File.\n"
|
_In_ "Ryujin::run: Invalid NT headers for the input PE File.\n"
|
||||||
|
|
||||||
@@ -46,7 +71,7 @@ bool Ryujin::run() {
|
|||||||
|
|
||||||
if (!m_isInitialized) {
|
if (!m_isInitialized) {
|
||||||
|
|
||||||
OutputDebugStringA(
|
::OutputDebugStringA(
|
||||||
|
|
||||||
_In_ "Ryujin::Ryujin: not initilized.\n"
|
_In_ "Ryujin::Ryujin: not initilized.\n"
|
||||||
|
|
||||||
@@ -55,15 +80,27 @@ bool Ryujin::run() {
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto syms = RyujinPdbParsing::ExtractProceduresFromPdb(
|
}
|
||||||
|
|
||||||
reinterpret_cast<uintptr_t>(m_mappedPE.get()),
|
void Ryujin::listRyujinProcedures() {
|
||||||
m_szFile,
|
|
||||||
m_strInputFilePath,
|
if (!m_isInitialized) {
|
||||||
m_strPdbFilePath
|
|
||||||
|
::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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ryujin::~Ryujin() {
|
Ryujin::~Ryujin() {
|
||||||
|
|||||||
@@ -16,10 +16,12 @@ private:
|
|||||||
const std::string& m_strOutputFilePath;
|
const std::string& m_strOutputFilePath;
|
||||||
uintptr_t m_szFile;
|
uintptr_t m_szFile;
|
||||||
BOOL m_isInitialized;
|
BOOL m_isInitialized;
|
||||||
|
std::vector<RyujinProcedure> m_ryujinProcedures;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ryujin(const std::string& strInputFilePath, const std::string& strPdbFilePath, const std::string& strOutputFilePath);
|
Ryujin(const std::string& strInputFilePath, const std::string& strPdbFilePath, const std::string& strOutputFilePath);
|
||||||
bool run();
|
bool run();
|
||||||
|
void listRyujinProcedures();
|
||||||
~Ryujin();
|
~Ryujin();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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");
|
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.get()->run();
|
||||||
|
|
||||||
ryujin.reset();
|
ryujin.reset();
|
||||||
|
|||||||
@@ -1,18 +1,116 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <windows.h>
|
||||||
|
#include <dbghelp.h>
|
||||||
|
#pragma comment(lib, "DbgHelp.lib")
|
||||||
#include "RyujinProcedure.hh"
|
#include "RyujinProcedure.hh"
|
||||||
//#include <dbghelp.h>
|
|
||||||
|
|
||||||
//#pragma comment(lib, "DbgHelp.lib")
|
#define SymTagFunction 5
|
||||||
|
|
||||||
class RyujinPdbParsing {
|
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:
|
public:
|
||||||
|
|
||||||
|
static std::vector<RyujinProcedure> ExtractProceduresFromPdb(uintptr_t mappedPebase, uintptr_t szFile, const std::string& strInputFilePath, const std::string& strPdbFilePath) {
|
||||||
static std::vector<RyujinProcedure> ExtractProceduresFromPdb(uintptr_t mappedPebase, uintptr_t m_szFile, const std::string& m_strInputFilePath, const std::string& m_strPdbFilePath) {
|
|
||||||
|
|
||||||
std::vector<RyujinProcedure> procs;
|
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;
|
return procs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user