如題 pc-play.games.dmm.co.jp/play/luminaprognosis_x/
我用charle 取得的資源: ttps://drive.google.com/drive/folders/1ltSytA3E60qemg2jtRGj-OzhqjAEGEZ0?usp=drive_link
自己有在 5ch 看到別人討論 是 XOR 加密 ? 但是實力不足無法確認
(只會用 xortool 最簡單功能測試猜測… 但是沒測出來.)
希望有高手能幫忙看看 謝謝 (主要目的還是收集自己抽的角色的圖片 自己也有課金一點 不過覺得官方經營的挺隨便的 感覺課不下去了 … -----遊戲活動兌換物一下就換光了 遊戲下半也不新增新兌換物…)
from pathlib import Path
from typing import Union, Tuple
from numpy import uint8, frombuffer as npbuff, tile as npfill
def Decrypt(fp: Path, klen: int = 32):
with open(fp, 'rb') as f:
if f.read(4).startswith((b'\xFF\xD8\xFF', b'\x89PNG')): return
f.seek(0)
darr = npbuff(f.read(), dtype=uint8)
dlen = len(darr)
basekey = f'{dlen}2fjaykPFd6bAJn59beX5TWDQzsEW'.encode('utf-8')
keylen = len(basekey)
key = bytearray(klen)
o, t = 0, 0
for i in range(klen):
o = key[i] = basekey[t] ^ o
t = (t + 1) % keylen
karr = npbuff(key, dtype=uint8)
data = (darr ^ npfill(karr, (dlen // klen) + 1)[:dlen]).tobytes()
if not data[:4].startswith((b'\xFF\xD8\xFF', b'\x89PNG')):
print(f'解密错误 --- {fp.as_posix()}')
return
with open(fp, 'wb') as f:
f.write(data)
def batch(img_path: str = '', ext: Union[str, Tuple[str, ...]] = ('.png', '.jpg'), subfolder: bool = False):
path = Path(img_path) if img_path else Path.cwd()
need = [i for i in (path.rglob('*') if subfolder else path.glob('*')) if i.suffix.endswith(ext)]
for i in need:
Decrypt(i)
if __name__ == '__main__':
path = r'D:\测试' # 指定图片所在文件夹
ext = ('.png', '.jpg') # 指定要解密的文件类型后缀
subfolder = True # 是否查找子文件夹内的文件
batch(path, ext, subfolder)
1 个赞
代码就这样, 如果有解密错误的文件, 你可以上传到谷歌云盘, 我有空会检查下
用大佬的程序解密后发现文件不全,cg图片是一组的循环重复,推测可能是游戏自身对抓包进行了某些限制?
cocos 有缓存,控制台禁用缓存后刷新应该可以抓到,但cg的话就是帧序列
一般来说cocos这种引擎底层的资源处理应该有人写过解析工具,但我没搜到过。自己造的轮子有点问题,但能凑合着用
from concurrent.futures import ThreadPoolExecutor
from cocos2dAsset.downloader import assetDownloader
from cocos2dAsset.parser import ManifestJson
from loguru import logger
from numpy import uint8, frombuffer as npbuff, tile as npfill
import requests
import shutil
import os
# logger.level('ERROR')
def decryptimage(url,path,data):
if path.endswith(('.png','.jpg')):
# 楼上的解密代码
if data.startswith((b'\xFF\xD8\xFF', b'\x89PNG')):
return
darr = npbuff(data, dtype=uint8)
dlen = len(darr)
basekey = f'{dlen}2fjaykPFd6bAJn59beX5TWDQzsEW'.encode('utf-8')
keylen = len(basekey)
klen = 32
key = bytearray(klen)
o, t = 0, 0
for i in range(klen):
o = key[i] = basekey[t] ^ o
t = (t + 1) % keylen
karr = npbuff(key, dtype=uint8)
decrypted_data = (darr ^ npfill(karr, (dlen // klen) + 1)[:dlen]).tobytes()
if not decrypted_data.startswith((b'\xFF\xD8\xFF', b'\x89PNG')):
logger.error(f'failed to decrypt {path}')
return
downloader.mkdir(path)
with open(path, 'wb') as f:
f.write(decrypted_data)
return True
config_dict = {
"downloader_assetroot": "https://cdn-app.miraigirl.net/",
"downloader_weburl": "",
"downloader_threadnum": 20,
"downloader_savepath": "resource/game",
"asset_baseurl": "https://cdn-app.miraigirl.net/assets"
}
downloader = assetDownloader(config_dict)
settings_jsonUrl = 'https://cdn-app.miraigirl.net/src/settings.ca618.json'
jsdata= requests.get(settings_jsonUrl).json()
downloader.manifestOfmanifestData['resources'] = jsdata['assets']['bundleVers']['resources']
downloader.jsurl = 'assets/{typename}/index.{version}.js'
downloader.configurl = 'assets/{typename}/config.{version}.json'
downloader.downloadAllManifest()
# 下载全部资源文件
# downloader.downloadAllFromManifest()
# 仅下载HCG
res:ManifestJson = ManifestJson('resources',downloader.manifestData['resources'])
downloader.downloadCallback = decryptimage
res.mapExt()
downloader.MTdownloadAndSetimport(res,res.getAllpackDownloadUrl())
downloader.MTdownloadAndSetimport(res, res.getAllINDimportDownloadUrl())
res.setRealPaths()
with ThreadPoolExecutor(max_workers=20) as executor:
for i in res.assetList:
if i.nativeVersion:
if i.nativeExt:
if 'HCG' in i.realPath:
executor.submit(downloader.downloadAndSaveBinary,res.convertInfoToUrl('native', i.uuid, i.nativeVersion, i.nativeExt))
# 按path名称复制
dst = 'game_img'
for i in res.assetList:
if i.nativeVersion and i.nativeExt and i.realPath:
srcpath = downloader.convertUrltoPath(res.convertInfoToUrl('native', i.uuid, i.nativeVersion, i.nativeExt))
if os.path.exists(srcpath):
dstpath = f'{dst}/{i.realPath}{i.nativeExt}'
downloader.mkdir(dstpath)
shutil.copy(srcpath,dstpath)
1 个赞