shavchen 发表于 2019-4-10 21:29

BugkuCTF逆向题目05 - [阿里Timer]

本帖最后由 shavchen 于 2019-4-10 22:09 编辑

## 题目下载
下载链接
`https://pan.baidu.com/s/1vIU3YKmXo0fnBm4rSciT8g`   

密码: i1py

## 题目分析
- 在安卓模拟器上运行程序
    ![流程.png](https://i.loli.net/2019/04/10/5cadadbc74e63.png)
- 程序流程
    > 提示信息
    >> Time remaining(s):200000
    >> AliCTF{}
    >   
    > 初步分析
    >> 应该是200000秒之后才会出现flag
    >> 下一步使用安卓调试神器jeb进一步分析      

## JEB分析
- JEB介绍
    > JEB:IDA+111=JEB,JEB相当于Windows平台上的IDA
    >
    > smali代码:双击Bytecode,出现smali代码;相较于C之汇编,则smali之于Java
    >> !(https://i.loli.net/2019/04/10/5cadb2004a6b6.png)
    >>
    >> (https://blog.csdn.net/cloverjf/article/details/78613830)
    >   
    > 快捷键:按`q`切换到java伪代码
- 进入android程序入口类
    - 进入方式

      `Bytecode/Hierarchy-net-tomorrow-MainActivity`

      ![入口类.png](https://i.loli.net/2019/04/10/5cadb2004c374.png)

      !(https://i.loli.net/2019/04/10/5cadb33e04764.png)
      > 双击左边的Bytecode默认进入的就是此入口类

    - 按 `Q` 查看java伪代码

      ![伪代码.png](https://i.loli.net/2019/04/10/5cadb3f5df43e.png)

    - 查看onCreate函数
      > 一个activity启动回调的第一个函数就是onCreate,这个函数主要做这个activity启动的一些必要的初始化的工作。
      >
      > onCreate之后调用了还有onRestart()和onStart()等。
      
      ![注释onCreate.png](https://i.loli.net/2019/04/10/5cadc40677139.png)

    -查看onCreate回调的MainActivity函数
      ```java
      public MainActivity() {
      super();
      this.beg = (((int)>(System.currentTimeMillis() / 1000))) + 200000;
         //当前时间(beg)为200000加上当前时间(s)   
      this.k = 0;   
         //k初始化为0,和onCreate函数中的flag字符串存在联系
      this.t = 0;
      }
      ```
      
    - 查看onCreate回调的is2函数

      !(https://i.loli.net/2019/04/10/5cadc494aef1e.png)

## 编写脚本
- 由于md渲染问题,代码放于文末

- 运行结果

    `k=1616384`

## Android Killer修改并打包源程序
- 进入入口类

    ![载入程序.png](https://i.loli.net/2019/04/10/5cadd09e36dc6.png)

- 搜索字符串 `AliCTF`

    !(https://i.loli.net/2019/04/10/5cadd1383063a.png)

    ![搜索字符串.png](https://i.loli.net/2019/04/10/5cadd1a7a01b0.png)

- 定位到变量 `k`
    > 搜索`stringFromJNI2`
    >
    > !(https://i.loli.net/2019/04/10/5cadd332ec48c.png)
    >> 上一条句把k存放在寄存器`v3`中,下面修改v3,就可以修改k
    >> 寄存器用v开头数字结尾的符号来表示,如v0、v1、v2、...

- 修改变量k的值
    > `const v3;1616384`
    >
    > ![修改变量k.png](https://i.loli.net/2019/04/10/5cadd3f6dfb97.png)

- 理一理思路
    > 这里我把`k`的值设置为正确的值,即执行200000次后会出现的值了
    >
    >但是因为if条件判断为假,程序还是会执行200000次,才会输出flag
    >
    > 这里就需要把`<=`改为`>`
    >> 搜索`<=`附近的字符串`AliCTF`

- 修改if判断条件

    ![反过来了.png](https://i.loli.net/2019/04/10/5cadd86d23ea4.png)
    > 发现这里是反过来的,下一步把 `>` 改成 `<=`
    >
    > 将`if-gtz v0, :cond_0`修改为`if-lez v0, :cond_0`
    >> ![小于.png](https://i.loli.net/2019/04/10/5cadd8f83b3c1.png)

- 编译打包程序
    > 在编译的时候遇到以下问题
      >>Project\res\values-v23\styles.xml:6: error: Error retrieving parent for item: No resource found that matches the given name '@android:style/WindowTitleBackground'.
      >>
      >>Project\res\values-v23\styles.xml:6: error: Error retrieving parent for item: No resource found that matches the given name '@android:style/WindowTitleBackground'.

- 解决方法
    > 找到res/value-v23/styles.xml,把resources下的东西注释掉
   ```xml
   <?xml version="1.0" encoding="utf-8"?>
    <resources>
      <!--
      ...
      -->
    </resources>
   ```
   > 找到res/value/public.xml,把所有带Base.V23的东西(两个)注释掉
   ```xml
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
      <!--
      ...
      -->
    </resources>
   ```

- 重新编译打包

    ![编译成功.png](https://i.loli.net/2019/04/10/5cadeb314bca4.png)

## 模拟器载入新安装包
- 成功获取flag

    !(https://i.loli.net/2019/04/10/5cadebc91d750.png)

- flag
    `flag{Y0vAr3TimerMa3te7}`

## 总结
- 环境问题
    > Android Killer编译apk始终失败
    >> 通过换jdk7以及修改res/xml成功编译
    >
    > 运行Jeb闪退
    >> 修改jeb_winos.bat,替换java版本   
    >> !(https://i.loli.net/2019/04/10/5cadee07e601d.png)

- 技术问题
    > 不懂smati语言,但是Jeb和AK自身的伪代码转义功能较强,还是可以看懂程序流程
    >
    > 下来需要潜心学习smati语法
    >
    > 本例程序代码量很少,遇到大型程序不会这么简单

## 代码部分
```c
#include <iostream>
using namespace std;
bool is2(int arg4)
{
      bool v1 = true;
      if(arg4 > 3)
      {
            if(arg4 % 2 != 0 && arg4 % 3 != 0)
            {
                int v0 = 5;
                while(true)
                {
                  if(v0 * v0 <= arg4)
                  {
                        if(arg4 % v0 != 0 && arg4 % (v0 + 2) != 0)
                        {
                            v0 += 6;
                            continue;
                        }
                        return false;
                  }
                  else
                        return v1;
                }
                return false;
            }
            v1 = false;
      }
      else if(arg4 <= 1)
            v1 = false;
      return v1;
}

int main()
{
    int time = 200000;
    int k = 0;
    while(time > 0)
    {
      if(is2(time))
                k+=100;
      else
                k--;
      time--;
    }
    cout << "k=" << k << endl ;
    return 0;
}
```

3432872 发表于 2019-4-10 21:35

学习了 非常有用

ts0001 发表于 2019-4-11 13:20

感谢分享,留存备用、谢谢!

cdevil 发表于 2019-4-11 18:52

学习了,其实楼主可以直接把时间的调用改成变量就可以了,然后去掉延时即可,让程序自己算出来

shavchen 发表于 2019-4-11 19:55

cdevil 发表于 2019-4-11 18:52
学习了,其实楼主可以直接把时间的调用改成变量就可以了,然后去掉延时即可,让程序自己算出来

你说的去掉延时是指干掉200000次的循环吗?
必须用循环200000次之后的变量k的值,才能算出最后的flag字符串呀

bakasonic 发表于 2019-4-11 20:03

感谢分享,留存备用、谢谢!

左神 发表于 2019-4-12 09:27

感谢分享,留存备用、谢谢!

cdevil 发表于 2019-4-13 10:05

shavchen 发表于 2019-4-11 19:55
你说的去掉延时是指干掉200000次的循环吗?
必须用循环200000次之后的变量k的值,才能算出最后的flag字 ...

不是啊,修改smali代码,全部用int型的变量替代时间类型的变量

shavchen 发表于 2019-4-14 21:01

shavchen 发表于 2019-4-11 19:55
你说的去掉延时是指干掉200000次的循环吗?
必须用循环200000次之后的变量k的值,才能算出最后的flag字 ...

懂你的意思了,用简单的循环替换时间变量相减的过程,让程序自己算出k的值,自动计算出flag
其实思路都差不太多吧

'醉清风' 发表于 2019-7-30 14:21

膜拜大佬
页: [1]
查看完整版本: BugkuCTF逆向题目05 - [阿里Timer]