Files
CoreInject/main.rb

202 lines
6.7 KiB
Ruby
Raw Normal View History

2023-12-31 17:54:10 +08:00
require 'json'
require 'fileutils'
require './Utils'
require 'pathname'
require 'shellwords'
def readPrototypeKey(file, keyName)
link = Shellwords.escape(file)
%x{defaults read #{link} #{keyName}}.chomp
end
def parseAppInfo(appBaseLocate, appInfoFile)
appInfo = {}
appInfo['appBaseLocate'] = "#{appBaseLocate}"
appInfo['CFBundleIdentifier'] = readPrototypeKey appInfoFile, 'CFBundleIdentifier'
appInfo['CFBundleVersion'] = readPrototypeKey appInfoFile, 'CFBundleVersion'
appInfo['CFBundleShortVersionString'] = readPrototypeKey appInfoFile, 'CFBundleShortVersionString'
appInfo['CFBundleName'] = readPrototypeKey appInfoFile, 'CFBundleExecutable'
appInfo
end
def scan_apps
applist = []
baseDir = '/Applications'
lst = Dir.glob("#{baseDir}/*")
lst.each do |app|
appInfoFile = "#{app}/Contents/Info.plist"
next unless File.exist?(appInfoFile)
begin
applist.push parseAppInfo app, appInfoFile
# puts "检查本地App: #{appInfoFile}"
rescue StandardError
next
end
end
applist
end
def checkCompatible(compatibleVersionCode, compatibleVersionSubCode, appVersionCode, appSubVersionCode)
return true if compatibleVersionCode.nil? && compatibleVersionSubCode.nil?
compatibleVersionCode&.each do |code|
return true if appVersionCode == code
end
compatibleVersionSubCode&.each do |code|
return true if appSubVersionCode == code
end
false
end
def main
ret = %x{csrutil status}.chomp
# System Integrity Protection status: disabled.
if ret.include?('status: enabled')
# puts "给老子把你那个b SIP关了先是不是关SIP犯法\n要求里写了要先关SIP能不能认真看看我写的说明\n如果你看了还没关说明你确实是SB\n如果你没看说明那你更SB。\nWhateverU ARE SB。"
# return
end
config = File.read('config.json')
config = JSON.parse config
basePublicConfig = config['basePublicConfig']
appList = config['AppList']
procVersion = config['Version']
puts "====\t自动注入开始执行\t====\n"
puts "====\tVersion(版本号): #{procVersion}\t====\n"
puts "====\tAutomatic Inject Script Checking... ====\n"
puts "====\tDesign By QiuChenly(github.com/qiuchenly)"
puts "注入时请根据提示输入'y' 或者按下回车键跳过这一项。\n"
puts "When i find useful options, pls follow my prompts enter 'y' or press enter key to jump that item.\n"
install_apps = scan_apps
# prepare resolve package lst
appLst = []
appList.each do |app|
packageName = app['packageName']
if packageName.is_a?(Array)
packageName.each { |name|
tmp = app.dup
tmp['packageName'] = name
appLst.push tmp
}
else
appLst.push app
end
end
appLst.each { |app|
packageName = app['packageName']
appBaseLocate = app['appBaseLocate']
bridgeFile = app['bridgeFile']
injectFile = app['injectFile']
supportVersion = app['supportVersion']
supportSubVersion = app['supportSubVersion']
extraShell = app['extraShell']
needCopy2AppDir = app['needCopyToAppDir']
deepSignApp = app['deepSignApp']
disableLibraryValidate = app['disableLibraryValidate']
entitlements = app['entitlements']
noSignTarget = app['noSignTarget']
noDeep = app ['noDeep']
localApp = install_apps.select { |_app| _app['CFBundleIdentifier'] == packageName }
if localApp.empty? && (appBaseLocate.nil? || !Dir.exist?(appBaseLocate))
next
end
if localApp.empty?
puts "[🔔] 此App包不是常见类型结构请注意当前App注入的路径是 #{appBaseLocate}"
puts "[🔔] This App Folder is not common struct,pls attention now inject into the app path is #{appBaseLocate}"
# puts "读取的是 #{appBaseLocate + "/Contents/Info.plist"}"
localApp.push(parseAppInfo appBaseLocate, appBaseLocate + '/Contents/Info.plist')
end
localApp = localApp[0]
if appBaseLocate.nil?
appBaseLocate = localApp['appBaseLocate']
end
bridgeFile = basePublicConfig['bridgeFile'] if bridgeFile.nil?
unless checkCompatible(supportVersion, supportSubVersion, localApp['CFBundleShortVersionString'], localApp['CFBundleVersion'])
puts "[😅] [#{localApp['CFBundleName']}] - [#{localApp['CFBundleShortVersionString']}] - [#{localApp['CFBundleIdentifier']}]不是受支持的版本,跳过注入😋。\n"
next
end
puts "[🤔] [#{localApp['CFBundleName']}] - [#{localApp['CFBundleShortVersionString']}] - [#{localApp['CFBundleIdentifier']}]是受支持的版本是否需要注入y/n(默认n)\n"
action = gets.chomp
next if action != 'y'
puts "开始注入App: #{packageName}"
dest = appBaseLocate + bridgeFile + injectFile
backup = dest + '_backup'
if File.exist? backup
puts "备份的原始文件已经存在,需要直接用这个文件注入吗y/n(默认y)\n"
puts "Find Previous Target File Backup, Are u use it injecty/n(default is y)\n"
action = gets.chomp
# action = 'y'
if action == 'n'
FileUtils.remove(backup)
FileUtils.copy(dest, backup)
else
end
else
FileUtils.copy(dest, backup)
end
current = Pathname.new(File.dirname(__FILE__)).realpath
current = Shellwords.escape(current)
# set shell +x permission
sh = "chmod +x #{current}/tool/insert_dylib"
# puts sh
system sh
backup = Shellwords.escape(backup)
dest = Shellwords.escape(dest)
sh = "sudo #{current}/tool/insert_dylib #{current}/tool/libInjectLib.dylib #{backup} #{dest}"
unless needCopy2AppDir.nil?
system "sudo cp #{current}/tool/libInjectLib.dylib #{Shellwords.escape(appBaseLocate + bridgeFile)}libInjectLib.dylib"
sh = "sudo #{current}/tool/insert_dylib #{Shellwords.escape(appBaseLocate + bridgeFile)}libInjectLib.dylib #{backup} #{dest}"
end
# puts sh
system sh
signPrefix = 'codesign -f -s - --timestamp=none --all-architectures'
if noDeep.nil?
puts 'Need Deep Sign.'
signPrefix = "#{signPrefix} --deep"
end
unless entitlements.nil?
signPrefix = "#{signPrefix} --entitlements #{current}/tool/#{entitlements}"
end
# 签名目标文件 如果加了--deep 会导致签名整个app
if noSignTarget.nil?
puts '开始签名...'
system "#{signPrefix} #{dest}"
end
unless disableLibraryValidate.nil?
sh = 'sudo defaults write /Library/Preferences/com.apple.security.libraryvalidation.plist DisableLibraryValidation -bool true'
system sh
end
unless extraShell.nil?
system "sudo sh #{current}/tool/" + extraShell
end
if deepSignApp
system "#{signPrefix} #{Shellwords.escape(appBaseLocate)}"
end
puts 'App处理完成。'
}
end
main