Compare commits
1
Commits
a4bdc22042
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c98fd8290 |
@@ -10,18 +10,33 @@
|
||||
- `tools/cslol-tools/` — cslol 工具链(`mod-tools.exe` / `cslol-dll.dll` / `wad-extract.exe` / `wad-make.exe`)。
|
||||
- `runtime/` — 全部本地状态(git 忽略)。
|
||||
|
||||
## 注入器(cslol-dll.dll)本地自管
|
||||
## 注入器(cslol-dll.dll)不更新
|
||||
|
||||
`tools/cslol-tools/` 下 `mod-tools.exe` / `cslol-dll.dll` / `wad-extract.exe` / `wad-make.exe` 都是**本地管理的二进制**,
|
||||
其中 `cslol-dll.dll` 与游戏大版本强绑定,**不自动更新**。
|
||||
其中 `cslol-dll.dll` **不更新**——updater 内不存在任何能写入它的代码路径(2026-10-02 起)。
|
||||
|
||||
原因:cslol-manager 上游 patcher 已换代(AeroHook,509344B),对当前游戏版本报
|
||||
`ah_result != 0 / C0000229`(STATUS_ORDINAL_NOT_FOUND),换上即全盘失效;而可用的
|
||||
MinHook 版(247128B,内部名 `League-of-Legends-Patch.dll`)不在上游 git 历史里,没有可 pin 的地址。
|
||||
原因:cslol-manager 的新 patcher(AeroHook,509384B)被**故意硬绑定**为只能由
|
||||
`cslol-manager.exe` / `ltk-manager` 启动,走 `mod-tools.exe` CLI 一律返回
|
||||
`ah_result != 0 / C0000229`。上游 issue #437 维护者原话:
|
||||
"this does mean cli tool is unfortunately unusable"。
|
||||
即它不是"坏了",而是设计上不给 CLI 用,因此 pin 任何 commit 都无意义。
|
||||
|
||||
`npm run update -- check` / `auto` 只校验本地指纹(已验证 SHA256 记录在 `packages/core/src/sources.ts`),
|
||||
不符会告警但**不会**自动下载替换。确需人工替换时才用
|
||||
`sync --only toolchain`,且必须先设 `LOLSKIN_ALLOW_INJECTOR_SYNC=1`。
|
||||
已于 2026-10-02 实际发生一次:`tools/cslol-tools/cslol-dll.dll.bak` 的**创建时间**
|
||||
(`2026/10/02 00:11:17`)即旧 `syncToolchain()` 覆盖掉可用 DLL 的时刻。
|
||||
|
||||
可用的 MinHook 版(247128B,内部名 `League-of-Legends-Patch.dll`)对应源码为
|
||||
`LeagueToolkit/cslol-patcher-legacy`,该仓库**只有源码、无预编译产物**,故无可自动更新的地址。
|
||||
|
||||
**要换 DLL 时人工放置文件**,然后用 `npm run update -- check` 核对指纹
|
||||
(已验证 SHA256 记录在 `packages/core/src/sources.ts` 的 `INJECTOR.knownGoodSha256`)。
|
||||
`check` / `auto` / `verify` 只读该文件,指纹不符会告警但绝不替换。
|
||||
`git` 内也必须存着已验证版本 —— 曾因初始提交存的是坏的 509384B,一度靠工作区覆盖才可用。
|
||||
|
||||
游戏大版本更新后如换肤失效,看 `runtime/state/overlay.log`:
|
||||
`Failed to find CRYPTO_free ptr.` / `Failed to write crypto free ptr:` 说明 patcher 需重编译;
|
||||
**日志无任何报错但不生效** 说明 `cslol-patcher-legacy/src/cslol-dll.c` 中校验返回点的
|
||||
机器码常量 `0x48C38B70247C8B48`(约 199 行)已变 —— 属静默失败,最难排查。
|
||||
需重编译时只改 3 个常量:`pattern[16]`(约 266 行)、`offset + 32`(约 276 行)、以及上述机器码。
|
||||
|
||||
## 命令
|
||||
|
||||
|
||||
@@ -49,13 +49,15 @@ export const CDRAGON = {
|
||||
* 与 mod-tools.exe / wad-extract.exe / wad-make.exe 一样按本地文件管理。
|
||||
*/
|
||||
export const INJECTOR = {
|
||||
/** 仅供人工排查/取证;不要接进自动更新。 */
|
||||
upstreamDlls: [
|
||||
"https://cdn.jsdelivr.net/gh/LeagueToolkit/cslol-manager@master/cslol-tools/vendor/cslol-patcher/cslol-dll.dll",
|
||||
"https://raw.githubusercontent.com/LeagueToolkit/cslol-manager/master/cslol-tools/vendor/cslol-patcher/cslol-dll.dll",
|
||||
],
|
||||
/** 已验证可用的注入器指纹(与 Aether 自带那份字节一致)。不符即说明被换掉了。 */
|
||||
knownGoodSha256: "25EA29710A83C5B12126E3BB8E6EC1549EACD0DCD4A4A10DA105A7037CB310CD",
|
||||
/** 重新编译/获取可用 patcher 的源码仓库(无预编译产物)。 */
|
||||
legacySource: "https://github.com/LeagueToolkit/cslol-patcher-legacy",
|
||||
/**
|
||||
* 取证用地址,**刻意不以数据形式保留**,确保 updater 无法下载它。
|
||||
* cslol-manager@cslol-tools/vendor/cslol-patcher/cslol-dll.dll
|
||||
* (raw.githubusercontent 同路径)
|
||||
* 该文件是 AeroHook 代(509384B),硬绑定只能由 cslol-manager.exe 启动,
|
||||
* 走 mod-tools CLI 必然 `C0000229`。谁再想接自动更新,先读上面那段注释。
|
||||
*/
|
||||
};
|
||||
|
||||
@@ -11,9 +11,9 @@ function usage(): void {
|
||||
logInfo(
|
||||
[
|
||||
"lolskin-updater <命令>",
|
||||
" auto | update 一键:检测 ->(有更新才)更新注入器 -> 校验",
|
||||
" auto | update 一键:检测 -> 校验(注入器为本地自管,不更新)",
|
||||
" check 只检测,不下载",
|
||||
" sync [--only hashes|toolchain] 更新(默认注入器)",
|
||||
" sync [--only hashes] 同步 hashes 库(注入器不参与更新)",
|
||||
" fetch-skin <heroId> <skinId> 单皮肤全量下载(主程序委托用)",
|
||||
" prefetch-skins [--hero <id>] 批量预下(占位)",
|
||||
" verify [--fix] 完整性校验 / 修复",
|
||||
@@ -65,6 +65,14 @@ async function main(argv: string[]): Promise<number> {
|
||||
const only = rest.includes("--only")
|
||||
? (rest[rest.indexOf("--only") + 1] as SyncOptions["only"])
|
||||
: undefined;
|
||||
if (only === ("toolchain" as SyncOptions["only"])) {
|
||||
logError(
|
||||
"sync --only toolchain 已移除:注入器不再由 updater 更新。" +
|
||||
"请人工放置 cslol-dll.dll,再用 `npm run update -- check` 核对指纹。" +
|
||||
"背景见 packages/core/src/sources.ts 的 INJECTOR 注释。"
|
||||
);
|
||||
return EXIT.USAGE;
|
||||
}
|
||||
return guarded(() => runSync({ only }));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,61 +1,28 @@
|
||||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
import { CDRAGON, CSLOL_DLL, HASH_DIR, INJECTOR, fileExists, logInfo, updateManifest } from "@lolskin/core";
|
||||
import { downloadToFile, getBuffer, sha256File } from "./downloader";
|
||||
import { CDRAGON, HASH_DIR, logInfo } from "@lolskin/core";
|
||||
import { getBuffer } from "./downloader";
|
||||
import { EXIT, type ExitCode } from "./exits";
|
||||
|
||||
export interface SyncOptions {
|
||||
only?: "hashes" | "toolchain";
|
||||
only?: "hashes";
|
||||
}
|
||||
|
||||
/**
|
||||
* 人工替换注入器 cslol-dll.dll(**仅显式调用**,自动流程不会触发)。
|
||||
* 注入器 cslol-dll.dll:**已彻底移除更新路径**(2026-10-02)。
|
||||
*
|
||||
* 警告:上游 cslol-manager 的 patcher 已换代(AeroHook,509344B),对当前游戏版本
|
||||
* 报 `C0000229`;本地可用的 MinHook 版(247128B)不在上游 git 历史里。
|
||||
* 换之前请确认新 DLL 与本地 mod-tools.exe 同代,否则换肤会整体失效。
|
||||
* 详见 packages/core/src/sources.ts 的 INJECTOR 注释。
|
||||
* 原 `syncToolchain()` 会从 cslol-manager 的可变 `@master` 引用下载 patcher,
|
||||
* 而上游该文件是**故意只允许 cslol-manager.exe 启动**的 AeroHook 版
|
||||
* (509384B),走 mod-tools CLI 一律 `ah_result != 0 / C0000229`。
|
||||
* 上游 issue LeagueToolkit/cslol-manager#437 维护者原话:
|
||||
* "this does mean cli tool is unfortunately unusable"。
|
||||
*
|
||||
* 曾于 2026-10-02 00:11 实际发生:`cslol-dll.dll.bak` 的创建时间即该次覆盖时刻。
|
||||
*
|
||||
* 现在 updater 内**没有任何**能写入 CSLOL_DLL 的代码路径。
|
||||
* 需要更换时由人工放置文件,并用 `npm run update -- check` 核对指纹。
|
||||
* 背景见 packages/core/src/sources.ts 的 INJECTOR 注释。
|
||||
*/
|
||||
async function syncToolchain(): Promise<ExitCode> {
|
||||
if (!process.env.LOLSKIN_ALLOW_INJECTOR_SYNC) {
|
||||
throw new Error(
|
||||
"注入器为本地自管二进制,自动更新已停用。" +
|
||||
"如确认要替换,请设置环境变量 LOLSKIN_ALLOW_INJECTOR_SYNC=1 后重试," +
|
||||
"并自行核对 SHA256 是否与已验证版本一致。"
|
||||
);
|
||||
}
|
||||
const bak = `${CSLOL_DLL}.bak`;
|
||||
if (fileExists(CSLOL_DLL)) {
|
||||
fs.copyFileSync(CSLOL_DLL, bak);
|
||||
logInfo(`已备份旧注入器 -> ${path.basename(bak)}`);
|
||||
}
|
||||
const tmp = `${CSLOL_DLL}.new`;
|
||||
let ok = false;
|
||||
let lastErr = "";
|
||||
for (const url of INJECTOR.upstreamDlls) {
|
||||
try {
|
||||
await downloadToFile(url, tmp);
|
||||
ok = true;
|
||||
break;
|
||||
} catch (e) {
|
||||
lastErr = (e as Error).message;
|
||||
fs.rmSync(tmp, { force: true });
|
||||
}
|
||||
}
|
||||
if (!ok) throw new Error(`注入器下载失败(所有源均失败):${lastErr}`);
|
||||
fs.renameSync(tmp, CSLOL_DLL);
|
||||
const sha = sha256File(CSLOL_DLL);
|
||||
if (sha.toUpperCase() !== INJECTOR.knownGoodSha256.toUpperCase()) {
|
||||
logInfo(
|
||||
`注意:新注入器指纹 ${sha.slice(0, 12)}… 与已验证版本不一致(上游已换代),换肤可能失效。`
|
||||
);
|
||||
}
|
||||
updateManifest((m) => {
|
||||
m.resources.toolchain = { ...m.resources.toolchain, present: true, injectorSha256: sha };
|
||||
});
|
||||
logInfo(`注入器已更新 (${fs.statSync(CSLOL_DLL).size}B, sha256=${sha.slice(0, 12)}…)`);
|
||||
return EXIT.OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* hashes 库(可选,仅 wad-extract 需要):
|
||||
@@ -87,8 +54,6 @@ async function syncHashes(): Promise<ExitCode> {
|
||||
}
|
||||
|
||||
export async function runSync(opts: SyncOptions = {}): Promise<ExitCode> {
|
||||
if (opts.only === "hashes") return syncHashes();
|
||||
if (opts.only === "toolchain") return syncToolchain();
|
||||
// 默认:按需更新注入器;hashes 不主动拉(可选)
|
||||
return syncToolchain();
|
||||
void opts;
|
||||
return syncHashes();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user