热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MachO的动态链接

对于存在别的动态库的函数,程序在运行的时候需要通过动态链接来获取函数的调用地址,在iOS上是通过dyld来实现的,下面来通过离子来做一下梳理-(void)vie

对于存在别的动态库的函数,程序在运行的时候需要通过动态链接来获取函数的调用地址,在iOS上是通过dyld来实现的,下面来通过离子来做一下梳理

- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. NSLog(@"first call"); NSLog(@"second call"); }

然后在两个NSLog都打上断点,运行。
程序断住之后,调节成汇编模式Debug –> Debug Workflow –> Always Show Disassembly,

留意到symbol stub for: NSLog 这句,这句就是跳转到NSLog的stub实现imp___stubs__NSLog
我们先用image list命令来获取模块的基地址

[ 0] 612400A7-6AEC-3714-842C-F83B079272BE 0x0000000100060000 /Users/apple/Library/Developer/Xcode/DerivedData/MachO的动态链接-dyjjhckpseuoonetiqiafxmmlsak/Build/Products/Debug-iphoneos/MachO的动态链接.app/MachO的动态链接

0x0000000100060000 是这次运行时模块的基地址,因为iOS有ASLR,每次都会随机装到内存,随机只是偏移,并不是打乱,所以程序运行时候的及地址为:静态的基地址 + ASLR偏移,静态的基地址可以使用machOview来查看

静态基地址 = 0000000100000000;

MachO的动态链接
Snip20200423_41.png

所以这次运行的偏移地址ASLR偏移 = 0x0000000100060000 – 0000000100000000 = 0x60000

回到刚刚的bl 0x1000e2560 ; symbol stub for: NSLog,我们可以去看看这个地址里面究竟是什么代码,先求出它对应的 静态地址=运行时地址-ASLR偏移 = 0x100066554 – 0x60000 = 0x100006554。然后用hopper打开,记住不勾选Resolve Lazy Bindings,跳转到该地址,如下

imp___stubs__NSLog: 0000000100006554 nop ; CODE XREF=-[ViewController viewDidLoad]+72, -[ViewController viewDidLoad]+84 0000000100006558 ldr x16, #0x100008008 000000010000655c br x16

这几句代码是取值之后跳转,先看看#0x100008008的值,单击点进去。这里有个坑,如果你用hopper导入的时候选择了Resolve Lazy Binding,那么这个地址会解析成了符号。所以导入的时候不要选,那么可以看到这个地址的值如下:

0000000100008008 dq 0x00000001000065fc ; DATA XREF=imp___stubs__NSLog+4

MachO的动态链接
Snip20200422_32.png

所以上面的几句汇编的意思是跳转0x00000001000065fc这个地址,然后我们再切到这个地址看看。
00000001000065fc ldr w16, #0x100006604 ; DATA XREF=_NSLog_ptr
0000000100006600 b 0x1000065e4

在这里压入一个参数之后,继续跳转到 0x1000065e4执行,继续跟入到这里,终于找到了stub_helper的调用。

MachO的动态链接
Snip20200423_42.png

,然后就会进入动态绑定

MachO的动态链接
Snip20200423_43.png

这个时候在终端si进入单步调试,发现第一次调用时候

MachO的动态链接
Snip20200422_28.png

NSLog方法跳转的是0x00000001000ce5fc,当第二次执行的时候,发现已经是拿到了真正的函数地址

MachO的动态链接
Snip20200422_33.png

但是这里其仍然是取的静态地址0x100008008处的值,只不过这个值已经变成了0x000000018248e598

我们可以打印一下静态地址0x1000e2560对应的动态地址0x1000e2560+ 0x60000 = 0x100068008,确实已经变成了0x000000018248e598

(lldb) x 0x100068008 0x100068008: 98 e5 48 82 01 00 00 00 98 e5 47 82 01 00 00 00 ..H.......G..... 0x100068018: 60 70 c2 87 01 00 00 00 14 66 06 00 01 00 00 00 `p.......f......

然后进入0x18248e598这个地址,你会发现这里就是NSLog的函数入口

Foundation`NSLog: -> 0x18248e598 : sub sp, sp, #0x20 ; =0x20 0x18248e59c : stp x29, x30, [sp, #0x10] 0x18248e5a0 : add x29, sp, #0x10 ; =0x10 0x18248e5a4 : add x8, x29, #0x10 ; =0x10 0x18248e5a8 : str x8, [sp, #0x8] 0x18248e5ac : add x1, x29, #0x10 ; =0x10 0x18248e5b0 : mov x2, x30 0x18248e5b4 : bl 0x1825673c0 ; _NSLogv 0x18248e5b8 : ldp x29, x30, [sp, #0x10] 0x18248e5bc : add sp, sp, #0x20 ; =0x20 0x18248e5c0 : ret

附上刚刚image list的另外一个模块,你会发现0x000000018248e598这个地址已经是另外模块的了。

[ 2] 73FF2B76-D90F-3C90-B010-8F6E36E3B71F 0x000000018247c000 /Users/apple/Library/Developer/Xcode/iOS DeviceSupport/10.3.1 (14E304)/Symbols/System/Library/Frameworks/Foundation.framework/Foundation

这个就是MachO的懒加载符号表的加载过程。第一次调用的时候是指向stub_helper,调用完一次之后,就会修改懒加载符号指针,让其指向真正的函数地址,以后就可以直接跳转。这个可以从第一次调用和第二次调用的MachO二进制文件看到

MachO的动态链接
Snip20200422_36.png

从上面的图可以知道0x100008008 这个位置就是Lazy Symbol Pointers,并且从MachOView看到最后边的value值,0x100008008对应的就是NSLog,那这个对应关系是怎么来的呢?先看一下Dynamic Symbol Table 下的Indirect Symbols,点击右上角,搜索NSLog

MachO的动态链接
Snip20200423_44.png

发现这里有两条记录,且两条记录的值是一样的,而且看MachOview解析出来的value,你会发现一个和TEXT段的_stubs 有关系,一个和DATA段的_la_symbol_ptr 有关系,这个关系是从哪里来的呢?先从_la_symbol_ptr的来说明,先找到下面的地方,section header 的_la_symbol_ptr

MachO的动态链接
Snip20200422_40.png

首先Address指的是这个section的真实地址,这里你会发现Lazy Symbol Pointers的表的起始文件偏移就是这个地址减去基地址,然后是Indirect Sym Index这个字段,在代码里面是Reserved1这个属性,在MachOView里面显示的是十进制13,起始这是一个索引偏移,指的是Lazy Symbol Pointers表中对应元素的第几个,这里是13,然后Indirect Symbols么个元素是4个字节,所以这里距离Indirect Symbols表头是偏移13 * 4 = 52字节 = 0x34,然后Indirect Symbols表头的文件偏移是0xD358,两个之和0xD358 + 0x34 = 0xD38C;

MachO的动态链接
Snip20200423_46.png

到这里,已经找到了Lazy Symbol Pointers表和Indirect Symbols表的对应关系,至于stubs表和Indirect Symbos表,同理可得。

跟住下来就是Indirect Symbols表是怎么找到”_NSLog” 这个字符的,留意上面的Data值000000D3,转为十进制是211,这个数值对应的就是Symbol Table的元素索引,找到Symbol Table 的第211个元素,如下图:

MachO的动态链接
Snip20200423_47.png

留意Data值000000CE,这个就是string Table的偏移,继续去到String Table,它的起始文件偏移是0000D3BC

MachO的动态链接
Snip20200423_48.png

然后找到文件偏移的位置,0000D3BC + 000000CE = 0xD48A

MachO的动态链接
Snip20200423_49.png

推荐阅读
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文讨论了如何在不使用SearchBar display controller的情况下,单独使用SearchBar并捕获其textChange事件。作者介绍了实际状况,即左侧SliderMenu中的SearchBar需要在主页TableView中显示搜索结果。然后,作者提供了解决方案和步骤,帮助读者实现这一功能。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • IOS开发之短信发送与拨打电话的方法详解
    本文详细介绍了在IOS开发中实现短信发送和拨打电话的两种方式,一种是使用系统底层发送,虽然无法自定义短信内容和返回原应用,但是简单方便;另一种是使用第三方框架发送,需要导入MessageUI头文件,并遵守MFMessageComposeViewControllerDelegate协议,可以实现自定义短信内容和返回原应用的功能。 ... [详细]
  • MVC设计模式的介绍和演化过程
    本文介绍了MVC设计模式的基本概念和原理,以及在实际项目中的演化过程。通过分离视图、模型和控制器,实现了代码的解耦和重用,提高了项目的可维护性和可扩展性。详细讲解了分离视图、分离模型和分离控制器的具体步骤和规则,以及它们在项目中的应用。同时,还介绍了基础模型的封装和控制器的命名规则。该文章适合对MVC设计模式感兴趣的读者阅读和学习。 ... [详细]
  • macOS Big Sur全新设计大版本更新,10+个值得关注的新功能
    本文介绍了Apple发布的新一代操作系统macOS Big Sur,该系统采用全新的界面设计,包括图标、应用界面、程序坞和菜单栏等方面的变化。新系统还增加了通知中心、桌面小组件、强化的Safari浏览器以及隐私保护等多项功能。文章指出,macOS Big Sur的设计与iPadOS越来越接近,结合了去年iPadOS对鼠标的完善等功能。 ... [详细]
  • Asp.net Mvc Framework 七 (Filter及其执行顺序) 的应用示例
    本文介绍了在Asp.net Mvc中应用Filter功能进行登录判断、用户权限控制、输出缓存、防盗链、防蜘蛛、本地化设置等操作的示例,并解释了Filter的执行顺序。通过示例代码,详细说明了如何使用Filter来实现这些功能。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • Todayatworksomeonetriedtoconvincemethat:今天在工作中有人试图说服我:{$obj->getTableInfo()}isfine ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
author-avatar
WingKeii-
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有