Ollvm
OLLVM(Obfuscator-LLVM)是瑞士西北应用科技大学安全实验室于2010年6月份发起的一个项目,该项目旨在提供一套开源的针对LLVM的代码混淆工具,以增加逆向工程的难度, 只不过Ollvm仅更新到llvm的4.0,2017年开始就没再更新。
Ollvm混淆主要分成三种模式,这三种模式主要是流程平坦化,指令替换,以及控制流伪造。
流程平坦化 :这个模式主要通过将if-else语句替换成do-while语句,然后通过switch语句来对流程的控制,这样就能模糊基本块之间的前后关系。
指令替换 :这个模式主要通过使用更复杂的指令序列来替换一些标准的二元运算符,从而增加逆向的难度。
控制流伪造 :这个模式主要是会在一个简单的运算中外包好几层if-else的判断,从而增加逆向的难度。
对Ollvm有更深入的理解,可参阅论文《Obfuscating C++ programs via control flow flattening》
env: arch-linux
使用apt源安装g++和cmake,从github获取ollvm的源码,并进行编译。
Ollvm 6.0: https://github.com/yazhiwang/ollvm-tll.git (编译成功!)
原版src: https://github.com/obfuscator-llvm/obfuscator/tree/llvm-4.0 (编译失败!)
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ../ollvm-tll-master
make -j8
cd
mkdir build
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_INCLUDE_TESTS=OFF ../
make -j8
这个模式主要是把一些if-else语句,嵌套成do-while语句
-mllvm -fla:激活控制流扁平化
-mllvm -split:激活基本块分割。在一起使用时改善展平。
-mllvm -split_num=3:如果激活了传递,则在每个基本块上应用3次。默认值:1
这个模式主要用功能上等效但更复杂的指令序列替换标准二元运算符(+ , – , & , | 和 ^)
-mllvm -sub:激活指令替换
-mllvm -sub_loop=3:如果激活了传递,则在函数上应用3次。默认值:1
这个模式主要嵌套几层判断逻辑,一个简单的运算都会在外面包几层if-else,所以这个模式加上编译速度会慢很多因为要做几层假的逻辑包裹真正有用的代码。
-mllvm -bcf:激活虚假控制流程 -mllvm -bcf_loop=3:如果激活了传递,则在函数上应用3次。默认值:1 -mllvm -bcf_prob=40:如果激活了传递,基本块将以40%的概率进行模糊处理。默认值:30
-mllvm -sobf 开启字符串混淆
-mllvm -seed=0xdeadbeaf 指定随机数种子生成器 bcf可以配合下面参数使用
对a.c进行混淆
#include<stdio.h>
void exec() {
printf("OOOKKKK!");
}
int main(void) {
int a = 0;
a ++;
printf("Hello World");
if(a >= 1) {
exec();
}
return 0;
}
~/tools/ollvm/bin/clang a.c -mllvm -fla -mllvm -sobf -mllvm -bcf -o a
ida64打开F5
int __cdecl main(int argc, const char **argv, const char **envp)
{
signed int v3; // eax
__int64 *v4; // rcx
int v5; // eax
signed int v6; // edx
signed int v7; // eax
signed int v8; // eax
signed int v9; // eax
__int64 *v11; // rcx
int v12; // eax
__int64 v13; // [rsp+0h] [rbp-50h]
int v14; // [rsp+8h] [rbp-48h]
int v15; // [rsp+Ch] [rbp-44h]
__int64 *v16; // [rsp+10h] [rbp-40h]
int v17; // [rsp+18h] [rbp-38h]
int v18; // [rsp+1Ch] [rbp-34h]
int v19; // [rsp+20h] [rbp-30h]
int v20; // [rsp+24h] [rbp-2Ch]
int v21; // [rsp+28h] [rbp-28h]
int v22; // [rsp+2Ch] [rbp-24h]
int v23; // [rsp+30h] [rbp-20h]
int v24; // [rsp+34h] [rbp-1Ch]
int v25; // [rsp+38h] [rbp-18h]
int v26; // [rsp+3Ch] [rbp-14h]
int v27; // [rsp+40h] [rbp-10h]
bool v28; // [rsp+45h] [rbp-Bh]
bool v29; // [rsp+46h] [rbp-Ah]
bool v30; // [rsp+47h] [rbp-9h]
v28 = (((_BYTE)x_2 - 1) * (_BYTE)x_2 & 1) == 0;
v29 = y_3 < 10;
v27 = 1567572003;
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
v26 = v27;
v25 = v27 + 1130483098;
if ( v27 != -1130483098 )
break;
v9 = -1065940243;
if ( y_3 < 10 || (((_BYTE)x_2 - 1) * (_BYTE)x_2 & 1) == 0 )
v9 = -714366873;
v27 = v9;
}
v24 = v26 + 1065940243;
if ( v26 != -1065940243 )
break;
v27 = -1130483098;
}
v23 = v26 + 714366873;
if ( v26 == -714366873 )
break;
v22 = v26 + 511865542;
if ( v26 == -511865542 )
{
v8 = -1065940243;
if ( y_3 < 10 || (((_BYTE)x_2 - 1) * (_BYTE)x_2 & 1) == 0 )
v8 = -1130483098;
v27 = v8;
}
else
{
v21 = v26 + 329192939;
if ( v26 == -329192939 )
{
v11 = &v13 - 2;
*((_DWORD *)&v13 - 4) = 0;
*(_DWORD *)v11 = 0;
*(_DWORD *)v11 = *((_DWORD *)&v13 - 4) + 1;
v12 = printf(&byte_404030);
v27 = 191033970;
v14 = v12;
}
else
{
v20 = v26 - 191033970;
if ( v26 == 191033970 )
{
v4 = &v13 - 2;
*((_DWORD *)&v13 - 4) = 0;
*(_DWORD *)v4 = 0;
*(_DWORD *)v4 = *((_DWORD *)&v13 - 4) + 1;
v16 = &v13 - 2;
v5 = printf(&byte_404030);
v6 = -329192939;
v30 = *(_DWORD *)v16 >= 1;
if ( y_3 < 10 || (((_BYTE)x_2 - 1) * (_BYTE)x_2 & 1) == 0 )
v6 = 1347608926;
v27 = v6;
v15 = v5;
}
else
{
v19 = v26 - 1347608926;
if ( v26 == 1347608926 )
{
v7 = -511865542;
if ( v30 )
v7 = 1700479422;
v27 = v7;
}
else
{
v18 = v26 - 1567572003;
if ( v26 == 1567572003 )
{
v3 = -329192939;
if ( v29 || v28 )
v3 = 191033970;
v27 = v3;
}
else
{
v17 = v26 - 1700479422;
if ( v26 == 1700479422 )
{
exec();
v27 = -511865542;
}
}
}
}
}
}
}
return 0;
}
以上成功实现代码混淆
Obfuscating C++ programs via control flow flattening
查看符号表
readelf -s test
采用strip工具对符号表进行去除
.symtab因为是在调试和链接时有用的,所以,可以从生产的二进制执行文件中移除。可以使用strip。strip是可以移除符号以及节的工具。
strip --remove-section=.symtab file_in
strip --remove-section=.strtab file_in
.dynsym
动态链接表,.dynstr
动态链接字符表。 gcc编译时添加参数,从而使用静态编译。gcc -static
或者 gcc -nostdlib
gcc -nostdlib
:不连接系统标准启动文件和标准库文件,只把指定的文件传递给连接器。gcc -static
:在支持动态链接的系统上,阻止连接共享库。该选项在其它系统上 无效。原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。