18/09/24-1-BugKu-逆向-LoopAndLoop(阿里CTF)
Posted fingerprint
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了18/09/24-1-BugKu-逆向-LoopAndLoop(阿里CTF)相关的知识,希望对你有一定的参考价值。
---恢复内容开始---
0x00
题目链接:https://pan.baidu.com/s/1boi4DX2Dp9-6cel0Q0KeHw 密码:jmgf
0x01
下载压缩包并解压得到apk,安装并打开apk。
尝试输入,若只输入数字,弹出“Not Right!”,若输入带有除数字外的字符,弹出“Not a Valid Integer number”。
0x02
使用jeb2反编译apk,找到核心算法区域反编译得到java源码进行分析。
1)`分析OnClick方法。
a.try-catch
NumberFormatException为数字格式异常,当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常。故若在apk输入有数字外的字符,程序捕获该异常,弹出“Not a Valid Integer number”信息。
b.if-else
对check(v1,99)==1835996258进行判断,若满足条件弹出flag,否则弹出“Not Right”。
1 public void onClick(View arg7) { 2 int v1; 3 String v2 = this.val$ed.getText().toString(); 4 try { 5 v1 = Integer.parseInt(v2); 6 } 7 catch(NumberFormatException v0) { 8 this.val$tv1.setText("Not a Valid Integer number"); 9 return; 10 } 11 12 if(MainActivity.this.check(v1, 99) == 1835996258) { 13 this.val$tv1.setText("The flag is:"); 14 this.val$tv2.setText("alictf{" + MainActivity.this.stringFromJNI2(v1) + "}"); 15 } 16 else { 17 this.val$tv1.setText("Not Right!"); 18 } 19 } 20 });
2)分析check方法
a.check方法为native层的原生函数,另外还有check1,check2,check3方法。
1 public MainActivity() { 2 super(); 3 } 4 5 public native int chec(int arg1, int arg2) { 6 } 7 8 public int check(int arg2, int arg3) { 9 return this.chec(arg2, arg3); 10 } 11 12 public int check1(int arg4, int arg5) { 13 int v1 = arg4; 14 int v0; 15 for(v0 = 1; v0 < 100; ++v0) { 16 v1 += v0; 17 } 18 19 return this.chec(v1, arg5); 20 } 21 22 public int check2(int arg5, int arg6) { 23 int v2; 24 int v3 = 1000; 25 int v1 = arg5; 26 if(arg6 % 2 == 0) { 27 int v0; 28 for(v0 = 1; v0 < v3; ++v0) { 29 v1 += v0; 30 } 31 32 v2 = this.chec(v1, arg6); 33 } 34 else { 35 for(v0 = 1; v0 < v3; ++v0) { 36 v1 -= v0; 37 } 38 39 v2 = this.chec(v1, arg6); 40 } 41 42 return v2; 43 } 44 45 public int check3(int arg4, int arg5) { 46 int v1 = arg4; 47 int v0; 48 for(v0 = 1; v0 < 10000; ++v0) { 49 v1 += v0; 50 } 51 52 return this.chec(v1, arg5); 53 }
b.将IDA分析so文件,反编译check方法。
经搜索知,native层check方法的前两个参数为JNI接口指针和对对象和Java类的引用,是默认的,后两个参数即为Java层参数,详见(https://blog.csdn.net/ljtyzhr/article/details/49156847)。
以及GetMethodID与CallIntMethod为JNI层调用Java层方法的函数,详见(https://blog.csdn.net/smbroe/article/details/44133741))。
则经分析可知check方法的功能为:
判断Java层传入的第二个参数的是否小于等于1,若是则返回Java层传入的第一个参数,若不是则回调Java层中check1,check2,check3方法中的一个。
CallMethod函数中*(&v10 + 2 * v8 % 3)决定调用Java层三个方法中的哪一个,v7和v8-1为传入Java层方法的变量。
1 int __fastcall Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec(int a1, int a2, int a3, int a4) 2 { 3 int v4; // r4 4 int v5; // r7 5 int result; // r0 6 int v7; // [sp+Ch] [bp-34h] 7 int v8; // [sp+10h] [bp-30h] 8 int v9; // [sp+14h] [bp-2Ch] 9 int v10; // [sp+1Ch] [bp-24h] 10 int v11; // [sp+20h] [bp-20h] 11 int v12; // [sp+24h] [bp-1Ch] 12 13 v9 = a2; 14 v8 = a4; 15 v4 = a1; 16 v7 = a3; 17 v5 = (*(int (**)(void))(*(_DWORD *)a1 + 24))(); 18 v10 = _JNIEnv::GetMethodID(v4, v5, "check1", "(II)I"); 19 v11 = _JNIEnv::GetMethodID(v4, v5, "check2", "(II)I"); 20 v12 = _JNIEnv::GetMethodID(v4, v5, "check3", "(II)I"); 21 if ( v8 - 1 <= 0 ) 22 result = v7; 23 else 24 result = _JNIEnv::CallIntMethod(v4, v9, *(&v10 + 2 * v8 % 3), v7, v8 - 1); 25 return result; 26 }
0x03
程序算法分析
满足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。接着进行算法求逆,写出脚本即可。
0x04
解题脚本
写脚本需要注意的细节是在对check2方法的求逆的时候,if的判断条件为(num-1)%2==0,不要忘记减去1,因为native层check函数传给Java层方法的第二个参数减去1了。
1 num = 99 2 flag = 1835996258 3 while num - 1 >0 : 4 tmp = num * 2 % 3 5 if(tmp == 0): 6 flag -=4950 7 if(tmp == 1): 8 if((num - 1) % 2 == 0): 9 flag -= 499500 10 else: 11 flag +=499500 12 if(tmp == 2): 13 flag -= 49995000 14 num -= 1 15 print flag
以上是关于18/09/24-1-BugKu-逆向-LoopAndLoop(阿里CTF)的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向Android 逆向用途 | Android 逆向原理