前言
简单的安卓逆向
一、测试程序
发现文件为APK文件,使用noc模拟器打开,先简单的看一下程序的执行结果。
猜测有输入字符串后有一个判断的函数,并且有一个结果错误的字符串反馈。
使用androidkiller对APK文件进行反编译后,根据Androidkiller反编译出的classes文件使用jd-gui进行反编译,得到java代码。
寻找主函数Mainactivity
程序的判断函数就是主函数本身,进行下一步开始分析。
二、进行分析
1.整体逻辑分析
代码在对b初始定义为0,定义了arrayofchar1和arrayofchar2两个数组,长度分别为17和38。
然后进入一个while循环条件恒位true。其中有b>=17和<17两种情况。b<17是首先进行的代码,再执行以后,会继续执行b>=17的代码部分,进行从用户的键盘的输入接收字符串。
2.部分代码分析
首先看输入数据之前的代码部分
显而易见的这段代码作用是进行赋值,分为三种情况当a数组的b位数据为大小写的a到z之间的数据将会对ascii进行-8后进行赋值。第二种情况是当数据为大小写a到i时对数据的ascii码进行+18,第三种是为其他的数据直接进行赋值。如果对这段程序的逻辑不是很清晰可以自己写这段程序进行动态调试更深的理解。
我自己使用了devc++的编译器代码如下:
#include <stdio.h>
int main(void) {
int b = 0;
int a[] = {65};
int str[2];
int i=0;
if ((a[b] < 'I' && a[b] >= 'A') || (a[b] < 'i' && a[b] >= 'a')) {
str[b] = (a[b] + 18);
}
else if ((a[b] >= 'A' && a[b] <= 'Z') || (a[b] >= 'a' && a[b] <= 'z')) {
str[b] = (a[b] - 8);
}
else {
str[b] = a[b];
}
//b++;
printf("%d\n",str[i]);
return 0;
}
这个判断的逻辑实际上是先进行输入字符是大小写“a-i”先进行判断,然后对字符是否为“a-z”进行判断,最后为数字或者其他字符进行直接赋值。输出结果为83,可以证明这个逻辑。
接下来分析b>=17的判断,String.valueOf(arrayOfChar1).equals(edit.getText().toString())这句java代码代码的含义是将数组1的改为字符串与输入的字符串进行对比,类似c语言中的strcmp()函数的功能。
b<38时,进入一个循环,类似与数组1的赋值逻辑,对数组2进行了赋值,这里不进行赘述。
当b>38时,将数组2赋值给str字符串,并且输出str到屏幕,所以可知str为我们的flag。
三、进行脚本编写
现在我们不知道核心的a[],b[]两个数组的内容。然后实在想不出来就去看了别的大佬的wp,然后发现Androidkiller反编译的有arrayofchar1和arrayofchar2的数据(他们的wp中没有说为甚什么使用arrayofchar2的数据作为flag)。根据我们以上的分析就解释了为什么使用数组二的数据作为flag。
发现得到的str2并不是flag{}格式的,所以根据经验对凯撒密码和栅栏密码进行举例。
我这里使用了bugku的在线工具进行了枚举得到了
flag{c164675262033b4c49bdf7f9cda28a75}
总结
总体来说这道题算是比较简单的apk re题目,主要考察了代码审计能力。