zoukankan      html  css  js  c++  java
  • http://ctf.bugku.com/challenges#Timer(%E9%98%BF%E9%87%8CCTF):Bugku——Timer(阿里CTF)

      做了第一个android apk逆向题,很多工具啥的还没用过,再接再厉。
      找到方法发现这个apk支持的SDK API是15-17,于是就下载了API 16并制作了模拟器,但发现还是运行不起来,不纠结,使用真机成功安装。目前从正向看还没有啥效果,那就从逆向分析代码看功能吧。
      反编译工具JEB。花时间搭上,反编译后发现MainActivity中存在flag字样,那这一块是有关键的功能咯。
      分析下它这儿的代码:
    package net.bluelotus.tomorrow.easyandroid;
     
    import android.os.Bundle;
    import android.os.Handler;
    import android.support.v7.app.AppCompatActivity;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.TextView;
     
    public class MainActivity extends AppCompatActivity {
        int beg;
        int k;
        int now;
        long t;
     
        static {
            System.loadLibrary("lhm");
        }
     
        public MainActivity() {
            super();
            this.beg = (((int)(System.currentTimeMillis() / 1000))) + 200000;
            this.k = 0;
            this.t = 0;
        }
     
        public static boolean is2(int arg4) {
            boolean 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;
        }
     
        protected void onCreate(Bundle arg7) {
            super.onCreate(arg7);
            this.setContentView(0x7F040018);
            View v2 = this.findViewById(0x7F0C0050);
            View v3 = this.findViewById(0x7F0C0051);
            Handler v0 = new Handler();
            v0.postDelayed(new Runnable(((TextView)v3), ((TextView)v2), v0) {
                public void run() {
                    MainActivity.this.t = System.currentTimeMillis();
                    MainActivity.this.now = ((int)(MainActivity.this.t / 1000));  // Int会只保留整数位的数
                    MainActivity.this.t = 1500 - MainActivity.this.t % 1000;  // 存在一种情况,即在200000秒之后,会得到flag
                    this.val$tv2.setText("AliCTF");
                    if(MainActivity.this.beg - MainActivity.this.now <= 0) {
                        this.val$tv1.setText("The flag is:");
                        this.val$tv2.setText("alictf{" + MainActivity.this.stringFromJNI2(MainActivity.this.k) + "}");
                    }
     
                    if(MainActivity.is2(MainActivity.this.beg - MainActivity.this.now)) {
                        MainActivity.this.k += 100;
                    }
                    else {
                        --MainActivity.this.k;
                    }
     
                    this.val$tv1.setText("Time Remaining(s):" + (MainActivity.this.beg - MainActivity.this.now));
                    this.val$handler.postDelayed(((Runnable)this), MainActivity.this.t);
                }
            }, 0);
        }
     
        public boolean onCreateOptionsMenu(Menu arg3) {
            this.getMenuInflater().inflate(0x7F0D0000, arg3);
            return 1;
        }
     
        public boolean onOptionsItemSelected(MenuItem arg3) {
            boolean v1 = arg3.getItemId() == 0x7F0C005F ? true : super.onOptionsItemSelected(arg3);
            return v1;
        }
     
        public native String stringFromJNI2(int arg1) {
        }
    }
      核心的一个函数是postDelayed(),它会划定时间间隔,然后定时地执行此函数的功能。本代码中此函数的功能中表明,如果时间间距MainActivity.this.beg - MainActivity.this.now <= 0,即会得到flag(它主要由MainActivity.this.k决定)。可这个条件满足后,flag中stringFromJNI2的功能逻辑是不可见的。
      因此,接下来分析的步骤应该是搞清楚功能逻辑,编码算出k值,再将它编译进apk中运行获得flag。emmmm,机智。
    1.算出k值
      经过持续地分析功能逻辑,可知初始的时间间距大约是200000秒,并且存在一种情况,就是200000秒后,条件MainActivity.this.beg - MainActivity.this.now <= 0会达到。因此,愉快地编程算出200000秒后的k值吧。
      java编程代码如下:
    package main;
     
    public class main {
     
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            int i;
            int beg= (((int)(System.currentTimeMillis() / 1000))) + 200000;
            int k = 0;
            int now;
            long t = 0;
            boolean b;
            int n=200000;
            for (i=0;i<200000;i++){
                b=is2(n);
                if (b){
                    k+=100;
                }
                else{
                    --k;
                }
                n--;
            }
            System.out.println(k);
        }
        static boolean is2(int n) {
            boolean v1 = true;
            if(n > 3) {
                if(n % 2 != 0 && n % 3 != 0) {
                    int v0 = 5;
                    while(true) {
                        if(v0 * v0 <= n) {
                            if(n % v0 != 0 && n % (v0 + 2) != 0) {
                                v0 += 6;
                                continue;
                            }
     
                            return false;
                        }
                        else {
                            return v1;
                        }
                    }
                }
     
                v1 = false;
            }
            else if(n <= 1) {
                v1 = false;
            }
     
            return v1;
        }
     
    }
      愉快地执行后,可知k为1616384。
    2.将k值写入apk中。
      那个,JEB只能查看反编译后的源码,却不能修改,那怎么办捏?可以使用apktool。
      进入apktool终端,即可看见帮助,简简单单的功能,但实用哦。使用命令apktool d -o C:UserswzDesktop1 C:UserswzDesktop1.apk,将反编译的结果保存到文件1中。出现下图信息,说明反编译成功。
      开始修改咯。该怎么修改捏?
      结合前面的分析可知,已经能够直接得到flag对应的k值了,这样应该让程序顺利地运行到修改好的flag处即可。那么应该有两处修改:(1)逻辑修改(使程序从长时间的循环中跳脱出来);(2)k修改(在flag相关k值最近的地方修改它)
      emmmmm,结合JEB的代码,依照如下图修改即可。咳咳,smali编码不太懂,临时简单弄得哈,意思是直接跳转到输入flag的那段语句里面,并且修改k值为1616384。
      嗯,使用apktool重新编译,命令为apktool b -o C:UserswzDesktop2.apk  C:UserswzDesktop1
      出现如下信息,说明编译成功。
      此时装在手机上运行,还是不行,没有认证,需要对它进行加密签名。java环境本身带着相应的keytool工具。
      首先生成证书。命令为 keytool -genkey -alias demo.keystore -keyalg RSA -validity 40000 -keystore demo.keystore
    其中:
    -genkey 产生证书文件 
    -alias 产生别名 
    -keystore 指定密钥库的.keystore文件中 
    -keyalg 指定密钥的算法,这里指定为RSA(非对称密钥算法) 
    -validity 为证书有效天数,这里我们写的是40000天
    提示信息如下:
    输入keystore密码:
    再次输入新密码:
    您的名字与姓氏是什么? [Unknown]: test
    您的组织单位名称是什么? [Unknown]: test
    您的组织名称是什么? [Unknown]:
    您所在的城市或区域名称是什么? [Unknown]:
    您所在的州或省份名称是什么? [Unknown]:
    该单位的两字母国家代码是什么 [Unknown]:
    CN=test, OU=test, O=Unknown, L=Unknown, ST=Unknown, C=Unknown 正确吗?
    [否]: y
     
    输入<demo.keystore>的主密码 (如果和 keystore 密码相同,按回车):
     
      根据自己情况输入,即生成证书demo.keystore,如下。
      开始签名啦。命令为 jarsigner -verbose -keystore demo.keystore 2.apk demo.keystore
    其中:
    -verbose 指定生成详细输出 
    -keystore 指定数字证书存储路径
      签名成功。如下图所示。
      运行看看,获取到flag,哈哈。
     
  • 相关阅读:
    C++ 字符数组函数与string函数
    std::vector介绍
    DirectX开发环境配置
    基于序列图像的三维体绘的视线投射算法
    关于灰度图和彩色图
    cin函数的一点理解
    两个getline 输入带空格的字符串
    彩色图转灰度图的原理和参考源码
    牛顿迭代法求一个数的平方根
    约瑟夫环问题
  • 原文地址:https://www.cnblogs.com/HYWZ36/p/10297636.html
Copyright © 2011-2022 走看看