我打算在LOL中进行游戏数据挖掘,但坚持解析重放文件。我发现最受欢迎的重播录音机是LOL Replay,用于记录.lrf文件中的游戏。它们保存为二进制文件。我尝试打印一个lrf文件来查找其中的一些模式。据我所知,该文件有两部分:
初始部分是元数据。它是人类可读的。最后,它显示了此.lrf文件的加密密钥(32字节)和客户端哈希。
第二部分有几个部分。每个部分都在" RESTful URL +加密+填充(可能)"格式。例如:
?S4GI____GET /observer-mode/rest/consumer/getGameDataChunk/EUW1/1390319411/1/token
?S4GH____?¥?G??,\??1?q??"Lq}?n??&??????l??(?^P???¥I?v??k>x??Z?£??3Gug
......
??6GI____GET /observer-mode/rest/consumer/getGameDataChunk/EUW1/1390319411/2/token
有些甚至是不可读的角色.3
我已关注此link和此wiki。看起来他们在使用GZIP压缩内容后使用BlowFish ECB算法加上PKCS5Padding进行加密。但我无法使用元数据中的32字节加密密钥解密内容。而且我不确定我应该从哪里开始阅读以及在哪里停止因为JVM一直警告我给定最后一个块没有正确填充。
所以我的问题是:
任何帮助将不胜感激。谢谢你们。
根据Divis和avbor的答案,我尝试使用以下Java代码段来解码块:
// Decode EncryptKey with GameId
byte[] gameIdBytes = ("502719605").getBytes();
SecretKeySpec gameIdKeySpec = new SecretKeySpec(gameIdBytes, "Blowfish");
Cipher gameIdCipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");
gameIdCipher.init(Cipher.DECRYPT_MODE, gameIdKeySpec);
byte[] encryptKeyBytes = Base64.decode("Sf9c+zGDyyST9DtcHn2zToscfeuN4u3/");
byte[] encryptkeyDecryptedByGameId = gameIdCipher.doFinal(encryptKeyBytes);
// Initialize the chunk cipher
SecretKeySpec chunkSpec = new SecretKeySpec(encryptkeyDecryptedByGameId, "Blowfish");
Cipher chunkCipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");
chunkCipher.init(Cipher.DECRYPT_MODE, chunkSpec);
byte[] chunkContent = getChunkContent();
byte[] chunkDecryptedBytes = chunkCipher.doFinal(chunkContent);
使用gameid解码加密密钥时没有错误。然而,它在最后两行中并不起作用。目前我只是硬编码getChunkContent()来返回一个包含两个RESTful URL之间字节的字节数组。但Java要么在线程" main"中返回" Exception。 javax.crypto.IllegalBlockSizeException:当使用填充密码"解密时,输入长度必须是8的倍数。
或者
返回"线程中的异常" main" javax.crypto.BadPaddingException:给定最终块未正确填充"。
我注意到两个RESTful URL之间的十六进制模式如下: (第一个URL的十六进制,例如/ observer-mode / rest / consumer / getKeyFrame / EUW1 / 502719605/2 / token)+ 0a +(块内容)+ 000000 +(下一个URL的十六进制)
我的问题是:
需要包含哪部分块?我是否需要包含" 0a"在最后一个URL之后?我是否需要包含" 000000"在下一个URL之前?
我使用正确的填充算法(Blowfish / ECB / PKCS5Padding)吗?
我的测试lrf文件可以在https://www.dropbox.com/s/yl1havphnb3z86d/game1.lrf
上下载
感谢Divis!使用上面的代码片段,我成功地解密了一些块信息而没有错误。当你编写自己的 getChunkContent():
时,有两点值得注意块内容在"十六进制之后开始,用于上一个网址0a"。
块内容尽可能接近" 0000000(下一个网址为十六进制)"当它的大小恰好达到8的倍数时。
但我还有两个问题要问:
以下是我为两个... / getKeyframe / ... RESTful网址之间的内容解码的示例。
39117e0cc2f7e4bb1f8b080000000000000bed7d0b5c15d5 ... 7f23a90000
我知道Gzip压缩数据以" 1f8b08开始......"根据这个RFC doc。我可以放弃" 39117e0cc2f7e4bb"并启动gzip解压缩正在进行的内容? (实际上我已经尝试从" 1f8b08开始解码..",至少它可以毫无错误地解压缩)
在gzip解压缩之后,结果仍然是一个很长的二进制序列(有一些可读的字符串,如召唤者名字,冠军名称等)当我查看wiki时,它看起来像它远未结束。我期望阅读每个项目,符文或可读字符串中的移动。我怎样才能从中读取这些游戏事件?或者我们需要一些耐心才能将自己与社区联系起来?
数百万的感谢!
答案 0 :(得分:3)
此处的存储库开发者贡献者,根据维基,关键是base64 Blowfish ECB“encryption_key”(游戏ID为河豚的关键)。
然后,使用此解密密钥解码内容(吹鱼ECB)。然后,gzip解码。
base64decode encryptionkey = decodedKey
blowfishECBdecode decodedKey with (string) gameId as key = decodedKey
blowfishECBdecode content with decodedKey as key = decodedContent
gzipdecode decodedContent = binary
我创建了一个库来下载和解码重播文件:https://github.com/EloGank/lol-replay-downloader并且 CLI命令也可用:https://github.com/EloGank/lol-replay-downloader-cli
希望它会有所帮助:)
答案 1 :(得分:1)
据我所知,您使用Blowfish解密了块和关键帧。为了获得解密所述块和关键帧的密钥,您可以使用给定的加密密钥base64对其进行编码,然后使用游戏ID作为密钥使用Blowfish,以获取块和关键帧的实际加密密钥