While driving with Waze as travel companion, Waze periodically sends various information to the Google Location Service using compressed protofub messages with the MASF protocol.

Packet overview

With MITMProxy, it is easy to capture traffic generated by the application. As an example, here is the screenshot of a captured message sent to https://www.google.com/loc/m/api:
request

MASF protocol specifications

masf_proto

  • loc/ql: query location to Google
  • loc/ul: upload location history to Google

Google Location protobuf specifications

Once we had got rid of the MASF protocol header, we are able to decode the protobuf message:
decoded

Since we do not have the specifications of the messages, I will try to put here what I had reversed.
In the case of Waze, sent messages are location requests. Those messages follow this structure:
class-diagram

What a location request looks like

PLATFORM_PROFILE {
  VERSION: "2023"
  PLATFORM: "andr[edited]st-keys"
  PLATFORM_KEY: "2:2[edited]PgVo"
  LOCALE {
    12: 0x53555f6e
  }
}
REQUEST_ELEMENTS {
  17 {
    3 {
      6 {
        1: [edited]
        1: [edited]
        1: [edited]
        1: 229449706754861
        [...]
      }
    }
    4: 0
  }
}
7: 1554

Platform key

The PLATFORM_KEY is meant to identify the device. This identifier can be found in the gls.platform.key file, next to the cache databases. This identifier is cleared when the Use wireless networks option is disabled in the Android settings. Find more details in the Martin Trigaux's thesis.

BSSIDs

Basically, Google receives the list of surrounding Wifi AP MAC addresses encoded on 48-bits integers.

For example, 229449706754861 integer is D0:AE:EC:43:D3:2D in hex. A simple request like https://api.mylnikov.org/wifi?v=1.1&bssid=D0AEEC43D32D to the Alexander Mylnikov Wifi database returns

{
  "result":200, 
  "data":{
    "lat": 47.22294648535, 
    "range": 46.904, 
    "lon": -1.55347160099, 
    "time": 1516524970
  }
}

Many thanks to @baarde for his precious help.

The following map represents a location request sent to Google during a trip to Nantes.

map

What a location history upload looks like

PLATFORM_PROFILE {
  VERSION: "2023"
  PLATFORM: "andr[edited]st-keys"
  PLATFORM_KEY: "2:2[edited]PgVo"
  LOCALE {
    12: 0x53555f6e
  }
}
REQUEST_ELEMENTS {
  WIFI_PROFILE {
    TIMESTAMP: 1516461515426
    WIFI_DEVICES {
      MAC: ""
      SSID: "F2"
      CHANNEL: 7
      RSSI: 18446744073709551592
      NOISE: 202481595462638
      12: 0
    }
    WIFI_DEVICES {
      MAC: ""
      SSID: "[edited]"
      CHANNEL: 11
      RSSI: 18446744073709551546
      NOISE: 25227706874428
      12: 0
    }
    WIFI_DEVICES {
      MAC: ""
      SSID: "[edited]"
      CHANNEL: 6
      RSSI: 18446744073709551543
      NOISE: 53312127063207
      12: 0
    }
    WIFI_DEVICES {
      MAC: ""
      SSID: "[edited]"
      CHANNEL: 1
      RSSI: 18446744073709551539
      NOISE: 169489827901332
      12: 0
    }
    WIFI_DEVICES {
      MAC: ""
      SSID: "[edited]"
      CHANNEL: 1
      RSSI: 18446744073709551531
      NOISE: 77561441513040
      12: 0
    }
  }
  LOCATION {
    LAT-LNG {
      LAT: [edited]
      LNG: [edited]
    }
    ACCURACY: 9
    TIMESTAMP: 1516461522000
    LOC_TYPE: 0
    ALTITUDE: 23
    HEADING: 340
    16: 0x00000000
    17: 1
  }
  [...]
}