逆向工程实验大作业——bugku-逆向-8、LoopAndLoop(阿里CTF、Android逆向)

LoopAndLoop(阿里CTF)

实验用到的四个代码都可以在我的Github上下载:https://github.com/OnlyLegends/Bugku–CTF-/tree/master/逆向类CTF

[LoopAndLoop]

The friendship between native and dex.

下载LoopAndLoop.apk在安卓模拟器中打开:

题目要求输入一串数字,随便输入字符串abc时会显示:Not a Valid Integer number。
在这里插入图片描述
随便输入数字123,显示错误:Not Right!
在这里插入图片描述

所以程序应该是让我们输入某串数字。

下面开始逆向LoopAndLoop(阿里CTF).apk:先解压缩,得到它的一些配置文件:
在这里插入图片描述

然后用dex2jar将classes.dex反编译成jar包:d2j-dex2jar.bat classes.dex
在这里插入图片描述

再用jd-gui将jar包打开,看到主要部分代码为:

在这里插入图片描述

通过对输入的字符串int i = Integer.parseInt(paramAnonymousView)转换成数字。

  1. 分析OnClick方法。

    1、try-catch

NumberFormatException为数字格式异常,当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常。故若在apk输入有数字外的字符,程序捕获该异常,输出"Not a Valid Integer number"信息。

2、if-else

对check(i,99)==1835996258进行判断,若满足条件通过MainActivity.this.stringFromJNI2(i)函数输出flag,否则输出"Not Right!"。

所以我们在这无法去修改if跳转,因为输出的flag是与取决于输入的数字,所以我们只能找到正确的数字,那么关键就是check函数了。

2)分析check方法

check方法中调用了native层的原生函数chec,另外还有check1,check2,check3方法也调用了chec函数。

在这里插入图片描述

Android架构分为5层:

在这里插入图片描述

1、Applications(核心应用程序):Java应用程序基本可以理解为各个App,由Java语言实现。

2、Java API Framework(开发框架包 ):Java框架层(系统服务)就是常说的Framework,我们编写的Android代码之所以能够正常识别和动作,都要依赖这一层的支持。这一层也是由Java语言实现。

3、Android运行环境或者是Native c/c++ 核心库):这部分常见一些本地服务和一些链接库等。这一层的一个特点就是通过C和C++语言实现。比如我们现在要执行一个复杂运算,如果通过java代码去实现,那么效率会非常低,此时可以选择通过C或C++代码去实现,然后和我们上层的Java代码通信(这部分在android中称为jni机制)。又比如我们的设备需要运行,那么必然要和底层的硬件驱动交互,也要通过Native层。

4、Hardware Abstraction Layer(硬件抽象层)

5、Linux Kernel(Linux内核)

所以在这里,这个app层的apk文件调用了Native层的库函数。

在这里插入图片描述

在这里插入图片描述

对本地方法的加载通过 System.loadLibrary 方法实现,System.loadLibrary 的参数是程序员任意选取的库名,这里是"lhm"。

在这里插入图片描述

之后我们在apk的配置文件lib/armeabi目录下找到了调用的库liblhm.so:
在这里插入图片描述

因为它是C/C++语言编写的,所以我们可以用IDA把它打开:

在这里插入图片描述

代码的关键部分:

在这里插入图片描述

在这里插入图片描述

上面chec(a1,a2,a3,a4)方法的前两个参数a1为JNI接口指针和a2为对对象和Java类的引用,是默认的,后两个参数a3和a4即为Java层参数i和99。

GetMethodID与CallIntMethod方法:

  1. jmethodID GetMethodID(JNIEnv *env, jclass clazz,const char *name, const char *sig); 获取一个Java方法的ID,这个函数将返回非静态类或接口实例方法的方法 ID。这里是获得了check1、check2、check3的ID。

  2. CallIntMethod:通过jmethodID调用的返回值为int的java方法。

但是这里的代码遇到了一个IDA的F5优化问题:由于Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec是一个JNI函数,我们在JNI开发的过程中知道第一个参数为JNIEnv*,第二个参数为jobject类型。JNI函数可能出现问题,导致我的IDA的F5优化后的代码为:

在这里插入图片描述

而实际上网上其他人的代码为:

在这里插入图片描述

这里不知是我的IDA的版本还是F5优化的问题,导致后面的v7,v8-1被IDA的F5反编译认为是没有意义的变量优化掉了。参考:

https://blog.csdn.net/feibabeibei_beibei/article/details/52733249

https://www.cnblogs.com/gm-201705/p/9863956.html

之后开始修改CallIntMethod的参数个数,先单击进入CallIntMethod函数查看:

在这里插入图片描述

发现它原本就是有四个参数的,而之前F5反编译出来的代码之后三个,再返回原chec函数查看:
在这里插入图片描述

我们只是查看了一下CallIntMethod函数再返回,它竟然就又反编译出了第四个参数v7。。。可能IDA的F5反编译优化在反编译JNI函数时真的可能出现问题。

加上第五个参数的方法:可以右击CallIntMethod函数选择Set item type或按快捷键Y即可编辑函数名及其参数:

在这里插入图片描述

点击OK之后第五个参数也出现了:

在这里插入图片描述

再查看CallIntMethod函数:

在这里插入图片描述

的确有了int a5这个参数。

那我们给它加个a6会怎样呢?

在这里插入图片描述

在这里插入图片描述

依旧显示出来了,但是代码变量名发生了一些变化,除此之外对函数没有什么影响了。后面再加a7也是没有逻辑算法上的影响了。所以CallIntMethod函数应该就是在5个参数的时候有意义。

另外:其实GetMethodID函数只有一个参数,但它开始反编译的结果确有四个参数:

在这里插入图片描述

在这里插入图片描述

再返回去看,有变成了一个参数:

在这里插入图片描述

看来,这里的IDA的F5反编译优化真的有点问题。

0x03

程序算法分析

言归正传,我们继续逆向,其实代码到了这,我们已经能看懂chec函数的主要算法了:

在这里插入图片描述

可以看到具体流程就是:根据CallIntMethod函数的第三个个参数*(&v10 + 2 * v8 % 3)的值来选择回调哪个Java函数:check(1、2、3)。

满足check(i,99)==1835996258即可得到flag,i为apk中输入的数值大小,check为native层的原生函数,功能是根据传入check的第二个参数k*2%3值选择回调Java层三个方法中的一个,check1,check2,check3都是对i值进行改变,分析知check最后返回的值也是i,满足最终的i等于1835996258即可,传入的99在check中每次会减1,check函数的终止条件即为减到2。

所以我们有了两种思路,1是进行算法求逆,将所有函数逆向,从最后的结果1835996258算出开始输入的数字串。2是进行暴力破解,从0逐个开始带入算法计算,直到某个数字算出的结果等于1835996258。

流程图如下:

在这里插入图片描述

0x04

解题脚本

方法1、进行算法求逆:

写脚本需要注意的细节是在对check2方法的求逆的时候,if的判断条件为(num-1)%2==0,不要忘记减去1,因为native层check函数传给Java层方法的第二个参数减去1了。

源代码:
LoopAndLoop.py

运行结果截图:

在这里插入图片描述

算出最初输入的数字串为:236492408。将它输入开始的Android应用:

在这里插入图片描述

Flag为:alictf{Jan6N100p3r}

方法2、进行暴力破解

到这里就已经很简单了,仅需对该程序进行爆破就好,先说说我刚开始踩的一个坑,一开始我为了移植方便,直接用Java写的爆破程序,代码如下:
LoopAndLoop.java

但是由于Java的速度不高,而且主要原因是这段代码的时间复杂度本身就非常大,Java不支持代码优化,所以半个小时都没跑完一轮。

在这里插入图片描述

之后我就用C语言重新写了一遍:

LoopAndLoop.c

代码优化很重要,不开启的话即使是C语言也快不到哪里去,不开启在Windows下跑,依旧跑不出来:

在这里插入图片描述

在Linux下运行并开启了代码优化,正是因为代码优化所以编译出来的程序时间复杂度就缩小了很多,我用gcc编译的,编译的时候开启了-O3(最高优化),结果如下:

在这里插入图片描述

用了54秒跑出了结果,就是236492408,输入结果即可得到flag。

为了更加快速的进行的爆破了,我还写了一个多线程版本的,兼容Windows和Linux,还要一件事,具体的线程数还要看看自己的机器,代码如下:

LoopAndLoop_thread.c

在这里插入图片描述
加了10条线程基本可以在20多秒跑出结果。

实验用到的四个代码都可以在我的Github上下载:https://github.com/OnlyLegends/Bugku–CTF-/tree/master/逆向类CTF

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
逆向工程是指通过逆向分析已有软件的代码和结构,从中获取信息并了解其功能和设计思路的过程。而IDA(Interactive DisAssembler)是逆向工程过程中常用的工具之一,它能够将二进制程序文件或动态链接库文件转换为汇编代码,以方便分析和理解。 逆向工程CTF(Capture The Flag)比赛中,参赛者需要通过逆向工程手段来获取隐藏在某个程序或应用中的标志(flag),常以此为目标进行竞赛。而IDA被广泛用作CTF逆向工程比赛的关键工具之一,主要用于分析并理解被逆向的程序。 通过IDA,参赛者可以加载二进制文件,然后通过静态或动态分析的方法获取程序的结构和逻辑。IDA提供友好的界面,能够将二进制代码转换为易于阅读和理解的汇编代码,并提供多种各类的分析功能,例如交叉引用分析、函数分析、字符串分析、结构和类分析等。这些功能使得解析程序的逻辑和功能变得更加方便和高效。 在逆向工程CTF中,参赛者需要运用IDA的各种功能,结合代码和结构分析,找出隐藏的标志(flag)。这个过程需要具备较强的程序分析能力和逻辑推理能力,同时对底层汇编语言和常见算法有一定了解。 综上所述,IDA作为逆向工程的重要工具,在逆向工程CTF中发挥着重要作用,通过IDA的使用,参赛者可以分析和理解不同程序的结构和逻辑,进而找到隐藏的标志(flag)以完成比赛的任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值