-
Notifications
You must be signed in to change notification settings - Fork 2
/
unlocker.js
159 lines (136 loc) · 5.03 KB
/
unlocker.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
const path = require('path');
const fs = require('fs');
const readline = require('readline');
const asar = require('asar');
const patchBySignature = require("./memoryScanner");
const regex = /getUserAccount\(\)\{.*?return\s+this\.#\w+\.fetch\(\{.*?\}\).*?\}/g;
const asarPatch = "getUserAccount(){return this.#v.fetch({endpoint:\"/v3/account\",method:\"GET\",name:\"/v3/account\",collectMetrics:0}).then(response=>{response.subscription={period:\"yearly\",state:\"active\"};response.flags=78;return response;})}"
const signature = "E8 ?? ?? ?? ?? 85 C0 75 ?? F6 C3 01 74 ?? 48 89 F9 E8 ?? ?? ?? ??"
const patchBytes = [0x31]
const patchOffset = 0x5
// ...
// test eax, eax (0x85 for r/m16/32/64)
// jnz short loc_1403A4DD2 (Integrity check failed)
// call near ptr funk_1445527E0
// ...
console.log("WeMod unlocker by K1tbyte")
let defaultDir = path.join(process.env.LOCALAPPDATA || path.join(process.env.HOME || process.env.USERPROFILE, 'AppData', 'Local'), 'WeMod');
let appDir = null
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const read = (title, onSubmit, onExit) => {
rl.question(title, (answer) => {
try {
onSubmit(answer)
} finally {
rl.close()
onExit?.()
}
});
}
const checkWeModPaths = (dir) => {
return fs.existsSync(dir) && fs.existsSync(path.join(dir, 'WeMod.exe')) && fs.existsSync(path.join(dir, 'resources'))
}
const patchAsar = unpackedPath => {
let items = fs.readdirSync(unpackedPath,{ withFileTypes: true })
items = items.filter(item => !item.isDirectory() && /^app-\w+/.test(item.name));
if(items.length === 0) {
console.log(" - No app bundle found")
return;
}
let asarPatchApplied = false;
for (const item of items) {
const data = fs.readFileSync(path.join(unpackedPath, item.name), { encoding: 'utf8'})
const matches = data.match(regex)
if(!matches) {
continue;
}
if(matches.length > 1) {
console.error(" - Multiple target functions found. Looks like the version is not supported")
throw new Error("Multiple target functions found");
}
console.log(" - Found target function in: ", item.name)
console.log(" - Patching asar...")
fs.writeFileSync(path.join(unpackedPath, item.name), data.replace(regex, asarPatch), {encoding: 'utf8'})
console.log(" - Patch applied")
asarPatchApplied = true;
break;
}
if(!asarPatchApplied) {
throw new Error("Failed to apply patch");
}
}
const patchPE = async () => {
console.log(" - Patching PE...")
const pePath = path.join(appDir, 'WeMod.exe')
const procStart = await patchBySignature(pePath, signature, patchBytes, patchOffset)
if(procStart === -1) {
console.log(" - Signature not found or already patched")
return;
}
console.log(" - Patch saved")
}
const start = async () => {
console.log(" - Extracting asar...")
try {
const asarPath = path.join(appDir, 'resources', 'app.asar')
asar.extractAll(asarPath, path.join(appDir, 'resources', 'app.asar.unpacked'))
} catch(e) {
console.error("Failed to extract asar", e)
return;
}
const unpackedPath = path.join(appDir, 'resources', 'app.asar.unpacked')
fs.renameSync(path.join(appDir, 'resources', 'app.asar'), path.join(appDir, 'resources', 'app.asar.backup'))
console.log(" - Backup saved")
patchAsar(unpackedPath)
await asar.createPackageWithOptions(unpackedPath, path.join(appDir, 'resources', 'app.asar'),
{ unpack: path.join(unpackedPath,"static/unpacked/**") })
console.log(" - Patch saved")
await patchPE()
console.log("Done!")
process.exit(0)
}
const prepare = async () => {
console.log(" - Path: ", appDir || "Not found")
if (!appDir) {
read("WeMod directory not found. Enter the path manually: ", (answer) => {
if (checkWeModPaths(answer)) {
appDir = answer;
return;
}
console.log("Invalid path")
}, prepare);
return;
}
read("Continue? (y/n): ", (answer) => {
if(answer.toLowerCase() === 'y') {
start()
}
})
}
if(fs.existsSync(defaultDir)) {
const items = fs.readdirSync(defaultDir, { withFileTypes: true });
const appFolders = items
.filter(item => item.isDirectory() && /^app-\w+/.test(item.name))
.map(item => {
const folderPath = path.join(defaultDir, item.name);
const stats = fs.statSync(folderPath); // Получаем информацию о папке
return {
name: item.name,
path: folderPath,
mtime: stats.mtime,
};
});
appFolders.sort((a, b) => b.mtime - a.mtime);
for(const folder of appFolders) {
if(checkWeModPaths(folder.path)) {
appDir = folder.path;
break;
}
}
}
(async () => {
await prepare();
})();