android逆向就是反编译的过程,因为看不懂android正向编译后的结果所以ctf中静态分析的前提是将出现文件反编译到我们看得懂一层源码,进行静态分析。
0x01 基础说明
android应用的逻辑代码是由java进行开发,所以是第一层就是java代码
java虚拟机jvm运行的是java文件编译过后的class文件
android虚拟机dalvik并不是执行java虚拟机jvm编译后生成的class文件,而是执行再重新整合打包后生成的dex文件编译之后的smali文件
apk:是编译完成后的android应用程序安装包
dex文件:是class文件的打包文件
smali文件:是dalvik字节码文件
class文件:是jvm字节码文件
0x02 工具使用
在ctf中android题目不一定给你完整编译完成后的apk,可能是编译过程中任意文件类型,下面斗哥分以下文件类型利用工具来得到斗哥看得懂的java源码
类型一:class文件
这种情况比较简单,推荐工具jd-gui
直接将class文件拉进去就可以看到java源码。
类型二:apk程序
android工程编译完成会得到我们想要的apk安装包,apk文件其实是一个压缩包。
修改后缀名为zip后解压,解压后的文件如下图所示:
meta-inf文件夹:
存放apk签名信息,用来保证apk包的完整性和系统的安全。
res文件夹:
存放资源文件,包括icon,xml文件。
androidmanifest.xml文件:
应用程序配置文件,每个应用都必须定义和包含的,它描述了应用的名字、版本、权限、引用的库文件等信息。
classes.dex文件:
可以直接在dalvik虚拟机上加载运行的文件,由java文件经过ide编译生成。
resources.arsc文件>
二进制资源文件,包括字符串等。
反编译apk推荐工具apkide、jeb
1. jeb使用:
jeb直接导入apk,反编译完成看到smali文件。
很多android逆向工具就反编译到smali文件这步。
jeb选中smali文件中按q,就可以看到java文件。
优点:从smali文件反编译成的java文件代码结构清晰。
缺点:无法修改。
2. apkide使用:
项目->打开apk
等待反编译完成。
看到smali文件。
选择要java源码的smali文件,点击下图按钮,打开java源码。
apkide关联了jd-gui,点击后将跳转到jd-gui。
apkide是将apk反编译到class再用jd-gui拿到java源码。
在apkide的apkide_v3.3\apkide\worksrc的项目目录下可以看到反编译后的class文件。
优点:功能强大,可以修改反编译出来的smali文件,重新编译生成apk。
缺点:编译成后的java代码不够清晰。
3.反编译区别
smali文件是由smali语法编写,smali语法宽松式的语法
所以反编译过程不同,工具不同,java源码肯定不同
下面是同一个apk用上面两个工具逆向的结果:
斗哥作为一名java开发的爱好者喜欢jeb的逆向结果,看着比较舒服。
类型三:dex文件
推荐工具dex2.jar
classes.dex文件,这个是android源码编译过的字节码包
尝试使用dex2.jar工具拿到java源码命令如下
.\d2j-dex2jar.bat c:\users\lin\desktop\classes.dex
jar文件可以理解为classes文件的压缩包,java虚拟机可以直接运行
用jd-gui打开classes-dex2jar.jar就可以看到java源码
类型四:smali文件
当只有一个单独的smali文件时就无法用上述的工具直接进行反编译
斗哥想到apkide可以对一个apk进行反编译到smali文件,对smali文件进行增删改查的操作
于是用apkide打开任意一个完整的apk然后添加smali文件(apk可以用自己开发的)
将smali文件添加apkide项目中。
重新编译生成apk。
编译成功后将在原apk目录生成一个apk。
再用jeb等工具打开就能看到ezreal.smali文件。
其他工具:
编辑器:notepad++、sublime等
android模拟器:夜神模拟器等
0x04 例题分析
将应用安装到模拟器查看界面是否有提示。
在文本框输入字符点击按钮提示错误,猜想是否用来判断正确的flag。
使用jeb工具编译成java文件,android文件下是sdk文件,我们要分析是com包下的源码文件。
代码量不多就三个类,先从程序入口mainactivity分析,找到关键代码块。
这句if就是判断flag是否正确。
搜索类查看哪里调用了此方法。
分析得到arg12就是界面要输入的参数,这时我们知道了v5的值就是我们要的flag。
oncreate函数调用了checksn方法并传入两个参数为:
mainactivity.this.edit_username.trim()
mainactivity.this.edit_sn.gettext().tostring().trim()
//oncreate是android中的一个特别的函数,用来“表示一个窗口正在生成”。
//其不产生窗口,只是在窗口显示前设置窗口的属性如风格、位置颜色等。
public void oncreate(bundle arg3) {
super.oncreate(arg3);
this.setcontentview(0x7f040019);
this.settitle(0x7f06001d);
this.edit_username = tenshine;
this.edit_sn = this.findviewbyid(0x7f0c0051);
this.btn_register = this.findviewbyid(0x7f0c0052);
this.btn_register.setonclicklistener(new view$onclicklistener() {
public void onclick(view arg5) {
if(!mainactivity.this.checksn(mainactivity.this.edit_username.trim(), mainactivity.this.edit_sn.gettext().tostring().trim())) {
toast.maketext(mainactivity.this, 0x7f06001e, 0).show();
}
else {
toast.maketext(mainactivity.this, 0x7f06001b, 0).show();
mainactivity.this.btn_register.setenabled(false);
mainactivity.this.settitle(0x7f060019);
}
}
});
}
分析v5的值,v5是由v3和v4生成的,v4是一个int并直接赋值为0用于循环就可以直接使用
而v3则是tohexstring方法的返回值,并要传入,v1是v1.update(arg11.getbytes());生成
arg11就是传入的参数tenshine
private boolean checksn(string arg11, string arg12) {
boolean v7 = false;
if(arg11 != null) {
try {
if(arg11.length() == 0) {
return v7;
}
if(arg12 == null) {
return v7;
}
if(arg12.length() != 22) {
return v7;
}
messagedigest v1 = messagedigest.getinstance(md5);
v1.reset();
v1.update(arg11.getbytes());
string v3 = mainactivity.tohexstring(v1.digest(), );
stringbuilder v5 = new stringbuilder();
int v4;
for(v4 = 0; v4 < v3.length(); v4 += 2) {
v5.append(v3.charat(v4));
}
if(!flag{ + v5.tostring() + }.equalsignorecase(arg12)) {
return v7;
}
}
catch(nosuchalgorithmexception v2) {
goto label_40;
}
v7 = true;
}
return v7;
label_40:
v2.printstacktrace();
return v7;
}
将上面的分析结果,取出生成v5的关系代码
都是纯java代码,不需要android的包引入,只需引入java的依赖包。
import java.security.messagedigest;
import java.security.nosuchalgorithmexception;
public class code {
static string tohexstring(byte[] arg8, string arg9) {
stringbuilder v3 = new stringbuilder();
byte[] v0 = arg8;
int v5 = v0.length;
int v4;
for(v4 = 0; v4 < v5; ++v4) {
string v2 = integer.tohexstring(v0[v4] & 255);
if(v2.length() == 1) {
v3.append('0');
}
v3.append(v2).append(arg9);
}
return v3.tostring();
}
public static void main(string[] args)throws nosuchalgorithmexception{
messagedigest v1 = messagedigest.getinstance(md5);
v1.reset();
v1.update(tenshine.getbytes());
string v3 = code.tohexstring(v1.digest(), );
stringbuilder v5 = new stringbuilder();
int v4;
for(v4 = 0; v4 < v3.length(); v4 += 2) {
v5.append(v3.charat(v4));
}
system.out.println(flag{ + v5.tostring() + });
}
}
用idea编辑运行,拿到flag。
以上就是android中怎么进行静态分析的详细内容。
