7 Commits
master ... v0

Author SHA1 Message Date
91c0e59d-6161-45ab-8aa4-2371574db28f
244d91b7bf 弃用代码,准备 checkout 到孤儿分支。 2025-12-31 13:05:36 +08:00
91c0e59d-6161-45ab-8aa4-2371574db28f
559cc98083 update README 2025-11-06 01:31:39 +08:00
91c0e59d-6161-45ab-8aa4-2371574db28f
12cdd344e1 bump sdgb authlite opt downloading related to latest 1.50 2025-11-06 01:16:15 +08:00
91c0e59d-6161-45ab-8aa4-2371574db28f
6c0d9336d2 bump sdga key and title api header to latest 1.55 & add mifare kind aimedb request (command id 15) 2025-11-06 01:15:43 +08:00
91c0e59d-6161-45ab-8aa4-2371574db28f
12fc3f881d bump sdga authv1 opt downloading related to latest 1.55 2025-11-06 01:14:25 +08:00
91c0e59d-6161-45ab-8aa4-2371574db28f
154ff02d73 add .DS_Store in .gitignore 2025-11-06 01:13:30 +08:00
91c0e59d-6161-45ab-8aa4-2371574db28f
f167858e0b fix music 2025-11-06 01:12:49 +08:00
7 changed files with 117 additions and 47 deletions

2
.gitignore vendored
View File

@@ -1,4 +1,4 @@
**/__pycache__
**/settings.py
**/.DS_Store
evil.py

View File

@@ -1,21 +1,25 @@
# Eaquira
A python 3 project to send game playlog to「舞萌DX」.
###### dev of SDGA was suspended
A python 3 project which is used to post title server of 「舞萌 DX」&「maimai DX International」
---
## Info
__Eaquira__ is a fork of `sdgb-some-api` main branch. Thanks to leakers.
The whole project was powered by Python 3, same as the origin. EVIL Python XD
## SDGA Usage
特别说明:国际服(下称 SDGA部分代码仅提供参考并不具备实用价值。
- 世嘉对 SDGA 的维护尚可,对于发送请求的 IP 有较为严格的要求。对于滥发请求的 IP 等会快速封禁。
- 由于 AiMeDB 已禁用对 FeliCa 卡类型老旧接口的支持(主要是 FeliCa Lookup 的部分,将 IDm 查表转换为 accessCode 相关),大部分使用蓝白卡(判断方式:卡号 5 开头)的玩家无法通过命令行模拟的方式实现上号,必须要通过购买第三方读卡器才能实现刷卡上号。
still in progress...
## SDGB Usage
SDGB 目前仍然停留在老旧的 1.40 版本支持(即 DX 2024仓库中现有代码并不支持最新版本。目前有计划在 Esquira 2.0 重构发送请求的架构(大饼)。
- _authlite.py_ Get latest opt file of SDGB.
- _login.py_ ```UserLoginApi```
- _logout.py_ ```UserLogoutApi```

View File

@@ -1,14 +1,33 @@
# This file contains the config of the whole project.
# DO NOT share your crtical info to others.
# Change the file name from .settings.py to settings.py.
from sdgb import aimedb_api, felica
from sdgb import aimedb_api, felica, mifare
accessCode = 50000000000000000000
IDm = "0000000000000000"
felica(IDm)
########## Felica Card ##########
#################################
## 这一部分仅作为参考,相关 API 已被 AiMeDB 禁用。
# accessCode = "50000000000000000000"
# IDm = "0000000000000000"
# felica(IDm)
# userId = aimedb_api(accessCode)
#################################
##################################
########## Mifare Card ##########
#################################
accessCode = "01036000000000000000"
serialNumber = "00000000"
userId = mifare(accessCode, serialNumber)
#################################
##################################
userId = aimedb_api(accessCode)
# 上传的乐曲成绩
# 此成绩将覆盖原有成绩

View File

@@ -5,7 +5,7 @@ import httpx
def DownloadOrder():
ua = 'Windows/3.0'
content = b'game_id=SDGA&ver=1.50&serial=A63E01E0048&encode=UTF-8'
content = b'game_id=SDGA&ver=1.56&serial=A63E01E0048&encode=UTF-8'
body = base64.b64encode(zlib.compress(content))
r = httpx.post(
'http://naominet.jp/sys/servlet/DownloadOrder',
@@ -14,7 +14,8 @@ def DownloadOrder():
'Pragma': 'DFI',
'User-Agent': ua,
'Content-Type': 'application/x-www-form-urlencoded',
}
},
proxy = 'http://127.0.0.1:6152'
)
resp_data = r.content
response = zlib.decompress(base64.b64decode(resp_data)).decode()

View File

@@ -12,9 +12,14 @@ from datetime import datetime
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
AesKey = "A;mv5YUpHBK3YxTy5KB^[;5]C2AL50Bq"
AesIV = "9FM:sd9xA91X14v]"
ObfuscateParam = "M9aBNKuY"
# Key 1.50
# AesKey = "A;mv5YUpHBK3YxTy5KB^[;5]C2AL50Bq"
# AesIV = "9FM:sd9xA91X14v]"
# ObfuscateParam = "M9aBNKuY"
AesKey = "Z6@9UJ@U79^4TH7H^7Pd25Z@;YiIZS9Z"
AesIV = "f@FTcYHXVGYLM5UK"
ObfuscateParam = "X7eBJcEU"
class aes_pkcs7(object):
def __init__(self, key: str, iv: str):
@@ -62,15 +67,17 @@ def sdgb_api(data, useApi, userId):
headers = {
"User-Agent": "%s#%d"%(get_hash_api(useApi), userId),
"Content-Type": "application/json",
"Mai-Encoding": "1.51",
"Mai-Encoding": "1.55",
"Accept-Encoding": "",
"Charset": "UTF-8",
"Content-Encoding": "deflate",
"Expect": "100-continue"
"Content-Encoding": "deflate"
},
data = data_enc
content = data_enc,
timeout = 10000,
proxy = "http://127.0.0.1:6152"
)
resp_enc = r.content
print(resp_enc)
try:
resp_def = aes.decrypt(resp_enc)
except:
@@ -158,3 +165,50 @@ def aimedb_api(accessCode):
decimal_value = int(rearranged_hex, 16)
return decimal_value
def mifare(accessCode, serial):
key = b'Copyright(C)SEGA'
# https://sega.bsnk.me/allnet/aimedb/common/
magic = "3ea1"
version = "2140"
command_id = "0f00" # ID = 15
length = "3000" # 48
gameId = "534447410000" # SDGA
storeId = "bc310000"
keychip_ID = "413633453031453032363400" # A63E01E0264
header = magic + version + command_id + length + "0000" + gameId + storeId + keychip_ID
access_code = str(accessCode)
serial = str(serial)
company_code = "00"
firmware_version = "02"
plaintext_hex_stream = header + access_code + company_code + firmware_version + serial
plaintext = unhexlify(plaintext_hex_stream)
cipher = AES.new(key, AES.MODE_ECB)
encrypted_message = cipher.encrypt(plaintext)
encrypted_hex_stream = hexlify(encrypted_message).decode('utf-8')
server_address = ('aime.naominet.jp', 22345)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect(server_address)
sock.sendall(encrypted_message)
response = sock.recv(1024)
decrypted_response = cipher.decrypt(response)
decrypted_hex_stream = hexlify(decrypted_response).decode('utf-8')
match = re.search(r'[0-9a-f]{64}([0-9a-f]{6})', decrypted_hex_stream)
if match:
six_digit_code = match.group(1)
rearranged_hex = six_digit_code[4:6] + six_digit_code[2:4] + six_digit_code[0:2]
decimal_value = int(rearranged_hex, 16)
return decimal_value

View File

@@ -3,6 +3,7 @@ from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import base64
import httpx
import re
def enc(key, iv, data):
cipher = AES.new(key, AES.MODE_CBC, iv)
@@ -14,14 +15,12 @@ def dec(key, iv ,data):
decrypted = de_cipher.decrypt(data)
return decrypted
def hello():
def DownloadOrder():
key = bytes([ 47, 63, 106, 111, 43, 34, 76, 38, 92, 67, 114, 57, 40, 61, 107, 71 ])
#key = bytes([ 45, 97, 53, 55, 85, 88, 52, 121, 57, 47, 104, 40, 73, 109, 65, 81 ])
iv = bytes.fromhex('00000000000000000000000000000000')
ua = 'SDGB;Windows/Lite'
#ua = 'SDHJ;Windows/Lite'
content = bytes([0] * 16) + b'title_id=SDGB&title_ver=1.41&client_id=A63E01C2805&token=205648745'
#content = bytes([0] * 16) + b'title_id=SDHJ&title_ver=1.11&client_id=A63E01E1326&token=205648745'
content = bytes([0] * 16) + b'title_id=SDGB&title_ver=1.51&client_id=A63E01C2805&token=205648745'
header = bytes.fromhex('00000000000000000000000000000000')
bytes_data = pad(header + content, 16)
encrypted = enc(key, iv, bytes_data)
@@ -39,4 +38,19 @@ def hello():
decrypted_str = decrypted_bytes.decode('UTF-8')
print(decrypted_str)
hello()
def uri():
data = DownloadOrder()
pattern = r"https://[^\s]+"
endpoint = re.search(pattern, data).group()
r = httpx.get(
endpoint,
headers = {
'User-Agent': 'A63E01E0000',
}
)
resp_data = r.content
response = resp_data.decode()
return response
if __name__ == "__main__":
print(uri())

View File

@@ -347,28 +347,6 @@ def music():
"deluxscoreMax": deluxscoreMax,
"scoreRank": scoreRank,
"extNum1": extNum1
},
{
"musicId": music_details['userMusicList'][0]['userMusicDetailList'][0]['musicId'],
"level": music_details['userMusicList'][0]['userMusicDetailList'][0]['level'],
"playCount": music_details['userMusicList'][0]['userMusicDetailList'][0]['playCount'],
"achievement": music_details['userMusicList'][0]['userMusicDetailList'][0]['achievement'],
"comboStatus": music_details['userMusicList'][0]['userMusicDetailList'][0]['comboStatus'],
"syncStatus": music_details['userMusicList'][0]['userMusicDetailList'][0]['syncStatus'],
"deluxscoreMax": music_details['userMusicList'][0]['userMusicDetailList'][0]['deluxscoreMax'],
"scoreRank": music_details['userMusicList'][0]['userMusicDetailList'][0]['scoreRank'],
"extNum1": music_details['userMusicList'][0]['userMusicDetailList'][0]['extNum1']
},
{
"musicId": music_details['userMusicList'][1]['userMusicDetailList'][0]['musicId'],
"level": music_details['userMusicList'][1]['userMusicDetailList'][0]['level'],
"playCount": music_details['userMusicList'][1]['userMusicDetailList'][0]['playCount'],
"achievement": music_details['userMusicList'][1]['userMusicDetailList'][0]['achievement'],
"comboStatus": music_details['userMusicList'][1]['userMusicDetailList'][0]['comboStatus'],
"syncStatus": music_details['userMusicList'][1]['userMusicDetailList'][0]['syncStatus'],
"deluxscoreMax": music_details['userMusicList'][1]['userMusicDetailList'][0]['deluxscoreMax'],
"scoreRank": music_details['userMusicList'][1]['userMusicDetailList'][0]['scoreRank'],
"extNum1": music_details['userMusicList'][1]['userMusicDetailList'][0]['extNum1']
}
],
"userCourseList": [],
@@ -384,7 +362,7 @@ def music():
"playMode": 0,
"useTicketId": -1,
"playCredit": 1,
"playTrack": 3,
"playTrack": 1,
"clientId": clientId,
"isPlayTutorial": False,
"isEventMode": False,