patch.swift 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. SidecarPatcher - Version 10
  3. Enabling Sidecar on old Mac (2015 or older)
  4. But I don't have Sidecar-unsupported Mac so I don't know it works.
  5. THIS SCRIPT DOESN'T MAKE SidecarCore BACKUP SO YOU HAVE TO DO THIS MANUALLY. PLEASE BACKUP /System/Library/PrivateFrameworks/SidecarCore.framework/Versions/A/SidecarCore. PLEASE. PLEASE. PLEASE.
  6. And after patching SidecarCore, this script won't work until replacing to original one.
  7. This script requires disabling SIP, and running as root.
  8. */
  9. import Foundation
  10. func shell(_ command: String) -> String{
  11. let task = Process()
  12. task.launchPath = "/bin/bash"
  13. task.arguments = ["-c", command]
  14. let pipe = Pipe()
  15. task.standardOutput = pipe
  16. task.launch()
  17. let data = pipe.fileHandleForReading.readDataToEndOfFile()
  18. let output: String = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String
  19. return output
  20. }
  21. // From https://gist.github.com/brennanMKE/a0a2ee6aa5a2e2e66297c580c4df0d66
  22. fileprivate func directoryExistsAtPath(_ path: String) -> Bool {
  23. var isDirectory = ObjCBool(true)
  24. let exists = FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory)
  25. return exists && isDirectory.boolValue
  26. }
  27. func importCore(path: String) -> String{
  28. return shell("xxd -p \"\(path)/SidecarCore\" | tr -d '\n'")
  29. }
  30. func checkSystem(core: String, code: [String: PatchCode]) -> [PatchCode]{
  31. var result: [PatchCode] = []
  32. // Check OS
  33. if #available(macOS 10.15, *){
  34. ()
  35. }else{
  36. assertionFailure("You're not using macOS 10.15 or later!")
  37. }
  38. // Check the system is patched (macModel and iPadModel)
  39. for (_, value) in code{
  40. if !core.contains(value.patched){
  41. result.append(value)
  42. }
  43. }
  44. if result.isEmpty{
  45. assertionFailure("Already patched!")
  46. }
  47. // Check SidecarCore is damaged
  48. for value in result{
  49. if !core.contains(value.original){
  50. assertionFailure("Not supported SidecarCore! or seems like damaged")
  51. }
  52. }
  53. // Check SIP status
  54. if !(shell("csrutil status") == ("System Integrity Protection status: disabled.\n")){
  55. assertionFailure("System Integrity Protection is enabled")
  56. }
  57. // Check privilege
  58. if !(shell("id -u") == "0\n"){
  59. assertionFailure("Must be run as root")
  60. }
  61. // return patch code
  62. return result
  63. }
  64. func patch(core: String, code: [PatchCode]) -> String{
  65. var core = core
  66. for value in code{
  67. core.replaceSubrange(core.range(of: value.original)!, with: value.patched)
  68. }
  69. return core
  70. }
  71. func exportCore(core: String, path: String){
  72. // Remove existing tmp dir
  73. if directoryExistsAtPath("/tmp/SidecarPatcher"){
  74. do {
  75. try fileManager.removeItem(atPath: "/tmp/SidecarPatcher")
  76. }
  77. catch let error as NSError {
  78. assertionFailure("\(error)")
  79. }
  80. }
  81. // Create temp dir
  82. let temp_dir = URL(fileURLWithPath: "/tmp/").appendingPathComponent("SidecarPatcher").path
  83. do{
  84. try fileManager.createDirectory(atPath: temp_dir, withIntermediateDirectories: true, attributes: nil)
  85. } catch let error as NSError {
  86. assertionFailure("\(error)")
  87. }
  88. // Export code
  89. let output_path = URL(fileURLWithPath: "/tmp/SidecarPatcher").appendingPathComponent("output.txt")
  90. do {
  91. try core.write(to: output_path, atomically: true, encoding: String.Encoding.utf8)
  92. } catch let error as NSError {
  93. assertionFailure("\(error)")
  94. }
  95. shell("xxd -r -p /tmp/SidecarPatcher/output.txt /tmp/SidecarPatcher/SidecarCore")
  96. // Mount system (thanks to: https://github.com/pookjw/SidecarPatcher/issues/1)
  97. shell("sudo mount -uw /")
  98. // Remove existing original system file
  99. if fileManager.fileExists(atPath: "\(path)/SidecarCore") {
  100. do {
  101. try fileManager.removeItem(atPath: "\(path)/SidecarCore")
  102. }
  103. catch let error as NSError {
  104. assertionFailure("\(error)")
  105. }
  106. }
  107. // Copy system file
  108. do {
  109. try fileManager.copyItem(atPath: "/tmp/SidecarPatcher/SidecarCore", toPath: "\(path)/SidecarCore")
  110. }
  111. catch let error as NSError {
  112. assertionFailure("\(error)")
  113. }
  114. // codesign
  115. shell("sudo codesign -f -s - \"\(path)/SidecarCore\"")
  116. shell("sudo chmod 755 \"\(path)/SidecarCore\"")
  117. }
  118. struct PatchCode{
  119. var original: String
  120. var patched: String
  121. }
  122. let fileManager = FileManager()
  123. let SidecarCorePath = "/System/Library/PrivateFrameworks/SidecarCore.framework/Versions/A"
  124. var patchDictionary: [String: PatchCode] = [:]
  125. patchDictionary["Mac"] = PatchCode(original: "694d616331332c3100694d616331332c3200694d616331332c3300694d616331342c3100694d616331342c3200694d616331342c3300694d616331342c3400694d616331352c3100694d616331362c3100694d616331362c32004d6163426f6f6b382c31004d6163426f6f6b416972352c31004d6163426f6f6b416972352c32004d6163426f6f6b416972362c31004d6163426f6f6b416972362c32004d6163426f6f6b416972372c31004d6163426f6f6b416972372c32004d6163426f6f6b50726f392c31004d6163426f6f6b50726f392c32004d6163426f6f6b50726f31302c31004d6163426f6f6b50726f31302c32004d6163426f6f6b50726f31312c31004d6163426f6f6b50726f31312c32004d6163426f6f6b50726f31312c33004d6163426f6f6b50726f31312c34004d6163426f6f6b50726f31312c35004d6163426f6f6b50726f31322c31004d61636d696e69362c31004d61636d696e69362c32004d61636d696e69372c31004d616350726f352c31004d616350726f362c31", patched: "694d616330302c3000694d616330302c3000694d616330302c3000694d616330302c3000694d616330302c3000694d616330302c3000694d616330302c3000694d616330302c3000694d616330302c3000694d616330302c30004d6163426f6f6b302c30004d6163426f6f6b416972302c30004d6163426f6f6b416972302c30004d6163426f6f6b416972302c30004d6163426f6f6b416972302c30004d6163426f6f6b416972302c30004d6163426f6f6b416972302c30004d6163426f6f6b50726f302c30004d6163426f6f6b50726f302c30004d6163426f6f6b50726f30302c30004d6163426f6f6b50726f30302c30004d6163426f6f6b50726f30302c30004d6163426f6f6b50726f30302c30004d6163426f6f6b50726f30302c30004d6163426f6f6b50726f30302c30004d6163426f6f6b50726f30302c30004d6163426f6f6b50726f30302c30004d61636d696e69302c30004d61636d696e69302c30004d61636d696e69302c30004d616350726f302c30004d616350726f302c30")
  126. patchDictionary["iPad"] = PatchCode(original: "69506164342c310069506164342c320069506164342c330069506164342c340069506164342c350069506164342c360069506164342c370069506164342c380069506164342c390069506164352c310069506164352c320069506164352c330069506164352c340069506164362c31310069506164362c3132", patched: "69506164302c300069506164302c300069506164302c300069506164302c300069506164302c300069506164302c300069506164302c300069506164302c300069506164302c300069506164302c300069506164302c300069506164302c300069506164302c300069506164302c30300069506164302c3030")
  127. print("SidecarPatcher (Version 10)")
  128. print("GitHub : https://github.com/pookjw/SidecarPatcher") // don't erase this
  129. let originalCore = importCore(path: SidecarCorePath) // get code
  130. let patchToCode = checkSystem(core: originalCore, code: patchDictionary) // check availability and get patch code
  131. let patchedCore = patch(core: originalCore, code: patchToCode) // patch code
  132. exportCore(core: patchedCore, path: SidecarCorePath) // copy patched code to system
  133. print("Reboot your macOS.")