I have recently seen the following code obfuscation method:

...
jump loc_1234
;-------------------------
         Bunch of junk
;-------------------------

loc_1234:
code continued...

The logic behind the obfuscation mechanism looks pretty straight forward. Bunch of junk is inserted into code with jump instructions to jump over it. I guess, the purpose is to confuse linear sweep disassemblers and obfuscate file in general. I would like to learn more about it. Does anyone know what it is called? How effective is this method against modern day anti-virus software?

  • I call that "destruction of sequential locality for temporally-related instructions". – Rolf Rolles Jun 26 '13 at 10:43
  • 1
    I would call this "dead code insertion". For me, this is a technique to evade linear sweep and recursive traversal. But, once you follow the semantics of the instructions when disassembling, this obfuscation is totally useless. – perror Jun 26 '13 at 11:28
  • @perror its not dead if it is executed from somewhere else. – cb88 Jun 26 '13 at 12:07
  • 1
    @cb88: I though it was a bunch of junk... – perror Jun 26 '13 at 14:56
  • @perror I think it should not confuse recursive traversal, due to the fact that it follows binary trees and will just follow jumps. Am I correct? – PSS Jun 26 '13 at 15:01
up vote 6 down vote accepted

This anti-disassembly technique is described as Jump Instruction with a Constant Condition in the Pratical Malware Analysis book (Chapter 16, page 336 of the 1st edition). The idea as you described is to have a condition such that the jump is always taken and add code after the jump that will generate a wrong disassembly at the location of the jump. As the disassembler assumes that both branches are coherent, it will disassemble only one of them.

Regarding effectiveness against antivirus software, most of them use emulators. As the condition is always taken, the emulator will continue there and see the right instructions.

A variation on this is to use a "branch function". The basic idea is as follows:

  • a jump instruction "jmp L" is converted to "call branch_fn" and N bytes of junk are inserted after the call instruction;
  • the callee, branch_fn, adds N to its return address and then returns.

This basic scheme can be elaborated in various ways, e.g.:

  • Multiple jumps can use the same branch function, and they can have different values of N (the amount of adjustment needed for the return address). The branch function uses the return address to identify the call site and thus the particular jump instruction under consideration, from which it can determine the amount of adjustment N necessary (e.g., using a table lookup based on the return address).
  • The amount of adjustment N applied to the return address need not be stored "in the clear", but can be computed dynamically via the evaluation of an expression. For example, using perfect hash functions to map the return addresses to an adjustment value N can produce pretty inscrutable code.
  • A branch function doesn't have to adjust its own return address, since that's relatively easy to spot. Instead, it can use a sequence of calls branch_fn0 --> branch_fn1 --> ... --> branch_fnK where the last one in the sequence "reaches into" the call stack to carry out the return address adjustment.

But, as mentioned above, this is basically aimed at throwing off static disassembly; it doesn't do a whole lot against dynamic analysis.

An alternative answer is that you are looking at hand coded assembly and there is actually no effort to deceive the disassembler.

When I hand code assembly, regardless of what good practice is, if it is a small bit of code I will very frequently set the Data Selector to match the Code Selector and simply embed my data right inside of the code segment. I especially do this if I'm writing a real mode boot loader, for example, or some other short lived piece of code.

Another place I would do this and still not be trying to obfuscate things is in a piece of exploit code. This allows me to have variables that I can reference reliably and still have a really tight piece of shell code.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.