2020 GKCTF

  1. Crypto
    1. 小学生的密码学
    2. 汉字的秘密
    3. babycrypto
    4. Backdoor
  2. Misc
    1. 签到
    2. Pokémon
    3. 问卷调查
    4. code obfuscation
    5. Harley Quinn
  3. Reverse
    1. Check_1n
  4. Web
    1. CheckIN
    2. cve版签到

Crypto

小学生的密码学

最基础仿射加密

1
2
3
4
from Crypto.Util.number import inverse
from base64 import *
flag = ''.join(chr(((ord(i)-ord('a') - 6))*inverse(11,26)%26+ord('a')) for i in 'welcylk')
print('flag{'+b64encode(flag)+'}')

汉字的秘密

当铺密码,然后有点脑洞的移位密码

1
2
a=[69,74,62,67,118,83,72,77,86,55,71,57,82,57,64,63,51,107]
flag=''.join(chr(a[i]+(ord('f')-ord('e'))+i) for i in range(len(a)))

babycrypto

已知p高位,coppersmith,现成的exp一把梭

1
2
3
4
5
6
7
8
9
10
n = 
p =
p_new = (p>>128)<<128
pbits = 1024
kbits = 128
pbar = p_new & (2^pbits-2^kbits)
PR.<x> = PolynomialRing(Zmod(n))
f = x + pbar
x0 = f.small_roots(X=2^kbits, beta=0.4)[0] # find root < 2^kbits with factor >= n^0.4
p = x0 + pbar

分解了n,之后这一题就结束了

Backdoor

p=k *M + (65537 ** a %M);ROCA, 是一个CVE,github上也有现成轮子

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#p,q=k*M+(65537**a %M)

# Hardcoded parameters for efficiency
# Found using params.py
param = \
{
512: {
"n": 39,
"a_max": 62,
"k_max": 37,
"M": 0x924cba6ae99dfa084537facc54948df0c23da044d8cabe0edd75bc6,
"M_prime": 0x1b3e6c9433a7735fa5fc479ffe4027e13bea,
"m": 5,
"t": 6,
"c_a": 0x80000
},
1024: {
"n": 71,
"a_max": 134,
"k_max": 37,
"M": 0x7923ba25d1263232812ac930e9683ac0b02180c32bae1d77aa950c4a18a4e660db8cc90384a394940593408f192de1a05e1b61673ac499416088382,
"M_prime": 0x24683144f41188c2b1d6a217f81f12888e4e6513c43f3f60e72af8bd9728807483425d1e,
"m": 4,
"t": 5,
"c_a": 0x40000000
},
2048: {
"n": 126,
"a_max": 434,
"k_max": 53,
"M": 0x7cda79f57f60a9b65478052f383ad7dadb714b4f4ac069997c7ff23d34d075fca08fdf20f95fbc5f0a981d65c3a3ee7ff74d769da52e948d6b0270dd736ef61fa99a54f80fb22091b055885dc22b9f17562778dfb2aeac87f51de339f71731d207c0af3244d35129feba028a48402247f4ba1d2b6d0755baff6,
"M_prime": 0x16928dc3e47b44daf289a60e80e1fc6bd7648d7ef60d1890f3e0a9455efe0abdb7a748131413cebd2e36a76a355c1b664be462e115ac330f9c13344f8f3d1034a02c23396e6,
"m": 7,
"t": 8,
"c_a": 0x400000000
}
}

# https://github.com/mimoo/RSA-and-LLL-attacks/blob/master/coppersmith.sage
def coppersmith_howgrave_univariate(pol, N, beta, mm, tt, XX):
"""
Coppersmith revisited by Howgrave-Graham

finds a solution if:
* b|N, b >= N^beta , 0 < beta <= 1
* |x| < XX
"""
#
# init
#
dd = pol.degree()
nn = dd * mm + tt

#
# checks
#
if not 0 < beta <= 1 :
raise ValueError("beta should belongs in (0, 1]")

if not pol.is_monic():
raise ArithmeticError("Polynomial must be monic.")


#
# Coppersmith revisited algo for univariate
#

# change ring of pol and x
polZ = pol.change_ring(ZZ)
x = polZ.parent().gen()

# compute polynomials
gg = []
for ii in range(mm):
for jj in range(dd):
gg.append((x * XX)**jj * N**(mm - ii) * polZ(x * XX)**ii)
for ii in range(tt):
gg.append((x * XX)**ii * polZ(x * XX)**mm)

# construct lattice B
BB = Matrix(ZZ, nn)

for ii in range(nn):
for jj in range(ii+1):
BB[ii, jj] = gg[ii][jj]

# LLL
BB = BB.LLL(early_red=True, use_siegel=True)

# transform shortest vector in polynomial
new_pol = 0
for ii in range(nn):
new_pol += x**ii * BB[0, ii] / XX**ii

# factor polynomial
potential_roots = new_pol.roots()

return [i[0] for i in potential_roots]

# Top level of the attack, feeds the queue for the workers
def roca(N):

# Key is not always of perfect size, infer from size
keylength = int(log(N, 2))
if keylength < 1000 :
keylength = 512
elif keylength < 2000 :
keylength = 1024
elif keylength < 4000 :
keylength = 2048
else:
keylength = 4096

# bruteforce
M_prime = param[keylength]['M_prime']
c_prime = discrete_log(N, Mod(65537, M_prime))
ord_prime = Zmod(M_prime)(65537).multiplicative_order()
top = (c_prime + ord_prime)/2
beta = 0.5
mm = param[keylength]['m']
tt = param[keylength]['t']

XX = int((2*pow(N, beta)) / M_prime)

# Bruteforce until p, q are found
a_prime = floor(c_prime/2)
while a_prime < top:

# Construct polynomial
m_inv = int(inverse_mod(M_prime, N))
k_tmp = int(pow(65537, a_prime, M_prime))
known_part_pol = int(k_tmp * m_inv)
F = PolynomialRing(Zmod(N), implementation='NTL', names=('x',))
(x,) = F._first_ngens(1)
pol = x + known_part_pol

# Get roots of polynomial using coppersmith
roots = coppersmith_howgrave_univariate(pol, N, beta, mm, tt, XX)

# Check if roots are p, q
for root in roots:
factor1 = k_tmp + abs(root) * M_prime
if mod(N, factor1) == 0:
factor2 = N // factor1
return int(factor1), int(factor2)
a_prime += 1


# Roca
p = 135879036921529661794648581653002330298301044224526679653380767028908108252308273197382392628515754461497140112085352276569074111872088188367336757057332590938346879044292991775026289443754785127606230777989486075849384095736865778026395017314284500188674246388734465652666728075877428904646726042443084490733
q = 136030166899916836494910593158841550636266310029556929683174827580476574762487106877006810987126725903225945843864212303796002840361299997548544768590518964089753416844749381816714973552330950849352052797513575852750175731227705787558580111648617297716840633123746097117675990517245812564173658065172087693179
#N = p*q
N=15518961041625074876182404585394098781487141059285455927024321276783831122168745076359780343078011216480587575072479784829258678691739
print ("[+] Factoring %i" % N)

factor1, factor2 = roca(N)

print ("[+] Found factors of N:")
print ("[+] p =" , factor1)
print ("[+] q =" , factor2)

分解n了,这一题结束了。

Misc

签到

进bilibili直播间复制

Pokémon

走到103,flag画在地板上了

问卷调查

pass

code obfuscation

首先用ps调好

然后因为这些空隙,直接扫可能是扫不出来的,这边推荐用支付宝扫码,然后扫的时候抖动你的手机,让画面模糊,把空隙给抖没了就能扫出来base(gkctf)

然后这张图下面有一个rar,经过测试密码是base58(gkctf),解密后是给了一串js代码,网站js解密后地得到

1
2
3
4
5
6
7
8
for n in a b c d e f g h i j k l m n o p q r s t u v w x y z do eval An = "n"
done
for n in A B C D E F G H I J K L M N O P Q R S T U V W X Y Z do eval An = "n"
done
num = 0
for n in a b c d e f g h i j do eval Bn = "n"
num =
$((num + 1)) done alert("Bk=' ';Bm='"';Bn='#';Bs=' (';Bt=')';By='.';Cb=';';Cc=' < ';Ce=' > ';Cl='_';Cn='{';Cp='}';Da='0 ';Db='1 ';Dc='2 ';Dd='3 ';De='4 ';Df=5 ';Dg='6 ';Dh='7 ';Di='8 ';Dj='9 ';")

字符替换,结合

得到

1
2
3
4
5
#include <stdio.h>
int main(){
print("w3lc0me_4o_9kct5");
retrun 0;
}

Harley Quinn

首先用AU把音频切掉,得到最后的电话音,然后用dtmf2num得到那一串数字

然后9键键盘加密得到ctfisfun,再用hint给的工具解密哈丽奎因那张图,得到flag.txt

Reverse

Check_1n

ida打开,搜索解密失败找到密码HelloWorld,然后开机,flag里头说让玩大砖块(真难),不过死了直接给flag,(还好)

Web

CheckIN

直接传一句话(base64encode),蚁剑连上,然后功能被禁用完了,

putenv还在,

直接LD_PRELOAD绕disablie_fuc

system没法输出flag,改一改hack.c,直接重定向到文件里就好了。

最后再在一句话那里include一下我们的hack.php就好

cve版签到

安恒月赛也有,get_header 的trick,直接日内网,url=http://127.0.0.1%00.ctfhub.com

tips说host以123结尾

payload:url=http://127.0.0.123%00.ctfhub.com


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可联系QQ 643713081,也可以邮件至 643713081@qq.com

文章标题:2020 GKCTF

文章字数:1.2k

本文作者:Van1sh

发布时间:2020-05-24, 17:05:00

最后更新:2020-06-02, 22:02:14

原始链接:http://jayxv.github.io/2020/05/24/2020GKCTF/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏