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. Python 控制流代码混淆简介,加大别人分析你代码逻辑和流程难度

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 王平 PS:如有需要Python学习资料的小伙伴可以加点击下方链接自 ...

  5. java中静态代码块详解

    感谢大佬:https://blog.csdn.net/qq_35868412/article/details/89360250 今天在项目中看到这行代码,静态代码块,很久没用静态代码块了,今天来复习一 ...

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

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

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

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

  8. Android 编程下的代码混淆

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

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

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

随机推荐

  1. cpu、内存、raid初识

    计算机基础 1u = 4.45cm dmidecode -s system-product-name 查看linux系统是物理机还是虚拟机 `逻辑CPU个数: cat /proc/cpuinfo | ...

  2. uniGUI for C++ builder之杂七杂八小知识

    uniGUI for C++ builder之杂七杂八小知识 2018年09月30日 22:16:05 中国银行之路在脚下 阅读数:41 标签: uniguibuilder 更多 个人分类: C++ ...

  3. sqlserver 自动创建作业执行备份数据库

    declare @name varchar(250)set @name='I:\dydb_n\dydb_n'+convert(varchar(50),getdate(),112)+ left(righ ...

  4. 曲苑杂坛--DML操作中如何处理那些未提交的数据

    对数据库稍有了解的人,数据库使用排他锁X锁来避免两个事务同时修改同一条数据,同时使用较低级别如行上加锁来提高并发度. 以下了两种场景很容易理解: 1>事务1执行 UPDATE TB1 SET C ...

  5. python网络爬虫抓取网站图片

    本文介绍两种爬取方式: 1.正则表达式 2.bs4解析Html 以下为正则表达式爬虫,面向对象封装后的代码如下: import urllib.request # 用于下载图片 import os im ...

  6. 【NumberValidators】工商营业执照号码和统一社会信用代码验证

    从本质上讲,工商营业执照号码和统一社会信用代码是两套完全不一样的编码规则,识别结果也仅有行政区划部分为两者共有,但因为这两种编码同时存在的原因,所以如果需要在系统中唯一标志一家企业时,还是可以通过工商 ...

  7. Java-String类型的参数传递问题

    刚才看见一个兄弟在为Java的String传值/传引用问题困惑,翻箱倒柜找到了这篇我很久以前写的文章,发在这里,希望能对迷惑的朋友有些帮助. 提要:本文从实现原理的角度上阐述和剖析了:在Java语言中 ...

  8. MariaDB 使用正则匹配查询(7)

    MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可MariaDB的目的是完全兼容MySQL,包括API和命令行,MySQL由于现在闭源了,而能轻松成为MySQ ...

  9. 二进制入门-打造Linux shellcode基础篇

    0x01 前言   本文的目的不是为了介绍如何进行恶意的破坏性活动,而是为了教会你如何去防御此类破坏性活动,以帮助你扩大知识范围,完善自己的技能,如有读者运用本文所学技术从事破坏性活动,本人概不负责. ...

  10. SpringCloud之Fegin

    Fegin是一个声明似的web服务客户端,它使得编写web服务客户端变得更加容易.使用Fegin创建一个接口并对它进行注解.它具有可插拔的注解支持包括Feign注解与JAX-RS注解,Feign还支持 ...