从Swift调用getsectiondata

Jur*_*ste 8 macos mach-o swift

这个问题和答案描述了如何在现代OS X/macOS版本上使用Objective-C从Mach-O部分读取数据:从getsectbyname中读取字节

描述的答案有效.我正在尝试用Swift实现同样的功能.我不能让它发挥作用.

我在"其他链接器标志"中有以下内容:-Wl,-sectcreate,__LOCALIZATIONS,__base,en.lproj/Localizable.strings,-segprot,__LOCALIZATIONS,r,r.

这个Swift代码为我提供了一个指向嵌入数据的指针,直到我尝试在Xcode之外运行代码并且ASLR打破它:

var size: UInt = 0
let _localizationSection = getsectdata(
    "__LOCALIZATIONS",
    "__base",
    &size)
Run Code Online (Sandbox Code Playgroud)

为了解决ASLR问题,根据上面的问题和答案,并根据我自己的测试,我应该使用getsectiondata.它在Objective-C中运行得很好,但我在Swift中没有运气.以下是我唯一能够通过编译器的东西,但它返回nil:

var size: UInt = 0
var header = _mh_execute_header
let localizationSection = getsectiondata(
    &header,
    "__LOCALIZATIONS",
    "__base",
    &size)
Run Code Online (Sandbox Code Playgroud)

正在拍摄_mh_execute_header问题的副本,有没有办法避免它?我需要一个UnsafePointer<mach_header_64>,但使用&_mh_execute_header第一个参数来getsectiondata导致编译错误.

我正在使用Swift 3.0,并在macOS 10.12上运行我的代码.

Mar*_*n R 5

链接到 Objective-C 代码之间的区别

void *ptr = getsectiondata(&_mh_execute_header, ...);
Run Code Online (Sandbox Code Playgroud)

和你的 Swift 翻译

var header = _mh_execute_header
let localizationSection = getsectiondata(&header, ...)
Run Code Online (Sandbox Code Playgroud)

是后者将全局 变量副本_mh_execute_header的地址传递给函数,显然这是不被接受的。如果将 Objective-C 代码修改为

struct mach_header_64 header = _mh_execute_header;
void *ptr = getsectiondata(&header, ...);
Run Code Online (Sandbox Code Playgroud)

然后它也失败了(实际上在我的测试中崩溃了)。

现在的问题是它_mh_execute_header作为常量暴露给 Swift:

public let _mh_execute_header: mach_header_64
Run Code Online (Sandbox Code Playgroud)

并且无法获取 Swift 中常量的地址。一种可能的解决方法是定义

#import <mach-o/ldsyms.h>
static const struct mach_header_64 *mhExecHeaderPtr = &_mh_execute_header;
Run Code Online (Sandbox Code Playgroud)

在桥接头文件中,然后将其用作

let localizationSection = getsectiondata(mhExecHeaderPtr, ...)
Run Code Online (Sandbox Code Playgroud)

在斯威夫特.


dlopen另一种选择是通过/查找符号dlsym

import MachO

if let handle = dlopen(nil, RTLD_LAZY) {
    defer { dlclose(handle) }

    if let ptr = dlsym(handle, MH_EXECUTE_SYM) {
        let mhExecHeaderPtr = ptr.assumingMemoryBound(to: mach_header_64.self)

        var size: UInt = 0
        let localizationSection = getsectiondata(
            mhExecHeaderPtr,
            "__LOCALIZATIONS",
            "__base",
            &size)

        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @JuriPakaste:我添加了另一个(纯Swift)解决方案。 (2认同)