Permutation Engine

Joined
Apr 4, 2009
Messages
898
Reaction score
157
Just an idea I had: for executable protection, rather than taking the approach of using virtualization, what about a route of obfuscation which won't result in a loss of performance?

For example, when speaking in terms of ASM, zeroing a register is almost always done using the XOR operation (XOR [register], [register]). There's many other ways that can be completed in a reasonable number of clock cycles:

Code:
SUB REGISTER, REGISTER

MOV REGISTER, 0

LEA REGISTER, [0]

PUSH 0
POP REGISTER

SHL REGISTER, 0x1F
SHL REGISTER, 0x1F

AND REGISTER, 0

IMUL REGISTER, 0

Or division/multiplication:

Code:
[IMUL X]
ROL [register], x/2

[IDIV X]
ROR [register], x/2
(For odd numbers, in the above example, you would have to make use of addition/subtraction).



My idea is to write a permutation engine which would change all instructions in an application, to make reading much more complicated, but runtime nearly identical. At this note, tools such as Hex-Ray's pseudo-code generator (Also known as one of the only reliable "C decompilers") aren't accustomed to analyzing such warped output.

On that note, I've been making a list of permutations for a permutation-engine I intend to begin writing. Some more that are notable:

Code:
XCHG:
XOR [register1], [register2]
XOR [register2], [register1]
XOR [register1], [register2]



ADD:
LEA REGISTER, [x+y]

SUB:
LEA REGISTER, [x-y]

MOV:
PUSH [register1]
{xchg} [register1], [[stackpointer]]
{mov} [[stackpointer]], [ptr]
POP [register2]
{mov} [[stackpointer]], [register1]
POP [register1]

PUSH [value]
POP [register]


CC?
 
Sounds like a good idea, as long as you don't too many memory operations, and like you said make sure they all use comparable amounts of clock cycles.

I believe you're capable of both, and I would say it's a good idea.
 
this would be extremely interesting to write

the obvious problem is that the replacement code is a different size than the code it is replacing, so you would need to move it around a lot at runtime

there's also the possibility of your engine being bypassed completely, but that could probably be avoided with encryption

finally, i think themida already includes this functionality, though that wouldn't make it any less interesting to create
 
this would be extremely interesting to write

the obvious problem is that the replacement code is a different size than the code it is replacing, so you would need to move it around a lot at runtime

there's also the possibility of your engine being bypassed completely, but that could probably be avoided with encryption

finally, i think themida already includes this functionality, though that wouldn't make it any less interesting to create

If you're given the source code, that's not an issue; otherwise, re-assembling the file is a quick'n'safe method to avoid such issues.

I don't see how my engine could be "bypassed"; unless you knew what every single permutation was, and could re-write them all in easier to understand terms. At that rate, the same is possible under virtualization and other obfuscation schemes.

Themida obfuscates its code, and has a VM; but it does not have such a feature.
 
If you're given the source code, that's not an issue; otherwise, re-assembling the file is a quick'n'safe method to avoid such issues.

I don't see how my engine could be "bypassed"; unless you knew what every single permutation was, and could re-write them all in easier to understand terms. At that rate, the same is possible under virtualization and other obfuscation schemes.

Themida obfuscates its code, and has a VM; but it does not have such a feature.

oh i see what you're going for

i was thinking of modifying the code at runtime, and working on that assumption, it could be bypassed by just skipping any calls to the engine

your idea is even more awesome than i thought

reassembling an exe is way outside of my realm of knowledge though, so the best i can do is wish you luck and keep an eye on this thread
 
I'm redesigning the engine, but, to show that progress is being made, here's something the former-engine produced:

Guy - Permutation Engine - RaGEZONE Forums
 
impressive

that particular example really does a number on efficiency, but i suppose that was to be expected

i'm still most interested in how you're going to actually apply it
 
impressive

that particular example really does a number on efficiency, but i suppose that was to be expected

i'm still most interested in how you're going to actually apply it

ADD ESP, 4 (x2) could be optimized to XOR ESP, 8. Eitherway, this project might get dropped, due to the fact anyone can write a reverse-permutation engine to undo any tricky-changes my engine would make for obfuscation purposes.
 
ADD ESP, 4 (x2) could be optimized to XOR ESP, 8. Eitherway, this project might get dropped, due to the fact anyone can write a reverse-permutation engine to undo any tricky-changes my engine would make for obfuscation purposes.

lol. Any1 who could understand what you just said that is O_o. Keep going on this project, it sounds like it's going to be good (didn't understand a thing).
 
ADD ESP, 4 (x2) could be optimized to XOR ESP, 8. Eitherway, this project might get dropped, due to the fact anyone can write a reverse-permutation engine to undo any tricky-changes my engine would make for obfuscation purposes.

you could go over it twice, first doing the actual obfuscation and then combining/optimizing the changes made

a 1:1 translation would, as you say, be reversible by an automated process, but if it was further modified after being obfuscated, it would be much harder

also, inserting junk commands now and then would make the whole thing much more confusing

Code:
pushf
clc
push ebp
push eax
jc short 10h
push esp
mov eax, esp
jc short 2ah
add dword [eax], 4
mov esp, [esp]
mov eax, [esp]
popf
popf

the efficiency of this can scarcely be compared to the original mov eax, ebp, but it cranks up the wtf factor by quite a bit

a program trying to reverse it would presumably not be able to do away with the jumps, as they could be legitimate, meaning by extension it would be unable to combine most, if not all, of the other instructions

this example could be reversed automatically, but the analysis required to do so would be on par with olly

a few tricks like this could be sprinkled around randomly with disastrous effects on analysers but little loss in efficiency (relative to your current obfuscation, anyway)

nops could be inserted at random to kill byte for byte comparisons, if such tricks were not generated dynamically

i would hate to see this project thrown out, as it happens to be relevant to my interests
 
you could go over it twice, first doing the actual obfuscation and then combining/optimizing the changes made

a 1:1 translation would, as you say, be reversible by an automated process, but if it was further modified after being obfuscated, it would be much harder

also, inserting junk commands now and then would make the whole thing much more confusing

Code:
pushf
clc
push ebp
push eax
jc short 10h
push esp
mov eax, esp
jc short 2ah
add dword [eax], 4
mov esp, [esp]
mov eax, [esp]
popf
popf

the efficiency of this can scarcely be compared to the original mov eax, ebp, but it cranks up the wtf factor by quite a bit

a program trying to reverse it would presumably not be able to do away with the jumps, as they could be legitimate, meaning by extension it would be unable to combine most, if not all, of the other instructions

this example could be reversed automatically, but the analysis required to do so would be on par with olly

a few tricks like this could be sprinkled around randomly with disastrous effects on analysers but little loss in efficiency (relative to your current obfuscation, anyway)

nops could be inserted at random to kill byte for byte comparisons, if such tricks were not generated dynamically

i would hate to see this project thrown out, as it happens to be relevant to my interests

Junk instructions would ruin the point of the project; it's intended to end up with no noticeable performance loss, something junk instructions would add.

In all honesty, you're better off designing a VM-like solution; you could have your entire program be interpreted by pseudo-bytecode, which decides which functions to execute, and in what series (A cross-platform representation of the entrypoint function, essentially). In this way, you'll given the same protection level offered by virtualization, but with less cross-platform compatibility issues, and an overall better performance.
 
Junk instructions would ruin the point of the project; it's intended to end up with no noticeable performance loss, something junk instructions would add.

you're barking up the wrong tree then; this whole concept totally destroys efficiency as the substitute instructions are more expensive than the originals (granted this criticism is pointless since you've already moved on)

In all honesty, you're better off designing a VM-like solution; you could have your entire program be interpreted by pseudo-bytecode, which decides which functions to execute, and in what series (A cross-platform representation of the entrypoint function, essentially). In this way, you'll given the same protection level offered by virtualization, but with less cross-platform compatibility issues, and an overall better performance.

that's an equally interesting concept

you pump out good ideas by the truckload
 
Back