Z0mbie
January 2005
Lets consider some C-to-asm transformations.
Lets assume a is eax, b is ebx, c is ecx, d is edx, and "condition" is a result of some binary comparison, i.e. single bit, 0 or 1.
First, we want to know how the following thing looks in assembly:
this looks like:
lets taste it in more real situation:
or, in simple form:
so, we have:
or
a bit more complex code, simple a=MIN(a,b) function:
which is equivalent to
which is equivalent to
which is equivalent to
which (using examples 1 and 2) results in:
absolute value, abs() function:
but, since NEG operation is the same as NOT+INC (we consider typical x86 asm), we can do the following:
and, in assembly it looks like:
some code in C:
and so, it looks like this:
As you can see, many basic operations could be encoded without conditional jmps. I.e. if we have some condition, we sometimes can avoid generating Jxx instruction. for example,
can be converted to
which is equivalent to example 5 + shr, and so on.
But, what if we want to call some subroutine? Okey, here is a solution:
But, what if we want to initialize some variable? Lets do the following then:
So, the following situation
can be converted into:
and each such line of code can be encoded using techniques shown in examples above.
The only thing we cant change, is direct jmp, which is used in cycles, like while() or for(;;).
However, we can expand conditional execution to the whole program, which will look like:
and then, we need only 1 jmp per whole program.
As you can see, there can be many conditions, like
- for 3 nested cycles, or we can write a program in state-machine style, like
and so on, and all these programs will be encoded w/o jmps.
A program, written with minimal jxx usage will have the following properties:
Okey, now lets imagine that you want to generate some different unique programs using the same C source. Then, you write kind of template, and you code some script to preprocess this template into C. In such a template, you can replace some macros with the following macro definition, choosing them randomly:
all these macros should generate different code, and uncommented macros should generate code w/o jmps.
In some situations, complex polymorphic decryptors are detected using set-of-instructions technique.
This technique can be defined as the following:
As such, when analyzing algorithm encounter some instruction which is out of defined set, it returns false.
Possible way of counteracting to such algorithms requires mistfall-like decryptor injection into program's code (for effective entrypoint hiding) plus splitting poly decryptor into some small parts where these parts are linked indirectly (i.e. located in the different places of code section), and order of their exection is pre-calculated using program tracing.
When you are generating some code, you can change its instruction statistics using the following ways:
As you can see, such constructions (ex.6/7) will allow you to produce code where
axiom: if some algorithm will analyze each conditional jmp, choosing only one of the variants of the execution flow (where only some defined set of instructions is used), it will result in false alarms.
However, here should be noted: statistical and more sophisticated detection algorithms are used only when all other more simple ways are impossible.
The only way to write near-to-undetectable code is to constantly check detection algorithms and fix all the bugs which resulted in detection.