Geoguessr hack/exploit with proxy (Fiddler on Windows)

There is a popular (and incredible) geographical game called Geoguessr, where players guess locations from Google Maps Street View imagery. I play it regularly, and I am sure many of you have seen those guys who can guess where they are just by a quick glimpse of the part of the grass or sky or just pixelated images. Well, you can do it, too.

Avoid using this method, but I would like to know about things in the real world.

How Geoguessr works?

As with any other web application, Geoguessr is a client-server application with client-side and server-side parts. The simplified explanation would be:

  • Through the application's user interface, the user sends a request to the web server across the Internet.

  • The web server forwards this request to the web application server.

  • After completing the specified task, the web application server generates the necessary data results.

  • The web application server then relays those results to the web server (requested information or processed data).

  • The client receives the requested information from the web server (tablet, mobile device, or desktop).

  • The requested information appears on the user's display.

http.png

Let's take, for example, a Classic Mode and find your map (World, Famous Places, United States, etc.). When you start a game, a browser will send an HTTP request to the endpoint: https://www.geoguessr.com/api/v3/games. The response will return the current location's latitude and longitude. That easy!

For different playing modes, the game will call other endpoints, e.q., Streaks will call https://www.geoguessr.com/api/v3/games/streak.

image.png

This begs the question: Well, we already have the information about the location; how to make something out of it without suffering? We can manually search for the latitude and longitude on Google Maps, but it is time-consuming and slow. There is a better idea, and we call it - an INTERMEDIARY (Proxy).

Proxy?

There is no better explanation than in Section 2.3 of RFC 7230 (Request for Comments) of the Internet Engineering Task Force (IETF).

A "proxy" is a message-forwarding agent that is selected by the client, usually via local configuration rules, to receive requests for some type(s) of absolute URI and attempt to satisfy those requests via translation through the HTTP interface. Some translations are minimal, such as for proxy requests for "http" URIs, whereas other requests might require translation to and from entirely different application-level protocols. Proxies are often used to group an organization's HTTP requests through a common intermediary for the sake of security, annotation services, or shared caching.

http_proxy.png

Fiddler Classic

We want something easy to work with, easily configurable, and accessible. This is not a sponsored blog post, but Fiddler Classic is one of the best tools of this kind for Windows I have been working with.

Fiddler Classic is a specialized proxy server tool for troubleshooting online traffic from programs like browsers. It records and collects online traffic before sending it to a web server. The replies from the server are then sent back to the Fiddler program, which subsequently sends them back to the client. Fiddler's web debugging user interface shows the captured web traffic through a session list.

Capture and decrypt HTTPS traffic

By default, Fiddler Classic does not capture and decrypt secure HTTPS traffic. We need to enable HTTPS traffic decryption to capture data sent through HTTPS.

  • Go to Tools > Options > HTTPS

  • Ensure that Capture HTTPS CONNECTs and Decrypt HTTPS Traffic are selected

image.png

Now we can track HTTPS requests made from our browsers. Here is an example of Geoguessr game invocation, the same results as those from the browser image above:

image.png

FiddlerScript

One of Fiddler's most powerful features is FiddlerScript, which enables us to alter requests and responses "on the fly" to implement any desired action. It is built on JScript.NET, a.NET version of JavaScript, making it simple for web developers to use. Most .NET developers can design basic rules using FiddlerScript because the syntax is similar enough to C#.

  • Go to Rules > Customize Rules..., and it will open up the FiddlerScript editor (or Notepad if you don't have an editor installed)

image.png

Many things are happening in that file, but we will focus on the OnBeforeResponse session event method. It fires after the complete response has been read from the server and before the response is returned to the client (unless Streaming is enabled), so we can add some behavior.

Open Microsoft Edge pinned to the location

Once we start playing the game, we want our FiddlerScript to run a new browser session with the location taken from the response pinned on a map.

To retrieve latitude and longitude from the JSON response, we need to do some JSON decoding and get the latest result from the rounds parameter (the parameter rounds is an array of the current and previous results).

The only thing left now is to launch a fresh browser session (or another tab) if you launch the same browser as your current one. I use the Brave browser and launch Microsoft Edge (because it is on Windows by default). Our final OnBeforeResponse event will look like this:

static function OnBeforeResponse(oSession: Session) {
    if (m_Hide304s && oSession.responseCode == 304) {
        oSession["ui-hide"] = "true";
    }

    // Only GET method, otherwise, it will open the browser again once we POST the results
    if (oSession.RequestMethod == "GET" 
        && (oSession.uriContains("/api/v3/games/") 
        || oSession.uriContains("/api/v3/challenges/")
        || oSession.uriContains("/api/battle-royale/")
        ) 
    ) {

        var latLng = oSession.GetResponseBodyAsString();
        var oJson = Fiddler.WebFormats.JSON.JsonDecode(latLng);

        var rs = oJson.JSONObject["rounds"];
        var lat =  rs[rs.Count - 1]["lat"];
        var lng = rs[rs.Count - 1]["lng"];

        var zoomLevel = "8z";

        Utilities.LaunchHyperlink("microsoft-edge:https://maps.google.com/maps/place/"+lat+","+lng+"/@"+lat+","+lng+","+zoomLevel);
    }
}

Finally, you need to keep FiddlerClassic open for it to act as a proxy. See it in action: