# 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">//第一个调用的activity
<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">
//允许广播————这个activity允许外部调用,广播接收器的名字是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())) {
//我们关注的是这个check类的检查方式
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 = []
#0xff-i-100-ord(ss[i])==0x30
for i in range(12):
ss.append(chr(0xff-0x30-100-i))
key = ""
for i in ss:
key+=i

print(key)

#结果为: “kjihgfedcba`”

# MainActivity2

这里完成之后,MainActivity 会调用 MainActivity2。但是在 Manifest 中没有对其进行声明(这回有什么影响吗?)但是 app 貌似已经进入了。

接着就是对图片的处理,要求我们输入现实吗,但是显示码在哪里?

image-20220718122215383

这里就引用了 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”。所以这里的显示码就是这个白名单。

image-20220718160715646

虽然到这里我们拿到了 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, 这样接收器就可以接收到信息了。

Edited on

Give me a cup of [coffee]~( ̄▽ ̄)~*

dreamcat WeChat Pay

WeChat Pay

dreamcat Alipay

Alipay

dreamcat PayPal

PayPal