Advertisement
Guest User

here

a guest
Dec 26th, 2016
1,704
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.55 KB | None | 0 0
  1. request = require 'request'
  2.  
  3. querystring = require 'querystring'
  4.  
  5. {parseString} = require 'xml2js'
  6.  
  7. socks_agent = require 'socks5-https-client/lib/Agent'
  8.  
  9. url = require 'url'
  10.  
  11. RosCrypt = require './roscrypt'
  12.  
  13. # gta5
  14. game =
  15. name: 'gta5'
  16. rosCrypt: RosCrypt 'C4pWJwWIKGUxcHd69eGl2AOwH2zrmzZAoQeHfQFcMelybd32QFw9s10px6k0o75XZeB5YsI9Q9TdeuRgdbvKsxc='
  17. newSecurity: true
  18.  
  19. crypto = require 'crypto'
  20.  
  21. addSecurity = (game, options, sessionKey, sessionTicket) ->
  22. # define headers
  23. options.headers['ros-SecurityFlags'] = '239' # nothing else is allowed in prod
  24. options.headers['ros-Challenge'] = new Buffer(8).toString 'base64' # to make the HMAC more random?
  25. options.headers['ros-SessionTicket'] = sessionTicket
  26.  
  27. # set HMAC
  28. nullBuffer = new Buffer(1)
  29. nullBuffer.writeUInt8 0, 0
  30.  
  31. baseKey = game.rosCrypt.getBaseKey false
  32.  
  33. key = new Buffer(16)
  34.  
  35. for i in [0..15]
  36. key.writeUInt8 (baseKey.readUInt8(i) ^ sessionKey.readUInt8(i)), i
  37.  
  38. hmac = crypto.createHmac 'sha1', key
  39.  
  40. # helper to append null buffer
  41. updateString = (str) ->
  42. hmac.update str
  43. hmac.update nullBuffer
  44.  
  45. # add the request method
  46. updateString options.method
  47.  
  48. # add the request URI
  49. parts = url.parse options.url
  50.  
  51. updateString parts.path
  52.  
  53. # security headers
  54. updateString options.headers['ros-SecurityFlags']
  55. updateString options.headers['ros-SessionTicket']
  56. updateString options.headers['ros-Challenge']
  57.  
  58. # platform hash key
  59. hmac.update game.rosCrypt.getBaseKey true
  60.  
  61. # set hmac
  62. options.headers['ros-HeadersHmac'] = hmac.digest().toString 'base64'
  63.  
  64. requestRos = (game, service, kv, secOptions, cb) ->
  65. ua = game.rosCrypt.encryptUA "e=1,t=#{ game.name },p=pcros,v=11"
  66.  
  67. sessionKey = null
  68. sessionTicket = null
  69.  
  70. sessionKey = secOptions.sessionKey if secOptions
  71. sessionTicket = secOptions.sessionTicket if secOptions
  72.  
  73. sessionKey = new Buffer(sessionKey, 'base64') if sessionKey
  74.  
  75. options =
  76. url: "https://prod.ros.rockstargames.com/#{ game.name }/11/gameservices/#{ service }"
  77. headers:
  78. 'User-Agent': 'ros ' + ua
  79. 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
  80. 'Accept': 'text/html'
  81. method: 'POST'
  82. body: game.rosCrypt.encrypt new Buffer(querystring.stringify kv), sessionKey
  83. encoding: null
  84. strictSSL: false
  85. agentClass: socks_agent
  86. agentOptions:
  87. socksPort: 9050
  88.  
  89. if game.newSecurity and sessionKey
  90. addSecurity game, options, sessionKey, sessionTicket
  91.  
  92. await request options, defer err, response, body
  93.  
  94. if err
  95. cb err
  96. else
  97. try
  98. decrypted = game.rosCrypt.decrypt(body, false, sessionKey).toString 'utf8'
  99.  
  100. cb null, decrypted
  101. catch e
  102. console.log response.statusCode
  103. console.log response.headers
  104. console.log e
  105.  
  106. cb e
  107.  
  108. # auth ticket handler
  109. authData = {}
  110.  
  111. authUser = process.env.ROS_USER
  112. authPassword = process.env.ROS_PASSWORD
  113.  
  114. doAuth = () ->
  115. requestRos game, 'auth.asmx/CreateTicketSc3', { ticket: '', email: '', platformName: 'pcros', nickname: authUser, password: authPassword }, null, (err, res) ->
  116. return if err
  117.  
  118. parseString res, (err, res) ->
  119. res = res.Response
  120.  
  121. console.log "Reauthenticated as #{ res.RockstarAccount[0].Nickname }"
  122.  
  123. authData.ticket = res.Ticket[0]
  124. authData.sessionTicket = res.SessionTicket[0]
  125. authData.sessionKey = res.SessionKey[0]
  126.  
  127. setTimeout doAuth, 7200 * 1000
  128.  
  129.  
  130. doAuth()
  131.  
  132. savedUris = {}
  133.  
  134. allowedPaths = ['DigitalData/DLCPacks2', 'DigitalData/DLCPacks3', 'Game_EFIGS']
  135.  
  136. # webapp
  137. express = require 'express'
  138.  
  139. app = express()
  140.  
  141. app.get '/file', (req, res) ->
  142. filename = req.query.name
  143.  
  144. # check if the path is allowed
  145. allowed = false
  146.  
  147. for path of allowedPaths
  148. if filename.indexOf path != -1
  149. allowed = true
  150. break
  151.  
  152. if not allowed
  153. res.status(404).end()
  154. return
  155.  
  156. if savedUris[filename] and savedUris[filename].expires > new Date()
  157. res.redirect(savedUris[filename].uri)
  158. return
  159.  
  160. await requestRos game, 'Entitlements.asmx/GetDownloadUrlFromPath', { ticket: authData.ticket, path: filename }, authData, defer err, resp
  161.  
  162. await parseString resp, defer err, resp
  163.  
  164. uri = resp.Response.Url[0]
  165.  
  166. expireDate = new Date()
  167. expireDate.setSeconds expireDate.getSeconds() + 240
  168.  
  169. savedUris[filename] =
  170. expires: expireDate
  171. uri: uri
  172.  
  173. res.redirect(uri)
  174.  
  175. app.listen(process.env.PORT || 8902)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement