Android模块遍历方法

发表于2015-07-15
评论0 2.8k浏览

一、背景

Android,中文俗称安卓,是一个以Linux为基础的开放源代码移动设备操作系统,主要用于智能手机和平板电脑,由Google成立的开放手持设备联盟持续领导与开发中。

在许多类 Unix 计算机系统中, procfs 是进程文件系统的缩写,包含一个伪文件系统,用于通过内核访问进程信息。这个文件系统通常被挂载到/proc目录。由于/proc不是一个真正的文件系统,它也就不占用存储空间,只是占用有限的内存。/proc/[pid]/maps里面存放的某一进程下的当前映射到内存中的模块列表信息。

 

二、maps内容格式

1. 内容展示

以进程/system/bin/sh为例,通过ps看到它的pid21358,调用cat /proc/21358/maps(必须有权限,如root用户或者和该进程属于同一用户),查看它的内容:

2. 格式解析:

可以看到,maps的文件固定为6列,最后1列的内容有些没有。第1列是地址,表示模块在进程空间的范围;第2列是虚拟内存的权限,r=读,w=写,x=执行,s=共享(多进程共享)p=私有(copy-on-write,如果有一进程要修改模块内容,会在进程的内存空间中单独拷贝一份);第3列为偏移量,为模块内容在文件的偏移;第4列为映射模块的主设备号和次设备号;第5列为映射模块在文件系统中的节点号,如果是文件的话;第6列是映射模块在文件系统中的路径。实际上,这6项是由linux内核的头文件mm.h中的vm_area_struct结构体中的数据成员。


三、模块遍历实现

函数说明:获取某一进程的某一模块的信息,因为没有使用的需求,这里没有返回信息。

参数1:进程的pid

参数2:要搜索的模块名称。

void searchModuleInfo(pid_t pid, const char *pszModName)

{

       FILE *fp;

       char szMapFilePath[32];

       char szMapFileItem[256];

       char *pszStrItem, *pszStrItemBackup;

 

       memeset(szMapFilePath, 0, 32);

       memset(szMapFileItem, 0, 256);

      

       if (pid < 0)

       {

              snprintf(szMapFilePath, 31, "/proc/self/maps");

       }

       else

       {

              snprintf(szMapFilePath, 31, "/proc/%d/maps", pid);

       }

 

       fp = fopen(szMapFilePath, "r");

       if (fp == NULL)

       {

              return ;

       }

 

       while (fgets(szMapFileItem, sizeof(szMapFileItem), fp) != NULL)

       {

              if (strstr(szMapFileItem, pszModName))

              {

                     pszStrItem = strtok_r(szMapFileItem, " t", &pszStrItemBackup); // 地址信息

                     pszStrItem = strtok_r(NULL, " t", &pszStrItemBackup); // 权限信息

                     pszStrItem = strtok_r(NULL, " t", &pszStrItemBackup); // 偏移信息

                     pszStrItem = strtok_r(NULL, " t", &pszStrItemBackup); // 设备信息

                     pszStrItem = strtok_r(NULL, " t", &pszStrItemBackup); // 节点信息

                     pszStrItem = strtok_r(NULL, " t", &pszStrItemBackup); // 路径信息

 

                     if (pszStrItem != NULL) // 判断是否有路径信息

                     {

                            if (pszStrItem[strlen(pszStrItem) - 1] == 'n')

                                   pszStrItem[strlen(pszStrItem) - 1] = 0; // 此为完整路径的模块信息

                     }

 

                     break;

              }

       }

 

       fclose(fp);

 

       return ;

}


*转载请注明来自游戏安全实验室(GSLAB.QQ.COM)

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引