picoCTF 2025 Writeup - Cryptography
Shuffle - 50pt
Description
A mysterious file has been found, with its contents shuffled in an unusual pattern. Can you reverse the process and uncover the hidden flag? The adventurer who decodes this puzzle must carefully read between the lines to reconstruct the flag. Characters at indices i, i+1, i+2 have been rearranged to become i+2, i, i+1.Download the shuffled flag from here.
Hint
- The flag has been reversed and shuffled in groups of 3 characters.
- Look at the flag and try to reverse it step by step.
ChatGPTに解かせた。
以下の文字列の(i+2,i,i+1)番目の文字を(i,i+1,i+2)番目にシャッフルし、その後逆順に並び替えてもらえますか?
af}23fab2gv_f_ldetbmlrc8{FsCoTipc
picoCTF{scr8mbledt_flvg_ba232ffa}
hashcrack - 100pt
Description
A company stored a secret message on a server which got breached due to the admin using weakly hashed passwords. Can you gain access to the secret stored within the server?Access the server using
nc verbal-sleep.picoctf.net 51759
Hints
- Understanding hashes is very crucial. Read more here.
- Can you identify the hash algorithm? Look carefully at the length and structure of each hash identified.
- Tried using any hash cracking tools?
$ nc verbal-sleep.picoctf.net 51759
にアクセスすると、md5,sha-1,sha256のハッシュが提示されるのでその元データを答える問題。
CrackStation でヒットするハッシュなので、それをそのまま入力すればフラグを得られる。
$ nc verbal-sleep.picoctf.net 51759
Welcome!! Looking For the Secret?
We have identified a hash: 482c811da5d5b4bc6d497ffa98491e38
Enter the password for identified hash: password123
Correct! You've cracked the MD5 hash with no secret found!
Flag is yet to be revealed!! Crack this hash: b7a875fc1ea228b9061041b7cec4bd3c52ab3ce3
Enter the password for the identified hash: letmein
Correct! You've cracked the SHA-1 hash with no secret found!
Almost there!! Crack this hash: 916e8c4f79b25028c9e467f1eb8eee6d6bbdff965f9928310ad30a8d88697745
Enter the password for the identified hash: qwerty098
Correct! You've cracked the SHA-256 hash with a secret found.
The flag is: picoCTF{UseStr0nG_h@shEs_&PaSswDs!_ce730f64}
EVEN RSA CAN BE BROKEN??? - 200pt
Description
This service provides you an encrypted flag. Can you decrypt it with just N & e?
Connect to the program with netcat:
$ nc verbal-sleep.picoctf.net 60565
The program's source code can be downloaded here.
Hints
- How much do we trust randomness?
- Notice anything interesting about N?
- Try comparing N across multiple requests
ncコマンドを実行すると以下のようにn,eと暗号文が出力されるので平文を求める。
$ nc verbal-sleep.picoctf.net 60565
N: 14748082129061358101224551733959137380335079893726184211275598168366184075168325847922896332734753868266137291798230804446529310948961552248289093108774142
e: 65537
cyphertext: 7966356211101522837194527512719886746226346275145577870870533140291304817570010169959825414318187173058097222718740356538867105062522523099840171250939571
Nが偶数なので、p,qの片方は2となる。
from sympy import mod_inverse
from Crypto.Util.number import long_to_bytes
# 与えられた値
p = 7374041064530679050612275866979568690167539946863092105637799084183092037584162923961448166367376934133068645899115402223264655474480776124144546554387071
q = 2
N = 14748082129061358101224551733959137380335079893726184211275598168366184075168325847922896332734753868266137291798230804446529310948961552248289093108774142
e = 65537
ciphertext = 7966356211101522837194527512719886746226346275145577870870533140291304817570010169959825414318187173058097222718740356538867105062522523099840171250939571
# φ(N) の計算
phi_N = (p - 1) * (q - 1)
# 秘密鍵 d の計算(e の逆元を求める)
d = mod_inverse(e, phi_N)
# 復号: plaintext = ciphertext^d mod N
plaintext = pow(ciphertext, d, N)
print(long_to_byte(plaintext).decode())
picoCTF{tw0_1$_pr!m3f81fef0a}
Guess My Cheese (Part 1) - 200pt
Description
Try to decrypt the secret cheese password to prove you're not the imposter!
Connect to the program on our server:
nc verbal-sleep.picoctf.net 49406
Hints
- Remember that cipher we devised together Squeexy? The one that incorporates your affinity for linear equations???
ncコマンドでアクセスすると以下のような出力を得る
*******************************************
*** Part 1 ***
*** The Mystery of the CLONED RAT ***
*******************************************
The super evil Dr. Lacktoes Inn Tolerant told me he kidnapped my best friend, Squeexy, and replaced him with an evil clone! You look JUST LIKE SQUEEXY, but I'm not sure if you're him or THE CLONE. I've devised a plan to find out if YOU'RE the REAL SQUEEXY! If you're Squeexy, I'll give you the key to the cloning room so you can maul the imposter...
Here's my secret cheese -- if you're Squeexy, you'll be able to guess it: TOAMIFFYXIIAIUDM
Hint: The cheeses are top secret and limited edition, so they might look different from cheeses you're used to!
Commands: (g)uess my cheese or (e)ncrypt a cheese
What would you like to do?
既存のチーズを暗号化するか、チーズを推測するかを選択して、3回まで会話することができる。
既存のチーズのリストは別問題のPart 2の方に添付されている。
既存のチーズを暗号化していると、同じ文字は同じ文字に暗号化されるため、換字暗号だと思われる。
換字のルールは接続ごとに変更され、問題として提示されるチーズも接続ごとに変化すると思われる。
2回まで暗号化してくれるので、2回でほとんどのアルファベットを網羅するようにすれば、ある程度の確率で推測することが可能。
ただし、提示される暗号化チーズは、既存のチーズのリストからそのまま出題されるのではなく、チーズの最後に3文字ソルトを付与したものを暗号化している。
換字暗号を解くとフラグが表示される。
picoCTF{ChEeSyb3e5eba8}
Guess My Cheese (Part 2) - 300pt
未解答
Description
The imposter was able to fool us last time, so we've strengthened our defenses!
Here's our list of cheeses.
Connect to the program on our server:
nc verbal-sleep.picoctf.net 58138
Hints
- I heard that SHA-256 is the best hash function out there!
- Remember Squeexy, we enjoy our cheese with exactly 2 nibbles of hexadecimal-character salt!
- Ever heard of rainbow tables?
接続すると以下が出力される
*******************************************
*** Part 2 ***
*** The Mystery of the CLONED RAT ***
*******************************************
DRAT! The evil Dr. Lacktoes Inn Tolerant's clone was able to guess the cheese last time! I guess simple ciphers aren't good hashing methods. But now I've strengthened my encryption scheme so that now ONLY SQUEEXY can guess it...
Here's my secret cheese -- if you're Squeexy, you'll be able to guess it: 001a6bec064d078e57a8fd5186ab3145234a903f2f7c37a38b351414078c82e5
Commands: (g)uess my cheese
What would you like to do?
ヒントから「チーズ名+16進数文字2文字のソルト」をsha256のハッシュのhexにしたテキストを作成して、ハッシュ値を検索してみたが、ヒットしてくれない
ChaCha Slide - 400pt
未解答
Description
Modern authenticated-encryption ciphers like ChaCha20-Poly1305 are great, but they can quickly fall apart if their limits aren't respected. Can you violate the integrity of a message encrypted by this program?
Additional details will be available after launching your challenge instance.
インスタンスを起動するとncの接続先と実行されるコードの取得先URLが提示される。
ncを実行すると以下のように出力される。
$ nc activist-birds.picoctf.net 49413
Plaintext: 'Did you know that ChaCha20-Poly1305 is an authenticated encryption algorithm?'
Plaintext (hex): 44696420796f75206b6e6f7720746861742043686143686132302d506f6c793133303520697320616e2061757468656e7469636174656420656e6372797074696f6e20616c676f726974686d3f
Ciphertext (hex): c5c4bb1555ddfdc5ff32437a5f78862eb0db5ea8a1639f3afb6b547d59b3ed9df8b77b19eec1819b7ddb7bdfdd68957c74799619c5b84ed1c5ac358f8539d444ad5ac5b34af115a70191b4e09ac3408e3bcdd1debba32312eb620587166afddff9e17155d4caffa8a7
Plaintext: 'That means it protects both the confidentiality and integrity of data!'
Plaintext (hex): 54686174206d65616e732069742070726f746563747320626f74682074686520636f6e666964656e7469616c69747920616e6420696e74656772697479206f66206461746121
Ciphertext (hex): d5c5be410cdfed84fa2f0c640b2c9e3dab8f78a3b453d739a62f110d42b7f18ca8e8205feed6c49467927bc6c0748932617e9158d8b35e94c7b03f898569cf4be25084a647b7645eaa95fbb60ede7bdcec769335027d6afddff9e17155d4caffa8a7
What is your message?
既知の平文とChaCha20-Poly1305で暗号化した暗号文のペアが2つ出力される。
コードは以下。
import secrets
import hashlib
from Crypto.Cipher import ChaCha20_Poly1305
flag = open("flag.txt").read().strip()
def shasum(x):
return hashlib.sha256(x).digest()
key = shasum(shasum(secrets.token_bytes(32) + flag.encode()))
# Generate a random nonce to be extra safe
nonce = secrets.token_bytes(12)
messages = [
"Did you know that ChaCha20-Poly1305 is an authenticated encryption algorithm?",
"That means it protects both the confidentiality and integrity of data!"
]
goal = "But it's only secure if used correctly!"
def encrypt(message):
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
ciphertext, tag = cipher.encrypt_and_digest(message)
return ciphertext + tag + nonce
def decrypt(message_enc):
ciphertext = message_enc[:-28]
tag = message_enc[-28:-12]
nonce = message_enc[-12:]
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
plaintext = cipher.decrypt_and_verify(ciphertext, tag)
return plaintext
for message in messages:
print("Plaintext: " + repr(message))
message = message.encode()
print("Plaintext (hex): " + message.hex())
ciphertext = encrypt(message)
print("Ciphertext (hex): " + ciphertext.hex())
print()
print()
user = bytes.fromhex(input("What is your message? "))
user_message = decrypt(user)
print("User message (decrypted): " + repr(user_message))
if goal in repr(user_message):
print(flag)
そのため、同じ鍵とノンスで
But it's only secure if used correctly!
を含む文字列を暗号化したhexを入力すればフラグが取得できそう。
鍵とノンスは毎回変化するが、1回のアクセスでは同じものを使っている。
ノンスは最後の12バイト(hexで24文字)
タグはノンスの手前の16バイト(hexで32文字)
暗号文は残り。
crypt(P, Key, Nonce) = C + Tag + Nonce
というイメージである。
ChaCha20はストリーム暗号なので、同じ鍵とノンスがあれば鍵ストリームを既知の平文と暗号文のxorで求めて、鍵ストリームと暗号化したい平文でxorを取ることで、暗号化まではできそう。
タグの偽装ができれば解けそうだが時間切れ。
Ricochet - 500pt
未解答
Description
I bought this robot to help me locate flags, but the controller is stuck in a demo loop where the robot just goes in circles. Can you exploit the encryption between the controller to navigate the robot to the flag?
Additional details will be available after launching your challenge instance.
Hints
- Don't forget that you can restart your instance if it gets in a bad state
Discussion