安洵杯密码复现

安洵杯密码题目分析

密码1:

task

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()

第一步 ,我们需要连接靶机
与靶机交互即可得到一串hash,爆破前4位使字符串的hash256与题目所给的一致

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

target_hash = "e7d00e85945e40298e71766df1134d7df4c33def9ded64389e541c50e689870e"

for char_1 in range(48, 123): # ASCII码中数字、大写字母和小写字母的范围
for char_2 in range(48, 123):
for char_3 in range(48, 123):
for char_4 in range(48, 123):
if len({char_1, char_2, char_3, char_4}) == 4: # 确保四个字符都是不同的
ascii_chars = (chr(char_1), chr(char_2), chr(char_3), chr(char_4))
combination = "".join(ascii_chars) + 'mw21BZK89qImQVZX' # 在每个组合后添加特定字符串

# 计算哈希值
hash_object = hashlib.sha256()
hash_object.update(combination.encode())
hashed = hash_object.hexdigest()

# 检查是否匹配目标哈希值
if hashed == target_hash:
print("匹配的组合为:", combination)
exit() # 找到匹配的组合后结束程序运行

#匹配的组合为: KsAxmw21BZK89qImQVZX

另一种更快的方法,直接利用pwntools与靶机交互,得到题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from pwn import *
from hashlib import sha256
import string
from pwnlib.util.iters import mbruteforce
import binascii

r = remote("124.71.177.14", 10010)

table = string.ascii_letters + string.digits

def pow():
r.recvuntil("XXXX + ")
suffix = r.recv(16).decode("utf8")
r.recvuntil(":")
cipher = r.recvline().strip().decode("utf8")
proof = mbruteforce(lambda x: sha256((x + suffix).encode()).hexdigest() ==
cipher, table, length=4, method='fixed')
r.sendline(proof)

pow()
r.sendline('1')
r.recvuntil('This is your flag: ')


接下来,靶机会返回一组数据

1
2
3
4
output
n=689148428917048752698561230187435330535844474535660975519663024686005813423116261691596518960359444398659487569281405280516756122565301499107276527019563398561775190548326726650095124347721633102683517354241616731272290842366644969493523095260169026118700872122205961125840074575539913181179624158591316008961999519664445180765805855068357280325140200570721885619207531433799082034359675994945498536733447149520815614429142224067402920944323350406000139261949314945008134993667106166371729994211490216695953544210086909916594288871041686796264966615061234867849533737850978285759970378711342002735127852669911135633280727507197770896643162828873860290236954478934069039880842775659386156914426681646990123375726632782848318765676209660955746904921591374247548244510795028854167024612141080434153599742660712283405861398644681971440490492676518075438358400296468401567303163631533553410643660848819592904185023897183284947919518254876711845553448295870785376932257813856605607299735796578232939819120320722961149946000934150374343672467868456190855696298746763169171976016018534242348938143398691129090031066272454600059389810619648519400690544893179323782655271245976991844056669848133657162015017534126606913505865717577945680934201
p=11000100010010100101011010011010100110111011101111001100001110011000011100001010101001011000011001100100100001111010100011101001001111100111011000010100100110000010011101111010111001001100100000101101011001100000110101101001111011001101110000100000100001100000100110001001010011000111101111101100101101010111011001101111101011001100111000011111000011101100110001101010000110111001100101011101011100111111010101001110101110110010100000000100001111101001110010101000010011011001100011111111100110011000001010000101101010001001001101010110101111101101111001110100101101101011000010111100100010000111101110001001101111101111110010000111101101000000111111011010011011101101000101000100010001101001011111000111000101101001100110011111100101011110011110110110000110100110001111010001001100011011110001110000001000111100101001000001001011110100101010001111110110110001110110001100101001011110010101010100101011110101010101001000000111010001000100111000011000011101011110101001001001011001011110010010010000010110110010000100100110111100110001011101101100010011110000000011001010010010100010110000000000101010111011011100010010001100000100100110101100011111100011110001001011111101001111000000010000110000111011100000001100111010011000011010001001101011100111000010001010010000000010111000110011100100110101010000000101101101100011110110111101010110011101000001100010011001001001101000000010100100100111010011011001101011011110101100000100011000100101001000010100101100100101000111000001100001001110000011000101000000001011100010011010001111011011001011000011111111101001100111000111110100010101011101100110100001010101101011001110000100100011010010001110111001001110000110100010011000010000011000011111101011011001001111010011100001101010110000110000010100100001011100101001011101010111000001100011110010010101010101100011110101111101101010101011100001001101001000101000100100111000010001100010100101100101000111100000001001110111101110110100010100000001001110011101000011100100010111101110010111101101010010001011010011100011111000011000001100011001100011
c=582755493501376550312021063293971269432622857973591275097520241824639113243678154601039738777785910875356099861877799721721629337353531048570147711682149769656300149663334265982311991206401905216350979684516071937023923185938510050693691337873407171757275643036119429129455102869684317978357782902189346531413458627379268090802106996865349905645096514117275113848528530242217188285324909887937524122208178818340097019103831473349905133558912714201852986162525855145162259280450040753185483478933398530730654529154485769469682628353274080092629445953899362883988215175193630488889635324515092313723195910983168425805177795699565396108348821928449320190783128803002754706992512092839782219348149442008758998793607436136085108333190190347733106486023581643835108125870863346801123024469552193808660738495330000657495372570089643330001020748391509387487524136411478620736071866518379044131693794690230740826475529806050936866355127348429602091123271970724772553111459156824158976033596665391059836828836907988254364980925568575831029223091042575366899359078304670344881979433579570857621141077250931877184312810916773443135402247438937358801349822845162460003198622710136542402567604311023354451215661022609583925197654492145458148760392

根据源码分析,他把其中的p做了这样一个操作
p1[random.choice([i for i, c in enumerate(p1) if c == ‘1’)]) = ‘0’: 在 p1 的随机位置找到一个为 ‘1’ 的位,并将其改为 ‘0’。
p2[random.choice([i for i, c in enumerate(p1) if c == ‘0’)]) = ‘1’: 在 p2 的随机位置找到一个为 ‘0’ 的位,并将其改为 ‘1’。
所以我们只需要根据这个漏洞遍历前1024位的0和后1024位的1进行异或操作即可
笔者这边直接构造了一个密码本

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
# -*- coding: utf-8 -*-
"""
Created on Sat Dec 23 14:15:02 2023

@author: lenovo
"""
p= 11000100010010100101011010011010100110111011101111001100001110011000011100001010101001011000011001100100100001111010100011101001001111100111011000010100100110000010011101111010111001001100100000101101011001100000110101101001111011001101110000100000100001100000100110001001010011000111101111101100101101010111011001101111101011001100111000011111000011101100110001101010000110111001100101011101011100111111010101001110101110110010100000000100001111101001110010101000010011011001100011111111100110011000001010000101101010001001001101010110101111101101111001110100101101101011000010111100100010000111101110001001101111101111110010000111101101000000111111011010011011101101000101000100010001101001011111000111000101101001100110011111100101011110011110110110000110100110001111010001001100011011110001110000001000111100101001000001001011110100101010001111110110110001110110001100101001011110010101010100101011110101010101001000000111010001000100111000011000011101011110101001001001011001011110010010010000010110110010000100100110111100110001011101101100010011110000000011001010010010100010110000000000101010111011011100010010001100000100100110101100011111100011110001001011111101001111000000010000110000111011100000001100111010011000011010001001101011100111000010001010010000000010111000110011100100110101010000000101101101100011110110111101010110011101000001100010011001001001101000000010100100100111010011011001101011011110101100000100011000100101001000010100101100100101000111000001100001001110000011000101000000001011100010011010001111011011001011000011111111101001100111000111110100010101011101100110100001010101101011001110000100100011010010001110111001001110000110100010011000010000011000011111101011011001001111010011100001101010110000110000010100100001011100101001011101010111000001100011110010010101010101100011110101111101101010101011100001001101001000101000100100111000010001100010100101100101000111100000001001110111101110110100010100000001001110011101000011100100010111101110010111101101010010001011010011100011111000011000001100011001100011
p1=1100010001001010010101101001101010011011101110111100110000111001100001110000101010100101100001100110010010000111101010001110100100111110011101100001010010011000001001110111101011100100110010000010110101100110000011010110100111101100110111000010000010000110000010011000100101001100011110111110110010110101011101100110111110101100110011100001111100001110110011000110101000011011100110010101110101110011111101010100111010111011001010000000010000111110100111001010100001001101100110001111111110011001100000101000010110101000100100110101011010111110110111100111010010110110101100001011110010001000011110111000100110111110111111001000011110110100000011111101101001101110110100010100010001000110100101111100011100010110100110011001111110010101111001111011011000011010011000111101000100110001101111000111000000100011110010100100000100101111010010101000111111011011000111011000110010100101111001010101010010101111010101010100100000011101000100010011100001100001110101111010100100100101100101111001001001000001011011001000010010011011
p2=1100110001011101101100010011110000000011001010010010100010110000000000101010111011011100010010001100000100100110101100011111100011110001001011111101001111000000010000110000111011100000001100111010011000011010001001101011100111000010001010010000000010111000110011100100110101010000000101101101100011110110111101010110011101000001100010011001001001101000000010100100100111010011011001101011011110101100000100011000100101001000010100101100100101000111000001100001001110000011000101000000001011100010011010001111011011001011000011111111101001100111000111110100010101011101100110100001010101101011001110000100100011010010001110111001001110000110100010011000010000011000011111101011011001001111010011100001101010110000110000010100100001011100101001011101010111000001100011110010010101010101100011110101111101101010101011100001001101001000101000100100111000010001100010100101100101000111100000001001110111101110110100010100000001001110011101000011100100010111101110010111101101010010001011010011100011111000011000001100011001100011

# 初始二进制数
p1 = "1100111110010000110010010100010101101111101111001100100001111001010011011000000000110110100001001110101101011010101001110011100111001110011011110110101000110111100100010111000110111000100011101000001011011011110101010101011110001111000001010111101100101010101001011011101000110011111000101101001010100011010001000110101111101110011011101111101011110010010010000001010000111001001001100101101111100111111111100101001000011010110010011001000110101011000000100110011001011011101101101001110101011100101111011100011100000101100001001000001001111100001000100010000100100000000111010000100111000000100111000100011001011010001010110011001001001111101100100011100000010111001111001011010011111001010000110100110001010101100111111010011000001000011011000101010110010101010000110111101001010101101110110111010001110011101101111111011111000011010111111111011011111110011101010110000111100011111000100011101101001011111000110011111011000111011101101011110001011010001100101000001111100110111110001010001100110000000111111011010100000111"

# 创建文件来保存输出结果
output_file = "listp1.txt"

modified_binaries = []

# 检查每一位,如果为0则改为1
for i in range(len(p1)):
if p1[i] == '0':
modified_p1 = p1[:i] + '1' + p1[i+1:]
modified_binaries.append(modified_p1)

# 将所有修改后的结果写入文件
with open(output_file, "w") as file:
for modified_p1 in modified_binaries:
file.write(modified_p1 + "\n")


# 初始二进制数
p2 = "0111110110100110111001011111100001000101010100101001101000110101111111001110110111100010001000001011111000001000010001010010001000001000001100010100001010101110100101000111110111111100000100110011111111100001100010011011101100111010111011111111010000111100001011100000011011011101001010110000110000100011111010001000100110110101011011011101101001010100100011111011100011001010001011110010001011100100111110101010100001111001110010100011111111011010101001011001110100101010101110011010010011010001011001000101110110111101100000000111010000001101101000110010101011101100011011010100000111110011100000101100011001011010101010011010000110000100101010000111010000010000111101011101001110000100001011001000101111111010001111101100111100001111010111000111110000000100101101011100110100010010100110010110111110010101110100100110110111111101101001101001111111000001010010111101011100010001110100001100111100100101000011000010010101110011000001011000100111010001101011010001010001010100010000111100101011010011001001001001010001011111"

# 创建文件来保存输出结果
output_file = "listp2.txt"

modified_binaries = []

# 检查每一位,如果为0则改为1
for i in range(len(p2)):
if p2[i] == '0':
modified_p1 = p2[:i] + '1' + p2[i+1:]
modified_binaries.append(modified_p1)

# 将所有修改后的结果写入文件
with open(output_file, "w") as file:
for modified_p1 in modified_binaries:
file.write(modified_p1 + "\n")


# 打开 listp1.txt 和 listp2.txt 文件以及输出文件 p.txt
with open('listp1.txt', 'r') as file1, open('listp2.txt', 'r') as file2, open('p.txt', 'w') as output_file:
# 逐行读取文件内容
p1_lines = file1.readlines()
p2_lines = file2.readlines()

# 遍历两个文件中的所有组合并将其写入输出文件
for p1 in p1_lines:
file2.seek(0) # 重新定位到 listp2.txt 文件的开头
for p2 in p2_lines:
# 写入组合到输出文件
output_file.write(f"{p1.strip()}{p2.strip()}\n")

然后遍历密码本进行rsa解密即可
这组数据比较特殊,直接爆破的情况下会遇到模不互素的情况
所以我们代码中加入跳过模不互素的情况即可

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
from Crypto.Util.number import *
import gmpy2

n = 689148428917048752698561230187435330535844474535660975519663024686005813423116261691596518960359444398659487569281405280516756122565301499107276527019563398561775190548326726650095124347721633102683517354241616731272290842366644969493523095260169026118700872122205961125840074575539913181179624158591316008961999519664445180765805855068357280325140200570721885619207531433799082034359675994945498536733447149520815614429142224067402920944323350406000139261949314945008134993667106166371729994211490216695953544210086909916594288871041686796264966615061234867849533737850978285759970378711342002735127852669911135633280727507197770896643162828873860290236954478934069039880842775659386156914426681646990123375726632782848318765676209660955746904921591374247548244510795028854167024612141080434153599742660712283405861398644681971440490492676518075438358400296468401567303163631533553410643660848819592904185023897183284947919518254876711845553448295870785376932257813856605607299735796578232939819120320722961149946000934150374343672467868456190855696298746763169171976016018534242348938143398691129090031066272454600059389810619648519400690544893179323782655271245976991844056669848133657162015017534126606913505865717577945680934201
e = 0x10001

with open('p.txt', 'r') as p_file:
for line in p_file:
p = line.strip()

q_candidate = n // int(p, 2)
if q_candidate * int(p, 2) != n:
continue # 如果不能整除,跳过当前行处理

phi = (int(p, 2) - 1) * (q_candidate - 1)
try:
d = gmpy2.invert(e, phi)
c = 582755493501376550312021063293971269432622857973591275097520241824639113243678154601039738777785910875356099861877799721721629337353531048570147711682149769656300149663334265982311991206401905216350979684516071937023923185938510050693691337873407171757275643036119429129455102869684317978357782902189346531413458627379268090802106996865349905645096514117275113848528530242217188285324909887937524122208178818340097019103831473349905133558912714201852986162525855145162259280450040753185483478933398530730654529154485769469682628353274080092629445953899362883988215175193630488889635324515092313723195910983168425805177795699565396108348821928449320190783128803002754706992512092839782219348149442008758998793607436136085108333190190347733106486023581643835108125870863346801123024469552193808660738495330000657495372570089643330001020748391509387487524136411478620736071866518379044131693794690230740826475529806050936866355127348429602091123271970724772553111459156824158976033596665391059836828836907988254364980925568575831029223091042575366899359078304670344881979433579570857621141077250931877184312810916773443135402247438937358801349822845162460003198622710136542402567604311023354451215661022609583925197654492145458148760392

m = pow(c, d, n)
decoded_message = long_to_bytes(m).decode('utf-8', 'ignore')

if "D0g3" in decoded_message:
print(decoded_message)
except ZeroDivisionError:
continue
#flag:D0g3{sYuWzkFk12A1gcWxG9pymFcjJL7CqN4Cq8PAIACObJ}

当然赛后也看到了别的师傅更快的方法,但是他们的脚本对笔者的数据并不能跑出结果,官方wp的脚本也跑不了这组数据所以此题存在运气成分
羡慕会写脚本

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
from Crypto.Util.number import *
from gmpy2 import *
from tqdm import *

n=
p0=''
c=
def msg(n, p0, c):
p1 = p0[:1024]
p2 = p0[1024:]
pp1 = [i for i, c in enumerate(p1) if c == '0']
pp2 = [i for i, c in enumerate(p1) if c == '1']
# print(pp1)
for i in tqdm(pp1):
p1 = list(p0[:1024])
p1[i] = '1'
for j in pp2:
p2 = list(p0[1024:])
p2[j] = '0'
ppp = ''.join(p1) + ''.join(p2)
ppp2 = int(ppp, 2)
if n % ppp2 == 0:
p = ppp2
print(i, j)
print(p)
q = n // p
d = invert(65537, (p-1)*(q-1))
m = long_to_bytes(int(pow(c, d, n)))
if b'D0g3' in m:
print(m)
return
p2[j] = "1"
p1[i] = "0"


msg(n, p0, c)

文章目录
  1. 1. 密码1:
,