Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux Execve内联程序集_Linux_Gcc_X86 64_System Calls_Inline Assembly - Fatal编程技术网

Linux Execve内联程序集

Linux Execve内联程序集,linux,gcc,x86-64,system-calls,inline-assembly,Linux,Gcc,X86 64,System Calls,Inline Assembly,我最近进入了gcc的内联汇编,有了基本的汇编知识,我非常了解如何进行系统调用,直到我尝试使用一个或多个参数执行一个简单的sys\u execve。 如果我没有向系统调用execve传递任何附加参数,那么系统调用execve可以正常工作,并且在尝试传递任何附加参数时只运行不带参数的可执行文件 #include <stdio.h> char *argv[]={"/bin/echo","parameter test", NULL}; int main(){ __asm__ vola

我最近进入了gcc的内联汇编,有了基本的汇编知识,我非常了解如何进行系统调用,直到我尝试使用一个或多个参数执行一个简单的sys\u execve。 如果我没有向系统调用execve传递任何附加参数,那么系统调用execve可以正常工作,并且在尝试传递任何附加参数时只运行不带参数的可执行文件

#include <stdio.h>

char *argv[]={"/bin/echo","parameter test", NULL};

int main(){
  __asm__ volatile ("int $0x80"
          :
          :"a"(11), // syscall number (execve)
           "b"(argv[0]), // filename
           "c"(argv), // arguments
           "d"(0)); // env
  return 0;
}

这是32位代码,使用32位约定。使用gcc-m32编译,它会工作的。或者,切换到正确的64位版本,例如:

#include <stdio.h>

char *argv[]={"/bin/echo","parameter test", NULL};

int main(){
    int ret;
  __asm__ volatile ("syscall"
          :"=a" (ret)
          :"a"(59), // syscall number (execve)
           "D"(argv[0]), // filename
           "S"(argv), // arguments
           "d"(0) // env
          :"rcx","r11","cc");
  return 0;
}
#包括
char*argv[]={/bin/echo”,“参数测试”,NULL};
int main(){
int ret;
__asm_uuuuu易失性(“系统调用”
:“=a”(ret)
:“a”(59),//系统调用号(execve)
“D”(argv[0]),//文件名
“S”(argv),//参数
“d”(0)//env
:“rcx”、“r11”、“cc”);
返回0;
}

实际问题是数组中有64位指针,但您使用的32位兼容性中断当然需要32位指针。

这是32位代码,使用32位约定。使用gcc-m32编译,它会工作的。或者,切换到正确的64位版本,例如:

#include <stdio.h>

char *argv[]={"/bin/echo","parameter test", NULL};

int main(){
    int ret;
  __asm__ volatile ("syscall"
          :"=a" (ret)
          :"a"(59), // syscall number (execve)
           "D"(argv[0]), // filename
           "S"(argv), // arguments
           "d"(0) // env
          :"rcx","r11","cc");
  return 0;
}
#包括
char*argv[]={/bin/echo”,“参数测试”,NULL};
int main(){
int ret;
__asm_uuuuu易失性(“系统调用”
:“=a”(ret)
:“a”(59),//系统调用号(execve)
“D”(argv[0]),//文件名
“S”(argv),//参数
“d”(0)//env
:“rcx”、“r11”、“cc”);
返回0;
}

实际问题是数组中有64位指针,但您使用的32位兼容性中断当然需要32位指针。

查看api,我不确定您的参数是否正确。另外,您是否为x64编译?如果是这样的话,您就不应该使用int 0x80。我正在为x64编译,按照我目前的进度,文件名部分是正确的,因为我尝试执行的任何可执行文件都是有效的。我一直坚持的是给它任何参数。我需要用户确定我必须通过什么。查看api,我不确定您的参数是否正确。另外,您是否为x64编译?如果是这样的话,您就不应该使用int 0x80。我正在为x64编译,按照我目前的进度,文件名部分是正确的,因为我尝试执行的任何可执行文件都是有效的。我一直坚持的是给它任何参数。我需要用户确定我必须传递的内容。
=a
值得明确指出:系统调用在
eax
(或
rax
)寄存器中返回一个值,因此编译器需要知道这正在发生。否则,它将假定asm代码保持未修改的
eax
,如果它以后需要代码中的值59,它可能会尝试从
eax
加载它。这将导致问题,因为实际上,
eax
已被系统调用的返回值覆盖。可能不太可能在这段代码中实际导致问题,但通常需要注意。顺便说一下,从我在amd64 abi中读到的内容来看,系统调用可能会对
r11
以及
rcx
@NateEldredge:这是正确的,
syscall
/
sysret
的设计保证了
syscall
将始终对rcx和r11(带RIP和RFLAGS)进行缓冲。让内核看到这些regs中的内容需要用户空间的合作(例如,将它们放在堆栈上)。Linux系统调用不查看用户空间堆栈,因此ABI只是保持它的简单性,并让系统调用在amd64上的这两个reg上完成,而不像32位
int0x80
中只修改
eax
(返回值)。另外,我建议
return1
from
main
,因为只有当
execve
返回一个错误而不是正常工作时,才会达到此目的。并为全局
argv
指定一个不同的名称,并使其
const
,这样它就可以位于
.rodata
部分,以防编译器自己无法做到这一点。@NateEldredge除了关闭rcx和r11之外,还关闭标志。您是否也应该添加“cc”?
=a
值得明确指出:系统调用在
eax
(或
rax
)寄存器中返回一个值,因此编译器需要知道这正在发生。否则,它将假定asm代码保持未修改的
eax
,如果它以后需要代码中的值59,它可能会尝试从
eax
加载它。这将导致问题,因为实际上,
eax
已被系统调用的返回值覆盖。可能不太可能在这段代码中实际导致问题,但通常需要注意。顺便说一下,从我在amd64 abi中读到的内容来看,系统调用可能会对
r11
以及
rcx
@NateEldredge:这是正确的,
syscall
/
sysret
的设计保证了
syscall
将始终对rcx和r11(带RIP和RFLAGS)进行缓冲。让内核看到这些regs中的内容需要用户空间的合作(例如,将它们放在堆栈上)。Linux系统调用不查看用户空间堆栈,因此ABI只是保持它的简单性,并让系统调用在amd64上的这两个reg上完成,而不像32位
int0x80
中只修改
eax
(返回值)。另外,我建议
return1
from
main
,因为只有当
execve
返回一个错误而不是正常工作时,才会达到此目的。并为全局
argv
指定一个不同的名称,并使其
const
,这样它就可以位于
.rodata
部分,以防编译器自己无法做到这一点。@NateEldredge除了关闭rcx和r11之外,还关闭标志。你不也应该加上“抄送”吗?