Mobile Protect - iOS Static Obfuscation
Prerequisites
An iOS project with the MobileProtect SDK installed.
A copy of the
datatheorem-obfuscate
tool.
Obfuscation Tool Download
In order to download the tool, you must have your Repo API Key on hand. You will find this API key in the Overview tab of the Active Protection page for Mobile Secure. Press the blue button on the right hand side that reads “Protect Mobile Apps“ and look for the “Keys & Config” section.
There are two options:
Direct download from Data Theorem’s portal: Direct Download Link
This link will open a login prompt, enter “1” for the user name and set the password to the contents of the Repo API Key.
By cloning the MobileProtect build repository:
Locate the Repo API Key and use it to run the following command:
git clone https://1:{REPO_API_KEY}@mobile-protect-repos.securetheorem.com/mobileprotect-ios
Move the datatheorem-obfuscate
binary to the root of the Xcode project (next to the .xcodeproj
or .xcworkspace
files).
Add Obfuscation Build Phases to Xcode
Disable ENABLE_USER_SCRIPT_SANDBOXING
by setting the variable in Build Settings > Build Options > User Script Sandboxing to NO, so the tool has access to the built files to modify them.
For projects using Cocoapods
For projects that use Cocoapods, add the following line to each target that is defined in the Podfile
:
script_phase({name: "Data Theorem Static Obfuscation", script: "$PROJECT_DIR/datatheorem-obfuscate", execution_position: :after_compile})
Additionally, add the following to the end of the Podfile
:
post_install do |installer|
installer.pods_project.targets.each do |target|
target.new_shell_script_build_phase("Data Theorem Static Obfuscation").shell_script = "$PODS_ROOT/../datatheorem-obfuscate"
end
end
Example Podfile
:
target `MyApp` do
pod 'MobileProtect'
script_phase({name: "Data Theorem Static Obfuscation", script: "$PROJECT_DIR/datatheorem-obfuscate", execution_position: :after_compile})
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.new_shell_script_build_phase("Data Theorem Static Obfuscation").shell_script = "$PODS_ROOT/../datatheorem-obfuscate"
end
end
For projects not using Cocoapods
For each target in the project (app/framework), add a Run Script
build phase named Data Theorem Static Obfuscation
to the Xcode project containing the following:
$PROJECT_DIR/datatheorem-obfuscate
Configuration
In the project's MobileProtect.plist
configuration file, perform the following steps:
Add a new key called
StaticObfuscation
with its type set toDictionary
.Inside this dictionary, insert a child key named
Enabled
with the typeBoolean
and set its value toYES
.
After making these changes and performing a “clean” of the project, the installation is complete. The application will be statically obfuscated the next time it is compiled.
Optional Configuration
The following configuration keys are supported:
Enabled
: A boolean value. Set toYES
to enable static obfuscation.ClassExcludeList
: Specify a path, relative to the project root, pointing to a file that contains a list of class names. Each class name should be on a separate line. The selectors associated with these classes will be excluded from static obfuscation.SelectorExcludeList
: A file path, relative to the project root, pointing to a file that contains a list of selector names. Each selector name should be on a separate line. Selectors in this file will be excluded from static obfuscation.
Excluding Selectors From Obfuscation
Projects that refer to selectors directly will need to exclude these selectors from obfuscation, otherwise the app might crash. Selectors are referred to directly:
When using the
@selector(...)
syntax.When using dynamic class lookup (
NSClassFromString()
,objc_getClass()
).When using key-value observation.
A typical crash caused by obfuscation of directly-referenced selectors will look similar to this:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SomeClassName someSelector]: unrecognized selector sent to instance 0x123abc123'
To resolve such a crash, add the class name (SomeClassName)
to the class exclusion list (refer to the ClassExcludeList
configuration) or add the selector someSelector
to the selector exclusion list (refer to the SelectorExcludeList
).
Sometimes, the error will mention the obfuscated selector name, e.g.:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SomeClassName XJEJKANDFKW]: unrecognized selector sent to instance 0x123abc123'
In this case, the corresponding (non-obfuscated) selector can be determined from the mapping file.