feat: Break Decompilers and Disassemblers feature

- Ryujin can now break decompilers and disassemblers using a simple technique. This feature was inspired by a talk from BinjaDev at Off by One Conf. It will definitely be improved in the near future with more techniques.
This commit is contained in:
keowu
2025-07-16 21:09:22 -03:00
parent 508a204d21
commit dd22fc4aa9
3 changed files with 36 additions and 1 deletions

View File

@@ -18,7 +18,7 @@
- Anti-Debug User + Kernel
- Troll Reversers(Exclusive)
- Anti-Dump
- Anti-Disassembly(Planned - **TODO**)
- Anti-Disassembly + Anti-Decompiler
- Custom Passes(Planned - **TODO**)
---

View File

@@ -183,6 +183,9 @@ void RyujinObfuscationCore::obfuscateIat() {
code.init(runtime.environment());
asmjit::x86::Assembler a(&code);
// Breaking Decompilers
insertBreakDecompilers(a);
// Using `rdgsbase rax` to store the base address of the GS segment in RAX -> rdgsbase rax
a.emit(asmjit::x86::Inst::kIdRdgsbase, asmjit::x86::rax);
@@ -216,6 +219,9 @@ void RyujinObfuscationCore::obfuscateIat() {
// call rax -> Calling the IAT
a.call(asmjit::x86::rax);
// Breaking Decompilers
insertBreakDecompilers(a);
// Obtaining the new section buffer
auto& opcodeBuffer = code.sectionById(0)->buffer();
// Obtaining the pointer to the buffer of raw opcode data generated
@@ -780,6 +786,9 @@ void RyujinObfuscationCore::insertVirtualization() {
code.init(runtime.environment());
asmjit::x86::Assembler a(&code);
// Breaking Decompilers
insertBreakDecompilers(a);
// Saving the current value of RCX
a.push(asmjit::x86::rcx);
// Saving the current value of RDX
@@ -815,6 +824,9 @@ void RyujinObfuscationCore::insertVirtualization() {
// Restoring the original value of RCX
a.pop(asmjit::x86::rcx);
// Breaking Decompilers
insertBreakDecompilers(a);
// Retrieving from ASMJIT<49>s JIT the resulting opcodes generated by our algorithm
auto& opcodeBuffer = code.sectionById(0)->buffer();
const auto pOpcodeBuffer = opcodeBuffer.data();
@@ -1573,6 +1585,9 @@ void RyujinObfuscationCore::insertAntiDebug() {
a.pop(asmjit::x86::rcx);
a.pop(asmjit::x86::rax);
// Breaking Decompilers
insertBreakDecompilers(a);
// pop RFLAGS
a.popfq();
@@ -1900,6 +1915,9 @@ void RyujinObfuscationCore::insertAntiDump() {
a.pop(asmjit::x86::rcx);
a.pop(asmjit::x86::rax);
// Breaking Decompilers
insertBreakDecompilers(a);
// pop RFLAGS
a.popfq();
@@ -1931,6 +1949,22 @@ void RyujinObfuscationCore::updateBasicBlocksContext() {
}
void RyujinObfuscationCore::insertBreakDecompilers(asmjit::x86::Assembler& a) {
//Breaking Decompilers(https://youtu.be/6UlxrDYng88?t=1287)
a.push(asmjit::x86::rbx);
std::vector<unsigned char> breakDecompilerOneByteTrick{
0xEB, 0xFF, 0xC3
};
a.embed(breakDecompilerOneByteTrick.data(), breakDecompilerOneByteTrick.size());
a.pop(asmjit::x86::rbx);
}
BOOL RyujinObfuscationCore::Run(bool& RyujinRunOncePass) {
//Add padding spaces

View File

@@ -31,6 +31,7 @@ private:
void insertVirtualization();
void insertAntiDebug();
void insertAntiDump();
void insertBreakDecompilers(asmjit::x86::Assembler& a);
std::vector<uint8_t> fix_branch_near_far_short(uint8_t original_opcode, uint64_t jmp_address, uint64_t target_address);
uint32_t findOpcodeOffset(const uint8_t* data, size_t dataSize, const void* opcode, size_t opcodeSize);