m34v2.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #!/usr/bin/env python3
  2. import subprocess
  3. import re
  4. import lxml
  5. from lxml import html
  6. import urllib
  7. import urllib.request
  8. import urllib3
  9. import base64
  10. class Foo:
  11. def __init__(self):
  12. self.headers = {}
  13. self.headers['User-Agent'] = 'Mozilla/5.0'
  14. self.pool = urllib3.PoolManager()
  15. self.cookies = {}
  16. def perform_xhr_post(self, url, extra_headers=[], fields={}):
  17. pool = self.pool
  18. headers = self.headers.copy()
  19. headers['X-Requested-With'] = 'XMLHttpRequest'
  20. for (k,v) in extra_headers:
  21. headers[k] = v
  22. xs = list(self.cookies.items())
  23. headers['Cookie'] = "; ".join(["%s=%s" % (k,v) \
  24. for (k,v) in xs \
  25. if k != 'PHPSESSID'])
  26. print("request POST %s" % url)
  27. print("request headers: %s" % headers)
  28. print("request fields: %s" % fields)
  29. f = pool.request_encode_body(method='POST',
  30. url=url,
  31. fields=fields,
  32. encode_multipart=False,
  33. headers=headers,
  34. redirect=False)
  35. return self.postprocess(f)
  36. # called by perform_get and perform_xhr_post after executing the request
  37. # f = the request object
  38. def postprocess(self, f):
  39. print("response headers: %s" % f.headers)
  40. if f.get_redirect_location():
  41. print("redirect: %s" % f.get_redirect_location())
  42. for cookie1 in f.headers.get_all('Set-Cookie'):
  43. cookies1 = re.findall('([^= ]*)=([^; ]*); ', cookie1)
  44. for (k,v) in cookies1:
  45. # what's the exact syntax? we don't really care. just remove the accidentally captured strings
  46. if not (re.match('[Mm]ax-[Aa]ge', k) or re.match('path', k)):
  47. if self.cookies.get(k):
  48. print("replacing cookie %s with %s" % (k, v) )
  49. else:
  50. print("setting cookie %s to %s" % (k, v) )
  51. if 'himalaya-site-ident' == k:
  52. print("himalaya-site-ident: ",base64.b64decode(v.replace('%3D', '=')))
  53. self.cookies[k] = v
  54. print(f.data)
  55. print()
  56. return f
  57. def perform_get(self, url, redirect=False):
  58. pool = self.pool
  59. headers = self.headers.copy()
  60. headers['Cookie'] = "; ".join(["%s=%s" % (k,v) for (k,v) in self.cookies.items()])
  61. print("request GET %s" % url)
  62. print("request headers: %s" % headers)
  63. f = pool.request(method='GET', url=url, headers=headers, redirect=redirect)
  64. return self.postprocess(f)
  65. print("let's go")
  66. foo = Foo()
  67. dummy='http://detectportal.firefox.com/success.txt'
  68. f1 = foo.perform_get(dummy)
  69. print(f1)
  70. base = re.findall(b'https://.*\\.conn4\\.com', f1.data)[0]
  71. base_host = re.findall(b'(?<=https://).*\\.conn4\\.com', f1.data)[0]
  72. url = f1.get_redirect_location()
  73. f2 = foo.perform_get(url)
  74. url = f2.get_redirect_location()
  75. f2 = foo.perform_get(url)
  76. f2_headers = {k.lower(): v for k, v in f2.headers.items()}
  77. print(f2_headers)
  78. url3 = f2_headers.get('location')
  79. if url3 is None:
  80. f3 = foo.perform_get(url)
  81. f3data = f2.data
  82. else:
  83. f3data = f3.data
  84. url = url3
  85. tokenstring = re.findall(b'"token":"([^"]+)"', f3data)[0]
  86. scenestring = re.findall(b'"id":"([^"]+)"', f3data)[0]
  87. sceneurl = b"%s/scenes/%s/" % (base, scenestring)
  88. # WTF, shouldn't urllib3 be using "bytes" everywhere????
  89. url = sceneurl.decode()
  90. f4aa = foo.perform_get(url)
  91. headers4 = {}
  92. # headers['Referer'] = 'https://accor.conn4.com/'
  93. headers4['Referer'] = sceneurl.decode()
  94. headers4['Cookie'] = "; ".join(["%s=%s" % (k,v) for (k,v) in foo.cookies.items()])
  95. headers4['X-Requested-With'] = 'XMLHttpRequest'
  96. headers4['Origin'] = base.decode()
  97. # if we made a mistake before arriving here, the server uses this value for Allow-Origin instead:
  98. # headers4['Origin'] = 'https://portal-eu-ffm01.conn4.com'
  99. headers4['Accept'] = '*/*'
  100. # unnecessary:
  101. # headers4['Cache-Control'] = 'no-cache'
  102. # headers4['Accept-Language'] = 'en-US,en;q=0.5'
  103. # headers4['Connection'] = 'keep-alive'
  104. headers4['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
  105. headers4['Host'] = base_host.decode()
  106. # 'accor.conn4.com'
  107. url = '%s/wbs/api/v1/create-session/' % base.decode()
  108. form = {}
  109. form['session_id'] = ''
  110. form['with-tariffs'] = '1'
  111. form['locale'] = 'en_US'
  112. form['authorization'] = "token=%s" % tokenstring.decode()
  113. f4a = foo.perform_xhr_post(url, extra_headers=list(headers4.items()), fields=form)
  114. sessions = re.findall(b'"session":"([^"]+)"', f4a.data)[0].decode()
  115. print(sessions)
  116. # oh, it's the same as the PHPSESSIONID.
  117. print(f4a.data)
  118. # wbsTokenstring = re.findall(b'wbsToken.*"token":"([^"]+)"', f4a.data)[0]
  119. print("-----------")
  120. url = '%s/_time?t=1577515801949' % base.decode()
  121. foo.perform_xhr_post(url)
  122. # "get" in original trace, but "post" works fine
  123. # firefox did this, but it's unnecessary (maybe this is the case where mac address hasn't changed)
  124. # url = 'https://accor.conn4.com/wbs/api/v1/login/free/'
  125. # form = {}
  126. # form['authorization'] = 'session=%s' % sessions
  127. # f4 = foo.perform_xhr_post(url, extra_headers=list(headers4.items()), fields=form)
  128. url = '%s/wbs/api/v1/register/free/' % base.decode()
  129. form = {}
  130. form['authorization'] = 'session=%s' % sessions
  131. form['registration_type'] = 'terms-only'
  132. form['authorization'] = "token=%s" % tokenstring.decode()
  133. form['registration[terms]'] = '1'
  134. f5 = foo.perform_xhr_post(url, extra_headers=list(headers4.items()), fields=form)
  135. # b'{"error":{"message":"Internal system exception","code":652,"backend-code":"1613"},"