首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iOS ARM64系统

iOS ARM64系统
EN

Stack Overflow用户
提问于 2019-07-11 09:22:28
回答 2查看 5.4K关注 0票数 2

我正在学习更多关于外壳代码的知识,并在arm64上在iOS设备上制作系统。我正在测试的设备是iPhone 6S。

我从这个链接(https://github.com/radare/radare2/blob/master/libr/include/sflib/darwin-arm-64/ios-syscalls.txt)中得到了系统的列表。

我了解到,x8用于从这里为arm64 (http://arm.ninja/2016/03/07/decoding-syscalls-in-arm64/)放置syscall编号。

我认为用于传递arm64参数的各种寄存器应该与arm相同,因此我引用了取自https://azeria-labs.com/writing-arm-shellcode/的这个链接(强壮)。

我用Xcode编写了内联程序集,下面是一些片段

代码语言:javascript
复制
//exit syscall
__asm__ volatile("mov x8, #1");
__asm__ volatile("mov x0, #0");
__asm__ volatile("svc 0x80");

但是,当我跨过这些代码时,应用程序不会终止。

代码语言:javascript
复制
char write_buffer[]="console_text";
int write_buffer_size = sizeof(write_buffer);

__asm__ volatile("mov x8,#4;"     //arm64 uses x8 for syscall number
                 "mov x0,#1;"     //1 for stdout file descriptor
                 "mov x1,%0;"    //the buffer to display
                 "mov x2,%1;"    //buffer size
                 "svc 0x80;"
                 :
                 :"r"(write_buffer),"r"(write_buffer_size)
                 :"x0","x1","x2","x8"
                 );

如果这个syscall有效,它应该在Xcode的控制台输出屏幕中打印出一些文本。然而,没有任何东西被打印出来。

有许多在线文章用于ARM组装,有些使用svc 0x80,有些使用svc 0等,因此可以有一些变化。我尝试了各种方法,但我无法让这两个代码片段工作。

有人能提供一些指导吗?

编辑:当我编写C函数syscall int return_value=syscall(1,0);时,Xcode在它的程序集视图中显示了什么

代码语言:javascript
复制
    mov x1, sp
    mov x30, #0
    str x30, [x1]
    orr w8, wzr, #0x1
    stur    x0, [x29, #-32]         ; 8-byte Folded Spill
    mov x0, x8
    bl  _syscall

我不知道为什么会发出这段代码。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-07-11 16:08:32

用于syscalls的寄存器完全是任意的,您选择的资源对于XNU来说肯定是错误的。

据我所知,用于arm64的XNU完全是私有的,可能会在没有通知的情况下进行更改,因此没有发布的标准,但是您可以通过获取XNU源代码的副本(如果您喜欢的话是焦油球在网上查看 )、handle_svc函数的grep以及遵循代码来拼凑它的工作方式。

我不打算详细说明你到底在哪里找到哪一位,但最终的结果是:

  • 直接传递给svc的内容被忽略,但是标准库使用svc 0x80
  • x16持有syscall号码
  • x0通过x8最多可容纳9个参数*
  • 堆栈上没有参数。
  • x0x1最多保留2个返回值(例如,fork)。
  • 进位用于报告错误,在这种情况下,x0保存错误代码。

*这仅用于具有8个参数的间接syscall (x16 = 0)。

* XNU源代码中的评论也提到了x9,但似乎写这篇文章的工程师应该仔细研究一下错误。

然后是实际可用的syscall号码:

  • "UNIX“的规范源是XNU源代码树中的文件bsd/kern/syscalls.master。在最新的0 13测试版中,这些测试将syscall的数字从540提高到了大约540
  • "Mach syscalls“的规范源是XNU源树中的文件osfmk/kern/syscall_sw.c。这些系统是用-10-100之间的负数调用的(例如,-28task_self_trap)。
  • 与最后一点无关的是,可以分别用syscall数mach_absolute_time-4调用两个syscall mach_continuous_time-3
  • 一些低级操作可以通过platform_syscall与syscall number 0x80000000一起使用。
票数 12
EN

Stack Overflow用户

发布于 2019-07-18 10:53:31

这应该能让你走了。正如@Siguza所提到的,您必须使用x16,而不是x8来表示syscall号码。

代码语言:javascript
复制
#import <sys/syscall.h>
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]));
    }
}

编辑

对于@PeterCordes的优秀评论,是的,有一个syscall数字定义头<sys/syscall.h>,我在上面的变体1中包含了它。

代码语言:javascript
复制
#ifdef __APPLE_API_PRIVATE
#define SYS_syscall        0
#define SYS_exit           1
#define SYS_fork           2
#define SYS_read           3
#define SYS_write          4

我还没有听说过iOS应用程序AppStore由于直接通过svc 0x80使用系统调用而被拒绝的情况,尽管如此,它肯定是而不是公共 API。

至于建议的@PeterCordes "=@ccc",即XCode11标志(由syscall错误设置)作为输出约束,即使对于x86,也不支持最新的XCode11 beta / LLVM 8.0.0,而对于ARM也不支持。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56985859

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档