如何在64位(Linux)汇编中将argv参数传递给execv函数

4
我试图在64位代码中调用/bin/bash时传递参数。我无法使用.data部分,这对我来说有点棘手。我已经查看了各种代码示例,但没有一个很清晰(我是初学者)。我想要调用的是/bin/bash -c id
当我尝试将第二个参数留空时,我的代码可以正常工作,但是当我添加它时,我会收到以下错误:
execve("/bin/bash", [0x7361622f6e69622f, 0x646920632d2068, 0x7361622f6e69622f, 0x68], NULL) = -1 EFAULT (Bad address)

编译命令: nasm -f elf64 -o test.o test.asm;ld -o test test.o

section .text 
  global _start

_start:
  mov rax,59                     
  lea rdi,[rel bin]             
  lea rsi,[rel msg]
  syscall                       

align 8
  msg db '/bin/bash -c /bin/id',0
  bin db '/bin/bash',0

2
做得好,第一个问题你包括了你想要做什么、期望的行为、实际的行为和完整的代码。这是一个令人愉快的惊喜。 - prl
1个回答

3

execve的第二个参数是字符串指针数组(char **char *argv[])的地址。你给它的却是一个单独的字符串的地址 (char *)。

此外,execve(2)还有一个第三个参数,环境列表。如man页所述,argv和/或envp可以为NULL,并且Linux将其视为等效于空列表 (在内存中指向NULL的有效指针)。

应该修改为:

      mov rax, 59
      lea rdi, [rel bin]
      lea rsi, [rel args]
      xor edx, edx             ; Linux accepts NULL instead of a pointer to NULL
      syscall


; section   .rodata
      align 8
args  dq bin, arg1, arg2, 0

arg1  db '-c',0
arg2  db '/bin/id',0
bin   db '/bin/bash',0

如果你正在编写shellcode,请注意这个代码包含多个0字节,既在指令里(非负rel32寻址模式和32位立即数),也在数据中。

如果你不是在编写shellcode(要提取为含有代码和数据的平面二进制文件),请将你的数据放在一个单独的部分,最好是只读数据.rodata


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接