crypto_ringringring

给了个nc连接,连上后给出了一个str拼接几个字符再md5后的前五位:

数据量较小于是可以爆破:

1
2
3
4
5
6
def md5Col(one, two):
for i in range(1048576):
text = hex(i).replace('0x', '')
if md5(text + one)[0:5] == two:
print(md5(text + one))
return text

通过后又要我们给出一个方程的100个解:

一开始用z3直接暴力求解,结果可想而知是非常慢的!于是这里就有一个小技巧了:我们处理一下方程,abcd四个变量等价,而且经过多次试验可知变量的范围是大于零的整数,于是我么假设abcd都相等,于是化简就是这样:

简化方程

于是将a从1到100循环,很快就有对应的e值从而获得100个解了:

然后就先让他跑,过一会儿就出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
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
# -*- coding: utf-8 -*-

import sys
import hashlib
from z3 import *
import socket
import time

otherIP = '192.168.39.182'
otherPort = '2378'

solves = ["", "[e = 2]","[e = 8]","[e = 18]","[e = 32]","[e = 50]","[e = 72]","[e = 98]","[e = 128]","[e = 162]","[e = 200]","[e = 242]","[e = 288]","[e = 338]","[e = 392]","[e = 450]","[e = 512]","[e = 578]","[e = 648]","[e = 722]","[e = 800]","[e = 882]","[e = 968]","[e = 1058]","[e = 1152]","[e = 1250]","[e = 1352]","[e = 1458]","[e = 1568]","[e = 1682]","[e = 1800]","[e = 1922]","[e = 2048]","[e = 2178]","[e = 2312]","[e = 2450]","[e = 2592]","[e = 2738]","[e = 2888]","[e = 3042]","[e = 3200]","[e = 3362]","[e = 3528]","[e = 3698]","[e = 3872]","[e = 4050]","[e = 4232]","[e = 4418]","[e = 4608]","[e = 4802]","[e = 5000]","[e = 5202]","[e = 5408]","[e = 5618]","[e = 5832]","[e = 6050]","[e = 6272]","[e = 6498]","[e = 6728]","[e = 6962]","[e = 7200]","[e = 7442]","[e = 7688]","[e = 7938]","[e = 8192]","[e = 8450]","[e = 8712]","[e = 8978]","[e = 9248]","[e = 9522]","[e = 9800]","[e = 10082]","[e = 10368]","[e = 10658]","[e = 10952]","[e = 11250]","[e = 11552]","[e = 11858]","[e = 12168]","[e = 12482]","[e = 12800]","[e = 13122]","[e = 13448]","[e = 13778]","[e = 14112]","[e = 14450]","[e = 14792]","[e = 15138]","[e = 15488]","[e = 15842]","[e = 16200]","[e = 16562]","[e = 16928]","[e = 17298]","[e = 17672]","[e = 18050]","[e = 18432]","[e = 18818]","[e = 19208]","[e = 19602]","[e = 20000]"]

def md5Col(one, two):
for i in range(1048576):
text = hex(i).replace('0x', '')
if md5(text + one)[0:5] == two:
print(md5(text + one))
return text

def md5(text):
content = text.encode('ansi')
md5hash = hashlib.md5(content)
md5 = md5hash.hexdigest()
return md5

def col(n):
a = Int('a')
b = Int('b')
c = Int('c')
d = Int('d')
e = Int('e')
# solve(a == n, b > 0, c > 0, d > 0, e > 0, a**4 + b**4 + c**4 + d**4 == e**2)
solve(2*n**2 == e)

if __name__ == '__main__':
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect((otherIP, int(otherPort))) #建立连接

mess = client.recv(1024).decode('utf-8') #接受信息
print(mess) #接受信息
one = mess[36:40]
two = mess[50:55]
print(one, two)
print(client.recv(1024).decode('utf-8')) #接受信息

firstAnswer = md5Col(one, two) #解出第一题
if firstAnswer == None:
exit()
print(firstAnswer)
client.send(firstAnswer.encode('utf-8')) #发送第一题

print(client.recv(1024).decode('utf-8')) #接受信息
# print(client.recv(1024).decode('utf-8')) #接受信息

for i in range(1, len(solves)):
A = B = C = D = str(i)
E = solves[i].replace('[e = ', '').replace(']', '')
print('show : ' + A, B, C, D, E)

print(client.recv(1024).decode('utf-8')) #接受信息
time.sleep(0.2)
client.send(A.encode('utf-8')) #发送
print(A)

print(client.recv(1024).decode('utf-8')) #接受信息
time.sleep(0.2)
client.send(B.encode('utf-8')) #发送
print(B)

print(client.recv(1024).decode('utf-8')) #接受信息
time.sleep(0.2)
client.send(C.encode('utf-8')) #发送
print(C)

print(client.recv(1024).decode('utf-8')) #接受信息
time.sleep(0.2)
client.send(D.encode('utf-8')) #发送
print(D)

print(client.recv(1024).decode('utf-8')) #接受信息
time.sleep(0.2)
client.send(E.encode('utf-8')) #发送
print(E)

print(client.recv(1024).decode('utf-8')) #接受信息
print(client.recv(1024).decode('utf-8')) #接受信息
print(client.recv(1024).decode('utf-8')) #接受信息
print(client.recv(1024).decode('utf-8')) #接受信息




crypto_bigrsa

打开之后很简单,就是两层加密,用yafu分解失败。经过高人指点,只有公因数这个可能了

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
import gmpy2
import binascii
import libnum

n1 = gmpy2.mpz(103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061)

n2 = gmpy2.mpz(115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073)

e = gmpy2.mpz(65537)

c = gmpy2.mpz(60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264)

#iteration
def gcd(a,b):
if b==0:
return a
else:
return gcd(b, remainder(a, b))

#此方法仅仅书用于a和b都为正数
def gcd_1(a,b):
while(b>0):
rem = remainder(a,b)
a = b
b = rem
return a

def remainder(x,y):
return x%y

p = gcd(n1,n2) # 10210039189276167395636779557271057346691950991057423589319031237857569595284598319093522326723650646963251941930167018746859556383067696079622198265424441

# q1 = n1 / p # 10169921435575123642561867469669552661717864247752251361375671837367086221354750692635829007786009042729357644276462913457660789233674358081650339142863821
# q2 = n2 / p # 11300955505231233842374743324817494386700809291852528704864397779486924493760947925710590633254027339824598181322986060728301639209174112581120081509548753
q1 = gmpy2.mpz(10169921435575123642561867469669552661717864247752251361375671837367086221354750692635829007786009042729357644276462913457660789233674358081650339142863821)
q2 = gmpy2.mpz(11300955505231233842374743324817494386700809291852528704864397779486924493760947925710590633254027339824598181322986060728301639209174112581120081509548753)

def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m

d2 = modinv(e,(p-1)*(q2-1))
d1 = modinv(e,(p-1)*(q1-1))

m2 = pow(c,d2,n2)
m1 = pow(m2,d1,n1)

print(hex(m1))
print(libnum.n2s(m1))

SangFor{qSccmm1WrgvIg2Uq_cZhmqNfEGTz2GV8}

misc_Misc520

1
2
有一天,zip爱上了pcap,zip为了能与pcap创造更多机会,不断地将自己的能力表现出来。可是,LSBSteg却突然杀了出来,将pcap吞并于png中,不放出来
。zip看到了png,多喝热水少做梦。zip异常的愤怒,不断地用自己的能力去报复png,不让png逃走。至今,zip仍未释怀。

打开之后是一个嵌套了520层的压缩包。。。

这里的story每个都是上面那段小故事,我就没在意,为我最后一步没解出flag埋下了伏笔。。。

解到最后一个压缩包,里面一个story和一张六百多kb的png:

根据题目描述,知道png里有LSB隐写,藏了pcap流量。于是到stegsolve里查看:

能发现三个通道都存在隐写,于是到数据提取内查看发现压缩包文件头:

提取出来,一个zip,打开有个加密的流量包,估计这就是zip爱上的pcap了:

没有其他的提示了,于是先用爆破,密码12345:

打开后发现全是usb流量,查看设备描述请求和应答,可知是鼠标流量:

关于CTF常见流量分析:

CTF流量分析常见题型(二)-USB流量 | qwzf

使用kali linux中的tshark 命令把cap data提取出来,并去除空行

1
2
tshark -r usb2.pcap -T fields -e usb.capdata > usbdata.txt
tshark -r usb2.pcap -T fields -e usb.capdata | sed '/^\s*$/d' > usbdata.txt #提取并去除空行

得到原始数据:

再用脚本处理并跑出用鼠标左键和右键隐藏的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# coding : utf-8

f = open('usbdata.txt','r')
fi = open('out.txt','w')
while 1:
a = f.readline().strip()
if a:
if len(a)==8: # 鼠标流量的话len改为8
out=''
for i in range(0,len(a),2):
if i+2 != len(a):
out+=a[i]+a[i+1]+":"
else:
out+=a[i]+a[i+1]
fi.write(out)
fi.write('\n')
else:
break

fi.close()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
nums = []
keys = open('out.txt', 'r')
f = open('xy.txt', 'w')
posx = 0
posy = 0
for line in keys:
if len(line) != 12:
continue
x = int(line[3:5], 16)
y = int(line[6:8], 16)
if x > 127:
x -= 256
if y > 127:
y -= 256
posx += x
posy += y
btn_flag = int(line[0:2], 16) # 1 for left , 2 for right , 0 for nothing
if btn_flag == 1 or btn_flag == 2: # 1 代表左键
f.write(str(posx))
f.write(' ')
f.write(str(posy))
f.write('\n')

f.close()

得到过滤后的坐标文件:

然后我们用gnuplot画出鼠标轨迹:

比赛到这一步怎么也做不出了。赛后看题解,原来那520个压缩包里有一个不是和上面一样的故事!是剩下的flag!坑啊

解压压缩包,并且比较每一个story的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
import zipfile import os
with open('./Story1/story', 'r', encoding='UTF-8') as f: txt = f.read()
f.close()
for i in range(520, -1, -1):
zfile = zipfile.ZipFile(str(i)+'.zip', 'r')
for filename in zfile.namelist(): data = zfile.read(filename) file = open(filename, 'w+b') file.write(data)
file.close() zfile.close()
os.remove(str(i)+'.zip')
if os.path.exists('story'):
with open('story', 'r', encoding='UTF-8') as story_f: story = story_f.read()
if story != txt: print(story)
story_f.close()
os.remove('story')

得到第一部分flag和一张图片(flag.png)72, 89, 75, 88, 128, 93, 58, 116, 76, 121, 120, 63, 108,

将两串数字合并,得到:[72, 89, 75, 88, 128, 93, 58, 116, 76, 121, 120, 63, 108, 130, 63, 111, 94, 51, 134, 119, 146]

通过提示,头是GWHT,可以看到前四位的ASCII码分别与GWHT相差1,2,3,4,编写脚本得到 flag

1
2
3
4
5
6
7
8
i = 1
flag_encode = [72, 89, 75, 88, 128, 93, 58, 116, 76, 121, 120, 63,
108, 130, 63, 111, 94, 51, 134, 119, 146]
flag = ''
for num in flag_encode:
flag += chr(num-i)
i += 1
print(flag)
2021-09-20
Contents

⬆︎TOP