C 如何将汇编程序正确地转换为外壳代码?

C 如何将汇编程序正确地转换为外壳代码?,c,assembly,nasm,shellcode,C,Assembly,Nasm,Shellcode,我在nasm(x64)中编写了一个程序,该程序应该执行/bin/bash,并且运行良好。然后我用objdump-D运行程序,我写下如下机器代码:\xbb\x68\x53\x48\xbb\x2f\x62\x69\x6e\x2f\x62\x61\x73\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05。然后我用/shell$(python-c'print”\xbb\x68\x53\x48\xbb\x2f\x62\x69\x6e\x2f\x62\x

我在nasm(x64)中编写了一个程序,该程序应该执行
/bin/bash
,并且运行良好。然后我用
objdump-D
运行程序,我写下如下机器代码:
\xbb\x68\x53\x48\xbb\x2f\x62\x69\x6e\x2f\x62\x61\x73\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05
。然后我用
/shell$(python-c'print”\xbb\x68\x53\x48\xbb\x2f\x62\x69\x6e\x2f\x62\x61\x73\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05“)运行了这个命令。
,我得到了一条非法指令。但是汇编程序运行得很好!有人能帮忙吗

shell.c:

int main(int argc, char **argv) {
    int (*func)();
    func = (int (*)()) argv[1];
    (int)(*func)();
}
bash.asm:

section .text
global start
start:
    mov rbx, 0x68
    push rbx
    mov rbx, 0x7361622f6e69622f
    push rbx
    mov rdi, rsp
    push rax
    push rdi
    mov rsi, rsp
    mov al, 59
    syscall

objdump:

./bash:     file format elf64-x86-64


Disassembly of section .text:

0000000000401000 <start>:
  401000:   bb 68 00 00 00          mov    $0x68,%ebx
  401005:   53                      push   %rbx
  401006:   48 bb 2f 62 69 6e 2f    movabs $0x7361622f6e69622f,%rbx
  40100d:   62 61 73 
  401010:   53                      push   %rbx
  401011:   48 89 e7                mov    %rsp,%rdi
  401014:   50                      push   %rax
  401015:   57                      push   %rdi
  401016:   48 89 e6                mov    %rsp,%rsi
  401019:   b0 3b                   mov    $0x3b,%al
  40101b:   0f 05                   syscall
/bash:文件格式elf64-x86-64
第节的分解。正文:
0000000000401000 :
401000:bb 6800 mov$0x68,%ebx
401005:53推送%rbx
401006:48 bb 2f 62 69 6e 2f movabs$0x7361622f6e69622f,%rbx
40100d:626173
401010:53推送%rbx
401011:48 89 e7 mov%rsp,%rdi
401014:50%推力rax
401015:57推送%rdi
401016:4889E6MOV%rsp%rsi
401019:b0 3b mov$0x3b,%al
40101b:0f 05系统调用

此处省略了零字节:

\xbb\x68\x53\x48\xbb\x2f\x62\x69\x6e\x2f\x62\x61\x73\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05
相对于

  401000:   bb 68 00 00 00          mov    $0x68,%ebx
零字节是指令的一部分,不能跳过。所以你必须包括它们


然而,问题是零字节将终止参数字符串,因此必须避免。作为外壳代码设计者,您有责任以一种不包含可能不会出现的字节值的方式构造它。在许多情况下,这意味着没有零字节,因为外壳代码是作为C字符串注入的,但在其他情况下,其他值也可能有问题。

您遗漏了第一条指令的3个零字节。像这样的外壳代码不应该有零字节,但这并不意味着您可以简单地忽略它们。您需要编写没有它们的代码。只需执行
推送$0x68
即可,而不必执行前两条指令。PS:您使用了
rax
,但没有对其进行初始化,这不太可能可靠地工作。@Jester谢谢您的提示。但当我和strace一起运行外壳代码时,我得到了这个
execve(“/bin/bash”、[“/bin/bash”]、0x7ffcdcd335eastrace:umoven:short read(6<8)@0x7ffcdcd33ffa/*322 vars,unterminated*/)=-1 EFAULT(Ungültige address)---SIGSEGV{si_signo sign=SIGSEGV,si_code=siu内核,si_addr=NULL}--++,被SIGSEGV++杀死字节,并执行
/bin/sh
(您可以将其修改为使用
/bin/bash
:。它还提供了一种自动生成外壳代码字符串的机制,而不是手动从objdump复制信息。您的代码不会将RDX(最后一个参数)归零。