Skip to content

LZCTF2025

约 1120 字大约 4 分钟

cryptomiscaiforensics

2025-06-29

CRYPTO

baby_RSA1

yafu分解n得到p和q

from Crypto.Util.number import *
p = 4511491
q = 473398607161
e = 19
print('LZCTF{'+str(inverse(e,(p-1)*(q-1)))+'}')
#LZCTF{2023326077889096379}

baby_RSA2

p-1与q-1有大公因子,r接近1/2

import random
try:
    gcd
except NameError:
    from math import gcd

def rho(N):
    f = lambda x: (pow(x, N-1, N) + 3) % N
    while True:
        t = random.randint(2, N)
        h = f(t)
        step_times = 0
        step_limit = 2
        while True:
            if not step_times < step_limit:
                step_times = 0
                step_limit *= 2
                t = h
                h = f(h)
            p = gcd(abs(int(t) - int(h)), N)
            if p == N:
                break
            elif p > 1:
                return (p, N // p)
            else:
                h = f(h)
                step_times += 1

p,q=rho(85506307179971345340573076298550920202050478522625049159869967159111928076600526030716602184667357077017298325347284339017988664271003344334793438409286753700312305433795917510554976379526043584238937850357500061114283285663795372182176438870325874623093086378492909249854224565645790634816064004980353927339)

from Crypto.Util.number import *

n = 85506307179971345340573076298550920202050478522625049159869967159111928076600526030716602184667357077017298325347284339017988664271003344334793438409286753700312305433795917510554976379526043584238937850357500061114283285663795372182176438870325874623093086378492909249854224565645790634816064004980353927339
e = 43607
c = 68328014893597066623399349398360593182413091005605015946953295199952206497756677637500669249013782647067938648822032536367228947314586981293553305067650790694832721627038265994289720151984888941279636426367917794666376911337568705513834836696396821589786928534416507370206499538258635478332286049006280738334

assert p*q==n 
print(long_to_bytes(pow(c, inverse(e, (p-1)*(q-1)), p*q)))
# b"LZCTF{POL14RD'5_rhO_@19ORITHm_i5_eFfI3NC7}"

baby_RSA3

p,q高位剪枝,再coppersmith低200位

from tqdm import tqdm
from Crypto.Util.number import *
n = 18533990774081566897552566974262097416460295871064804716373477024458224583522146855795204088818577499983520478103695933066516427066168181562414247509838099162181918528079086808226654604433995649076665294969782084669933927159454550871793142158829962300169809318365892055515646987531642336954765598527590522427799703483495093933794419314821614565957860695602543483221366210619570810159771730145263874453729964655090920499220891262725136545941883135824095492047785480934566560350995537806977473860830360480078523477495159622804146945417715254386041023406698198040669055126009408685953639669289579101769142130296613107591
gift = 42089255107159644583243254598992173546231159197860225956184289942731016232048934241123609827471609802766849625026279691927614648402900660432266990311919092764372302457083612513044459849201763773868157045807629807005100889882669587731744668236728455
c = 535090531842740167243170702307390311291418643839953177643033139688308288048493882840030210480697107197195866097337989494938593681295268305213202491239077700948212854458878557554149377025747886069438127094984221317976417891714763155456795259109436887901296931886835427960445871705831446950463087754746896991672464282855314609785006828445084507077109236184885281019216321163984730055041891629599140899243888109990514225470827365484173158535001369482072321937262615267964012363537100865187587392137138811523904739819588617917058206346220437709132474051417974788177837958025460255179655794332495569438305627298928356457

print(int(gift).bit_length())
xor_p_q = bin(gift)[2:].zfill(824)
print(len(xor_p_q))
print(xor_p_q)
p_count = []
bit = 824

print(n.bit_length())
def find(p,q):
    length = len(p)
    p_min = p + '0'*(1024-length)
    p_max = p + '1'*(1024-length)
    q_min = q + '0'*(1024-length)
    q_max = q + '1'*(1024-length)
    
    if int(p_min,2) < int(q_min,2):
        return 
    
    if int(p_min,2)*int(q_min,2) > n:
        return
    
    if int(p_max,2)*int(q_max,2) < n:
        return 
    
    if length == 824:
        p_count.append(int(p,2))
        return 
    else:
        if xor_p_q[length]=="0":
            find(p+"0",q+"0")
            find(p+"1",q+"1")
        else:
            find(p+"0",q+"1")
            find(p+"1",q+"0")

p = ""
q = ""
find(p,q)

PR.<x> = PolynomialRing(Zmod(n))
for i in tqdm(p_count,leave="true"):
    f = i*(2^200) + x
    f = f.monic()
    result = f.small_roots(X=2^201,beta=0.4)
    if result:
        p = int(f(result[0]))
        q = n//p
        print(long_to_bytes(pow(c,inverse(65537,int((p-1)*(q-1))),n)))
        break
# b'LZCTF{62ff69bc-e121-454a-9d80-347066af9b80}'

Do_you_know_factor

调用factordb的api对n进行分解查询,当分解结果有两位并且均128bits的时候就是p和q

from Crypto.Util.number import *
import gmpy2
import requests
from tqdm import *
PKEY = 50996360358591058519231936875020349959831130775354958086708907272224566458331
ENC = 149917270740249846070888582165796880841173145322459848679460751820343617381
c_high = ENC<<8
n_high = (PKEY>>8)<<8
e_high = (PKEY & (2**8-1))<<8
def factor_n(n):
    url = "http://factordb.com/api?query={}".format(str(n))
    try:
        response = requests.get(url)
        fac = response.json()['factors']
        fac_data = [int(i[0]) for i in fac]
        return fac_data
    except:
        pass

p_q = []
for i in trange(2**8):
    n = n_high+i
    fac_data = factor_n(n)
    if len(fac_data)==2:
        if fac_data[0].bit_length()==128 and fac_data[1].bit_length()==128 and isPrime(fac_data[0]) and isPrime(fac_data[1]):
            p_q = fac_data
            break
p,q = int(fac_data[0]),int(fac_data[1])
n = p*q
phi = (p-1)*(q-1)
for i in range(2**8):
    for j in range(2**8):
        c = c_high + i
        e = e_high + j
        if isPrime(e):
            try:
                d = gmpy2.invert(e, phi)
                m = pow(c,d,n)
                flag = long_to_bytes(m)
                if all(k<=127 and k >=33 for k in flag):
                    print(b"LZCTF{"+flag+b"}")
                    break
            except:
                pass
# b'LZCTF{f@C7OR_I7!!}'

Smooth

p-1和q-1光滑+离散对数(CRT)

from gmpy2 import *
from Crypto.Util.number import *
a = 2
n = 2
N =56967102676346815408343874856836051984486997911462792815888426625782789674448496737568928459807745408501199292247437221316473537422310413322217963252103157597835340862804343591928487949009552264961201767328922731921539776469249475995285462420869151827003355142463635248173553082174775682494899477341

while True:
    a = pow(a, n, N)
    res = GCD(a-1, N)
    if res != 1 and res != N:
        q = N // res
        print("p=",res)
        print("q=",q)
        break
    n += 1
from Crypto.Util.number import *

p= 1569583007727469646320106699006883952880643533050399258106042200627613911491386033003301795784812918452232653328628527756095365113713795095198954586071
q= 36294418578617886095375401554783457088387456693400632587167630115333816990093459421711328568372947712284776400063017607732278627138744903508750395371

c_1 = 33074792071449086224114814703708843481389095793091562008464759764178413125388758744628590569869218695818323865944327000709040910061593695089113913785753372154238993698427170939964518499360382358242068705549469991284880316789504232558380660667898760105739982870841503013939242347681568529360218427555
c_2 = 39009674283046620472345718972417867788587693901920798006010342993567931591776398720380199723310244431905108686389809230430272689978916365374896542294350722451098585295701885565180474927517518583938563436272470923659959529268632190305834904190601486839276361945866759259432037346167176170371096371550
e = 0x10001
n=p*q

Zp, Zq = Zmod(p), Zmod(q)
d = inverse_mod(e, (p-1)*(q-1))
m_1 = int(pow(c_1, d, n))
print(long_to_bytes(m_1).decode(),end='')

m_2p = discrete_log(Zp(c_2), Zp(e))
m_2q = discrete_log(Zq(c_2), Zq(e))
m_2 = crt([m_2p, m_2q], [p-1, q-1])
print(long_to_bytes(m_2p).decode())
# LZCTF{SMo0th_NumbEr_I5_v3Ry_DAnGERoU5}

MISC

warmlight不会协议分析

寻找smb登录成功的session setup

对smb2流量按长度排序找到对象,再按时间排序

得到成功会话信息:

username:hackbackzip
domain:DESKTOP-0TNOE4V
ServerChalange:c609ad1b3a15aedc
NTproofstring:eb1b0afc1eef819c1dccd514c9623201
modifiedntlmv2respomse:01010000000000006f233d3d9f9edb01755959535466696d0000000002001e004400450053004b0054004f0050002d00300054004e004f0045003400560001001e004400450053004b0054004f0050002d00300054004e004f0045003400560004001e004400450053004b0054004f0050002d00300054004e004f0045003400560003001e004400450053004b0054004f0050002d00300054004e004f00450034005600070008006f233d3d9f9edb010900280063006900660073002f004400450053004b0054004f0050002d00300054004e004f004500340056000000000000000000

hashcat字典爆破:

hackbackzip::DESKTOP-0TNOE4V:d102444d56e078f4:eb1b0afc1eef819c1dccd514c9623201:01010000000000006f233d3d9f9edb01755959535466696d0000000002001e004400450053004b0054004f0050002d00300054004e004f0045003400560001001e004400450053004b0054004f0050002d00300054004e004f0045003400560004001e004400450053004b0054004f0050002d00300054004e004f0045003400560003001e004400450053004b0054004f0050002d00300054004e004f00450034005600070008006f233d3d9f9edb010900280063006900660073002f004400450053004b0054004f0050002d00300054004e004f004500340056000000000000000000

得到密码:pikeplace

LZCTF{hackbackzip:pikeplace}

W3c10m3

ps一下,扫码得到:password:Data_Matrix,解压后用zxing扫码

LZCTF{QR_DM_3mb3dd3d_Fl4g_5aMpl3}

NUDT520

听声音是摩斯密码,放网站

lsb音频隐写,使用SilentEye得到压缩包flag.zip(爆破密码,第一次用的是字典,跑了老久han)

解压后出现NNUUDDTT.lzb,注意提示:"与后缀无关,与文件名有关"。观察文件内容:

此处含有许多NNUUDDTT中的字符,同时出现^异或标志,猜测异或文件名(meng)

结果结尾显示LSB520,文件头位PNG,改后缀并lsb按照rgb分别5、2、0处理数据

LZCTF{LSB_Stegan0graphy_Master_1n_PNG_WAV}

FORENSICS

who_is_the_winner-1

autopsy挂载img,Temp下有hack.txt

LZCTF{H@_hA_y0ur_PC_15_h4cK3d!}

who_is_the_winner-2

在C:\windows\system32\Task发现windowsupdate中可疑行为:

C:\Users\Public\Downloads\svchost.exe
C:\Users\admin\AppData\Local\Temp\_MEI39842\mal.py

LZCTF{C:\Users\Public\Downloads\svchost.exe}

who_is_the_winner-3

上一问的木马导出,用pyinstxtractor处理,得到mal.pyc,010打开,注意到base64编码的部分字符(前方存在create、base64)

得到密码,用户在autopsy的os account出现过。

LZCTF{w1nh4ck3r_P@ssw0rd!}

AI

JailBreak-exec

把route.ts喂给ai,并提示他注意eval()函数

按照回答尝试绕过,使用提示词工程中的“不允许”

发现先用:"); const cmd = 'pro' + 'cess'; const act = 'ex' + 'it'; global[cmd][act](1); //

进行扰乱,再使用"); require('child_process').execSync('whoami').toString() 即可得到类似shell的情况

LZCTF{5e3f511f-9dca-4396-a810-da61cbb1d722}