Android系统内核基于Linux2.6+内核,因此,其在进程内存管理方面的非常多机制和Linux是非常相像的。首先,让我们来看一个典型的Android进程的内存镜像(App进程和Native本地进程略有区别,但原理是一样的):

和Linux一样,Android提供了基于/proc的“伪文件”系统来作为查看用户进程内存映像的接口(cat /proc/pid/maps)。能够说,这是Android系统内核层开放给用户层关于进程内存信息的一扇窗户。通过它,我们能够查看到当前进程空间的内存映射情况,模块载入情况以及虚拟地址和内存读写运行(rwxp)属性等。

首先我们来解读下上面的maps。

以libc.so为例:

第一列:400dd000------40142000  ,能够看出这是内存中连续的地址空间,分成了3个子空间,分为400dd000-40142000,40142000-40144000,40144000-40146000。你可能会问了,既然是载入libc.so,为什么要载入3次?好问题!

我们继续看第二列:r-xp  r--p   rw-p。当中r表示仅仅读,w表示可写,x表示可运行,p表示私有(s表示共享)。让我们看一下libc.so的elf的程序头和段说明部分内容(ELF为类unix的可运行或共享镜像的格式,类似于windows PE格式,兴许漫游系列具体解说),我们能够通过Google提供的Android NDK Toolchains工具链的arm-linux-androideabi-readelf来读取(arm-linux-androideabi-readelf  -a libc.so).

这块我们不具体解析,重点关注上图中我标记的两块内容。LOAD表示该段须要载入到内存,Flg标志表示该段在内存镜像中的属性,至此,能够基本回答上面的问题了。内核在载入libc.so的时候,參照ELF程序头,来讲段一一映射到内存。因为libc.so包括了代码段、数据段等,因此依照不同的属性映射到不同的位置。

如上面的400dd000-40142000包括了.text  .plt等Section,而40142000-40144000,40144000-40146000则包括了.data  .bss .got等Section。

总结一下:libc.so在被映射到内存的时候,内核是依据elf程序头来一一映射“组装的”,不同类型的段被映射到不同区域。

以下,我们来看一下Linux内核提供的内存映射API(mmap)。

       #include <sys/mman.h>

       void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

參数:

addr  : 要映射的内存地址參考,内核依照这个地址来动态决定新分配的内存位置

length :大小(bytes)

prot :

       PROT_EXEC  Pages may be executed.//可运行

       PROT_READ  Pages may be read.//可读

       PROT_WRITE Pages may be written.//可写

       PROT_NONE  Pages may not be accessed.//不可訪问

flags:

       MAP_SHARED Share this mapping.  Updates to the mapping are visible to
other processes that map this file, and are carried
through to the underlying file. The file may not actually
be updated until msync(2) or munmap() is called. MAP_PRIVATE
Create a private copy-on-write mapping. Updates to the
mapping are not visible to other processes mapping the
same file, and are not carried through to the underlying
file. It is unspecified whether changes made to the file
after the mmap() call are visible in the mapped region.

fd和offset表示要映射的文件句柄和初始偏移,如为空,相当于分配一块空的内存块,mmap返回映射后的内存块基址。实际上内核就是调用mmap一步一步把elf文件搬到内存的。

写到这里,我们开个小差,具体研究下mmap的prot參数,如上面所说,该标志表示将映射内存块的读写以及运行属性,而Linux除了初始映射的时候能够设置内存属性以外,在载入到内存后,依旧能够改动其属性(需root权限),这就有点意思了,这意味着我们能够在进程运行的时候,动态改动其内存属性(除了内核vsyscall区域),具体这能干些啥,你懂的

看API(mprotect

       #include <sys/mman.h>

       int mprotect(void *addr, size_t len, int prot);

參数:

addr:要改动的内存基址(必须页面对齐,page size的倍数,一般为4K对齐)

len:大小(bytes)

prot:改动后的rwx属性。

看到这里,那些所谓的游戏”辅助、外挂“都笑了!

我们最好还是写一段代码看看mproject和mmap能干些啥!

/*
* mmap & mprotect call
* Created on: 2014-6
* Author: Chris.Z
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <errno.h> int main()
{
void* membase = NULL;
printf("[+]call mmap to alloc memory,size of 4k btyes\n");
membase = mmap(NULL,0x1000,PROT_READ,MAP_ANONYMOUS|MAP_PRIVATE,NULL,NULL);
if(membase == MAP_FAILED)
{
printf("[+]mmap failed with errno:%d\n",errno);
return 1;
}
printf("[+]allocated memory base:0x%x\n",membase);
if(getchar())
{
printf("[+]modify the addr:0x%x prots to rwx\n",membase);
mprotect(membase,0x1000,PROT_READ|PROT_WRITE|PROT_EXEC);
}
if(getchar())
free(membase);
return 0;
}

上面的代码段,我们让内核在当前进程内存空间分配一片大小为4K的匿名内存,初始属性为”仅仅读“,然后我们调用mprotect将其属性改为”rwx“。看执行结果:

能够看到我们分配后的内存块的基址为:0x401da000,查看进程maps,发现确实已分配属性为"r--p"的内存块,结束地址为0x401db000,大小为0x1000,正好4K。

输入回车后,我们看到的结果:

到这里,我们知道了怎样在当前进程动态的分配一块页面对齐的内存,同一时候改动其属性,当然这里演示的是对于当前进程的操作,假设要操作一个第三方的进程,还须要一些其它的玩意儿,比方进程附加、注入之类的操作,这个后面慢慢讲!

好了,就写到这里,Enjoy IT!

转载请注明出处:生活秀

Android漫游记(1)---内存映射镜像(memory maps)的更多相关文章

  1. C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 VC中进程与进程之间共享内存 .net环境下跨进程、高频率读写数据 使用C#开发Android应用之WebApp 分布式事务之消息补偿解决方案

    C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). ...

  2. C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转

    原文:C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing ...

  3. C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped

    节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). 内存映射文件对于托管世界的开发人员来说似乎很陌生,但它确实已经是很远古的技术了,而且在操作 ...

  4. 底板芯片组与内存映射(Motherboard Chipsets and the Memory Map) 【转】

    转自:http://blog.chinaunix.net/uid-25909619-id-4194650.html 底板芯片组与内存映射 我打算写一些关于计算机内部构造(computer intern ...

  5. Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6939890 在Android系统中,针对移动设 ...

  6. Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6664554 在上一文章Android系统匿名共 ...

  7. Android系统匿名共享内存(Anonymous Shared Memory)Java调用接口分析

    一.Ashmem驱动程序 ~/Android/kernel/goldfish ----include ----linux ----ashmem.h ----mm ----ashmem.c 驱动程序具体 ...

  8. Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6666491 在前面一篇文章Android系统匿 ...

  9. Android 内存管理 &amp;Memory Leak &amp; OOM 分析

    1.Android 流程管理&内存 Android主要应用在嵌入式设备其中.而嵌入式设备因为一些众所周知的条件限制,通常都不会有非常高的配置,特别是内存是比較有限的. 假设我们编写的代 码其中 ...

随机推荐

  1. c++编程碰到的奇怪问题与解决

    今天写一个工具,调试过程中莫名其妙崩溃,类某些成员变量指针很奇怪,为0x00003001.最后检查的结果居然是这样的: 文件class1.h: class1 { int a; int b; } 文件: ...

  2. leetcode先刷_Unique Paths II

    那么上述问题,假设这个矩阵堵塞障碍,不能在若干组合前面所用的方法,因为这么多的位置实际上是没有办法的事儿. 还有剩下的唯一合理的解决方案dp该.与最低要求,并且等,从右下角以前突起,对于位置(i, j ...

  3. 0112.1——iOS开发之理解iOS中的MVC设计模式

    模型-视图-控制器(Model-View-Controller,MVC)是Xerox PARC在20世纪80年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已广泛应用于用户交互应用程 ...

  4. (原)不明白JNI指针调用顺序

    很不明白JNI里面获取指针的顺序(可能这样描述不太恰当吧). 下面按照传入指针的顺序的代码一跑就崩溃.如下: JNIEXPORT jint JNICALL Java_com_example_X_XX_ ...

  5. JDBC学习入门

    一.JDBC相关概念介绍 1.1.数据库驱动 这里的驱动的概念和平时听到的那种驱动的概念是一样的,比如平时购买的声卡,网卡直接插到计算机上面是不能用的,必须要安装相应的驱动程序之后才能够使用声卡和网卡 ...

  6. 基于jQuery UI的tabs选项卡美化

    很多朋友对JS望而生畏,但听很多朋友说jQuery很简单,因此开始使用jQuery,使用之后发现,只会写简单的功能,复杂的功能还是不太会写或者总是担心自己写的有性能问题,对前端人员来说只能通过不断学习 ...

  7. 评论PK投票功能的手机版

    ajax投票.点赞.回复,投票后自动转到查看投票结果,投票结果进度条动画显示 地址:http://files.cnblogs.com/files/macliu/hyw_wap.rar 效果图: 首页:

  8. zabbix之3触发器/action及模板

    1.触发器: {server_name:item_name.func.operator.condition} 一旦condition(条件)触发,则item状态改变 触发器之间可以存在依赖关系,即it ...

  9. R语言数据合并使用merge数据追加使用rbind和cbind

    R语言中的横向数据合并merge及纵向数据合并rbind的使用 我们经常会遇到两个数据框拥有相同的时间或观测值,但这些列却不尽相同.处理的办法就是使用merge(x, y ,by.x = ,by.y ...

  10. Database Go and JSON

    在使用Go开发web项目的过程中, 数据库读写操作与JSON格式的输入输出是两块最基础的模块, Go的标准库已经帮我们做了很多, 熟悉database/sql与encoding/json这两个库能帮我 ...