DASCTF 2023 & 0X401七月暑期挑战赛

Crpyto

ezRSA

from Crypto.Util.number import *
from secret import secret, flag
def encrypt(m):
    return pow(m, e, n)
assert flag == b"dasctf{" + secret + b"}"
e = 11
p = getPrime(512)
q = getPrime(512)
n = p * q
P = getPrime(512)
Q = getPrime(512)
N = P * Q
gift = P ^ (Q >> 16)
print(N, gift, pow(n, e, N))
print(encrypt(bytes_to_long(secret)),
    encrypt(bytes_to_long(flag)))

# 75000029602085996700582008490482326525611947919932949726582734167668021800854674616074297109962078048435714672088452939300776268788888016125632084529419230038436738761550906906671010312930801751000022200360857089338231002088730471277277319253053479367509575754258003761447489654232217266317081318035524086377 8006730615575401350470175601463518481685396114003290299131469001242636369747855817476589805833427855228149768949773065563676033514362512835553274555294034 14183763184495367653522884147951054630177015952745593358354098952173965560488104213517563098676028516541915855754066719475487503348914181674929072472238449853082118064823835322313680705889432313419976738694317594843046001448855575986413338142129464525633835911168202553914150009081557835620953018542067857943

# 69307306970629523181683439240748426263979206546157895088924929426911355406769672385984829784804673821643976780928024209092360092670457978154309402591145689825571209515868435608753923870043647892816574684663993415796465074027369407799009929334083395577490711236614662941070610575313972839165233651342137645009 46997465834324781573963709865566777091686340553483507705539161842460528999282057880362259416654012854237739527277448599755805614622531827257136959664035098209206110290879482726083191005164961200125296999449598766201435057091624225218351537278712880859703730566080874333989361396420522357001928540408351500991

先dfs得到P,Q 再解相关消息得到flag
但是这个dfs我每次写都会出不同bug...

"""
dfs求P,Q
然后分解N 得出n
再RSA解出明文
"""
e = 11
N = 75000029602085996700582008490482326525611947919932949726582734167668021800854674616074297109962078048435714672088452939300776268788888016125632084529419230038436738761550906906671010312930801751000022200360857089338231002088730471277277319253053479367509575754258003761447489654232217266317081318035524086377 
gift = 8006730615575401350470175601463518481685396114003290299131469001242636369747855817476589805833427855228149768949773065563676033514362512835553274555294034 
def dfs(p,q):
    if(len(p)==512):
        pp = int(p,2)
        if N%pp==0:
            print(pp,N//pp,end='\n')
    else:
        l = len(p)
        pp = int(p,2)
        qq = int(q,2)
        if((pp^(qq>>16))%(2**l) == gift%(2**l) and ((pp*qq)%(2**l)) == (N%(2**l))):
            dfs('0'+p,'0'+q)
            dfs('0'+p,'1'+q)
            dfs('1'+p,'0'+q)
            dfs('1'+p,'1'+q)


for q_low in range(1<<17):
    dfs('1',bin(q_low)[2:])
"""
8006847171912577069085166877758626954304824756138758266557706391662987806065132448544117840031499707938227955094109779732609035310252723066470330862622641 
9366986529377069783394625848920106951220134111548343265311677163992169555436421569730703291128771472885865288798344038000984911921843088200997725324682297
"""

这里还有一种快的多的方法:

from tqdm import *
N = 75000029602085996700582008490482326525611947919932949726582734167668021800854674616074297109962078048435714672088452939300776268788888016125632084529419230038436738761550906906671010312930801751000022200360857089338231002088730471277277319253053479367509575754258003761447489654232217266317081318035524086377 
gift = 8006730615575401350470175601463518481685396114003290299131469001242636369747855817476589805833427855228149768949773065563676033514362512835553274555294034 

for j in trange(1):
    pbar = gift >>(512-16)
    while True:
        try:
            qbar = (N>>(1024 - pbar.bit_length()*2))//pbar
            qbar = qbar>>6
            gifts = gift^(qbar<<(512-16-qbar.bit_length()))
            pbar = gifts >> (512-16-qbar.bit_length())

        except:
            break

    for i in range(64):
        p = (pbar<<6)+i
        if N % p == 0:
            q = N//p
            print("[+] p =",p)
            print("[+] q =",q)
            break

然后相关消息求解:

def attack(m1,m2,e,n,mbit):
    PR.<x> = PolynomialRing(Zmod(n))
    f1 = x^e - m1
    f2 = (s2n(b'}')+(x*2**8)+s2n(b"dasctf{")*(2**(8+mbit)))^e-m2
    def gcd(g1, g2):
        while g2:
            g1, g2 = g2, g1 % g2
        return g1.monic()
    return -gcd(f1,f2)[0]

for mbit in range(1,400):
    try:
        secret = attack(m1,m2,e,n,mbit)
        if(secret):
            print(n2s(int(secret)).decode())
    except:
        continue
# C0pper_Sm1th_Mak3s_T1ng5_Bet4er

这里用些小技巧 :try except防止有些解不出来的情况报错
再用decode能保证无意义的bytes不会输出

ezDHKE

from Crypto.Util.number import *
from Crypto.Cipher import AES
from hashlib import sha256
from random import randbytes, getrandbits
from flag import flag

def diffie_hellman(g, p, flag):
    alice = getrandbits(1024)
    bob = getrandbits(1024)
    alice_c = pow(g, alice, p)
    bob_c = pow(g, bob, p)
    print(alice_c , bob_c)
    key = sha256(long_to_bytes(pow(bob_c, alice, p))).digest()
    iv = b"dasctfdasctfdasc"
    aes = AES.new(key, AES.MODE_CBC, iv)
    enc = aes.encrypt(flag)
    print(enc)

def getp():
    p = int(input("P = "))
    assert isPrime(p)
    assert p.bit_length() >= 1024 and p.bit_length() <= 2048
    g = 2
    diffie_hellman(g, p, flag)

getp()

本质是要离散对数求解alice 由于p由我们自己提供 所以我们提供一个光滑数使得能快速求解离散对数
构造光滑数:

def gen_primes(nbit, imbalance):
    """
    :param nbit: 最终光滑数比特数
    :param imbalance: 最小单位比特数
    :return: 比特数
    """
    p = int(2)
    FACTORS = [p]
    while p.bit_length() < nbit - 2 * imbalance:
        factor = getPrime(imbalance)
        FACTORS.append(factor)
        p *= factor
    rbit = (nbit - p.bit_length()) // 2

    while True:
        r, s = [getPrime(rbit) for _ in '01']
        _p = p * r * s
        if _p.bit_length() < nbit: rbit += 1
        if _p.bit_length() > nbit: rbit -= 1
        if isPrime(_p + 1):
            FACTORS.extend((r, s))
            p = _p + 1
            break

    FACTORS.sort()
    return (p, FACTORS)
p = 1
while int(p).bit_length() != 1024:
    p = gen_primes(1024, 16)[0]

总:

from Crypto.Util.number import *
from Crypto.Cipher import AES
from hashlib import sha256

def gen_primes(nbit, imbalance):
    """
    :param nbit: 最终光滑数比特数
    :param imbalance: 最小单位比特数
    :return: 比特数
    """
    p = int(2)
    FACTORS = [p]
    while p.bit_length() < nbit - 2 * imbalance:
        factor = getPrime(imbalance)
        FACTORS.append(factor)
        p *= factor
    rbit = (nbit - p.bit_length()) // 2

    while True:
        r, s = [getPrime(rbit) for _ in '01']
        _p = p * r * s
        if _p.bit_length() < nbit: rbit += 1
        if _p.bit_length() > nbit: rbit -= 1
        if isPrime(_p + 1):
            FACTORS.extend((r, s))
            p = _p + 1
            break

    FACTORS.sort()
    return (p, FACTORS)
p = 1
while int(p).bit_length() != 1024:
    p = gen_primes(1024, 16)[0]
print('p =', p)
p = 95222031386982518600581680760048895038902220410609605485056966026197717548482967890182247609079713955696755427279984159519531463416753122558820299142790621730584765728333142744245593476307366954744209962144178968214119880140990039752097139909922059904755330545838623475817850074193853808706457235558934301967
a_c = 5067202762535347924644107267592645095822339022001804740010281699665277262877469712778891927183200198064959829846339940562081608629210758713033514330099266673106554608680475743389078378023846281302050873170348735330045830136751773765814641056144070836089660285053742247242045185216454611908850121362139566190
b_c =  42211633752219027935846707414239119252378241216321435838353564474614683776948227344182910150587401840371195951570536559709470771975024619976604457598691930926038270611896389721828565609459140420374409031707944912132234038369240587001629771897874560267246605192299374541914485157318326586144908446307225975585
enc = b'L}.\x97\x9e\x06\xe6W`\x86M\xd3\xb0\x18\xc6\x9c\xe8\xa05M\x18\xbd\xe2\x86\x1d<\xab5\xf9l\x9d\xdc\xa9U\xe1T\xf5\x85\xa1kc\xdb\x94\xa0\xc9\xf6/\xb1'

alice = discrete_log(mod(a_c,p),mod(2,p))
print(alice)
alice = 1638146344954429230613781913443382648574730527192987161928045244022817065435416307821717214054584750071473750478214985544494824268103568035336600576764308685654582191542517666412246052381117067644270340200903170970763613720818385416718856033067314054445419334269341152477968702345145396129988411760177908036
key = sha256(long_to_bytes(pow(b_c, alice, p))).digest()
iv = b"dasctfdasctfdasc"
aes = AES.new(key, AES.MODE_CBC, iv)
flag = aes.decrypt(enc).decode()
print(flag)

再解:

from Crypto.Util.number import *
from Crypto.Cipher import AES
from hashlib import sha256
# p = 1
# cnt = 0
# while True:
#     if(p.bit_length()>=1024 and isPrime(p+1)):
#         print(f'p= {p+1}')
#         break
#     p *= sieve_base[cnt]
#     cnt += 1
p = 20404068993016374194542464172774607695659797117423121913227131032339026169175929902244453757410468728842929862271605567818821685490676661985389839958622802465986881376139404138376153096103140834665563646740160279755212317501356863003638612390661668406235422311783742390510526587257026500302696834793248526734305801634165948702506367176701233298064616663553716975429048751575597150417381063934255689124486029492908966644747931
alice_c = 2028023118973335608933213426411106707321512231070295452855846045914205470173052454875684217591764526682014109423800138402999754770347503854978075513027409214531063003055887639873686813807510697274712995331988288004695406114271515381415041219562128822140781744928307306153445845088200582071268569254979352823048453477810101227938890392579800248753840892142600948992762362064045942239456536106370245902129824159711875657880735
bob_c = 9504267470831972113715914183603398612906201341311814800916032139498723663046340159098917253548368333210992389992440892568287812398688495880461775190008915647692058725872723795257476934433855458958113734570231228254088641806626783439093590637693578278419843846587896478676802948635519498988754108229564410255492134993321018575577473502967496193939648644787542365500861317084439884904816016949448412516083120795520818271815239
enc = b"\x99\xb9\xcb\xbe:\x04\xb8\xb8\xd8\x0c\x1bt\xa2\xab\x02_t\xf8\x8f\xc8'\xe7\x11\x85\xf4NLv\xdbo\x14\x05A\xeb.UF\xb0\x11 \xa5\xf7\xb84O\xc3K\x80"
# alice = discrete_log(mod(alice_c,p),mod(2,p))
# print(alice)
alice = 105577687054129861646306034602647509584045134562289991600097393196559035643241686385608271361326428884991414297297791416521052784162442458079286262814706417126976276397346369348383237451704523049931225768818566677426840808701475604822108395019002106638433572669119751383584134617167555211772234741688279542036
key = sha256(long_to_bytes(pow(bob_c, alice, p))).digest()
iv = b"dasctfdasctfdasc"
aes = AES.new(key, AES.MODE_CBC, iv)
print(aes.decrypt(enc).decode())

Reverse

controlflow

hook混淆 里面牵扯了很多函数动调逐步分析
主函数先进行了一次加密
image
然后是这层
image
再是这层
image
这里下标也要+10
sub_1001220结束后会进入一段汇编
image
这里就是 flag[i] -= i
这个循环结束后会到这
image
flag[i] *= 3
然后是这个
image
这里要注意是 flag[i+10] 下标不是i 而是 i+10
最后进入总check
image
函数过多 学习用z3求解

from z3 import *
enc = [0x00000CCF, 0x00000CC0, 0x00000CFC, 0x00000CD8, 0x00000D23, 0x00000D11, 0x00000DC8, 0x00000D7D, 0x00000DAA, 0x00000E2B, 0x00000E7C, 0x00000E5B, 0x00000EA9, 0x00000ECA, 0x00000F5A, 0x00000F5A, 0x00000FB1, 0x0000104D, 0x00001095, 0x0000117C, 0x0000137D, 0x000012F3, 0x0000142E, 0x0000141C, 0x00001233, 0x00001287, 0x000011F4, 0x00001758, 0x00001461, 0x0000122A, 0x00001782, 0x000017F7, 0x00001911, 0x0000194D, 0x00001A10, 0x00001AEB, 0x00001B90, 0x00001CE6, 0x00001DE2,0x1ED2]
flag = [BitVec('flag[%d]'%i,8) for i in range(40)]
buf = [0]*40
for i in range(40):
    buf[i] = flag[i]
    buf[i] ^= 0x401
for i in range(40):
    buf[i] += i*i
for i in range(20):
    buf[i+10] ^= i*(i+1)
for i in range(40):
    buf[i] -= i
for i in range(40):
    buf[i] *= 3
for i in range(0,20,2):
    buf[i+10] ^= buf[i+1+10]
    buf[i+1+10] ^= buf[i+10]
    buf[i+10] ^= buf[i+1+10]
s = Solver()
for i in range(40):
    s.add(buf[i] == enc[i])
print(s.check())
print(s.model())
ans = s.model()
for i in flag:
    print(chr(ans[i].as_long()),end='')
# DASCTF{TWpnemRuSTRkVzVsWVhOMmJqZzNOREoy}
posted @ 2023-11-13 19:16  N0zoM1z0  阅读(113)  评论(0编辑  收藏  举报