首页
社区
课程
招聘
[原创]AntiOllvm 去除二进制文件Ollvm混淆并编译回二进制文件
发表于: 2021-6-17 09:53 12597

[原创]AntiOllvm 去除二进制文件Ollvm混淆并编译回二进制文件

2021-6-17 09:53
12597

AntiOllvm去除二进制文件 Ollvm 混淆,并生成新的可执行二进制文件

架构 ELF COFF Mach-O
Arm Yes
Arm64
X86
X86_64
架构 ELF COFF Mach-O
Arm Yes
Arm64
X86
X86_64
  • Ollvm 已经开源很久了,现在市面很多恶意软件都使用它,为了防止分析加壳加混淆基本是必备的。假如一个恶意软件使用某种算法加密了你的文件,并且采用了混淆,如果你要自己解密或者制作解密工具都离不开分析它的算法。而使用混淆后伪代码几乎不可查看,为此你要付出大量的时间和精力去分析。现在网上通用一点的方法有使用 unicorn 模拟执行,还有使用 trace 功能跟踪运行过的代码。
  • 使用 unicorn 模拟执行
    • 虽然可以支持很多架构的运行,但是从汇编层构建出 CFG 还是比较吃力的
    • 具体的分析都对应着直接的汇编指令,再加上多架构这样处理起来非常麻烦
    • 还有修复跳转,补丁指令,在原函数中代码分散,甚至还需要修复指令的重定位
  • 使用 trace 跟踪
    • trace 分析相对较简单,但缺点是你需要在真机上运行
    • 每次运行也不一定会覆盖所有路径
    • 在还原算法或分析时看的是汇编指令,增加分析难度
  • 虽然可以支持很多架构的运行,但是从汇编层构建出 CFG 还是比较吃力的
  • 具体的分析都对应着直接的汇编指令,再加上多架构这样处理起来非常麻烦
  • 还有修复跳转,补丁指令,在原函数中代码分散,甚至还需要修复指令的重定位
  • trace 分析相对较简单,但缺点是你需要在真机上运行
  • 每次运行也不一定会覆盖所有路径
  • 在还原算法或分析时看的是汇编指令,增加分析难度
  • 采用将二进制代码还原为 LLVM IR 的方式,经过各种优化去除混淆后再编译回原文件
  • 采用这种方案优点很多
    • 本身 Ollvm 就是在 LLVM IR 中转换代码然后编译,在还原回 LLVM IR 后能最大限度的还原特征
    • 可以利用现有的 LLVM 中的优化,各种分析也可以查找部分现成的
    • 统一了所有架构的分析,分析方法通用,重建 CFG 非常容易
    • 分析过程更加直观,不接触汇编代码,更容易分析出混淆规则
  • 本身 Ollvm 就是在 LLVM IR 中转换代码然后编译,在还原回 LLVM IR 后能最大限度的还原特征
  • 可以利用现有的 LLVM 中的优化,各种分析也可以查找部分现成的
  • 统一了所有架构的分析,分析方法通用,重建 CFG 非常容易
  • 分析过程更加直观,不接触汇编代码,更容易分析出混淆规则
  • AntiOllvm 使用 retdec 将二进制文件还原为 LLVM IR
  • 使用 LLVM 中的内部优化,将 IR 码优化为较高可读性的代码,这期间部分指令替换以及不可达代码就已经优化掉了
  • 定制 Pass 去除掉函数内部的 虚假控制流和平坦化
  • 最后通过 LLVM 将代码重新编译回汇编并回填文件
  • 等测试稳定会后陆续开放其它架构
  • IDA 插件的开发(需等所有架构开放后)
  • 该项目是收费项目,AntiOllvm仓库只会存放说明文件和一些测试样本的源码和二进制文件
  • 目前还未提供可购买版本,鉴于目前不够稳定,样本量较少,后续稳定后会推出正式可购买版本
  • 欢迎大家提供样本(越复杂越好)到我的邮箱 beichenzhizuoshi@163.com,也可在本仓库提交 issues 附带样本及说明,目前只接受 Arm 架构的 ELF 样本,发送样本时请在标题上注明 二进制架构及文件格式 例如 Arm-ELF 测试样本, 内容上注明被混淆的 函数名称或地址,和你自认为的 混淆难度等级(1-3),我会在去混淆通过后回复你去混淆后的二进制文件
  • AntiOllvm,在这个仓库会公布文档和一些测试的源码以及去混淆后的二进制文件
  • 该样本是使用 openssl 加密库,开启混淆,注意测试与 MD5 算法有关方法 MD5_Updatemd5_block_data_order,样本详细说明可以查看仓库 OpenSSLTest
  • 未混淆和去混淆后的运行对比
    gif
  • 混淆过后的 MD5_Update CFG
    MD5_Update Obf CFG
  • 混淆过后的 md5_block_data_order CFG
    md5_block_data_order Obf CFG
  • 未混淆 MD5_Update CFG 如下:
    MD5_Update CFG
  • 去混淆后 MD5_Update CFG
    MD5_Update AntiObf  CFG
  • 未混淆 md5_block_data_order CFG
    md5_block_data_order CFG
  • 去混淆后 md5_block_data_order CFG
    CFG

    交流反馈

  • 点击AntiOllvm 获取更多信息
  • Ollvm 已经开源很久了,现在市面很多恶意软件都使用它,为了防止分析加壳加混淆基本是必备的。假如一个恶意软件使用某种算法加密了你的文件,并且采用了混淆,如果你要自己解密或者制作解密工具都离不开分析它的算法。而使用混淆后伪代码几乎不可查看,为此你要付出大量的时间和精力去分析。现在网上通用一点的方法有使用 unicorn 模拟执行,还有使用 trace 功能跟踪运行过的代码。
  • 使用 unicorn 模拟执行
    • 虽然可以支持很多架构的运行,但是从汇编层构建出 CFG 还是比较吃力的
    • 具体的分析都对应着直接的汇编指令,再加上多架构这样处理起来非常麻烦
    • 还有修复跳转,补丁指令,在原函数中代码分散,甚至还需要修复指令的重定位
  • 虽然可以支持很多架构的运行,但是从汇编层构建出 CFG 还是比较吃力的
  • 具体的分析都对应着直接的汇编指令,再加上多架构这样处理起来非常麻烦
  • 还有修复跳转,补丁指令,在原函数中代码分散,甚至还需要修复指令的重定位
  • 使用 trace 跟踪
    • trace 分析相对较简单,但缺点是你需要在真机上运行
    • 每次运行也不一定会覆盖所有路径
    • 在还原算法或分析时看的是汇编指令,增加分析难度
  • trace 分析相对较简单,但缺点是你需要在真机上运行
  • 每次运行也不一定会覆盖所有路径
  • 在还原算法或分析时看的是汇编指令,增加分析难度
  • 采用将二进制代码还原为 LLVM IR 的方式,经过各种优化去除混淆后再编译回原文件
  • 采用这种方案优点很多
    • 本身 Ollvm 就是在 LLVM IR 中转换代码然后编译,在还原回 LLVM IR 后能最大限度的还原特征
    • 可以利用现有的 LLVM 中的优化,各种分析也可以查找部分现成的
    • 统一了所有架构的分析,分析方法通用,重建 CFG 非常容易
    • 分析过程更加直观,不接触汇编代码,更容易分析出混淆规则

  • [招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

    收藏
    免费 3
    支持
    分享
    最新回复 (30)
    雪    币: 116
    活跃值: (1012)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    2
    广告?
    2021-6-17 10:44
    0
    雪    币: 8838
    活跃值: (5331)
    能力值: ( LV4,RANK:50 )
    在线值:
    发帖
    回帖
    粉丝
    3
    万里星河 广告?
    自信点,把?去掉。
    2021-6-17 13:56
    0
    雪    币: 5235
    活跃值: (3260)
    能力值: ( LV10,RANK:175 )
    在线值:
    发帖
    回帖
    粉丝
    4
    用retdec反编译的ir优化
    去除ollvm应该是我先在论坛上发的吧
    收费了???
    2021-6-17 19:53
    0
    雪    币: 3442
    活跃值: (2517)
    能力值: ( LV3,RANK:30 )
    在线值:
    发帖
    回帖
    粉丝
    5
    挤蹭菌衣 用retdec反编译的ir优化 去除ollvm应该是我先在论坛上发的吧 收费了???
    你的帖子我也看过,但是我使用的方法跟你完全不一样,你用到了模拟执行,而我目前只是静态分析,不能说我使用retdec就是抄你的吧,样本我也公开了,你可以自己去试试你的方法效果怎样,反正我没试过。再说我添加了很多arm neon指令支持,还有修复各种Bug,回编译,这跟你那个完全没关系吧
    2021-6-17 20:08
    0
    雪    币: 5235
    活跃值: (3260)
    能力值: ( LV10,RANK:175 )
    在线值:
    发帖
    回帖
    粉丝
    6
    北辰制作 你的帖子我也看过,但是我使用的方法跟你完全不一样,你用到了模拟执行,而我目前只是静态分析,不能说我使用retdec就是抄你的吧,样本我也公开了,你可以自己去试试你的方法效果怎样,反正我没试过。再说我添 ...
    大佬能不能放出优化的源码一起技术交流下 我看你这个图是纯去除有源码的平坦化的
    还有能私聊一下这个反混淆值几个钱吗 我也想喝点汤 我这还有个还原vmp的半成品
    最后 我没有模拟执行 那只是方便的叫法 我是纯静态分析跟踪var值变化
    2021-6-17 21:20
    0
    雪    币: 3442
    活跃值: (2517)
    能力值: ( LV3,RANK:30 )
    在线值:
    发帖
    回帖
    粉丝
    7

    你可以加我群私聊,之所以放出有源码的那是不想惹上法律问题

    最后于 2021-6-17 21:28 被北辰制作编辑 ,原因:
    2021-6-17 21:27
    0
    雪    币: 3442
    活跃值: (2517)
    能力值: ( LV3,RANK:30 )
    在线值:
    发帖
    回帖
    粉丝
    8
    挤蹭菌衣 大佬能不能放出优化的源码一起技术交流下 我看你这个图是纯去除有源码的平坦化的 还有能私聊一下这个反混淆值几个钱吗 我也想喝点汤 我这还有个还原vmp的半成品 最后 我没有模拟执行 那只是方便的叫法 ...
    可以加群私聊
    2021-6-17 21:28
    0
    雪    币: 5235
    活跃值: (3260)
    能力值: ( LV10,RANK:175 )
    在线值:
    发帖
    回帖
    粉丝
    9
    北辰制作 可以加群私聊
    群在哪里 没找到点错了不好意思
    2021-6-17 22:02
    0
    雪    币: 3818
    活跃值: (4233)
    能力值: ( LV9,RANK:180 )
    在线值:
    发帖
    回帖
    粉丝
    10

    看起来楼主实现了类似SATURN Software deobfuscation framework based on LLVM的反混淆框架, 自己使用还是很有价值的,但是要难商业化,我觉得还是有点难度:

    • 无法恢复CFG就直接废了,比如我开源的混淆,阿里的混淆,光混淆。
    • 代码混淆加编译器优化后,各种稀奇古怪的case可能非常多,出现问题后,如果工具不能自己完全掌控的话就只能等你处理,等你处理好可能我自己都调试出来了。
    • 回编译后的代码正确性很难保证。比如间接的函数调用(c++虚函数,函数指针等),他们的参数识别基本都是反编译器瞎猜的。一些变长的函数参数(printf),它的参数也不好识别。我的混淆器就可以把直接的函数调用转成间接的。不知道楼主怎么保证函数调用参数是正确的?

    另外还有个疑问,既然已经用RetDec,为啥不直接使用他的反编译器,个人感觉没必要将反混淆的IR再编译回二进制?

    最后于 2021-6-17 22:06 被krash编辑 ,原因:
    2021-6-17 22:06
    0
    雪    币: 2507
    活跃值: (4651)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    11
    只能去ollvm吗?定制的能去不?
    2021-6-17 22:53
    0
    雪    币: 3442
    活跃值: (2517)
    能力值: ( LV3,RANK:30 )
    在线值:
    发帖
    回帖
    粉丝
    12
    krash 看起来楼主实现了类似SATURN Software deobfuscation framework based on LLVM的反混淆框架, 自己使用还是很有价值的,但是要难商业化,我觉得还是有 ...
    编译回二进制的目的是在于可以直接运行,生成二进制文件就可以用于其它工具分析,其实参数的识别我仔细分析过arm的参数,只要你传入的参数>=实际参数,那么多余的参数可以不用管,因为实际函数用不到,大于4个参数写入堆栈是在调用方堆栈上写入到sp正偏移,但是sp的值并没有改变,被调用函数方使用就读取没使用就不用读取,返回后sp还原,因此只要你保证参数大于等于实际参数就可以了。间接调用就把调用函数当作函数指针就行了,至于虚函数反编译后本质就只是偏移,只要保证翻译优化正确那么偏移就会正确,变参函数比如标准库这可以直接拿到函数签名。最后还有人工指定函数参数
    2021-6-17 22:54
    0
    雪    币: 2458
    活跃值: (3333)
    能力值: ( LV6,RANK:90 )
    在线值:
    发帖
    回帖
    粉丝
    13
    krash 看起来楼主实现了类似SATURN Software deobfuscation framework based on LLVM的反混淆框架, 自己使用还是很有价值的,但是要难商业化,我觉得还是有 ...
    你把r0-r3挂到call的use链上就可以了,因为r0-r3穿过call,是会被破坏的,所以编译器原生不信任经过call的r0-r3
    2021-6-17 22:59
    0
    雪    币: 2458
    活跃值: (3333)
    能力值: ( LV6,RANK:90 )
    在线值:
    发帖
    回帖
    粉丝
    14
    北辰制作 编译回二进制的目的是在于可以直接运行,生成二进制文件就可以用于其它工具分析,其实参数的识别我仔细分析过arm的参数,只要你传入的参数>=实际参数,那么多余的参数可以不用管,因为实际函数用不到,大 ...
    你这边内部测试过多少个函数可以写回了?最大测试的函数有多大?
    2021-6-17 23:04
    0
    雪    币: 3442
    活跃值: (2517)
    能力值: ( LV3,RANK:30 )
    在线值:
    发帖
    回帖
    粉丝
    15
    baikaishiu 你这边内部测试过多少个函数可以写回了?最大测试的函数有多大?
    我正在测一个超大函数,论坛上找的样本,且是魔改版的混淆,需要点时间,目前的版本使用正常的ollvm基本上没有问题可以完美还原
    2021-6-17 23:15
    0
    雪    币: 2458
    活跃值: (3333)
    能力值: ( LV6,RANK:90 )
    在线值:
    发帖
    回帖
    粉丝
    16
    北辰制作 我正在测一个超大函数,论坛上找的样本,且是魔改版的混淆,需要点时间,目前的版本使用正常的ollvm基本上没有问题可以完美还原
    超大是多大?我这边现在最大时26K已经写回了,正在尝试32k的,以前的mem-phi实现的有问题,正在重写
    2021-6-17 23:18
    0
    雪    币: 3442
    活跃值: (2517)
    能力值: ( LV3,RANK:30 )
    在线值:
    发帖
    回帖
    粉丝
    17
    baikaishiu 超大是多大?我这边现在最大时26K已经写回了,正在尝试32k的,以前的mem-phi实现的有问题,正在重写
    你也在去混淆?找到一个50多k的,函数大小无所谓,关键是混淆的程度
    2021-6-17 23:34
    0
    雪    币: 2458
    活跃值: (3333)
    能力值: ( LV6,RANK:90 )
    在线值:
    发帖
    回帖
    粉丝
    18

    不是的,体积大小的影响太大了,各种情况覆盖的情况复杂很多。比如,这里有个9K的函数


    看起来时不是挺复杂,但是实际上解起来很简单。


    这个26K的,看起来就一点点,实际上复杂很多:

    这个里面貌似有在做多媒体优化,大量的simd指令,写回去很麻烦。


    这个是我最后转出来的结果15520:

    2021-6-17 23:42
    0
    雪    币: 2458
    活跃值: (3333)
    能力值: ( LV6,RANK:90 )
    在线值:
    发帖
    回帖
    粉丝
    19
    北辰制作 你也在去混淆?找到一个50多k的,函数大小无所谓,关键是混淆的程度
    真正的上超大的,可能是微信的so里面有2个 300k的函数,和一个 3M左右的混淆函数,64K以下的个人感觉还好
    2021-6-17 23:43
    0
    雪    币: 2458
    活跃值: (3333)
    能力值: ( LV6,RANK:90 )
    在线值:
    发帖
    回帖
    粉丝
    20
    北辰制作 你也在去混淆?找到一个50多k的,函数大小无所谓,关键是混淆的程度
    我个人感觉你这套机制有点问题,你太依赖于ret2dec本身的优化了,假如某个变形ollvm,把整个cfg断开了以后,也就是反编译器走不到下一个指令地址,断开了,那么你优化出来就是错的。你必须得先解开整个ollvm,找到下一个反汇编地址才行
    2021-6-17 23:46
    0
    雪    币: 3442
    活跃值: (2517)
    能力值: ( LV3,RANK:30 )
    在线值:
    发帖
    回帖
    粉丝
    21
    baikaishiu 不是的,体积大小的影响太大了,各种情况覆盖的情况复杂很多。比如,这里有个9K的函数看起来时不是挺复杂,但是实际上解起来很简单。这个26K的,看起来就一点点,实际上复杂很多:这个里面貌似有在做多媒体优化 ...
    所以为了支持arm的neon指令我花了大量时间翻译,软件只要做到80%能解就行了,即使解不完全还能正确编译回去也可以
    2021-6-17 23:49
    0
    雪    币: 2458
    活跃值: (3333)
    能力值: ( LV6,RANK:90 )
    在线值:
    发帖
    回帖
    粉丝
    22
    还有个问题,我没用过ret2dec,IDA在转某些较大的函数时,生成的高级语言代码,我感觉是有点问题的,这个不知道是不是我哪里没用对,你的函数就直接优化它们生成的高级语言就不出错?我是完全不敢,只能在cfg上做。
    2021-6-17 23:51
    0
    雪    币: 2458
    活跃值: (3333)
    能力值: ( LV6,RANK:90 )
    在线值:
    发帖
    回帖
    粉丝
    23
    北辰制作 所以为了支持arm的neon指令我花了大量时间翻译,软件只要做到80%能解就行了,即使解不完全还能正确编译回去也可以

    所以你手工把llvm ir转成了arm neon?没有完全用他们的后端?

    llvm ir好像有好几层的(我没用过llvm),hir, mir, lir,你是从哪一层ir开始转汇编的?


    我看你的帖子,其实没有完全看懂

    最后于 2021-6-18 00:00 被baikaishiu编辑 ,原因:
    2021-6-17 23:59
    0
    雪    币: 3442
    活跃值: (2517)
    能力值: ( LV3,RANK:30 )
    在线值:
    发帖
    回帖
    粉丝
    24
    baikaishiu 还有个问题,我没用过ret2dec,IDA在转某些较大的函数时,生成的高级语言代码,我感觉是有点问题的,这个不知道是不是我哪里没用对,你的函数就直接优化它们生成的高级语言就不出错?我是完全不敢,只能在 ...
    如果真有问题那也是IDA的问题,最主要保证翻译和优化正确,那么编译的结果自然正确,翻译的正确性需要详细的每条指令测试,优化的正确使用LLVM内部优化可以信任,其它如retdec的优化本身有许多bug,在非llvm内部优化尽量做到保守,保证其正确性。
    2021-6-18 00:03
    0
    雪    币: 3442
    活跃值: (2517)
    能力值: ( LV3,RANK:30 )
    在线值:
    发帖
    回帖
    粉丝
    25
    baikaishiu 北辰制作 所以为了支持arm的neon指令我花了大量时间翻译,软件只要做到80%能解就行了,即使解不完全还能正确编译回去也可以 所以你手工把ll ...
    是在翻译 arm neon 汇编指令时将其翻译为合法的 llvm ir,编译肯定的是用LLVM的后端,只是要自己处理符号重定位才能回填文件
    2021-6-18 00:15
    0
    游客
    登录 | 注册 方可回帖
    返回
    //