Siunam's Website

My personal website

Home About Blog Writeups Projects E-Portfolio

Re:Zero

Table of Contents

  1. Overview
  2. Background
  3. Enumeration
  4. Exploitation
  5. Conclusion

Overview

Background

  1. Complete Achievement 0 - 20
  2. No Revives, No Kill, Dealt 0 damage in game

Once completed, refresh the browser and the flag will be printed on the console.

Web: http://chal.hkcert23.pwnable.hk:28040

Note: There is a guide for this challenge here.

Enumeration

In this challenge, we can go to a web application:

In here, we can play a multiplayer game called “BrowserQuest”.

BrowserQuest is a tribute to classic video-games with a multiplayer twist. You play as a young warrior driven by the thrill of adventure. No princess to save here, just a dangerous world filled with treasures to discover. And it’s all done in glorious HTML5 and JavaScript. (from https://hacks.mozilla.org/2012/03/browserquest/)

Without further ado, let’s dive into the game!

After clicked the “PLAY” button, we’ll can play with the game and start our adventure!

In this challenge’s description, it said:

  1. Complete Achievement 0 - 20
  2. No Revives, No Kill, Dealt 0 damage in game

Once completed, refresh the browser and the flag will be printed on the console.

Wait… How can I finish all 21 (0 - 20) achievements with no revives, no kill, and dealt 0 damage in the game…

When we clicked the “PLAY” button, it popped up a “How to play” popup, and it mentioned our character is automatically saved as we play:

Hmm… I wonder how our session/game data is being saved… Cookies? Local storage?

We can use the development tools to find that out:

Now, we can go to the “Storage” tab (“Application” tab in Chrome) and view stored cookies and local storage:

Nothing in cookies…

Ah ha! We found it! It’s in local storage!

In our local storage, there’s a key called data, with the following value:

{"hasAlreadyPlayed":true,"player":{"name":"siunam","weapon":"sword1","armor":"clotharmor","image":"data:image/png;base64,iVBORw0[...]ggg=="},"achievements":{"unlocked":[],"ratCount":0,"skeletonCount":0,"totalKills":0,"totalDmg":0,"totalRevives":0}}

Beautified:

{
    "hasAlreadyPlayed": true,
    "player":
    {
        "name": "siunam",
        "weapon": "sword1",
        "armor": "clotharmor",
        "image": "data:image/png;base64,iVBORw0[...]ggg=="
    },
    "achievements":
    {
        "unlocked":
        [],
        "ratCount": 0,
        "skeletonCount": 0,
        "totalKills": 0,
        "totalDmg": 0,
        "totalRevives": 0
    }
}

As you can see, our achievements are currently empty.

Hmm… Looks like the game doesn’t check the integrity of our game data! Which means we should be able to modify it to whatever we want!

Exploitation

But before we do that, we need to know the format of the achievements.

So let’s try to talk to an NPC and get a sample:

Then, view the local storage data key’s value again:

{
    "hasAlreadyPlayed": true,
    "player":
    {
        "name": "siunam",
        "weapon": "sword1",
        "armor": "clotharmor",
        "image": "data:image/png;base64,iVBORw0[...]ggg=="
    },
    "achievements":
    {
        "unlocked":
        [
            4
        ],
        "ratCount": 0,
        "skeletonCount": 0,
        "totalKills": 0,
        "totalDmg": 0,
        "totalRevives": 0
    }
}

Now we know the format of the achievements!

Let’s modify that!

{
    "hasAlreadyPlayed": true,
    "player":
    {
        "name": "siunam",
        "weapon": "sword1",
        "armor": "clotharmor",
        "image": "data:image/png;base64,iVBORw0[...]ggg=="
    },
    "achievements":
    {
        "unlocked":
        [
            0,
            1,
            2,
            3,
            4,
            5,
            6,
            7,
            8,
            9,
            10,
            11,
            12,
            13,
            14,
            15,
            16,
            17,
            18,
            19,
            20
        ],
        "ratCount": 0,
        "skeletonCount": 0,
        "totalKills": 0,
        "totalDmg": 0,
        "totalRevives": 0
    }
}

Finally, copy and paste the above modified JSON data, and refresh the page:

We got the flag!

Conclusion

What we’ve learned:

  1. Modifying local storage data