I’m no glorious reverser, however I’m always glad to learn some cool new technique to
detect interesting behaviour
As my journey reversing for fun and non-profit I got into different methods to call a function
in an “obfuscated” way
Such way that in most cases you won’t be able to know where the call would actually go to
The actual value of the call is decided upon runtime and is based on the value of a few things
The actualy value of the call is decided upon runtime and is based on usually one of things below:
1.The value of the register
For example – let’s take a look at this simple method
mov eax,[ebp-22] shl eax,3 call eax
in this example below the value of ebp-22 can be calculated upon runtime
but if we’d try to statically analyse the function it will be quite hard to follow the stack changes and call
as this example is quite abstract, most malware add different kind of obduscation methods
such as different calls to useless function and register manipulation
2. push `n ret
push 5 push &exit call obfuscation_method ret
In this example it gets a bit trickier, obfuscation_method doesn’t really interest us
since once we’ll comeback from obfuscation_method, we’ll be back to the previous stack frame
and since we’ve pushed the address of printf beforehand – we’ll return to it immidiately after calling obfuscation_method
3. nopsled, bruteforce
In this specific method we don’t really know at all (nor does the program itself) where are we going
The method is based on a simple “brute-force” loop which tries calling addresses by simple arithmetic manipluation
mov eax,&base_offset mov ecx,MAX_BASE_OFFSET call [eax+ecx]
in this specific method we’ll have to allocate an array of MAX_BASE_OFFSET
pad it with nops or garbage instructions and add our real code in specific location for example
nop nop nop nop nop [ ... real code goes here ... ] ret nop nop nop nop [ ... more real code goes here ... ] ret nop nop nop nop
it is quite hard (and frustrating) to know where the real code is especially if don’t have nops and real garbage code the disadvantage in this specific method is that you must align you code perfectly else you’ll get an exception of an invalid instruction
this method is quite equivalent to a malware which doesn’t know it’s decryption key (same concept) and so it just bruteforce’s itself until it finds the key the disadvantage here is that you’ll need large computation power in order to get they decryption key when not dealing with the classical xor/XTEA/etc crypto
I’ve read about this method in peter ferrie’s article and decided to try to implement it on my own
From Peter Ferrie’s article :
Nanomites are a more advanced method of anti-dumping.
They were introduced in Armadillo. They work by replacing
branch instructions with an “int 3” instruction, and using
tables in the unpacking code to determine the details. The
details in this case are whether or not the “int 3” is a
nanomite or a debug break; whether or not the branch
should be taken, if it is a nanomite; the address of the
destination, if the branch is taken; and how large the
instruction is, if the branch is not taken.
A process that is protected by nanomites requires selfdebugging
(known as “Debug Blocker” in Armadillo, see Anti-Debugging:Self-Debugging
section below), which uses a copy of the same process.
This allows the debugger to intercept the exceptions that are
generated by the debuggee when the nanomite is hit.
When the exception occurs in the debuggee, the debugger recovers
the exception address and searches for it in an address table. If a match is found, then
the nanomite type is retrieved from a type table. If the CPU
flags match the type, then the branch will be taken. When
that happens, the destination address is retrieved from a
destination table, and execution resumes from that address.
Otherwise, the size of the branch is retrieved from the size
table, in order to skip the instruction.
This method however adds much more complication to the code you’re writing
and divides it into separate projects:
One is your original project which has all the code you’ve written originally
The other is a “stub” ( those who ever wrote a packer would know this acronym better than I do) that keeps track of the nanomites and knows when a real nanomite is hit and not a regular int 3 instruction caused by the debugger / compiler.
The third is a project that injects the stub ( PE/ELF file manipulation, adding a new section if necessary ) and replaces the calls/jmps
with nanomites (int 3 instructions)
This is a whole new level of complication and it really frustrates the reversing process, not talking about that it is really hard to statically reverse such binary
without having all the instructions in your hand….