Guest User

Untitled

a guest
Jul 25th, 2018
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. if you're reading this, you're probably attempting to reverse-engineer a certain mobile game's protocol. congratulations! you have just found a gold mine. I put this together over months worth of research i did to keep my bot updated.
  2.  
  3. if you use this information wisely and put in some effort and research on your own you will be able to make your very own bot or client
  4.  
  5. note that by the time you read this the keys will probably be outdated and you will have to extract them yourself
  6.  
  7. uid = random 32-byte array/string
  8. initial_key = initial_string ^ initial_bytes
  9. (these are at the bottom, they differ between EN and JP and they often change with updates. especially initial_bytes)
  10.  
  11. device_info looks something like this (I censored the values because I don't know if they can be linked back to me, you will have to sniff http traffic and get your exact values, especially the hashes)
  12. {
  13. "GreatStockOption":"...",
  14. "Hardware":"...",
  15. "adbEnbled":"...",
  16. "basePath":"...",
  17. "db_sha1":"...",
  18. "ro.build.fingerprint":"...",
  19. "ro.build.tags":"test-keys",
  20. "ro.build.version.release":"...",
  21. "ro.product.board":"...",
  22. "ro.product.brand":"...",
  23. "ro.product.device":"...",
  24. "ro.product.manufacturer":"...",
  25. "ro.product.model":"...",
  26. "ro.product.name":"...",
  27. "signature":"...",
  28. "SuspiciousElement":[]
  29. }
  30.  
  31. device_data = base64(device_info)
  32. user, pass = your user/pass from the GameEngineActivity.xml or randomly generated if creating a new account
  33. authkey_json = {"1":"user","2":"passwd","3":"device_data"}
  34.  
  35. (crypto is explained later, don't worry)
  36. authkey_data = base64(encrypt_aes_128_cbc(data=authkey_json, key=uid))
  37. authkey_token = base64(public_key_encrypt(uid))
  38.  
  39. there's a bunch of http headers that you need to send and keep track of.
  40. http responses are gzipped.
  41. see https://github.com/twisteroidambassador/llsifclient . it's an outdated implementation that doesn't work anymore, but it has most of the required http headers
  42.  
  43. additionally, every http request is signed with a HMAC SHA1 hash of the request body using session_key as the key. this hash is in the request header X-Message-Code
  44.  
  45. POST /main.php/login/authkey
  46. {"dummy_token":"authkey_token","auth_data":"authkey_data"}
  47.  
  48. for this particular request, the HMAC SHA1 key is uid ^ initial_key. the response will give us a token to generate a session key that we will use for subsequent requests
  49.  
  50. response will look like
  51. {"response_data":{"authorize_token":"...","dummy_token":"..."},"release_info":[...],"status_code":200}
  52.  
  53. session_key = uid ^ base64_decode(response_dummy_token)
  54.  
  55. encrypted_user = base64(encrypt_aes_128_cbc(data=user, key=session_key))
  56. encrypted_pass = base64(encrypt_aes_128_cbc(data=pass, key=session_key))
  57.  
  58. POST /main.php/login/login
  59. {"login_key":"encrypted_user","login_passwd":"encrypted_pass"}
  60.  
  61. since 30.2 jp version started using more of the key shuffling functions hidden in the assets lua code. this results in endpoints such as lbonus using a different key for the HMAC SHA1 signature instead of session_key, usually generated by shuffling initial_string and initial_key and xoring them together (for example swapping the first and second half of initial_string and xoring that with initial_key)
  62.  
  63. this is now also in the EN version since Client-Version 16.0.79 / Bundle-Version 6.0.2 (maybe even earlier, I haven't touched this in 3 months)
  64.  
  65. ####################################################
  66. # crypto #
  67. ####################################################
  68. encrypt_aes_128_cbc cuts the key to the first 16 bytes and uses a random 16-byte IV. the result is iv followed by the encrypted data
  69.  
  70. public_key_encrypt uses this public key
  71.  
  72. -----BEGIN PUBLIC KEY-----
  73. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDnBh9E2yTc5p5ryLQi/9wcRHLj
  74. T14CsJ+gNCf2Yr1p0iQjc7LyOTyRTkxbR0VketWKy9rzVgHtzdH+3T8KlIIPGYc+
  75. GFSxpXqX0tS4rV2aRIftkse+xJzkY5OlxQvWfQU7anwUiuh6peLJgpoiloQ6KS6z
  76. LbYcBxRDVsUmYaFDhwIDAQAB
  77. -----END PUBLIC KEY-----
  78.  
  79. with pkcs1 padding
  80.  
  81. here's an example of the aforementioned crypto functions implemented in python 2.7 using m2crypto
  82.  
  83. import os
  84. from M2Crypto import BIO, RSA, EVP
  85.  
  86. def encrypt_aes_128_cbc(data, key):
  87. iv = os.urandom(16)
  88. cipher = EVP.Cipher(alg='aes_128_cbc', key=key[:16], iv=iv, op=1, padding=True)
  89. v = cipher.update(data)
  90. v = iv + v + cipher.final()
  91. return v
  92.  
  93. def public_key_encrypt(data):
  94. bio = BIO.MemoryBuffer('''-----BEGIN PUBLIC KEY-----
  95. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDnBh9E2yTc5p5ryLQi/9wcRHLj
  96. T14CsJ+gNCf2Yr1p0iQjc7LyOTyRTkxbR0VketWKy9rzVgHtzdH+3T8KlIIPGYc+
  97. GFSxpXqX0tS4rV2aRIftkse+xJzkY5OlxQvWfQU7anwUiuh6peLJgpoiloQ6KS6z
  98. LbYcBxRDVsUmYaFDhwIDAQAB
  99. -----END PUBLIC KEY-----
  100. ''')
  101. pubkey = RSA.load_pub_key_bio(bio)
  102. return pubkey.public_encrypt(data, RSA.pkcs1_padding)
  103.  
  104. example python implementation of the HMAC SHA1 hash for X-Message-Code
  105.  
  106. import hmac
  107. import hashlib
  108.  
  109. def gen_xmessagecode(data, key):
  110. try:
  111. hmacsha1 = hmac.new(key, digestmod='sha1')
  112. except AttributeError:
  113. hmacsha1 = hmac.new(key, digestmod=hashlib.sha1)
  114.  
  115. hmacsha1.update(data)
  116. return hmacsha1.hexdigest()
  117.  
  118. ####################################################
  119. # EN Client-Version 16.0.79 / Bundle-Version 6.0.2 #
  120. ####################################################
  121. host = "prod.en-lovelive.klabgames.net"
  122. initial_string = "vXT9PNz3SRyioCzMHnNcOuq3a6BqJD6C"
  123. initial_bytes = [ 32 37 37 34 62 39 65 37 39 61 62 31 36 65 35 35 30 35 66 39 65 62 36 62 66 38 34 61 31 39 65 61 ]
  124.  
  125. lbonus_key:
  126. "HnNcOuq3a6BqJD6C" (2nd half of initial_string)
  127. XOR [ 32 37 37 34 62 39 65 37 39 61 62 31 36 65 35 35 ] (1st half of initial_bytes)
  128. = [ 7A 59 79 57 2D 4C 14 04 58 57 20 40 7C 21 03 76 ]
  129.  
  130. "vXT9PNz3SRyioCzM" (1st half of initial_string)
  131. XOR [ 30 35 66 39 65 62 36 62 66 38 34 61 31 39 65 61 ] (2nd half of initial_bytes)
  132. = [ 46 6D 32 00 35 2C 4C 51 35 6A 4D 08 5E 7A 1F 2C ]
  133.  
  134. join these together and you have
  135. lbonus_key = [ 7A 59 79 57 2D 4C 14 04 58 57 20 40 7C 21 03 76 46 6D 32 00 35 2C 4C 51 35 6A 4D 08 5E 7A 1F 2C ]
  136.  
  137. ####################################################
  138. # JP Client-Version 34.2 / Bundle-Version 6.2 #
  139. ####################################################
  140. host = "prod-jp.lovelive.ge.klabgames.net"
  141. initial_string = "eit4Ahph4aiX4ohmephuobei6SooX9xo"
  142. initial_bytes = [ 30 38 64 65 37 32 38 31 64 32 30 64 63 33 66 62 61 35 31 39 30 63 63 64 30 64 61 32 39 36 32 32 ]
  143.  
  144. lbonus_key:
  145. "ephuobei6SooX9xo" (2nd half of initial_string)
  146. XOR [ 30 38 64 65 37 32 38 31 64 32 30 64 63 33 66 62 ] (1st half of initial_bytes)
  147. = [ 55 48 0C 10 58 50 5D 58 52 61 5F 0B 3B 0A 1E 0D ]
  148.  
  149. "eit4Ahph4aiX4ohm" (1st half of initial_string)
  150. XOR [ 61 35 31 39 30 63 63 64 30 64 61 32 39 36 32 32 ] (2nd half of initial_bytes)
  151. = [ 04 5C 45 0D 71 0B 13 0C 04 05 08 6A 0D 59 5A 5F ]
  152.  
  153. join these together and you have
  154. lbonus_key = [ 55 48 0C 10 58 50 5D 58 52 61 5F 0B 3B 0A 1E 0D 04 5C 45 0D 71 0B 13 0C 04 05 08 6A 0D 59 5A 5F ]
Add Comment
Please, Sign In to add comment