feat: New HVPass (extension for code obfuscation) + MiniVM code mutation (for HVPass and standard MiniVM); Bug fixes for extracted unused registers (with future XMM support); Bug fixes for junk/mutation overwriting the RAX register unexpectedly; Improvements and added support for fixing relocation offsets in memory mov instructions; articles/projects diagrams and more.
- New HVPass feature – This feature allows the code VM to run through Microsoft’s Hypervisor API, adding an extra layer of analysis difficulty. - MiniVM (normal) or MiniVM + HVPass – Now support junk/mutation in the stub, making the logic and instructions randomized at each interaction, further protecting the stub’s code. - Bug fix – Fixed an issue in the extraction of unused registers from candidate procedures, where some registers were not being handled correctly. - Bug fix – Fixed an issue in the extraction of XMM registers to enable junk/mutation support for multimedia registers. - Bug fix – Fixed a problem in the junk/mutation logic for the instructions cdqe and cbw, which were incorrectly overwriting the RAX register, breaking results even when the registers were in use. - Bug fix – Some instructions were not having relocations properly fixed by the RIP-relative relocation algorithm; this has now been corrected. - Articles + Project Diagrams as well. Some of these issues, as well as feature suggestions like HVPass, were discovered or suggested by the reviewers of Ryujin’s article.
This commit is contained in:
@@ -67,12 +67,13 @@ Options:
|
||||
--Troll Crashes the entire OS if a debugger is detected (requires --AntiDebug).
|
||||
--AntiDump Inserts anti-dump mechanisms that break the binary in memory, making dumps harder to analyze.
|
||||
--MemoryProtection Protects obfuscated code against in-memory or on-disk patching.
|
||||
--HVPass Protect some parts of Ryujin using Microsoft Hypervisor APIs
|
||||
--procs <comma,separated,names> Procedures to obfuscate (default: main, invoke_main, ...)
|
||||
|
||||
--help Show this help message
|
||||
|
||||
In Action Usage Example:
|
||||
RyujinConsole.exe --input C:\\Users\\Keowu\\Documents\\GitHub\\Ryujin\\compiled\\release\\DemoObfuscation.exe --pdb C:\\Users\\Keowu\\Documents\\GitHub\\Ryujin\\compiled\\release\\RyujinConsole.pdb --output C:\\Users\\Keowu\\Documents\\GitHub\\Ryujin\\compiled\\release\\DemoObfuscation.ryujin.exe --virtualize --junk --encrypt --AntiDebug --troll --AntiDump --procs main,sub,subadd,sum,invoke_main,__scrt_common_main,j___security_init_cookie
|
||||
RyujinConsole.exe --input C:\\Users\\Keowu\\Documents\\GitHub\\Ryujin\\compiled\\release\\DemoObfuscation.exe --pdb C:\\Users\\Keowu\\Documents\\GitHub\\Ryujin\\compiled\\release\\RyujinConsole.pdb --output C:\\Users\\Keowu\\Documents\\GitHub\\Ryujin\\compiled\\release\\DemoObfuscation.ryujin.exe --virtualize --junk --encrypt --AntiDebug --troll --AntiDump --iat --HVPass --procs main,sub,subadd,sum,invoke_main,__scrt_common_main,j___security_init_cookie
|
||||
|
||||
)";
|
||||
|
||||
@@ -131,6 +132,7 @@ auto main(int argc, char* argv[]) -> int {
|
||||
config.m_isAntiDebug = has_flag(args, "--AntiDebug");
|
||||
config.m_isAntiDump = has_flag(args, "--AntiDump");
|
||||
config.m_isMemoryProtection = has_flag(args, "--MemoryProtection");
|
||||
config.m_isHVPass = has_flag(args, "--HVPass");
|
||||
|
||||
// Registering a new custom pass for invocation via callback
|
||||
config.RegisterCallback(RyujinCustomPassDemo);
|
||||
|
||||
@@ -35,6 +35,7 @@ public:
|
||||
bool m_isTrollRerversers; // The user wants to trick and use a special feature to troll reversers when their debugs be detected making they loose all the progress
|
||||
bool m_isAntiDump; // Enable Anti Dump technic for Ryujin protected binary
|
||||
bool m_isMemoryProtection; // Memory CRC32 protection
|
||||
bool m_isHVPass; // Run some features of ryujin using Microsoft Hypervisor Framework API
|
||||
RyujinObfuscatorProcs m_strProceduresToObfuscate; // Names of the procedures to obfuscate
|
||||
RyujinCallbacks m_callbacks; // Ryujin Custom Pass Callbacks
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ public:
|
||||
bool m_isTrollRerversers; // The user wants to trick and use a special feature to troll reversers when their debugs be detected making they loose all the progress
|
||||
bool m_isAntiDump; // Enable Anti Dump technic for Ryujin protected binary
|
||||
bool m_isMemoryProtection; // Memory CRC32 protection
|
||||
bool m_isHVPass; // Run some features of ryujin using Microsoft Hypervisor Framework API
|
||||
RyujinObfuscatorProcs m_strProceduresToObfuscate; // Names of the procedures to obfuscate
|
||||
RyujinCallbacks m_callbacks; // Ryujin Custom Pass Callbacks
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,54 +18,139 @@ RyujinProcedure RyujinObfuscationCore::getProcessedProc() {
|
||||
|
||||
BOOL RyujinObfuscationCore::extractUnusedRegisters() {
|
||||
|
||||
std::vector<ZydisRegister> candidateRegs = {
|
||||
|
||||
ZYDIS_REGISTER_RAX,
|
||||
ZYDIS_REGISTER_RCX,
|
||||
ZYDIS_REGISTER_RDX,
|
||||
ZYDIS_REGISTER_RBX,
|
||||
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,
|
||||
// List of all general-purpose registers considered as candidates for junk/mutation during comparison.
|
||||
const std::vector<ZydisRegister> candidateGprRegs = {
|
||||
|
||||
ZYDIS_REGISTER_RAX, ZYDIS_REGISTER_RCX, ZYDIS_REGISTER_RDX,
|
||||
ZYDIS_REGISTER_RBX, 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
|
||||
|
||||
};
|
||||
|
||||
// List of XMM registers considered as candidates for junk/mutation during comparison.
|
||||
const std::vector<ZydisRegister> candidateXmmRegs = {
|
||||
|
||||
ZYDIS_REGISTER_XMM0, ZYDIS_REGISTER_XMM1, ZYDIS_REGISTER_XMM2, ZYDIS_REGISTER_XMM3,
|
||||
ZYDIS_REGISTER_XMM4, ZYDIS_REGISTER_XMM5, ZYDIS_REGISTER_XMM6, ZYDIS_REGISTER_XMM7,
|
||||
ZYDIS_REGISTER_XMM8, ZYDIS_REGISTER_XMM9, ZYDIS_REGISTER_XMM10, ZYDIS_REGISTER_XMM11,
|
||||
ZYDIS_REGISTER_XMM12, ZYDIS_REGISTER_XMM13, ZYDIS_REGISTER_XMM14, ZYDIS_REGISTER_XMM15
|
||||
|
||||
};
|
||||
|
||||
m_unusedRegisters.clear();
|
||||
|
||||
std::set<ZydisRegister> usedRegs;
|
||||
|
||||
for (auto blocks : m_proc.basic_blocks) {
|
||||
// Regardless of everything, the stack manipulation registers RSP and RBP will always be considered as used.
|
||||
usedRegs.insert(ZYDIS_REGISTER_RSP);
|
||||
usedRegs.insert(ZYDIS_REGISTER_RBP);
|
||||
|
||||
for (auto instr : blocks.instructions) {
|
||||
for (const auto& block : m_proc.basic_blocks) {
|
||||
|
||||
for (auto i = 0; i < instr.instruction.info.operand_count; ++i) {
|
||||
for (const auto& instr : block.instructions) {
|
||||
|
||||
const auto& dinfo = instr.instruction.info;
|
||||
const uint8_t opcount = dinfo.operand_count;
|
||||
|
||||
for (uint8_t i = 0; i < opcount; ++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) {
|
||||
// Registers with explicit operands
|
||||
if (op.type == ZYDIS_OPERAND_TYPE_REGISTER) {
|
||||
|
||||
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 reg = op.reg.value;
|
||||
ZydisRegisterClass cls = ZydisRegisterGetClass(reg);
|
||||
|
||||
// Normalizing GPRs to GPR64 registers
|
||||
if (cls == ZYDIS_REGCLASS_GPR8 || cls == ZYDIS_REGCLASS_GPR16 || cls == ZYDIS_REGCLASS_GPR32 || cls == ZYDIS_REGCLASS_GPR64) {
|
||||
|
||||
int16_t id = ZydisRegisterGetId(reg);
|
||||
|
||||
// Considering the lower-nibble registers
|
||||
if (cls == ZYDIS_REGCLASS_GPR8 && id >= 4 && id <= 7)
|
||||
id -= 4;
|
||||
|
||||
ZydisRegister reg64 = ZydisRegisterEncode(ZYDIS_REGCLASS_GPR64, id);
|
||||
if (reg64 != ZYDIS_REGISTER_NONE) usedRegs.insert(reg64);
|
||||
|
||||
}
|
||||
// Fetching XMM registers
|
||||
else if (cls == ZYDIS_REGCLASS_XMM)
|
||||
usedRegs.insert(reg);
|
||||
// Checking for segment registers
|
||||
else if (cls == ZYDIS_REGCLASS_SEGMENT)
|
||||
usedRegs.insert(reg);
|
||||
}
|
||||
// Registers in use with memory operands
|
||||
else if (op.type == ZYDIS_OPERAND_TYPE_MEMORY) {
|
||||
|
||||
if (op.mem.base != ZYDIS_REGISTER_NONE) {
|
||||
|
||||
ZydisRegister base = op.mem.base;
|
||||
ZydisRegisterClass cls = ZydisRegisterGetClass(base);
|
||||
|
||||
if (cls == ZYDIS_REGCLASS_GPR8 || cls == ZYDIS_REGCLASS_GPR16 || cls == ZYDIS_REGCLASS_GPR32 || cls == ZYDIS_REGCLASS_GPR64) {
|
||||
|
||||
int16_t id = ZydisRegisterGetId(base);
|
||||
ZydisRegister base64 = ZydisRegisterEncode(ZYDIS_REGCLASS_GPR64, id);
|
||||
if (base64 != ZYDIS_REGISTER_NONE) usedRegs.insert(base64);
|
||||
|
||||
}
|
||||
else
|
||||
usedRegs.insert(base);
|
||||
|
||||
}
|
||||
|
||||
// Collecting index registers
|
||||
if (op.mem.index != ZYDIS_REGISTER_NONE) {
|
||||
|
||||
ZydisRegister idx = op.mem.index;
|
||||
ZydisRegisterClass cls = ZydisRegisterGetClass(idx);
|
||||
|
||||
if (cls == ZYDIS_REGCLASS_GPR8 || cls == ZYDIS_REGCLASS_GPR16 || cls == ZYDIS_REGCLASS_GPR32 || cls == ZYDIS_REGCLASS_GPR64) {
|
||||
|
||||
int16_t id = ZydisRegisterGetId(idx);
|
||||
ZydisRegister idx64 = ZydisRegisterEncode(ZYDIS_REGCLASS_GPR64, id);
|
||||
if (idx64 != ZYDIS_REGISTER_NONE) usedRegs.insert(idx64);
|
||||
|
||||
}
|
||||
else
|
||||
usedRegs.insert(idx);
|
||||
|
||||
}
|
||||
|
||||
// Hackfix for segment registers like: cs:[rax]
|
||||
if (op.mem.segment != ZYDIS_REGISTER_NONE)
|
||||
usedRegs.insert(op.mem.segment);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ZydisRegister freeReg = ZYDIS_REGISTER_NONE;
|
||||
for (auto reg : candidateRegs)
|
||||
if (usedRegs.count(reg) == 0) m_unusedRegisters.push_back(reg);
|
||||
/*
|
||||
Based on the collected registers, compare each register with the list of used registers
|
||||
so we can build the unique set of used registers.
|
||||
*/
|
||||
for (ZydisRegister r : candidateGprRegs)
|
||||
if (usedRegs.count(r) == 0)
|
||||
m_unusedRegisters.push_back(r);
|
||||
|
||||
return m_unusedRegisters.size() >= 2; //Theres unused regs for be used by us ?
|
||||
/*
|
||||
* TEMPORARILY DISABLED until Ryujin implements support for multimedia registers.
|
||||
*
|
||||
* Based on the collected XMM registers, compare each register with the list of used XMM registers
|
||||
* to build the unique set of used XMM registers.
|
||||
*/
|
||||
//for (ZydisRegister r : candidateXmmRegs)
|
||||
// if (usedRegs.count(r) == 0)
|
||||
// m_unusedRegisters.push_back(r);
|
||||
|
||||
// We need at least 2 registers in order for obfuscation to work.
|
||||
return (m_unusedRegisters.size() >= 2); // Seriously, Keowu? Yes. We need room to run some passes.
|
||||
}
|
||||
|
||||
void RyujinObfuscationCore::addPaddingSpaces() {
|
||||
@@ -295,7 +380,7 @@ void RyujinObfuscationCore::insertJunkCode() {
|
||||
|
||||
// Ignore stack unused registers, if the feature for extracting unused register fail
|
||||
if (idx == 4 /*RSP*/ || idx == 5 /*RBP*/) continue;
|
||||
|
||||
|
||||
// Converting GB Register Index to a GB Register
|
||||
auto regx = a.gpz(uint32_t(idx));
|
||||
|
||||
@@ -370,13 +455,33 @@ void RyujinObfuscationCore::insertJunkCode() {
|
||||
case 31: a.stc(); break;
|
||||
case 32: a.clc(); break;
|
||||
case 33: a.cmc(); break;
|
||||
case 34: a.cdqe(); break;
|
||||
case 35: a.cbw(); break;
|
||||
|
||||
//////////////////////////
|
||||
// Different logic for these registers because they overwrite RAX
|
||||
//--------------------------------------------------
|
||||
case 34: {
|
||||
a.push(asmjit::x86::rax);
|
||||
a.pushf();
|
||||
a.cdqe();
|
||||
a.popf();
|
||||
a.pop(asmjit::x86::rax);
|
||||
break;
|
||||
}
|
||||
case 35: {
|
||||
a.push(asmjit::x86::rax);
|
||||
a.pushf();
|
||||
a.cbw();
|
||||
a.popf();
|
||||
a.pop(asmjit::x86::rax);
|
||||
break;
|
||||
}
|
||||
///////////////////////////////
|
||||
case 36: a.sbb(regx, value); break;
|
||||
case 37: a.bsf(regx, regx); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Junk Code Out
|
||||
@@ -788,11 +893,13 @@ void RyujinObfuscationCore::insertVirtualization() {
|
||||
|
||||
// Breaking Decompilers
|
||||
insertBreakDecompilers(a);
|
||||
|
||||
|
||||
// Saving the current value of RCX
|
||||
a.push(asmjit::x86::rcx);
|
||||
// Saving the current value of RDX
|
||||
a.push(asmjit::x86::rdx);
|
||||
// Setup stack for MS HV Code MiniVMm stub
|
||||
if (m_config.m_isHVPass) a.sub(asmjit::x86::rsp, 0x28);
|
||||
// Storing in the first argument RCX the value of the register from the first operand of the mathematical operation
|
||||
a.mov(asmjit::x86::rcx, mapZydisToAsmjitGp(instr.instruction.operands[0].reg.value));
|
||||
// Storing in the second argument RDX the value of the bytecode sequence to be interpreted by the Ryujin MiniVM
|
||||
@@ -819,6 +926,8 @@ void RyujinObfuscationCore::insertVirtualization() {
|
||||
a.call(asmjit::x86::rax);
|
||||
// Storing the result of the MiniVM execution stored in RAX into the correct register to continue the normal execution flow
|
||||
a.mov(mapZydisToAsmjitGp(instr.instruction.operands[0].reg.value), asmjit::x86::rax);
|
||||
// Setup stack for MS HV Code MiniVMm stub
|
||||
if (m_config.m_isHVPass) a.add(asmjit::x86::rsp, 0x28);
|
||||
// Restoring the original value of RDX
|
||||
a.pop(asmjit::x86::rdx);
|
||||
// Restoring the original value of RCX
|
||||
@@ -2653,21 +2762,45 @@ void RyujinObfuscationCore::applyRelocationFixupsToInstructions(uintptr_t imageB
|
||||
auto size = new_opcodes.size();
|
||||
auto data = new_opcodes.data();
|
||||
|
||||
//Avoid memory op for stack
|
||||
if (instruction.instruction.operands->mem.base == ZYDIS_REGISTER_RSP) {
|
||||
|
||||
std::printf("Invalid relocation fix candidate for -> %s\n", instruction.instruction.text);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Getting the memory immediate offset value to build the signature
|
||||
const uint32_t memmory_immediate_offset = mem->disp.value;
|
||||
|
||||
// Creating a signature to search for the offset in the obfuscated opcodes
|
||||
ZyanI64 offset = 0;
|
||||
unsigned char ucOpcodeSignature[7]{ 0 };
|
||||
std::memcpy(&ucOpcodeSignature, reinterpret_cast<void*>(instruction.addressofinstruction), 3); // 3 BYTES do opcode relativo ao LEA ou MOV
|
||||
std::memcpy(&*(ucOpcodeSignature + 3), &memmory_immediate_offset, sizeof(memmory_immediate_offset));
|
||||
|
||||
// Finding the offset of the "LEA" or "MOV" that uses memory-relative addressing
|
||||
const ZyanI64 offset = findOpcodeOffset(data, size, &ucOpcodeSignature, 7);
|
||||
// If original instruction is not a mov reg, cs[](beacuse it has 6 not 7 bytes)
|
||||
if (*reinterpret_cast<unsigned char*>(instruction.addressofinstruction) != 0x8B) {
|
||||
|
||||
// Creating a signature to search for the offset in the obfuscated opcodes
|
||||
std::memcpy(&ucOpcodeSignature, reinterpret_cast<void*>(instruction.addressofinstruction), 3); // 3 BYTES do opcode relativo ao LEA ou MOV
|
||||
std::memcpy(&*(ucOpcodeSignature + 3), &memmory_immediate_offset, sizeof(memmory_immediate_offset));
|
||||
|
||||
// Finding the offset of the "LEA" or "MOV" that uses memory-relative addressing
|
||||
offset = findOpcodeOffset(data, size, &ucOpcodeSignature, 7);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
// Creating a signature to search for the offset in the obfuscated opcodes
|
||||
std::memcpy(&ucOpcodeSignature, reinterpret_cast<void*>(instruction.addressofinstruction), 6); // 6 bytes do opcode relativo MOV CODE SEGMENT: mov reg, cs:addr
|
||||
|
||||
// Finding the offset of the "MOV reg, cs:addr" that uses memory-relative addressing
|
||||
offset = findOpcodeOffset(data, size, &ucOpcodeSignature, 6);
|
||||
|
||||
}
|
||||
|
||||
// If we don't find any offset, there may be an issue or bug.
|
||||
if (offset == 0) {
|
||||
|
||||
std::printf("[X] Invalid lea reference or uknown lea detected.....\n");
|
||||
std::printf("[X] Invalid lea/mov reference or uknown lea/mov detected.....\n");
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -2694,12 +2827,181 @@ void RyujinObfuscationCore::applyRelocationFixupsToInstructions(uintptr_t imageB
|
||||
const uintptr_t new_memory_immediate = target_original - new_obfuscated_rip;
|
||||
|
||||
// Fixing the immediate value for the "LEA" or "MOV" instruction with the corrected relative immediate value
|
||||
std::memcpy(&*(data + offset + 3), &new_memory_immediate, sizeof(uint32_t)); // 3 bytes for the size of the LEA or MOV opcode
|
||||
if (*reinterpret_cast<unsigned char*>(instruction.addressofinstruction) != 0x8B)
|
||||
std::memcpy(&*(data + offset + 3), &new_memory_immediate, sizeof(uint32_t)); // 3 bytes for the size of the LEA or MOV opcode
|
||||
else
|
||||
std::memcpy(&*(data + offset + 2), &new_memory_immediate, sizeof(uint32_t)); // 3 bytes for the size of the LEA or MOV opcode
|
||||
|
||||
std::printf("[OK] Fixing -> %s - from %X to %X\n", instruction.instruction.text, mem->disp.value, new_memory_immediate);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else if ((instruction.instruction.info.mnemonic == ZYDIS_MNEMONIC_MOV || instruction.instruction.info.mnemonic == ZYDIS_MNEMONIC_LEA) && instruction.instruction.operands->type == ZYDIS_OPERAND_TYPE_MEMORY && instruction.instruction.operands->mem.type == ZYDIS_MEMOP_TYPE_MEM) {
|
||||
|
||||
if (instruction.instruction.info.length > 5) {
|
||||
|
||||
// References for data and vector size with obfuscated opcodes
|
||||
auto size = new_opcodes.size();
|
||||
auto data = new_opcodes.data();
|
||||
|
||||
const ZydisDecodedOperandMem* mem = &instruction.instruction.operands[0].mem;
|
||||
|
||||
//Avoid memory op for stack
|
||||
if (instruction.instruction.operands->mem.base == ZYDIS_REGISTER_RSP) {
|
||||
|
||||
//std::printf("Invalid relocation fix candidate for -> %s\n", instruction.instruction.text);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Getting the memory immediate offset value to build the signature
|
||||
const uint32_t memmory_immediate_offset = mem->disp.value;
|
||||
|
||||
ZyanI64 offset = 0, fix_byte = 0;
|
||||
unsigned char ucOpcodeSignature[11]{ 0 };
|
||||
|
||||
if (instruction.instruction.info.length == 6) {
|
||||
|
||||
std::memcpy(&ucOpcodeSignature, reinterpret_cast<void*>(instruction.addressofinstruction), 6);
|
||||
|
||||
offset = findOpcodeOffset(data, size, &ucOpcodeSignature, 6);
|
||||
|
||||
fix_byte = 2;
|
||||
|
||||
}
|
||||
else if (instruction.instruction.info.length == 7) {
|
||||
|
||||
std::memcpy(&ucOpcodeSignature, reinterpret_cast<void*>(instruction.addressofinstruction), 7);
|
||||
|
||||
offset = findOpcodeOffset(data, size, &ucOpcodeSignature, 7);
|
||||
|
||||
fix_byte = 3;
|
||||
|
||||
}
|
||||
else if (instruction.instruction.info.length == 10) {
|
||||
|
||||
std::memcpy(&ucOpcodeSignature, reinterpret_cast<void*>(instruction.addressofinstruction), 10);
|
||||
|
||||
offset = findOpcodeOffset(data, size, &ucOpcodeSignature, 10);
|
||||
|
||||
fix_byte = 2;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
std::printf("ERROR Unexpected Instruction mov cs[], reg/imm -> %s - %d\n", instruction.instruction.text, instruction.instruction.info.length);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Retrieving the instruction address in the original section
|
||||
const uintptr_t original_address = instruction.addressofinstruction;
|
||||
|
||||
// Calculating new address in the obfuscated section
|
||||
const uintptr_t obfuscated_va_address = ((imageBase + virtualAddress + offset));
|
||||
|
||||
/*
|
||||
Calculating new displacement for the immediate value
|
||||
*/
|
||||
// Calculating the address of the instruction following the original instruction
|
||||
const uintptr_t original_rip = original_address + instruction.instruction.info.length;
|
||||
|
||||
// Calculating the original target address of the original instruction
|
||||
const uintptr_t target_original = original_rip + memmory_immediate_offset;
|
||||
|
||||
// Calculating the address of the instruction following the obfuscated instruction
|
||||
const uintptr_t new_obfuscated_rip = obfuscated_va_address + instruction.instruction.info.length;
|
||||
|
||||
// New memory immediate value for the instruction
|
||||
const uintptr_t new_memory_immediate = target_original - new_obfuscated_rip;
|
||||
|
||||
// Fixing the immediate value for the "LEA" or "MOV" instruction with the corrected relative immediate value
|
||||
std::memcpy(&*(data + offset + fix_byte), &new_memory_immediate, sizeof(uint32_t));
|
||||
|
||||
std::printf("[OK] Fixing -> %s - from %X to %X\n", instruction.instruction.text, mem->disp.value, new_memory_immediate);
|
||||
}
|
||||
|
||||
}
|
||||
else if ((instruction.instruction.info.mnemonic == ZYDIS_MNEMONIC_ADD || instruction.instruction.info.mnemonic == ZYDIS_MNEMONIC_SUB || instruction.instruction.info.mnemonic == ZYDIS_MNEMONIC_XOR) && (instruction.instruction.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY || instruction.instruction.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY)) {
|
||||
|
||||
|
||||
// References for data and vector size with obfuscated opcodes
|
||||
auto size = new_opcodes.size();
|
||||
auto data = new_opcodes.data();
|
||||
|
||||
//Avoid memory op for stack
|
||||
if (instruction.instruction.operands->mem.base == ZYDIS_REGISTER_RSP) {
|
||||
|
||||
std::printf("Invalid relocation fix candidate for -> %s\n", instruction.instruction.text);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
ZydisDecodedOperandMem* mem;
|
||||
if (instruction.instruction.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
mem = &instruction.instruction.operands[0].mem;
|
||||
else
|
||||
mem = &instruction.instruction.operands[1].mem;
|
||||
|
||||
// Getting the memory immediate offset value to build the signature
|
||||
const uint32_t memmory_immediate_offset = mem->disp.value;
|
||||
|
||||
ZyanI64 offset = 0, fix_byte = 0;
|
||||
unsigned char ucOpcodeSignature[11]{ 0 };
|
||||
|
||||
|
||||
if (instruction.instruction.info.length == 6) {
|
||||
|
||||
std::memcpy(&ucOpcodeSignature, reinterpret_cast<void*>(instruction.addressofinstruction), 6);
|
||||
|
||||
offset = findOpcodeOffset(data, size, &ucOpcodeSignature, 6);
|
||||
|
||||
fix_byte = 2;
|
||||
|
||||
}
|
||||
else if (instruction.instruction.info.length == 7) {
|
||||
|
||||
std::memcpy(&ucOpcodeSignature, reinterpret_cast<void*>(instruction.addressofinstruction), 7);
|
||||
|
||||
offset = findOpcodeOffset(data, size, &ucOpcodeSignature, 7);
|
||||
|
||||
fix_byte = 3;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
std::printf("ERROR Unexpected Instruction bitwise/math [], reg or bitwise/math reg, [] -> %s - %d\n", instruction.instruction.text, instruction.instruction.info.length);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Retrieving the instruction address in the original section
|
||||
const uintptr_t original_address = instruction.addressofinstruction;
|
||||
|
||||
// Calculating new address in the obfuscated section
|
||||
const uintptr_t obfuscated_va_address = ((imageBase + virtualAddress + offset));
|
||||
|
||||
/*
|
||||
Calculating new displacement for the immediate value
|
||||
*/
|
||||
// Calculating the address of the instruction following the original instruction
|
||||
const uintptr_t original_rip = original_address + instruction.instruction.info.length;
|
||||
|
||||
// Calculating the original target address of the original instruction
|
||||
const uintptr_t target_original = original_rip + memmory_immediate_offset;
|
||||
|
||||
// Calculating the address of the instruction following the obfuscated instruction
|
||||
const uintptr_t new_obfuscated_rip = obfuscated_va_address + instruction.instruction.info.length;
|
||||
|
||||
// New memory immediate value for the instruction
|
||||
const uintptr_t new_memory_immediate = target_original - new_obfuscated_rip;
|
||||
|
||||
// Fixing the immediate value for the "LEA" or "MOV" instruction with the corrected relative immediate value
|
||||
std::memcpy(&*(data + offset + fix_byte), &new_memory_immediate, sizeof(uint32_t));
|
||||
|
||||
std::printf("[OK] Fixing Math/Bitwise Operators -> %s | %d\n", instruction.instruction.text, instruction.instruction.info.length);
|
||||
|
||||
}
|
||||
else if (instruction.instruction.info.meta.category == ZYDIS_CATEGORY_COND_BR || instruction.instruction.info.meta.category == ZYDIS_CATEGORY_UNCOND_BR) {
|
||||
|
||||
@@ -2743,6 +3045,12 @@ void RyujinObfuscationCore::applyRelocationFixupsToInstructions(uintptr_t imageB
|
||||
*/
|
||||
auto obfuscated_target_address = basic_block_obfuscated.instructions.at(0).addressofinstruction;
|
||||
|
||||
/*
|
||||
Preventing problems.
|
||||
When IAT is obfuscated. theres no JUMP Address(it's always "0")! because it is solved during runtime. so the reloc is fixed, let's advance to the next blog!
|
||||
*/
|
||||
if (obfuscated_jmp_address == 0 && m_config.m_isIatObfuscation) continue;
|
||||
|
||||
/*
|
||||
Let's fix our new branch. Previously it was a "near" jump, but now it will be "far" depending on the jump length.
|
||||
This procedure will perform the calculation and generate a far or near branch depending on the need
|
||||
@@ -2815,9 +3123,18 @@ void RyujinObfuscationCore::removeOldOpcodeRedirect(uintptr_t newMappedPE, std::
|
||||
We will use findOpcodeOffset to find the exact offset of the procedure's start
|
||||
in the unmapped region with the SEC_IMAGE flag.
|
||||
*/
|
||||
unsigned char ucSigature[10]{ 0 };
|
||||
std::memcpy(ucSigature, reinterpret_cast<void*>(m_proc.address), 10);
|
||||
auto offsetz = findOpcodeOffset(reinterpret_cast<unsigned char*>(newMappedPE), szMapped, &ucSigature, 10);
|
||||
unsigned char* ucSigature = new unsigned char[m_proc.size] { 0 };
|
||||
std::memcpy(ucSigature, reinterpret_cast<void*>(m_proc.address), m_proc.size);
|
||||
auto offsetz = findOpcodeOffset(reinterpret_cast<unsigned char*>(newMappedPE), szMapped, ucSigature, m_proc.size);
|
||||
|
||||
delete[] ucSigature;
|
||||
|
||||
/*
|
||||
* Future assert
|
||||
if (!offsetz) {
|
||||
std::printf("[X] Fatal Error on removeOldOpcodeRedirect -> %s\n", m_proc.name);
|
||||
exit(-1);
|
||||
}*/
|
||||
|
||||
// Based on the obfuscation configuration, some users can decide to not remove the original code from the original procedure after obfuscation.
|
||||
if (!isIgnoreOriginalCodeRemove) std::memset(reinterpret_cast<void*>(newMappedPE + offsetz), 0x90, m_proc.size); // Removing all the opcodes from the original procedure and replacing them with NOP instructions.
|
||||
|
||||
@@ -17,7 +17,7 @@ class RyujinObfuscationCore {
|
||||
|
||||
private:
|
||||
const int MAX_PADDING_SPACE_INSTR = 14;
|
||||
const int MAX_JUNK_GENERATION_ITERATION = 5;
|
||||
const int MAX_JUNK_GENERATION_ITERATION = 8;
|
||||
std::vector<ZydisRegister> m_unusedRegisters;
|
||||
std::vector<RyujinBasicBlock> m_obfuscated_bb;
|
||||
uintptr_t m_ProcImageBase;
|
||||
|
||||
@@ -35,6 +35,7 @@ public:
|
||||
bool m_isTrollRerversers; // The user wants to trick and use a special feature to troll reversers when their debugs be detected making they loose all the progress
|
||||
bool m_isAntiDump; // Enable Anti Dump technic for Ryujin protected binary
|
||||
bool m_isMemoryProtection; // Memory CRC32 protection
|
||||
bool m_isHVPass; // Run some features of ryujin using Microsoft Hypervisor Framework API
|
||||
RyujinObfuscatorProcs m_strProceduresToObfuscate; // Names of the procedures to obfuscate
|
||||
RyujinCallbacks m_callbacks; // Ryujin Custom Pass Callbacks
|
||||
|
||||
|
||||
4073
diagrams/ryujin_core.excalidraw
Normal file
4073
diagrams/ryujin_core.excalidraw
Normal file
File diff suppressed because one or more lines are too long
709
diagrams/ryujin_minivm.excalidraw
Normal file
709
diagrams/ryujin_minivm.excalidraw
Normal file
@@ -0,0 +1,709 @@
|
||||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "https://excalidraw.com",
|
||||
"elements": [
|
||||
{
|
||||
"id": "M8c9eQZB7X5MZItasDS9w",
|
||||
"type": "rectangle",
|
||||
"x": 391.20001220703125,
|
||||
"y": 192.60000610351562,
|
||||
"width": 344.79998779296875,
|
||||
"height": 307.20001220703125,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "a0",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1615675767,
|
||||
"version": 129,
|
||||
"versionNonce": 2118539607,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"id": "c1iXEu4S5qWnIgYbjx1Zc",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1749686313933,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "46FHFpNht2wlAuCrvcVyc",
|
||||
"type": "text",
|
||||
"x": 516,
|
||||
"y": 154.1999969482422,
|
||||
"width": 58.23994445800781,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "a1",
|
||||
"roundness": null,
|
||||
"seed": 554549911,
|
||||
"version": 55,
|
||||
"versionNonce": 171168151,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1749685574176,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "Ryujin",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "Ryujin",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "xdJ2irJYkaNC9r3QEIouH",
|
||||
"type": "rectangle",
|
||||
"x": 833.6000366210938,
|
||||
"y": 205.40000915527344,
|
||||
"width": 144.79998779296875,
|
||||
"height": 121.59999084472656,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "a2",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 679450583,
|
||||
"version": 45,
|
||||
"versionNonce": 916855385,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"id": "GSUC-T1BCvyWszlmgyl-H",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "KVVsXm6d78Iek_N-4mTZ5",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1749686124093,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "u0hyTPfKwpUasROfCYwNp",
|
||||
"type": "text",
|
||||
"x": 856,
|
||||
"y": 235,
|
||||
"width": 114.89994812011719,
|
||||
"height": 75,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "a3",
|
||||
"roundness": null,
|
||||
"seed": 994638937,
|
||||
"version": 37,
|
||||
"versionNonce": 1352983513,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1749685595466,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "mov rax, 10\nadd rbx, 20\nsub rcx, 30",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "mov rax, 10\nadd rbx, 20\nsub rcx, 30",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "GSUC-T1BCvyWszlmgyl-H",
|
||||
"type": "arrow",
|
||||
"x": 831.2000122070312,
|
||||
"y": 271,
|
||||
"width": 212.79998779296875,
|
||||
"height": 3.20001220703125,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "a4",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 568230297,
|
||||
"version": 79,
|
||||
"versionNonce": 1291788375,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1749685606290,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-212.79998779296875,
|
||||
3.20001220703125
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "xdJ2irJYkaNC9r3QEIouH",
|
||||
"focus": -0.05938365959726409,
|
||||
"gap": 2.4000244140625
|
||||
},
|
||||
"endBinding": null,
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "kJtdz2klrATJ98T_MfkEO",
|
||||
"type": "rectangle",
|
||||
"x": 480.8000183105469,
|
||||
"y": 244.60000610351562,
|
||||
"width": 118.39999389648438,
|
||||
"height": 68,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "a5",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 832654263,
|
||||
"version": 38,
|
||||
"versionNonce": 842147095,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1749685611598,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "L_pSiLFD-D1qnLQGHAGoK",
|
||||
"type": "text",
|
||||
"x": 498.3999938964844,
|
||||
"y": 256.6000061035156,
|
||||
"width": 88.41993713378906,
|
||||
"height": 50,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "a6",
|
||||
"roundness": null,
|
||||
"seed": 1291545143,
|
||||
"version": 17,
|
||||
"versionNonce": 54828087,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1749685618526,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "custom\nbytecode",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "custom\nbytecode",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "KVVsXm6d78Iek_N-4mTZ5",
|
||||
"type": "arrow",
|
||||
"x": 578.4000244140625,
|
||||
"y": 359,
|
||||
"width": 198.4000244140625,
|
||||
"height": 10.399993896484375,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "a7",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 479607415,
|
||||
"version": 100,
|
||||
"versionNonce": 1093613177,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1749686207162,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
198.4000244140625,
|
||||
10.399993896484375
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": null,
|
||||
"endBinding": {
|
||||
"elementId": "NFjixAoh2CztYuP1DNIN-",
|
||||
"focus": -0.4045620317282552,
|
||||
"gap": 10.39996337890625
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "NFjixAoh2CztYuP1DNIN-",
|
||||
"type": "text",
|
||||
"x": 787.2000122070312,
|
||||
"y": 363.8000183105469,
|
||||
"width": 731.2396240234375,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "a8",
|
||||
"roundness": null,
|
||||
"seed": 1290016793,
|
||||
"version": 81,
|
||||
"versionNonce": 318460471,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"id": "iFf2168HoefeSA26Qvyxp",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "KVVsXm6d78Iek_N-4mTZ5",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1749686206810,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "Insert a jump into the original code to vmentry(for execute the bytecode)",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "Insert a jump into the original code to vmentry(for execute the bytecode)",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "j5zq_Cm9IYKmHffzVgFTn",
|
||||
"type": "rectangle",
|
||||
"x": 1548.4000244140625,
|
||||
"y": 304.6000061035156,
|
||||
"width": 208,
|
||||
"height": 180.00006103515625,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "a9",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1910262775,
|
||||
"version": 76,
|
||||
"versionNonce": 1150487223,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1749686159293,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "Bgo_NssAKTn1SdIHyYsMn",
|
||||
"type": "text",
|
||||
"x": 1576.4000244140625,
|
||||
"y": 319,
|
||||
"width": 205.4998779296875,
|
||||
"height": 150,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "aA",
|
||||
"roundness": null,
|
||||
"seed": 792391961,
|
||||
"version": 88,
|
||||
"versionNonce": 1848161657,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"id": "iFf2168HoefeSA26Qvyxp",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1749686197118,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "nop\nnop\npush rcx\nmov rcx, ptrbytecode\ncall vmentry\nmov rax...",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "nop\nnop\npush rcx\nmov rcx, ptrbytecode\ncall vmentry\nmov rax...",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "iFf2168HoefeSA26Qvyxp",
|
||||
"type": "arrow",
|
||||
"x": 1469.5999755859375,
|
||||
"y": 383.8000183105469,
|
||||
"width": 78.4000244140625,
|
||||
"height": 21.5999755859375,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "aB",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 1319005721,
|
||||
"version": 21,
|
||||
"versionNonce": 1768435865,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1749686197118,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
78.4000244140625,
|
||||
21.5999755859375
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "NFjixAoh2CztYuP1DNIN-",
|
||||
"focus": -0.7045371306368834,
|
||||
"gap": 5
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "Bgo_NssAKTn1SdIHyYsMn",
|
||||
"focus": -0.4601077518323214,
|
||||
"gap": 28.4000244140625
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "Az2n4_JQ_Rep62w0qbnpI",
|
||||
"type": "arrow",
|
||||
"x": 641.2000122070312,
|
||||
"y": 364.20001220703125,
|
||||
"width": 63.20001220703125,
|
||||
"height": 49.600006103515625,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "aC",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 313306169,
|
||||
"version": 38,
|
||||
"versionNonce": 499366105,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1749686269123,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-63.20001220703125,
|
||||
49.600006103515625
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": null,
|
||||
"endBinding": null,
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "O5yT6LnxD7xhW31GADKYB",
|
||||
"type": "text",
|
||||
"x": 468.3999938964844,
|
||||
"y": 432.20001220703125,
|
||||
"width": 820.1596069335938,
|
||||
"height": 50,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "aD",
|
||||
"roundness": null,
|
||||
"seed": 137944663,
|
||||
"version": 136,
|
||||
"versionNonce": 1340294711,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1749686305048,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "ryujin will insert bytecode in some section\nthe vm will interpret it and return back with the full context to not broke the code",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "ryujin will insert bytecode in some section\nthe vm will interpret it and return back with the full context to not broke the code",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "c1iXEu4S5qWnIgYbjx1Zc",
|
||||
"type": "arrow",
|
||||
"x": 434.3999938964844,
|
||||
"y": 503.20001220703125,
|
||||
"width": 170.39999389648438,
|
||||
"height": 156.79998779296875,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "aE",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 1561486455,
|
||||
"version": 28,
|
||||
"versionNonce": 1291089975,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1749686313933,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
170.39999389648438,
|
||||
156.79998779296875
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "M8c9eQZB7X5MZItasDS9w",
|
||||
"focus": 0.8835765524851282,
|
||||
"gap": 3.399993896484375
|
||||
},
|
||||
"endBinding": null,
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "WLU2ZgAEJXhP7nLOkpjLn",
|
||||
"type": "text",
|
||||
"x": 663.2000122070312,
|
||||
"y": 647.2000122070312,
|
||||
"width": 690.9995727539062,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "aF",
|
||||
"roundness": null,
|
||||
"seed": 870526871,
|
||||
"version": 98,
|
||||
"versionNonce": 999258681,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1749686340544,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "The vm will only allow some simple menemonic for multiplication(for now)",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "The vm will only allow some simple menemonic for multiplication(for now)",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "tLeEn07Up0otFbkxmXxyS",
|
||||
"type": "text",
|
||||
"x": 359.60003662109375,
|
||||
"y": 86.39999389648438,
|
||||
"width": 1619.8392333984375,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "aG",
|
||||
"roundness": null,
|
||||
"seed": 1720073049,
|
||||
"version": 213,
|
||||
"versionNonce": 1953987225,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1749687328143,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "to not use too much space we already have padding with nop -> compile the instructions to vm bytecode with a maximum of 8 bytes and interpret eah one individually",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "to not use too much space we already have padding with nop -> compile the instructions to vm bytecode with a maximum of 8 bytes and interpret eah one individually",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"gridSize": 20,
|
||||
"gridStep": 5,
|
||||
"gridModeEnabled": false,
|
||||
"viewBackgroundColor": "#ffffff",
|
||||
"lockedMultiSelections": {}
|
||||
},
|
||||
"files": {}
|
||||
}
|
||||
1435
diagrams/ryujin_overview.excalidraw
Normal file
1435
diagrams/ryujin_overview.excalidraw
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user