In the past, we learned about the setup of Ruby debugging environment and basic Ruby syntax. Today, we will use Ruby’s advanced library to modify iOS dynamic library files.
ruby-macho
In Ruby, ruby-macho is used to modify Mach O files. The rules can be found on Github, the repository address is Ruby-Macho.
Modify the Load Command of the dynamic library
Construction project Engineering
We create a new folder and create a Gemfile file to which we introduce the necessary libraries for Ruby debugging and ruby-macho
Gemfile:
source 'https://rubygems.org'
gem 'ruby-debug-ide'
gem 'debase'
gem 'rexml'
gem 'ruby-macho'
gem 'solargraph'
Copy the code
Next, place the libAFNetworking. Dylib file in the bin directory in the root folder, as shown in the following figure:
View dependency information for dynamic libraries
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 # The dynamic library relies on the dynamic library file_dylibs = MachO: : view dylibs (macho_path_dylib) / / 3 file_dylibs. Each do | dylib | puts dylib end output: /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/WebKitCopy the code
- 1, the introduction of
macho
Ruby library. - Make a copy of the dynamic library.
- 3, check the
The dynamic library
orExecutable file
You can view other library files that the dynamic library depends on.
Modify rpath
For the meaning of RPATH in dynamic libraries, see this article dynamic Library Principles.
1. First, let’s check the RPATH value in the dynamic database:
Copy = MachO:: machofile. new(macho_path_copy_dylib) Origin = MachO:: machofile. new(macho_path_dylib) puts "views rpath: - copy - # {copy. Rpaths} -- -- -- -- -- origin -- -- -- -- -- - : # {origin. Rpaths} "output: view rpath: -- copy ---- ["@executable_path/Frameworks", "@loader_path/Frameworks"] ----- origin ------: ["@executable_path/Frameworks", "@loader_path/Frameworks"]Copy the code
2. Change the rpath value
# change 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 ------: #{origine. rpaths}" modify rpath >>>>>>: ["@executable_path/Frameworks", "@loader_path/Frameworks/LY"] ----- origin ------: ["@executable_path/Frameworks", "@loader_path/Frameworks"]Copy the code
From here we can see that we have successfully changed @loader_path/Frameworks/LY from libafNetworking_copy. dylib to @loader_path/Frameworks/LY.
3. Add the rpath value
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 ------: #{origine.rpaths}" add rpath >>>>>: ["@executable_path/Frameworks", "@loader_path/Frameworks/LY", "@loader_path/Frameworks/LY1/LY2"] ----- origin ------: ["@executable_path/Frameworks", "@loader_path/Frameworks"]Copy the code
We have now successfully added a new RPATH to the replica dynamic library.
4. Delete the Rpath
# delete 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} "output: delete rpath > > > > : ["@executable_path/Frameworks", "@loader_path/Frameworks/LY"] ------origin-----: ["@executable_path/Frameworks", "@loader_path/Frameworks"]Copy the code
This is a simple implementation of Ruby-Macho in modifying Mach O files. The complete code is as follows:
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 The dynamic library relies on the dynamic library file_dylibs = MachO: : view dylibs (macho_path_dylib) file_dylibs. Each do | dylib | puts dylib end # check rpath Copy = MachO:: machofile. new(macho_path_copy_dylib) Origin = MachO:: machofile. new(macho_path_dylib) puts "views rpath: -- copy ---- #{copy.rpaths} ----- origin ------: #{origin. Rpaths}" #{rootpath :: 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 ------: #{origine.rpaths}" # add 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 ------: #{origine.rpaths}" # delete 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}"Copy the code