โ๏ธ Tap Into Hash
A detailed write-up of the Rev challenge 'Tap Into Hash' from PicoCTF - 2025
๐ Challenge Overview
Category Details Additional Info ๐ Event PicoCTF - 2025 Event Link ๐ฐ Category Rev โ๏ธ ๐ Points 200 Out of 500 total โญ Difficulty ๐ก Medium Personal Rating: 3/10 ๐ค Author NGIRIMANA Schadrack Profile ๐ฎ Solves (At the time of flag submission) 1.328 solve rate ๐ Date 14-03-2025 PicoCTF - 2025 ๐ฆพ Solved By mH4ck3r0n3 Team:
๐ Challenge Information
Can you make sense of this source code file and write a function that will decode the given encrypted file content? Find the encrypted file here. It might be good to analyze source file to get the flag.
๐ฏ Challenge Files & Infrastructure
Provided Files
Files:
๐ Initial Analysis
First Steps
Analyzing the attached files, I understood that the program essentially generates a blockchain consisting of 5 blocks.
Blockchain Creation
Genesis Block:
- The first block is created with an index of 0, a
previous_hash
set to"0"
, a current timestamp, and a fixed string"EncodedGenesisBlock"
for the transactions.Subsequent Blocks:
- For each of the following blocks (from 1 to 4), a string for the transactions is generated (e.g.,
"Transaction_1"
,"Transaction_2"
, etc.) and encoded in Base64. Theproof_of_work
function simulates the mining process by incrementing thenonce
until the block’s hash (calculated using SHA256) starts with"00"
. Hereโs how the blockโs hash is calculated:
1 2 3
def calculate_hash(self): block_string = f"{self.index}{self.previous_hash}{self.timestamp}{self.encoded_transactions}{self.nonce}" return hashlib.sha256(block_string.encode()).hexdigest()
- Concatenating Hashes:
- After all the blocks have been created, a string is generated by concatenating the hashes of each block, separated by the character
-
. In this specific case, since each hash is 64 characters long and there are 4 separators, the total length is: 5 * 64 + 4 = 324 characters.Token (Flag) Insertion
The
encrypt
function is responsible for inserting a token (the flag) into the blockchain string:
- Placement:
- The token is inserted exactly in the middle of the original string. With a length of 324, the midpoint is at index 162.
- String Modification:
- The modified string is formed by concatenating:
- The first half of the original string (from the start to index 162)
- The token (inner_txt)
- The second half of the original string (from index 162 to the end)
1 2 3 4
midpoint = len(plaintext) // 2 # 324 // 2 = 162 first_part = plaintext[:midpoint] second_part = plaintext[midpoint:] modified_plaintext = first_part + inner_txt + second_part
XOR Encryption
After inserting the token, the modified message is encrypted in blocks using a simple XOR-based mechanism:
- Padding:
- Padding (PKCS#7) is applied to ensure the length of the text is a multiple of 16 bytes. The
pad
function adds padding bytes where each byte equals the number of padding bytes added.
1 2 3 4
def pad(data, block_size): padding_length = block_size - len(data) % block_size padding = bytes([padding_length] * padding_length) return data.encode() + padding
- Generating the XOR Key:
- The SHA256 hash of the key is computed, and the first 16 bytes of this hash are used as the key for the XOR mechanism.
- Blockwise XOR Encryption:
- The text (after padding) is divided into 16-byte blocks, and for each block, an XOR operation is performed with the key:
1 2 3 4 5 6 7 8
def xor_bytes(a, b): return bytes(x ^ y for x, y in zip(a, b)) # In the for loop: for i in range(0, len(plaintext), block_size): block = plaintext[i:i + block_size] cipher_block = xor_bytes(block, key_hash[:block_size]) ciphertext += cipher_block
Now that we have a general understanding of what the program does, letโs move on to the exploitation phase.
๐ฌ Vulnerability Analysis
Potential Vulnerabilities
- XOR Repeated Key
๐ฏ Solution Path
Exploitation Steps
Initial setup
To retrieve the token (flag) from the encrypted file, we need to reverse the operations:
- Decrypt the text (by applying XOR again)
- Remove the padding
- Determine the position of the flag
- Extract the token
Let’s see how.
Exploitation
To do all of this, I wrote a Python script. For the first step, since the XOR operation is reversible (XORing twice with the same key returns the original data), I need to iterate over the 16-byte blocks of the ciphertext and apply XOR with the first 16 bytes of the key’s hash:
1 2 3 4 5 6 7 8 9
def decrypt(ciphertext, key): block_size = 16 key_hash = hashlib.sha256(key).digest() key_block = key_hash[:block_size] decrypted = b"" for i in range(0, len(ciphertext), block_size): block = ciphertext[i:i+block_size] decrypted += xor_bytes(block, key_block) return remove_pkcs7_padding(decrypted).decode('utf-8')
Once the decrypted text is obtained, the PKCS#7 padding must be removed:
1 2 3
def remove_pkcs7_padding(data): padding_length = data[-1] return data[:-padding_length]
Knowing that the original blockchain string (without the token) had a length of 324 characters, the extra part in the decrypted text corresponds to the token. Since the token was injected in the middle (index 162), I extract the substring starting from that index with a length of:
len(decrypted_text) - 324
:
1 2 3 4 5 6
def decode_encrypted_file(encrypted, key): decrypted_text = decrypt(encrypted, key) blockchain_length = 324 token_length = len(decrypted_text) - blockchain_length flag = decrypted_text[162:162 + token_length] return flag
After explaining how the exploit works, I simply executed it and obtained the flag.
๐ ๏ธ Exploitation Process
Approach
Since I’ve already explained the exploit previously, I’ll just leave the script here:
๐ฉ Flag Capture
FlagpicoCTF{block_3SRhViRbT1qcX_XUjM0r49cH_qCzmJZzBK_45cd2a52}
Proof of Execution
๐ง Tools Used
Tool Purpose Python Exploit
๐ก Key Learnings
Skills Improved
- Binary Exploitation
- Reverse Engineering
- Web Exploitation
- Cryptography
- Forensics
- OSINT
- Miscellaneous
๐ Final Statistics
Metric | Value | Notes |
---|---|---|
Time to Solve | 00:20 | From start to flag |
Global Ranking (At the time of flag submission) | 1243/10396 | Challenge ranking |
Points Earned | 200 | Team contribution |
Created: 14-03-2025 โข Last Modified: 14-03-2025 *Author: mH4ck3r0n3 โข Team: *