LOADING

加载过慢请开启缓存 浏览器默认开启

SRCTF-writeup

2024/8/6

adwa拉去打的社工我懒得写wp,最后第九应该是

懒得写社工,社工出了五个,感觉没啥技术含量

SRCTF-writeup

Crypto

hash attack(侥幸三血)

下载附件查看代码

Util.py

import random


iv = 0x7380166F4914B2B9172442D7DA8A0600A96F30BC163138AAE38DEE4DB0FB0E4E
MAX = 2**32


def str_bin(msg):
    return "".join([bin(ord(i))[2:].zfill(8) for i in msg])


def int_bin(a, l):
    return bin(a)[2:].zfill(l)


def bin_hex(a, l):
    return hex(int(a, 2))[2:].zfill(l)


def int_left_shift(a, k, bit=32):
    return ((a << k) & 0xFFFFFFFF) | ((a & 0xFFFFFFFF) >> (bit - k))


def T(j):
    return 0x79CC4519 if j <= 15 else 0x7A879D8A


def FF(x, y, z, j):
    if j <= 15:
        return x ^ y ^ z
    else:
        return (x & y) | (x & z) | (y & z)


def GG(x, y, z, j):
    if j <= 15:
        return x ^ y ^ z
    else:
        return (x & y) | ((x ^ 0xFFFFFFFF) & z)


def P0(x):
    return x ^ int_left_shift(x, 9) ^ int_left_shift(x, 17)


def P1(x):
    return x ^ int_left_shift(x, 15) ^ int_left_shift(x, 23)


def pad(msg):
    if len(msg) < 512:
        l = len(msg)
        k = 512 - (l - 447) % 512
        return msg + "1" + k * "0" + int_bin(l, 64)
    else:
        return msg


def msg_pad(bi):
    w = []
    for i in range(16):
        w.append(int(bi[32 * i : 32 * i + 32], 2))
    for i in range(16, 68):
        w.append(
            P1(w[i - 16] ^ w[i - 9] ^ int_left_shift(w[i - 3], 15))
            ^ int_left_shift(w[i - 13], 7)
            ^ w[i - 6]
        )
    w_ = []
    for i in range(64):
        w_.append(w[i] ^ w[i + 4])
    return w, w_


def cf(vi, bi):
    w, w_ = msg_pad(bi)
    abcdefgh = []
    for i in range(8):
        abcdefgh.append(int(vi[i * 32 : (i + 1) * 32], 2))
    a, b, c, d, e, f, g, h = abcdefgh
    for j in range(64):
        ss1 = int_left_shift(
            int_left_shift(a, 12) + e + int_left_shift(T(j), j % 32) % MAX, 7
        )
        ss2 = ss1 ^ (int_left_shift(a, 12))
        tt1 = (FF(a, b, c, j) + d + ss2 + w_[j]) % MAX
        tt2 = (GG(e, f, g, j) + h + ss1 + w[j]) % MAX
        d = c
        c = int_left_shift(b, 9)
        b = a
        a = tt1
        h = g
        g = int_left_shift(f, 19)
        f = e
        e = P0(tt2)
    vi_1 = int(
        int_bin(a, 32)
        + int_bin(b, 32)
        + int_bin(c, 32)
        + int_bin(d, 32)
        + int_bin(e, 32)
        + int_bin(f, 32)
        + int_bin(g, 32)
        + int_bin(h, 32),
        2,
    ) ^ int(vi, 2)
    return int_bin(vi_1, 256)


def iteration_func(msg):
    n = len(msg) // 512
    bi = []
    for i in range(n):
        bi.append(msg[512 * i : 512 * i + 512])
    v = [int_bin(iv, 256)]
    for i in range(n):
        v.append(cf(v[i], bi[i]))
    return bin_hex(v[n], 64)


def ez_hash(msg, salt=None):
    bin_msg = str_bin(msg)
    pad_msg = pad(bin_msg)
    if salt is not None:
        pad_msg += salt
    c = iteration_func(pad_msg)
    return c


def gensalt():
    strings = """0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ """
    return "".join([random.choice(strings) for _ in range(32)])

hash_attack.py

from Util import ez_hash, gensalt
from base64 import b64decode

FLAG = open("flag").read()
salt = gensalt()
key = "adwa_only_has_one_key"
hash_key = ez_hash(key, salt)
try:
    password = b64decode(input("input your key: ")).decode("latin-1")
except:
    print("wrong")
    exit(0)
if password != key and ez_hash(password, salt) == hash_key:
    print(FLAG)
print("Your key is wrong")

分析代码,先看hash_attack.py,分析代码,首先打开了一个FLAG文件读取了flag,然后使用Util.py内部构造的函数gensalt()然后使用这个key然后使用hash_key函数得到一段hash_key,在这里面我们要输入的是base64解码之后得到的结果要不等于key并且要输入的base64解码之后的key的hash_key与前面的相等,在这里注意一下base64解码之后的编码是latin-1,这个编码的范围是0x00到0xff,这是个伏笔。

那我么那就可以去分析Utils函数了,我们先分析一下ez_hash函数吧

def ez_hash(msg, salt=None):
    bin_msg = str_bin(msg))
    pad_msg = pad(bin_msg)
    if salt is not None:
        pad_msg += salt
    c = iteration_func(pad_msg)
    return c

在这个函数里面首先调用str_bin函数讲输入的key转化为二进制

def str_bin(msg):
    return "".join([bin(ord(i))[2:].zfill(8) for i in msg])

然后填充了一下,pad函数如下,其实就是去看二进制长度不足512位需要后面补1之后补上0不过需要留下64位,这64位为长度的2进制并且要扩充到64位放在最后

def pad(msg):
    if len(msg) < 512:
        l = len(msg)
        k = 512 - (l - 447) % 512
        return msg + "1" + k * "0" + int_bin(l, 64)
    else:
        return msg

然后开始判断salt是否为空然后进行判断看salt加不加在被填充的明文的后面,根据前面的分析知道显而易见不是空的,所以需要加上salt最后调用函数iteration_func(pad_msg)加密得到hash,在iteration_func(msg)函数里面先将前面填充过的密文在这里的长度除一下512用来决定bi数组的填充然后再将bi数组和数组v进行迭代压缩运算,最后输出64位hash

def iteration_func(msg):
    n = len(msg) // 512
    bi = []
    for i in range(n):
        bi.append(msg[512 * i : 512 * i + 512])
    v = [int_bin(iv, 256)]
    for i in range(n):
        v.append(cf(v[i], bi[i]))
    return bin_hex(v[n], 64)

接下来你看这个函数你会看到一个问题我们已知原本的key那我们可以得到他的hash为f8af7e6cdf77fa6fae7703e222167f0e9c0158be6182eca5d9853c177b785b19
然后你会发现既然我们有了这个key那么他的填充后的二进制什么的我也都会知道,这时候关键的来了,那么填充后的二进制我知道而且还是latin-1编码,他会输出所有的东西,那么可以直接转换了得到填充之后的key的字符串,然后思路清晰了,既然填充的是这玩意,那么我们直接传这玩意的base64就好了。

import base64
from base64 import *
import random
from Cryptodome.Util.number import *

iv = 0x7380166F4914B2B9172442D7DA8A0600A96F30BC163138AAE38DEE4DB0FB0E4E
MAX = 2**32


def str_bin(msg):
    return "".join([bin(ord(i))[2:].zfill(8) for i in msg])


def int_bin(a, l):
    return bin(a)[2:].zfill(l)


def bin_hex(a, l):
    return hex(int(a, 2))[2:].zfill(l)


def int_left_shift(a, k, bit=32):
    return ((a << k) & 0xFFFFFFFF) | ((a & 0xFFFFFFFF) >> (bit - k))


def T(j):
    return 0x79CC4519 if j <= 15 else 0x7A879D8A


def FF(x, y, z, j):
    if j <= 15:
        return x ^ y ^ z
    else:
        return (x & y) | (x & z) | (y & z)


def GG(x, y, z, j):
    if j <= 15:
        return x ^ y ^ z
    else:
        return (x & y) | ((x ^ 0xFFFFFFFF) & z)


def P0(x):
    return x ^ int_left_shift(x, 9) ^ int_left_shift(x, 17)


def P1(x):
    return x ^ int_left_shift(x, 15) ^ int_left_shift(x, 23)


def pad(msg):
    if len(msg) < 512:
        l = len(msg)
        k = 512 - (l - 447) % 512
        return msg + "1" + k * "0" + int_bin(l, 64)
    else:
        return msg


def msg_pad(bi):
    w = []
    for i in range(16):
        w.append(int(bi[32 * i : 32 * i + 32], 2))
    for i in range(16, 68):
        w.append(
            P1(w[i - 16] ^ w[i - 9] ^ int_left_shift(w[i - 3], 15))
            ^ int_left_shift(w[i - 13], 7)
            ^ w[i - 6]
        )
    w_ = []
    for i in range(64):
        w_.append(w[i] ^ w[i + 4])
    return w, w_


def cf(vi, bi):
    w, w_ = msg_pad(bi)
    abcdefgh = []
    for i in range(8):
        abcdefgh.append(int(vi[i * 32 : (i + 1) * 32], 2))
    a, b, c, d, e, f, g, h = abcdefgh
    for j in range(64):
        ss1 = int_left_shift(
            int_left_shift(a, 12) + e + int_left_shift(T(j), j % 32) % MAX, 7
        )
        ss2 = ss1 ^ (int_left_shift(a, 12))
        tt1 = (FF(a, b, c, j) + d + ss2 + w_[j]) % MAX
        tt2 = (GG(e, f, g, j) + h + ss1 + w[j]) % MAX
        d = c
        c = int_left_shift(b, 9)
        b = a
        a = tt1
        h = g
        g = int_left_shift(f, 19)
        f = e
        e = P0(tt2)
    vi_1 = int(
        int_bin(a, 32)
        + int_bin(b, 32)
        + int_bin(c, 32)
        + int_bin(d, 32)
        + int_bin(e, 32)
        + int_bin(f, 32)
        + int_bin(g, 32)
        + int_bin(h, 32),
        2,
    ) ^ int(vi, 2)
    return int_bin(vi_1, 256)


def iteration_func(msg):
    n = len(msg) // 512

    bi = []
    for i in range(n):
        bi.append(msg[512 * i : 512 * i + 512])
    v = [int_bin(iv, 256)]
    print(v)
    print(len(v))
    print(bi)
    print("nihao")
    print()


    for i in range(n):
        v.append(cf(v[i], bi[i]))
        print(v[0])
        print(v[n])
        print(v[1])

    return bin_hex(v[n], 64)


def ez_hash(msg, salt=None):
    bin_msg = str_bin(msg)
    print(bin_msg)
    pad_msg = pad(bin_msg)
    print(pad_msg)
    if salt is not None:
        pad_msg += salt
    print(pad_msg)
    c = iteration_func(pad_msg)
    return c


def gensalt():
    strings = """0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ """
    return "".join([random.choice(strings) for _ in range(32)])



flag=b'srctf{99999999}'
salt = gensalt()
key = "adwa_only_has_one_key"
hash_key = ez_hash(key, salt)
print(hash_key)
bin_msg = str_bin(key)
print(bin_msg)
l = len(key)
print(int_bin(l, 64))
pad_msg = pad(bin_msg)
print(pad_msg)
print(iteration_func(pad_msg))
c='1111100010101111011111100110110011011111011101111111101001101111101011100111011100000011111000100010001000010110011111110000111010011100000000010101100010111110011000011000001011101100101001011101100110000101001111000001011101111011011110000101101100011001'
print(long_to_bytes(int(c,2)))
p=long_to_bytes(int(c,2))
print(base64.b64encode(p).decode("latin-1"))


print("------------------------------------------------")
keypad='01100001011001000111011101100001010111110110111101101110011011000111100101011111011010000110000101110011010111110110111101101110011001010101111101101011011001010111100110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010101000'
print(long_to_bytes(int(keypad,2)).decode('latin-1'))


n=long_to_bytes(int(keypad,2)).decode('latin-1').encode('latin-1')
print(base64.b64encode(n))
lll=base64.b64encode(n)
print(base64.b64decode(lll).decode('latin-1'))
print(1111111)

hash1_key = ez_hash(n, salt)
print(hash1_key)
print(len(keypad))

exp如下:

from pwn import *
import base64
from base64 import *
import random
from Cryptodome.Util.number import *
io =remote("110.40.35.62",33860)

a=io.recvuntil(b'\n')
keypad='01100001011001000111011101100001010111110110111101101110011011000111100101011111011010000110000101110011010111110110111101101110011001010101111101101011011001010111100110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010101000'
n=long_to_bytes(int(keypad,2)).decode('latin-1').encode('latin-1')
a1=base64.b64encode(n)
io.sendline(a1)
b=io.recvuntil('\n')
print(a)
print(b)

leak(一血)

task.py

from Crypto.Util.number import *
import gmpy2
from enc import flag

m = bytes_to_long(flag)
p = getPrime(512)
q = getPrime(512)
e = 1013
n = pq
d = gmpy2.invert(e,(p-1)
(q-1))
dp = d % (p-1)
leak = dp>>200
c = pow(m,e,n)
print(f”n = {n}”)
print(f”e = {e}”)
print(f”leak = {leak}”)
print(f”c = {c}”)
‘’’
n = 110213245423787811834518112811871374057182659656333171180583906182098866895106152169202974253392946952670696530676210762805363864263383224528537325490112353868969261155364863882874549993204597016739119560224274234085791998310748667903130690276875928801213222945825623033159412256315898753155041172844790881283
e = 1013
leak = 2111661101489986207946671243111315656386526068378675693749037940046822939637002369276880737091
c = 44953911831010760674028216893023771903735777342102642215298073259026291235527656090988244571561391378675170728470813535186907109257362776905391646755360995924417928753904003476238093726521687524894340317021957879542128875867159267372684219741723042726979008939837475097290381429403885987472234565635819680600
‘’’

很明显了dp高位泄露

e⋅dp≡e⋅d≡1(mod(p−1))
⇔e⋅dp=k(p−1)+1=kp−k+1⇔e⋅dp+k−1≡0(modp)

∵dp<p−1

∴k<e

∴e⋅(dp0<<k+x)+k−1≡0(modp)

exp如下:

#Sage
from tqdm import *
secret = 2111661101489986207946671243111315656386526068378675693749037940046822939637002369276880737091

e = 1013

n = 110213245423787811834518112811871374057182659656333171180583906182098866895106152169202974253392946952670696530676210762805363864263383224528537325490112353868969261155364863882874549993204597016739119560224274234085791998310748667903130690276875928801213222945825623033159412256315898753155041172844790881283


F.<x> = PolynomialRing(Zmod(n))
d = inverse_mod(e, n)
for k in tqdm(range(1, e)):
    f = (secret << 200) + x + (k - 1) * d
    x0 = f.small_roots(X=2 ** (200 + 1), beta=0.44, epsilon=1/32)
    if len(x0) != 0:
        dp = x0[0] + (secret << 200)
        for i in range(2, e):
            p = (e * Integer(dp) - 1 + i) // i
            if n % p == 0:
                break
            if p < 0:
                continue
            else:
                print('k = ',k)
                print('p = ',p)
                print('dp = ',dp)
                q = n // p
                d =inverse(e,(p-1)*(q-1))
                print(long_to_bytes(pow(c,d,n)))
                break

baby

task.py

from Cryptodome.Util.number import *
from secret import flag

m = bytes_to_long(flag)
p = getPrime(512)
q = getPrime(512)
r = getPrime(700)
t = getPrime(800)
tmp = getPrime(10)
print(f"leak = {p*r+q*t+tmp}")
print(f"r = {r}")
print(f"t = {t}")
e = 65537
n = p*q
print(f"c = {pow(m,e,n)}")
print(f"leak = {p*r+q*t+tmp}")
print(f"r = {r}")
print(f"t = {t}")
print(tmp)
'''
c = 30075387915048470863070050827629191303436443913395824732907226821054460652219815718226645166341618100700084925720992983286419204902032573926790086035422540879196867669665497753447829812026327367178333296715527968448124126434045869420695221514125724904849358819864918062875310272203931927234053359553779163755
leak = 52407066630998720273731758848751180003129908965730006096464345923549459617438414126937562326106182853585345246472838907532807236677219886418149723311118855918338387062301958904467478605422673207935942348215552655035846974843053690523359908921489934306458440759517598485452824210146131626776354968352617955744704892906092826257342911994753745093428990023111339468228443855826492957321799005181961
r = 4515378990844403115229704433484433833022655205121974667074150580454343643752811757675793959795169040704894972951300994535151410073321406165168737850534934347874731893617893819762340858239387281147345869706971753
t = 6006929234728180950140499814342609393927042935104177663404375056306287820676434237439964941788093406713118055152122129530273026459457066165368157449726903765601586482566299501860863052052121811433466409338266730837645652741024637475218039773
'''

看到这个造格就好了,但是如果直接构造等式pr+qt+tmp=leak的格得到的结果的值偏小,那么就想到要扩大一下式子,那同时求两个式子rleak,tleak,这样我们得到rleak=r(pr+qt+tmp),tleak=t*(pr+qt+tmp),相减即可构造等式

t * leak - r * leak = t * p * r + q * t^2 + tmp * t - p * r^2 - r * q * t - leak * r

(t-r) * leak - (t-r) * tmp = t * r * q - t * r * p + q * t^2 - p * r^2

(t-r)(leak-tmp)=t * r(q-p) + q * t^2 - p * r^2

(t-r)(leak-tmp) - t * r * (q-p) - q * t^2 + p * r^2 = 0

由此构造格

Mtrix(ZZ,[1,0,0,r^2],[0,1,0,-t^2],[0,0,1,-t * r],[(leak-tmp)*(t-r)])

tmp很小跑破就好然后会发现就是701

exp:

from sage.all import Matrix, ZZ
from Crypto.Util.number import getPrime
from gmpy2 import *

leak = 52407066630998720273731758848751180003129908965730006096464345923549459617438414126937562326106182853585345246472838907532807236677219886418149723311118855918338387062301958904467478605422673207935942348215552655035846974843053690523359908921489934306458440759517598485452824210146131626776354968352617955744704892906092826257342911994753745093428990023111339468228443855826492957321799005181961
r = 4515378990844403115229704433484433833022655205121974667074150580454343643752811757675793959795169040704894972951300994535151410073321406165168737850534934347874731893617893819762340858239387281147345869706971753
t = 6006929234728180950140499814342609393927042935104177663404375056306287820676434237439964941788093406713118055152122129530273026459457066165368157449726903765601586482566299501860863052052121811433466409338266730837645652741024637475218039773

i=701
# 构造矩阵 P
P = Matrix(ZZ, [
    [1, 0,  0,-(r**2)],
    [0, 1,  0,t**2],
    [0,0,1,t*r],
    [0, 0,  0,(leak-i)*(t-r)],


])

print(P.LLL())


e = 65537
a=10107036304221590140315537220898906759095811790937615837692120715006548746019505046230668048672611600884439559253340540831445253603270525554564368273932957
b=8724435494930578791898201381855906261499199490201926298013879508413402076594452143243163216133538607634050021589040517038447172885148196774972396508093843
c = 30075387915048470863070050827629191303436443913395824732907226821054460652219815718226645166341618100700084925720992983286419204902032573926790086035422540879196867669665497753447829812026327367178333296715527968448124126434045869420695221514125724904849358819864918062875310272203931927234053359553779163755
print(isPrime(a))
print(a.bit_length())
p=a
q=b
d=inverse(e,(p-1)*(q-1))
print(long_to_bytes(pow(c,d,p*q)))

Elementary Chinese

漐訦硁剏鐐遑瓜谠黥噻麚俵曧玫甠媸辌戋黥巹飖煭谨晋瑢鳵鲢醢厨広癕讚鲛徣蟥昉豜雴餭謡爮裹涛僦茺仦蔯餭猳鼣譋壵鐄碝攡驑鐐钾髯蒥躚烗黥犬蝒虇雯緥畋讅瑊肰擁襙蝒寃輲镁饶穩泾姲騂讅噻竊蚇擹坕缀裶糆萾瓬睁問擹鹨巹鷬鵷礟緥巅殱麺铦氋颷黜磘勆镭碾泾赞锽侭瀾晶晗鲠哰齝摛缀爂膼麏褦鸉覴羘剙脡巑黥餅婴広蛟橳佳爮麚踺嘊徖賍鱝広筝鶵曍瓣棾

勾吧题目,中文的音调,然后四进制,1,2,3,4声对应着四进制0,1,2,3,这里面主要知识点可能是python有个pypinyin库hhh

exp:

from pypinyin import lazy_pinyin, Style
from Cryptodome.Util.number import *
print(lazy_pinyin('漐訦硁剏鐐遑瓜谠黥噻麚俵曧玫甠媸辌戋黥巹飖煭谨晋瑢鳵鲢醢厨広癕讚鲛徣蟥昉豜雴餭謡爮裹涛僦茺仦蔯餭猳鼣譋壵鐄碝攡驑鐐钾髯蒥躚烗黥犬蝒虇雯緥畋讅瑊肰擁襙蝒寃輲镁饶穩泾姲騂讅噻竊蚇擹坕缀裶糆萾瓬睁問擹鹨巹鷬鵷礟緥巅殱麺铦氋颷黜磘勆镭碾泾赞锽侭瀾晶晗鲠哰齝摛缀爂膼麏褦鸉覴羘剙脡巑黥餅婴広蛟橳佳爮麚踺嘊徖賍鱝広筝鶵曍瓣棾', style=Style.TONE3))
z=[]
a=lazy_pinyin('漐訦硁剏鐐遑瓜谠黥噻麚俵曧玫甠媸辌戋黥巹飖煭谨晋瑢鳵鲢醢厨広癕讚鲛徣蟥昉豜雴餭謡爮裹涛僦茺仦蔯餭猳鼣譋壵鐄碝攡驑鐐钾髯蒥躚烗黥犬蝒虇雯緥畋讅瑊肰擁襙蝒寃輲镁饶穩泾姲騂讅噻竊蚇擹坕缀裶糆萾瓬睁問擹鹨巹鷬鵷礟緥巅殱麺铦氋颷黜磘勆镭碾泾赞锽侭瀾晶晗鲠哰齝摛缀爂膼麏褦鸉覴羘剙脡巑黥餅婴広蛟橳佳爮麚踺嘊徖賍鱝広筝鶵曍瓣棾', style=Style.TONE3)
for i in a:
    z.append(int(i[-1]))
print(z)
c=''
for i in z:
    i-=1
    c+=str(i)
print(long_to_bytes(int(c,4)))

Who_is_Bob(一血)

task.py

from Cryptodome.Util.number import *

flag = bytes_to_long(b'SRCTF{Kicky_Mu_is_a_beautiful_girl!}')
p = getPrime(512)
q = getPrime(512)
e = 65537
Bob = getRandomInteger(30)
n = p*q
c = pow(flag, e, n)
leak = (p-Bob)*(q-Bob)

print("n = ", n)
print("c = ", c)
print("leak = ", leak)
print(Bob)
'''

n =  83551533637791995343217075093207075888114751056630372530634434127047066670630844940247145420790307521479826874365675804269523298586266076638571271567234671704671269359605807984410204884607410984160816036002212842986210090410991351912353876745392317665760163054027137901527714797966126447118700149990317258891
c =  78309281660733853390608911365864030224721696340767714309397025309727923007988734506317736073773797381428997269420533151442862487934268321488021490923820201215298630613307224160553995648878611049792491221454161735360351132054599297761941011233121670402299191829524451472897533682050463933866813803099215448841
leak =  83551533637791995343217075093207075888114751056630372530634434127047066670630844940247145420790307521479826874365675804269523298586266076638571257216554908695119517636260243773643003707817620018239877623870076598042268179945412307565612034852201182156671007990234097768953570942262083345175668126848614778091      

'''

分析一下式子

leak = (p-Bob)*(q-Bob)

n=p*q

n-leak=Bob(p+q-Bob)

然后因为我们知道Bob是30bit而且这个式子也很明显了,分解一下肯定有Bob,知道Bob啥都解决了,然后放到factorb分解下,然后稍微凑到30bit直接出了,压根不用爆破,就不几个可能的组合。

1base64

试了几下就是952222492**22

exp:

from Cryptodome.Util.number import *
from sympy import *
n =  83551533637791995343217075093207075888114751056630372530634434127047066670630844940247145420790307521479826874365675804269523298586266076638571271567234671704671269359605807984410204884607410984160816036002212842986210090410991351912353876745392317665760163054027137901527714797966126447118700149990317258891
c =  78309281660733853390608911365864030224721696340767714309397025309727923007988734506317736073773797381428997269420533151442862487934268321488021490923820201215298630613307224160553995648878611049792491221454161735360351132054599297761941011233121670402299191829524451472897533682050463933866813803099215448841

leak = 83551533637791995343217075093207075888114751056630372530634434127047066670630844940247145420790307521479826874365675804269523298586266076638571257216554908695119517636260243773643003707817620018239877623870076598042268179945412307565612034852201182156671007990234097768953570942262083345175668126848614778091
# p*q-p*b-q*b+b**2
#b*(p+q-b)=a
a=n-leak
print(a)
e=65537
b=95222249*2**2*2
print(b)
v=a//b+b
print(v)
phi=n-v+1
d=inverse(e,phi)
print(long_to_bytes(pow(c,d,n)))
h=95222249*5
print(h.bit_length())

justez(二血)

task.py

from Cryptodome.Util.number import *

flag = bytes_to_long(b'SRCTF{Kicky_Mu_is_a_beautiful_girl!}')

Ö_0Ovo = getPrime(30)
o_oOvo = getPrime(512)
o_oÖvo = getPrime(512)

phi_n = (o_oOvo-1)*(o_oÖvo-1)
e = pow(Ö_0Ovo, -1, phi_n)
n = o_oOvo * o_oÖvo
c = pow(flag, e, n)

print('n =', n)
print('the_secret =', c)
print('crazy_e =', e)

'''
n = 59447861832652211537262617254184281479829852166925461903662081261289292515576905767937322840660932440029530280492275752616941795671201953079301018060203465429579475061460085183882511211044583402328605487602525290853335843501892756351462762579677498265076859047191958682405236293711382106634923860856875702197
the_secret = 5531240943076956185419252532740075458153435638783876058593858932704838715927408036778103767030441428608060995278765402621496571055270582748608426450102229896581270452441624390124702053351607096961665933344552694074590045043665839297172339145388284294053051066633951096064582407552698859869765532283938542919
crazy_e = 14983946116420718695910350497572468216707179624388443450376271801029353003883222766239928455540840247101746285898514708092585961191614089889673789620455880325382360817355279757931949420354758283821942288319417005937365971171869321539979940627452543996523114498789386921202216406398001675382099523934286309463
'''

题如其名,e很大求d,直接wiener攻击

import ContinuedFractions, Arithmetic, RSAvulnerableKeyGenerator

def hack_RSA(e,n):
    '''
    Finds d knowing (e,n)
    applying the Wiener continued fraction attack
    '''
    frac = ContinuedFractions.rational_to_contfrac(e, n)
    print(frac)
    convergents = ContinuedFractions.convergents_from_contfrac(frac)

    for (k,d) in convergents:

        #check if d is actually the key
        if k!=0 and (e*d-1)%k == 0:
            phi = (e*d-1)//k
            print(phi)
            s = n - phi + 1
            print(s)
            # check if the equation x^2 - s*x + n = 0
            # has integer roots
            discr = s*s - 4*n
            print(discr)
            if(discr>=0):
                t = Arithmetic.is_perfect_square(discr)
                print(t)
                if t!=-1 and (s+t)%2==0:
                    print("Hacked!")
                    return d

# TEST functions

def test_hack_RSA():
    print("Testing Wiener Attack")
    times = 0

    while(times>0):
        e,n,d = RSAvulnerableKeyGenerator.generateKeys(1024)
        print("(e,n) is (", e, ", ", n, ")")
        print("d = ", d)

        hacked_d = hack_RSA(e, n)

        if d == hacked_d:
            print("Hack WORKED!")
        else:
            print("Hack FAILED")

        print("d = ", d, ", hacked_d = ", hacked_d)
        print("-------------------------")
        times -= 1
def RSA():
    n = 59447861832652211537262617254184281479829852166925461903662081261289292515576905767937322840660932440029530280492275752616941795671201953079301018060203465429579475061460085183882511211044583402328605487602525290853335843501892756351462762579677498265076859047191958682405236293711382106634923860856875702197
    e = 14983946116420718695910350497572468216707179624388443450376271801029353003883222766239928455540840247101746285898514708092585961191614089889673789620455880325382360817355279757931949420354758283821942288319417005937365971171869321539979940627452543996523114498789386921202216406398001675382099523934286309463
    d=hack_RSA(e, n)
    print("d=",d)

if __name__ == "__main__":
    #test_is_perfect_square()
    #print("-------------------------")

    RSA()

exp:

from Cryptodome.Util.number import *

n = 59447861832652211537262617254184281479829852166925461903662081261289292515576905767937322840660932440029530280492275752616941795671201953079301018060203465429579475061460085183882511211044583402328605487602525290853335843501892756351462762579677498265076859047191958682405236293711382106634923860856875702197
the_secret = 5531240943076956185419252532740075458153435638783876058593858932704838715927408036778103767030441428608060995278765402621496571055270582748608426450102229896581270452441624390124702053351607096961665933344552694074590045043665839297172339145388284294053051066633951096064582407552698859869765532283938542919
crazy_e = 14983946116420718695910350497572468216707179624388443450376271801029353003883222766239928455540840247101746285898514708092585961191614089889673789620455880325382360817355279757931949420354758283821942288319417005937365971171869321539979940627452543996523114498789386921202216406398001675382099523934286309463
d = 820035527
print(long_to_bytes(pow(the_secret,d,n)))

MiniRsa

task.py

from Cryptodome.Util.number import *
flag=b'12222'

m = bytes_to_long(flag)
p_lists = [159514797898368694161035323666560455482927593628677715144231158683776654589410889361171506677869798913439553045649444471426486937156757512923737117257266219702305948490272092580126724358398210101455463243496876546152497051194626631388993441751102173455821084385690114474413278066052568157824769407231302148231,164502040257301220127513609478443722760842040728679662285075057209725349316105183287859838362165949816685266852802699646133095636456140274119704558163346582955848072668773982942422021335047461181890966859173748565841810779262398379776937252911005772364747785905459772986563538358107206075165619121918994313769,12067354386497776843231760139208442059041398520525521383656281303341787642443750743770398376846740004903417368242663172521036538264680412501426825455937841,110389310327674438994512412189140404012421052386936465666855251542042378560401291600983416103427179353607040781976104766195786129003714052707327680357018140453491041540444836366277074087514554288700445714013715928343998664686187619330641898588950044266264672614012387217326725054091455281834050284619735562549,131168948504860583548757651969440837258361128569062609463069944727375174669195551932348531223057116675553618553732609541174461910935866787631844529969966272525720171277182239591792328433851360949404595252497565480569603077853913064387239844154330498879841647697426578252738103633954750574330627202596111430527]

p = getPrime(1024)
q = getPrime(1024)
e = 65537
n = p * q
c = pow(m, e, n)
print(len(p_lists))
for i in p_lists:
    print(i.bit_length())
    a = (a - i) % n
lists = [n, e, p, q]
for _ in range(len(lists)):
    lists[_] = (lists[_] * getPrime(512)) % n
    print(lists[_],_)
    if lists[_] == 0:
        for i in p_lists:
            lists[_] = (lists[_] - i ) % n

print(f"lists = {lists}")
print(f"c = {c}")

"""
lists = [19034306342361575075980551192712932322561988507704505619003321414454907641123196592043365494891212486631173617896128451305418561737688048967513695641921599895309500342048432076585214210554842683457585293799208643896433433876203082395319550418122273580170345397532087392101148847164139646172755862708188955074277199371835992255416573480806974852069162630676280643957223609636372925574762048260194971667671613092718354976535258179882483301719485865787139872158633048232174665688800039155623876126394585564220031878057948716342605048404401736509363831312390340124864856687925198309333062696436226782334117439595759538940, 735330208874124234708140189708190509639084585785019826186806221072030230392356294636951475819901892456531468208010283670339949843143111658956194009976314737497, 1602301325810709453980853329085731847189218243782953569904960880815334610650572082382219179731782825651268085475709993054918232934300216394178608235615344495673512692541974847829942480171431671140039053286087943307976082240770926172332448900407286986345896064450121772794727122073540966838136136436311798370861018787733155173660981857717532831514899794350952923611979062563752154655540017198341394961130185339410014663001790342283582793527539631430062006919362717, 1490871212681506284400346092290638774030823320747089448463392252548500186740778483192999592745868050668105386341645983368296594796392901704435327383316688779360786838012347149230273755275378107539155514295046237111681414693463240979896636803365784453108997600704264840021949772185282342808188139710222290864584233541392564011658505044015371776137094111399194018534838868815570165823623635735936443128581542320020795321638570854400035174475756508084590680356839283]
c = 15709429897819175308791479593882604989090989118233668933670906164260634913646468935153698184826048828639442348549719275685262082300536207994989372917456166207109082588994547995099508074828988380667184703433477180995225527115780075500780238386354394158860518835289592441774944550726238379621327375074110844317019009627210693272418127362069725045971765997290253778268185565684106141611166424581425058580613958929007167669365312045402281728283642414980252973340376734458355144454456208389560426222274622157045069419138452349507377359387075362422897820554817185082519230849569674743365163066580506210507870872289317520453
"""

分析一下代码

for _ in range(len(lists)):
    lists[_] = (lists[_] * getPrime(512)) % n
    print(lists[_],_)
    if lists[_] == 0:
        for i in p_lists:
            lists[_] = (lists[_] - i ) % n

当_为0的时候lists[0]=n,根据式子lists[0]又被赋值为0,然后满足下面的条件,循环进行lists[] = (lists[] - i ) % n,因为是负数,(-1) mod 3 = 2 ,所以list[0]=(-sum(p_lists))mod n,因为n很大远远大于p_lists的所有值所以,list[0]+sum(p_list)=n,如果不明白的话有疑问的举个例子假设p_lists为(1,2,3)n=0,根据这个式子list[0]=(-sum(p_lists))mod n=4,一步步算,(-1)mod 10 = 9, (9-2)mod 10 = 7, (7-3)mod 10 = 4,等式两边相等即成立。

n= 19034306342361575075980551192712932322561988507704505619003321414454907641123196592043365494891212486631173617896128451305418561737688048967513695641921599895309500342048432076585214210554842683457585293799208643896433433876203082395319550418122273580170345397532087392101148847164139646172755862708188955074842774468824197192248392478110560271583714445989637096516455021799292482709874964442558264034191657852003834210696116604812313915271964493169753757906230275936894286163250033868002163549648231127070023472761238893531817963189169875143920039116155675831544950707882293903547228845180471551901684882787358931857

接下来我们继续当_=1,2,3的时候都不会跳到if条件里面,首先e这个没啥用不用管,一开始看错了以为是乘固定素数呢然后用二元copper把数算出来了发现用的不是一个hhh,其实没这么复杂分析一下就好了,list[2]+kn=xp,因为n很大远远大于p*x所以显而易见k=1,然后gcd((list[2]-n),n)就能找到共享素数p,然后简单的解rsa

下面的代码有很多当时测试的玩意,hhh算是思路历程了

exp:

from Cryptodome.Util.number import *
a1=[(11220077343700874844868397847142690535713941525932218841063921465310133670939412768923683962035215106833261641637705169146283013307644714572778644276917081, 0)]
print(a1[0][0].bit_length())
print(a1[0][0])



e=65537
a=0
lists = [19034306342361575075980551192712932322561988507704505619003321414454907641123196592043365494891212486631173617896128451305418561737688048967513695641921599895309500342048432076585214210554842683457585293799208643896433433876203082395319550418122273580170345397532087392101148847164139646172755862708188955074277199371835992255416573480806974852069162630676280643957223609636372925574762048260194971667671613092718354976535258179882483301719485865787139872158633048232174665688800039155623876126394585564220031878057948716342605048404401736509363831312390340124864856687925198309333062696436226782334117439595759538940, 735330208874124234708140189708190509639084585785019826186806221072030230392356294636951475819901892456531468208010283670339949843143111658956194009976314737497, 1602301325810709453980853329085731847189218243782953569904960880815334610650572082382219179731782825651268085475709993054918232934300216394178608235615344495673512692541974847829942480171431671140039053286087943307976082240770926172332448900407286986345896064450121772794727122073540966838136136436311798370861018787733155173660981857717532831514899794350952923611979062563752154655540017198341394961130185339410014663001790342283582793527539631430062006919362717, 1490871212681506284400346092290638774030823320747089448463392252548500186740778483192999592745868050668105386341645983368296594796392901704435327383316688779360786838012347149230273755275378107539155514295046237111681414693463240979896636803365784453108997600704264840021949772185282342808188139710222290864584233541392564011658505044015371776137094111399194018534838868815570165823623635735936443128581542320020795321638570854400035174475756508084590680356839283]
c = 15709429897819175308791479593882604989090989118233668933670906164260634913646468935153698184826048828639442348549719275685262082300536207994989372917456166207109082588994547995099508074828988380667184703433477180995225527115780075500780238386354394158860518835289592441774944550726238379621327375074110844317019009627210693272418127362069725045971765997290253778268185565684106141611166424581425058580613958929007167669365312045402281728283642414980252973340376734458355144454456208389560426222274622157045069419138452349507377359387075362422897820554817185082519230849569674743365163066580506210507870872289317520453
p_lists = [159514797898368694161035323666560455482927593628677715144231158683776654589410889361171506677869798913439553045649444471426486937156757512923737117257266219702305948490272092580126724358398210101455463243496876546152497051194626631388993441751102173455821084385690114474413278066052568157824769407231302148231,164502040257301220127513609478443722760842040728679662285075057209725349316105183287859838362165949816685266852802699646133095636456140274119704558163346582955848072668773982942422021335047461181890966859173748565841810779262398379776937252911005772364747785905459772986563538358107206075165619121918994313769,12067354386497776843231760139208442059041398520525521383656281303341787642443750743770398376846740004903417368242663172521036538264680412501426825455937841,110389310327674438994512412189140404012421052386936465666855251542042378560401291600983416103427179353607040781976104766195786129003714052707327680357018140453491041540444836366277074087514554288700445714013715928343998664686187619330641898588950044266264672614012387217326725054091455281834050284619735562549,131168948504860583548757651969440837258361128569062609463069944727375174669195551932348531223057116675553618553732609541174461910935866787631844529969966272525720171277182239591792328433851360949404595252497565480569603077853913064387239844154330498879841647697426578252738103633954750574330627202596111430527]
for i in p_lists:
    a =a-i
print(a)
print(lists[0])
print(lists[2].bit_length())
print(len(lists))
print('n=',abs(a)+lists[0])
n=abs(a)+lists[0]
print(GCD(n,abs(a1[0][0]-lists[2])))
print((e*a1[0][0])%n)
print(lists[1])

ll=[(11220077339709635726777525897452256601442845090640906873349438291267951836510978263550168517361014957135496097427771013568460027795775190112227266400634683, 19034306342361575075980551192712932322561988507704505619003321414454907641123196592043365494891212486631173617896128451305418561737688048967513695641921599895309500342048432076585214210554842683457585293799208643896433433876203082395319550418122273580170345397532087392101148847164139646172755862708188955074842774468824197192248392478110560271583714445989637096516455021799292482709874964442558264034191657852003834210696116604812313915271964493169753757906230275936632712325167712393035301580897906279990336760333134809754615492306233562965255957418542620620802490236995839149443443843689078527330529230909439414131)]
print(ll[0][1])
print(ll[0][1]-n)
print(GCD(ll[0][1],abs(ll[0][0]-lists[2])))

print('-----------------')

print((e*a1[0][0])%n)
print(lists[1])
print((e*a1[0][0])%ll[0][1]-lists[1])

print('----------')

x=a1[0][0]
print((n-lists[2])%x)
print(lists[2])
print(n)
print(isPrime(lists[2]))
print(GCD((lists[2]+n),n))
p=170227469070241841763148054562004862447726514900324249635095368549356574670876464940511386246190784798101060303632270705490765525907964764648633720784812193696421939208910670196084625369397193071660922036152737897057315861207525730278430352143859902140137594973703018689254363474185575431432343658362418010719


l=n%p
print(l)
q=n//p
d=inverse(e,(p-1)*(q-1))
print(long_to_bytes(pow(c,d,n)))

leak revenge

task.py

from Crypto.Util.number import *
from secret import flag

m = bytes_to_long(flag)
p = getPrime(512)
q = getPrime(512)
n = p * q
e = getPrime(64)
dp = inverse(e, p - 1)
print(f"n = {n}")
print(f"e = {e}")
print(f"dph = {dp >> 115 <<115}")
print(f"c = {pow(m,e,n)}")

"""
n = 99808598778276923350368946118829564161543192771741967304113142692217693457972421525964898372688505220132024575461230316318177765543298394717753949509523080306599063058808987337840085569950414884529534449801215600413303898393849792345972321407524999652571659221193654323489992751031985715286873931985408130197
e = 9550490518460184889
dph = 4239371595915398923623854132330356869028911602649930928560125044718768467773415379438150660838271530302945945606708178367182566660953659123879375907323904
c = 18661814437233106799783882536249538287931377372915334052147813302071480339780465378376553936510407532657463793836895065758256947765504246845601788497861702555369338586376572381147331367628136147491699775987490116748428373153021965663362046971594255692960097313870139384700219810117047587229718472407783734575
"""

跟那个leak差不多,就是e很大思路就是

e⋅dp≡e⋅d≡1(mod(p−1))
⇔e⋅dp=k(p−1)+1=kp−k+1⇔e⋅dp+k−1≡0(modp)

∵dp<p−1

∴k<e

∴e⋅(dp0<<k+x)+k−1≡0(modp)

但是都说了很大,所以原本的双循环脚本根本跑不完的,但是太大了单循环也不行,所以不管先怎么说先求出dp吧,这里用到二元copper

#Sage
from Crypto.Util.number import *
import itertools
from tqdm import *
def small_roots(f, bounds, m=1, d=None):
    if not d:
        d = f.degree()
    R = f.base_ring()
    N = R.cardinality()
    f /= f.coefficients().pop(0)
    f = f.change_ring(ZZ)
    G = Sequence([], f.parent())
    for i in range(m + 1):
        base = N ^ (m - i) * f ^ i
        for shifts in itertools.product(range(d), repeat=f.nvariables()):
            g = base * prod(map(power, f.variables(), shifts))
            G.append(g)
    B, monomials = G.coefficient_matrix()
    monomials = vector(monomials)
    factors = [monomial(*bounds) for monomial in monomials]
    for i, factor in enumerate(factors):
        B.rescale_col(i, factor)
    B = B.dense_matrix().LLL()
    B = B.change_ring(QQ)
    for i, factor in enumerate(factors):
        B.rescale_col(i, 1 / factor)
    H = Sequence([], f.parent().change_ring(QQ))
    for h in filter(None, B * monomials):
        H.append(h)
        I = H.ideal()
        if I.dimension() == -1:
            H.pop()
        elif I.dimension() == 0:
            roots = []
            for root in I.variety(ring=ZZ):
                root = tuple(R(root[var]) for var in f.variables())
                roots.append(root)
            return roots
    return []
n = 99808598778276923350368946118829564161543192771741967304113142692217693457972421525964898372688505220132024575461230316318177765543298394717753949509523080306599063058808987337840085569950414884529534449801215600413303898393849792345972321407524999652571659221193654323489992751031985715286873931985408130197
e = 9550490518460184889
dp0 = 4239371595915398923623854132330356869028911602649930928560125044718768467773415379438150660838271530302945945606708178367182566660953659123879375907323904
c = 18661814437233106799783882536249538287931377372915334052147813302071480339780465378376553936510407532657463793836895065758256947765504246845601788497861702555369338586376572381147331367628136147491699775987490116748428373153021965663362046971594255692960097313870139384700219810117047587229718472407783734575

R.<m1,m2> = PolynomialRing(Zmod(n))
d = inverse_mod(e, n)

f = dp0 + m1 + (m2 - 1) * d
roots = small_roots(f,bounds=(2^115,2^115), m=2, d=5)
if roots:
    print(roots)

然后得到了x+dp0=dp,后面得到了k,然后就有两种做法:

方法一:

因为这个e实在太大了,当dp较小,e较大的时候枚举 dp因 e⋅dp≡1(mod(p−1))又由费马小定理,对任意 r有 me⋅dp≡m(modp)即 p∣(m^(e⋅dp)−m);又 p∣n,很大概率p=gcd(me⋅dp−m,n)

但是这时候可能会说这个dp也很大,但是其实这个条件主要是看e的大小这里的e太大了,所以直接

p=gcd(m^(e⋅dp)−m,n)

方法二:

前面二元copper把k算出来了,那么e⋅dp+k−1≡0(modp),只有p是未知数,p=gcd((e*dp+k-1),n),然后得到了p然后解决了

exp:

from gmpy2 import *
from Cryptodome.Util.number import long_to_bytes
from tqdm import *

n = 99808598778276923350368946118829564161543192771741967304113142692217693457972421525964898372688505220132024575461230316318177765543298394717753949509523080306599063058808987337840085569950414884529534449801215600413303898393849792345972321407524999652571659221193654323489992751031985715286873931985408130197
e = 9550490518460184889
dp0 = 4239371595915398923623854132330356869028911602649930928560125044718768467773415379438150660838271530302945945606708178367182566660953659123879375907323904
c = 18661814437233106799783882536249538287931377372915334052147813302071480339780465378376553936510407532657463793836895065758256947765504246845601788497861702555369338586376572381147331367628136147491699775987490116748428373153021965663362046971594255692960097313870139384700219810117047587229718472407783734575
dp=dp0+3027685711070484531889028075542545
k= 3406275539771437164
p=(e*dp-1+k)//k
print(p)
print(n%p)
q=n//p
d=invert(e,(p-1)*(q-1))
print(long_to_bytes(pow(c,d,n)))

MISC

工控流量

首先得到一个npz文件查看一下发现和ciscn的差不多,因为output没东西其实就是测信道分析,不过这个需要找的是偏离方差最大的坐标的索引对应的字符

这个你会看到input的大小是128并且为0f组成,然后在index看到是07组成,那么这个就是8*16分析traces,去寻找每一组里面偏离方差最多的索引就好了,不过我之前用的var不知道为什么不行

import numpy as np
f = 'srctf.npz'
d = np.load(f)
t = d['trace']
def ms_diff(trace, group):
    return np.mean(np.square(group - trace), axis=1).mean()
tpg = 16
dt_indices = []
for i in range(0, len(t), tpg):
    g = t[i:i + tpg]
    max_diff_index = np.argmax([ms_diff(trace, g) for trace in g])
    dt_indices.append(i + max_diff_index)
print(dt_indices)
n = [12, 28, 42, 49, 74, 83, 101, 117]#dt_indices

cs = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
mod_40_chars = [cs[num % 16] for num in n]
print(''.join(mod_40_chars))