Guest User

Untitled

a guest
Jul 25th, 2018
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.84 KB | None | 0 0
  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. response will look like
  49. {"response_data":{"authorize_token":"...","dummy_token":"..."},"release_info":[...],"status_code":200}
  50.  
  51. session_key = uid ^ base64_decode(response_dummy_token)
  52.  
  53. encrypted_user = base64(encrypt_aes_128_cbc(data=user, key=session_key))
  54. encrypted_pass = base64(encrypt_aes_128_cbc(data=pass, key=session_key))
  55.  
  56. POST /main.php/login/login
  57. {"login_key":"encrypted_user","login_passwd":"encrypted_pass"}
  58.  
  59. 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)
  60.  
  61. 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)
  62.  
  63. ####################################################
  64. # crypto #
  65. ####################################################
  66. 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
  67.  
  68. public_key_encrypt uses this public key
  69.  
  70. -----BEGIN PUBLIC KEY-----
  71. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDnBh9E2yTc5p5ryLQi/9wcRHLj
  72. T14CsJ+gNCf2Yr1p0iQjc7LyOTyRTkxbR0VketWKy9rzVgHtzdH+3T8KlIIPGYc+
  73. GFSxpXqX0tS4rV2aRIftkse+xJzkY5OlxQvWfQU7anwUiuh6peLJgpoiloQ6KS6z
  74. LbYcBxRDVsUmYaFDhwIDAQAB
  75. -----END PUBLIC KEY-----
  76.  
  77. with pkcs1 padding
  78.  
  79. here's an example of the aforementioned crypto functions implemented in python 2.7 using m2crypto
  80.  
  81. import os
  82. from M2Crypto import BIO, RSA, EVP
  83.  
  84. def encrypt_aes_128_cbc(data, key):
  85. iv = os.urandom(16)
  86. cipher = EVP.Cipher(alg='aes_128_cbc', key=key[:16], iv=iv, op=1, padding=True)
  87. v = cipher.update(data)
  88. v = iv + v + cipher.final()
  89. return v
  90.  
  91. def public_key_encrypt(data):
  92. bio = BIO.MemoryBuffer('''-----BEGIN PUBLIC KEY-----
  93. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDnBh9E2yTc5p5ryLQi/9wcRHLj
  94. T14CsJ+gNCf2Yr1p0iQjc7LyOTyRTkxbR0VketWKy9rzVgHtzdH+3T8KlIIPGYc+
  95. GFSxpXqX0tS4rV2aRIftkse+xJzkY5OlxQvWfQU7anwUiuh6peLJgpoiloQ6KS6z
  96. LbYcBxRDVsUmYaFDhwIDAQAB
  97. -----END PUBLIC KEY-----
  98. ''')
  99. pubkey = RSA.load_pub_key_bio(bio)
  100. return pubkey.public_encrypt(data, RSA.pkcs1_padding)
  101.  
  102. example python implementation of the HMAC SHA1 hash for X-Message-Code
  103.  
  104. import hmac
  105. import hashlib
  106.  
  107. def gen_xmessagecode(data, key):
  108. try:
  109. hmacsha1 = hmac.new(key, digestmod='sha1')
  110. except AttributeError:
  111. hmacsha1 = hmac.new(key, digestmod=hashlib.sha1)
  112.  
  113. hmacsha1.update(data)
  114. return hmacsha1.hexdigest()
  115.  
  116. ####################################################
  117. # EN Client-Version 16.0.79 / Bundle-Version 6.0.2 #
  118. ####################################################
  119. host = "prod.en-lovelive.klabgames.net"
  120. initial_string = "vXT9PNz3SRyioCzMHnNcOuq3a6BqJD6C"
  121. 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 ]
  122.  
  123. lbonus_key:
  124. "HnNcOuq3a6BqJD6C" (2nd half of initial_string)
  125. XOR [ 32 37 37 34 62 39 65 37 39 61 62 31 36 65 35 35 ] (1st half of initial_bytes)
  126. = [ 7A 59 79 57 2D 4C 14 04 58 57 20 40 7C 21 03 76 ]
  127.  
  128. "vXT9PNz3SRyioCzM" (1st half of initial_string)
  129. XOR [ 30 35 66 39 65 62 36 62 66 38 34 61 31 39 65 61 ] (2nd half of initial_bytes)
  130. = [ 46 6D 32 00 35 2C 4C 51 35 6A 4D 08 5E 7A 1F 2C ]
  131.  
  132. join these together and you have
  133. 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 ]
  134.  
  135. ####################################################
  136. # JP Client-Version 34.2 / Bundle-Version 6.2 #
  137. ####################################################
  138. host = "prod-jp.lovelive.ge.klabgames.net"
  139. initial_string = "eit4Ahph4aiX4ohmephuobei6SooX9xo"
  140. 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 ]
  141.  
  142. lbonus_key:
  143. "ephuobei6SooX9xo" (2nd half of initial_string)
  144. XOR [ 30 38 64 65 37 32 38 31 64 32 30 64 63 33 66 62 ] (1st half of initial_bytes)
  145. = [ 55 48 0C 10 58 50 5D 58 52 61 5F 0B 3B 0A 1E 0D ]
  146.  
  147. "eit4Ahph4aiX4ohm" (1st half of initial_string)
  148. XOR [ 61 35 31 39 30 63 63 64 30 64 61 32 39 36 32 32 ] (2nd half of initial_bytes)
  149. = [ 04 5C 45 0D 71 0B 13 0C 04 05 08 6A 0D 59 5A 5F ]
  150.  
  151. join these together and you have
  152. 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