美文网首页
Swift中dump出MachO中的属性信息

Swift中dump出MachO中的属性信息

作者: spyn_n | 来源:发表于2022-01-13 19:35 被阅读0次

前言

  本篇在 Swift的属性 篇的基础上操作指针读取MachO中属性的案例,针对单个结构体/类进行dump。具体的操作和注释已经在案例中注明:

需要注意的是:在解析的过程中,关于FieldDescriptor 中的fieldRecords,因为fieldRecords是一片连续的内存空间,其并没有存储一个类似于前面的字段,所以不能取其中的值作为offset,我就计算错过一次,找了好久才发现跟实际手动算皮配不上

struct PSYModel{
    var age: Int
    let name: String
}

var size: UInt = 0
// 获取segment:__TEXT, section:__swift5_types的地址(包含了基地址)
var sPtr = getsectdata("__TEXT", "__swift5_types", &size)
// vmAddress(UnsafePointer<mach_header>!),这其实是程序运行的首地址
var mhHeaderPtr = _dyld_get_image_header(0)
// 得到一个segment_command_64结构体地址
var setCommond64Ptr = getsegbyname("__LINKEDIT")
// 定义并计算基地址
var linkBaseAddress:UInt64 = 0
if let vmAddress = setCommond64Ptr?.pointee.vmaddr, let fileOffset = setCommond64Ptr?.pointee.fileoff{
    linkBaseAddress = vmAddress - fileOffset
}

var offset:UInt64 = 0
if let unwrappedPtr = sPtr{
    // 将UnsafeMutablePointer<Int8>转换成Int,在按位转换成Int64--> UInt64
    let intRepreaentation = UInt64(bitPattern: Int64(Int(bitPattern: unwrappedPtr)))
    offset = intRepreaentation - linkBaseAddress
}

// 因为UnsafePointer没有具体的类型不能进行计算,需要转换成确定的类型
let mhHeaderPtr_IntRepreaentation = UInt64(bitPattern: Int64(Int(bitPattern: mhHeaderPtr)))
// 计算__swift5_types的地址信息(UInt64)
var dataLoAddress = mhHeaderPtr_IntRepreaentation + offset

// 将地址信息返回指针类型,访问地址取出内容值
var dataLoAddressPtr = withUnsafePointer(to: &dataLoAddress){return $0}
var dataLoContent = UnsafePointer<UInt32>.init(bitPattern: Int(exactly: dataLoAddress) ?? 0)?.pointee

// 得到typeDescriptor的偏移值
var typeDescriptorOffset = UInt64(dataLoContent!) + offset - linkBaseAddress
// 得到typeDescriptor真实地址
var typeDescriptorAddress = typeDescriptorOffset + mhHeaderPtr_IntRepreaentation

// 根据源码得出的结构体信息声明
struct TargetClassDescriptor{
    var flags: UInt32
    var parent: UInt32
    var name: Int32
    var accessFunctionPointer: Int32
    var fieldDescriptor: Int32
    var superClassType: Int32
    var metadataNegativeSizeInWords: UInt32
    var metadataPositiveSizeInWords: UInt32
    var numImmediateMembers: UInt32
    var numFields: UInt32
    var fieldOffsetVectorOffset: UInt32
    var Offset: UInt32
    var size: UInt32
    //vtable
}

// 将地址值强转成结构体
let classDescriptor = UnsafePointer<TargetClassDescriptor>.init(bitPattern: Int(exactly: typeDescriptorAddress) ?? 0)?.pointee

// 计算结构体名称
if let name = classDescriptor?.name{
    // 计算name的地址
    let nameAddress = Int64(typeDescriptorAddress) + Int64(name) + 8
    
    print("nameAddress:\(nameAddress)")
    
    if let cChar = UnsafePointer<CChar>.init(bitPattern: Int(exactly: nameAddress) ?? 0){
        print("name名字 = \(String(cString: cChar))")
    }
}

// 真实地址fieldDescriptorAddress + 结构体偏移值
let fieldDescriptorRelaticveAddress = typeDescriptorAddress + 16
// 取出里面的值,其实就是fieldDescriptor的offset
let fieldDescriptorOffset = UnsafePointer<UInt32>.init(bitPattern: Int(exactly: fieldDescriptorRelaticveAddress) ?? 0)?.pointee

// 得到FieldDescriptor的真实地址
let fieldDescriptorAddress = fieldDescriptorRelaticveAddress + UInt64(fieldDescriptorOffset!)


struct FieldDescriptor{
    var mangledTypeName: UInt32
    var superclass: UInt32
    var Kind: UInt16
    var fieldRecordSize: UInt16
    var numFields: UInt32 // 属性个数
    //var fieldRecords: UInt32 // [FieldRecords]
}

struct FieldRecord{
   var Flags : UInt32
   var mangledTypeName: UInt32
   var fieldName: UInt32
}

// 转换成结构体
let fieldDescriptor = UnsafePointer<FieldDescriptor>.init(bitPattern: Int(exactly: fieldDescriptorAddress) ?? 0)?.pointee

// 真实地址FieldRecord + 结构体偏移值
let fieldRecordAddress = fieldDescriptorAddress + 16

for i in 0..<fieldDescriptor!.numFields{

    let stride: UInt64 = UInt64(MemoryLayout<FieldRecord>.stride * Int(i))
    
    let fieldNameRelaticveAddress = fieldRecordAddress + 8 + stride
    let fieldNameOffset = UnsafePointer<UInt32>.init(bitPattern: Int(exactly: fieldNameRelaticveAddress) ?? 0)?.pointee
    // 计算name的地址
    let fieldNameAddress = fieldNameRelaticveAddress + UInt64(fieldNameOffset!) - linkBaseAddress
    
    if let cChar = UnsafePointer<CChar>.init(bitPattern: Int(exactly: fieldNameAddress) ?? 0){
        print("属性名字 = \(String(cString: cChar))")
    }
}

print("end")

输出:
nameAddress:4294994300
name名字 = PSYModel
属性名字 = age
属性名字 = name
end
Program ended with exit code: 0
输出结果

相关文章

  • Swift中dump出MachO中的属性信息

    前言   本篇在 Swift的属性 [https://www.jianshu.com/p/d3ed8a9c146...

  • ios-class-guard - Swift & OC Mix

    Swift OC 代码需要混淆代码 一、class-dump 能够从可执行文件中获取类/方法和属性的信息, ios...

  • OC的@property与Swift的存储属性/计算属性类比

    Swift中的计算属性/存储属性与OC中的@property   Swift中引入了存储属性、计算属性的概念,存储...

  • iOS9新特性

    1.nullable:用于属性,返回值,参数中.提示信息; 目的:迎合swift,因为swift是强类型,必须指定...

  • Swift 属性

    Swift 属性 在Swift中属性主要分为存储属性、计算属性、延迟存储属性、类型属性这四种,并且Swift还提供...

  • Swift进阶(三)--- 属性

    Swift的属性 在swift中,属性主要分为以下几种: 存储属性 计算属性 延迟存储属性 类型属性 一:存储属性...

  • 浅谈 Swift 中的属性(Property)

    Properties in Swift 前言 Swift 中的属性分为存储属性与计算属性,存储属性即为我们平时常用...

  • Swift中的属性

    1. 存储属性 简单来说,每一个存储属性就是存储在特定类或结构体实例里的一个常量或变量。存储属性可以使变量存储属性...

  • Swift中的属性

      我们都知道,类是由属性和方法组成的,一般而言,属性主要是用来访问数据成员,而方法则是用来执行某些操作,比如说计...

  • swift中的属性

    属性可以将值与特定的类、结构体或者是枚举联系起来。 一、简介 存储属性与计算属性的差异: 存储属性会存储敞亮或者变...

网友评论

      本文标题:Swift中dump出MachO中的属性信息

      本文链接:https://www.haomeiwen.com/subject/yhancrtx.html