Contents

โš™๏ธ Tap Into Hash

A detailed write-up of the Rev challenge 'Tap Into Hash' from PicoCTF - 2025

/images/PicoCTF-2025/Rev/TapIntoHash/challenge_presentation.png
Challenge Presentation

๐Ÿ“Š 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. The proof_of_work function simulates the mining process by incrementing the nonce 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

Flag

picoCTF{block_3SRhViRbT1qcX_XUjM0r49cH_qCzmJZzBK_45cd2a52}

Proof of Execution

/images/PicoCTF-2025/Rev/TapIntoHash/automated_flag.png
Automated Flag
Screenshot of successful exploitation

๐Ÿ”ง 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: *