Ruby高级 iOS库的使用

·  阅读 378

在前面我们了解了Ruby调试环境的搭建和Ruby基本语法,今天我们通过Ruby中的高级库来修改iOS的动态库文件。

ruby-macho

Ruby中,ruby-macho是用来修改Mach O文件的。我们可以通过Github来了解其使用规则,仓库地址为 ruby-macho

修改动态库的Load Command

搭建项目工程

我们新建一个文件夹,并创建Gemfile文件,在Gemfile中引入Ruby调试的必要库和ruby-macho

Gemfile:

source 'https://rubygems.org'

gem 'ruby-debug-ide'
gem 'debase'
gem 'rexml'
gem 'ruby-macho'
gem 'solargraph'
复制代码

接下来,将 libAFNetworking.dylib文件放入根文件夹下的bin目录下,目录结构入下图所示:

截屏2021-08-28 下午3.12.07.png

查看动态库的依赖信息

require 'macho' // 1

macho_path_dylib = './bin/libAFNetworking.dylib'
macho_path_copy_dylib = './bin/libAFNetworking_copy.dylib'

FileUtils.cp macho_path_dylib, macho_path_copy_dylib // 2 

# 所有关于动态库的信息, 该动态库所依赖的动态库
file_dylibs = MachO::Tools.dylibs(macho_path_dylib) //3

file_dylibs.each do |dylib|
    puts dylib
end

输出结果:
/System/Library/Frameworks/Foundation.framework/Foundation
/usr/lib/libobjc.A.dylib
/usr/lib/libSystem.B.dylib
/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics
/System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices
/System/Library/Frameworks/Security.framework/Security
/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration
/System/Library/Frameworks/UIKit.framework/UIKit
/System/Library/Frameworks/WebKit.framework/WebKit
复制代码
  • 1,引入 macho ruby库。
  • 2,将动态库拷贝一份。
  • 3,查看动态库或者可执行文件的信息,可以查看该动态库依赖的其他库文件。

修改rpath

关于动态库中rpath的含义,可以参考这篇文章动态库原理

1,首先,我们先来查看动态库里面的rpath值:

copy = MachO::MachOFile.new(macho_path_copy_dylib)
origin = MachO::MachOFile.new(macho_path_dylib)
puts "查看 rpath : -- copy ---- #{copy.rpaths} ----- origin ------: #{origin.rpaths}"

输出结果:
查看 rpath : -- copy ---- ["@executable_path/Frameworks", "@loader_path/Frameworks"] ----- origin ------: ["@executable_path/Frameworks", "@loader_path/Frameworks"]
复制代码

2,修改 rpath 值

# 修改 rpath
MachO::Tools.change_rpath(macho_path_copy_dylib, '@loader_path/Frameworks', '@loader_path/Frameworks/LY')

copy = MachO::MachOFile.new(macho_path_copy_dylib)
origin = MachO::MachOFile.new(macho_path_dylib)
puts "modify rpath >>>>>>: #{copy.rpaths} ----- origin ------: #{origin.rpaths}"

输出结果:
modify rpath >>>>>>: ["@executable_path/Frameworks", "@loader_path/Frameworks/LY"] ----- origin ------: ["@executable_path/Frameworks", "@loader_path/Frameworks"]
复制代码

从这里我们可以看出,我们已经将libAFNetworking_copy.dylib中的@loader_path/Frameworks的值,成功修改为 @loader_path/Frameworks/LY

3,添加 rpath 值

MachO::Tools.add_rpath(macho_path_copy_dylib, '@loader_path/Frameworks/LY1/LY2')

copy = MachO::MachOFile.new(macho_path_copy_dylib)
origin = MachO::MachOFile.new(macho_path_dylib)
puts "add rpath >>>>>: #{copy.rpaths} ----- origin ------: #{origin.rpaths}"

输出结果:
add rpath >>>>>: ["@executable_path/Frameworks", "@loader_path/Frameworks/LY", "@loader_path/Frameworks/LY1/LY2"] ----- origin ------: ["@executable_path/Frameworks", "@loader_path/Frameworks"]
复制代码

现在在副本动态库中,我们已经成功的添加了一个新的rpath。

4,删除 rpath

# 删除 rpath

MachO::Tools.delete_rpath(macho_path_copy_dylib, '@loader_path/Frameworks/LY1/LY2')
copy = MachO::MachOFile.new(macho_path_copy_dylib)

puts "delete rpath >>>>: #{copy.rpaths} ------origin-----: #{origin.rpaths}"

输出结果:

delete rpath >>>>: ["@executable_path/Frameworks", "@loader_path/Frameworks/LY"] ------origin-----: ["@executable_path/Frameworks", "@loader_path/Frameworks"]
复制代码

以上就是 ruby-macho在修改Mach O文件的一个简单的应用实现了。完整的代码如下:

require 'macho'

#ruby-macho
macho_path_dylib = './bin/libAFNetworking.dylib'
macho_path_copy_dylib = './bin/libAFNetworking_copy.dylib'

# copy macho_path_dylib => macho_path_copy_dylib
FileUtils.cp macho_path_dylib, macho_path_copy_dylib

# 动态库 /exec 所有关于动态库的信息, 该动态库所依赖的动态库
file_dylibs = MachO::Tools.dylibs(macho_path_dylib)
file_dylibs.each do |dylib|
    puts dylib
end

# 查看 rpath
copy = MachO::MachOFile.new(macho_path_copy_dylib)
origin = MachO::MachOFile.new(macho_path_dylib)
puts "查看 rpath : -- copy ---- #{copy.rpaths} ----- origin ------: #{origin.rpaths}"

# 修改 rpath
MachO::Tools.change_rpath(macho_path_copy_dylib, '@loader_path/Frameworks', '@loader_path/Frameworks/LY')
copy = MachO::MachOFile.new(macho_path_copy_dylib)
origin = MachO::MachOFile.new(macho_path_dylib)
puts "modify rpath >>>>>>: #{copy.rpaths} ----- origin ------: #{origin.rpaths}"

# 添加 rpath
MachO::Tools.add_rpath(macho_path_copy_dylib, '@loader_path/Frameworks/LY1/LY2')
copy = MachO::MachOFile.new(macho_path_copy_dylib)
origin = MachO::MachOFile.new(macho_path_dylib)
puts "add rpath >>>>>: #{copy.rpaths} ----- origin ------: #{origin.rpaths}"

# 删除 rpath
MachO::Tools.delete_rpath(macho_path_copy_dylib, '@loader_path/Frameworks/LY1/LY2')
copy = MachO::MachOFile.new(macho_path_copy_dylib)
puts "delete rpath >>>>: #{copy.rpaths} ------origin-----: #{origin.rpaths}"
复制代码
分类:
iOS
标签: