$ cat writeup.md…
$ cat writeup.md…
HackTheBox
Connection: `nc 154.57.164.65 30945`
"On your way to the vault, you decide to follow the underground tunnels, a vast and complicated network of paths used by early humans before the great war. From your previous hack, you already have a map of the tunnels, along with information like distances between sections of the tunnels. While you were studying it to figure your path, a wild super mutant behemoth came behind you and started attacking. Without a second thought, you run into the tunnel, but the behemoth came running inside as well. Can you use your extensive knowledge of the underground tunnels to reach your destination fast and outrun the behemoth?"
Connection: nc 154.57.164.65 30945
Connecting to the server revealed the following protocol:
i x j (2 <= i,j <= 100) and a flat list of numbers representing the gridThe challenge name "Dynamic Paths" directly hints at Dynamic Programming. This is a classic minimum path sum problem (equivalent to LeetCode #64):
m x n grid of non-negative integersClassic 2D DP with recurrence:
dp[0][0] = grid[0][0]
dp[i][0] = dp[i-1][0] + grid[i][0] (first column — can only come from above)
dp[0][j] = dp[0][j-1] + grid[0][j] (first row — can only come from left)
dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1]) (general case)
Answer: dp[rows-1][cols-1]
Time complexity: O(rows x cols) per round — easily handles 100x100 grids.
from pwn import * def min_path_sum(grid): rows = len(grid) cols = len(grid[0]) dp = [[0] * cols for _ in range(rows)] dp[0][0] = grid[0][0] for i in range(1, rows): dp[i][0] = dp[i - 1][0] + grid[i][0] for j in range(1, cols): dp[0][j] = dp[0][j - 1] + grid[0][j] for i in range(1, rows): for j in range(1, cols): dp[i][j] = grid[i][j] + min(dp[i - 1][j], dp[i][j - 1]) return dp[rows - 1][cols - 1] r = remote("154.57.164.65", 30945) # Read the intro text intro = r.recvuntil(b"Test 1/100") print(intro.decode()) for t in range(100): if t > 0: r.recvuntil(f"Test {t + 1}/100".encode()) # Read dimensions line r.recvuntil(b"\n") dims_line = r.recvline().decode().strip() print(f"\n--- Test {t + 1}/100 ---") print(f"Dims: {dims_line}") parts = dims_line.split() rows = int(parts[0]) cols = int(parts[1]) # Read the numbers line nums_line = r.recvline().decode().strip() nums = list(map(int, nums_line.split())) print(f"Numbers: {nums[:20]}{'...' if len(nums) > 20 else ''}") # Build grid grid = [] for i in range(rows): row = nums[i * cols : (i + 1) * cols] grid.append(row) answer = min_path_sum(grid) print(f"Answer: {answer}") r.recvuntil(b"> ") r.sendline(str(answer).encode()) # Get the flag print("\n=== GETTING FLAG ===") remaining = r.recvall(timeout=10) print(remaining.decode())
All 100 tests passed on the first run. Grid sizes ranged from 2x2 up to ~100x100. The DP algorithm handled all sizes efficiently with no timeouts.
$ cat /etc/motd
Liked this one?
Pro unlocks every writeup, every flag, and API access. $9/mo.
$ cat pricing.md$ grep --similar