Jump to content
Tuts 4 You

Eclipse Runtime Obfuscator


Go to solution Solved by kao,

Recommended Posts

C5Hackr
Posted

Eclipse Runtime Obfuscator


Hey everyone,

I’m sharing an UnpackMe challenge that combines VMProtect packing with runtime function obfuscation using Eclipse Runtime Obfuscator. This should be an interesting challenge for those who enjoy working with dynamic obfuscation and anti-debugging techniques.

Protection Details:

  • VMProtect is used for basic packing, with import protection and anti-debug enabled.
  • Eclipse Runtime Obfuscator dynamically obfuscates function execution, making dumped analysis and debugging difficult.
  • Function code is relocated to a new memory region at runtime and accessed through vectored exception handling (VEH) instead of direct execution.
  • Eclipse Runtime Obfuscation Features in this UnpackMe:
    • Exception-Based Execution Handling – Execution is redirected via VEH, preventing direct tracing.
    • Junk Code Injection – Adds meaningless instructions to mislead disassembly and make static analysis harder.
    • Dynamic Function Relocation – Functions are moved at runtime, disrupting predictable memory access.
    • Control Flow Obfuscation – Execution flow is broken up and redirected via exception handling.
    • Anti-Debugging Protection – The binary throws access violations and illegal instructions to interfere with debuggers.

Goals:

  • Unpack the binary (remove VMProtect and restore the original imports).
  • Defeat runtime function relocation and deobfuscate the function logic by resorting the original function code.
  • Reconstruct a clean, runnable (optional) version of the executable with original control flow.
  • Explain how you unpacked and fixed the program, detailing the approach to defeating VEH-based execution and restoring the function code.
  • Bonus points if you can crack the password in the console application demo code.

Notes:

  • VMProtect is only used for packing, not virtualization.
  • The main challenge comes from Eclipse’s runtime function relocation and exception-based redirections.
  • Dumping the process isn’t enough, as function code is dynamically obfuscated in memory.
  • Would love to see a write-up on defeating the VEH-based execution and restoring the original function code!

More information can be found about the Eclipse Runtime Obfuscator project on GitHub.

Looking forward to seeing your approaches. Good luck and happy reversing!


 

  • Like 2
Posted

What's the point of applying VMProtect over your supposedly secure protection? 

I'd love to look at your obfuscator but I have zero interest in wasting my time on bypassing VMProtect anti-debug or import rebuilding - that's been done hundreds of times before and adds absolutely no value to the challenge at hand.

  • Like 1
Posted (edited)
49 minutes ago, kao said:

What's the point of applying VMProtect over your supposedly secure protection? 

I'd love to look at your obfuscator but I have zero interest in wasting my time on bypassing VMProtect anti-debug or import rebuilding - that's been done hundreds of times before and adds absolutely no value to the challenge at hand.

The reason for using VMProtect here isn’t to add another layer of security to the challenge itself—it’s because Eclipse's runtime obfuscation relies on the code being packed for the protection to be effective.

Without a packer, the original function code would still exist in the .text section before it gets relocated at runtime, making it trivial to extract before the obfuscation even kicks in. By applying VMProtect’s basic packing, the goal is to ensure that the original function never exists in its true form inside the executable from the start, forcing analysis to focus on runtime deobfuscation rather than simple static extraction.

I get that VMProtect’s anti-debug and import protection have been solved countless times, and I agree that’s not the interesting part of the challenge. The real focus here is on defeating Eclipse’s VEH-based execution redirection and function relocation, which is what I’d love to see people tackle.

Furthermore, I could have made my own custom anti-debugger, packer, and IAT obfuscation, but honestly, I was lazy and didn't have much time to do so, and just decided to use VMProtect instead. It served the purpose of keeping the function code from being analyzed statically, which is all I needed it for.

That said, I totally understand if dealing with VMProtect is a dealbreaker for you.

Edited by C5Hackr
added a sentence for explaining why vmprotect was used
  • Like 1
  • Confused 1
  • Solution
Posted
2 hours ago, C5Hackr said:

Without a packer, the original function code would still exist in the .text section before it gets relocated at runtime, making it trivial to extract before the obfuscation even kicks in.

I suggest you think about this long and hard. What could possibly go wrong? :)

 

I'll take the bonus points.. 

Spoiler

Password: HhegaSh8W24Y

And semi-decompiled password checking routine: :) 

    OBF_START();
    strcpy((char *)password_string, "wWZX^lW\ah\r\vf");
    printf("Enter password: ");
    sscanf("%49s", entered_password);
    password_len = -1LL;
    do
      ++password_len;
    while ( password_string[password_len] );
    counter = 0LL;
    if ( password_len )
    {
      if ( password_len < 0x40 )
        goto xor_short_password;
      // ...
      // Do optimized XOR for long strings
      // ...
      if ( counter < password_len )
      {
xor_short_password:
        do
        {
          dexored_pass[counter] = password_string[counter] ^ 0x3F;
          ++counter;
        }
        while ( counter < password_len );
      }
    }
    dexored_pass[password_len] = 0;
    flag = inlined_strcmp(entered_password, dexored_pass);
    v14 = 0;
    v15 = "Access Granted! You cracked it!\n";
    if ( flag )
    {
      v14 = v5;
      v15 = "Access Denied! Try again.\n";
    }
    v5 = v14;
    printf(v15);

 

 

 

  • Like 2
  • Thanks 2
Posted (edited)
18 minutes ago, kao said:

I suggest you think about this long and hard. What could possibly go wrong? :)

 

I'll take the bonus points.. 

  Hide contents

Password: HhegaSh8W24Y

And semi-decompiled password checking routine: :) 

    OBF_START();
    strcpy((char *)password_string, "wWZX^lW\ah\r\vf");
    printf("Enter password: ");
    sscanf("%49s", entered_password);
    password_len = -1LL;
    do
      ++password_len;
    while ( password_string[password_len] );
    counter = 0LL;
    if ( password_len )
    {
      if ( password_len < 0x40 )
        goto xor_short_password;
      // ...
      // Do optimized XOR for long strings
      // ...
      if ( counter < password_len )
      {
xor_short_password:
        do
        {
          dexored_pass[counter] = password_string[counter] ^ 0x3F;
          ++counter;
        }
        while ( counter < password_len );
      }
    }
    dexored_pass[password_len] = 0;
    flag = inlined_strcmp(entered_password, dexored_pass);
    v14 = 0;
    v15 = "Access Granted! You cracked it!\n";
    if ( flag )
    {
      v14 = v5;
      v15 = "Access Denied! Try again.\n";
    }
    v5 = v14;
    printf(v15);

 

 

 

Bravo! 🎉 Impressive work reversing through the layers and pulling out the password check routine so cleanly.

I’m curious—how did you approach it? Did you focus on bypassing VEH handling and dumping the relocated functions, or did you go straight for unpacking it statically rather than dumping it? Also, any pain points, or was it a straightforward crack?

Really appreciate you taking the time to check it out! Looking forward to your breakdown. 🔥

Edited by C5Hackr
grammar fix
  • Like 2
Posted

You actually solved it for me - see the quote in my previous post. :) 
The protection is pointless if the original code is present in it's original place even for a short period of time. I just needed to dump the process memory at the right time.

Could I make a tool to rebuild relocated functions? Sure, I'd need to find num_ObfuscatedFunctions and ObfuscatedFunctions and then do the reverse of RelocateFunction for each of them. But I'm lazy. :) 

  • Like 2
Posted
16 hours ago, kao said:

You actually solved it for me - see the quote in my previous post. :) 
The protection is pointless if the original code is present in it's original place even for a short period of time. I just needed to dump the process memory at the right time.

Could I make a tool to rebuild relocated functions? Sure, I'd need to find num_ObfuscatedFunctions and ObfuscatedFunctions and then do the reverse of RelocateFunction for each of them. But I'm lazy. :) 

Touché! 😆 While I would have loved to see a full function rebuilder in action, I did basically say/hint at by any means necessary, so fair play on taking the most efficient route.

This runtime obfuscation was really just meant to be a cool PoC for runtime-based protection, rather than an impenetrable shield. The idea was to make static analysis a pain and force dynamic reversing, but yeah—if the code exists in a readable state, even for a moment, it’s game over.

Still, I appreciate you taking a look at it. If I ever cook up something more annoying, I’ll be sure to let you know. 😈

  • Like 2

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...