代码混淆是将计算机程序的代码,转换成功能上等价,但是难于阅读和理解形式的行为。代码混淆可以有效提升反编译的难度。 本文主要介绍了C/C++混淆方法和手段。
1. Obfuscator-LLVM实现C/C++混淆:
利用Obfuscator-LLVM工具实现C/C++混淆方法:
控制流平坦化:在不改变源代码功能的前提下,将C、C++等语言中的if、while、for、do等控制语句转化为switch分支选择语句。控制流平坦化有点像虚拟机保护,case块相当于vm的handle,case值相当于vm的opcode。
指令替换:生成条件跳转指令有两种方法,一种称为opaque predicate,另一种称为bogus control flow。假设基本块block0,opaque predicate后变为:if(恒等式){block0;}else{垃圾代码}或if(恒不等式){垃圾代码}else{block0;};bogus control flow后变为if(随机条件){block0;}else{block1;},else的基本块block1复制于block0。
控制流伪造。
2.其他常见的C/C++混淆手段:
多重分支;
基本块分割:把基本块分成多个基本块。有两种方法:一种是根据概率对基本块的当前指令进行分割;另一种是计算基本块的总指令数,标记为a,随机生成小于a的数,标记为b,基本块b条指令后进行分割,a减掉b,进行多次迭代直至a等于1。
字符串加密;
常量隐藏;
常量展开;
常量数组随机化:让常量在数组中的索引随机化。假设常量数组a[],索引值i,随机生成索引数组b[]、c[]、d[](可生成更多),循环用z[b[c[d[i]]]]=a[i]生成随机后的常量数组z[],然后用z[b[c[d[i]]]]替换a[i]。
表达式变换:对逻辑操作not、and、or、xor,可以先把操作数抽取分成多个更小的数进行操作,最后用or连接起来,当然这四个操作可以用与非门或是或非门来完成。还有其它常见的运算可以把操作数看成大数然后进行大数运算,还有一些运算可以转变为SIMD指令进行运算。至于浮点数,有很多浮点数的软件实现可供参考。
相关阅读: