`mov byte [esi+7], al` 处的分段错误

逆向工程 部件 外壳代码
2021-06-26 09:23:11
Section .text
        global _start

_start:
        jmp short GoToCall

shellcode:
        pop             esi
        xor             eax, eax
        mov byte        [esi+7], al
        lea             ebx, [esi]
        mov long        [esi + 8], ebx
        mov long        [esi + 12], eax
        mov byte        al, 0x0b
        mov             ebx, [esi]
        lea             ecx, [esi + 8]
        lea             edx, [esi + 12]
        int             0x80

GoToCall:
        Call shellcode
        db      "/bin/shJAAAABBBB"

编译上面的shellcode后,我得到了下面的反汇编。在第 3 行,我遇到了 Segmentaion 错误。

(gdb) disassemble shellcode 
Dump of assembler code for function shellcode:
   0x08049002 <+0>: pop    %esi
   0x08049003 <+1>: xor    %eax,%eax
=> 0x08049005 <+3>: mov    %al,0x7(%esi)
   0x08049008 <+6>: lea    (%esi),%ebx
   0x0804900a <+8>: mov    %ebx,0x8(%esi)
   0x0804900d <+11>:    mov    %eax,0xc(%esi)
   0x08049010 <+14>:    mov    $0xb,%al
   0x08049012 <+16>:    mov    (%esi),%ebx
   0x08049014 <+18>:    lea    0x8(%esi),%ecx
   0x08049017 <+21>:    lea    0xc(%esi),%edx
   0x0804901a <+24>:    int    $0x80
End of assembler dump.
(gdb) printf "%s", $esi
/bin/shJAAAABBBB(gdb) printf "%s", $esi+7
JAAAABBBB(gdb) si

Program received signal SIGSEGV, Segmentation fault.
0x08049005 in shellcode ()
(gdb) 
4个回答

导致 SIGSEGV 的指令试图'\0''h'in之后存储 a "/bin/shJAAAABBBB"

您的所有代码/数据都在.text可能是只读部分中。objdump -h在生成的二进制文件上运行,您应该在输出中看到类似以下内容:

  5 .text         00000031  00001000  00001000  00001000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE

其中包含存储字符串字节的地址。

shellcode所在和执行的内存是不可写的。它可能由于不同的原因发生,我猜你的 shellcode 被编码为 C 文字字符串。由于此内存位置不可写,因此您会收到异常。

如果您只是想尝试 shellcode,请使用mmap(2)with flag分配一个内存页面PROT_EXEC | PROT_READ | PROT_WRITE,将您的 shellcode 复制到其中并跳转到它。

顺便说一句,你的shellcode是空字节的,如果你使用strcpy(3)函数复制它,你可以删除两者xor eax, eaxmov [esi+7], al因为strcpy(3)会为你写0x00。只需确保将“/bin/shJAAAABBBB”修剪为“/bin/sh”。

这是因为/bin/sh需要\0,所以替换"AAAABBBB"\0

正如@booto 的回答所示,objdump -h打印.text部分是只读的。

您可以尝试这样编译,而不必更新原始源代码:

nasm -f elf32 -o ./Execve.o Execve.nasm
ld -N -o ./Execve ./Execve.o

ld -N

将文本和数据部分设置为可读可写。