it Sova
Description¶
I wonder who should pay for the gas on the first date.
Solution¶
-
The given website provides a backend code snippet and an input box. Sending any input will return the contract address:
0x5FbDB2315678afecb367f032d93F642f64180aa3
. -
To solve the challenge, we need to figure out the
user_input
that lets the functionvalidate()
execute successfully. -
We can use the RPC URL provided in the code snippet to get the EVM bytecode of the target contract, and then use Dedaub to decompile.
-
By briefly reviewing the decompiled code, basically, the function
validate()
accepts a string parameter and verifies its validity. It then performs corresponding computations based on the values stored in the contract storage and updates memory accordingly. Finally, it checks whether the result inMEM[0x1e0]
is equal to0x16c11e3b4fe39c85
(note that there are some discrepancies between the actual behavior and the decompiled code). -
There are a total of 104 slots with values in the contract storage. Additionally, the computations and the locations of memory updates depend on the values read from these slots, making it difficult to directly understand the intent from the decompiled code.
-
Another approach is to use Forge's debugger to observe how the function processes the user input and the pattern of memory updates. In short, the program first reverses the first 8 bytes of the input and splits them into two groups of 4 bytes each, assumed to be x and y, respectively. These two groups are then stored in four memory locations, assumed to be A, B, C, and D. Among them, A, B, and C hold the value x, while D holds the value y. Next, the program performs calculations using the values in these four memory locations in combination with masks. The final returned value is based on values stored in C and D. For details, refer to the following code:
-
Next, we can infer the input based on the desired result. According to the above code, let \(X[i]\) represent the result of each iteration. Given \(C[i]\) and \(D[i]\), we can deduce that \(A[i-1]=B[i-1]=D[i]\) and \(C[i-1]=B[i-1]\). Then, we can compute \(A[i]\) with \(A[i-1]\), and by XORing it with \(C[i]\), we can obtain \(D[i-1]\). Repeat the above steps until the initial values of A (B / C) and D are obtained.
-
With the two obtained values, we can retrieve the target input:
Qy=*}OV(
<3
Flag¶
SAS{h00t_h00t_7h1s_6uy_w1ll_c0v3r_th3_c0st5_9f03fd}