Advertisement
Guest User

Untitled

a guest
Jul 21st, 2016
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.80 KB | None | 0 0
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3.  
  4. import os
  5. import re
  6. import sys
  7. import struct
  8. import json
  9. import requests
  10. import argparse
  11. import pokemon_pb2
  12. import time
  13.  
  14. from google.protobuf.internal import encoder
  15.  
  16. from datetime import datetime
  17. from geopy.geocoders import GoogleV3
  18. try:
  19. from requests.packages.urllib3.exceptions import InsecureRequestWarning
  20. requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
  21. except ImportError:
  22. pass
  23. from s2sphere import *
  24.  
  25. def encode(cellid):
  26. output = []
  27. encoder._VarintEncoder()(output.append, cellid)
  28. return ''.join(output)
  29.  
  30. def getNeighbors():
  31. origin = CellId.from_lat_lng(LatLng.from_degrees(FLOAT_LAT, FLOAT_LONG)).parent(15)
  32. walk = [origin.id()]
  33. # 10 before and 10 after
  34. next = origin.next()
  35. prev = origin.prev()
  36. for i in range(10):
  37. walk.append(prev.id())
  38. walk.append(next.id())
  39. next = next.next()
  40. prev = prev.prev()
  41. return walk
  42.  
  43. with open('config.json') as file:
  44. credentials = json.load(file)
  45.  
  46. PTC_CLIENT_SECRET = credentials.get('PTC_CLIENT_SECRET', None)
  47. ANDROID_ID = credentials.get('ANDROID_ID', None)
  48. SERVICE = credentials.get('SERVICE', None)
  49. CLIENT_SIG = credentials.get('CLIENT_SIG', None)
  50.  
  51. API_URL = 'https://pgorelease.nianticlabs.com/plfe/rpc'
  52. LOGIN_URL = 'https://sso.pokemon.com/sso/login?service=https%3A%2F%2Fsso.pokemon.com%2Fsso%2Foauth2.0%2FcallbackAuthorize'
  53. LOGIN_OAUTH = 'https://sso.pokemon.com/sso/oauth2.0/accessToken'
  54.  
  55. SESSION = requests.session()
  56. SESSION.headers.update({'User-Agent': 'Niantic App'})
  57. SESSION.verify = False
  58.  
  59. DEBUG = False
  60. COORDS_LATITUDE = 0
  61. COORDS_LONGITUDE = 0
  62. COORDS_ALTITUDE = 0
  63. FLOAT_LAT = 0
  64. FLOAT_LONG = 0
  65. deflat, deflng = 0, 0
  66. default_step = 0.001
  67.  
  68. NUM_STEPS = 10
  69. PKMN_DATA_FILE = 'pkmn.json'
  70. PKSTOP_DATA_FILE = 'pkstop.json'
  71. GYM_DATA_FILE = 'gym.json'
  72. DATA = {
  73. 'pokemon':{},
  74. 'pokestop':{},
  75. 'gym':{}
  76. }
  77.  
  78. def f2i(float):
  79. return struct.unpack('<Q', struct.pack('<d', float))[0]
  80.  
  81. def f2h(float):
  82. return hex(struct.unpack('<Q', struct.pack('<d', float))[0])
  83.  
  84. def h2f(hex):
  85. return struct.unpack('<d', struct.pack('<Q', int(hex,16)))[0]
  86.  
  87. def prune():
  88. # prune despawned pokemon
  89. cur_time = int(time.time())
  90. for (pokehash, poke) in DATA['pokemon'].items():
  91. poke['timeleft'] = poke['timeleft'] - (cur_time - poke['timestamp'])
  92. poke['timestamp'] = cur_time
  93. if poke['timeleft'] <= 0:
  94. del DATA['pokemon'][pokehash]
  95.  
  96. def write_data_to_file():
  97. prune()
  98.  
  99. # different file for bandwith save
  100. with open(PKMN_DATA_FILE, 'w') as f:
  101. json.dump(DATA['pokemon'], f, indent=2)
  102.  
  103. with open(PKSTOP_DATA_FILE, 'w') as f:
  104. json.dump(DATA['pokestop'], f, indent=2)
  105.  
  106. with open(GYM_DATA_FILE, 'w') as f:
  107. json.dump(DATA['gym'], f, indent=2)
  108.  
  109. def add_pokemon(pokeId, name, lat, lng, timestamp, timeleft):
  110. pokehash = '%s:%s:%s' % (lat, lng, pokeId)
  111. if pokehash in DATA['pokemon']:
  112. if abs(DATA['pokemon'][pokehash]['timeleft'] - timeleft) < 2:
  113. # Assume it's the same one and average the expiry time
  114. DATA['pokemon'][pokehash]['timeleft'] += timeleft
  115. DATA['pokemon'][pokehash]['timeleft'] /= 2
  116. else:
  117. print('[-] Two %s at the same location (%s,%s)' % (name, lat, lng))
  118. DATA['pokemon'][pokehash]['timeleft'] = min(DATA['pokemon'][pokehash]['timeleft'], timeleft)
  119. else:
  120. DATA['pokemon'][pokehash] = {
  121. 'id': pokeId,
  122. 'name': name,
  123. 'lat': lat,
  124. 'lng': lng,
  125. 'timestamp': timestamp,
  126. 'timeleft': timeleft
  127. }
  128.  
  129. def add_pokestop(pokestopId, lat, lng, timeleft):
  130. if pokestopId in DATA['pokestop']:
  131. DATA['pokestop'][pokestopId]['timeleft'] = timeleft
  132. else:
  133. DATA['pokestop'][pokestopId] = {
  134. 'id': pokestopId,
  135. 'lat': lat,
  136. 'lng': lng,
  137. 'timeleft': timeleft
  138. }
  139.  
  140. def add_gym(gymId, team, lat, lng, points, pokemonGuard):
  141. if gymId in DATA['gym']:
  142. DATA['gym'][gymId]['team'] = team
  143. DATA['gym'][gymId]['points'] = points
  144. DATA['gym'][gymId]['guard'] = pokemonGuard
  145. else:
  146. DATA['gym'][gymId] = {
  147. 'id': gymId,
  148. 'team': team,
  149. 'lat': lat,
  150. 'lng': lng,
  151. 'points': points,
  152. 'guard': pokemonGuard
  153. }
  154.  
  155. def set_location(location_name):
  156. geolocator = GoogleV3()
  157. prog = re.compile('^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$')
  158. global deflat
  159. global deflng
  160. if prog.match(location_name):
  161. local_lat, local_lng = [float(x) for x in location_name.split(",")]
  162. alt = 0
  163. deflat, deflng = local_lat, local_lng
  164. else:
  165. loc = geolocator.geocode(location_name)
  166. deflat, deflng = local_lat, local_lng = loc.latitude, loc.longitude
  167. alt = loc.altitude
  168. print '[!] Your given location: {}'.format(loc.address.encode('utf-8'))
  169.  
  170. print('[!] lat/long/alt: {} {} {}'.format(local_lat, local_lng, alt))
  171. set_location_coords(local_lat, local_lng, alt)
  172.  
  173.  
  174. def set_location_coords(lat, lng, alt):
  175. global COORDS_LATITUDE, COORDS_LONGITUDE, COORDS_ALTITUDE
  176. global FLOAT_LAT, FLOAT_LONG
  177. FLOAT_LAT = lat
  178. FLOAT_LONG = lng
  179. COORDS_LATITUDE = f2i(lat) # 0x4042bd7c00000000 # f2i(lat)
  180. COORDS_LONGITUDE = f2i(lng) # 0xc05e8aae40000000 #f2i(lng)
  181. COORDS_ALTITUDE = f2i(alt)
  182.  
  183. def get_location_coords():
  184. return (COORDS_LATITUDE, COORDS_LONGITUDE, COORDS_ALTITUDE)
  185.  
  186. def api_req(api_endpoint, access_token, *mehs, **kw):
  187. while True:
  188. try:
  189. p_req = pokemon_pb2.RequestEnvelop()
  190. p_req.rpc_id = 1469378659230941192
  191.  
  192. p_req.unknown1 = 2
  193.  
  194. p_req.latitude, p_req.longitude, p_req.altitude = get_location_coords()
  195.  
  196. p_req.unknown12 = 989
  197.  
  198. if 'useauth' not in kw or not kw['useauth']:
  199. p_req.auth.provider = 'ptc'
  200. p_req.auth.token.contents = access_token
  201. p_req.auth.token.unknown13 = 14
  202. else:
  203. p_req.unknown11.unknown71 = kw['useauth'].unknown71
  204. p_req.unknown11.unknown72 = kw['useauth'].unknown72
  205. p_req.unknown11.unknown73 = kw['useauth'].unknown73
  206.  
  207. for meh in mehs:
  208. p_req.MergeFrom(meh)
  209.  
  210. protobuf = p_req.SerializeToString()
  211.  
  212. r = SESSION.post(api_endpoint, data=protobuf, verify=False)
  213.  
  214. p_ret = pokemon_pb2.ResponseEnvelop()
  215. p_ret.ParseFromString(r.content)
  216.  
  217. if DEBUG:
  218. print("REQUEST:")
  219. print(p_req)
  220. print("Response:")
  221. print(p_ret)
  222. print("\n\n")
  223.  
  224. if DEBUG:
  225. print("[ ] Sleeping for 1 second")
  226. time.sleep(0.51)
  227. return p_ret
  228. except Exception, e:
  229. if DEBUG:
  230. print(e)
  231. print('[-] API request error, retrying')
  232. time.sleep(0.51)
  233. continue
  234.  
  235. def get_profile(access_token, api, useauth, *reqq):
  236. req = pokemon_pb2.RequestEnvelop()
  237.  
  238. req1 = req.requests.add()
  239. req1.type = 2
  240. if len(reqq) >= 1:
  241. req1.MergeFrom(reqq[0])
  242.  
  243. req2 = req.requests.add()
  244. req2.type = 126
  245. if len(reqq) >= 2:
  246. req2.MergeFrom(reqq[1])
  247.  
  248. req3 = req.requests.add()
  249. req3.type = 4
  250. if len(reqq) >= 3:
  251. req3.MergeFrom(reqq[2])
  252.  
  253. req4 = req.requests.add()
  254. req4.type = 129
  255. if len(reqq) >= 4:
  256. req4.MergeFrom(reqq[3])
  257.  
  258. req5 = req.requests.add()
  259. req5.type = 5
  260. if len(reqq) >= 5:
  261. req5.MergeFrom(reqq[4])
  262.  
  263. return api_req(api, access_token, req, useauth = useauth)
  264.  
  265. def get_api_endpoint(access_token, api = API_URL):
  266. p_ret = get_profile(access_token, api, None)
  267. try:
  268. return ('https://%s/rpc' % p_ret.api_url)
  269. except:
  270. return None
  271.  
  272.  
  273. def login_ptc(username, password):
  274. print('[!] login for: {}'.format(username))
  275. head = {'User-Agent': 'Niantic App'}
  276. r = SESSION.get(LOGIN_URL, headers=head)
  277.  
  278. try:
  279. jdata = json.loads(r.content)
  280. except ValueError, e:
  281. debug('login_ptc: could not decode JSON from {}'.format(r.content))
  282. return None
  283.  
  284. # Maximum password length is 15 (sign in page enforces this limit, API does not)
  285.  
  286. if len(password) > 15:
  287. print '[!] Trimming password to 15 characters'
  288. password = password[:15]
  289.  
  290. data = {
  291. 'lt': jdata['lt'],
  292. 'execution': jdata['execution'],
  293. '_eventId': 'submit',
  294. 'username': username,
  295. 'password': password,
  296. }
  297. r1 = SESSION.post(LOGIN_URL, data=data, headers=head)
  298.  
  299. ticket = None
  300. try:
  301. ticket = re.sub('.*ticket=', '', r1.history[0].headers['Location'])
  302. except Exception, e:
  303. if DEBUG:
  304. print(r1.json()['errors'][0])
  305. return None
  306.  
  307. data1 = {
  308. 'client_id': 'mobile-app_pokemon-go',
  309. 'redirect_uri': 'https://www.nianticlabs.com/pokemongo/error',
  310. 'client_secret': PTC_CLIENT_SECRET,
  311. 'grant_type': 'refresh_token',
  312. 'code': ticket,
  313. }
  314. r2 = SESSION.post(LOGIN_OAUTH, data=data1)
  315. access_token = re.sub('&expires.*', '', r2.content)
  316. access_token = re.sub('.*access_token=', '', access_token)
  317. return access_token
  318.  
  319. def raw_heartbeat(api_endpoint, access_token, response):
  320. m4 = pokemon_pb2.RequestEnvelop.Requests()
  321. m = pokemon_pb2.RequestEnvelop.MessageSingleInt()
  322. m.f1 = int(time.time() * 1000)
  323. m4.message = m.SerializeToString()
  324. m5 = pokemon_pb2.RequestEnvelop.Requests()
  325. m = pokemon_pb2.RequestEnvelop.MessageSingleString()
  326. m.bytes = "05daf51635c82611d1aac95c0b051d3ec088a930"
  327. m5.message = m.SerializeToString()
  328.  
  329. walk = sorted(getNeighbors())
  330.  
  331. m1 = pokemon_pb2.RequestEnvelop.Requests()
  332. m1.type = 106
  333. m = pokemon_pb2.RequestEnvelop.MessageQuad()
  334. m.f1 = ''.join(map(encode, walk))
  335. m.f2 = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
  336. m.lat = COORDS_LATITUDE
  337. m.long = COORDS_LONGITUDE
  338. m1.message = m.SerializeToString()
  339. response = get_profile(
  340. access_token,
  341. api_endpoint,
  342. response.unknown7,
  343. m1,
  344. pokemon_pb2.RequestEnvelop.Requests(),
  345. m4,
  346. pokemon_pb2.RequestEnvelop.Requests(),
  347. m5)
  348. try:
  349. payload = response.payload[0]
  350. except (AttributeError, IndexError):
  351. return
  352. heartbeat = pokemon_pb2.ResponseEnvelop.HeartbeatPayload()
  353. heartbeat.ParseFromString(payload)
  354. return heartbeat
  355.  
  356. def heartbeat(api_endpoint, access_token, response):
  357. while True:
  358. try:
  359. h = raw_heartbeat(api_endpoint, access_token, response)
  360. return h
  361. except Exception, e:
  362. if DEBUG:
  363. print(e)
  364. print('[-] Heartbeat missed, retrying')
  365.  
  366.  
  367. def scan(api_endpoint, access_token, response, origin, pokemons):
  368. steps = 0
  369. steplimit = NUM_STEPS
  370. pos = 1
  371. x = 0
  372. y = 0
  373. dx = 0
  374. dy = -1
  375. while 4 < 5:
  376. if (steps >= steplimit**2):
  377. steps = 0
  378. pos = 1
  379. x = 0
  380. y = 0
  381. dx = 0
  382. dy = -1
  383. while steps < steplimit**2:
  384. original_lat = FLOAT_LAT
  385. original_long = FLOAT_LONG
  386. parent = CellId.from_lat_lng(LatLng.from_degrees(FLOAT_LAT, FLOAT_LONG)).parent(15)
  387.  
  388. h = heartbeat(api_endpoint, access_token, response)
  389. hs = [h]
  390. seen = set([])
  391. for child in parent.children():
  392. latlng = LatLng.from_point(Cell(child).get_center())
  393. set_location_coords(latlng.lat().degrees, latlng.lng().degrees, 0)
  394. hs.append(heartbeat(api_endpoint, access_token, response))
  395. set_location_coords(original_lat, original_long, 0)
  396.  
  397. visible = []
  398.  
  399. for hh in hs:
  400. try:
  401. for cell in hh.cells:
  402. for wild in cell.WildPokemon:
  403. hash = wild.SpawnPointId + ':' + str(wild.pokemon.PokemonId)
  404. if (hash not in seen):
  405. visible.append(wild)
  406. seen.add(hash)
  407. if cell.Fort:
  408. for Fort in cell.Fort:
  409. if Fort.Enabled == True:
  410. if Fort.GymPoints:
  411. add_gym(Fort.FortId, Fort.Team, Fort.Latitude, Fort.Longitude, Fort.GymPoints, pokemons[Fort.GuardPokemonId - 1]['Name'])
  412. elif Fort.FortType:
  413. expire_time = 0
  414. if Fort.LureInfo.LureExpiresTimestampMs:
  415. expire_time = datetime\
  416. .fromtimestamp(Fort.LureInfo.LureExpiresTimestampMs / 1000.0)\
  417. .strftime("%H:%M:%S")
  418. add_pokestop(Fort.FortId, Fort.Latitude, Fort.Longitude, expire_time)
  419.  
  420. except AttributeError:
  421. break
  422.  
  423. for poke in visible:
  424. other = LatLng.from_degrees(poke.Latitude, poke.Longitude)
  425. diff = other - origin
  426. # print(diff)
  427. difflat = diff.lat().degrees
  428. difflng = diff.lng().degrees
  429.  
  430. print("[+] (%s) %s is visible at (%s, %s) for %s seconds" % (poke.pokemon.PokemonId, pokemons[poke.pokemon.PokemonId - 1]['Name'], poke.Latitude, poke.Longitude, poke.TimeTillHiddenMs / 1000))
  431.  
  432. timestamp = int(time.time())
  433. add_pokemon(poke.pokemon.PokemonId, pokemons[poke.pokemon.PokemonId - 1]['Name'], poke.Latitude, poke.Longitude, timestamp, poke.TimeTillHiddenMs / 1000)
  434.  
  435. write_data_to_file()
  436.  
  437. if (-steplimit/2 < x <= steplimit/2) and (-steplimit/2 < y <= steplimit/2):
  438. set_location_coords((x * 0.0025) + deflat, (y * 0.0025 ) + deflng, 0)
  439. if x == y or (x < 0 and x == -y) or (x > 0 and x == 1-y):
  440. dx, dy = -dy, dx
  441. x, y = x+dx, y+dy
  442. steps +=1
  443.  
  444. print('[+] Scan: %0.1f %%' % (((steps + (pos * .25) - .25) / steplimit**2) * 100))
  445.  
  446.  
  447. def main():
  448. full_path = os.path.realpath(__file__)
  449. (path, filename) = os.path.split(full_path)
  450.  
  451. write_data_to_file()
  452. pokemons = json.load(open(path + '/pokemon.json'))
  453. #parser = argparse.ArgumentParser()
  454. #parser.add_argument("-u", "--username", help="PTC Username", required=True)
  455. #parser.add_argument("-p", "--password", help="PTC Password", required=True)
  456. #parser.add_argument("-l", "--location", help="Location", required=True)
  457. #parser.add_argument("-d", "--debug", help="Debug Mode", action='store_true')
  458. #parser.set_defaults(DEBUG=False)
  459. #args = parser.parse_args()
  460.  
  461. #if args.debug:
  462. # global DEBUG
  463. # DEBUG = True
  464. # print('[!] DEBUG mode on')
  465.  
  466. set_location("San Fernando, Cadiz")
  467.  
  468. access_token = login_ptc("USUARIO", "CONTRASEÑA")
  469. if access_token is None:
  470. print('[-] Error logging in: possible wrong username/password')
  471. return
  472. print('[+] RPC Session Token: {} ...'.format(access_token[:25]))
  473.  
  474. api_endpoint = get_api_endpoint(access_token)
  475. if api_endpoint is None:
  476. print('[-] RPC server offline')
  477. return
  478. print('[+] Received API endpoint: {}'.format(api_endpoint))
  479.  
  480. response = get_profile(access_token, api_endpoint, None)
  481. if response is not None:
  482. print('[+] Login successful')
  483.  
  484. if response.payload != '':
  485. payload = response.payload[0]
  486. profile = pokemon_pb2.ResponseEnvelop.ProfilePayload()
  487. profile.ParseFromString(payload)
  488. print('[+] Username: {}'.format(profile.profile.username))
  489.  
  490. creation_time = datetime.fromtimestamp(int(profile.profile.creation_time)/1000)
  491. print('[+] You are playing Pokemon Go since: {}'.format(
  492. creation_time.strftime('%Y-%m-%d %H:%M:%S'),
  493. ))
  494.  
  495. for curr in profile.profile.currency:
  496. print('[+] {}: {}'.format(curr.type, curr.amount))
  497. else:
  498. print('[-] Profile payload empty')
  499. else:
  500. print('[-] Ooops...')
  501.  
  502. origin = LatLng.from_degrees(FLOAT_LAT, FLOAT_LONG)
  503.  
  504. while True:
  505. scan(api_endpoint, access_token, response, origin, pokemons)
  506.  
  507.  
  508. if __name__ == '__main__':
  509. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement