distributed_training

remote applications

Competetion

iCTF24

Challenge Author

nsigma

Date

Dec. 29, 2024

a server is set up to accept a 4x4 matrix upload in .pt format (e.g., you upload matA). The server will then return the results of the multiplication matA * matB, where matB is a secret matrix stored on the server. Can you get the flag?


Hints

None

Solution

To get the secret matrix (matB) we need to send the server an identity matrix. An identity matrix is a matrix that when used to multiply by another matrix, results in the second matrix. Since the server is performing matrix multiplication, this will give us matB. ![](/media/writeup_images/ictf24/distributed_training/2024-11-27_distribued_training_.png) In order to get a matrix in the ".pt" format we can use the pytorch library which allows us to easily create matrices. We use the eye method to make an identity matrix that's 4x4. ```python import torch identity_matrix 4x4 = torch.eye(4) torch.save(identity_matrix_4x4, "identity_matrix_4x4.pt") ``` Now that we have the matrix, we need to send it to the server under the /upload directory: ```python import torch import requests identity_matrix_4x4 = torch.eye(4) torch.save(identity_matrix_4x4, "identity_matrix_4x4.pt") url = "https://ictf24-under-distributed-training.chals.io/upload" with open("identity_matrix_4x4.pt", "rb") as file: files = {"file": file} response = requests.post(url, files=files) print(response.text) ``` In return, we get back the matrix that's the product of matrix A and B. Since we gave it an identity matrix, this should be matrix B. ``` Response Text: {"result":"[[25449.0, 26228.0, 25211.0, 25652.0], [25695.0, 13619.0, 29235.0, 13361.0], [24428.0, 12656.0 27491.0, 13164.0], [12383.0, 18253.0, 30815.0, 32120.0]]"} ``` Now we need to figure out how they encoded the flag into the matrix. One of the files we are given in called compute.py. This file has a function labeled "flag_to_matrix". Figuring out how to reverse this function should give us the flag. ```python def flag_to_matrix(flag: str) -> torch.Tensor: # Convert the flag to a matrix of integers assert len(flag) == 32 # two characters per integer mat = torch.tensor( [ord(flag[i]) + (ord(flag[i + 1]) << 8) for i in range(0, len(flag), 2)], dtype=torch.float, ) mat = mat.view(MATRIX_SIZE) return mat ``` The function looks like it's shoving two characters into one number. It's doing this by getting the ascii code of the second character and bit shifting it to the left by 8. After adding that result with the first number, it puts the sum into the matrix. It's effectively putting the second number into the left side of the bits, while the first number stays on the right side. To reverse this we can use bitwise and against 0xFF (255) which will isolate the rightmost bits, giving us the first letter. For the second letter we can reverse the left bit shift with a right one. We can do this process for each number, giving us the flag. ```python def matrix_to_flag(matrix): flat_matrix = matrix.view(-1).int().tolist() flag_chars = "" for num in flat_matrix: char1 = chr(num & 0xFF) char2 = chr(num >> 8) flag_chars += char1 + char2 return flag_chars ``` ``` ictf{b4d_d353r14l_p1ckl3_0MG_xx} ```