diff --git a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc index fff5a31..c14e98f 100644 --- a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc +++ b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc @@ -162,19 +162,19 @@ bool Ryujin::run(const RyujinObfuscatorConfig& config) { auto tempValued = obc.getProcessedProc().getUpdateOpcodes(); - //Fix relocations + // Fix relocations obc.applyRelocationFixupsToInstructions(reinterpret_cast(imgDos), peSections.getRyujinSectionVA() + offsetVA, tempValued); - //Removendo e adicionando um salto no procedimento original e removendo opcodes originais para um salto ao novo código ofuscado + // Removing and adding a jump in the original procedure and removing original opcodes for a jump to the new obfuscated code obc.removeOldOpcodeRedirect(peSections.mappedPeDiskBaseAddress(), peSections.getRyujinMappedPeSize(), reinterpret_cast(imgDos) + peSections.getRyujinSectionVA() + offsetVA, config.m_isIgnoreOriginalCodeRemove); - //Destructing class + // Destructing class obc.~RyujinObfuscationCore(); - //Inserindo procedures na lista de opcodes corrigidos + // Inserting procedures into the list of corrected opcodes opcodesWithRelocsFixed.insert(opcodesWithRelocsFixed.end(), tempValued.begin(), tempValued.end()); - // Incrementando o offset com o tamanho dos opcodes em questão + // Incrementing the offset with the size of the opcodes in question offsetVA += tempValued.size(); } diff --git a/RyujinConsole/RyujinConsole/Ryujin/RyujinCore/RyujinObfuscationCore.cc b/RyujinConsole/RyujinConsole/Ryujin/RyujinCore/RyujinObfuscationCore.cc index 67c7bb9..6ca810a 100644 --- a/RyujinConsole/RyujinConsole/Ryujin/RyujinCore/RyujinObfuscationCore.cc +++ b/RyujinConsole/RyujinConsole/Ryujin/RyujinCore/RyujinObfuscationCore.cc @@ -74,38 +74,48 @@ BOOL RyujinObfuscationCore::extractUnusedRegisters() { void RyujinObfuscationCore::addPaddingSpaces() { + // Initializing AsmJit asmjit::JitRuntime runtime; for (auto& block : m_proc.basic_blocks) { + // Vector to store the opcodes related to the current context basic block std::vector> new_instructions; for (auto& opcode : block.opcodes) { + // Saving all original opcodes of the basic block std::vector new_opcodes; for (auto individual_opcode : opcode) new_opcodes.push_back(individual_opcode); + // Adding them to the main control vector new_instructions.push_back(new_opcodes); //Storing Nop-Spacing std::vector gen_opcodes; + // Initializing AsmJit asmjit::CodeHolder code; code.init(runtime.environment()); asmjit::x86::Assembler a(&code); + // Inserting nop-spacing technique for (auto i = 0; i < MAX_PADDING_SPACE_INSTR; i++) a.nop(); + // Flush flatten code.flatten(); + // Getting the result from JIT auto section = code.sectionById(0); const auto buf = section->buffer().data(); auto size = section->buffer().size(); + // Storing each new generated opcode for (auto i = 0; i < size; ++i) gen_opcodes.push_back(buf[i]); + // Storing in the main vector of the block new_instructions.push_back(gen_opcodes); } @@ -266,7 +276,322 @@ void RyujinObfuscationCore::obfuscateIat() { } void RyujinObfuscationCore::insertJunkCode() { - // TODO + + // Initializing AsmJit + asmjit::JitRuntime runtime; + + for (auto& block : m_proc.basic_blocks) { + + // New vector to load the updated opcodes for the given block + std::vector> new_instructions; + + for (auto& opcode : block.opcodes) { + + // Saving all original opcodes of the basic block + std::vector new_opcodes; + + // Storing the original opcodes of the procedure + for (auto individual_opcode : opcode) new_opcodes.push_back(individual_opcode); + + // Inserting original opcodes into the control vector + new_instructions.push_back(new_opcodes); + + // Generating junk code + std::vector junk_opcodes; + + // Initializing AsmJit + asmjit::CodeHolder code; + code.init(runtime.environment()); + asmjit::x86::Assembler a(&code); + + // Let's iterate over all registers not used by the procedure to generate junk code + for (auto reg : m_unusedRegisters) { + + // Nop-Spacing technique for alignment + for (auto i = 0; i < MAX_PADDING_SPACE_INSTR; i++) a.nop(); + + // Junk code insertion technique + for (auto i = 0; i < MAX_JUNK_GENERATION_ITERATION; i++) { + + // Generating random value for obfuscation + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dist(0, 0xFFFF); + auto random_value = dist(gen); + + // Each free register has its own junk code (todo: this should be random and generated with some algorithm) + switch (reg) { + + case ZYDIS_REGISTER_RAX: { + + // Junk Code Entry + a.push(asmjit::x86::rax); + a.pushf(); + a.mov(asmjit::x86::rax, 0); + + a.xor_(asmjit::x86::rax, random_value); + a.inc(asmjit::x86::rax); + a.dec(asmjit::x86::rax); + a.add(asmjit::x86::rax, random_value); + a.sub(asmjit::x86::rax, random_value); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::rax); + + break; + + } + case ZYDIS_REGISTER_RBX: { + + // Junk Code Entry + a.push(asmjit::x86::rbx); + a.pushf(); + a.mov(asmjit::x86::rbx, 0); + + a.rol(asmjit::x86::rbx, random_value); + a.ror(asmjit::x86::rbx, random_value); + a.xchg(asmjit::x86::rbx, asmjit::x86::rbx); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::rbx); + break; + + } + case ZYDIS_REGISTER_RCX: { + + // Junk Code Entry + a.push(asmjit::x86::rcx); + a.pushf(); + a.mov(asmjit::x86::rcx, 0); + + a.mov(asmjit::x86::rcx, random_value); + a.add(asmjit::x86::rcx, random_value); + a.mov(asmjit::x86::rcx, random_value); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::rcx); + break; + + } + case ZYDIS_REGISTER_RDX: { + + // Junk Code Entry + a.push(asmjit::x86::rdx); + a.pushf(); + a.mov(asmjit::x86::rdx, 0); + + a.add(asmjit::x86::rdx, random_value); + a.shr(asmjit::x86::rdx, random_value); + a.shl(asmjit::x86::rdx, random_value); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::rdx); + break; + + } + case ZYDIS_REGISTER_RSI: { + + // Junk Code Entry + a.push(asmjit::x86::rsi); + a.pushf(); + a.mov(asmjit::x86::rsi, 0); + + a.mov(asmjit::x86::rsi, random_value); + a.not_(asmjit::x86::rsi); + a.not_(asmjit::x86::rsi); + a.add(asmjit::x86::rsi, random_value); + a.sub(asmjit::x86::rsi, random_value); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::rsi); + break; + + } + case ZYDIS_REGISTER_RDI: { + + // Junk Code Entry + a.push(asmjit::x86::rdi); + a.pushf(); + a.mov(asmjit::x86::rdi, 0); + + a.mov(asmjit::x86::rdi, random_value); + a.xor_(asmjit::x86::rdi, asmjit::x86::rdi); + a.add(asmjit::x86::rdi, random_value); + a.sub(asmjit::x86::rdi, random_value); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::rdi); + break; + + } + case ZYDIS_REGISTER_R8: { + + // Junk Code Entry + a.push(asmjit::x86::r8); + a.pushf(); + a.mov(asmjit::x86::r8, 0); + + a.xor_(asmjit::x86::r8, asmjit::x86::r8); + a.mov(asmjit::x86::r8, random_value); + a.or_(asmjit::x86::r8, random_value); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::r8); + break; + + } + case ZYDIS_REGISTER_R9: { + + // Junk Code Entry + a.push(asmjit::x86::r9); + a.pushf(); + a.mov(asmjit::x86::r9, 0); + + a.shr(asmjit::x86::r9, random_value); + a.shl(asmjit::x86::r9, random_value); + a.add(asmjit::x86::r9, random_value); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::r9); + break; + + } + case ZYDIS_REGISTER_R10: { + + // Junk Code Entry + a.push(asmjit::x86::r10); + a.pushf(); + a.mov(asmjit::x86::r10, 0); + + a.mov(asmjit::x86::r10, random_value); + a.imul(asmjit::x86::r10, random_value); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::r10); + break; + + } + case ZYDIS_REGISTER_R11: { + + // Junk Code Entry + a.push(asmjit::x86::r11); + a.pushf(); + a.mov(asmjit::x86::r11, 0); + + a.inc(asmjit::x86::r11); + a.mov(asmjit::x86::r11, random_value); + a.dec(asmjit::x86::r11); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::r11); + break; + + } + case ZYDIS_REGISTER_R12: { + + // Junk Code Entry + a.push(asmjit::x86::r12); + a.pushf(); + a.mov(asmjit::x86::r12, 0); + + a.add(asmjit::x86::r12, random_value); + a.sub(asmjit::x86::r12, random_value); + a.mov(asmjit::x86::r12, random_value); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::r12); + break; + + } + case ZYDIS_REGISTER_R13: { + + // Junk Code Entry + a.push(asmjit::x86::r13); + a.pushf(); + a.mov(asmjit::x86::r13, 0); + + a.mov(asmjit::x86::r13, random_value); + a.xor_(asmjit::x86::r13, random_value); + a.add(asmjit::x86::r13, random_value); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::r13); + break; + } + case ZYDIS_REGISTER_R14: { + + // Junk Code Entry + a.push(asmjit::x86::r14); + a.pushf(); + a.mov(asmjit::x86::r14, 0); + + a.xor_(asmjit::x86::r14, random_value); + a.xor_(asmjit::x86::r14, random_value); + a.add(asmjit::x86::r14, random_value); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::r14); + break; + + } + case ZYDIS_REGISTER_R15: { + + // Junk Code Entry + a.push(asmjit::x86::r15); + a.pushf(); + a.mov(asmjit::x86::r15, 0); + + a.add(asmjit::x86::r15, random_value); + a.add(asmjit::x86::r15, random_value); + a.sub(asmjit::x86::r15, random_value); + a.xor_(asmjit::x86::r15, random_value); + + // Junk Code Out + a.popf(); + a.pop(asmjit::x86::r15); + break; + + } + default: break; + } + + } + + } + + // AsmJit Flush flatten + code.flatten(); + + // Getting the result of opcodes generated via JIT to add to our junk opcodes in the current iteration context + auto section = code.sectionById(0); + const auto buf = section->buffer().data(); + auto size = section->buffer().size(); + for (auto i = 0; i < size; ++i) junk_opcodes.push_back(buf[i]); + + // Adding the newly processed opcodes to the global instruction vector + new_instructions.push_back(junk_opcodes); + + } + + // Overwriting opcodes with the new obfuscated ones + block.opcodes.clear(); + block.opcodes.assign(new_instructions.begin(), new_instructions.end()); + + } + } void RyujinObfuscationCore::updateBasicBlocksContext() { diff --git a/RyujinConsole/RyujinConsole/Ryujin/RyujinCore/RyujinObfuscationCore.hh b/RyujinConsole/RyujinConsole/Ryujin/RyujinCore/RyujinObfuscationCore.hh index 3550eb2..d1ec7d6 100644 --- a/RyujinConsole/RyujinConsole/Ryujin/RyujinCore/RyujinObfuscationCore.hh +++ b/RyujinConsole/RyujinConsole/Ryujin/RyujinCore/RyujinObfuscationCore.hh @@ -16,7 +16,8 @@ class RyujinObfuscationCore { private: - const int MAX_PADDING_SPACE_INSTR = 15; + const int MAX_PADDING_SPACE_INSTR = 10; + const int MAX_JUNK_GENERATION_ITERATION = 2; std::vector m_unusedRegisters; std::vector m_obfuscated_bb; uintptr_t m_ProcImageBase;