Fetching...

-

Just a minute...

我们通过自己编写测试代码,再用OLLVM的不同指令进行加固,并逆向查看加固效果,加深对代码加固机理的了解。OLLVM目前提供的功能包括控制流平坦化(fla指令),指令替代(sub指令),代码虚拟化(bcf指令)以及虚假控制流(obf指令),接下来,我们团队对各个指令的机理进行详细的分析。

1.控制流平坦化

控制流平坦化的主要思想,就是把原本顺序执行的代码变成一个一个的基本块,并复杂化各个代码块之间的关系,使得代码的执行流程不再清晰。

OLLVM的控制流平坦化功能实现于Flattening.cpp中,主要有以下两个步骤。

第一步:判断是否能够平展。若可以,则跳入flatten方法中执行。在函数开始,使用LowerSwitchPass去除switch,将switch结构换成if结构。保存所有的基本代码块,如果只有一个基本代码块,则不进行处理;如果第一个基本块的末尾是有条件的跳转指令,那么需要将它分割开,并且将它保存到origBB。

1
2
3
// Lower switch
FunctionPass *lower = createLowerSwitchPass();
lower->runOnFunction(*f);

第二步:创建两个基本块,存放循环头和尾的指令。然后将first bb移到到loopEntry的前面,并且创建一条跳转指令,从first bb跳到loopEntry。紧接着创建了一条从loopEnd跳到loopEntry的指令。最后,创建了switch指令和switch default块,并且创建相应的跳转。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Create main loop
loopEntry = BasicBlock::Create(f->getContext(), "loopEntry", f, insert);
loopEnd = BasicBlock::Create(f->getContext(), "loopEnd", f, insert);
load = new LoadInst(switchVar, "switchVar", loopEntry);
// Move first BB on top
insert->moveBefore(loopEntry);
BranchInst::Create(loopEntry, insert);
// loopEnd jump to loopEntry
BranchInst::Create(loopEntry, loopEnd);
BasicBlock *swDefault =
BasicBlock::Create(f->getContext(), "switchDefault", f, loopEnd);
BranchInst::Create(loopEnd, swDefault);
// Create switch instruction itself and set condition
switchI = SwitchInst::Create(&*f->begin(), swDefault, 0, loopEntry);
switchI->setCondition(load);

第三步,删除first bb的跳转指令,改为跳转到loopEntry,将所有的基本块加入switch结构.接下来是根据原先的跳转来计算switch变量。

(1)若为没有后继(return BB)的基本块,直接跳过。

(2)若为只有一个后继的基本块,首先删除跳转指令,并且通过后继基本块来搜索对应的switch case,根据case创建一条存储指令,达到跳转的目的。

(3)两个后继的情况跟一个后继的处理方法相似,不同的是,创建一条select指令,根据条件的结果来选择分支。

为了测试控制流平坦化混淆的效果,我们编写了如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
int main()
{

while (n>0)
{
if(a[i%16]>0x60)
{
........................
}
else
{
........................
}
if(a[i%16]>0x70)
{
........................
}
else
{
........................
}
if(a[i%16]>0x80)
{
........................
}
else
{
........................
}
........................
}

将该代码编译成exe文件,逆向后主函数的控制流程图如图1:

1573125852244

图1 源程序逆向后主函数的控制流程图

可以看出,除了内嵌的几个选择结构以外,总体来说,程序的结构都是顺序结构,这样代码分析就十分容易,例如从while循环代码逆向后,我们仍然可以清晰的看到代码的执行原理,如图2所示:

1573126048613

图2 源程序逆向所得C代码

除了变量名有所不同以外,我们能轻易的看到各个条件分支的选择条件,以及各条异或操作代码的先后顺序。

而被混淆后,代码的执行流程就完全不同了,所有代码块的先后顺序都被打乱,代之以各种分发器决定代码执行的先后顺序,如图3所示:

1573126374237

图3 控制流平坦化混淆后的控制流程图

具体到代码上,可以看到很多的while循环。而一个while循环内,各基本块之间也变成了平行关系,并通过一个分发器进行分发,如图4:

1573126820484

图4 混淆后逆向所得C代码

从图中看出,变量v17控制整个执行流程,执行完一个基本块后通过改变v17的值跳到下一个基本块,例如图中标黄的v17==-1882529108,那么下一个块就是最上面的++v20,–v21。所以控制流平坦化主要是打乱代码块的先后顺序,让代码的执行流程没有这么明显、直接。

2.指令替代

通过把简单的指令变为更加复杂的指令,我们可以把汇编代码换为许多相似的指令,我们写了另一个类似的程序,并对其用指令替代进行混淆。这次,我们把重点放在以下几条C代码上:

1
2
3
........................
a[(i+1)%16]^=char(0x52);
........................

对于异或语句,逆向后的汇编代码如图5:

1573130730912

图5 指令替代之前异或语句汇编代码

F5为C代码,如图6:

1573130812706

图6 指令替代之前异或语句反汇编代码

进行指令替代后语句汇编代码如图7:

1573130921334

图7 指令替代之后异或语句汇编代码

F5为C代码,如图8:

1573130948253

图8 指令替代之后异或语句反汇编代码

可以看到,整个代码的逻辑变得比较复杂,并不能看出来是异或0x52,给整个逆向分析带来了很大困难。

3.虚假控制流

和控制流平坦化类似,混淆控制流也是通过混淆控制流程以达到干扰程序分析的目的。但和控制流平坦化不一样,虚假控制流其实是通过增加一些完全无用的分支跳转以达到混淆控制流程的目的,在对上述程序进行修改后,我们首先在不加混淆的情况下进行逆向,得到的控制流图如图9:

1573216331690

图9 虚假控制流操作前的控制流程图

可以看到,整个程序的结构十分清晰,这样逆向分析起来也是十分容易的。

现在我们对其进行虚假控制流混淆,混淆后的程序流程图如图10:

1573216442789

图10 虚假控制流操作后的控制流程图

可以看出,混淆后的程序不仅有了更多更复杂的分支,代码块也更加碎片化。图11中是反汇编为C语言后的代码:

1573216604570

图11虚假控制流操作后的反汇编代码

看到具体代码,我们可以发现这里面加了很多的标签(LABEL),还有不少的goto语句,正是这些跳转,使得程序流程更加复杂。而整个while循环和if语句的执行条件,更是加大了逆向分析的难度。

Related post
Comment
Share
  • ACTF2020密码学部分writeup

    编写的项目文件请参考项目链接。同时欢迎大家访问ACTF2020的所有赛题。喜欢的话请多多资瓷一下,给我们实验室的项目加个Star或者Fork,谢谢。 为了保护服务器的同时不给选手带来更多困难,密码学部分的交互题开了pow算力检测,我也...

    ACTF2020密码学部分writeup
  • 通过python脚本自动插入汇编反调试代码

    研究背景在之前OLLVM项目的研究过程中,我们发现反调试技术对反混淆脚本有一定的干扰作用,如果可以在OLLVM的中间代码中自动化插入反调试代码,那么就可以给OLLVM的代码混淆增加一层保障。 方案分析探讨多种方案以后,我认为最适合在汇...

    通过python脚本自动插入汇编反调试代码
  • 基于门限方案的条形码保密及容错技术

    关键词:门限方案,条形码保密,条形码容错,条形码认证与防伪造。 经历过初期两个小项目的探索,我们项目团队积累了一定的项目研究经验,在老师和16级学长的帮助下,我们把研究方向转到了门限方案的实际应用上。结合市面上用9张合并的条形码提高条...

    基于门限方案的条形码保密及容错技术
  • 2020新年原创脚本-其中的小把戏你清楚吗

    关键词:随机数素数生成,新年祝福小程序。 脚本创作这是我在大年三十写的一个程序,当时我正准备去伯克利交流,但由于疫情的缘故,出国变数增大,所以我就打算通过随机数“未卜先知”。以下就是我的脚本: 12345678910111213141...

    2020新年原创脚本-其中的小把戏你清楚吗
  • 基于CRT的物流信息安全处理方案

    关键词:中国剩余定理,密钥分发技术,隐私保护。 引言在2018年11月份的时候,段老师在密码学课上讲到了密钥分发协议,我当时就觉得这个协议很有意思也很有应用前景。后来老师还很主动地分享了一下它的idea,其中一部分就是有关物流单上的信...

    基于CRT的物流信息安全处理方案
  • 基于CRT的新型群文件共享系统

    关键词:隐私保护,权限管理,身份认证,中国剩余定理,密钥分发,密钥更新。 这个项目的是在2019年寒假期间进行的,4月份在中南大学信息安全作品赛答辩,但是由于功能只实现了主体部分,加之我在台上比较胆怯紧张,所以只获得团队三等奖,但是当...

    基于CRT的新型群文件共享系统
  • 安卓反混淆软件探索-deobf

    关键词:代码混淆,代码反混淆及其原理,代码反混淆软件测试与性能对比。 前言我们的大创项目其实是分两方面进行的,一方面,我们从代码混淆的角度比较各种软件对安卓程序的加固能力;另一方面,我们着重针对OLLVM进行反混淆测试。OLLVM集成...

    安卓反混淆软件探索-deobf
  • 记一次安卓代码加固软件的测试过程

    关键词:代码加固,软件测试,原理分析,过程分析。 在大创项目的实践中,我们对市面上的一些安卓代码加固软件进行了采集,经过搜集,发现了几类代码加固方法并分组进行研究。我发现很多代码加固软件都是对java字节码进行混淆与加固,另外一些则选...

    记一次安卓代码加固软件的测试过程
  • 对OLLVM代码加固技术的改进

    1.反静态调试反静态调试可以通过花指令,代码加密,代码加壳等方式实现。 请看图1所示的一段反调试代码: ​ 图1 花指...

    对OLLVM代码加固技术的改进
  • 对音频缓存加密的探讨

    关键词:缓存解密,批量自动执行脚本,版权保护相关建议。 前段时间,某音乐被爆其缓存文件只使用了简单的异或加密,且容易得到加密密钥为0xa3。原文链接点击这里。以下是我的延伸探讨。 1.对音频缓存的批量解密攻击抱着好奇的心理,我把手机...

    对音频缓存加密的探讨
Please check the parameter of comment in config.yml of hexo-theme-Annie!