原文地址
https://4xwi11.github.io/posts/a1174b3b/
隴原戰"疫"2021網路安全大賽
Crypto
mostlycommon
共模再開個方
import gmpy2
from Crypto.Util.number import *
e1 = 65536 // 2
e2 = 270270 // 2
n = 122031686138696619599914690767764286094562842112088225311503826014006886039069083192974599712685027825111684852235230039182216245029714786480541087105081895339251403738703369399551593882931896392500832061070414483233029067117410952499655482160104027730462740497347212752269589526267504100262707367020244613503
c1 = 39449016403735405892343507200740098477581039605979603484774347714381635211925585924812727991400278031892391996192354880233130336052873275920425836986816735715003772614138146640312241166362203750473990403841789871473337067450727600486330723461100602952736232306602481565348834811292749547240619400084712149673
c2 = 43941404835820273964142098782061043522125350280729366116311943171108689108114444447295511969090107129530187119024651382804933594308335681000311125969011096172605146903018110328309963467134604392943061014968838406604211996322468276744714063735786505249416708394394169324315945145477883438003569372460172268277
get_tuple = gmpy2.gcdext(e1, e2) # return (g,s,t) g = gcd(e1,e2) and g = e1*s + e2*t
r = -get_tuple[1]
s = get_tuple[2]
a = gmpy2.powmod(gmpy2.invert(c1, n), r, n)
b = gmpy2.powmod(c2, s, n)
m = gmpy2.f_mod(gmpy2.mul(a,b),n)
print(gmpy2.iroot(m, 2))
print(long_to_bytes(gmpy2.iroot(m, 2)[0]))
easytask(recuring)
差點以為是和省賽NTRU那樣的題目(其實就是
雖然r是完全可以爆破的,但是要3個小時才能跑完(再買個記憶體條
所以可還行,emmmm,寫了個腳本但比賽中沒有出(做不進去,組里還一直催專案,我tm,到底知不知道實驗室是什么撐起來的,還非得比賽的時候催,瞬間不想做了
有能力出,但沒出,總結一下幾點
- 遍歷所有的
r不慢,但是不精明的操作(在回圈中生成AES解密)會導致空間復雜度很大,導致程式非常慢 - 賽后問尚師傅,其實真正的
r開頭是-3 -2(應該是刻意為之),所以盡管空間復雜度很大,但是比賽中還是遍歷到了,判斷機制寫得不對(馬虎,還有別的原因 - 綜上,判斷機制不是非得是
flag.starswith(b'flag'),求出來的m很有特征的;可以學尚師傅,先自己定個r,然后用腳本跑一遍(處理大資料,陽哥的樣本方法 - 比賽中先算出
r保存在記憶體里,再開始遍歷
調整后的腳本快多了
#!/usr/bin/env sage
# -*- coding: utf-8 -*-
import hashlib
from Crypto.Cipher import AES
import re
from itertools import product
c = '1070260d8986d5e3c4b7e672a6f1ef2c185c7fff682f99cc4a8e49cfce168aa0'
c = bytes.fromhex(c)
ct_e = '[151991736758354 115130361237591 58905390613532 130965235357066 74614897867998 48099459442369 45894485782943 7933340009592 25794185638]'
ct_W = '''[-10150241248 -11679953514 -8802490385 -12260198788 -10290571893 -334269043 -11669932300 -2158827458 -7021995]
[ 52255960212 48054224859 28230779201 43264260760 20836572799 8191198018 14000400181 4370731005 14251110]
[ 2274129180 -1678741826 -1009050115 1858488045 978763435 4717368685 -561197285 -1999440633 -6540190]
[ 45454841384 34351838833 19058600591 39744104894 21481706222 14785555279 13193105539 2306952916 7501297]
[-16804706629 -13041485360 -8292982763 -16801260566 -9211427035 -4808377155 -6530124040 -2572433293 -8393737]
[ 28223439540 19293284310 5217202426 27179839904 23182044384 10788207024 18495479452 4007452688 13046387]
[ 968256091 -1507028552 1677187853 8685590653 9696793863 2942265602 10534454095 2668834317 8694828]
[ 33556338459 26577210571 16558795385 28327066095 10684900266 9113388576 2446282316 -173705548 -577070]
[ 35404775180 32321129676 15071970630 24947264815 14402999486 5857384379 10620159241 2408185012 7841686]'''
e = []
for i in re.findall(r"\d+", ct_e):
e.append(int(i))
e = matrix(e)
W = [[0 for _ in range(9)] for j in range(9)]
ct_W = re.findall(r'-?\d+', ct_W)
for i in range(len(ct_W)):
W[i // 9][i % 9] = int(ct_W[i])
W = matrix(W)
inv_W = W.inverse()
table = [_ for _ in range(-3, 4)]
r = product(table, repeat=9)
for ri in r:
rx = matrix(ri)
m = (e - rx) * inv_W
if 0 < m[0][0] < 1024:
M = list(m[0])
key = hashlib.sha256(str(M).encode()).digest()
cipher = AES.new(key, AES.MODE_ECB)
flag = cipher.decrypt(c)
if flag.startswith(b'flag') or flag.startswith(b'SET'):
print(r)
print(flag)
break
讓我看看之前的腳本為啥不能出
我們自己寫一個r,就[-3,-3,-3,-3,-3,-3]吧,然后走一遍,我知道了,是這個問題
M = list(m[0])
sage矩陣轉串列的時候要多取一個,差不多是這么一個意思吧

寄
Civet cat for Prince(recuring)
代碼小饒
目的,已知IV,可以獲得輸入name+'a_cat_permission'的密文,可以有最多兩次自己輸入IV和密文進行解密,求輸入name+'Princepermission'的密文,注意最后這里我們可以自己定義IV
重點是最后一句話,這就是利用點,復現的時候我一個上午都沒注意到,以為是要用它的IV;然后下午看到,那就比較簡單了
一個小思路,假設獲取的name_cipher
c
c
c分成前半段
c
1
,
c
2
c_1,\ c_2
c1?, c2?,密文構造成
c
1
⊕
a
_
c
a
t
_
p
e
r
m
i
s
s
i
o
n
⊕
P
r
i
n
c
e
p
e
r
m
i
s
s
i
o
n
+
c
2
c_1\oplus a\_cat\_permission\ \oplus Princepermission + c_2
c1?⊕a_cat_permission ⊕Princepermission+c2?
這樣第二段密文解密出來就是Princepermission
然后利用一次解密的機會,將上面這個密文的前半段和系統的IV丟進去,得到的結果記為
m
1
m_1
m1?,求
m
1
⊕
I
V
⊕
P
r
i
n
c
e
p
e
r
m
i
s
s
i
o
n
m_1\oplus IV \oplus Princepermission
m1?⊕IV⊕Princepermission
這樣解密出來的第一段就是Princepermission,其實name無所謂什么都可以
到此這道題已經被我們攻破,可能有點繞,但是海星
寫了個jo本,源檔案改過了?打本地可以,遠程有時候可以,可能是有些結果有換行
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import hashlib
from pwn import *
from itertools import product
import string
context.log_level = 'debug'
table = string.ascii_letters + string.digits
class Solve:
def __init__(self):
# self.sh = remote('node4.buuoj.cn', 28743)
self.sh = remote('node4.buuoj.cn', 29129)
self._Princepermission = b'Princepermission'
self._a_cat_permission = b'a_cat_permission'
self.iv = b''
self.cipher_name = b''
self.payload_cipher = b''
self.payload_iv = b''
def proof_of_work(self):
"""
[+] sha256(XXXX+Q3kqSv2c) == e9ded46c9d0dbcf14d8c36852678fe59daec43b1025c282738a81e7ea9f395f9
[+] Give Me XXXX :
"""
proof = self.sh.recvline()
tail = proof[16:24].decode()
HASH = proof[29:93].decode()
for i in product(table, repeat=4):
head = ''.join(i)
t = hashlib.sha256((head + tail).encode()).hexdigest()
if t == HASH:
self.sh.recvuntil(b'[+] Give Me XXXX :')
self.sh.sendline(head.encode())
break
def solve_BANNER(self, _name):
self.sh.sendlineafter(b'[-]', b'1')
self.sh.sendlineafter(b'[-]', _name)
self.sh.recvline()
self.sh.recvline()
self.sh.recvuntil(b'Miao~ ')
self.iv = self.sh.recvuntil(b"I'm a")[:-6]
print(len(self.iv))
def solve_NAME(self):
self.sh.sendlineafter(b'[-]', b'1')
self.sh.recvuntil(b'Permission:')
self.cipher_name = self.sh.recvuntil(b"I'm a")[:-6]
self.cipher_name = self.cipher_name
self.payload_cipher = xor(xor(self.cipher_name[:16], self._a_cat_permission),
self._Princepermission) + self.cipher_name[16:32]
def solve_Princepermission(self):
self.sh.sendlineafter(b'[-]', b'2')
self.sh.sendlineafter(b'[-]', self.payload_cipher[:16])
self.sh.sendlineafter(b'[-]', self.iv)
self.sh.recvuntil(b'The message is ')
self.payload_iv = xor(xor(self.sh.recvuntil(b'1.getpermission')[:16], self.iv), self._Princepermission)
def solve_flag(self):
self.sh.sendlineafter(b'[-]', self.payload_cipher)
self.sh.sendlineafter(b'[-]', self.payload_iv)
self.sh.recvuntil(b'The prince asked me to tell you this:\n')
flag = self.sh.recvline()
print(flag)
def solve(self):
self.proof_of_work()
self.solve_BANNER(self._Princepermission)
# get cipher_name
# chance ====> 2
self.solve_NAME()
# get cipher_Princepermission
# chance ====> 1
self.solve_Princepermission()
# chance ====> 0
self.sh.sendlineafter(b'[-]', b'3')
# get flag
self.solve_flag()
if __name__ == '__main__':
solution = Solve()
solution.solve()

好一個貍貓換太子
Re
EasyRe
反編譯失敗,查了好久,嘗試平衡堆疊,手動修無果,然后想起一開始看到一串32位的字串沒用到,隨便搜了下竟然是hello world的md5,抱著試一試的心態丟進去就對了

xs
還是太容易被別人影響了
努力很廉價,也很昂貴,對自己來說廉價,對別人來說昂貴
你在樓上看到的風景,我選擇貼地接近
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/354511.html
標籤:其他
上一篇:kali2021設定中文
下一篇:Locally Differential Private Frequency Estimation with Consistency: LDP的主流后處理演算法
