DEV Community

Cover image for Sonar Bypass: how Minecraft anti-bot verification works on the wire
𝐒𝐮𝐧𝐝𝐫𝐚𝐦 𝐘𝐚𝐝𝐚𝐯
𝐒𝐮𝐧𝐝𝐫𝐚𝐦 𝐘𝐚𝐝𝐚𝐯

Posted on AI-assisted

Sonar Bypass: how Minecraft anti-bot verification works on the wire

The kick message said "verification failed". No stage, no hint.

Sonar sits in front of a Minecraft server and makes you prove you are a real client: a teleport, a fall, two packet echoes, a boat ride. It all happens at protocol level, so there is no config flag to turn it off. I logged both directions until the sequence made sense.

1. The teleport. First packet puts you at y=3019. You confirm with your position, and the position matters. The second teleport arrives as y=39 with the relative flag set, so spawn is 3019 + 39 = 3058, not 39. Treat it as absolute and you confirm a spot inside the ground.

2. The platform. A section block update right before the fall gives the block id (8185) and its height (0.8125). It is a slab, so you land at spawnY - 4 + 0.8125. Miss the half block and you land inside it.

3. Gravity. Eight ticks of dy = (dy - 0.08) * 0.98, one position packet per tick, then the landing packet with onGround.

let dy = 0, y = spawnY;
for (let i = 0; i < 8; i++) {
  dy = (dy - 0.08) * 0.98;
  y += dy;
  sendPos(y, false);
}
sendPos(spawnY - 4 + platformHeight, true);
Enter fullscreen mode Exit fullscreen mode

4. Echo one: animation. The server swings your arm and waits. Swing back once. Twice gets you kicked.

5. Echo two: held slot. The first slot packet is invalid on purpose, then the real one follows. A vanilla client only confirms a valid slot that actually changed, so a bot that answers everything fails here without a clue.

6. The boat. Driven by keepalives: boat, out, minecart, out. No packet tells you it started. And while you are in the boat you send vehicle movement, not player movement.

The two that cost me days

I confirmed the teleport after sending my position. Logs looked perfect. But the server compares the confirm against where you were when it issued the teleport, and by then I had moved. One line of reordering fixed it.

I also forgot the tick end packet. Without it the movement packets never close and the whole fall is discarded - exact same symptom as a wrong position, which is why it ate an evening.

Code

About 600 lines of Node.js, zero dependencies. Framing is the only part worth showing:

function varint(n) {
  const out = [];
  while (true) {
    const b = n & 0x7f;
    n >>>= 7;
    if (n === 0) { out.push(b); return Buffer.from(out); }
    out.push(b | 0x80);
  }
}

function frame(id, payload) {
  const body = Buffer.concat([varint(id), payload]);
  return Buffer.concat([varint(body.length), body]);
}
Enter fullscreen mode Exit fullscreen mode

After that it is just a state machine over the packets you receive - no proxy in the middle, nothing that breaks on a server update.

Tested against Sonar 2.1.52 and 2.1.53, on 1.21.x and 26.1.x, on servers I had permission to test.

One caveat: this is a research tool. Running it on a server you do not own breaks that server's rules, and it will get your account banned. I wrote it to understand the verification, not to farm one.

Repo: github.com/SirYadav1/sonar-bypass
Site: yadav.codes

Top comments (0)