feat: Ryujin Basic Blocks, Opcode extractor and disassembler.

- Working on Ryujin Basic Block parsing feature.
- Opcodes Extractor.
- Disassembler.
- Fixing some bugs when printing names.
This commit is contained in:
keowu
2025-05-24 19:50:25 -03:00
parent 8c10fd6088
commit ee3025b942
6 changed files with 146 additions and 3 deletions

View File

@@ -91,13 +91,13 @@ bool Ryujin::run(const RyujinObfuscatorConfig& config) {
return FALSE;
}
for (const auto& proc : m_ryujinProcedures) {
for (auto& proc : m_ryujinProcedures) {
auto it = std::find(config.m_strProceduresToObfuscate.begin(), config.m_strProceduresToObfuscate.end(), proc.name);
if (it == config.m_strProceduresToObfuscate.end()) continue;
std::printf("[WORKING ON]: %s\n", proc.name);
std::printf("[WORKING ON]: %s\n", proc.name.c_str());
// Is a valid procedure ?
if (proc.size == 0) {
@@ -111,8 +111,22 @@ bool Ryujin::run(const RyujinObfuscatorConfig& config) {
continue;
}
//Create basic blocks
//Get procedure opcodes from mapped pe file
auto ucOpcodes = new unsigned char[proc.size] { 0 };
std::memcpy(
ucOpcodes,
reinterpret_cast<void*>(proc.address),
proc.size
);
//Create basic blocks
RyujinBasicBlockerBuilder rybb(ZYDIS_MACHINE_MODE_LONG_64, ZydisStackWidth_::ZYDIS_STACK_WIDTH_64);
proc.basic_blocks = rybb.createBasicBlocks(ucOpcodes, proc.size, proc.address);
//Clean up opcodes
delete[] ucOpcodes;
}

View File

@@ -7,6 +7,7 @@
#include "PDB/RyujinPdbParsing.hh"
#include "Utils/RyujinUtils.hh"
#include "Models/RyujinObfuscatorConfig.hh"
#include "RyujinCore/BasicBlockerBuilder.hh"
class Ryujin {

View File

@@ -0,0 +1,100 @@
#include "BasicBlockerBuilder.hh"
bool RyujinBasicBlockerBuilder::isControlFlow(const ZydisDecodedInstruction& instruction) const {
return (instruction.meta.category == ZYDIS_CATEGORY_CALL ||
instruction.meta.category == ZYDIS_CATEGORY_RET ||
instruction.meta.category == ZYDIS_CATEGORY_UNCOND_BR ||
instruction.meta.category == ZYDIS_CATEGORY_COND_BR ||
instruction.meta.category == ZYDIS_CATEGORY_SYSTEM ||
instruction.meta.category == ZYDIS_CATEGORY_INTERRUPT ||
instruction.meta.category == ZYDIS_CATEGORY_SYSCALL);
}
RyujinBasicBlockerBuilder::RyujinBasicBlockerBuilder(ZydisMachineMode machine, ZydisStackWidth stack) {
::ZydisDecoderInit(
_Inout_ &decoder,
_In_ machine,
_In_ stack
);
}
std::vector<RyujinBasicBlock> RyujinBasicBlockerBuilder::createBasicBlocks(const unsigned char* chOpcode, size_t szOpcode, uintptr_t start_address) {
std::vector<RyujinBasicBlock> blocks;
std::size_t offset = 0;
uintptr_t curr_addr = start_address;
while (offset < szOpcode) {
RyujinBasicBlock block;
block.start_address = start_address;
std::size_t inner = offset;
while (inner < szOpcode) {
ZydisDisassembledInstruction instr;
if (!ZYAN_SUCCESS(::ZydisDisassembleIntel(
_In_ ZYDIS_MACHINE_MODE_LONG_64,
_In_ curr_addr + (inner - offset),
_In_ chOpcode + inner,
_In_ szOpcode - inner,
_Out_ &instr
))) {
std::printf(
"RyujinBasicBlockerBuilder::createBasicBlocks: Zydis disam failed %llx\n",
inner
);
break;
}
//Storing the instruction relative to the basic block
RyujinInstruction inst;
inst.addressofinstruction = curr_addr + (inner - offset);
inst.instruction = instr;
block.instructions.push_back(
inst
);
//Storing the original opcodes from basic block
block.opcodes.emplace_back(
chOpcode + inner,
chOpcode + inner + instr.info.length
);
inner += instr.info.length;
//Theres a branch ? so let's preparate the next block
if (isControlFlow(
instr.info
)) break;
}
block.end_address = curr_addr + (inner - offset);
blocks.push_back(std::move(block));
curr_addr = block.end_address;
offset = inner;
}
return blocks;
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include <Zydis/Zydis.h>
#include <Zydis/SharedTypes.h>
#include <vector>
#include "../Models/RyujinBasicBlock.hh"
class RyujinBasicBlockerBuilder {
private:
ZydisDecoder decoder;
bool isControlFlow(const ZydisDecodedInstruction& instruction) const;
public:
RyujinBasicBlockerBuilder(ZydisMachineMode machine, ZydisStackWidth stack);
std::vector<RyujinBasicBlock> createBasicBlocks(const unsigned char* chOpcode, size_t szOpcode, uintptr_t start_address);
};

View File

@@ -133,6 +133,7 @@
<ItemGroup>
<ClCompile Include="RyujinConsole.cc" />
<ClCompile Include="Ryujin\Ryujin.cc" />
<ClCompile Include="Ryujin\RyujinCore\BasicBlockerBuilder.cc" />
<ClCompile Include="Ryujin\Utils\RyujinUtils.cc" />
</ItemGroup>
<ItemGroup>
@@ -142,6 +143,7 @@
<ClInclude Include="Ryujin\Models\RyujinProcedure.hh" />
<ClInclude Include="Ryujin\PDB\RyujinPdbParsing.hh" />
<ClInclude Include="Ryujin\Ryujin.hh" />
<ClInclude Include="Ryujin\RyujinCore\BasicBlockerBuilder.hh" />
<ClInclude Include="Ryujin\Utils\RyujinUtils.hh" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@@ -25,6 +25,9 @@
<Filter Include="Ryujin\Models">
<UniqueIdentifier>{df02e440-42fd-4d5d-ace9-62fb1891e33c}</UniqueIdentifier>
</Filter>
<Filter Include="Ryujin\RyujinCore">
<UniqueIdentifier>{cc8cdc69-0dce-4cc2-9b0d-6bba400b9599}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Ryujin\Utils\RyujinUtils.cc">
@@ -36,6 +39,9 @@
<ClCompile Include="RyujinConsole.cc">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Ryujin\RyujinCore\BasicBlockerBuilder.cc">
<Filter>Ryujin\RyujinCore</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Ryujin\Models\RyujinBasicBlock.hh">
@@ -59,5 +65,8 @@
<ClInclude Include="Ryujin\Ryujin.hh">
<Filter>Ryujin</Filter>
</ClInclude>
<ClInclude Include="Ryujin\RyujinCore\BasicBlockerBuilder.hh">
<Filter>Ryujin\RyujinCore</Filter>
</ClInclude>
</ItemGroup>
</Project>