# adworld_mobile—— 基础的 android
# 这是一个新的系列,这里记录的是我自己在学习安卓逆向过程中的刷题记录。
# 首先我们来看看项目的注册声明
# Mainfest.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?xml version="1.0" encoding="UTF-8"?> <manifest android:versionCode="1" android:versionName="1.0" package="com.example.test.ctf02" platformBuildVersionCode="24" platformBuildVersionName="7.0" xmlns:android="http://schemas.android.com/apk/res/android"> <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="24" /> <application android:allowBackup="true" android:debuggable="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name="com.example.test.ctf02.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:enabled="true" android:exported="true" android:name="com.example.test.ctf02.GetAndChange"> <intent-filter> <action android:name="android.is.very.fun" /> </intent-filter> </receiver> <activity android:name="com.example.test.ctf02.NextContent" /> <activity android:name="com.example.test.ctf02.MainActivity2" /> </application> </manifest>
|
# 我们直接看入口点的位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public class MainActivity extends AppCompatActivity { private Button login; private EditText passWord;
public MainActivity() { super(); }
static EditText access$000(MainActivity arg1) { return arg1.passWord; }
protected void onCreate(Bundle arg3) { super.onCreate(arg3); this.setContentView(0x7F04001A); this.passWord = this.findViewById(0x7F0B0055); this.login = this.findViewById(0x7F0B0056); this.login.setOnClickListener(new View$OnClickListener() { public void onClick(View arg7) { if(new Check().checkPassword(MainActivity.this.passWord.getText().toString())) { Toast.makeText(MainActivity.this, "Good,Please go on!", 0).show(); MainActivity.this.startActivity(new Intent(MainActivity.this, MainActivity2.class)); MainActivity.this.finish(); } else { Toast.makeText(MainActivity.this, "Failed", 0).show(); } } }); } }
|
# check 类的定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package com.example.test.ctf02;
public class Check { public Check() { super(); }
public boolean checkPassword(String arg7) { int v5 = 12; boolean v2 = false; char[] v1 = arg7.toCharArray(); if(v1.length == v5) { int v0 = 0; while(true) { if(v0 < v1.length) { v1[v0] = ((char)(0xFF - v0 - 100 - v1[v0])); if(v1[v0] == 0x30 && v0 < v5) { ++v0; continue; } } else { break; } return v2; } v2 = true; }
return v2; } }
|
首先长度限制为 12,然后将我们输入的字符串转为字符数组,根据代码我们写出逆向解析
1 2 3 4 5 6 7 8 9 10 11
| ss = []
for i in range(12): ss.append(chr(0xff-0x30-100-i)) key = "" for i in ss: key+=i
print(key)
|
# MainActivity2
这里完成之后,MainActivity 会调用 MainActivity2。但是在 Manifest 中没有对其进行声明(这回有什么影响吗?)但是 app 貌似已经进入了。
接着就是对图片的处理,要求我们输入现实吗,但是显示码在哪里?
这里就引用了 MainActivity2 的部分,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class MainActivity2 extends AppCompatActivity { Button button; EditText editText; ImageView imageView;
public MainActivity2() { super(); }
public void init() { this.imageView = this.findViewById(0x7F0B0029); this.imageView.setImageResource(0x7F020053); this.editText = this.findViewById(0x7F0B0057); this.button = this.findViewById(0x7F0B0056); }
protected void onCreate(Bundle arg3) { super.onCreate(arg3); this.setContentView(0x7F04001B); this.init(); this.button.setOnClickListener(new View$OnClickListener() { public void onClick(View arg4) { MainActivity2.this.sendBroadcast(new Intent(MainActivity2.this.editText.getText().toString())); } });
|
到那时我并不是很理解这些代码都是什么意思。我猜测 imageView 是与我们的图像有关,而且下面我看到了 click,会将我们输入的字符串广播发送,发送对象是谁呢?这里我不是很清楚,但是这是一个 intent 类(intent 应该是一个广播报文,用于组件之间的数据传递). 在 manifest 中见过,注册了接收器 ——com.example.test.ctf02.GetAndChange,然后我去搜索了一下 intentfilter 是一个白名单过滤器,注册的时候。声明了广播的注册,接收者,以及白名单 “android.is.very.fun”。所以这里的显示码就是这个白名单。
虽然到这里我们拿到了 flag。
# 进一步
广播接收器在接收到 intent 之后进行了什么?
1 2 3 4 5 6 7 8 9
| public class GetAndChange extends BroadcastReceiver { public GetAndChange() { super(); }
public void onReceive(Context arg3, Intent arg4) { arg3.startActivity(new Intent(arg3, NextContent.class)); } }
|
他这里又打开了 NextContent,这里出现了两个.jpg 图像,第一个就是我们最开始看到的,而第二个是一个压缩文件,所以这里的逻辑应该就是去处理这所文件,然后进行替换显示,我们在 assets 中看到了压缩文件,也就是 flag 的图片。
但是到这里,就结束了吗?我们看这个接收器的声明,export 属性是允许其他应用调用当前的组件,所以这个如果这个广播我们可以直接发送,就会直接拿到 flag。所以我们怎么进行广播?一个师傅的做法是利用 adb 调试器,发送如下指令
1
| adb shell am broadcast -a android.is.very.fun
|
解析一下,就是 adb 执行 shell,这个 am 不是很理解,然后 adb shell am 又可以添加一下命令和选项,其中 broadcast 就是广播,-a 是选项允许监听交互的一些通信,最后加上 intent, 这样接收器就可以接收到信息了。