0%

WriteUp-第六届安洵杯网络安全挑战赛-010101

赛事名称

i-SOON_CTF_2023
第六届安洵杯网络安全挑战赛

赛事描述

https://dce.i-soon.net/#/examineDetails

赛事网址

https://dce.i-soon.net/#/examineDetails

010101

题目

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
# -*- coding:utf-8 -*-
import os
import random
import string
import hashlib
import socketserver
from Crypto.Util.number import isPrime, long_to_bytes, getStrongPrime, bytes_to_long

flag = b"D0g3{******************************************}"

class MyServer(socketserver.BaseRequestHandler):
def proof(self):
random.seed(os.urandom(8))
random_str = ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(20)])
str_sha256 = hashlib.sha256(random_str.encode()).hexdigest()
self.request.sendall(('SHA256(XXXX + %s):%s\n' % (random_str[4:], str_sha256)).encode())
self.request.sendall('Give Me XXXX:\n'.encode())
XXXX = self.request.recv(2048).strip()

if hashlib.sha256((XXXX + random_str[4:].encode())).hexdigest() != str_sha256:
return False

return True

def getPQN(self):
while True:
p = getStrongPrime(2048)
q = getStrongPrime(2048)
n = p * q
if p.bit_length() == 2048 and q.bit_length() == 2048 and n.bit_length() == 4096:
return p, q, n

def encrypt(self):
p, q, n = self.getPQN()
m = bytes_to_long(flag)
e = 0x10001
c = pow(m, e, n)
p = bin(p)[2:]
p1 = list(p[:1024])
p2 = list(p[1024:])
p1[random.choice([i for i, c in enumerate(p1) if c == '1'])] = '0'
p2[random.choice([i for i, c in enumerate(p1) if c == '0'])] = '1'
return n, ''.join(p1) + ''.join(p2), c

def handle(self):
if not self.proof():
self.request.sendall(b'Error Hash!')
return
n, p, c = self.encrypt()
self.request.sendall('Press 1 to get ciphertext\n'.encode())
number = self.request.recv(512).strip().decode()
if number == '1':
self.request.sendall((str(n) + '\n').encode())
self.request.sendall((str(p) + '\n').encode())
self.request.sendall((str(c) + '\n').encode())
else:
self.request.sendall('Incorrect input!\n'.encode())
return


class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass

if __name__ == '__main__':
sever = socketserver.ThreadingTCPServer(('0.0.0.0', 10001), MyServer)
ThreadedTCPServer.allow_reuse_address = True
ThreadedTCPServer.allow_reuse_port = True
sever.serve_forever()

考点

  • crypto
  • SHA256
  • RSA

WriteUp

  • 分析代码逻辑:
    • proof
      • 随机生成一个字符串random_str
      • 计算字符串的哈希值str_sha256
      • 给出random_str[4:]str_sha256,让用户计算random_str[:4]
      • 如果用户给定的random_str[:4]random_str[4:]的哈希值相同,则验证通过
    • getPQN
      • 随机生成两个大素数pq,满足以下要求:p.bit_length() == 2048 and q.bit_length() == 2048 and (p*q).bit_length() == 4096
      • return p, q, n
    • encrypt
      • 通过getPQN生成pqn
      • 计算密文c = pow(m, e, n)
      • p进行变换:前1024位随机挑选一个1变成0,后1024位随机挑选一位变成1,得到fake_p
      • return n, fake_p, c
    • handle
      • 通过proof函数判断用户输入的XXXXrandom_str[4:]的哈希值是否相同
      • 相同的话,通过encrypt函数对flag进行加密,返回n, fake_p, c
  • 解题步骤:
    • nc连入服务器,获取random_str[4:]str_sha256
    • 通过getXXXX.py爆破random_str[:4],并将结果发送给服务器,获得n,fake_p,c
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      import hashlib
      import itertools
      from string import digits, ascii_letters, punctuation
      alpha_bet=digits+ascii_letters+punctuation
      strlist = itertools.product(alpha_bet, repeat=4)

      sha256="5ccd4cda1dc33d20a072cddf2cf921c865b274da912edb7ac3f157404c3fe4e3"
      tail="uLBLoFfDko5h5uA9"

      xxxx=''

      for i in strlist:
      data=i[0]+i[1]+i[2]+i[3]
      data_sha=hashlib.sha256((data+str(tail)).encode()).hexdigest()
      if(data_sha==str(sha256)):
      xxxx=data
      break

      print(xxxx)
    • 基于encrypt函数,编写decrypt.py脚本,破解p,解密得到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
      # -*- coding:utf-8 -*-
      import os
      import random
      import string
      import hashlib
      import socketserver
      from Crypto.Util.number import long_to_bytes


      n=909467367699122020071016988650306999295228108976638769699035391871165765547800730173871546690865275123375066230171521311068819816852640125745292539541259006023609504769135551654529045891894185101263480691408339167146959806826342796151867522273018753414683125578415962666829770904166690498846087399777025030862122796483743577214854248422262763202974262015130017066825754008160259189414818697567284326444565265735329976239935592453543076795651573576794776003238789860869381589213987112412732442793109900427324085928201408085720252507826509949584097216821241278182597257299885172782505117521436358744947983811939554943145617958259867137670519879871430621545154465019553001205911580515698810275961361004704605451591223643427530911392689056988136336912424730785373902092658701108834786609423741166892942322112744091173801215997979197781791157780385712374075574951133435122784372704793303399699730638707098947178219189508884581830248871075957102690166621382729933821529281361101591281902812061185346676660877303782149165897420682724683205662866974137418732285231256810541807361468193401184858075051706155601176563558866315093106261534227649361408522136583934234512184301782185760219449297423394506961283209453334215176208906015567865682661
      fake_p='11100000100010111111010011100000110011001000001001111011001010011100001101000000001010000010101000011110000001000000010111000110101000101101011101111010001110110000000001101110100011101001100011101010110011111001001011101000110100011011101011110110001111100110101000010110110001001110001101111111100001101101110010011110100101110001101101101011011100111110101111000111000010011101001000011110000101111000010110000001100001111001011100011001110110110110000110000110111010111101110111100100111101111001100110010000000110011011111011111100000010010111111000010110010000110000111100011001111010101000111110011110001010101010010100001010100110111111101010010000000100101011001011100100111111001000111011111010101011111111010011101110111111110011101111001000011011000000000011100101101000001101110101100001110000110101011001000010110110000110110001101010110001100010110010110000000001110001101111011100011011110101010010011010100011010100010101100000010111100000101100010110000100001001101001001001111011011000101010001011010001100101110111111100111111001011100001100001011101011000000001101111011011001001100100111101100100111100100000000111110100011100011110001101100000100000101001101100010100000110111010001111011010110100101010101100000000001111001111010100011000010010010001010011100111100001101100111100010101111101011001100011111011000011101111110101110010100011000111010100000000111110111001111110100011100100111101001101011010110001100000101010001111000110100110101110001011100010011100111110111111010001110111000001000010111110100000110110110010111101101111010010110100011110110011011010010000000000101110101001001111100110111111001000000101101011111011110110111111001101001111011100110101101010101100000010100111101110110101101010100110011010011101101000010011101011001011110001011110011000101110000100000110100011101001100101110000001110100111010110110000101000011011010011100101101011010010010100110011011100001110001000000111101111000001010110111111010110101111000100111111111111101111001110101101111111101111011011101111111000100000110111'
      c=694500789519839583373480124753870609796624184368847740052659890684952282469412685843793893336588959688292535565388961237054382061607809034620598317779687541764120119851622500197513641485700221545824097256986828990721130988465432457926804939623885349284941907683524562179105951076405178191916974212394857571647273209891325684133975190612454243345915122493599006273649156588911638621279271660577286076492174133379924878816759449537816258877983535822071467357826352013991371273144147958254806851665648862909470014188217381547444474766611515043375595448634817257201321537710925281810846187991415244304258902323932755496219900194257710795367213151869032406828586461628113793387618900293473170817978068346842472541499877290335671510770413540109295368927586613167172537907784632075379648806105818669008103026164730513033786875076959900405998112656279798642754984874654321483935047414576483030634418889375971016788408747123075626184286939742532706576269950026208168650867226593584227608482405783125152467929531339747039920420671850985997912834217484356948372454631601487864570640693252550030654681522447089126289751692094672022733644147229926742656125552935762042624836326359406490008032106080800094693108856102201450516929541344003829402493
      e = 0x10001


      fake_p1=list(fake_p[:1024])
      fake_p2=list(fake_p[1024:])
      p=0
      q=0
      for i, x in enumerate(fake_p1):
      if x == '0':
      p1=fake_p1[:i]+['1']+fake_p1[i+1:]
      p2=fake_p2
      p=int(''.join(p1)+''.join(p2),2)
      if n%p==0:
      q=n//p
      if p.bit_length() == 2048 and q.bit_length() == 2048 and n.bit_length() == 4096:
      print("Get p q!\n")
      break
      else:
      print("bad format1!")
      else:
      for j,y in enumerate(fake_p2):
      if y== '1':
      p2=fake_p2[:j]+['0']+fake_p2[j+1:]
      p=int(''.join(p1)+''.join(p2),2)
      if n%p==0:
      q=n//p
      if p.bit_length() == 2048 and q.bit_length() == 2048 and n.bit_length() == 4096:
      print("Get p q!\n")
      break
      else:
      print("bad format2!")
      print(p)
      print(q)
      phi_n = (p - 1) * (q - 1)
      print("phi_n:")
      print(phi_n)
      d = pow(e, -1, phi_n)
      m = pow(c, d, n)
      print(long_to_bytes(m))

FLAG

1
D0g3{sYuWzkFk12A1gcWxG9pymFcjJL7CqN4Cq8PAIACObJ}

欢迎关注我的其它发布渠道