赞
踩
一、要获取最新版本的obfuscator-llvm分支,可以使用以下命令:
- $ git clone -b llvm-4.0 https://github.com/obfuscator-llvm/obfuscator.git
- $ mkdir build
- $ cd build
- $ cmake -DCMAKE_BUILD_TYPE=Release ../obfuscator/
- $ make -j7
构建完成后,您应该拥有所有二进制文件build/bin
。请注意,此源树包含LLVM和Clang。
用cmake编译的过程中,可能会出现如下问题
CMake Error at cmake/modules/AddLLVM.cmake:1163 (add_custom_target):
add_custom_target cannot create target "check-llvm-bindings-ocaml" because
another target with the same name already exists. The existing target is a
custom target created in source directory
"/home/xxx/obfuscator/test". See documentation
for policy CMP0002 for more details.
Call Stack (most recent call first):
cmake/modules/AddLLVM.cmake:1226 (add_lit_target)
test/CMakeLists.txt:150 (add_lit_testsuites)
修改为以下命令再尝试编译可顺利通过
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_INCLUDE_TESTS=OFF ../obfuscator/
二、将build/bin里的 clang++ 、clang、clang-format、 clang-4.0、拷贝到 android-ndk-r16b/toolchains/llvm/prebuilt/linux-x86_64/bin(覆盖前请自行备份) 。 在CMakeLists.txt 里的 SET(CMAKE_CXX_FLAGS 追加 -mllvm -fla ,CMAKE_C_FLAGS 也可以加,然后 重新编译你的项目。(我这里是用cmake编译,如果你是ndk-build 那么你可以在 LOCAL_CFLAGS、LOCAL_CPPFLAGS 里添加)
重新编译,你可能会发现缺少头文件,从obfuscator 里的build 文件里按文件名一搜,拷贝到报错的目录即可。
源代码混淆有两种方法:一种是对C/C++的AST进行操作,由于最终输出的还是源代码,因此通用性强,只不过没有资料可供参考,较难实现。另一种是对各编译器的IR进行操作,如LLVM IR或GCC的gimple等,限制于各编译器目标cpu的实现,通用性比较差。基于LLVM IR的源代码混淆由于有可供参考的资料,实现比较容易。
该实现已经在控制流平坦化的实现(http://bbs.pediy.com/showthread.php?t=209203)一文中说明,实际上控制流平坦化有点像虚拟机保护,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。
把跳转指令BranchInst变为switch指令SwitchInst。先生成一个switch变量v,当指令是无条件跳转指令时,设置v为一个常量;当指令是条件跳转时,设置v为用SelectInst生成两个常量语句。常量在SwitchInst中所对应的case块的后继块就是跳转指令的后继块,其余的case块的后继块则可以随机选择一个基本块作为为后继块。
把基本块分成多个基本块。有两种方法:一种是根据概率对基本块的当前指令进行分割;另一种是计算基本块的总指令数,标记为a,随机生成小于a的数,标记为b,基本块b条指令后进行分割,a减掉b,进行多次迭代直至a等于1。
让基本块的前驱块不一定在前面,后继块不一定在后面。对入口块进行块分割,随机化除入口块的其它基本块,放在入口块后面。
该实现也在控制流平坦化实现(http://bbs.pediy.com/showthread.php?t=209203)一文中说明。
有两种方法:一种是字符串的各个元素都有自己的加密方法,这样解密方法就是常量展开,先随机生成加密字符串,然后对目标字符串各个元素以加密字符串常量展开。另一种是共用同样的加密算法,其操作必须可逆,如xor、sub、add,在用加密算法生成加密字符串时,用栈记录每次运算的常量值和运算的可逆运算(add对应sub,sub对应add,xor对应xor),最后根据记录栈生成解密算法。
让常量在数组中的索引随机化。假设常量数组a[],索引值i,随机生成索引数组b[]、c[]、d[](可生成更多),循环用z[b[c[d[i]]]]=a[i]生成随机后的常量数组z[],然后用z[b[c[d[i]]]]替换a[i]。
1、数组元素
把常量放在常量数组,进行常量数组随机化,然后进行数组访问。
2、生成函数
记录多个常量,每个常量就是一个函数参数,再把与常量相关的操作搬进函数内,当然常量要替换成函数参数。
对逻辑操作not、and、or、xor,可以先把操作数抽取分成多个更小的数进行操作,最后用or连接起来,当然这四个操作可以用与非门或是或非门来完成。还有其它常见的运算可以把操作数看成大数然后进行大数运算,还有一些运算可以转变为SIMD指令进行运算。至于浮点数,有很多浮点数的软件实现可供参考。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。