Geoguessr exploit with proxy (Fiddler on Windows)
Published: 2022-10-27 19:53:40

There is a popular (and incredible) geographical game called [Geoguessr](https://www.geoguessr.com/), 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.


![HTTPS communication](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3vk2uaaft7vbxaz8zfvu.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`. 

![Geoguessr game](https://cdn.hashnode.com/res/hashnode/image/upload/v1666878244347/lqa4yPd5C.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](https://www.google.com/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](https://www.rfc-editor.org/rfc/rfc7230#section-2.3) (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](https://cdn.hashnode.com/res/hashnode/image/upload/v1666858636687/4ZsHauEEk.png)

## Fiddler Classic
We want something easy to work with, easily configurable, and accessible. This is not a sponsored blog post, but [Fiddler Classic](https://www.telerik.com/fiddler/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](https://cdn.hashnode.com/res/hashnode/image/upload/v1666877587850/VXyB2iL82.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](https://cdn.hashnode.com/res/hashnode/image/upload/v1666876546105/lMickkCYO.png)

### FiddlerScript
One of Fiddler's most powerful features is [FiddlerScript](https://www.telerik.com/blogs/understanding-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](https://cdn.hashnode.com/res/hashnode/image/upload/v1666878570594/wRUylu4yX.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:

```c#
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:

{% embed https://www.youtube.com/watch?v=tQS0U7K5L4M %}