0%

VNCTF2022公开赛WP

VNCTF2022公开赛 Writeup

1. 个人信息

名称:0HB

排名:73

2. 解题情况

一道Crypto,总五道

一道Web, 总五道

两道Misc,总六道

其中Crypto方向第27名

答题情况

3. 具体WP

MISC

题目一名称:仔细找找

步骤一

原图肉眼可得:VN???{34a?@w}

盲猜vnctf{…}

步骤二

改了下颜色,对着a之后、**@之前**看点是否连成线来确定“被遮挡住”的形状为E

绿色

vnctf{34aE@w}

题目二名称:问卷

步骤一

填完问卷即解。


Web

题目一名称:GameV4.0

步骤一

启动靶机,转到页面,审查元素

web

步骤二

  • Base64解码
  • Url解码

CyberChef解码


Crypto

题目一名称:ezmath

步骤一

启动靶机,下载server.py文件,连接(macOS)

1
nc node4.buuoj.cn 25196

步骤二

1
2
[+] sha256(XXXX+k7h8CNcM3jCpuivQ) == 7dbe1e6a592f589a44508d3cb5d72e87a2f653714109dd16d1d94ea461c59a9c
[+] Plz Tell Me XXXX :

连接后,可见四位的sha256爆破

上Python,写!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import hashlib
import sys

def decry(data):
s = hashlib.sha256() # Get the hash algorithm.
s.update(data.encode()) # Hash the data.
b = s.hexdigest() # Get he hash value.
return b


list1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "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", "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"]
for a in list1:
for b in list1:
for c in list1:
for d in list1:
flag = "{0}{1}{2}{3}k7h8CNcM3jCpuivQ".format(a, b, c, d)
flag_sha = decry(flag)
flag1 = flag[0:4]
print(flag1)
if str(flag_sha) == '7dbe1e6a592f589a44508d3cb5d72e87a2f653714109dd16d1d94ea461c59a9c':
print('恭喜!')
sys.exit()

得到:UtFn,输入之。

步骤三

1
plz give me the 3080090231th (n) that satisfying (2^n-1) % 15 == 0   (the 1st 2^n-1 is 15):

(2^n -1 )% 15 == 0 ,即:

2的n次方-1 后除15 得 = 0,求满足该条件的第3080090231个n

  • 推一遍

    第一个除15得0的正整数是15,此时2^n -1=15,即:第一个n=4

    第二个除15得0的正整数是30,此时n解不出正整数

    第三个除15得0的正整数是45,此时n解不出正整数

    第四个除15得0的正整数是60,此时n解不出正整数

    ….

    第十七个除15得0的正整数是255,此时2^n -1=255,即:第二个n=8

    这样,就知道了什么叫做求第X个的解n

  • 计算机爆破

    思路却不同以上,以计算机的思维,该如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    target = 3080090231
    num = 0 # 第num个n
    n = 1

    while num != target:
    n += 1
    if (2 ** n - 1) % 15 == 0:
    num += 1
    print("num",num)
    print("n", n)

    print("第 {0} 个的解n为: {1}".format(num, n))

    运行到第百万位个n,用了三四分钟,现在十位数的要求,显然不可能直接爆破

  • 观察数据,找规律

    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
    num 0
    n 2
    num 0
    n 3
    num 1
    n 4
    num 1
    n 5
    num 1
    n 6
    num 1
    n 7
    num 2
    n 8
    num 2
    n 9
    num 2
    n 10
    num 2
    n 11
    num 3
    n 12
    num 3
    n 13
    num 3
    n 14
    num 3
    n 15
    num 4
    n 16
    num 4
    n 17
    num 4
    n 18
    num 4
    n 19
    num 5
    n 20

    可见:

    第1个n:4

    第2个n:8

    第3个n:12

    第X个n:4*X

  • 输入12320360924(4*3080090231)

步骤四

1
2
You are so smart!
plz give me the 3423213917th (n) that satisfying (2^n-1) % 15 == 0 (the 1st 2^n-1 is 15):
  • 看server.py代码

    可见,并不是解出一个来就给flag,我们得知道判定条件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    for i in range(777):
    times = getPrime(32)
    self.send(b'plz give me the ' + str(times).encode() + b'th (n) that satisfying (2^n-1) % 15 == 0:')
    n = int(self.recv())
    a , ret = check(times,n)
    if a == True:
    self.send(ret.encode())
    counts += 1
    else:
    self.send(ret.encode())
    if counts == 777:
    self.send(b'You get flag!')
    self.send(flag)
    else:
    self.send(b'something wrong?')
    self.request.close()

    得知:要解此问777次可得flag

  • python 实现netcat功能

    学习后,依次写代码

    • 先是sha256爆破

      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
      import socket

      if __name__ == '__main__':
      HOST = 'node4.buuoj.cn'
      PORT = 28158

      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      s.connect((HOST, PORT))
      data = ''.join(str(s.recv(1024)).strip("\n"))
      sha_key = data[18:34] # like: dygRhRVGRA146H43
      sha_data = data[39:103] # like: d06a5396ad875acdf0796cc5b0c083170e38728847085cfd99dadaeda71a3d17
      import hashlib
      import re


      # 第一关 sha256
      def decry(data):
      s = hashlib.sha256() # Get the hash algorithm.
      s.update(data.encode()) # Hash the data.
      b = s.hexdigest() # Get he hash value.
      return b


      list1 = ["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", "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", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ]


      def yi():
      for a in list1:
      for b in list1:
      for c in list1:
      for d in list1:
      flag = "{0}{1}{2}{3}{4}".format(a, b, c, d, sha_key)
      flag_sha = decry(flag)
      flag1 = flag[0:4]
      print(flag1)
      if str(flag_sha) == str(sha_data):
      print('恭喜!')
      return str(flag1)

      s.send(yi().encode())
    • 后是没夸你真睿智🤔的那次求n

      1
      2
      3
      4
      5
      6
      7
      8
      9
      s_ = s.recv(1024)

      # 进入第二关
      # b'plz give me the 2832346159th (n) that satisfying (2^n-1) % 15 == 0 (the 1st 2^n-1 is 15):\n'

      target = str(s_)
      target = target.split('th')
      target = target[1][2:]
      s.send(str(int(target)*4).encode())
    • 再是剩下776次

      • 这里发现接受一次(s_ = s.recv(1024)),有时只返回You are so smart,不给题,导致报错。

      对此,写if判断,此时再接受一次(s_ = s.recv(1024)),得到题目

      1
      2
      3
      s_ = s.recv(1024)
      if str(s_) == r"b'You are so smart.\n'":
      s_ = s.recv(1024)
      • 循环接受题目,发送解答,利用正则表达式捕捉题目要求num
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      import re  
      for i in range(778):
      s_ = s.recv(1024)
      if str(s_) == r"b'You are so smart.\n'":
      s_ = s.recv(1024)
      s_ = str(s_)
      print(s_)
      reg = r'\d\d\d\d\d\d\d\d\d\d'
      target = re.search(reg, s_)
      target = target.group()
      s.send(str(int(target) * 4).encode())

      这里循环给多一些,报错了自动停止(多多益善,反倒是少了会功亏一篑

      :(

总代码

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
import socket
import hashlib
import re

if __name__ == '__main__':
HOST = 'node4.buuoj.cn'
PORT = 28158

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
data = ''.join(str(s.recv(1024)).strip("\n"))
sha_key = data[18:34] # like: dygRhRVGRA146H43
sha_data = data[39:103] # like: d06a5396ad875acdf0796cc5b0c083170e38728847085cfd99dadaeda71a3d17


# 第一关 sha256
def decry(data):
s = hashlib.sha256() # Get the hash algorithm.
s.update(data.encode()) # Hash the data.
b = s.hexdigest() # Get he hash value.
return b


list1 = ["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", "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", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ]


def yi():
for a in list1:
for b in list1:
for c in list1:
for d in list1:
flag = "{0}{1}{2}{3}{4}".format(a, b, c, d, sha_key)
flag_sha = decry(flag)
flag1 = flag[0:4]
print(flag1)
if str(flag_sha) == str(sha_data):
print('恭喜!')
return str(flag1)

s.send(yi().encode())
s_ = s.recv(1024)

# 进入第二关
# b'plz give me the 2832346159th (n) that satisfying (2^n-1) % 15 == 0 (the 1st 2^n-1 is 15):\n'

target = str(s_)
target = target.split('th')
target = target[1][2:]
s.send(str(int(target)*4).encode())

for i in range(778):
s_ = s.recv(1024)
if str(s_) == r"b'You are so smart.\n'":
s_ = s.recv(1024)
s_ = str(s_)
print(s_)
reg = r'\d\d\d\d\d\d\d\d\d\d'
target = re.search(reg, s_)
target = target.group()
s.send(str(int(target) * 4).encode())
# b'You are so smart.\nYou get flag!\nflag{4e2fbdd6-1023-408c-816f-08a3725f97e1}\n'
# flag{4e2fbdd6-1023-408c-816f-08a3725f97e1}