apple.py
location.proto
google.py
Google не сделал до конца т-к слишком много времени занимают тесты.
Python:
from locale import locale_alias as locales
from random import choice, randint
from struct import pack
from requests import post
import location_pb2
class Apple:
def __init__(self) -> None:
self.version = choice([
'13.4.117E262', '8.4.1.12H321', '13.1.117A854', '15.4.119E258'
])
self.url = choice([
# 'https://gs-loc.apple.com/clls/wloc', - only valid user agents
'https://gs-loc.ls-apple.com.akadns.net/clls/wloc'
# https://gsp10-ssl.apple.com/hcy/pbcwloc - OLD
])
def req_header(self) -> bytes:
NUL_SQH = pack('>h', 1)
NUL_NUL = pack('>h', 0)
llength = pack('>h', 5)
locale = choice(list(locales.values())).split('.')[0].encode('utf-8')
ilength = pack('>h', 19)
identifier = 'com.apple.locationd'.encode('utf-8')
vlength = pack('>h', 12)
version = self.version.encode('utf-8')
return NUL_SQH + llength + locale + ilength + identifier + \
vlength + version + NUL_NUL + NUL_SQH + NUL_NUL
def send(self, data: bytes) -> bytes:
ld_ver = f'{randint(1619, 2492)}.{randint(1, 4)}.{randint(4, 16)}'
cf_ver = f'{randint(682, 1384)}.{randint(1, 7)}.{randint(3, 10)}'
d_ver = choice(['14.0.0', '19.6.0'])
headers: dict = {
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': f'locationd/{ld_ver} CFNetwork/{cf_ver} Darwin/{d_ver}' # noqa
}
req = post(self.url, data, headers=headers, verify=False).content
data_buffer = req[
(req.find(pack('>h', 0)+pack('>h', 1)+pack('>h', 0)) + 8):
]
return data_buffer
def create_request(
self, macs: list, noise: int = 0, signal: int = 100
) -> bytes:
request = location_pb2.Request()
request.noise = noise
request.signal = signal
for mac in macs:
request.wifis.add(mac=mac.lower())
message: bytes = request.SerializeToString()
size = pack('>h', len(message))
return self.req_header() + size + message
def parse_data(self, data: bytes) -> dict:
response = location_pb2.Response()
response.ParseFromString(data)
wifi_list = {}
for wifi in response.wifis:
if wifi.location.latitude != 18446744055709551616:
if wifi_list.get(wifi.mac):
continue
lng = str(int(wifi.location.longitude) * pow(10, -8))
lat = str(int(wifi.location.latitude) * pow(10, -8))
wifi_list[wifi.mac] = {}
wifi_list[wifi.mac]['channel'] = wifi.channel
wifi_list[wifi.mac]['lat'] = lat
wifi_list[wifi.mac]['lng'] = lng
wifi_list[wifi.mac]['accuracy'] = wifi.location.accuracy
wifi_list[wifi.mac]['altitude'] = wifi.location.altitude
wifi_list[wifi.mac]['url'] = f'https://www.openstreetmap.org/directions?from=&to={lat},{lng}' # noqa
return wifi_list
def detect(self, macs: str, noise: int = 0, signal: int = 100) -> dict:
for i in range(len(macs)):
macs[i] = macs[i].replace(':0', ':').lower()
request = self.create_request(macs, noise, signal)
response = self.send(request)
out = self.parse_data(response)
for mac, data in out.items():
if mac in macs:
print(f'Apple: {mac} -> {data["url"]}')
return out
location.proto
Код:
syntax = "proto2";
message Response {
message ResponseWifi {
message WifiLocation {
optional int64 latitude = 1; // X * pow(10, -8)
optional int64 longitude = 2; // X * pow(10, -8)
optional int32 accuracy = 3; // Radius (meters)
optional int32 zeroField4 = 4; // always 0
optional int32 altitude = 5; // -500 if unknown
optional int32 altitudeAccuracy = 6; // Not set if altitude=-500
optional int32 unknown11 = 11; // [5,63]?
optional int32 unknown12 = 12; // [30,4000]?
}
optional string mac = 1;
optional WifiLocation location = 2;
optional int32 channel = 21;
}
repeated ResponseWifi wifis = 2;
}
message Request {
message RequestWifi {
optional string mac = 1;
}
repeated RequestWifi wifis = 2;
optional int32 noise = 3 [default=0];
optional int32 signal = 4 [default=100];
optional string source = 5;
}
google.py
Python:
from struct import pack
from time import time
from zlib import compress
from requests import post
from AppProfile_pb2 import AppProfile
from LocRequest_pb2 import LocRequest
from PlatformProfile_pb2 import PlatformProfile
from RequestElements_pb2 import RequestElements
from WifiProfile_pb2 import WifiProfile
class Google:
def __init__(self) -> None:
self.url = 'https://www.google.com/loc/m/api'
self.headers = {
'User-Agent': 'GoogleMobile/1.0 (M5 MRA58K)'
}
self.app_name = 'location'
self.app_version = '2021'
self.app_system = 'android'
self.app_env = 'gms'
self.locale = 'en_US'
self.splitter = 'g'.encode()
self.request = 'g:loc/ql'.encode()
def _generate_header(self, masf_body: bytes) -> bytes:
app_details = (
f'{self.app_name},{self.app_version},{self.app_system},' +
f'{self.app_env},{self.locale}'
).encode()
return (
pack('>h', 2) + pack('>h', 0) + chr(31).encode() +
app_details +
pack('l', 0) +
pack('>h', 1) + self.splitter +
pack('!i', len(masf_body)) +
pack('x') +
masf_body
)
def _generate_masf_body(self, proto_msg: bytes) -> bytes:
return (
pack('>h', 257) + pack('>h', 1) + pack('>h', 8) +
self.request + pack('>l', 4) + 'POSTmr'.encode() + pack('>l', 4) +
'ROOT'.encode() + pack('x') +
pack('!i', len(proto_msg)) +
pack('>h', 1) + self.splitter +
proto_msg
)
def __generate_platform__(self) -> PlatformProfile:
profile = PlatformProfile()
profile.VERSION = self.app_version
profile.PLATFORM = 'android/INEW/INEW/CXQ:4.4.2/KOT49H/1417078902:user/test-keys' # noqa
profile.LOCALE = self.locale
profile.PLATFORM_KEY = '2:20W9brSbFzyttn-n:8i85ia2kECu1PgVo'
return profile
def __generate_app__(self) -> AppProfile:
profile = AppProfile()
profile.appName = self.app_env
profile.appKey = self.app_name
return profile
def send_bssid(self, mac: str):
profile = WifiProfile()
profile.TIMESTAMP = int(time())
profile.PREFETCH_MODE = 2
profile.WIFI_DEVICES.MAC = mac
wifi_elem = RequestElements()
wifi_elem.WIFI_PROFILE.ParseFromString(profile.SerializeToString())
request = LocRequest()
request.REQUEST_ELEMENTS.ParseFromString(wifi_elem.SerializeToString())
request.PLATFORM_PROFILE.ParseFromString(
self.__generate_platform__().SerializeToString()
)
request.APP_PROFILES.ParseFromString(
self.__generate_app__().SerializeToString()
)
data = compress(self._generate_header(self._generate_masf_body(
request.SerializeToString()
)))
a = post(self.url, data=data, headers=self.headers).content
print(a)
a = Google()
a.send_bssid('11:11:11:11')
Google не сделал до конца т-к слишком много времени занимают тесты.