Dylib文件介绍和安全防范

Dylib文件介绍

dylib(Dynamic Library,动态链接库)是 macOS 和 iOS 系统中使用的动态链接库文件格式,类似于 Windows 系统的 .dll 文件和 Linux 系统的 .so文件,支持x64、ARM64、ARM64e 等架构。

它的核心作用是为多个程序提供可共享的代码和资源,实现代码复用、减少内存占用,并支持程序的模块化更新。

Dylib文件基本结构

dylib 文件结构一般由以下几部分组成。

Mach-O头部

Mach-O header主要是描述文件类型(如动态库)、CPU 架构(如x64、arm64)、加载命令数量和大小等信息,如图所示:

加载命令

加载命令(Load Commands)是指定依赖的其他库、符号表位置、代码签名等信息,如图所示:

其中关键命令包括:

  • SEGMENT_64:定义内存段,包括__TEXT, __DATA__LINKEDIT等段;
  • ID_DYLIB:库的唯一标识,包括命名、路径、版本号等信息;
  • LOAD_DYLIB:依赖的其他 dylib,比如libSystem.B.dylib文件路径;
  • SYM_TAB:符号表位置;
  • DYLD_INFO_ONLY:动态链接信息,比如重定位、绑定信息等;
  • CODE_SIGNATURE:代码签名信息。

段和节

代码段(Text Segment)是指存储可执行代码(如函数实现)等信息,数据段(Data Segment)是指存储全局变量、常量等信息,其中:

  • TEXT 段:包含代码(.text)、常量数据(.const)、字符串常量(.cstring)等;
  • DATA 段:包含可写数据(.data)、未初始化全局变量(.BSS)等;
  • LINKEDIT 段:是指存储动态链接元数据,包括符号表、字符串表、重定位信息等;
  • 每个段下可有多个节(Section)。

符号表

符号表(Symbol Table),记录dylib库中导出和导入等的符号信息,以便链接时符号查找和重定位。

Dylib重要机制

dylib的特有机制

安装名称

  • 每个 .dylib 文件在编译时会指定一个”install name”,即库的唯一标识路径;
  • 这个路径会被写入依赖它的可执行文件或其他库中,运行时会优先按”install name”查找库文件;
  • 可用 install_name_tool 修改”install name”,命令参考如下:otool -D libDemo.dylib   # 查看 install name
    install_name_tool -id @rpath/libDemo.dylib libDemo.dylib  # 修改 install name

路径规则

关于库的查找路径,一般是@rpath、@loader_path、@executable_path这三个变量,这些变量极大增强了库的部署灵活性。

  • @rpath:运行时搜索路径(可执行文件或库可设置多个 rpath)。
  • @loader_path:当前加载库文件所在目录。
  • @executable_path:可执行文件所在目录。

版本控制

  1. dylib支持”当前版本”和”兼容版本”号,以便于系统和开发者管理库的兼容性。
  2. 可用 otool -L 查看依赖库及其版本,如图所示:

dylib的加载机制

加载时机

  1. 启动时加载,一般是可执行文件启动时,系统动态链接器(dyld)会加载所有依赖的dylib库。
  2. 运行时加载,一般可直接通过 dlopen() 动态加载库。

查找顺序

加载.dylib时,dyld 按以下顺序查找库文件:

  1. 优先按install name查找;
  2. 通过@rpath、@loader_path、@executable_path解析实际路径;
  3. 通过系统默认路径去查找,如/usr/lib/usr/local/lib等路径。

安全机制

  1. 支持代码签名和库验证,防止恶意库注入;
  2. 支持 System Integrity Protection(SIP)等安全特性。

基本使用

创建动态库

使用Xcode创建项目

  • 打开 Xcode → File → New → Project;
  • 选择 macOS → Library → 模板类型选择Dynamic Library
  • 输入产品名(如MyDyLib),语言选择 Objective-C/Swift。

项目结构,参考如下:

MyDyLib/
├── MyDyLib.h          # 公共头文件
├── MyDyLib.m          # 实现代码
└── Info.plist

示例代码,参考如下:

// MyDyLib.h
#import <Foundation/Foundation.h>

@interface MathOperations : NSObject
+ (int)add:(int)a to:(int)b;
+ (int)multiply:(int)a by:(int)b;
@end

编译动态库

设置编译选项

在项目设置中:

  • Build Settings → Mach-O Type 设置为 Dynamic Library
  • Build Settings → Installation Directory 设置安装路径(如@rpath)。

生成dylib

  • 选择目标设备(iOS 或 macOS),然后进行编译,一般情况下dylib库生成的路径为:
# macOS
~/Library/Developer/Xcode/DerivedData/.../Build/Products/Debug/libMyDyLib.dylib

# iOS
.../Build/Products/Debug-iphoneos/libMyDyLib.dylib

使用动态库

  1. 创建 macOS/iOS Application项目,然后链接编译好的动态库;
  2. 在项目中设置,Build Phases → Link Binary With Libraries添加 dylib库,如图所示:
  1. 添加dylib库后,在Target-General-Frameworks&Libraries处设置为Embed&Sign,这样dylib库将默认集成在app的Frameworks目录下。
  1. 设置完成后,即可进行调用接口,示例代码如下:
// ViewController.m
#import "MyDyLib.h"

- (void)viewDidLoad {
   int result = [MathOperations add:5 to:3];
   NSLog(@"Result: %d", result);
}
  1. 然后就可以编译app应用了。

安全防范

安全问题

被逆向风险

虽然编译生成的二进制文件逆向分析难度较高,但由于相应的反编译工具(比如ida、Ghidra)也成熟强大,依然可以反编译为类C伪代码;

被调试风险

攻击者可通过调试工具附加应用进程进行调试,在调试过程中可能暴露敏感信息(如密钥、算法逻辑);

程序被篡改风险

攻击者可以通过修改应用内存改变程序行为,绕过安全检查或实现恶意功能,导致数据泄露;

调试符号暴漏

dylib库中包含调试符号(如函数名、变量名、函数地址),可能暴露敏感信息,则攻击者可以更容易地理解代码逻辑,对代码进行分析。

防范措施

Native程序又叫本地程序,通常指用C、C++、OC等编译型语言开发,直接编译为特定平台机器码的可执行文件(如.exe、.so、.dylib等),可以直接在操作系统上运行。

dylib库属于Native程序的一种,Virbox Protector工具在对dylib文件的保护上有着成熟的方案,可以实现对dylib文件进行函数级和整体保护,具体方案参考官网文档Native程序保护最佳实践

滚动至顶部
售前客服
周末值班
电话

电话

13910187371