@Ouroburos sent me a IR which crashes Obfuscator-LLVM. So the investigation begin.
Below is a generated Control-Flow-Graph for the affected function.
However running bcf on this IR using
bin/opt -boguscf -bcf_prob=100 won’t pass IRVerifier, yielding the following message:
The unwind destination does not have an exception handling instruction!
Now that if you have enough knowledge of LLVM you will surely recognize this error as a InvokeInst going wild and jumping to illegal destination block. First, let’s bootup opt again and dump the CFG of the obfuscated IR, in order to do that we need to disable IR verifier first by using
-disable-verify. The full command would be:
bin/opt -boguscf -bcf_prob=100 -S original.ll -disable-verify -o Obfuscated.ll
Yielding the following image.I did the annotation part for you : )
Let’s explain this CFG a little bit more.Among other things, the root cause of the issue is the basicblock marked as
originalBBpart2, which I’ve circled out with blue. If you remember our CFG for the un-obfuscated version, this block is the terminator of the first BB that got seperated out.Below is the code responsible for this extracted from Obfuscator-LLVM
// Split at this point (we only want the terminator in the second part)
Initially, this piece of code does seem to be correct. However, in order to loop though all BasicBlocks,the author used a
void bogus(Function &F) following codes that insert all BBs from this function into the set. That’s how things went horribly wrong.
At later stage in the obfuscation, BasicBlock
%16 also got obfuscated into
%48. Remember the BCF uses
BasicBlock::getFirstNonPHIOrDbgOrLifetime() to locate the split point. And that, unfortunately, means our poor
LandingPad also got splited to
%26 ‘s terminating
InvokeInst is using a BB that doesn’t have LandingPad. And the original LandingPad BasicBlock is now referenced by an unconditional BranchInst (aka the one after
%56), this newly generated IR will surely fail to pass IRVerifier and thus crash the whole compiling process.
The easist solution would be inserting codes checking if the BB is a landing pad before obfuscating. However I do feel like constant based branching condition is far from effective so here I purpose a new solution that generates random mathematical expressions as LHS and use
tinyexpr to evaluate the RHS