Summary of iOS App Security:

1. Prevent packet capture from tampering with data

2. Prevent decompilation

3. Prevent dynamic debugging

4. Prevent secondary packaging

Key detection: Jailbreak detection

  • OK, this is the beginning of the body.

1. Prevent packet capture from tampering with data

For bag capture, the operation of using the artifact Charles will be covered in a separate article.

If you do not understand, the following is to use Charles to capture packets. Charles capture package tutorial

If someone really wants to grab your package, how do you guard against it? All I can say is, let it go, let it go, let it go.

Because basically if you want to grab the data that your program accesses, you can basically grab it.

For iOS, I’m doing two things right now.

1) Determine whether an agent is set up for packet capture, the current means is basically to set up an agent, so we can judge whether an agent is set up for the next step of prevention.

Insert this method before the network request, + (BOOL)getDelegateStatus {NSDictionary *proxySettings = CFBridgingRelease((__bridge CFTypeRef) _Nullable)((__bridge NSDictionary *)CFNetworkCopySystemProxySettings())); NSArray *proxies = CFBridgingRelease((__bridge CFTypeRef _Nullable)((__bridge NSArray *)CFNetworkCopyProxiesForURL((__bridge CFURLRef)[NSURL URLWithString:@"http://www.google.com"], (__bridge CFDictionaryRef)proxySettings))); NSDictionary *settings = [proxies objectAtIndex:0]; NSLog(@"host=%@", [settings objectForKey:(NSString *)kCFProxyHostNameKey]); NSLog(@"port=%@", [settings objectForKey:(NSString *)kCFProxyPortNumberKey]); NSLog(@"type=%@", [settings objectForKey:(NSString *)kCFProxyTypeKey]); If ([[Settings objectForKey:(NSString *) kCFProxyTypeNone] isEqualToString:@"kCFProxyTypeNone"]) {return NO; } else {// set the proxy return YES; }}Copy the code

2) RSA works with the background to set public and private keys to encrypt the requested data and returned data. Here is a separate introduction.

2. Prevent decompiling (prevent class-dump, hopper unmarshalling)

Escape detection

You usually need a jailbroken phone to get your own IPA bag

  • Check whether a jailbreak tool is installed on a device. The following files exist on a device that has a jailbreak tool installed: /Applications/Cydia.app /Library/MobileSubstrate/MobileSubstrate.dylib /bin/bash /usr/sbin/sshd /etc/apt

  • Determine whether cydia applications exist on the device

  • Permission to read the system application list A device that is not jailbroken does not have the permission to read all application names

  • The environment variable DYLD_INSERT_LIBRARIES obtained from the non-jailbroken phone DYLD_INSERT_LIBRARIES is NULL.

In summary, check whether the device is jailbroken

+ (BOOL)isJailbroken {NSArray *jailFilePaths = @[@"/Applications/ cydia.app ", @"/Library/MobileSubstrate/MobileSubstrate.dylib", @"/bin/bash", @"/usr/sbin/sshd", @"/etc/apt"]; for (NSString *filePath in jailFilePaths) { if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) { return YES; Cydia if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.example.package"]]){ return YES; } if ([[NSFileManager defaultManager] fileExistsAtPath:@"/User/Applications/"]){NSArray *applist = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/User/Applications/" error:nil]; NSLog(@"applist = %@",applist); return YES; Char *env = getenv("DYLD_INSERT_LIBRARIES"); if (env ! = NULL) { return YES; } return NO; }Copy the code

Code confusion

The way to generate obfuscation code here is through shell scripts, and we need a document to write the method or variable names we need to obfuscate.

  • Open terminal, CD to file directory, use

    touch confuse.shtouch func.list

At this point, drag the. Sh and. List files from the directory into the project

  • Writing a shell script

In your project, find the.sh file you just dragged in and write the script to confusion.sh

#! /bin/bash # this is a Shell script. http://www.runoob.com/linux/linux-shell.html # below using sqlite3 increase data, if you don't understand the sqlite3 command, self discipline: http://www.runoob.com/sqlite/sqlite-tutorial.html # data table TABLENAME = "CodeObfuscationOC" # database name SYMBOL_DB_FILE = "CodeObfuscation. Db" # to be replaced the method list file STRING_SYMBOL_FILE = "$PROJECT_DIR/ConfusionDemo/func. List" HEAD_FILE="$PROJECT_DIR/$PROJECT_NAME/CodeObfuscation. H "createTable() {echo "create table $TABLENAME(src text,des text);" | sqlite3 $SYMBOL_DB_FILE } insertValue() { echo "insert into $TABLENAME values('$1','$2');" | sqlite3 $SYMBOL_DB_FILE } query() { echo "select * from $TABLENAME where src='$1';" | sqlite3 $SYMBOL_DB_FILE} # generated randomly 16 name randomString () {openssl rand - 64 | base64 tr - CD 'a zA - Z | head - c 16} Rm -f $SYMBOL_DB_FILE rm -f $HEAD_FILE $HEAD_FILE echo '# ifNdef CodeObfuscation_h #define CodeObfuscation_h' >> $HEAD_FILE echo "//confuse string At ` date ` "> > $HEAD_FILE # method using cat will list the contents of the file read out entirely, forming an array, and then read line by line, and to replace the cat" $STRING_SYMBOL_FILE "| while the read - ra line; do if [[ ! -z "$line"]] then random= 'randomString' echo $line $random Write the generated string to the macro definition file, $HEAD_FILE echo "#define $line $random" >> $HEAD_FILE fi done echo "#endif" >> $HEAD_FILE sqlite3 $SYMBOL_DB_FILE .dumpCopy the code
  • Add the run script command

640.jpg

  • Then add $PROJECT_DIR ConfusionDemo/confuse. Sh

  • Authorizing a script

Next, in our project folder, give our script the highest permissions through terminal

chmod 777 confuse.sh
Copy the code
  • Add the precompiled file PCH

6401.jpg

Then configure the PCH file

6402.jpg

  • Add $PROJECT_DIR ConfusionDemo/PrefixHeader. PCH

  • Generate CodeObfuscation. H file

If we compile the code at this point, there is an extra CodeObfuscation. H file in the project (if not, go to the project folder, which is where I found it, and drag it into the project). This is the file that replaces the method name, which we introduce in the PCH file.

  • Add the name of the method you want to replace to func.list

Open the func.list file you dragged in before in the middle of your project and add the method names you want to obfuscate

// The name of the method in the project is its own code, Do not confuse the system the method name viewControllerTestMethodA viewControllerTestMethodB viewControllerTestMethodC viewControllerMethodWithParameter testString testArray testMutDicCopy the code
  • The results of

After the compilation

#ifndef CodeObfuscation_h
#define CodeObfuscation_h
 
#define viewControllerTestMethodA CTBxmOXAbJYekhnH
#define viewControllerTestMethodB RnPEjnXygFXLdikO
#define viewControllerTestMethodC IzHlDYOpaAFYFTXa
#define viewControllerMethodWithParameter nWqyalBcfoUSRVpc
#define testString MNPoVYdmCcklAnCO
#define testArray kHMRxPlGXGeqekxL
#define testMutDic hphPSODIvbBFSTHX
#endif
Copy the code

If you see this change in CodeObfuscation, you have successfully obfuscated your code. Even if you reverse class-dump it, it’s just a bunch of gibberish.

  • A few points to note

    Don’t confuse the system approach in iOS;

    Don’t confuse initialization methods like init in iOS;

    Do not confuse xiB files, which will cause the corresponding file cannot be found.

    Do not confuse class names used in storyboards;

    Confusion is risky and may be rejected by the App Store as a 2.1 package.

3. Prevent dynamic debugging

GDB and LLDB are dynamic debugging tools built into Xcode. Using GDB, LLDB allows you to debug your application dynamically (see parameters, return values, function call flow, etc.).

To stop hackers from using the debuggers GDB and LLDB to attack your App, you can insert the following code into the main.m file:

#import <dlfcn.h> #import <sys/types.h> typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data);  #if ! defined(PT_DENY_ATTACH) #define PT_DENY_ATTACH 31 #endif // ! defined(PT_DENY_ATTACH) void disable_gdb() { void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW); ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace"); ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0); dlclose(handle); } int main(int argc, char *argv[]) { // Don't interfere with Xcode debugging sessions. #if ! (DEBUG) disable_gdb(); #endif @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class])); }}Copy the code

4. Prevent secondary packaging

The apps and frameworks for iOS and OS X contain binaries and required resource files

(such as: Images, different language files, XIB/Storyboard files, profile files, etc.), when signing packages with the developer’s private key, for executables (Mach-O) the signature is written directly to that file, and for other resource files, It will be written to the CodeResources file under the _CodeSignature file, which is only a PList file.

The list file contains not only a list of files and their signatures, but also a set of rules that determine which resource files should be signed.

With the release of OS X 10.10 DP 5 and 10.9.5, Apple changed the format of the code signature and also changed the rules about resources.

If you use the CoDesign tool 10.9.5 or later, there are four different areas in the CodeResources file, with rules and Files for older versions, and Files2 and Rules2 for the new second version of the code signature.

The main difference is that in the new version you can no longer exclude certain resource files from the code signature, as in the past you could, simply by adding a file called ResourceRules. Plist to the signed package specifies which resource files should be ignored when checking the code signature.

However, this is no longer valid in the new version of code signing.

All code files and resource files must be signed, no exceptions can be made.

In the new version of code signing, an executable package within a package, such as an extension, is a separate entity that needs to set up a signature and should be treated separately when checking for signature integrity.

Some hackers may tamper with your package (including resource files and binaries) to add ads or modify your program’s logic, and then re-sign the package. Since third-party hackers can’t get the private key to sign the certificate, Therefore, the file embedded. Mobileprovision related to the signature in the program package will be replaced. We can directly check whether the file has been modified to determine whether the program is repackaged. Detect whether Embedded. Mobileprovision has been tampered with:

/ / calibration value, can be through the last packaging # define PROVISION_HASH @ "w2vnN9zRdwo0Z0Q4amDuwM2DKhc =" static NSDictionary * rootDic = nil; void checkSignatureMsg() { NSString *newPath=[[NSBundle mainBundle]resourcePath]; if (! rootDic) { rootDic = [[NSDictionary alloc] initWithContentsOfFile:[newPath stringByAppendingString:@"/_CodeSignature/CodeResources"]]; } NSDictionary*fileDic = [rootDic objectForKey:@"files2"]; NSDictionary *infoDic = [fileDic objectForKey:@"embedded.mobileprovision"]; NSData *tempData = [infoDic objectForKey:@"hash"]; NSString *hashStr = [tempData base64EncodedStringWithOptions:0]; if (! [PROVISION_HASH isEqualToString:hashStr]) { abort(); // Exit application}}Copy the code

Look at the original

IOS reverse collection is recommended