Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix iPhone13 pro #84

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b48c1fb
use kfd
hrtowii Jul 30, 2023
046e080
use kfd
hrtowii Jul 30, 2023
9cd9689
should work now
hrtowii Jul 31, 2023
7240f3e
kfd support
hrtowii Jul 31, 2023
a71637e
doesn't work. why?
hrtowii Jul 31, 2023
c03b93a
enable for custom fonts
hrtowii Jul 31, 2023
b5419c9
try uicaching?
hrtowii Jul 31, 2023
9845c5e
try uicaching
hrtowii Jul 31, 2023
99d1113
i was rewriting the file to itself :skull:
hrtowii Aug 1, 2023
9467ca6
Probably ready for release
hrtowii Aug 1, 2023
7d98b60
readme changes
hrtowii Aug 1, 2023
5865bc8
update readme, i'll cleanup unused stuff later
hrtowii Aug 1, 2023
70132ae
Yuhh
hrtowii Aug 1, 2023
84b9347
Bruh
hrtowii Aug 1, 2023
a9de3ae
Bruh
hrtowii Aug 1, 2023
b792996
Revert deleting files
hrtowii Aug 1, 2023
1e7fa0b
cleanup 1
hrtowii Aug 1, 2023
c3fccea
clarify instructions
hrtowii Aug 1, 2023
4a214e1
i fucked up just now. fixed!
hrtowii Aug 1, 2023
8f0ab89
Added all iOS support (not iPad atm)
34306 Aug 1, 2023
a892db0
Merge pull request #1 from 34306/patch-1
hrtowii Aug 1, 2023
9f7afd1
Added offsets for iPhone SE (2022) on iOS 16.6b1
M3ggy213 Aug 1, 2023
87a49e8
most cursed shit ever (thanks 34306)
hrtowii Aug 1, 2023
7db8dfc
Update dynamic_info.h
gorouflex Aug 1, 2023
c694adc
Merge pull request #3 from gorouflex/main
hrtowii Aug 1, 2023
9ebb778
Merge pull request #2 from M3ggy213/main
hrtowii Aug 1, 2023
00f2b22
iphone 14 pro, 16.4.1 offsets kfd
michaljedrr Aug 1, 2023
f54b006
iphone 14 pro, 16.4.1 offsets kfd
michaljedrr Aug 1, 2023
3b7f34e
Added offset for iPhone SE 2022, iOS 16.4
dora727 Aug 1, 2023
4e6174d
12 (pro) 16.6b1 offsets
hrtowii Aug 1, 2023
03b5c09
Merge pull request #4 from michaljedrr/main
hrtowii Aug 1, 2023
362a160
Merge pull request #5 from dora727/main
hrtowii Aug 1, 2023
9ca1f4b
Added offsets for iPad 9th Gen, 16.1.1
Genxster1998 Aug 1, 2023
adc343e
Merge pull request #6 from Genxster1998/main
hrtowii Aug 1, 2023
f3256ac
t1sz_boot 25ull is needed for iPhone 13 Pro to exploit
wqhqq1 Aug 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
# KFDFontOverwrite
KFDFontOverwrite is an app that allows you to overwrite fonts on iOS ported to use the [kfd](https://github.com/felix-pb/kfd) kernel read/write primitives and [xsf1re's fork](https://github.com/wh1te4ever/kfd), which further built on them.

This needs kfd offsets found in [dynamic_info.h](https://github.com/hrtowii/WDBFontOverwrite/blob/main/WDBFontOverwrite/libkfd/info/dynamic_info.h).
If you don't see your device + iOS combination, please refer to [lrdsnow's kfd-offsets repository](https://github.com/Lrdsnow/kfd_offsets), add them to dynamic_info, and change the 4 + 0x8 to 0x10. then build with xcode.

If you don't have xcode, please wait or open a PR with your dynamic_info.h. I will collate them together and push IPAs everyday.

I'm waiting for a unfiied dynamic_info.h file to come out with every device/iOS combination (it will be monstrously long)

## How do I use it?
1. open the app, wait 30 seconds to kopen
2. apply fonts
3. kclose (it will automatically respring)

If you're using custom fonts, you can import them first, then follow the 3 steps.

## How does overwriting to a file work?
Answer: Following [opa334's](https://twitter.com/opa334dev/status/1684995963960643584) [instructions](https://twitter.com/opa334dev/status/1684993935213539328) on Twitter, I managed to create a function that overwrites the contents of one file to another without requiring vnode offsets.

Source for this code is in my [kfd fork](https://github.com/hrtowii/kfd/commit/751f85cb991041df1b264713bbb7cfb187499f45), this project, and in [xsf1re's github repository](https://github.com/wh1te4ever/kfd/blob/main/kfd/fun/thanks_opa334dev_htrowii.m)

## Credits
* opa334 for telling how to overwrite files
* xsf1re
* GinsuDev
* zhuowei for the original WDBFontOverwrite

# Original README.md
Proof-of-concept app to overwrite fonts on iOS using [CVE-2022-46689](https://support.apple.com/en-us/HT213530).

Works on iOS 16.1.2 and below (tested on iOS 16.1) on unjailbroken devices.
Expand Down
225 changes: 189 additions & 36 deletions WDBFontOverwrite.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"pins" : [
{
"identity" : "dynamic",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mhdhejazi/Dynamic",
"state" : {
"revision" : "ab9a2570862d54aed2663691bb767f881226a12f",
"version" : "1.2.0"
}
}
],
"version" : 2
}
2 changes: 0 additions & 2 deletions WDBFontOverwrite/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,5 @@
</dict>
</dict>
</array>
<key>NSAppleMusicUsageDescription</key>
<string>WDBFontOverwrite</string>
</dict>
</plist>
3 changes: 3 additions & 0 deletions WDBFontOverwrite/MainInterface/ActionButtons.ViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,17 @@ extension ActionButtons {
if error != nil {
print("can't get disk access, using backup respring")
respringLegacy()
xpc_crasher(UnsafeMutablePointer<CChar>(mutating: "com.apple.backboard.TouchDeliveryPolicyServer"))
} else {
xpc_crasher(UnsafeMutablePointer<CChar>(mutating: "com.apple.frontboard.systemappservices"))
xpc_crasher(UnsafeMutablePointer<CChar>(mutating: "com.apple.backboard.TouchDeliveryPolicyServer"))
}
}
}

@available(iOS, deprecated: 15)
func respringLegacy() {
xpc_crasher(UnsafeMutablePointer<CChar>(mutating: "com.apple.backboard.TouchDeliveryPolicyServer"))
let sharedApplication = UIApplication.shared
let windows = sharedApplication.windows
if let window = windows.first {
Expand Down
60 changes: 60 additions & 0 deletions WDBFontOverwrite/MainInterface/CustomFontsScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,71 @@ struct CustomFontsScene: View {
@StateObject private var viewModel = ViewModel()
@EnvironmentObject var progressManager: ProgressManager
@Environment(\.openURL) private var openURL
@State private var kfd: UInt64 = 0

private var puaf_pages_options = [16, 32, 64, 128, 256, 512, 1024, 2048]
@State private var puaf_pages_index = 7
@State private var puaf_pages = 0

private var puaf_method_options = ["physpuppet", "smith"]
@State private var puaf_method = 1

private var kread_method_options = ["kqueue_workloop_ctl", "sem_open"]
@State private var kread_method = 1

private var kwrite_method_options = ["dup", "sem_open"]
@State private var kwrite_method = 1

var body: some View {
NavigationView {
VStack(spacing: 10) {
Form {
Section {
Picker(selection: $puaf_pages_index, label: Text("puaf pages:")) {
ForEach(0 ..< puaf_pages_options.count, id: \.self) {
Text(String(self.puaf_pages_options[$0]))
}
}.disabled(kfd != 0)
}
Section {
Picker(selection: $puaf_method, label: Text("puaf method:")) {
ForEach(0 ..< puaf_method_options.count, id: \.self) {
Text(self.puaf_method_options[$0])
}
}.disabled(kfd != 0)
}
Section {
Picker(selection: $kread_method, label: Text("kread method:")) {
ForEach(0 ..< kread_method_options.count, id: \.self) {
Text(self.kread_method_options[$0])
}
}.disabled(kfd != 0)
}
Section {
Picker(selection: $kwrite_method, label: Text("kwrite method:")) {
ForEach(0 ..< kwrite_method_options.count, id: \.self) {
Text(self.kwrite_method_options[$0])
}
}.disabled(kfd != 0)
}
Section {
HStack {
Button("kopen") {
puaf_pages = puaf_pages_options[puaf_pages_index]
kfd = do_kopen(UInt64(puaf_pages), UInt64(puaf_method), UInt64(kread_method), UInt64(kwrite_method))
do_fun()
}.disabled(kfd != 0).frame(minWidth: 0, maxWidth: .infinity)
Button("kclose") {
do_kclose(kfd)
puaf_pages = 0
kfd = 0
}.disabled(kfd == 0).frame(minWidth: 0, maxWidth: .infinity)
Button("respring") {
// restartBackboard()
restartFrontboard()
// restartFrontboard()
}.disabled(kfd == 0).frame(minWidth: 0, maxWidth: 100)
}}
Section {
ExplanationView(
systemImage: "textformat",
Expand Down
86 changes: 73 additions & 13 deletions WDBFontOverwrite/MainInterface/PresetFontsScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,87 @@ import SwiftUI
struct PresetFontsScene: View {
@EnvironmentObject private var progressManager: ProgressManager
private let viewModel = ViewModel()

@State private var kfd: UInt64 = 0

private var puaf_pages_options = [16, 32, 64, 128, 256, 512, 1024, 2048]
@State private var puaf_pages_index = 7
@State private var puaf_pages = 0

private var puaf_method_options = ["physpuppet", "smith"]
@State private var puaf_method = 1

private var kread_method_options = ["kqueue_workloop_ctl", "sem_open"]
@State private var kread_method = 1

private var kwrite_method_options = ["dup", "sem_open"]
@State private var kwrite_method = 1

var body: some View {
NavigationView {
Form {
Section {
ExplanationView(
systemImage: "textformat",
description: "Choose from a selection of preset fonts.",
canShowProgress: true
)
Picker(selection: $puaf_pages_index, label: Text("puaf pages:")) {
ForEach(0 ..< puaf_pages_options.count, id: \.self) {
Text(String(self.puaf_pages_options[$0]))
}
}.disabled(kfd != 0)
}
Section {
Picker(selection: $puaf_method, label: Text("puaf method:")) {
ForEach(0 ..< puaf_method_options.count, id: \.self) {
Text(self.puaf_method_options[$0])
}
}.disabled(kfd != 0)
}
Section {
Picker(selection: $kread_method, label: Text("kread method:")) {
ForEach(0 ..< kread_method_options.count, id: \.self) {
Text(self.kread_method_options[$0])
}
}.disabled(kfd != 0)
}
Section {
Picker(selection: $kwrite_method, label: Text("kwrite method:")) {
ForEach(0 ..< kwrite_method_options.count, id: \.self) {
Text(self.kwrite_method_options[$0])
}
}.disabled(kfd != 0)
}
.listRowBackground(Color(UIColor(red: 0.44, green: 0.69, blue: 0.67, alpha: 1.00)))
fontsSection
actionSection
Section {
HStack {
Button("kopen") {
puaf_pages = puaf_pages_options[puaf_pages_index]
kfd = do_kopen(UInt64(puaf_pages), UInt64(puaf_method), UInt64(kread_method), UInt64(kwrite_method))
do_fun()
}.disabled(kfd != 0).frame(minWidth: 0, maxWidth: .infinity)
Button("kclose") {
do_kclose(kfd)
puaf_pages = 0
kfd = 0
}.disabled(kfd == 0).frame(minWidth: 0, maxWidth: .infinity)
Button("respring") {
// restartBackboard()
restartFrontboard()
// restartFrontboard()
}.disabled(kfd == 0).frame(minWidth: 0, maxWidth: 100)
}
Section {
ExplanationView(
systemImage: "textformat",
description: "Choose from a selection of preset fonts.",
canShowProgress: true
)
}
.listRowBackground(Color(UIColor(red: 0.44, green: 0.69, blue: 0.67, alpha: 1.00)))
fontsSection
actionSection
}
.navigationTitle("Presets")
}
.navigationTitle("Presets")
.navigationViewStyle(.stack)
}
.navigationViewStyle(.stack)
}
}

private extension PresetFontsScene {
var fontsSection: some View {
Section {
Expand Down Expand Up @@ -60,7 +120,7 @@ private extension PresetFontsScene {
} header: {
Text("Actions")
} footer: {
Text("Originally created by [@zhuowei](https://twitter.com/zhuowei). Updated & maintained by [@GinsuDev](https://twitter.com/GinsuDev).")
Text("Originally created by [@zhuowei](https://twitter.com/zhuowei). KFD fork by [@htrowii](https://twitter.com/htrowii). Updated & maintained by [@GinsuDev](https://twitter.com/GinsuDev).")
}
}
}
Expand Down
100 changes: 30 additions & 70 deletions WDBFontOverwrite/OverwriteFontImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@

import UIKit
import UniformTypeIdentifiers
import Dynamic
var connection: NSXPCConnection?

func removeIconCache() {
print("removing icon cache")
if connection == nil {
let myCookieInterface = NSXPCInterface(with: ISIconCacheServiceProtocol.self)
connection = Dynamic.NSXPCConnection(machServiceName: "com.apple.iconservices", options: []).asObject as? NSXPCConnection
connection!.remoteObjectInterface = myCookieInterface
connection!.resume()
print("Connection: \(connection!)")
}

(connection!.remoteObjectProxy as AnyObject).clearCachedItems(forBundeID: nil) { (a: Any, b: Any) in // passing nil to remove all icon cache
print("Successfully responded (\(a), \(b ?? "(null)"))")
}
}


func overwriteWithFont(name: String) async {
let fontURL = Bundle.main.url(
Expand Down Expand Up @@ -39,6 +57,7 @@ func overwriteWithFontImpl(
pathToTargetFont: String
) {
var fontData: Data = try! Data(contentsOf: fontURL)

#if false
let documentDirectory = FileManager.default.urls(
for: .documentDirectory,
Expand All @@ -50,81 +69,21 @@ func overwriteWithFontImpl(
let origData = try! Data(contentsOf: URL(fileURLWithPath: pathToRealTargetFont))
try! origData.write(to: URL(fileURLWithPath: pathToTargetFont))
#endif

// open and map original font
let fd = open(pathToTargetFont, O_RDONLY | O_CLOEXEC)
if fd == -1 {
sendImportMessage(.failure("Unable to open font."))
return
}
defer { close(fd) }
// check size of font
let originalFontSize = lseek(fd, 0, SEEK_END)
guard originalFontSize >= fontData.count else {
sendImportMessage(.failure("Font too big."))
return
}
lseek(fd, 0, SEEK_SET)

if fontData[0..<4] == Data([0x77, 0x4f, 0x46, 0x32]) {
// if this is a woff2 (and not a ttc)
// patch our font with the padding
// https://www.w3.org/TR/WOFF2/#woff20Header
// length
withUnsafeBytes(of: UInt32(originalFontSize).bigEndian) {
fontData.replaceSubrange(0x8..<0x8 + 4, with: $0)
}
// privOffset
withUnsafeBytes(of: UInt32(fontData.count).bigEndian) {
fontData.replaceSubrange(0x28..<0x28 + 4, with: $0)
let cPathtoTargetFont = pathToTargetFont.withCString { ptr in
return strdup(ptr)
}
// privLength
withUnsafeBytes(of: UInt32(Int(originalFontSize) - fontData.count).bigEndian) {
fontData.replaceSubrange(0x2c..<0x2c + 4, with: $0)
}
}
let mutablecPathtoTargetFont = UnsafeMutablePointer<Int8>(mutating: cPathtoTargetFont)

// Map the font we want to overwrite so we can mlock it
let fontMap = mmap(nil, fontData.count, PROT_READ, MAP_SHARED, fd, 0)
if fontMap == MAP_FAILED {
sendImportMessage(.failure("Map failed"))
return
}
// mlock so the file gets cached in memory
guard mlock(fontMap, fontData.count) == 0 else {
sendImportMessage(.failure("Can't mlock"))
return
}

updateProgress(total: true, progress: Double(fontData.count))

// for every 16k chunk, rewrite
print(Date())
for chunkOff in stride(from: 0, to: fontData.count, by: 0x4000) {
print(String(format: "%lx", chunkOff))
if chunkOff % 0x40000 == 0 {
updateProgress(total: false, progress: Double(chunkOff))
let cFontURL = fontURL.path.withCString { ptr in
return strdup(ptr)
}
let dataChunk = fontData[chunkOff..<min(fontData.count, chunkOff + 0x4000)]
var overwroteOne = false
for _ in 0..<2 {
let overwriteSucceeded = dataChunk.withUnsafeBytes { dataChunkBytes in
return unaligned_copy_switch_race(
fd, Int64(chunkOff), dataChunkBytes.baseAddress, dataChunkBytes.count)
}
if overwriteSucceeded {
overwroteOne = true
break
}
print("try again?!")
}
guard overwroteOne else {
sendImportMessage(.failure("can't overwrite"))
return
}
}
let mutablecFontURL = UnsafeMutablePointer<Int8>(mutating: cFontURL)

funVnodeOverwrite2(cPathtoTargetFont, mutablecFontURL) // the magic is here

updateProgress(total: false, progress: Double(fontData.count))
sendImportMessage(.success)
removeIconCache()
print(Date())
}

Expand Down Expand Up @@ -202,3 +161,4 @@ func importCustomFontImpl(
try! FileManager.default.copyItem(at: fileURL, to: targetURL)
return nil
}

10 changes: 7 additions & 3 deletions WDBFontOverwrite/WDBFontOverwrite-Bridging-Header.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
#import "vm_unaligned_copy_switch_race.h"
#import "_UIKeyboardCache.h"
#import "helpers.h"
#import "grant_full_disk_access.h"
#import "fun/helpers.h"
#import "fun/fun.h"
#import "fun/grant_full_disk_access.h"
#import "fun/krw.h"
#import "fun/thanks_opa334dev_htrowii.h"
#import "uicache/ISIconCacheServiceProtocol-Protocol.h"

Loading