iOS ARM64 Syscalls

前端 未结 2 1350
难免孤独
难免孤独 2020-12-22 08:14

I am learning more about shellcode and making syscalls in arm64 on iOS devices. The device I am testing on is iPhone 6S.

I got the list of syscalls from this link (h

2条回答
  •  一整个雨季
    2020-12-22 09:15

    This should get you going. As @Siguza mentioned you must use x16 , not x8 for the syscall number.

    #import 
    char testStringGlobal[] = "helloWorld from global variable\n";
    int main(int argc, char * argv[]) {
        char testStringOnStack[] = "helloWorld from stack variable\n";
    #if TARGET_CPU_ARM64
    
        //VARIANT 1 suggested by @PeterCordes
        //an an input it's a file descriptor set to STD_OUT 1 so the syscall write output appears in Xcode debug output
        //as an output this will be used for returning syscall return value;
        register long x0 asm("x0") = 1;
        //as an input string to write
        //as an output this will be used for returning syscall return value higher half (in this particular case 0)
        register char *x1 asm("x1") = testStringOnStack;
        //string length
        register long x2 asm("x2") = strlen(testStringOnStack);
        //syscall write is 4
        register long x16 asm("x16") = SYS_write; //syscall write definition - see my footnote below
    
        //full variant using stack local variables for register x0,x1,x2,x16 input
        //syscall result collected in x0 & x1 using "semi" intrinsic assembler
        asm volatile(//all args prepared, make the syscall
                     "svc #0x80"
                     :"=r"(x0),"=r"(x1) //mark x0 & x1 as syscall outputs
                     :"r"(x0), "r"(x1), "r"(x2), "r"(x16): //mark the inputs
                     //inform the compiler we read the memory
                     "memory",
                     //inform the compiler we clobber carry flag (during the syscall itself)
                     "cc");
    
        //VARIANT 2
        //syscall write for globals variable using "semi" intrinsic assembler
        //args hardcoded
        //output of syscall is ignored
        asm volatile(//prepare x1 with the help of x8 register
                     "mov x1, %0 \t\n"
                     //set file descriptor to STD_OUT 1 so it appears in Xcode debug output
                     "mov x0, #1 \t\n"
                     //hardcoded length
                     "mov x2, #32 \t\n"
                     //syscall write is 4
                     "mov x16, #0x4 \t\n"
                     //all args prepared, make the syscall
                     "svc #0x80"
                     ::"r"(testStringGlobal):
                     //clobbered registers list
                     "x1","x0","x2","x16",
                     //inform the compiler we read the memory
                     "memory",
                     //inform the compiler we clobber carry flag (during the syscall itself)
                     "cc");
    
        //VARIANT 3 - only applicable to global variables using "page" address
        //which is  PC-relative addressing to load addresses at a fixed offset from the current location (PIC code).
        //syscall write for global variable using "semi" intrinsic assembler
        asm volatile(//set x1 on proper PAGE
                     "adrp x1,_testStringGlobal@PAGE \t\n" //notice the underscore preceding variable name by convention
                     //add the offset of the testStringGlobal variable
                     "add x1,x1,_testStringGlobal@PAGEOFF \t\n"
                     //set file descriptor to STD_OUT 1 so it appears in Xcode debug output
                     "mov x0, #1 \t\n"
                     //hardcoded length
                     "mov x2, #32 \t\n"
                     //syscall write is 4
                     "mov x16, #0x4 \t\n"
                     //all args prepared, make the syscall
                     "svc #0x80"
                     :::
                     //clobbered registers list
                     "x1","x0","x2","x16",
                     //inform the compiler we read the memory
                     "memory",
                     //inform the compiler we clobber carry flag (during the syscall itself)
                     "cc");
    #endif
        @autoreleasepool {
            return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }
    }
    

    EDIT

    To @PeterCordes excellent comment, yes there is a syscall numbers definition header which I included in the above snippet^ in Variant 1. But it's important to mention inside it's defined by Apple like this:

    #ifdef __APPLE_API_PRIVATE
    #define SYS_syscall        0
    #define SYS_exit           1
    #define SYS_fork           2
    #define SYS_read           3
    #define SYS_write          4
    

    I haven't heard of a case yet of an iOS app AppStore rejection due to using a system call directly through svc 0x80 nonetheless it's definitely not public API.

    As for the suggested "=@ccc" by @PeterCordes i.e. carry flag (set by syscall upon error) as an output constraint that's not supported as of latest XCode11 beta / LLVM 8.0.0 even for x86 and definitely not for ARM.

提交回复
热议问题