Jump to content
Tuts 4 You

Control flow obfuscation


Lostin

Recommended Posts

Hello


 


I was wondering how this is coded? how i can make a lot of Unconditional branches forward/backward?


 


how this is implemented? i mean how i can control the execution flow with jumps like themida VM, or VMP.


 


I can make this only forward but backward/forward will interference with each other.


 


Also one more question. Do these jmps random? or it has fixed addresses?


 


Any ideas will be appreciated.


Edited by Lostin
Link to comment

I'm just guessing you're referring to Control Flow Flattening - if that's not the case please elaborate. It's originally introduced by Chenxi Wang, for educational material in general I suggest taking a look at everything Collberg publishes.

Basically one reduces control flow to a data flow problem by making control flow dependent on the value of a certain switch variable. Imagine a big switch instruction where each basic block of the function you want to obfuscate gets assigned an unique value. Now replace all jumps (unconditional and conditional) by an update of the switch variable and jump back to the switch instruction itself. It now indirectly redirects control flow to the original successor block. Conditional jumps are translated to conditional updates to the switch variable.

Edit: On a second read you might refer to opaque predicates - conditional jumps that always take a certain branch (false or true) but never the other. Backward jumps could be introduced by simple re-arranging the order of basic blocks. Most code in packer stubs is created dynamically so they insert these predicates at one point and then simply shuffle the order of blocks before translating them to (e.g. x86) assembler code. Thus some jumps may in fact point backwards which would be hard to achieve when modifying existing x86 assembler code, due to relocations and such.

Edited by metr0
  • Like 2
Link to comment

metr0 thanks for your information. i am not sure about this Control Flow Flattening but i just wanted to write the codes without modifying an existing code. I am actually writing some random junks and i want to transfer code execution on random areas with forward and backward unconditional branches.


 


I am sorry but i forgot to mention that i do not want to modify an existing code. I am trying to write this code with unconditional branches directly like i mentioned but without having the source code. So i am just wondering about the idea. My current idea is to alloc some mem space and then write the codes and log each x amount of lines then increment a value as of numberofblocks where each block contains small amount of codes like blocks, block1 block2 etc and store each start of a block pointer in a variable. After this write a JMP 00000000 after each block end, then arrange the blocks one after the other but in random order like so



block1
some codes here
JMP block2
block3
some codes here
JMP block4
block4
some codes here
block2
some codes here
JMP block3

on the end those JMP 00000000 will be corrected with the correct blocks order.


Is this good idea or there is an easier way.


Edited by Lostin
Link to comment
 and log each x amount of lines then increment a value as of numberofblocks where each block contains small amount of codes

 

What do you mean by that? What would the value be for, what are you logging?

 

Do you want to interleave original program code with junk code or do the lines "some codes here" stand for junk code only as of now? Assuming the latter your approach seems fine. Write a small junk code generator engine that generates a basic block of trash and append a jmp with offset 0 to it (just like you said). Your trash generator could temporarily store the generated code in some structure, the code calling your engine would request and collect various trash blocks, shuffle them and then fix up the jumps. It would make sense to have each structure contain a list of indices where you need to fix up, e.g.:

struct Fixup {

unsigned int Index; // Index of block the relocation points to.

unsigned int Offset; // Offset into block's code.

FIXUP_TYPE Type; // Type of fixup: direct (e.g. push Immediate; ret) or indirect (e.g. jmp Immediate).

unsigned int Size; // Size of fixup (e.g. short or long jump).

};

struct Block {

unsigned int Index; // Index of trash block.

vector<unsigned char> Code; // Trash code itself, either some IR or raw x86 bytecode.

map<unsigned int, Fixup> Fixups; // Map of fixups, indexed by offset into Code array.

};

(This is merely a suggestion.) This keeps in mind that:

  • Relocations might point into other blocks (the most common case).

Relocations might not always point at the start of a block (thus the offset).

Relocations are either direct or indirect (encoding as immediate or as offset). This could also be handled implicitly.

Relocations may apply to offsets that are either near of far (1 byte, 4 bytes).

  • Like 1
Link to comment

Do you want to interleave original program code with junk code or do the lines "some codes here" stand for junk code only as of now?

 

Yes z9D4QB9.gif

 

Logging each start and end of block with the size (End of block - Start of block) so later i can know how much to copy when shuffling the order.

 

I made something like this currently similar as your explanation

 

Make a structure for the blocks.

Each structure contains members of BlockStart - BlockEnd - BlockSize (each member is an array of 50 element)

Start write the random codes at some mem region and on a loop and log each new iteration as a new block.

After this loop through all the blocks and shuffle the order.

Update the order again after been randomized.(New addresses)

Start fix the JMP 00000000 according to what's logged (on each JMP of block it will point to the next block starting address) and so on.

 

And now is working fine thank you. You are a good programmer  z9D4QB9.gif

 

What you mean by relocations? do you mean the fixups that are used to reallocate the PE to a new imagebase? Why this is needed if my exe only loaded at 400000 imagebase.

Edited by Lostin
  • Like 1
Link to comment

Nice to hear your code's working. Make sure to post a sample or even a crackme after you've implemented enough features to make it interesting! ;)

I guess we're talking about the same. With relocations I refer to "fixing up the jump offsets" - just like you do after your logging process.

  • Like 1
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...