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

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

首次发表于个人网站:https://yumlii33.github.io/

赛事名称

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

赛事描述

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

赛事网址

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

010101

题目

# -*- 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

      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

      # -*- 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

D0g3{sYuWzkFk12A1gcWxG9pymFcjJL7CqN4Cq8PAIACObJ}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值