(八)Mach-O小试牛刀

1. Mach-O小试牛刀

1.1 温习Mach-O

segment是磁盘和内存中具有相同内存保护的分组。在一个分组中,segment可以有零个或多个section

section是在segment中找到的子组件。他们对程序有专门的作用。例如,有一个特定的section用于编译代码,另一个section用于硬编码字符串。

sectionsegment加载命令决定。加载命令位于可执行文件的开头,紧跟在Mach-O header之后。

其中有几个重要的segment__TEXT__DATA__LINKEDIT

1.2 Mach-O sections

这里有一个名为MachOFun的iOS项目。这是一个简单的基于UITabBarController的应用程序,它分隔了我们将在这里实现的不同示例。

其中一个选项是带有一些占位符数据的UITableViewController。首先构建一个数据源,在内存中查找所有硬编码的不安全HTTP URL,然后在UITableView中将它们显示为“public shaming”。

另一个标签显示了一个相当丑陋的老虎机,实现赌博的目的。我们将使用Mach-O知识欺骗系统,并始终获胜。

MachOFun

我们来看一下项目所有的section

(lldb) image dump sections MachOFun
Sections for '/Users/xxx/Library/Developer/Xcode/DerivedData/MachOFun-gsmnrawhxbagdmhjegfsuaqahrqq/Build/Products/Debug-iphonesimulator/MachOFun.app/MachOFun' (x86_64):
  SectID     Type             Load Address                             Perm File Off.  File Size  Flags      Section Name
  ---------- ---------------- ---------------------------------------  ---- ---------- ---------- ---------- ----------------------------
  0x00000100 container        [0x0000000000000000-0x0000000100000000)* ---  0x00000000 0x00000000 0x00000000 MachOFun.__PAGEZERO
  0x00000200 container        [0x000000010947a000-0x0000000109489000)  r-x  0x00000000 0x0000f000 0x00000000 MachOFun.__TEXT
  0x00000001 code             [0x000000010947b1a0-0x0000000109485cda)  r-x  0x000011a0 0x0000ab3a 0x80000400 MachOFun.__TEXT.__text
  0x00000002 code             [0x0000000109485cda-0x0000000109485ef0)  r-x  0x0000bcda 0x00000216 0x80000408 MachOFun.__TEXT.__stubs
  0x00000003 code             [0x0000000109485ef0-0x000000010948627a)  r-x  0x0000bef0 0x0000038a 0x80000400 MachOFun.__TEXT.__stub_helper
  0x00000004 regular          [0x0000000109486280-0x0000000109486507)  r-x  0x0000c280 0x00000287 0x00000000 MachOFun.__TEXT.__const
  0x00000005 data-cstr        [0x0000000109486507-0x00000001094873a2)  r-x  0x0000c507 0x00000e9b 0x00000002 MachOFun.__TEXT.__objc_methname
  0x00000006 data-cstr        [0x00000001094873b0-0x00000001094888c3)  r-x  0x0000d3b0 0x00001513 0x00000002 MachOFun.__TEXT.__cstring
  0x00000007 regular          [0x00000001094888c4-0x0000000109488a39)  r-x  0x0000e8c4 0x00000175 0x00000000 MachOFun.__TEXT.__swift5_typeref
  0x00000008 regular          [0x0000000109488a3c-0x0000000109488b3c)  r-x  0x0000ea3c 0x00000100 0x00000000 MachOFun.__TEXT.__swift5_capture
  0x00000009 regular          [0x0000000109488b40-0x0000000109488ba6)  r-x  0x0000eb40 0x00000066 0x00000000 MachOFun.__TEXT.__swift5_reflstr
  0x0000000a regular          [0x0000000109488ba8-0x0000000109488c48)  r-x  0x0000eba8 0x000000a0 0x00000000 MachOFun.__TEXT.__swift5_fieldmd
  0x0000000b regular          [0x0000000109488c48-0x0000000109488c58)  r-x  0x0000ec48 0x00000010 0x00000000 MachOFun.__TEXT.__swift5_types
  0x0000000c regular          [0x0000000109488c58-0x0000000109488dd4)  r-x  0x0000ec58 0x0000017c 0x00000000 MachOFun.__TEXT.__entitlements
  0x0000000d compact-unwind   [0x0000000109488dd4-0x0000000109489000)  r-x  0x0000edd4 0x0000022c 0x00000000 MachOFun.__TEXT.__unwind_info
  0x00000300 container        [0x0000000109489000-0x000000010948c000)  rw-  0x0000f000 0x00003000 0x00000000 MachOFun.__DATA
  0x0000000e data-ptrs        [0x0000000109489000-0x0000000109489008)  rw-  0x0000f000 0x00000008 0x00000006 MachOFun.__DATA.__nl_symbol_ptr
  0x0000000f data-ptrs        [0x0000000109489008-0x00000001094890d0)  rw-  0x0000f008 0x000000c8 0x00000006 MachOFun.__DATA.__got
  0x00000010 data-ptrs        [0x00000001094890d0-0x0000000109489398)  rw-  0x0000f0d0 0x000002c8 0x00000007 MachOFun.__DATA.__la_symbol_ptr
  0x00000011 data-ptrs        [0x0000000109489398-0x00000001094893a0)  rw-  0x0000f398 0x00000008 0x00000009 MachOFun.__DATA.__mod_init_func
  0x00000012 regular          [0x00000001094893a0-0x0000000109489688)  rw-  0x0000f3a0 0x000002e8 0x00000000 MachOFun.__DATA.__const
  0x00000013 data-ptrs        [0x0000000109489688-0x00000001094896a8)  rw-  0x0000f688 0x00000020 0x10000000 MachOFun.__DATA.__objc_classlist
  0x00000014 regular          [0x00000001094896a8-0x00000001094896b8)  rw-  0x0000f6a8 0x00000010 0x10000000 MachOFun.__DATA.__objc_catlist
  0x00000015 regular          [0x00000001094896b8-0x00000001094896d8)  rw-  0x0000f6b8 0x00000020 0x00000000 MachOFun.__DATA.__objc_protolist
  0x00000016 regular          [0x00000001094896d8-0x00000001094896e0)  rw-  0x0000f6d8 0x00000008 0x00000000 MachOFun.__DATA.__objc_imageinfo
  0x00000017 data-ptrs        [0x00000001094896e0-0x000000010948b258)  rw-  0x0000f6e0 0x00001b78 0x00000000 MachOFun.__DATA.__objc_const
  0x00000018 data-cstr-ptr    [0x000000010948b258-0x000000010948b338)  rw-  0x00011258 0x000000e0 0x10000005 MachOFun.__DATA.__objc_selrefs
  0x00000019 regular          [0x000000010948b338-0x000000010948b358)  rw-  0x00011338 0x00000020 0x00000000 MachOFun.__DATA.__objc_protorefs
  0x0000001a data-ptrs        [0x000000010948b358-0x000000010948b370)  rw-  0x00011358 0x00000018 0x10000000 MachOFun.__DATA.__objc_classrefs
  0x0000001b data-ptrs        [0x000000010948b370-0x000000010948b620)  rw-  0x00011370 0x000002b0 0x00000000 MachOFun.__DATA.__objc_data
  0x0000001c data             [0x000000010948b620-0x000000010948b7a5)  rw-  0x00011620 0x00000185 0x00000000 MachOFun.__DATA.__data
  0x0000001d regular          [0x000000010948b7a8-0x000000010948b860)  rw-  0x000117a8 0x000000b8 0x00000000 MachOFun.__DATA.__swift_hooks
  0x0000001e zero-fill        [0x000000010948b860-0x000000010948b8b8)  rw-  0x00000000 0x00000000 0x00000001 MachOFun.__DATA.__bss
  0x0000001f zero-fill        [0x000000010948b8b8-0x000000010948b8c0)  rw-  0x00000000 0x00000000 0x00000001 MachOFun.__DATA.__common
  0x00000400 container        [0x000000010948c000-0x00000001094a5000)  r--  0x00012000 0x00018de0 0x00000000 MachOFun.__LINKEDIT

我们可以看到一下这个section

0x00000001 code  [0x000000010947b1a0-0x0000000109485cda)  r-x  0x000011a0 0x0000ab3a 0x80000400 MachOFun.__TEXT.__text
  • 分析这个输出,0x00000001LLDB标识section的方法。
  • LLDB已将内容标识为代码(code)
  • 括号中的地址是section在内存中的位置。
  • 0x000011a0是磁盘上的偏移量,而0x0000ab3a是磁盘上section的大小。
  • 最后,flag值为0x80000400,它是S_ATTR_SOME_INSTRUCTIONSS_ATTR_PURE_INSTRUCTIONS。详情可以查看mach-o/loader.h

注意:磁盘上的sectionsegment的大小可能与加载到内存时的大小不同。这将由Mach-O加载命令决定的。例如,__PAGEZERO段在磁盘上占用0字节。但当加载到内存中时,它占用64位进程中的前2^32位。使用otool -l /user/bin/ls | grep "Load command 0" -A11可以验证这一点。filesize变量为0,vmsize变量为0x00000001000000002^32

使用LLDB,我们可以获取任何方法或函数,并找到它所在的部分。

(lldb) image lookup -n "-[UIViewController viewDidLoad]"
1 match found in /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore:
        Address: UIKitCore[0x0000000000438886] (UIKitCore.__TEXT.__text + 4414950)
        Summary: UIKitCore`-[UIViewController viewDidLoad]

方法-[UIViewController viewDidLoad]位于UIKitCore中。上面的输出给出了UIKitCore模块的完整路径。通过UIKitCore[0x0000000000438886]显示磁盘上的偏移量;它包含在UIKitCore.__TEXT.__text的偏移量4414950处。

清除屏幕并再次运行image dump sections MachOFun LLDB命令。这一次,搜索MachOFun.文本。cstring部分。

下面我们看看MachOFun.__TEXT.__cstring这个section

0x00000006 data-cstr  [0x00000001094873b0-0x00000001094888c3)  r-x  0x0000d3b0 0x00001513 0x00000002 MachOFun.__TEXT.__cstring

这是存储UTF-8硬编码字符串的地方。用于打印语句、键值编码/观察或源代码中介于“”之间的任何其他内容。使用LLDB,通过引用大小和开始加载地址来查看此部分中的内存。

memory read -r -fC -c 0x00001513 0x00000001094873b0

这将打印从地址0x00000001094873b0开始的内存。将输出格式化为可打印字符-fC,重复处理0x00001513次,并强制-r打印每次计数,因为LLDB默认为1024字节的上限。我们将在这里看到大量熟悉的字符串,例如"Unexpectedly found nil while unwrapping an Optional value"。

许多其他section包含用于不同目的的UTF-8字符串。例如__TEXT.__objc_methname包含OC方法名由应用程序直接引用。__TEXT.__swift5_reflstr包含对Swift映射项目的引用。Swift的其中一个运行时反射,将引用IBOutletIBInspectable变量。

注意:除了__TEXT.__cstring section,还有__TEXT.__ustring section,存储UTF-16编码字符串。这些字符串是UTF-16编码的,所以需要使用大小适当的字符(char16_t *)来查看它们。

1.3 查找HTTP字符串

既然已经知道硬编码的UTF-8字符串存储在模块的__TEXT.__cstring中。下面搜索进程中的每个模块,以查看是否有任何字符串以“http:”开头的字符串。
打开InsecureNetworkRequestsTableViewController.swift

import MachO

然后在setupDataSource方法的内容替换为:

for i in 0..<_dyld_image_count() {
      let imagePath = _dyld_get_image_name(i)!
      let name = String(validatingUTF8: imagePath)!
      let basenameString = (name as NSString).lastPathComponent
      var module : InsecureHTTPRequestsData = (basenameString, [])
      var rawDataSize: UInt = 0
      guard let rawData = getsectdatafromFramework(basenameString,
                                                   "__TEXT",
                                                   "__cstring",
                                                   &rawDataSize) else { continue }
      print("__TEXT.__cstring data: \(rawData), \(basenameString)")
    }

getsectdatafromFramework函数接受模块名、包含segment名和section名,并将指针指向section在内存中的位置。此外,还有一个名为rawDataSizeinout变量,给出内存中section的大小。

运行一下。我们将看到每个包含__TEXT.__cstring的模块以及它们在模块中的加载地址。

__TEXT.__cstring data: 0x00000001021f85e0, dyld_sim
__TEXT.__cstring data: 0x000000010218f3b0, MachOFun
...

点击暂停。查询dyld_sim的加载地址:

(lldb) image lookup -a 0x00000001021f85e0
      Address: dyld_sim[0x000000000004a5e0] (dyld_sim.__TEXT.__cstring + 0)
      Summary: "rebaseDyld"

dyld_sim[0x000000000004a5e0]显示磁盘上__TEXT.__cstring的偏移量。请记住,如果可执行文件是具有多个架构扇区的胖可执行文件,那么这可能不是磁盘上的最终偏移量。使用LLDB,在dyld_sim.__TEXT.__cstring打印出第一个字符串:

(lldb) x/s 0x00000001021f85e0
0x1021f85e0: "rebaseDyld"

编译到dyld_sim模块中的第一个硬编码字符串是字符串rebaseDyld

我们已经找到了__TEXT.__cstring section的起始地址。现在是解析整个内存缓冲区,搜索以“http:”开头的字符串的时候了。这个内存缓冲区是一堆UTF-8C字符串。这意味着您需要一直解析字符串直到达到NULL
打开InsecureNetworkRequestsTableViewController.swift并在setupDataSource()中,删除先前的print语句并替换为:

var index = 0
while index < rawDataSize {
  let cur = rawData.advanced(by: index)
  let length = strlen(cur)
  index = index + length + 1
  guard let str = String(utf8String: cur),
    length > 0 else { continue }
  if str.hasPrefix("http:") {
    module.strings.append(str)
  }
}

if module.strings.count > 0 {
  dataSource.append(module)
}

这段代码将获取指向内存中一个__TEXT.__cstring sectionrawDatawhile循环执行几个检查,确保存在长度大于0的有效UTF-8字符串。如果是,则检查字符串的开头是否包含字符“http:”。如果是,则将字符串添加到字符串数组中。最后,如果模块有任何包含“http:”的字符串,则该字符串将添加到dataSource变量中。

最后,在MachOFun模块中设置一个受控测试,以确保这段代码能正确的工作。在viewDidLoad中添加:

let _ = "https://www.baidu.com" 
let _ = "http://www.weibo.com"

运行一下。

测试

正如我们所看到的,https://www.baidu.com没在里面,http://www.weibo.com在里面。并且,不仅在MachOFun中有许多不安全的硬编码URL,像libxml2.2dylibGeoServicesCFNetwork等模块中也有。

1.4 __DATA segment中的sections

暂停MachOFun应用程序,使用image dump sections MachOFun查询data section,找到__DATA.__objc_classlist

0x00000013 data-ptrs  [0x000000010a3a0720-0x000000010a3a0740)  rw-  0x00010720 0x00000020 0x10000000 MachOFun.__DATA.__objc_classlist

这个部分存储指向OC或Swift类的类指针。这个部分是一个类指针数组,指向存储在__DATA.__objc_data中的实际类。把__DATA.__objc_data看作是打包在一起的OC数据缓冲区。就像硬编码的UTF-8字符串存储在__TEXT.__cstring一样。

我们可以快速确定MachOFun模块实现了4个类。segment大小是0x00000020除以64位进程中指针的大小(8字节),32/8=4个OC/Swift类。

(lldb) x/4gx 0x000000010a3a0720
0x10a3a0720: 0x000000010a3a2420 0x000000010a3a2518
0x10a3a0730: 0x000000010a3a25c8 0x000000010a3a2650

(lldb) cpo 0x000000010a3a2420
MachOFun.CasinoContainerView

(lldb) cpo 0x000000010a3a2518
MachOFun.CasinoViewController

(lldb) cpo 0x000000010a3a25c8
MachOFun.InsecureNetworkRequestsTableViewController

(lldb) cpo 0x000000010a3a2650
MachOFun.AppDelegate
__bss、__common和__const sections

有时模块需要保留对函数调用之后的数据的引用。比如在函数中声明一个常量let v=UIView(),指针v将存储在栈中,指向堆中分配的内存。但指令指针一离开函数,对v变量的引用就消失得无影无踪了。这就是为什么在__DATA segment中有几个部分被设计用来在进程的整个生命周期中存储变量。

当我们声明一个全局变量时,它通常会被放入__DATA.__common。这个section用来在整个模块,甚至模块之间共享信息。

如果开发人员想让变量在函数调用之间生存下来,但又不能让任何其他模块访问它,甚至不能从同一个模块中的其他源文件访问它,该怎么办呢?这通常通过在__DATA.__bss存储这些变量来实现。C/Objective-C将通过对变量的static声明来实现。在Swift中,这可以通过对Swift变量的private声明来实现。

最后,有一些全局变量要声明为在程序生命周期内不变。我们可以在C/Objective-C中将它们标记为const,在__DATA.__const中存储这些变量。从开发人员的角度来看,Swift基本不需要接触__DATA.__const的数据,因为let关键字和在编译时检查变量的更改。

1.5 游戏作弊

__DATA segment不仅存储对模块中数据的引用,还提供对未在模块中定义的外部变量、类、方法和函数的引用。

理论上,如果模块可以在任何地址进行加载,那么在调用该代码时,必须使用引用点来指示从何处开始查找。由于直到运行时才知道此位置,因此这个起始引用点必须可从调用模块写入。

这适用于外部C函数、Swift/Objective-C类、全局变量等。

__DATA.__la_symbol_ptr是一个相当有趣的部分。因为它存储对外部函数的引用。这些外部函数在调用时在运行时被延迟解析。为了让这个复杂的过程正常工作,__DATA.__la_symbol_ptr存储了一系列函数指针,这些指针指向调用模块__TEXT.__stub_helper中的偏移量。当dyld解析这个外部函数的位置的时候确定。我们只要知道外部函数在默认情况下是通过__DATA.__la_symbol_ptr引用的。如果函数指针没有指向__TEXT.__stub_helper中的地址,dyld则会“解析”外部函数。

暂停MachOFun程序,并在LLDB中键入以下内容:

(lldb) exp -l objc -O -- [[NSBundle mainBundle] executablePath]
/Users/xxx/Library/Developer/CoreSimulator/Devices/85225EEE-8D5B-4091-A742-5BEBAE1C4906/data/Containers/Bundle/Application/44BBD366-CB9A-406B-B15E-EE5D666F4CFC/MachOFun.app/MachOFun

通过objdump命令来查找MachOFun可执行文件中所有懒绑定的外部函数。

(lldb) platform shell objdump -lazy-bind /Users/xxx/Library/Developer/CoreSimulator/Devices/85225EEE-8D5B-4091-A742-5BEBAE1C4906/data/Containers/Bundle/Application/44BBD366-CB9A-406B-B15E-EE5D666F4CFC/MachOFun.app/MachOFun | grep arc
__DATA   __la_symbol_ptr    0x1000102F0 libSystem        _arc4random_uniform

结果出来了,arc4random_uniformMachOFun的代码中被调用了。这个0x1000102F0是在没有ASLR处理时的偏移量,它包括了__PAGEZERO的偏移量(就是0x100000000)以及磁盘上的实际实际偏移量0x102F0

我们要怎么把0x1000102F0告诉给内存呢?我们可以通过_dyld_get_image_vmaddr_slide这个接口来拿到地址。为了确保将正确的索引引用到模块中,通常索引1将指向主可执行文件。确保输出是MachOFun之后,将索引1上与dyld_get_image_vmaddr_slide一起使用,并将从objdump命令检索到的值添加到后面:

(lldb) po (char *)_dyld_get_image_name(1)
"/Users/xxx/Library/Developer/CoreSimulator/Devices/85225EEE-8D5B-4091-A742-5BEBAE1C4906/data/Containers/Bundle/Application/44BBD366-CB9A-406B-B15E-EE5D666F4CFC/MachOFun.app/MachOFun"
(lldb) p/x (intptr_t)_dyld_get_image_vmaddr_slide(1) + 0x1000102F0
(long) $1 = 0x00000001097922f0

这里得到了0x00000001097922f0。这个值是arc4random_uniform解析到内存中外部引用位置的加载地址。解析这个地址的值:

(lldb) x/gx 0x00000001097922f0
0x1097922f0: 0x00007fff522f38b9
(lldb) image lookup -a 0x00007fff522f38b9
      Address: libsystem_c.dylib[0x00000000000228b9] (libsystem_c.dylib.__TEXT.__text + 137321)
      Summary: libsystem_c.dylib`arc4random_uniform

这意味着arc4random_uniform函数已经被解析。因为函数指针在__DATA.__la_symbol_ptr中指向arc4random_uniform,而不是__TEXT.__stub_helper中的偏移量。

哈哈,现在我们甚至不会在arc4random_uniform上设置断点。因为我们非常确信这个老虎机正在调用arc4random_uniform来生成随机。我们在内存中改变指针,看看会发生什么!

LLDB中创建一个返回5的全局函数。

(lldb) exp -l objc -p -- int lolzfunc() { return 5; }
(lldb) p/x lolzfunc
(int (*)()) $3 = 0x00000001108c9110 (0x00000001108c9110)

-p选项表示在栈帧之外执行此代码。这是非常必要的。因为我们不能在其他C代码中声明这个函数。这意味着内存中有一个名为lolzfunc的全局函数。

进攻计划现在应该很清楚了。我们将arc4random_uniform的外部指针更改为新创建函数lolzfunc的地址。

(lldb) memory write -s8 0x00007fff522f38b9 0x00000001108c9110

第一个指针是前面找到的arc4random_uniform的原始地址。第二个指针是新的lolzfunc地址。这告诉LLDB0x00007fff522f38b9位置写入8字节(-s8),值为0x00000001108c9110。

取消断点,来试一试。


测试
OC swizzling vs 函数插入

与Objective-C的method swizzling不同,延迟指针加载是基于每个模块进行的。这意味着我们刚才执行的技巧只在MachOFun模块调用arc4random_uniform时有效。如果CFNetwork先调用了arc4random_uniform,它就不会工作。

回到MachoFun应用程序,看到"Print a random number to console"按钮了吗?

该代码解析一个IBAction方法,该方法调用SomeClassInAFramework.printARandomNumber()。该方法是在一个AFrameworkframework中实现的。在静态printARandomNumber()函数中,调用arc4random_uniform生成随机数。

点几次按钮,观察arc4random_uniform是否正常工作。这意味着,如果要交换所有arc4random_uniform存根,必须遍历每个模块。在内存中找到arc4random_uniform location存根,并用新函数的地址替换它。

幸运的是,dyld会在可执行文件中寻找一个特殊的__DATA section,叫做__DATA.__interpose。如果dyld看到这个section,之后加载的所有模块中的存根都会被这个新函数所替换。

MachOFuntarget中,有一个shell脚本被悄悄地隐藏起来。单击MachOFun项目,选择MachOFun,选择Build Phases,然后展开Run Script。从那里,删除构建脚本顶部的exit 0行。

echo """
#include <stdlib.h>
#define DYLD_INTERPOSE(_replacment,_replacee) \
__attribute__((used)) static struct{ const void* replacment; const void* replacee; } _interpose_##_replacee \
__attribute__ ((section (\"__DATA,__interpose\"))) = { (const void*)(unsigned long)&_replacment, (const void*)(unsigned long)&_replacee };

int dereksfunc() { return 7; }

DYLD_INTERPOSE(dereksfunc, arc4random_uniform)
""" > /tmp/lolz.c

clang /tmp/lolz.c -shared -fpic -isysroot `xcrun --show-sdk-path -sdk iphonesimulator`  -o /tmp/lolz.dylib && codesign --force --sign - /tmp/lolz.dylib

此脚本将在/tmp/lolz.dylib创建一个动态库,并使用特殊的代码签名对库进行签名。因为模拟器需要一个有效的签名,即使代码签名不匹配也没事。

这个动态库非常简单。它声明了一个名为dereksfunc的函数,该函数返回整数7。此函数的地址通过arc4random_uniform插入,因此所有未来加载的模块都将替换arc4random_uniform的存根。

使用强大的DYLD_INSERT_LIBRARIES环境变量,可以在加载任何其他模块之前,首先加载这个lolz.dylib模块,从而外部模块引用的每一个arc4random_uniform将替换为dereksfunc

DYLD_INSERT_LIBRARIES

运行一下。导航到模拟器中的Casino选项卡,让老虎机旋转几圈。现在你将一直获得🕶,因为arc4random_uniform返回7。即使是"Print a random number to console"按钮也将始终返回7

(lldb) image dump sections lolz.dylib
Sections for '/tmp/lolz.dylib' (x86_64):
  SectID     Type             Load Address                             Perm File Off.  File Size  Flags      Section Name
  ---------- ---------------- ---------------------------------------  ---- ---------- ---------- ---------- ----------------------------
  0x00000100 container        [0x000000010ee79000-0x000000010ee7a000)  r-x  0x00000000 0x00001000 0x00000000 lolz.dylib.__TEXT
  0x00000001 code             [0x000000010ee79fa0-0x000000010ee79fab)  r-x  0x00000fa0 0x0000000b 0x80000400 lolz.dylib.__TEXT.__text
  0x00000002 compact-unwind   [0x000000010ee79fac-0x000000010ee79ff4)  r-x  0x00000fac 0x00000048 0x00000000 lolz.dylib.__TEXT.__unwind_info
  0x00000200 container        [0x000000010ee7a000-0x000000010ee7b000)  rw-  0x00001000 0x00001000 0x00000000 lolz.dylib.__DATA
  0x00000003 regular          [0x000000010ee7a000-0x000000010ee7a010)  rw-  0x00001000 0x00000010 0x00000000 lolz.dylib.__DATA.__interpose
  0x00000300 container        [0x000000010ee7b000-0x000000010ee80000)  r--  0x00002000 0x00004890 0x00000000 lolz.dylib.__LINKEDIT

我们看到了大小足够放下两个函数指针的0x00000010。我们用x/2gx来查看一下0x000000010ee7a000

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

推荐阅读更多精彩内容