0x00  前言

静态反汇编之王,毫无疑问就是Ida pro,大大降低了反汇编工作的门槛,尤其是出色的“F5插件”Hex-Rays可以将汇编代码还原成类似于C语言的伪代码,大大提高了可读性。但个人觉得“F5插件”只能作为一项辅助手段,在结合动态调试和静态分析之后,了解了整个函数的流程再利用F5看“C语言”代码才是最佳的手段。而这篇文章就是学习如何手写”花指令“,来干扰ida的静态分析和”F5插件“。

0x01 反汇编引擎

反汇编引擎就是将二进制程序翻译成了汇编的工具。主流的反汇编算法主要是两种:线性扫描反汇编和递归下降反汇编。

线性扫描算法是将一条指令的结束作为另一条指令的开始,从第一个字节开始,以线性模式扫描整个代码段,逐条反汇编每天指令,直到完成整个代码段的分析。主要优点是可以覆盖程序的所有代码段,但是却没有考虑到代码中可能混有的数据,容易出错。

递归下降算法依据程序的控制流,根据一条指令是否被另一条指令引用来决定是否对其进行反汇编。例如遇见条件跳转指令,反汇编器从true或者false两个分支处选择一个进行反汇编,如果是正常的代码,反汇编器优先选择true分支或者false分支,输出的汇编代码并没有任何区别,但是在遇见人工编码的”花指令“后,同一块代码的两个分支经常会产生不同的反汇编结果。当冲突时,反汇编器会优先选择信任的分支,而大多数面向程序控制流的反汇编器会首先选择false分支。

更多的具体关于反汇编引擎的介绍请参考看雪论坛的文章:

《各种开源引擎,反汇编引擎的对比》 :http://bbs.pediy.com/showthread.php?p=1401094#post1401094

0x02  欺骗“F5” Hex-Rays

简单的”push+ret”组合(和jmp一样)根本不能骗过ida ,很轻易的就被f5还原出了”C语言”。而多出来的memset()函数是f5将编译器自动开辟栈的空间的代码还原了。

我们继续变化,将”push+ret”组合换成另一种形式:

结果令人有点失望,还是被f5直接还原了。

那我们继续修改,向下跳转后再向上跳转,ida会不会以为是循环?

好像是成功了,欺骗了ida的f5。但是稍微看一眼汇编代码就很容易看出这个循环跳转

但通过以上的例子可以总结出ida f5插件的一些特性:

(1)对于jmp指令的分析完全没有问题

(2)“push+ret”指令的组合直接当成jmp处理

(3)向下跳转再向上跳转,会认为是循环

(4)对于手动通过寄存器将值置于栈上的分析能力较弱,但简单的还是可以直接分析出。

之前都是在函数内部跳转,也可以改变跳转的方式,做函数间的长跳转。

而点进去saveregs会发现是这样的

很好,看来又成功欺骗了f5插件。但是读汇编代码会发现

双击进入_next,还是被发现了我们的真正的代码。

0x03  针对反汇编引擎

之前都是用跳转指令来迷惑”F5”插件,那可不可以让运行的结果和ida分析的汇编完全不同呢?这里我们就需要插入一些机器码来迷惑反汇编引擎,比如经常会用到在代码中间插入一些数据,让ida无法对数据和代码进行有效的区别,最普通的就是0xE8,因为这是call指令的第一个字节。

当”f5”还原时,弹出对话框,显示无法”Decompilation”。

反汇编的结果显示将0xE8作为call指令的第一个字节解释,然后成为了一个call指令,但是ida已经标注出为红色了,有经验的人一看就知道这块代码是被”加花”了的.

主要这里的xor eax , eax 和jz这两句,这本就是个跳转,为什么不直接写成jmp呢?因为之前说到过的面向控制流的反汇编引擎的策略是遇见jmp直接跳转,0xe8就会就被识别,这里人为的写成“条件跳转”,以此来达到混淆的目的。机器码的插入方法有很多,但一些机器码既可以作为前一条指令的结尾,又可以作为下条指令的开始,比如说刚刚的e8指令,尽量不要用在CPU可以执行的地方,不然很容易让程序崩溃。我们可以来看稍微复杂的指令插入

可以看到ida的分析结果有点令人失望,”f5”之后也没什么用。

我们可以借助更多的机器码达到欺骗ida的目的

反汇编的汇编代码:

这里ida将0x66 0xb8识别为mov指令的前两个字节了,然后导致之后的分析错误。而在0xe8的中间还可以加入大量的其它花指令。

0x04 SEH

SEH 结构化异常处理,这里就不多做介绍了,可以阅读之前的文章Windows x86 SEH 学习,需要说明的是编译器实现的SEH和普通的不一样。

0x05  破坏栈帧分析

Ida试图分析一个函数来确定其栈帧结构,特别是遇到ret/retn就认为到达一个函数结尾,因此很容易伪造栈帧来阻止静态分析。给之前的代码加上一个ret 0xff

Ida f5 的结果,认为有63个参数。

还有就是在函数中改变esp的值:比如说这里的"cmp esp,0x1000",后面的"add esp , 0x102"是永远不会执行的,在这里可以改变esp,也可以做其他的很多混淆手段。

最后f5显示栈帧已经被破坏了,是不是很熟悉,和之前在函数中调用pop,eax的结果一样,都显示栈帧已经被破坏了。

0x06 小结

列举了非常基本的几种针对ida 和 f5插件的混淆代码,虽然很基础,但是可以将非常非常多的混淆代码进行叠加,形成庞大的”花指令”,花指令的目的就是增加分析的成本。编写混淆代码最重要的一点就是堆栈平衡。如果对于代码混淆,保护做更进一步学习,可以加入GitHub上的开源项目 WProtect 利用”虚拟机技术”来保护代码,也可以学习LLVM相关的知识,利用LLVM IR来保护代码。关于汇编的分析,个人还是觉得不能太依靠ida和Hex-Rays插件,要自己先动态走一遍流程,熟悉整个框架以后再借助ida 和"F5"插件来提高效率。

参考资料:

《IDA Pro 权威指南》

《恶意代码分析实战》

《加密与解密》

Windows x86 下的 静态代码混淆的更多相关文章

  1. Windows环境下应用Java代码操作Linux资源

    >>>>>>>>>>>>>>>>>>>>>>>>> ...

  2. 去除Windows平台下每行代码的“^m”

    有时在Windows里编写好的shell脚本放到Linux里不能运行了,打开编辑器显示正常,结果用vim打开发现每一行末尾都有^m,于是搜了一下解决办法. Windows上写好的文件,在Linux或者 ...

  3. android 常用第三方包的代码混淆

    首先在:project.properties 文件下,启动代码混淆 proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:pro ...

  4. Linux下编译静态MinGW环境,编译windows平台Qt程序(使用MXE)

    参考链接: MXE.>大多数程序都是在windows平台下开发的程序.windows 在现实中也是绕不过的一个系统平台,做为受过几年VC,MFC”虐待”的程序员,在做为一个程序员之前是一位Lin ...

  5. Qt5.8 在windows下mingw静态编译

    官方对编译一些条件介绍:https://doc.qt.io/qt-5/windows-requirements.html 在默认情况下,用QtCreator编译程序时,使用的是动态编译.编译好的程序在 ...

  6. Android 编程下的代码混淆

    什么是代码混淆 Java 是一种跨平台的.解释型语言,Java 源代码编译成中间”字节码”存储于 class 文件中.由于跨平台的需要,Java 字节码中包括了很多源代码信息,如变量名.方法名,并且通 ...

  7. Android Studio环境下代码混淆+签名打包

    Android Studio环境下代码混淆+签名打包 作者 Mr_冯先生 关注 2016.08.21 01:10 字数 1040 阅读 734评论 5喜欢 34 注:本文使用的Android Stud ...

  8. windows环境下使用git客户端、github和tortoisegit管理项目代码

    一.为什么 为什么不用svn? svn是一个优秀的代码和版本管理工具,使用svn只需要搭建好svn中央仓库,配置本地svn客户端即可,自从google code关闭服务之后,互联网上已经没有非常好的公 ...

  9. 【转】Android 编程下的代码混淆

    什么是代码混淆 代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为.代码混淆可以用于程序源代码,也可以用于程序编译而成的中 ...

随机推荐

  1. Linux权限

    在Linux中要修改一个文件夹或文件的权限我们需要用到linux chmod命令来做,下面我写了几个简单的实例大家可参考一下. 语法如下: chmod [who] [+ | - | =] [mode] ...

  2. JavaScript-冒泡排序

    随机生成10个不重复的100以内的整数放入数组,并排序后进行打印<br /> 如: for(var i=0;i<9;i++) { for(var j=i+1;j<9;j++) ...

  3. 也谈SSO,一个简单实用的单点登录Demo

    关于SSO(单点登录),百度百科解释如下 : “SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次主要 ...

  4. 忽然想到,为什么以前iOS的工资高

    听说做iOS的在上海工资也可以  前几年还行,现在也不太行了除非你水平很高 现在移动应用已经100多万了,基本饱和了以前是新的商业模式要抢时间,会的人也少

  5. Akka(16): 持久化模式:PersistentFSM-可以自动修复的状态机器

    前面我们讨论过FSM,一种专门为维护内部状态而设计的Actor,它的特点是一套特殊的DSL能很方便地进行状态转换.FSM的状态转换模式特别适合对应现实中的业务流程,因为它那套DSL可以更形象的描述业务 ...

  6. 为什么很多第三方接口,都改成了基于http,直接传递json数据的方式来代替webservice?

    这实际上是三个问题,从WebService到今天流行的RESTful API(JSON) over HTTP,经历了数次变革 1 WebService有很多协议,为什么HTTP比较流行? WebSer ...

  7. Java并发之CyclicBarrier工具类

    一.CyclicBarrier工具类介绍 在上一篇文中我们介绍到了CountDownLatch工具类,其实CyclicBarrier和CountDownLatch工具类实现的功能差不多.我们可以从字面 ...

  8. oracle创建dblink的脚本

    创建dblink的脚本 create public database link wsbsbb_27(dblink名字) connect to wsbsbb(用户名) IDENTIFIED BY wsb ...

  9. Java线程池相关类-Executor框架

    1.Executor 接口源码: public interface Executor { /** * Executes the given command at some time in the fu ...

  10. JavaWeb项目中文乱码问题

    1.从浏览器读数据乱码(post 请求方式) 前提是前端页面是UTF-8编码,因为服务器端默认采用ISO解码,所以乱码,在读取前加上: request.setCharacterEncoding(&qu ...