Android中使用"hacker"方式解决ServiceManager的权限限制问题(1)
2016-08-02 10:59
519 查看
缘由
有一个系统,需要我们的解决方案,但是却没有提供BSP的源码。我们的方案有一个So文件,并在其中有注册service,但是启动后发现service并没有注册成功,查询log发现是:
<span style="font-family:Microsoft YaHei;font-size:18px;">E/ServiceManager﹕ add_service('XXXX',0x48) uid=YYY - PERMISSION DENIED</span>看起来是我们不具备权限,然后确定了一下SElinux的状态,发现是没有开启的,而servicemanager对添加service的权限的检查是位于其代码中的。
关于ServiceManager是如何检查权限的可以参考一下stackoverflow中的答案,或者自己看看servicemanager的源码。
参考的链接为这个,从这里面我们可以得知权限的检查写死在了对应的source code中(Android 4.4),暂时没有配置文件,这个和SeLinux不一样。
判断逻辑
ServiceManager的判断逻辑为:1. uid判断是否为system
2. 是否在可信任的表格中
如果两个都不是,那么就认为没有权限,然后打印出前面的话来。这个对应的代码为:
int svc_can_register(unsigned uid, uint16_t *name) { unsigned n; if ((uid == 0) || (uid == AID_SYSTEM)) return 1; for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++) if ((uid == allowed .uid) && str16eq(name, allowed .name)) return 1; return 0; }另外这个allowed的数组为:
/* TODO: * These should come from a config file or perhaps be * based on some namespace rules of some sort (media * uid can register media.*, etc) */ static struct { unsigned uid; const char *name; } allowed[] = { { AID_MEDIA, "media.audio_flinger" }, { AID_MEDIA, "media.log" }, { AID_MEDIA, "media.player" }, { AID_MEDIA, "media.camera" }, { AID_MEDIA, "media.audio_policy" }, { AID_DRM, "drm.drmManager" }, { AID_NFC, "nfc" }, { AID_BLUETOOTH, "bluetooth" }, { AID_RADIO, "radio.phone" }, { AID_RADIO, "radio.sms" }, { AID_RADIO, "radio.phonesubinfo" }, { AID_RADIO, "radio.simphonebook" }, /* TODO: remove after phone services are updated: */ { AID_RADIO, "phone" }, { AID_RADIO, "sip" }, { AID_RADIO, "isms" }, { AID_RADIO, "iphonesubinfo" }, { AID_RADIO, "simphonebook" }, { AID_MEDIA, "common_time.clock" }, { AID_MEDIA, "common_time.config" }, { AID_KEYSTORE, "android.security.keystore" }, };
从里面的注释可以看出,以后这个可能会变成使用通配符方式,或者是配置文件的方式,但是现在还是直接写死了。
如果要让我们的service可以成功注册,那么可以:
直接将前面的return 0改成return 1即可
将我们的service添加到allowed数组中
我们先使用第一种方式来完成。
反汇编完成
获取servicemanager elf文件
这个非常容易,直接adb pull即可,这个servicemanager位于/system/bin下面。定位需要更改的位置
我们使用反汇编工具,加载这个ELF文件,然后根据前面的log提示,搜索这个位置即可:然后jump进去:
然后其伪代码为:
signed int __fastcall sub_87C(int a1, void *a2, unsigned int a3, int a4, int a5, int a6) { int v6; // r9@1 void *v7; // r7@1 int v8; // r6@1 int v9; // r5@1 _BYTE *v10; // r3@5 const char *v11; // r1@5 const char *v12; // r2@5 int v13; // r0@6 int v14; // r4@6 _BYTE *v15; // r0@8 void *v16; // r0@10 int v17; // r2@13 int v19; // [sp+0h] [bp-28h]@5 int v20; // [sp+4h] [bp-24h]@5 v6 = a1; v7 = a2; v8 = a3; v9 = a4; if ( !a4 || !a3 || a3 > 0x7F ) return -1; if ( sub_7D4(a5, (int)a2) ) { v13 = sub_80C(v7, v8); v14 = v13; if ( v13 ) { if ( *(_DWORD *)(v13 + 4) ) { v15 = sub_73C((int)v7); _android_log_print( 6, "ServiceManager", "add_service('%s',%p) uid=%d - ALREADY REGISTERED, OVERRIDE\n", v15, v9, a5); sub_774(v6, v14); } *(_DWORD *)(v14 + 4) = v9; } else { v16 = malloc(2 * (v8 + 13)); v14 = (int)v16; if ( !v16 ) { v19 = v9; v20 = a5; v10 = sub_73C((int)v7); v11 = "ServiceManager"; v12 = "add_service('%s',%p) uid=%d - OUT OF MEMORY\n"; goto LABEL_12; } *((_DWORD *)v16 + 5) = v8; *((_DWORD *)v16 + 1) = v9; memcpy((char *)v16 + 24, v7, 2 * (v8 + 1)); *(_WORD *)(v14 + 2 * (v8 + 12)) = 0; v17 = dword_30B8; *(_DWORD *)(v14 + 8) = sub_774; *(_DWORD *)(v14 + 12) = v14; *(_DWORD *)(v14 + 16) = a6; *(_DWORD *)v14 = v17; dword_30B8 = v14; } sub_CFC(v6, v9); sub_D2C(v6, v9, v14 + 8); return 0; } v10 = sub_73C((int)v7); v19 = v9; v20 = a5; v11 = "ServiceManager"; v12 = "add_service('%s',%p) uid=%d - PERMISSION DENIED\n"; LABEL_12: _android_log_print(6, v11, v12, v10, v19, v20); return -1; }
根据if判断,知道我们需要到sub_7D4中修改
我们先在function/symbol list中找到这symbol:
然后再jump过去:
框中就是我们前面提到的return 0,这个就是我们需要更改的位置。
其伪代码和前面的ServiceManager中的判断非常类似:
修改
在修改之前我们需要找到其对应instruction,这个在IDA Pro中非常容易,直接在hex view中sync对应的窗口过来即可:在这里其对应对位置为:
因为ARM是小端模式,所以高低字节序相反,因此前面MOVS R0, 0对应的指令是0x2000。
指令说明
我们非常清楚根据APCS(arm procedure call standard), 此文档可以google或者baidu,也可以到我的资源中下载(http://download.csdn.net/detail/sy373466062/9592421), R0是作为返回值,因此直接改这一条就够了。显然0x200是2个Byte,因此是Thumb指令,我们可以查询一下这个指令,然后将其改成MOVS R0, 1
对此,我们参考Thumb指令的说明文档非常容易更改。
在Thumb指令文档中(下载地址:http://download.csdn.net/detail/sy373466062/9592423),可以看到:
从这个指令可以看出前面的Rd就是我们这里面的R0, 后面的offset8立即数,为0,我们这里需要改成1,因此,重新拼接一下就是:0x2001。
关于指令的修改可以参考:
http://stackoverflow.com/questions/9279451/armv7-word-patch-cbnz
如果觉得要找这些比较麻烦,那么可以使用ARM ASM Converter软件来转换,直接在软件的底下输入指令,然后点击convert即可:
这个软件业给出了Thumb指令为2001,这个软件可以从我的资源下载(http://download.csdn.net/detail/sy373466062/9592450)
修改
我们使用010Editor或者UE等一些软件来修改比较合适,例如在010Editor中找到对应的位置(0x800),然后直接更改即可:修改完成后保存,为了确保我们修改正确,可以比较一下:
然后就可以push进去测试了。
测试
因为我们是add_service,因此可以先在log中看是否还有Permission Denied的提示,同时也可以使用下面的命令来查看我的service注册成功没有:service list | grep XXX
相关文章推荐
- 解决问题:vs 使用命令行参数调试时出现"当前项目设置指定将使用特定的安全权限对该项目进行调试.在此模式下,命令行参数将不会传递给可执行文件."
- Window访问Linux共享"您可能没有权限使用网络资源"问题解决
- android客户端通过Get方式提交参数给服务器,使用URL和HttpURLConnection实现,以及乱码问题解决
- 解决android使用gson解析json字符串,并使用混淆编译方式打包apk遇到的问题
- 解决android使用gson解析json字符串,并使用混淆编译方式打包apk遇到的问题
- win7 共享的问题,"您可能没有权限使用网络资源"的解决办法
- 解决android使用gson解析json字符串,并使用混淆编译方式打包apk遇到的问题
- Android安装应用后点击"打开"(Open)带来的问题及解决方式
- Android安装应用后点击"打开"(Open)带来的问题及解决方式
- android开发(37) android使用android_serialport_api 操作串口,解决权限问题
- 解决android使用gson解析json字符串,并使用混淆编译方式打包apk遇到的问题
- android TextView多行文本(超过3行)使用ellipsize="end"属性无效问题的解决方法
- Android 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚
- Android 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚
- Android 解决65535的限制 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚
- Android 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚
- Android 解决65535的限制 使用android-support-multidex解决Dex超出方法数的限制问题
- 使用PermissionsDispatcher轻松解决Android权限问题
- Android使用多进程方式,解决Webview内存难释放的问题
- Android——使用android-support-multidex解决Dex超出方法数的限制问题