feat: Begin working on Ryuujin core
- Working on obfuscated core - Optimizing Ryuujin
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
#pragma once;
|
||||||
|
|
||||||
struct RyujinInstruction {
|
struct RyujinInstruction {
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class RyujinObfuscatorConfig {
|
class RyujinObfuscatorConfig {
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <string>
|
||||||
#include "RyujinBasicBlock.hh"
|
#include "RyujinBasicBlock.hh"
|
||||||
|
|
||||||
class RyujinProcedure {
|
class RyujinProcedure {
|
||||||
@@ -10,4 +11,26 @@ public:
|
|||||||
uintptr_t size;
|
uintptr_t size;
|
||||||
std::vector<RyujinBasicBlock> basic_blocks;
|
std::vector<RyujinBasicBlock> basic_blocks;
|
||||||
|
|
||||||
|
std::vector<ZyanU8> getUpdateOpcodes() {
|
||||||
|
|
||||||
|
std::vector<unsigned char> result;
|
||||||
|
|
||||||
|
for (auto& block : basic_blocks) {
|
||||||
|
|
||||||
|
auto& blocks = block.opcodes;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < blocks.size(); ++i) {
|
||||||
|
const auto& block = blocks[i];
|
||||||
|
if (!block.empty()) {
|
||||||
|
for (const auto& byte : block) {
|
||||||
|
result.emplace_back(byte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -94,6 +94,8 @@ bool Ryujin::run(const RyujinObfuscatorConfig& config) {
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<RyujinProcedure> processed_procs;
|
||||||
|
|
||||||
for (auto& proc : m_ryujinProcedures) {
|
for (auto& proc : m_ryujinProcedures) {
|
||||||
|
|
||||||
auto it = std::find(config.m_strProceduresToObfuscate.begin(), config.m_strProceduresToObfuscate.end(), proc.name);
|
auto it = std::find(config.m_strProceduresToObfuscate.begin(), config.m_strProceduresToObfuscate.end(), proc.name);
|
||||||
@@ -134,9 +136,10 @@ bool Ryujin::run(const RyujinObfuscatorConfig& config) {
|
|||||||
proc.basic_blocks = rybb.createBasicBlocks(ucOpcodes, proc.size, proc.address);
|
proc.basic_blocks = rybb.createBasicBlocks(ucOpcodes, proc.size, proc.address);
|
||||||
|
|
||||||
//Is time to obfuscate ?
|
//Is time to obfuscate ?
|
||||||
if (config.m_isVirtualized) todoAction();
|
RyujinObfuscationCore obc(config, proc);
|
||||||
if (config.m_isIatObfuscation) todoAction();
|
obc.Run();
|
||||||
if (config.m_isJunkCode) todoAction();
|
processed_procs.push_back(obc.getProcessedProc());
|
||||||
|
obc.~RyujinObfuscationCore();
|
||||||
|
|
||||||
//TODO: Custom passes support
|
//TODO: Custom passes support
|
||||||
|
|
||||||
@@ -155,12 +158,15 @@ bool Ryujin::run(const RyujinObfuscatorConfig& config) {
|
|||||||
RyujinPESections peSections;
|
RyujinPESections peSections;
|
||||||
peSections.AddNewSection(m_strInputFilePath, chSectionName);
|
peSections.AddNewSection(m_strInputFilePath, chSectionName);
|
||||||
|
|
||||||
//Process new opcodes
|
//Get New Opcodes - todo: improve, this only works for the first procedure
|
||||||
std::vector<unsigned char> tempValued = { 0xDE, 0xAD, 0xBE, 0xEF };
|
std::vector<unsigned char> tempValued = processed_procs.front().getUpdateOpcodes();
|
||||||
peSections.ProcessOpcodesNewSection(tempValued);
|
|
||||||
|
|
||||||
//Fix relocations
|
//Fix relocations
|
||||||
|
|
||||||
|
|
||||||
|
//Process new opcodes
|
||||||
|
peSections.ProcessOpcodesNewSection(tempValued);
|
||||||
|
|
||||||
//Save output file
|
//Save output file
|
||||||
peSections.FinishNewSection(m_strOutputFilePath);
|
peSections.FinishNewSection(m_strOutputFilePath);
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "Utils/RyujinUtils.hh"
|
#include "Utils/RyujinUtils.hh"
|
||||||
#include "Models/RyujinObfuscatorConfig.hh"
|
#include "Models/RyujinObfuscatorConfig.hh"
|
||||||
#include "RyujinCore/BasicBlockerBuilder.hh"
|
#include "RyujinCore/BasicBlockerBuilder.hh"
|
||||||
|
#include "RyujinCore/RyujinObfuscationCore.hh"
|
||||||
#include "Utils/RyujinPESections.hh"
|
#include "Utils/RyujinPESections.hh"
|
||||||
|
|
||||||
class Ryujin {
|
class Ryujin {
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
#include "RyujinObfuscationCore.hh"
|
||||||
|
|
||||||
|
RyujinObfuscationCore::RyujinObfuscationCore(const RyujinObfuscatorConfig& config, const RyujinProcedure& proc) {
|
||||||
|
|
||||||
|
m_proc = proc;
|
||||||
|
|
||||||
|
if (!extractUnusedRegisters())
|
||||||
|
throw std::exception("No registers avaliable for obfuscation...");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RyujinProcedure RyujinObfuscationCore::getProcessedProc() {
|
||||||
|
|
||||||
|
return this->m_proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL RyujinObfuscationCore::extractUnusedRegisters() {
|
||||||
|
|
||||||
|
std::vector<ZydisRegister> candidateRegs = {
|
||||||
|
|
||||||
|
ZYDIS_REGISTER_RAX,
|
||||||
|
ZYDIS_REGISTER_RCX,
|
||||||
|
ZYDIS_REGISTER_RDX,
|
||||||
|
ZYDIS_REGISTER_RBX,
|
||||||
|
ZYDIS_REGISTER_RSP,
|
||||||
|
ZYDIS_REGISTER_RBP,
|
||||||
|
ZYDIS_REGISTER_RSI,
|
||||||
|
ZYDIS_REGISTER_RDI,
|
||||||
|
ZYDIS_REGISTER_R8,
|
||||||
|
ZYDIS_REGISTER_R9,
|
||||||
|
ZYDIS_REGISTER_R10,
|
||||||
|
ZYDIS_REGISTER_R11,
|
||||||
|
ZYDIS_REGISTER_R12,
|
||||||
|
ZYDIS_REGISTER_R13,
|
||||||
|
ZYDIS_REGISTER_R14,
|
||||||
|
ZYDIS_REGISTER_R15,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
std::set<ZydisRegister> usedRegs;
|
||||||
|
|
||||||
|
for (auto blocks : m_proc.basic_blocks) {
|
||||||
|
|
||||||
|
for (auto instr : blocks.instructions) {
|
||||||
|
|
||||||
|
for (auto i = 0; i < instr.instruction.info.operand_count; ++i) {
|
||||||
|
|
||||||
|
const ZydisDecodedOperand& op = instr.instruction.operands[i];
|
||||||
|
|
||||||
|
if (op.type == ZYDIS_OPERAND_TYPE_REGISTER) usedRegs.insert(op.reg.value);
|
||||||
|
else if (op.type == ZYDIS_OPERAND_TYPE_POINTER) {
|
||||||
|
|
||||||
|
if (op.mem.base != ZYDIS_REGISTER_NONE) usedRegs.insert(op.mem.base);
|
||||||
|
if (op.mem.index != ZYDIS_REGISTER_NONE) usedRegs.insert(op.mem.index);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ZydisRegister freeReg = ZYDIS_REGISTER_NONE;
|
||||||
|
for (auto reg : candidateRegs)
|
||||||
|
if (usedRegs.count(reg) == 0) m_unusedRegisters.push_back(reg);
|
||||||
|
|
||||||
|
return m_unusedRegisters.size() >= 2; //Theres unused regs for be used by us ?
|
||||||
|
}
|
||||||
|
|
||||||
|
void RyujinObfuscationCore::addPaddingSpaces() {
|
||||||
|
|
||||||
|
asmjit::JitRuntime runtime;
|
||||||
|
|
||||||
|
for (auto& block : m_proc.basic_blocks) {
|
||||||
|
|
||||||
|
std::vector<std::vector<ZyanU8>> new_instructions;
|
||||||
|
|
||||||
|
for (auto& opcode : block.opcodes) {
|
||||||
|
|
||||||
|
std::vector<ZyanU8> new_opcodes;
|
||||||
|
|
||||||
|
for (auto individual_opcode : opcode) {
|
||||||
|
|
||||||
|
new_opcodes.push_back(individual_opcode);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
new_instructions.push_back(new_opcodes);
|
||||||
|
|
||||||
|
//Inserindo junkcode
|
||||||
|
std::vector<ZyanU8> gen_opcodes;
|
||||||
|
|
||||||
|
asmjit::CodeHolder code;
|
||||||
|
code.init(runtime.environment());
|
||||||
|
asmjit::x86::Assembler a(&code);
|
||||||
|
|
||||||
|
for (auto i = 0; i < 50; i++) {
|
||||||
|
a.nop();
|
||||||
|
}
|
||||||
|
|
||||||
|
code.flatten();
|
||||||
|
|
||||||
|
auto section = code.sectionById(0);
|
||||||
|
const uint8_t* buf = section->buffer().data();
|
||||||
|
size_t size = section->buffer().size();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; ++i) {
|
||||||
|
gen_opcodes.push_back(buf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_instructions.push_back(gen_opcodes);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Overrite the original opcodes with new ones
|
||||||
|
block.opcodes.clear();
|
||||||
|
block.opcodes.assign(new_instructions.begin(), new_instructions.end());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL RyujinObfuscationCore::Run() {
|
||||||
|
|
||||||
|
//Add padding spaces
|
||||||
|
addPaddingSpaces();
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (config.m_isIatObfuscation) todoAction();
|
||||||
|
|
||||||
|
if (config.m_isVirtualized) todoAction();
|
||||||
|
if (config.m_isJunkCode) todoAction();
|
||||||
|
*/
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RyujinObfuscationCore::~RyujinObfuscationCore() {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
#include <asmjit/asmjit.h>
|
||||||
|
#include <Zydis/Zydis.h>
|
||||||
|
#include <Zydis/SharedTypes.h>
|
||||||
|
#include "../Models/RyujinProcedure.hh"
|
||||||
|
#include "../Models/RyujinObfuscatorConfig.hh"
|
||||||
|
|
||||||
|
class RyujinObfuscationCore {
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<ZydisRegister> m_unusedRegisters;
|
||||||
|
RyujinProcedure m_proc;
|
||||||
|
BOOL extractUnusedRegisters();
|
||||||
|
void addPaddingSpaces();
|
||||||
|
|
||||||
|
public:
|
||||||
|
RyujinObfuscationCore(const RyujinObfuscatorConfig& config, const RyujinProcedure& proc);
|
||||||
|
BOOL Run();
|
||||||
|
RyujinProcedure getProcessedProc();
|
||||||
|
~RyujinObfuscationCore();
|
||||||
|
|
||||||
|
};
|
||||||
@@ -134,6 +134,7 @@
|
|||||||
<ClCompile Include="RyujinConsole.cc" />
|
<ClCompile Include="RyujinConsole.cc" />
|
||||||
<ClCompile Include="Ryujin\Ryujin.cc" />
|
<ClCompile Include="Ryujin\Ryujin.cc" />
|
||||||
<ClCompile Include="Ryujin\RyujinCore\BasicBlockerBuilder.cc" />
|
<ClCompile Include="Ryujin\RyujinCore\BasicBlockerBuilder.cc" />
|
||||||
|
<ClCompile Include="Ryujin\RyujinCore\RyujinObfuscationCore.cc" />
|
||||||
<ClCompile Include="Ryujin\Utils\RyujinPESections.cc" />
|
<ClCompile Include="Ryujin\Utils\RyujinPESections.cc" />
|
||||||
<ClCompile Include="Ryujin\Utils\RyujinUtils.cc" />
|
<ClCompile Include="Ryujin\Utils\RyujinUtils.cc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@@ -145,6 +146,7 @@
|
|||||||
<ClInclude Include="Ryujin\PDB\RyujinPdbParsing.hh" />
|
<ClInclude Include="Ryujin\PDB\RyujinPdbParsing.hh" />
|
||||||
<ClInclude Include="Ryujin\Ryujin.hh" />
|
<ClInclude Include="Ryujin\Ryujin.hh" />
|
||||||
<ClInclude Include="Ryujin\RyujinCore\BasicBlockerBuilder.hh" />
|
<ClInclude Include="Ryujin\RyujinCore\BasicBlockerBuilder.hh" />
|
||||||
|
<ClInclude Include="Ryujin\RyujinCore\RyujinObfuscationCore.hh" />
|
||||||
<ClInclude Include="Ryujin\Utils\RyujinPESections.hh" />
|
<ClInclude Include="Ryujin\Utils\RyujinPESections.hh" />
|
||||||
<ClInclude Include="Ryujin\Utils\RyujinUtils.hh" />
|
<ClInclude Include="Ryujin\Utils\RyujinUtils.hh" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -45,6 +45,9 @@
|
|||||||
<ClCompile Include="Ryujin\Utils\RyujinPESections.cc">
|
<ClCompile Include="Ryujin\Utils\RyujinPESections.cc">
|
||||||
<Filter>Ryujin\Utils</Filter>
|
<Filter>Ryujin\Utils</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Ryujin\RyujinCore\RyujinObfuscationCore.cc">
|
||||||
|
<Filter>Ryujin\RyujinCore</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Ryujin\Models\RyujinBasicBlock.hh">
|
<ClInclude Include="Ryujin\Models\RyujinBasicBlock.hh">
|
||||||
@@ -74,5 +77,8 @@
|
|||||||
<ClInclude Include="Ryujin\Utils\RyujinPESections.hh">
|
<ClInclude Include="Ryujin\Utils\RyujinPESections.hh">
|
||||||
<Filter>Ryujin\Utils</Filter>
|
<Filter>Ryujin\Utils</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Ryujin\RyujinCore\RyujinObfuscationCore.hh">
|
||||||
|
<Filter>Ryujin\RyujinCore</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
Reference in New Issue
Block a user