adb + strace + monkey 获取应用运行时的系统调用(最终结果写至txt文件)

简介adb、strace和monkey

adb(安卓调试桥) 全称为 Android Debug Bridge,是一个命令行工具。它起一个桥梁作用,将Android与PC打通。利用adb我们可以在PC端对Android系统进行操作。
strace是Linux系统的一个调试分析工具,由于Android是基于Linux内核的,因此strace也存在于Android系统。其可以用于追踪应用程序运行时触发的系统调用。
monkey是Android系统的一个命令行工具,使用monkey命令会通过对应用程序进行一系列的随意操作,对应用程序进行压力测试。

strace的用法可以参考博客:
Linux strace命令

adb + monkey 的使用可以参考博客:
Adb命令的使用以及monkey命令的使用

获取系统调用

思路

我想要获取的是应用从一开始执行的系统调用序列,而(1)在不执行应用的情况下是不能获取其进程号的。同时,(2)如果通过运行应用获取其进程号,关闭应用再次启动时,其进程号会发生改变。由于上述两点原因,决定strace其父进程。

在Android系统中,用户应用程序均是由zygote孕育的,其运行时的父进程均为zygote。
在这里插入图片描述
因此,只要获取zygote的进程号进行追踪即可。strace zygote 的同时,执行monkey命令对指定应用进行操作,获取zygote进程的系统调用序列,从中筛选指定应用的系统调用序列。

整个过程

写了下主要命令,代码就不放了

1.获取zygote进程号

public String getPid(String name)throws Exception{
  //执行 adb shell ps命令获取当前进程信息
   Process proc = Runtime.getRuntime().exec("adb shell ps");
   //以字节流输入
   InputStream ins = proc.getInputStream();
   //转换为字符流
   InputStreamReader insr = new InputStreamReader(ins);
   //使用带有缓存功能的字符流方便按行操作
   BufferedReader bufr = new BufferedReader(insr);
   String nextline = null;
   String pid = null;
   /*按行读取数据,将其具有空隙的地方用空格替代,然后以空格分割字符串,
   得到其第7个字符串判断其是否为我们需要的进程*/
   while((nextline=bufr.readLine())!=null){
      String repnextline1 = nextline.replaceAll("\\s+"," ");
      String[] substr = repnextline1.split(" ");
      if((substr.length > 8) && (substr[8].equals(name))) {
 	 pid = substr[1];
         break;	  
      }
   }
    bufr.close();
    return pid;
}

2.安装应用

adb install apk所在路径

3.trace zygote进程并输出结果至Android系统中
这一命令一旦执行需要通过kill strace(第5步) 来结束

adb shell strace -o anfilepath(安卓系统中路径) -T -tt -e trace=all -f -p  pid(zygote进程)

4.执行monkey命令操作应用

adb shell monkey --ignore-crashes --ignore-timeouts -p  进程名 500(执行次数)

5.结束strace

通过第1步的代码获取进程号

adb shell kill strace的进程号

6.将Android系统中的文件提取到PC端

adb pull filepath(PC端路径) anfilepath(Android中路径)

7.删除Android系统中的文件

adb shell rm anfilepath(Android中路径)

8.卸载应用

adb uninstall apk包名(与其进程名一致)

最后从系统调用中筛选应用的系统调用的细节就不写了。
得到的系统调用txt截图如下:
在这里插入图片描述