Perspective
Perspective
Platform: 0ops_ctf | Category: Reversing | Type: Challenge | Difficulty: Medium | OS: Windows | Author: XESXOR | Date: 2025-12-20 | Status: Solved Techniques: 3D point cloud analysis, Float data extraction from binary, Orthographic projection visualization, PE binary analysis
Summary
Task: Windows PE64 OpenGL/GLFW 3D application with camera controls and hidden message. Solution: Extract float32 data from binary, convert to 3D points, apply orthographic XY projection to reveal flag text.
Perspective — 0ops CTF
Description
An artist's perspective is always unique
File: perspective.zip contains perspective.exe
Analysis
1. File Identification
bash read-only • copy allowedfile perspective.exe # perspective.exe: PE32+ executable (console) x86-64, for MS Windows
This is a Windows PE64 application. When running (or analyzing strings) we can see:
- OpenGL/GLFW 3D application
- Camera controls: WASD (movement), Arrow keys (rotation), R (reset)
- Text: "The Artist's Perspective - What do you see?"
2. Finding Data
Binary analysis reveals a large block of float32 data at offset 0x5d3c0:
bash read-only • copy allowedxxd -s 0x5d3c0 -l 64 perspective.exe # Float number patterns visible in little-endian format
3. Extracting Points
Found 1366 3D points (4098 float values = 1366 * 3 coordinates):
- X range: -24.871 to 24.294
- Y range: -14.983 to 15.000
- Z range: -9.864 to 24.920
Solution
Extracting and Visualizing Points
python read-only • copy allowed#!/usr/bin/env python3 import struct import numpy as np import matplotlib.pyplot as plt # Read the binary with open('perspective.exe', 'rb') as f: data = f.read() # Extract float data offset = 0x5d3c0 num_floats = 4098 # 1366 points * 3 coordinates floats = [] for i in range(num_floats): val = struct.unpack('<f', data[offset + i*4 : offset + i*4 + 4])[0] floats.append(val) # Convert to 3D points points = np.array([ (floats[i], floats[i+1], floats[i+2]) for i in range(0, len(floats)-2, 3) ]) print(f"Total points: {len(points)}") print(f"X range: {points[:,0].min():.3f} to {points[:,0].max():.3f}") print(f"Y range: {points[:,1].min():.3f} to {points[:,1].max():.3f}") print(f"Z range: {points[:,2].min():.3f} to {points[:,2].max():.3f}") # XY projection visualization (top-down view) plt.figure(figsize=(20, 10)) plt.scatter(points[:, 0], points[:, 1], s=8, c='black') plt.axis('equal') plt.title('XY Projection - Top-Down View') plt.savefig('flag.png', dpi=150, bbox_inches='tight') plt.show()
Result
When projecting points onto the XY plane (orthographic top-down projection), the points form readable text:
0ops{REDACTED}
Alternative Approaches
- Running in Windows/Wine — can try to find the correct camera angle manually
- 3D visualization — use matplotlib 3D scatter for interactive rotation
- Different projections — try XZ, YZ projections if XY doesn't yield results
Theory
The challenge uses a classic steganography technique in 3D space:
- Points are positioned so that at a certain viewing angle they form text
- Orthographic projection (without perspective) best reveals the hidden message
- Leetspeak in the flag: "Perspective is everything"