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.

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}
```