iOS 内存布局

Apple-macho.png

    现代操作系统的内存分配以页为单位进行管理,而页通过段进行管理,组成了段页式内存管理。对于一个典型的进程来说,它的内存空间是由哪些部分组成的?每个部分又被安置在空间的什么位置?

抽象内存布局

代码段

    CPU 运行一个程序,实质就是在顺序执行该程序的机器码。一个程序的机器码会被组织到同一个地方,这个地方就是代码段

  • 可执行指令
  • 在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

数据段

    另外,程序在运行过程中必然要操作数据。这其中,对于有初值的变量,它的初始值会存放在程序的二进制文件中,而且,这些数据部分也会被装载到内存中,即程序的数据段

  • 数据段存放的是程序中已经初始化且不为 0 的全局变量和静态变量

.data 可读/写 .rodata 只读

BSS段

    对于未初始化的全局变量和静态变量,因为编译器知道它们的初始值都是 0,因此便不需要再在程序的二进制映像中存放这么多 0 了,只需要记录他们的大小即可,这便是BSS 段

    数据段和 BSS段里存放的数据也只能是部分数据,主要是全局变量和静态变量,但程序在运行过程中,仍然需要记录大量的临时变量,以及运行时生成的变量,这里就需要新的内存区域了,即程序的堆空间栈空间。与代码段以及数据段不同的是,堆和栈并不是从磁盘中加载,它们都是由程序在运行的过程中申请,在程序运行结束后释放。

堆空间

    堆是向⾼地址扩展的数据结构,是不连续的内存区域。由代码分配和释放,手动申请空间,如果不释放,程序结束时,可能会由操作系统回收 。

  • 优点:
    灵活⽅便,数据适应⾯⼴泛
  • 缺点:
    效率有⼀定降低,容易产生碎片。

栈空间

    栈是向低地址扩展的数据结构,由编译器⾃动分配并释放,存放函数的参数值,局部变量等。栈是系统数据结构,对应线程/进程是唯⼀的。

  • 优点:
    快速⾼效,不会产生碎片
  • 缺点:
    有限制,数据不灵活。(先进后出)

    总的来说,一个程序想要运行起来所需要的几块基本内存区域:代码段、数据段、BSS 段、堆空间和栈空间。下面就是内存布局的示意图:

基本内存区域.png

    这是程序运行起来所需要的最小功能集,除了上面所讲的基本内存区域外,现代应用程序中还会包含其他的一些内存区域,主要有以下几类:

  • 存放加载的共享库的内存空间
    如果一个进程依赖共享库,那对应的,该共享库的代码段、数据段、BSS 段也需要被加载到这个进程的地址空间中。
  • 共享内存段
    我们可以通过系统调用映射一块匿名区域作为共享内存,用来进行进程间通信。
  • 内存映射文件
    我们也可以将磁盘的文件映射到内存中,用来进行文件编辑或者是类似共享内存的方式进行进程通信。

    这样我们就初步了解了一个进程内存中需要哪些区域。

Section 与 Segment

    对于磁盘的程序,每一个单元结构称为 Section。对于内存镜像,每一个单元结构称为 Segment。往往多个 Section 会对应一个 Segment,例如 .text.rodata、等一些只读的 Section,会被映射到内存的一个只读 / 执行的 Segment 里;而 .data.bss 等一些可读写的 Section,则会被映射到内存的一个具有读写权限的 Segment 里。
     总的来说,Section 主要是指在磁盘中的程序段,而 Segment 则用来指代内存中的程序段,Segment 是将具有相同权限属性的 Section 集合在一起,系统为它们分配的一块内存空间
下图展示了部分 Mach-O 文件结构,也展示了在 iOS 中 Section 和 Segment 的关系

Section 和 Segment 的关系

ASLR:内存空间布局随机化

    Mach-O 文件利用两种空间描述,来表达自己在 Mach-O 文件和虚拟内存中不同空间的分配方式。每个 App 都有自己独立的虚拟内存,这个虚拟内存只存在与自己的 Mach-O 文件的 load commands 的描述中。当 App 执行时,会被系统映射到实际的物理内存中。程序一旦编译完成,函数就安静的放在了 __TEXT 段, 全局变量就安静的放在了 __DATA 段上。等用户点击后,才被加载到内存。
    在 iOS 逆向中,通过 Hopper 工具反汇编可以看到函数的虚拟内存地址,但是 Hopper 中展示的内存地址是没有 ASLR 的。想要得到函数的真正函数地址,还需要得到当前 Mach-O 文件在内存中的 ASLR 偏移值。当 App 被加载到内时,系统会自动进行 ASLR ,在 __PAGEZERO 段的上面随机多出一段空间作为偏移,使得 Mach-O 文件的整个虚拟内存向下整体(包括堆,栈,共享库映射等线性布局)偏移。从而可以让生成的函数内存地址不断变动。这样可以提高黑客的破解难道。

那如何得到当前 Mach-O 文件的 ASLR 偏移值呢?

    通过 lldb 调试器的 Mach-O 文件列表查询命令,-o 查询所有使用的 Mach-O 文件包括 dyld 链接编辑器、App 的 Mach-O 文件、dylib 库,得到的第一个结果就是所需要的 ASLR 偏移值。

image list -o -f

APP 的进程内存布局

    一般来说,进程的内存布局是相似的。在iOS App 中是通过 Mach-O 文件从而在虚拟内存中逻辑结构和布局的。关于 Mach-O 可以查看了解 Mach-O 文件Mach-O 文件中不同的内容段 __TEXT__DATA 等在虚拟内存中的内存分布是用 VM AddressVM Size 来描述的;在 Mach-O 本地文件中的空间分布是用 File OffsetFile Size 来描述的

通过代码输出变量及常量的地址

int a = 10;                   //已初始化全局变量
int b;                        //未初始化全局变量
const int testConst =  20; //const 常量

int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
        static int c = 20;    //已初始化静态变量
         
         static int d;         //未初始化静态变量
         
         int e;                //未初始化局部变量

         int f = 20;           //已初始化局部变量

         NSString *str = @"123";//字符串常量
         
         NSObject *obj = [[NSObject alloc] init];//通过alloc动态分配(实例对象)
         
         NSLog(@"\n&a=%p\n&b=%p\n&c=%p\n&d=%p\n&e=%p\n&f=%p\nstr=%p\nobj=%p\n&testConst=%p",
               &a, &b, &c, &d, &e, &f, str, obj,&testConst);
        // Setup code that might create autoreleased objects goes here.
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

通过输出地址以及 image list -o -f 查看到的 dylibdyld 地址信息,得到下面 iOS 内存布局的示意图

iOS 内存布局的示意图

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335