In the application development process, we need to not only complete the normal business logic, application performance, code robustness related issues, we sometimes need to consider the application security issues. So the issue of application security has a lot to do with it. For example, to prevent static analysis, code confusion, logic confusion; To prevent re-signing, apply ID checking, even code HASH checking, and so on. So in this article I want to talk about injection detection of code, because we find that with the update of iOS, our protection methods have changed a little bit.

Code injection

There are roughly two ways to inject code

  • Jailbreak injection: By modificationDYLD_INSERT_LIBRARIESValue of the environment variable to insert the dynamic library and execute
  • Non-jailbreak injection:
    • Package your custom Framwork or Dylib libraries directly into the APP and re-sign them.
    • Use Yololib to modify the MachO file and add the library path. Dyld loads and executes when the application starts.

Early protection mode

Find Other Linker Flages in the project’s Build Settings and add the fields -wl, -sectCreate,__RESTRICT,__raestrict,/dev/null This operation adds a Section to the executable file. We used MachOView analysis as follows:

MachOView

When this field is present in the MachO file, the way we insert the dynamic library through the jailbreak environment is disabled. Play a protective role. Its principle can be analyzed in DYLD source code.

Dyld source code analysis

The source version of DYLD analyzed here is 519.2.2. We can locate the _main function to load the insert dynamic library by retrieving DYLD_INSERT_LIBRARIES as follows.

// load any inserted libraries if ( sEnv.DYLD_INSERT_LIBRARIES ! = NULL ) { for (const char* const* lib = sEnv.DYLD_INSERT_LIBRARIES; *lib ! = NULL; ++lib) loadInsertedDylib(*lib); }Copy the code

But long before this environmental variable was judged, Dyld had made a judgment call

    if ( gLinkContext.processIsRestricted ) {
        pruneEnvironmentVariables(envp, &apple);
        // set again because envp and apple may have changed or moved
        setContext(mainExecutableMH, argc, argv, envp, apple);
    }
Copy the code

If the process is restricted! The current process is restricted from inserting into the dynamic library! Will call pruneEnvironmentVariables function to remove related environment variables. When will our processIsRestricted value be true? Further analysis of the source reveals that two key functions influence its value. The hasRestrictedSegment function specializes in detecting RESTRICT segments

// any processes with setuid or setgid bit set or with __RESTRICT segment is restricted
    if ( issetugid() || hasRestrictedSegment(mainExecutableMH) ) {
        gLinkContext.processIsRestricted = true;
    }
Copy the code

You can also see this through comments. Dynamic library inserts for any process whose __RESTRICT section is set to RESTRICTED will be restricted. We enter the processIsRestricted function, which is implemented as follows.

#if __MAC_OS_X_VERSION_MIN_REQUIRED
static bool hasRestrictedSegment(const macho_header* mh)
{
    const uint32_t cmd_count = mh->ncmds;
    const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));
    const struct load_command* cmd = cmds;
    for (uint32_t i = 0; i < cmd_count; ++i) {
        switch (cmd->cmd) {
            case LC_SEGMENT_COMMAND:
            {
                const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;

                //dyld::log("seg name: %s\n", seg->segname);
                if (strcmp(seg->segname, "__RESTRICT") == 0) {
                    const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
                    const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
                    for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
                        if (strcmp(sect->sectname, "__restrict") == 0) 
                            return true;
                    }
                }
            }
            break;
        }
        cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
    }

    return false;
}
Copy the code

Therefore, setting restricted to RESTRICTED in MachO by adding Other Linker Flags can be used to prevent code injection from jailbreaking. But the new dyLD source code drops the __RESTRICT detection. Starting with iOS10, this protection is no longer available

DYLD_INSERT_LIBRARIES detection

Now that the DYLD loading process no longer checks the __RESTRICT section, we manually check the DYLD_INSERT_LIBRARIES environment variable. Function to view the value of the current process environment variable.

  char *env = getenv("DYLD_INSERT_LIBRARIES");
  NSLog(@"%s",env);
Copy the code

Env is null when the dynamic library is not inserted. Then we can see the console output once the plug-in is written to our application

The 2019-01-03 19:20:37. 285 antiInject [7482-630392] / Library/MobileSubstrate/MobileSubstrate dylibCopy the code

Whitelist detection

So the above detection can only detect code injection in jailbroken environments. In non-jailbroken environments, reverse engineers can use the Yololib tool to inject dynamic libraries. So we can check to see if the dynamic library loaded by our application is owned by our source

bool HKCheckWhitelist(){ int count = _dyld_image_count(); for (int i = 0; i < count; I++) {// get the library name! const char * imageName = _dyld_get_image_name(i); // If the application is whitelisted, the path of the application itself is not determined. if (! strstr(libraries, imageName)&&! STRSTR (imageName "/ var/mobile/Containers/Bundle/Application")) {printf (" within the library than white list!!!!! \n%s",imageName); return NO; } } return YES; }Copy the code

The libraries variable is whitelisted.

IOS development exchange technology group: 563513413, no matter you are big bull or small white are welcome to enter, share BAT, Ali interview questions, interview experience, discuss technology, we exchange learning and growth together!