Skip to main content

hgame2021 密码学 writeup

·520 words·3 mins

HGAME 2021网络攻防大赛crypto wp #

EncryptedChats #

Description

Switch 的病友 Million 来监狱探监…

Challenge Address

Switch: 你好老伙汁
Million: 你好

Switch: 所以为什么这家伙在这里

Liki: 因为我是来记录你们谈话内容的

Million: 好吧
Million: 不过我可以提一个要求吗

Liki: ?

Million: 我们...换一个群聊
Switch: 好啊! 我看看, 就换到加法群聊吧!

Switch: , 帮忙选一个质数 g 
Liki: ??, 12602983924735419868428783329859102652072837431735895060811258460532600319539509800915989811879506790207025505003183121812480524033163157114086741486989697

Million: 这位女士可以劳烦您再为我们选择一个质数 p 
Liki: ???...那就,  30567260905179651419358486099834315837354102714690253338851161207042846254351374572818884286661092938876675032728700590336029243619773064402923830209873155153338320502164587381848849791304214084993139233581072431814555885408821184652544361671134564827265516331283076223247829980225591857643487356406284913560960657053777612115591241983729716542192518684003840806442329098770424504275465756739925434019460351138273272559738332984560095465809481270198689251655392941966835733947437503158486731906649716026200661065054914445245468517406404904444261196826370252359102324767986314473183183059212009545789665906197844518119 , 够大了吗?

Million: 好的, 我选好我的 a , 那么 A = 6407001517522031755461029087358686699246016691953286745456203144289666065160284103094131027888246726980488732095429549592118968601737506427099198442788626223019135982124788211819831979642738635150279126917220901861977041911299607913392143290015904211117118451848822390856596017775995010697100627886929406512483565105588306151304249791558742229557096175320767054998573953728418896571838697779621641522372719890056962681223595931519174265357487072296679757688238385898442549594049002467756836225770565740860731932911280385359763772064721179733418453824127593878917184915316616399071722555609838785743384947882543058635
# A = g ^ a % p = pow(g, a, p)

Switch: okay, b 也选好了, B = 5522084830673448802472379641008428434072040852768290130448235845195771339187395942646105104638930576247008845820145438300060808178610210847444428530002142556272450436372497461222761977462182452947513887074829637667167313239798703720635138224358712513217604569884276513251617003838008296082768599917178457307640326380587295666291524388123169244965414927588882003753247085026455845320527874258783530744522455308596065597902210653744845305271468086224187208396213207085588031362747352905905343508092625379341493584570041786625506585600322965052668481899375651376670219908567608009443985857358126335247278232020255467723
# B = g ^ b % p = pow(g, b, p)

Liki: ????

Million: {'iv': 'd3811beb5cd2a4e1e778207ab541082b', 'encrypted_flag': '059e9c216bcc14e5d6901bcf651bee361d9fe42f225bc0539935671926e6c092'}
Switch: {'iv': 'b4259ed79d050dabc7eab0c77590a6d0', 'encrypted_flag': 'af3fe410a6927cc227051f587a76132d668187e0de5ebf0608598a870a4bbc89'}

Million: 再见伙汁
Switch: 再见

Liki: ?????

加法群的幂是乘法

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Util.number import long_to_bytes
import hashlib
import gmpy2 as gp
from binascii import a2b_hex
A = 6407001517522031755461029087358686699246016691953286745456203144289666065160284103094131027888246726980488732095429549592118968601737506427099198442788626223019135982124788211819831979642738635150279126917220901861977041911299607913392143290015904211117118451848822390856596017775995010697100627886929406512483565105588306151304249791558742229557096175320767054998573953728418896571838697779621641522372719890056962681223595931519174265357487072296679757688238385898442549594049002467756836225770565740860731932911280385359763772064721179733418453824127593878917184915316616399071722555609838785743384947882543058635
B = 5522084830673448802472379641008428434072040852768290130448235845195771339187395942646105104638930576247008845820145438300060808178610210847444428530002142556272450436372497461222761977462182452947513887074829637667167313239798703720635138224358712513217604569884276513251617003838008296082768599917178457307640326380587295666291524388123169244965414927588882003753247085026455845320527874258783530744522455308596065597902210653744845305271468086224187208396213207085588031362747352905905343508092625379341493584570041786625506585600322965052668481899375651376670219908567608009443985857358126335247278232020255467723
p = 30567260905179651419358486099834315837354102714690253338851161207042846254351374572818884286661092938876675032728700590336029243619773064402923830209873155153338320502164587381848849791304214084993139233581072431814555885408821184652544361671134564827265516331283076223247829980225591857643487356406284913560960657053777612115591241983729716542192518684003840806442329098770424504275465756739925434019460351138273272559738332984560095465809481270198689251655392941966835733947437503158486731906649716026200661065054914445245468517406404904444261196826370252359102324767986314473183183059212009545789665906197844518119
g = 12602983924735419868428783329859102652072837431735895060811258460532600319539509800915989811879506790207025505003183121812480524033163157114086741486989697
x1 = gp.invert(g,p)*A%p
x2 = gp.invert(g,p)*B%p
key1 = x1*x2*g%p
shared_secret = key1
sha1 = hashlib.sha1()
sha1.update(str(shared_secret).encode('ascii'))
key = sha1.digest()[:16]
iv1 = a2b_hex('d3811beb5cd2a4e1e778207ab541082b')
iv2= a2b_hex('b4259ed79d050dabc7eab0c77590a6d0')
data1 = a2b_hex('059e9c216bcc14e5d6901bcf651bee361d9fe42f225bc0539935671926e6c092')
data2 = a2b_hex('af3fe410a6927cc227051f587a76132d668187e0de5ebf0608598a870a4bbc89')
decrypt1 = AES.new(key,AES.MODE_CBC,iv1)
decrypt2 = AES.new(key,AES.MODE_CBC,iv2)
flag1 = decrypt1.decrypt(data1)
flag2 = decrypt2.decrypt(data2)
print(flag1,flag2)
# hgame{AdD!tiVe-Gr0up~DH_K3y+eXch@nge^4nd=A3S}

夺宝大冒险2 #

lfsr基础

from icecream import *
from pwn import *

# nc  30607
sh = remote('182.92.108.71', 30607)
ans = []
for i in range(10):
    buf = sh.recvuntil('guess:')
    sh.sendline('-1')
    sh.recvuntil('Wrong, the secret is ')
    buf = int(sh.recvuntil('\n')[:-1])
    # print(buf)
    ans.append(buf)
print(ans)
bstr = ''
for i in ans:
    ic(i, bin(i)[2:].rjust(4, '0'))
    bstr += bin(i)[2:].rjust(4, '0')
s = bstr
ic(bstr,len(s))

init = int(bstr[:40],2)
ic(init)
class LXFIQNN():
    def __init__(self, init, mask, length):
        self.init = init
        self.mask = mask
        self.lengthmask = 2**(length+1)-1

    def next(self):
        nextdata = (self.init << 1) & self.lengthmask
        i = self.init & self.mask & self.lengthmask
        output = 0
        while i != 0:
            output ^= (i & 1)
            i = i >> 1
        nextdata ^= output
        self.init = nextdata
        return output

    def random(self, nbit):
        output = 0
        for _ in range(nbit):
            output <<= 1
            output |= self.next()
        return output

prng = LXFIQNN(init, 0b1011001010001010000100001000111011110101, 40)

for i in range(81):
    secret = prng.random(4)
    sh.sendline(str(secret))
    print(sh.recvuntil('guess'))
sh.interactive()
#hgame{lfsr_121a111y^use-in&crypto}

夺宝大冒险1 #

保证$a<c,b<c,a,b,c互质$,task1,2 很容易求出来

task3用选择明文是思想先把a,b消掉,对tmp1,tmp2取最大公因数,平均跑50次由一组适合我们这个算法的a,b,c

from icecream import *

from libnum import *
from pwn import *

# print(sh.recvline())

def t1(sh):
    s = sh.recvline().decode()
    ic(s)
    s =s.split(',')
    print(((s[0][1:]), (s[1][:-1])))
    a,c = (int(s[0][1:]),int(s[1][:-2]))
    m1 = int(sh.recvline())
    m2 = int(sh.recvline())
    b = (m2-a*m1)%c
    # ic(b,int(sh.recvline()))
    # ic(b)
    sh.sendline(str(b))

def t2(sh):

    c = int(sh.recvline())
    m = [0]+[int(sh.recvline()) for i in range(3)]
    a = (m[2]-m[3])*(invmod(m[1]-m[2],c))
    a %= c
    b = m[2]-a*m[1]
    b %= c
    # ic(a, sh.recvline())
    # ic(b, sh.recvline())
    # ic(a,b)
    sh.sendline(str(a))
    sh.sendline(str(b))

def t3(sh):
    m = [123]+[int(sh.recvline()) for i in range(7)]
    ic(m, len(m))

    # tmp1 = -(m[7]-m[6])*(m[5]-m[4])-(m[6]-m[5])*(m[6]-m[5])
    tmp1 = abs((m[4]-m[3])*(m[2]-m[1])-(m[3]-m[2])*(m[3]-m[2]))
    tmp2 = abs((m[7]-m[6])*(m[5]-m[4])-(m[6]-m[5])*(m[6]-m[5]))

    ic(tmp1, tmp2)
    tmp = gcd(tmp1, tmp2)
    # ic(tmp, int(sh.recvline()))
    # ic(tmp)
    sh.sendline(str(tmp))
    # print(tmp1 % .cgen, tmp2 % gen.c)

# nc 182.92.108.71 30641
def main():
    tot =0
    while 1:
        tot+=1
        try:
            sh = remote('182.92.108.71', 30641)
            t1(sh)
            t2(sh)
            t3(sh)
            buf = (sh.recvall())
            print(buf)
            if b'win' in buf:
                print(f'try  {tot} times')
                break
        except:
            pass

        

if __name__ == '__main__':
    main()
    
        
'''
[+] Receiving all data: Done (56B)
[*] Closed connection to 182.92.108.71 port 30641
b'win\nhgame{Cracking^prng_Linear)Congruential&Generators}\n'
try  46 times
'''