Advent of Cyber 2024 Day 19: I merely noticed that you’re improperly stored, my dear secret!

Lab link.

Questions

1. What is the OTP flag?

If we run the command frida-trace ./TryUnlockMe -i 'libaocgame.so!*', it will automatically start tracing all the functions. The penguin is requesting a PIN code, which is handled by the _Z7set_otpi function. The _Z7set_otpi function manages the OTP process. We open the file in Visual Studio Code and modify its content as shown in the image.

args[0] is captured and logged so that we can access the OTP code during our investigation with Frida.

2. What is the billionaire item flag?

Instead of collecting coins, you can manipulate the function responsible for purchasing items using Frida to set the price to zero. The function that handles the purchasing process is called: _Z17validate_purchaseiii. The three ‘i’ letters in the function name indicate that it takes three integer parameters.
Parameter 1: The ID of the item to be purchased (Item ID).
Parameter 2: The price of the item (Price).
Parameter 3: The number of coins the player has (Player’s Coins).

Manipulating the Function
You can bypass the price by setting the price parameter (args[1]) to zero. To set the price to zero, you can use the following script:

When the price is set to zero, the game will no longer check your coin balance to purchase items.
You can now acquire any item you want, such as the Right of Pass, for free.

3. What is the biometric flag?

When we reach the third level of the game, biometric verification is required. This verification is carried out using a function called _Z16check_biometricsPKc(). However, unlike previous levels, this function works with strings (text) instead of integers, making debugging a bit more challenging. Locate the JavaScript file named _Z16check_biometricsPKc in the handlers folder created by Frida. In this file, we will add debugging and manipulation code. To examine the parameter passed to the function, add the following code to the onEnter method:

  • Memory.readCString(args[0]) reads the string (text) parameter passed to the function.
  • By logging this parameter, we can understand what value the game uses during biometric verification.

This output shows the parameter sent to the function. However, this value may not be directly sufficient to pass biometric verification, so we will take one step further.

Logging the Return Value of the Function
To understand what the function returns, add logging code to the onLeave method. Update the handler as follows:
By logging the return value of the function, we can determine whether the biometric verification was successful.

This output indicates that the function returns 0, which means the biometric verification has failed.

Manipulating the Return Value
You can trick the game into thinking the biometric verification has succeeded by modifying the return value of the function. To do this, update the onLeave method as follows:

defineHandler({
onEnter(log, args, state) {
log(‘_Z16check_biometricsPKc()’);
log(“PARAMETER:” + Memory.readCString(args[0]));
},

onLeave(log, retval, state) {
log(“The return value is: ” + retval);
retval.replace(ptr(1)); // This sets the return value to 1 (True)
}
});

The retval.replace(ptr(1)) code changes the return value of the function to 1. This means that the biometric verification is successful for the game. Run the game again and trigger the biometric verification.

If everything is correctly configured, the game will now perceive the biometric verification as passed and will allow you to proceed to the next stage.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir