With our experimental environment, it should also be possible to try to deobfuscate this whole transformation. We start with the same screenshot as we ended with after the obfuscation process.
Manual inspection of the obfuscated function reveals that control flow falls through from the entry basic block to the switch-block.
The entry basic block inserts zero into register %eax. Register %eax is used as the offset in the switch table. With Loco, we can highlight the target basic block of the entry on the switch table, which is needed since in a CFG address computations are meaningless. A right click on the switch-block pops up a window where the user can choose an entry in the switch-table to highlight the appropriate basic block. Now we can make changes to the CFG to modify the control flow so that the highlighted basic block becomes a successor of the entry basic block directly.
We have several different possibilities to change control flow. The most efficient one in this case is only changing the target of the fallthrough edge. A right click on the appropriate edge pops up a menu with different choices. One of them is choosing a new target. Other possibilities to change control flow are deleting and adding edges. When deleting an edge, a user can choose to let Loco handle all side-effects. A side-effect is for example substituting a conditional jump with an unconditional jump when the fallthrough edge following a conditional jump is removed. Adding new edges is done by clicking the head and tail for the new edge.
A new target for an edge is chosen. As a side-effect, a new layout of the CFG is computed and shown so that the user has a better overview on the control flow in the function.
When continuing the deobfuscation process from the new target of the modified edge, we can figure out that control flow can go two ways, depending on a conditional definition of register %eax. As in the previous case, we can modify the CFG such that the switch-construct is bypassed and control flow goes directly to the two possible targets. In order to do so, the last instruction of the basic block has to be modified which can be done using a basic block editing window. As can be seen from Figure~\ref{screen10}, instructions in a the basic block can be edited and removed. On top of this new instructions can be added and a basic block can be split.
Using the graph and block editing features, the original CFG can be rebuild. After the control flow has been recovered, the analysis from the underlying Diablo framework can be used, e.g. liveness analysis to remove useless instructions. Most of these analysis improve the readability of the code, which helps in revealing the functionality.
In our example, a lot of push and pop instructions are left in the code. With a simple local optimization these instructions can automatically be removed. Control flows always towards the same basic block. That basic block will pop %eax and %ebx, so these five instructions are now useless and can be eliminated by liveness analysis. After the whole deobfuscation transformation, we end up with exactly the same CFG as we started.