Closed Smellon69 closed 5 months ago
This is something to be done in an obfuscation pass automatically, not in code manually. This would require a significant change in the project in how instructions are encoded to be able to achieve something like this.
The TODO comment is saying that instructions which use a memory operand can be expanded to recreate the same function but act.
For instance, mov rax, [rbx + rcx * 2]
can be "expanded" like this:
mov some_reg, rcx
imul some_reg, 2
add some_reg, rbx
mov some_reg, [some_reg]
mov rax, some_reg
This would give way for other obfuscation passes to do even more complex things to these instructions such as obfuscation the multiplication of imul some_reg, 2
through MBA or whichever way I decide to implement it.
In this specific example,
zydis_helper::enc(ZYDIS_MNEMONIC_LEA, ZREG(VTEMP), ZMEMBD(VSP, 8 * (vm_stack_regs + vm_overhead), 8))
Would achieve the same thing as this:
mov VTEMP, VSP
imul VTEMP, 8 * (vm_stack_regs + overhead)
mov VTEMP, [VTEMP]
This is not something that should be done by hand. It will make the assembly code more unreadable which is not something I want to be happening in the project. Everything should be as readable as possible and most of the obfuscation should be left to be automatically generated.
Me and another contributor are currently trying to work on this exact problem. I would personally not recommend this to be a first issue to try to tackle.
Unfortunately, there are not a lot of good first issues I could think of related to the project. Everything requires a deep understanding of the project and how it works which is not anyone's fault but mine. This is just the result of code complexity, missing documentation, etc on my end but I have no problem explaining things. I will let you know if I have any suggestions but feel free to play around with the project.
I recommend compiling the project on x64-debug so the randomization of registers is not really random. This will allow you to create new registers and see the changes reflect after protection if that's what you're interested in.
I've noticed something in the virtualizer that might need fixing. Let's say we're calling a function to authenticate a user, then checking the result with test eax, ecx
('m not entirely sure if this is correct assembly). After that, we use je
for a conditional jump if equal.
Almost the 1:1 assembly of what it looked like after virtualization by EagleVM:
call protected.random-name
test, eax, ecx
je something-i-dont-remember
The problem is, this sequence makes it easy for someone to figure out what we're doing.
Is there a way we could "obfuscate" the test
instruction? I'm not sure how to solve this issue, but when I try protecting the same code with VMProtect 2.X/3.X, it becomes completely incomprehensible to me. It seems to somehow heavily obfuscate this to the point where I can't "crack" it.
Also, where in the code are the register names created? I want to mess around with a few things but I can't seem to find where you actually set the register names in assembly.
This is not an error. There's a way to virtualize the test instruction, it's just not implemented. There are plenty of instructions I have not written handlers for. Writing a handler for instructions is trivial and plenty examples are available through the already existing handlers (look at CMP).
The goal of the project is not to create a commercial obfuscation product, it's for research purposes to demonstrate how code virtualization works. There is no obfuscation here other than the virtualization. It's not my priority to write handlers for each instruction that is missed by the virtualizer as there are far more interesting things to be doing. If you want to protect your code to be "completely incomprehensible" with VMPs obfuscation techniques, use VMP. If your goal is to find a substitute for VMP, this project is not for that. If you want to protect commercial software with this project, this project is not for you.
This is for research and not intended to be used on for a product.
TEST virtualization can be is a feature request, you can request it or implement it yourself. Please keep separate issues separate.
Also, where in the code are the register names created? I want to mess around with a few things but I can't seem to find where you actually set the register names in assembly.
I don't understand this question.
Also, where in the code are the register names created? I want to mess around with a few things but I can't seem to find where you actually set the register names in assembly.
I don't understand this question.
The custom handlers that are used by the virtualizer, the name appears to be randomly generated. Where can I find where the names are generated?
Handlers do not have randomly generated names... they are files in the project with appropriate class names.
Handlers do not have randomly generated names... they are files in the project with appropriate class names.
I'm very confused now, could you show me the code where one is located as an example?
https://github.com/notpidgey/EagleVM/blob/master/EagleVM.Core/source/virtual_machine/handlers/ia32_handlers/add.cpp There is a massive folder named "handlers". Please put in some effort into looking at the project to familiarize yourself.
Is your feature request related to a problem? Please describe. I tried to implement your second TODO inside of vm_enter.cpp: // TODO: for instruction obfuscation, for operands that use MEM, manually expand them out store it in a new register such as VEMEM and then just dereference that register !!!
Describe the solution you'd like Maybe some sort of help as to why my code isn't working
Describe alternatives you've considered Just fixing my code?
Additional context Here's my code from me attempting to complete it and horribly failing:
Why did I make this issue? Well because I wanted to actually try to help you rather then spam opening issues and not attempting to fix them myself. This was my first attempt at doing something that you said needed to be done in the code, and I'd like to see if you can guide me towards my problem and a possible solution. Feel free to add the VEMEM register to a new test project and see if you can help me with figuring out the error. I made the VEMEM register #8 and increased the registers count from 8-9.