1. 程式人生 > 實用技巧 >紀實:校內線上訓練——Crypto

紀實:校內線上訓練——Crypto

近日,學校俱樂部舉辦了有關網安的比賽,不去不知道,真的是一句“我好菜”走天下……在此就是記錄一下那些我做過的和沒做上的題,其實看了一下別人的wp總是就差臨門一腳,心情很糟 v_v

接下來會按照順序呢會連續記錄PWN、REVERSE、MISC、WEB、CRYPTO的……

1.babyRSA

n = 2175688405733541703870452086626738401792220260185622845647

e = 0x10001

c = 909189959980475048848571460773306576585339198658788147448

  這道題真的是重新整理我對RSA的認知:

  對於這道題,當你分解n時會發現分解出三個質數,我當時十分詫異,因為從來沒聽說過RSA的p、q之外還能有其他引數,同時如果當做一個p×q、k的話存在一個合數是不是會出問題,但是後來通過查詢資料,我才明白

  費馬小定理是對於每一個質數都存在正確性的,所以說n分解出來的質數的個數不會影響最終的解碼過程

  其餘部分就比較簡單,直接按照正常過程走即可

2.Random

main函式原始碼:

import random
import socketserver
from Crypto.Util import number
import
os flag = os.environ.get('flag', 'flag{test_flag}') class EncryptHandler(socketserver.BaseRequestHandler): p = 1543 iv = 792 def encrypt(self, m: list): self.r1.seed(self.r1_key) self.r2.seed(self.r2_key) res = [] w = self.iv for i in m: w
= ((i + w + self.r1.randrange(0, self.p)) % self.p) * self.r2.randrange(0, self.p) % self.p res.append(w) w ^= self.random_key return res def setup(self): self.random_key = random.randrange(0, self.p) self.r1_key = random.randrange(0, self.p) self.r2_key = random.randrange(0, self.p) self.r1 = random.Random() self.r2 = random.Random() self.enc_flag = self.encrypt(list(flag.encode())) def handle(self): hello_msg = ('Hello, here gives you the encrypted Flag:\n' '{}\n' 'You can type any msg, and I will give you the encrypted message\n' ).format(self.enc_flag) self.request.sendall(hello_msg.encode()) while True: msg = self.request.recv(1024)[:-1] self.request.sendall((str(self.encrypt(msg)) + '\n').encode()) if __name__ == '__main__': HOST, PORT = with socketserver.ThreadingTCPServer((HOST, PORT), EncryptHandler) as server: try: server.serve_forever() except KeyboardInterrupt: server.shutdown()

  這道題程式碼挺複雜,但是看起來還是比較方便的。整個流程就是通過隨機數一次加密一個flag,但是連線沒有斷,可以持續傳送,這樣就造成了漏洞。我們可以像揹包演算法一樣(?演算法誤入?),但是這裡比較暴力,一個一個試過去即可。

  上一發我自己的payload:

from pwn import *
import ast

io=remote()
#這裡是為了方便後面byte列表直接轉換成列表
io.recvuntil("\n")
byt=io.recvuntil("]")
# print(byt)
io.recv()
#這裡是將byte型別的列表轉換成List
rule=ast.literal_eval(byt.decode())
print (rule)
stmp="1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz|{},:;.? !@_-+=#$%^&*()<>~`/\\"+'\''+'\"'

length=len(rule)


test=""
for i in range(length):
    print(i)
    print(test)
    for j in stmp:
        #print(j)
        io.sendline(test+j)
        res=io.recv()[:-1].decode()
        res=ast.literal_eval(res)
        #print(res)
        if res[i]==rule[i]:
            test+=j
            break;

print(test)

3.Small e

main函式原始碼:

from flag import flag
from Crypto.Util import number
import os
assert type(flag) == str

flag_b = flag.encode() + os.urandom(128 - len(flag))
p = [number.getPrime(1024) for _ in range(3)]
q = [number.getPrime(1024) for _ in range(3)]
n = [_p * _q for _p, _q in zip(p, q)]

e = 3
m = number.bytes_to_long(flag_b)
for i in range(3):
    print("n{} = {}".format(i, n[i]))
    print("c{} = {}".format(i, pow(m, e, n[i])))

Output.txt內容:

n0 = 16067817932594307041570490664780805848472742222521209486359183294876659529608435557600537260250449433611595173684925374508467672404417859479495004093579610726032262914323802262015761804257474778421075371915604733039622965481151880946821099347099589181944483948769906556017986079391359211585782596464924468208449010284942962635113163737362978946256184113197172628780615797285233916435176242221439390878162794629364484926505774613228229646458189210171950867198879934364120504046273177961083687027937189811732509344365844834160229805810205081446686611488115226014344875552419979932806334691942178914927653481984541110621
c0 = 9879971463914625690975893241580185387981496369356734957012721513373144938753569045503323744985869516225432489622517950293366904764152664636972215860898639778481845669980292323448545868723176321988532040102362409575435129737188286227622375002577654117407187235639039788403421568330907783489740293783760374579674272228953702822209345735718037784007905107507640441789566148023418182843850856028272425280660185409774791229291736804113219546032069271224441643592470352853688723172019556711071350797050854277490132448056258928350601925843959503438270798312618141538795176843674864017991973083157087900179066637653967471786
n1 = 27220804436805864442162182442813759263069372128468811270228757759122242102746634331274204813645700606025198464757315069476396636457109385709010309093761124250367793217269514777894950749932026790104944920542415154470272710654996775902535083921322900858510081080526361203971974235685839596700898966986819478871421472486198215667112358892381840624555494963218129513959117765033488219148477371667129956523403726492811804971592929874287476692563269065787601147950636445646208059251015601569921025370871805357871922113088791024382926047840273911791193990034677955545643860434985638900984527560552087922124397003230357748287
c1 = 18601174471639330838673755997627097179717053665843260588739160926694895023115719989743218032177933064024790567417281962648968287556842258818888225805040849173826497707326525590383774570277339562504216146208571367319040674013938991326596042075188486353554578994481344994910413567203491400010042812019323116569805264327599429345975064505984904064402357370098622911816024581171930600566133580491190247014980742239289588062485016239992005485018607729737084787372336151888759198583123570341162243303928994460199822642294565067160393816192370390199699022295478284192467413238687379911409873590966380239175755869062503249758
n2 = 18003911632122599813425550392025295318460144538002420546091473342504066065913374478380723966510863927323450160422323963085439934919821408030000597030220444017446677275520530600602313223716913843706289020789546341254298514327568202682323289952838243830866298465249322960573348784191060837060844553425424656343221015762038900638842760791476620770787585512880263777811650363550291113188707834451876652168342500756621692207745249699478983220317963165032407100517970067554347460807373078643124640438035329791669756566825583763144347915561928759654089817337965531158175165510730703911869587267266225122572337924741504872421
c2 = 16232129131608810282413937706144487240626338624250308577834225698445782468881682329646696899789457330498386668165599055270602304521900866238477820450745745574235835329025428831975135564432471301944638869445512637388111199953848153394755434332731325017811903037131194504517921570433491911858368670794242170207150194844396867824699460595352243616284981999437646934978307049377044110514736105768616893202608779347282837560546402961227548577594166063494153158225233408919063945070416486278018607780042733335959208255707942063870095648981102997015240784176457028384300754675188591655968245197618705494443537255712721037015

  這道題就是典型的中國剩餘定理的應用啦。由於ci≡m^e(modni),我們直接可以套公式(x1*y1*M/n1+x2*y2*M/n2+x3*y+*M/n3+……x=ci,y≡1(mod ni),M=n1*n2*n3*……),即可得到flag,這裡直接上我的payload:

import gmpy2

e=3
n = [16067817932594307041570490664780805848472742222521209486359183294876659529608435557600537260250449433611595173684925374508467672404417859479495004093579610726032262914323802262015761804257474778421075371915604733039622965481151880946821099347099589181944483948769906556017986079391359211585782596464924468208449010284942962635113163737362978946256184113197172628780615797285233916435176242221439390878162794629364484926505774613228229646458189210171950867198879934364120504046273177961083687027937189811732509344365844834160229805810205081446686611488115226014344875552419979932806334691942178914927653481984541110621,
27220804436805864442162182442813759263069372128468811270228757759122242102746634331274204813645700606025198464757315069476396636457109385709010309093761124250367793217269514777894950749932026790104944920542415154470272710654996775902535083921322900858510081080526361203971974235685839596700898966986819478871421472486198215667112358892381840624555494963218129513959117765033488219148477371667129956523403726492811804971592929874287476692563269065787601147950636445646208059251015601569921025370871805357871922113088791024382926047840273911791193990034677955545643860434985638900984527560552087922124397003230357748287,
18003911632122599813425550392025295318460144538002420546091473342504066065913374478380723966510863927323450160422323963085439934919821408030000597030220444017446677275520530600602313223716913843706289020789546341254298514327568202682323289952838243830866298465249322960573348784191060837060844553425424656343221015762038900638842760791476620770787585512880263777811650363550291113188707834451876652168342500756621692207745249699478983220317963165032407100517970067554347460807373078643124640438035329791669756566825583763144347915561928759654089817337965531158175165510730703911869587267266225122572337924741504872421]
c = [9879971463914625690975893241580185387981496369356734957012721513373144938753569045503323744985869516225432489622517950293366904764152664636972215860898639778481845669980292323448545868723176321988532040102362409575435129737188286227622375002577654117407187235639039788403421568330907783489740293783760374579674272228953702822209345735718037784007905107507640441789566148023418182843850856028272425280660185409774791229291736804113219546032069271224441643592470352853688723172019556711071350797050854277490132448056258928350601925843959503438270798312618141538795176843674864017991973083157087900179066637653967471786,
18601174471639330838673755997627097179717053665843260588739160926694895023115719989743218032177933064024790567417281962648968287556842258818888225805040849173826497707326525590383774570277339562504216146208571367319040674013938991326596042075188486353554578994481344994910413567203491400010042812019323116569805264327599429345975064505984904064402357370098622911816024581171930600566133580491190247014980742239289588062485016239992005485018607729737084787372336151888759198583123570341162243303928994460199822642294565067160393816192370390199699022295478284192467413238687379911409873590966380239175755869062503249758,
16232129131608810282413937706144487240626338624250308577834225698445782468881682329646696899789457330498386668165599055270602304521900866238477820450745745574235835329025428831975135564432471301944638869445512637388111199953848153394755434332731325017811903037131194504517921570433491911858368670794242170207150194844396867824699460595352243616284981999437646934978307049377044110514736105768616893202608779347282837560546402961227548577594166063494153158225233408919063945070416486278018607780042733335959208255707942063870095648981102997015240784176457028384300754675188591655968245197618705494443537255712721037015]

N=n[0]*n[1]*n[2]
res=0

for i in range(3):
    m=N//n[i]
    d,r,s=gmpy2.gcdext(n[i],m)
    #d=r*n[i]+s*m
    res+=c[i]*s*m
x=res%N
n=N
m=gmpy2.iroot(gmpy2.mpz(x), e)
print(m)

4.babyDES

main函式程式碼:

import os
import base64
from Crypto.Util import number, strxor
from flag import flag

assert(len(flag) == 34)

def gen_key():
    return [os.urandom(17) for _ in range(8)]

def rnd(x: bytes, k: bytes):
    assert(len(x) == 34)
    l = x[:17]
    r = x[17:]
    _r = l
    _l = strxor.strxor(strxor.strxor(r, k), l)
    return _l + _r

def enc(x: bytes, keys):
    res = x
    for i in range(8):
        res = rnd(res, keys[i])
    return res

if __name__ == '__main__':
    test = os.urandom(34)
    keys = gen_key()
    enc_test = enc(test, keys)
    enc_flag = enc(flag.encode(), keys)
    print(base64.b64encode(test).decode())
    print(base64.b64encode(enc_test).decode())
    print(base64.b64encode(enc_flag).decode())

output.txt內容:

w4C2TsB73uEIwk14cvQMP9m/nakb+Wh1ZvF70o6BZuHy9w==
5+AplczBBKDQCWgudMjj8sLxU1K5mvFS7JS9xg1QdFxiJg==
L03S5WraHoNkN//llN17IUicEn7gh9elR1s1L9KduKa9AQ==

  我們得到了test的內容以及加密過的test內容和加密過的flag內容。我們只需要得到key的內容從而解密flag內容。

  通過計算可以得到l8、r8和l、r的直接關係,因此我們就能求出結果。

  這道題當時覺得太麻煩就沒做,所以上一發官方payload:

  

import base64
from Crypto.Util import number, strxor

def getK(a,enc_a):
    l=a[:17]
    r=a[17:]
    _l=enc_a[:17]
    _r=enc_a[17:]
    kl=strxor.strxor(strxor.strxor(r,l),_r)
    kr=strxor.strxor(_l,r)
    return [kl,kr]

def dec(enc_a,kl,kr):
    _l=enc_a[:17]
    _r=enc_a[17:]
    r=strxor.strxor(_l,kr)
    l=strxor.strxor(strxor.strxor(_r,kl),r)
    return l+r        

test="w4C2TsB73uEIwk14cvQMP9m/nakb+Wh1ZvF70o6BZuHy9w=="
enc_test="5+AplczBBKDQCWgudMjj8sLxU1K5mvFS7JS9xg1QdFxiJg=="
enc_flag="L03S5WraHoNkN//llN17IUicEn7gh9elR1s1L9KduKa9AQ=="
test=base64.b64decode(test.encode())
enc_test=base64.b64decode(enc_test.encode())
enc_flag=base64.b64decode(enc_flag.encode())


kkey=[]
kkey=getK(test,enc_test)
fle=dec(enc_flag,kkey[0],kkey[1])
print(fle)

5.babyHash

main函式程式碼:

import socketserver
from Crypto.Util import number
import itertools
from flag import flag 

class HashHandler(socketserver.BaseRequestHandler):

    iv =  b'"[\xc3\x02D( \xf1'

    def __padding(self, x: bytes):
        if len(x) % 8:
            pad_len = 8 - len(x) % 8
            return x + bytes([pad_len] * pad_len)
        else:
            return x

    def __compress(self, x: bytes):
        num = number.bytes_to_long(x)
        r = pow(num, 361268568442343347925, 664882992644331722007361840306123225067) & (2 ** 128 - 1)
        m = int(bin(r)[2::2], 2)
        s = m ^ (num >> 64)
        return number.long_to_bytes(s)

    def md(self, m: bytes):
        m = self.__padding(m)
        h = self.iv
        for i in range(0, len(m), 8):
            subm = m[i: i+8]
            h = self.__compress(h + subm)
        return h

    def handle(self):
        self.request.sendall(b'input a: ')
        a = self.request.recv(1024)[:-1]
        self.request.sendall(b'input b: ')
        b = self.request.recv(1024)[:-1]
        if a != b and self.md(a) == self.md(b):
            self.request.sendall((flag + '\n').encode())
        else:
            self.request.sendall(b'nononono')

if __name__ == '__main__':
    HOST, PORT = '0.0.0.0', 12002
    with socketserver.ThreadingTCPServer((HOST, PORT), HashHandler) as server:
        server.serve_forever()
            

  程式碼整體就是收到對方發出的兩組byte,判斷二者是否相同,在進行MD5加密:現將兩組64位平衡,之後在進行MD5操作。程式碼很難,如果從加密處攻入反正我是不知道可不可以qwq……其實程式碼中補全8位那裡其實挺怪的,從這裡可以作為突破口:  

1234567”    #a
“1234567\x01”    #b

  這樣就可以滿足所有要求!