非root设备使用gdbserver进行 native 调试的方法

没有root的设备,要使用gdbserver 调试app 会遇到权限问题。(emulator 没有问题)

1
2
3
1|shell@mako:/data/local/tmp $ ./gdbserver :1234 --attach 16907
Cannot attach to lwp 16907: Operation not permitted (1)
Exiting

Android 系统提供了一个run-as 命令来暂时切换用户,但是这个命令有限制,必须是app
打开了debuggable才行,否则会报 Package xx is not debuggable 的错误。

http://android.googlesource.com/platform/system/core.git/+/master/run-as/run-as.c
的注释来看,主要的作用有两个:

  1. 可以查看开发这自己应用的数据
  2. 可以使用gdb_server 进行native 的debug

我们的需求是第2个,我们希望可以使用gdb_server 来调试 app

1
2
3
4
5
6
shell@mako:/ $ run-as
Usage: run-as <package-name> <command> [<args>]
shell@mako:/ $
shell@mako:/ $ run-as system_server /data/tmp/gdbserver --attach 596 :1234
run-as: Package 'system_server' is unknown

翻看源码,发现有下面 代码:

1
2
3
4
5
6
7
8
/* reject system packages */
if (userAppId < AID_APP) {
panic("Package '%s' is not an application\n", pkgname);
}
/* reject any non-debuggable package */
if (!info.isDebuggable) {
panic("Package '%s' is not debuggable\n", pkgname);
}

限制比较严格,调试系统app估计是没什么戏,root了应该就没有问题了。但是调试一般的app
还是没有问题的,用apktool 将 AndroidManifest.xml 的 debuggable 设置为true,重新
打包就可以进行native 的 debug 了。

下面以CVE-2014-7911的POC为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.heen.CVE_2014_7911">
<application
android:allowBackup="true"
android:debuggable="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

这个app 正好 android:debuggable=”true” 不用修改了,在模拟器上安装这个app。搭建
gdb调试环境, 分下面几个步骤走:

  1. 创建几个目录
1
2
3
mkdir ~/Android
mkidr ~/Android/system_lib
mkidr ~/Android/vendor_lib
  1. 将Android 设置上的lib下载到本地
1
2
3
4
5
6
7
8
9
10
11
12
13
14
cd ~/Android/system_lib/
adb pull /system/lib
cd ~/Android/vendor_lib/
adb pull /vendor/lib
cd ~/Android
# 在64位系统 /system/bin/app_process32 和 /system/bin/app_process64
adb pull /system/bin/app_process
cd ~/Android
adb pull /system/bin/linker
  1. 上传gdbserver
1
adb push $NDK_PATH/prebuilt/android-arm/gdbserver/gdbserver /data/local/tmp/gdbserver

环境基本搭建好了,测试一下 run-as 命令

1
2
3
4
5
6
7
8
> adb shell ps
...
u0_a86 16907 174 900568 38564 ffffffff 00000000 S com.heen.CVE_2014_7911
...
> adb shell run-as com.heen.CVE_2014_7911 id
uid=10086(u0_a86) gid=10086(u0_a86) groups=1003(graphics),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:untrusted_app:s

已经切换过来了,uid 变了,挂上gdbserver

1
2
3
4
> adb shell run-as com.heen.CVE_2014_7911 /data/local/tmp/gdbserver :123 --attach 16907
Can't open socket: Permission denied.
Exiting

报了另外一个错误,还是不行,google 一翻发现有debug-pipe 参数,尝试了一下

1
2
3
> adb shell run-as com.heen.CVE_2014_7911 /data/local/tmp/gdbserver +debug-pipe --attach 16907
Attached; pid = 16907
Listening on Unix socket debug-pipe

恩,现在没有报错了,执行一下端口转发。

1
adb forward tcp:5039 localfilesystem:/data/data/com.heen.CVE_2014_7911/debug-pipe
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
> $NDK_PATH/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdb ~/Android/app_process
GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-linux-android".
For bug reporting instructions, please see:
<http://source.android.com/source/report-bugs.html>...
Reading symbols from /home/henices/Android/app_process...(no debugging symbols found)...done.
(gdb) target remote :5039
Remote debugging using :5039
warning: Could not load shared library symbols for 100 libraries, e.g. /system/bin/linker.
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
0x4013a73c in ?? ()
(gdb) info proc
process 16907
cmdline = 'com.heen.CVE_2014_7911'
cwd = '/'
exe = '/system/bin/app_process'
(gdb) set solib-search-path ~/Android:~/Android/system_lib/:~/Android/vendor_lib/
(gdb) info sharedlibrary
0x400f3a60 0x400fe79c Yes (*) /home/henices/Android/linker
0x40126070 0x401566ec Yes (*) /home/henices/Android/system_lib/libc.so
0x40174828 0x401749c8 Yes (*) /home/henices/Android/system_lib/libstdc++.so
0x401798f0 0x4018c478 Yes (*) /home/henices/Android/system_lib/libm.so
0x40114f50 0x40116490 Yes (*) /home/henices/Android/system_lib/liblog.so
0x4010c38c 0x40110988 Yes (*) /home/henices/Android/system_lib/libcutils.so
0x401acb1c 0x401af20c Yes (*) /home/henices/Android/system_lib/libgccdemangle.so
0x401a81d0 0x401a94ac Yes (*) /home/henices/Android/system_lib/libcorkscrew.so
0x4019b780 0x401a1f24 Yes (*) /home/henices/Android/system_lib/libutils.so
0x401cbc50 0x401d5ba4 Yes (*) /home/henices/Android/system_lib/libbinder.so
0x402955f0 0x4029585c Yes (*) /home/henices/Android/system_lib/libhardware.so
0x402925d0 0x40292834 Yes (*) /home/henices/Android/system_lib/libmemtrack.so
0x402bbbf0 0x402cb80c Yes (*) /home/henices/Android/system_lib/libz.so
0x402a4240 0x402b23fc Yes (*) /home/henices/Android/system_lib/libandroidfw.so
0x402d6774 0x402e53a0 Yes (*) /home/henices/Android/system_lib/libexpat.so
0x403083a8 0x4031e684 Yes (*) /home/henices/Android/system_lib/libstlport.so

OK, 已经可以调试了。