coder-jay@home:~$

逆向工程入门简述

从一个逆向小白的正向工程师转向逆向工程的学习之旅

前言

在写这片文章时,本人入坑逆向也没有多久,作为小白,文章重点探讨小白入门的一些基本要点,如有大佬翻牌,还望多指点。

本文仅作为学习交流,请勿用作非法用途。

什么是逆向? 通俗来讲,逆向工程就是将机器才能够懂的机器代码(0101二进制代码)翻译成人能够读懂的代码(汇编、smali代码)。 但实际情况往往是,我们只寻找关键的代码去翻译或仅了解其业务逻辑,因为要将所有的机器代码翻译出来,工作量是极其巨大的且繁琐的。

本人原本是做Android开发的,所以最早接触的是Android APK的逆向,在没有涉及到JNI代码的APK中,逆向也相对容易一些。 但是很多应用开发者会比较注重代码安全,一些关键代码使用JNI的方式实现,来增加逆向难度,但仅仅是增加了难度,并不能阻挡reverse engineer的脚步。

汇编语言之于逆向工程

掌握汇编语言是学会逆向的充分必要条件,汇编语言基本上是最接近机器代码的编程语音了,基本上所有的逆向工具都是先将二进制文件反汇编成汇编代码,供给逆向工程师分析(Java语言也是类似,可以认为smali代码是面向JVM的机器代码)。

在分析汇编语言时,会比较枯燥,我们往往不需要一行一行的仔细去分析,只需要关注一些关键的代码即可,理出代码片段的大致思路然后再着重分析关键代码即可; 也可以借助工具(如IDA Pro,Hopper Disassembler),将汇编代码转换成C的伪代码,这样分析起来效率会更高。

逆向工具

  • IDA Pro:逆向工程师的灵魂,功能强大,自行体会。
  • Hopper Disassembler:功能和IDA类似,不如IDA强大,但价格比IDA便宜太多,对objective-c支持更友好。
  • apktool:Android APK反编译工具。
  • dex2jar:dex文件转jar工具。
  • JD-GUI:直接jar反编译成Java代码浏览。
  • Android Studio:smali代码浏览,Android APK断点debug。
  • Charles/Flidder、Wireshark:网络抓包工具。
  • UltraEdit: 查看、修改二进制文件等。

逆向的分类

逆向工程按照编程语言类别,可以分为:

  • 解释型语言的逆向(如Android APP)
  • 编译型语言的逆向(如C/C++、Objective-C)

解释型语言(如Java)的运行环境是JVM之类的虚拟机,其反编译的难度通常较低。以Java语言为例,编译器编译的结果通常是.class或者.dex文件,在没有做代码混淆的情况下,很容易反汇编出Java源码,分析出代码逻辑。而且混淆也只是将类、方法、变量名称替换成a b c d这种没有任何意义的名字,增加理解难度而已。

编译型语言(如C/C++,Objective-C等)最终编译出来的机器代码就比较复杂,因为其机器代码是跟CPU架构相关的,因此针对不同的CPU架构编译出来的二进制文件是不同的,反汇编得到的代码也会不一样。往往需要针对特定的CPU架构去解读汇编语言,才能正确的分析出结果出来,这就需要对不同架构CPU的寄存器、寻址方式等特性有所了解才行。另外二进制文件反汇编出来的函数、变量名通常是机器生成的无意义字符串,所以分析难度通常相较于解释型语言会更大一些。

分析手段

常用的分析手段有以下三种:

  1. 静态分析
  2. 动态分析
  3. 网络流量分析
  4. 【你没有看错】

在做逆向的时候,通常需要根据需要被分析的程序特点,选择一种或者多种手段结合使用,来达到最佳效果。

静态分析

将机器代码反汇编成方便人类理解的代码,如smali代码(Java)、汇编代码或汇编代码翻译的C语言伪代码等等,通过分析这些比较低级的编程语言的代码,找到程序的业务流程或设计逻辑。

动态分析

通过断点调试手段,让程序单步执行进行分析。动态分析往往是在静态分析出一定的结果的基础上进行,找到合适的地方给代码打断点,即时地读取当前变量的值,来进一步分析程序的逻辑、获取程序关系数据。

网络流量分析

通过代理方式或者其他方式,截取程序与服务器通信的数据流量(抓包),来分析客户端和服务端的通信协议。网络流量分析比较有局限性,若客户端使用Http这种明文传输的协议,会比较容易分析;但如果客户端使用SSL、Https等加密传输协议与服务端进行通信,那么抓包的前提是需要拿到服务端下发给客户端的证书才能进一步解密分析,这种情况下就比较棘手。网上有方案通过安装插件拿到Chrome或者Firefox浏览器的本地证书,但只适用于客户端是网页的情况。若其他大佬有好的宝贵经验,还望能指点迷津。

正如上文所提到的分析汇编代码,往往不需要所有代码都逐行逐句都分析,其实不仅仅是分析汇编,我们在逆向分析所有代码(汇编、smali、C伪代码)时,以上三种分析手段往往只用在分析一些关键的、主干思路代码。很多时候,一些不重要的、通用写法的代码,就需要凭借自己点编程经验猜测了,提高逆向分析效率。

猜测的前提是,你需要有一定的编程经验,能够在逆向分析出一些代码后,对其上下的代码进行合理的推测,推测不出来的代码再通过以上手段分析。可以这么说,你的推测能力决定了你的逆向分析效率,而编程经验则是你猜测能力的基石。


详细章节