Android漫游记(1)---内存映射镜像(memory maps)

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)

时间: 2024-10-12 17:59:42

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

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

原文:C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). 内存映射文件对于托管世界的开发人员来说似乎很陌生,但它确实已经是很远古的技术了,而且在操作系统中地位相当.实际上,任何想要共享数据的通信模型都会在幕后使用它. 内存映射文件究竟是个什么?内存映射文件允许你保留一块地址空间,然后将该物理存储映射到这块内存空间中进行操作.物理存储是文件管理,而内存

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

节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). 内存映射文件对于托管世界的开发人员来说似乎很陌生,但它确实已经是很远古的技术了,而且在操作系统中地位相当.实际上,任何想要共享数据的通信模型都会在幕后使用它. 内存映射文件究竟是个什么?内存映射文件允许你保留一块地址空间,然后将该物理存储映射到这块内存空间中进行操作.物理存储是文件管理,而内存映射文件是操作系统级内存管理. 优势:     1.访问磁盘文件上的数据不需执行I/O操作和缓存

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

转自:http://blog.chinaunix.net/uid-25909619-id-4194650.html 底板芯片组与内存映射 我打算写一些关于计算机内部构造(computer internal)的博文(post),以解释现代操作系统内核是如何工作的.希望对一些在这方面没有经验,又感兴趣的程序员和爱好者(enthusiasts and programmers)提供些帮助.这些博文主要关注于Linux,Windows,以及Intel处理器.计算机的内部构造是我的兴趣之一.我曾经写过一些类

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

一.Ashmem驱动程序 ~/Android/kernel/goldfish ----include ----linux ----ashmem.h ----mm ----ashmem.c 驱动程序具体解释请看<Android系统源码情景分析>.作者罗升阳. 二.执行时库cutils的匿名共享内存訪问接口 ~/Android/system/core ----libcutils ----ashmem-dev.c 具体解释请看<Android系统源码情景分析>,作者罗升阳. 三.Memo

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

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6664554 在上一文章Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划中, 我们简要介绍了Android系统的匿名共享内存机制,其中,简要提到了它具有辅助内存管理系统来有效地管理内存的特点,但是没有进一步去了解它是如何实 现的.在本文中,我们将通过分析Android系统的匿名共享内存

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

一.Ashmem驱动程序 ~/Android/kernel/goldfish ----include ----linux ----ashmem.h ----mm ----ashmem.c 驱动程序详解请看<Android系统源代码情景分析>,作者罗升阳. 二.运行时库cutils的匿名共享内存访问接口 ~/Android/system/core ----libcutils ----ashmem-dev.c 详解请看<Android系统源代码情景分析>,作者罗升阳. 三.Memory

android自带的内存memory和第三方外部存储disk管理

/** * @author [email protected] * @time 20140606 */ package com.intbird.utils; import java.io.File; import com.yilake.store.FileHelper; import android.graphics.Bitmap; import android.os.Environment; import android.util.LruCache; public class CacheMan

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

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6666491 在前面一篇文章Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析中,我们系统地介绍了Android系统匿名共享内存的实现原理,其中着重介绍了它是如何辅助内存管理系统来有效地管理内存的,在再前面一篇文章Android系统匿名共享内存Ashmem(Anonymous Share

记一次内存泄露调试(memory leak)-Driver Monkey

Author:DriverMonkey Mail:[email protected] Phone:13410905075 QQ:196568501 硬件环境:AM335X 软件环境:linux 3.2 现象:1)系统运行一晚上,配置硬件操作失效 2)系统放置在那,没有用户输入会自己死机 调试过程: 第一步:分析硬件配置失效原因,怀疑配置硬件代码有问题 最后发现 代码 调用 system() 函数配置硬件没有调用成功 返回值 为 -1. 第二步: 继续上一步 分析 system() 在什么情况下会