Added workaround for 32 bit windows agent on 64 bit windows, to inject sysnative when callind readdirSync() on %windir%
Updated documentation for windows terminal.
Bryan Roe committed
Oct 14, 2022 at 11:18 UTC
06ec0caec46056513c300366c215f464577d4bec
3 files changed
+262
-74
agents/meshcore.js
+21
@@ -47,6 +47,27 @@ var MESHRIGHT_NODESKTOP = 65536;
47
48
var pendingSetClip = false; // This is a temporary hack to prevent multiple setclips at the same time to stop the agent from crashing.
49
50
+function __readdirSync_fix(path)
51
+{
52
+ var sysnative = false;
53
+ pathstr = require('fs')._fixwinpath(path);
54
+ if (pathstr.split('\\*').join('').toLowerCase() == process.env['windir'].toLowerCase()) { sysnative = true; }
55
+ var ret = __readdirSync_old(path);
56
+ if (sysnative) { ret.push('sysnative'); }
57
+ return (ret);
58
+}
59
+
60
+if (process.platform == 'win32' && require('_GenericMarshal').PointerSize == 4 && require('os').arch() == 'x64')
61
+{
62
+ if(require('fs').readdirSync.version == null)
63
+ {
64
+ require('fs').__readdirSync_old = require('fs').readdirSync;
65
+ require('fs').readdirSync = __readdirSync_fix;
66
+ }
67
+}
68
+
69
+
70
+
71
function bcdOK() {
72
if (process.platform != 'win32') { return (false); }
73
if (require('os').arch() == 'x64') {
agents/modules_meshcore/win-terminal.js
+199
-56
@@ -1,5 +1,5 @@
1
/*
2
-Copyright 2018 Intel Corporation
2
+Copyright 2018-2022 Intel Corporation
3
4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
@@ -89,21 +89,50 @@ function windows_terminal() {
89
var newCsbi = GM.CreateVariable(22);
90
91
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, newCsbi).Val == 0) { return; }
92
- if (newCsbi.Deref(4, 2).toBuffer().readUInt16LE() != this.currentX || newCsbi.Deref(6, 2).toBuffer().readUInt16LE() != this.currentY) {
93
- //wchar_t mywbuf[512];
94
- //swprintf(mywbuf, 512, TEXT("csbi.dwCursorPosition.X = %d, csbi.dwCursorPosition.Y = %d, newCsbi.dwCursorPosition.X = %d, newCsbi.dwCursorPosition.Y = %d\r\n"), csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y, newCsbi.dwCursorPosition.X, newCsbi.dwCursorPosition.Y);
95
- //OutputDebugString(mywbuf);
96
-
97
- //m_viewOffset = newCsbi.srWindow.Top;
98
- //WriteMoveCursor((SerialAgent *)this->sa, (char)(newCsbi.dwCursorPosition.Y - m_viewOffset), (char)(newCsbi.dwCursorPosition.X - m_viewOffset));
99
- //LowStackSendData((SerialAgent *)(this->sa), "", 0);
100
-
92
+ if (newCsbi.Deref(4, 2).toBuffer().readUInt16LE() != this.currentX || newCsbi.Deref(6, 2).toBuffer().readUInt16LE() != this.currentY)
93
+ {
94
+ //
95
+ // Reference for CONSOLE_SCREEN_BUFFER_INFO can be found at:
96
+ // https://learn.microsoft.com/en-us/windows/console/console-screen-buffer-info-str
97
+ //
98
+
99
this.currentX = newCsbi.Deref(4, 2).toBuffer().readUInt16LE();
100
this.currentY = newCsbi.Deref(6, 2).toBuffer().readUInt16LE();
101
}
102
}
103
106
- this.ClearScreen = function () {
104
+ this.ClearScreen = function ()
105
+ {
106
+ //
107
+ // Reference for CONSOLE_SCREEN_BUFFER_INFO can be found at:
108
+ // https://learn.microsoft.com/en-us/windows/console/console-screen-buffer-info-str
109
+ //
110
+
111
+ //
112
+ // Reference for GetConsoleScreenBufferInfo can be found at:
113
+ // https://learn.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo
114
+ //
115
+
116
+ //
117
+ // Reference for FillConsoleOutputCharacter can be found at:
118
+ // https://learn.microsoft.com/en-us/windows/console/fillconsoleoutputcharacter
119
+ //
120
+
121
+ //
122
+ // Reference for FillConsoleOutputAttribute can be found at:
123
+ // https://learn.microsoft.com/en-us/windows/console/fillconsoleoutputattribute
124
+ //
125
+
126
+ //
127
+ // Reference for SetConsoleCursorPosition can be found at:
128
+ // https://learn.microsoft.com/en-us/windows/console/setconsolecursorposition
129
+ //
130
+
131
+ //
132
+ // Reference for SetConsoleWindowInfo can be fount at:
133
+ // https://learn.microsoft.com/en-us/windows/console/setconsolewindowinfo
134
+ //
135
+
136
var CONSOLE_SCREEN_BUFFER_INFO = GM.CreateVariable(22);
137
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, CONSOLE_SCREEN_BUFFER_INFO).Val == 0) { return; }
138
@@ -132,6 +161,7 @@ function windows_terminal() {
161
this._kernel32.SetConsoleWindowInfo(this._stdoutput, 1, rect);
162
}
163
164
+ // This does a rudimentary check if the platform is capable of PowerShell
165
this.PowerShellCapable = function()
166
{
167
if (require('os').arch() == 'x64')
@@ -144,6 +174,7 @@ function windows_terminal() {
174
}
175
}
176
177
+ // Starts a Legacy Windows Terminal Session
178
this.StartEx = function Start(CONSOLE_SCREEN_WIDTH, CONSOLE_SCREEN_HEIGHT, terminalTarget)
179
{
180
// The older windows terminal does not support
@@ -164,7 +195,9 @@ function windows_terminal() {
195
this._stdinput = this._kernel32.GetStdHandle(STD_INPUT_HANDLE);
196
this._stdoutput = this._kernel32.GetStdHandle(STD_OUTPUT_HANDLE);
197
this._connected = false;
167
- var coordScreen = GM.CreateVariable(4);
198
+
199
+ // Coord structure can be found at: https://learn.microsoft.com/en-us/windows/console/coord-str
200
+ var coordScreen = GM.CreateVariable(4);
201
coordScreen.Deref(0, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_WIDTH);
202
coordScreen.Deref(2, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_HEIGHT);
203
@@ -172,10 +205,21 @@ function windows_terminal() {
205
rect.Deref(4, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_WIDTH - 1);
206
rect.Deref(6, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_HEIGHT - 1);
207
175
- if (this._kernel32.SetConsoleWindowInfo(this._stdoutput, 1, rect).Val == 0) {
208
+ //
209
+ // Reference for SetConsoleWindowInfo can be found at:
210
+ // https://learn.microsoft.com/en-us/windows/console/setconsolewindowinfo
211
+ //
212
+ if (this._kernel32.SetConsoleWindowInfo(this._stdoutput, 1, rect).Val == 0)
213
+ {
214
throw ('Failed to set Console Screen Size');
215
}
178
- if (this._kernel32.SetConsoleScreenBufferSize(this._stdoutput, coordScreen.Deref(0, 4).toBuffer().readUInt32LE()).Val == 0) {
216
+
217
+ //
218
+ // Reference for SetConsoleScreenBufferSize can be found at:
219
+ // https://learn.microsoft.com/en-us/windows/console/setconsolescreenbuffersize
220
+ //
221
+ if (this._kernel32.SetConsoleScreenBufferSize(this._stdoutput, coordScreen.Deref(0, 4).toBuffer().readUInt32LE()).Val == 0)
222
+ {
223
throw ('Failed to set Console Buffer Size');
224
}
225
@@ -278,8 +322,16 @@ function windows_terminal() {
322
return (this.stopping);
323
}
324
325
+ //
326
+ // This function uses the SetWinEventHook() method, so we can hook
327
+ // All events between EVENT_CONSOLE_CARET and EVENT_CONSOLE_END_APPLICATION
328
+ //
329
this._hookThread = function ()
330
{
331
+ //
332
+ // Reference for SetWinEventHook() can be found at:
333
+ // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwineventhook
334
+ //
335
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });
336
ret.userArgs = [];
337
for (var a in arguments)
@@ -292,24 +344,43 @@ function windows_terminal() {
344
var p = this._user32.SetWinEventHook.async(EVENT_CONSOLE_CARET, EVENT_CONSOLE_END_APPLICATION, 0, this._ConsoleWinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
345
p.ready = ret;
346
p.terminal = this;
295
- p.then(function (hwinEventHook) {
296
- if (hwinEventHook.Val == 0) {
347
+ p.then(function (hwinEventHook)
348
+ {
349
+ if (hwinEventHook.Val == 0)
350
+ {
351
this.ready._rej('Error calling SetWinEventHook');
298
- } else {
352
+ } else
353
+ {
354
this.terminal.hwinEventHook = hwinEventHook;
355
this.ready._res();
356
this.terminal._GetMessage();
357
}
358
});
359
305
- this._ConsoleWinEventProc.on('GlobalCallback', function (hhook, dwEvent, hwnd, idObject, idChild, idEventThread, swmsEventTime) {
360
+ //
361
+ // This is the WINEVENTPROC callback for the WinEventHook we set
362
+ //
363
+ this._ConsoleWinEventProc.on('GlobalCallback', function (hhook, dwEvent, hwnd, idObject, idChild, idEventThread, swmsEventTime)
364
+ {
365
+ //
366
+ // Reference for WINEVENTPROC can be found at:
367
+ // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-wineventproc
368
+ //
369
if (!this.terminal.hwinEventHook || this.terminal.hwinEventHook.Val != hhook.Val) { return; }
370
var buffer = null;
371
309
- switch (dwEvent.Val) {
372
+ //
373
+ // Reference for Console WinEvents can be found at:
374
+ // https://learn.microsoft.com/en-us/windows/console/console-winevents
375
+ //
376
+
377
+ switch (dwEvent.Val)
378
+ {
379
case EVENT_CONSOLE_CARET:
380
+ // The console caret has moved
381
break;
382
case EVENT_CONSOLE_UPDATE_REGION:
383
+ // More than one character has changed
384
if (!this.terminal.connected) {
385
this.terminal.connected = true;
386
this.terminal._stream._promise._res();
@@ -321,25 +392,30 @@ function windows_terminal() {
392
}
393
break;
394
case EVENT_CONSOLE_UPDATE_SIMPLE:
395
+ // A single character has changed
396
//console.log('UPDATE SIMPLE: [X: ' + LOWORD(idObject.Val) + ' Y: ' + HIWORD(idObject.Val) + ' Char: ' + LOWORD(idChild.Val) + ' Attr: ' + HIWORD(idChild.Val) + ']');
397
var simplebuffer = { data: [ Buffer.alloc(1, LOWORD(idChild.Val)) ], attributes: [ HIWORD(idChild.Val) ], width: 1, height: 1, x: LOWORD(idObject.Val), y: HIWORD(idObject.Val) };
398
this.terminal._SendDataBuffer(simplebuffer);
399
break;
400
case EVENT_CONSOLE_UPDATE_SCROLL:
401
+ // The console has scrolled
402
//console.log('UPDATE SCROLL: [dx: ' + idObject.Val + ' dy: ' + idChild.Val + ']');
403
this.terminal._SendScroll(idObject.Val, idChild.Val);
404
break;
405
case EVENT_CONSOLE_LAYOUT:
406
+ // The console layout has changed.
407
//console.log('CONSOLE_LAYOUT');
408
//snprintf( Buf, 512, "Event Console LAYOUT!\r\n");
409
//SendLayout();
410
break;
411
case EVENT_CONSOLE_START_APPLICATION:
412
+ // A new console process has started
413
//console.log('START APPLICATION: [PID: ' + idObject.Val + ' CID: ' + idChild.Val + ']');
414
//snprintf( Buf, 512, "Event Console START APPLICATION!\r\nProcess ID: %d - Child ID: %d\r\n\r\n", (int)idObject, (int)idChild);
415
//SendConsoleEvent(dwEvent, idObject, idChild);
416
break;
417
case EVENT_CONSOLE_END_APPLICATION:
418
+ // A console process has exited
419
if (idObject.Val == this.terminal._hProcessID)
420
{
421
//console.log('END APPLICATION: [PID: ' + idObject.Val + ' CID: ' + idChild.Val + ']');
@@ -360,18 +436,44 @@ function windows_terminal() {
436
return (ret);
437
}
438
363
- this._GetMessage = function () {
439
+ // Retrieves a message from the calling thread's message queue
440
+ this._GetMessage = function ()
441
+ {
442
+ //
443
+ // Reference for GetMessage() can be found at:
444
+ // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessage
445
+ //
446
+
447
+ //
448
+ // Reference for TranslateMessage() can be found at:
449
+ // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-translatemessage
450
+ //
451
+
452
+ //
453
+ // Reference for DispatchMessage() can be found at:
454
+ // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-dispatchmessage
455
+ //
456
+
457
if (this._user32.abort) { console.log('aborting loop'); return; }
365
- this._user32.GetMessageA.async(this._user32.SetWinEventHook.async, MSG, 0, 0, 0).then(function (ret) {
458
+ this._user32.GetMessageA.async(this._user32.SetWinEventHook.async, MSG, 0, 0, 0).then(function (ret)
459
+ {
460
//console.log('GetMessage Response');
367
- if (ret.Val != 0) {
368
- if (ret.Val == -1) {
461
+ if (ret.Val != 0)
462
+ {
463
+ if (ret.Val == -1)
464
+ {
465
// handle the error and possibly exit
370
- } else {
466
+ }
467
+ else
468
+ {
469
+ // Translates virtual-key messages into character messages
470
//console.log('TranslateMessage');
372
- this.nativeProxy._user32.TranslateMessage.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function () {
471
+ this.nativeProxy._user32.TranslateMessage.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function ()
472
+ {
473
+ // Dispatches a message to a window procedure
474
//console.log('DispatchMessage');
374
- this.nativeProxy._user32.DispatchMessageA.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function () {
475
+ this.nativeProxy._user32.DispatchMessageA.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function ()
476
+ {
477
this.nativeProxy.terminal._GetMessage();
478
}, console.log);
479
}, console.log);
@@ -384,7 +486,8 @@ function windows_terminal() {
486
if (this.nativeProxy.terminal._hProcess == null) { return; }
487
488
this.nativeProxy.terminal.stopping._res();
387
- if (this.nativeProxy.terminal._kernel32.TerminateProcess(this.nativeProxy.terminal._hProcess, 1067).Val == 0) {
489
+ if (this.nativeProxy.terminal._kernel32.TerminateProcess(this.nativeProxy.terminal._hProcess, 1067).Val == 0)
490
+ {
491
var e = this.nativeProxy.terminal._kernel32.GetLastError().Val;
492
console.log('Unable to kill Terminal Process, error: ' + e);
493
}
@@ -394,22 +497,38 @@ function windows_terminal() {
497
console.log('REJECTED_UnhookWinEvent: ' + err);
498
});
499
}
397
- }, function (err) {
500
+ }, function (err)
501
+ {
502
// Get Message Failed
503
console.log('REJECTED_GETMessage: ' + err);
504
});
505
}
402
- this._WriteBuffer = function (buf) {
403
- for (var i = 0; i < buf.length; ++i) {
404
- if (typeof (buf) == 'string') {
506
+
507
+ this._WriteBuffer = function (buf)
508
+ {
509
+ for (var i = 0; i < buf.length; ++i)
510
+ {
511
+ if (typeof (buf) == 'string')
512
+ {
513
this._WriteCharacter(buf.charCodeAt(i), false);
406
- } else {
514
+ } else
515
+ {
516
this._WriteCharacter(buf[i], false);
517
}
518
}
519
}
520
this._WriteCharacter = function (key, bControlKey)
521
{
522
+ //
523
+ // Reference for WriteConsoleInput() can be found at:
524
+ // https://learn.microsoft.com/en-us/windows/console/writeconsoleinput
525
+ //
526
+
527
+ //
528
+ // Reference for INPUT_RECORD can be found at:
529
+ // https://learn.microsoft.com/en-us/windows/console/input-record-str
530
+ //
531
+
532
var rec = GM.CreateVariable(20);
533
rec.Deref(0, 2).toBuffer().writeUInt16LE(KEY_EVENT); // rec.EventType
534
rec.Deref(4, 4).toBuffer().writeUInt16LE(1); // rec.Event.KeyEvent.bKeyDown
@@ -427,62 +546,78 @@ function windows_terminal() {
546
}
547
548
// Get the current visible screen buffer
430
- this._GetScreenBuffer = function (sx, sy, ex, ey) {
549
+ this._GetScreenBuffer = function (sx, sy, ex, ey)
550
+ {
551
+ //
552
+ // Reference for GetConsoleScreenBufferInfo() can be found at:
553
+ // https://learn.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo
554
+ //
555
+
556
+ //
557
+ // Reference for ReadConsoleOutput() can be found at:
558
+ // https://learn.microsoft.com/en-us/windows/console/readconsoleoutput
559
+ //
560
+
561
var info = GM.CreateVariable(22);
562
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, info).Val == 0) { throw ('Error getting screen buffer info'); }
433
-
563
+
564
var nWidth = info.Deref(14, 2).toBuffer().readUInt16LE() - info.Deref(10, 2).toBuffer().readUInt16LE() + 1;
565
var nHeight = info.Deref(16, 2).toBuffer().readUInt16LE() - info.Deref(12, 2).toBuffer().readUInt16LE() + 1;
436
-
437
- if (arguments[3] == null) {
566
+
567
+ if (arguments[3] == null)
568
+ {
569
// Use Default Parameters
570
sx = 0;
571
sy = 0;
572
ex = nWidth - 1;
573
ey = nHeight - 1;
443
- } else {
574
+ } else
575
+ {
576
if (this._scrx != 0) { sx += this._scrx; ex += this._scrx; }
577
if (this._scry != 0) { sy += this._scry; ey += this._scry; }
578
this._scrx = this._scry = 0;
579
}
448
-
580
+
581
var nBuffer = GM.CreateVariable((ex - sx + 1) * (ey - sy + 1) * 4);
582
var size = GM.CreateVariable(4);
583
size.Deref(0, 2).toBuffer().writeUInt16LE(ex - sx + 1, 0);
584
size.Deref(2, 2).toBuffer().writeUInt16LE(ey - sy + 1, 0);
453
-
585
+
586
var startCoord = GM.CreateVariable(4);
587
startCoord.Deref(0, 2).toBuffer().writeUInt16LE(0, 0);
588
startCoord.Deref(2, 2).toBuffer().writeUInt16LE(0, 0);
457
-
589
+
590
var region = GM.CreateVariable(8);
591
region.buffer = region.toBuffer();
592
region.buffer.writeUInt16LE(sx, 0);
593
region.buffer.writeUInt16LE(sy, 2);
594
region.buffer.writeUInt16LE(ex, 4);
595
region.buffer.writeUInt16LE(ey, 6);
464
-
465
- if (this._kernel32.ReadConsoleOutputA(this._stdoutput, nBuffer, size.Deref(0, 4).toBuffer().readUInt32LE(), startCoord.Deref(0, 4).toBuffer().readUInt32LE(), region).Val == 0) {
596
+
597
+ if (this._kernel32.ReadConsoleOutputA(this._stdoutput, nBuffer, size.Deref(0, 4).toBuffer().readUInt32LE(), startCoord.Deref(0, 4).toBuffer().readUInt32LE(), region).Val == 0)
598
+ {
599
throw ('Unable to read Console Output');
600
}
468
-
601
+
602
// Lets convert the buffer into something simpler
603
//var retVal = { data: Buffer.alloc((dw - dx + 1) * (dh - dy + 1)), attributes: Buffer.alloc((dw - dx + 1) * (dh - dy + 1)), width: dw - dx + 1, height: dh - dy + 1, x: dx, y: dy };
471
-
604
+
605
var retVal = { data: [], attributes: [], width: ex - sx + 1, height: ey - sy + 1, x: sx, y: sy };
606
var x, y, line, ifo, tmp, lineWidth = ex - sx + 1;
474
-
475
- for (y = 0; y <= (ey - sy) ; ++y) {
607
+
608
+ for (y = 0; y <= (ey - sy) ; ++y)
609
+ {
610
retVal.data.push(Buffer.alloc(lineWidth));
611
retVal.attributes.push(Buffer.alloc(lineWidth));
478
-
612
+
613
line = nBuffer.Deref(y * lineWidth * 4, lineWidth * 4).toBuffer();
480
- for (x = 0; x < lineWidth; ++x) {
614
+ for (x = 0; x < lineWidth; ++x)
615
+ {
616
retVal.data.peek()[x] = line[x * 4];
617
retVal.attributes.peek()[x] = line[2 + (x * 4)];
618
}
619
}
485
-
620
+
621
return (retVal);
622
}
623
@@ -507,6 +642,11 @@ function windows_terminal() {
642
643
this._SendScroll = function _SendScroll(dx, dy)
644
{
645
+ //
646
+ // Reference for GetConsoleScreenBufferInfo() can be found at:
647
+ // https://learn.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo
648
+ //
649
+
650
if (this._scrollTimer || this._stream == null) { return; }
651
652
var info = GM.CreateVariable(22);
@@ -546,12 +686,15 @@ function LOWORD(val) { return (val & 0xFFFF); }
686
function HIWORD(val) { return ((val >> 16) & 0xFFFF); }
687
function GetEsc(op, args) { return (Buffer.from('\x1B[' + args.join(';') + op)); }
688
function MeshConsole(msg) { require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": JSON.stringify(msg) }); }
549
-function TranslateLine(x, y, data, attributes) {
689
+function TranslateLine(x, y, data, attributes)
690
+{
691
var i, fcolor, bcolor, rcolor, fbright, bbright, lastAttr, fc, bc, rc, fb, bb, esc = [], output = [GetEsc('H', [y, x])];
551
- if (typeof attributes == 'number') { attributes = [ attributes ]; } // If we get a single attribute, turn it into an array.
692
+ if (typeof attributes == 'number') { attributes = [attributes]; } // If we get a single attribute, turn it into an array.
693
553
- for (i = 0; i < data.length; i++) {
554
- if (lastAttr != attributes[i]) { // To boost performance, if the attribute is the same as the last one, skip this entire part.
694
+ for (i = 0; i < data.length; i++)
695
+ {
696
+ if (lastAttr != attributes[i])
697
+ { // To boost performance, if the attribute is the same as the last one, skip this entire part.
698
fc = (attributes[i] & 0x0007);
699
fc = ((fc & 0x0001) << 2) + (fc & 0x0002) + ((fc & 0x0004) >> 2); // Foreground color
700
bc = (attributes[i] & 0x0070) >> 4;
@@ -559,19 +702,19 @@ function TranslateLine(x, y, data, attributes) {
702
rc = (attributes[i] & 0x4000); // Reverse color set
703
fb = (attributes[i] & 0x0008) >> 3; // Bright foreground set
704
bb = (attributes[i] & 0x0080); // Bright background set
562
-
705
+
706
if (rc != rcolor) { if (rc != 0) { esc.push(7); } else { esc.push(0); fcolor = 7; bcolor = 0; fbright = 0; bbright = 0; } rcolor = rc; } // Reverse Color
707
if (fc != fcolor) { esc.push(fc + 30); fcolor = fc; } // Set the foreground color if needed
708
if (bc != bcolor) { esc.push(bc + 40); bcolor = bc; } // Set the background color if needed
709
if (fb != fbright) { esc.push(2 - fb); fbright = fb; } // Set the bright foreground color if needed
567
- if (bb != bbright) { if (bb == 0) { esc.push(bcolor + 40); } else { esc.push(bcolor + 100); bbright = bb; } } // Set bright Background color if needed
710
+ if (bb != bbright) { if (bb == 0) { esc.push(bcolor + 40); } else { esc.push(bcolor + 100); bbright = bb; } } // Set bright Background color if needed
711
712
if (esc.length > 0) { output.push(GetEsc('m', esc)); esc = []; }
713
lastAttr = attributes[i];
714
}
715
output.push(Buffer.from(String.fromCharCode(data[i])));
716
}
574
-
717
+
718
return Buffer.concat(output);
719
}
720
agents/modules_meshcore/win-virtual-terminal.js
+42
-18
@@ -47,20 +47,20 @@ function vt()
47
48
var GM = require('_GenericMarshal');
49
var k32 = GM.CreateNativeProxy('kernel32.dll');
50
- k32.CreateMethod('CancelIoEx');
51
- k32.CreateMethod('CreatePipe');
52
- k32.CreateMethod('CreateProcessW');
53
- k32.CreateMethod('CreatePseudoConsole');
54
- k32.CreateMethod('CloseHandle');
55
- k32.CreateMethod('ClosePseudoConsole');
56
- k32.CreateMethod('GetProcessHeap');
57
- k32.CreateMethod('HeapAlloc');
58
- k32.CreateMethod('InitializeProcThreadAttributeList');
59
- k32.CreateMethod('ResizePseudoConsole');
60
- k32.CreateMethod('UpdateProcThreadAttribute');
61
- k32.CreateMethod('WriteFile');
62
- k32.CreateMethod('ReadFile');
63
- k32.CreateMethod('TerminateProcess');
50
+ k32.CreateMethod('CancelIoEx'); // https://learn.microsoft.com/en-us/windows/win32/fileio/cancelioex-func
51
+ k32.CreateMethod('CreatePipe'); // https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe
52
+ k32.CreateMethod('CreateProcessW'); // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw
53
+ k32.CreateMethod('CreatePseudoConsole'); // https://learn.microsoft.com/en-us/windows/console/createpseudoconsole
54
+ k32.CreateMethod('CloseHandle'); // https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
55
+ k32.CreateMethod('ClosePseudoConsole'); // https://learn.microsoft.com/en-us/windows/console/closepseudoconsole
56
+ k32.CreateMethod('GetProcessHeap'); // https://learn.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-getprocessheap
57
+ k32.CreateMethod('HeapAlloc'); // https://learn.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapalloc
58
+ k32.CreateMethod('InitializeProcThreadAttributeList'); // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-initializeprocthreadattributelist
59
+ k32.CreateMethod('ResizePseudoConsole'); // https://learn.microsoft.com/en-us/windows/console/resizepseudoconsole
60
+ k32.CreateMethod('UpdateProcThreadAttribute'); // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute
61
+ k32.CreateMethod('WriteFile'); // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile
62
+ k32.CreateMethod('ReadFile'); // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile
63
+ k32.CreateMethod('TerminateProcess'); // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-terminateprocess
64
65
var ret = { _h: GM.CreatePointer(), _consoleInput: GM.CreatePointer(), _consoleOutput: GM.CreatePointer(), _input: GM.CreatePointer(), _output: GM.CreatePointer(), k32: k32 };
66
var attrSize = GM.CreateVariable(8);
@@ -77,18 +77,31 @@ function vt()
77
throw ('Error calling CreatePseudoConsole()');
78
}
79
80
+ //
81
+ // Reference for STARTUPINFOEXW
82
+ // https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-startupinfoexw
83
+ //
84
+
85
+ //
86
+ // Reference for STARTUPINFOW
87
+ // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfow
88
+ //
89
+
90
k32.InitializeProcThreadAttributeList(0, 1, 0, attrSize);
91
attrList = GM.CreateVariable(attrSize.toBuffer().readUInt32LE());
82
- var startupinfoex = GM.CreateVariable(GM.PointerSize == 8 ? 112 : 72);
83
- startupinfoex.toBuffer().writeUInt32LE(GM.PointerSize == 8 ? 112 : 72, 0);
84
- attrList.pointerBuffer().copy(startupinfoex.Deref(GM.PointerSize == 8 ? 104 : 68, GM.PointerSize).toBuffer());
92
+ var startupinfoex = GM.CreateVariable(GM.PointerSize == 8 ? 112 : 72); // Create Structure, 64 bits is 112 bytes, 32 bits is 72 bytes
93
+ startupinfoex.toBuffer().writeUInt32LE(GM.PointerSize == 8 ? 112 : 72, 0); // Write buffer size
94
+ attrList.pointerBuffer().copy(startupinfoex.Deref(GM.PointerSize == 8 ? 104 : 68, GM.PointerSize).toBuffer()); // Write the reference to STARTUPINFOEX
95
96
if (k32.InitializeProcThreadAttributeList(attrList, 1, 0, attrSize).Val != 0)
97
{
98
if (k32.UpdateProcThreadAttribute(attrList, 0, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, ret._h.Deref(), GM.PointerSize, 0, 0).Val != 0)
99
{
90
- if (k32.CreateProcessW(0, GM.CreateVariable(path, { wide: true }), 0, 0, 1, EXTENDED_STARTUPINFO_PRESENT, 0, 0, startupinfoex, pi).Val != 0)
100
+ if (k32.CreateProcessW(0, GM.CreateVariable(path, { wide: true }), 0, 0, 1, EXTENDED_STARTUPINFO_PRESENT, 0, 0, startupinfoex, pi).Val != 0) // Create the process to run in the pseudoconsole
101
{
102
+ //
103
+ // Create a Stream Object, to be able to read/write data to the pseudoconsole
104
+ //
105
ret._startupinfoex = startupinfoex;
106
ret._process = pi.Deref(0);
107
ret._pid = pi.Deref(GM.PointerSize == 4 ? 8 : 16, 4).toBuffer().readUInt32LE();
@@ -111,6 +124,10 @@ function vt()
124
flush();
125
}
126
});
127
+
128
+ //
129
+ // The ProcessInfo object is signaled when the process exits
130
+ //
131
ds._obj = ret;
132
ret._waiter = require('DescriptorEvents').addDescriptor(pi.Deref(0));
133
ret._waiter.ds = ds;
@@ -151,6 +168,7 @@ function vt()
168
ds._rpbufRead = GM.CreateVariable(4);
169
ds.__read = function __read()
170
{
171
+ // Asyncronously read data from the pseudoconsole
172
this._rp = this.terminal.k32.ReadFile.async(this.terminal._output.Deref(), this._rpbuf, this._rpbuf._size, this._rpbufRead, 0);
173
this._rp.then(function ()
174
{
@@ -173,6 +191,8 @@ function vt()
191
}
192
throw ('Internal Error');
193
}
194
+
195
+ // This evaluates whether or not the powershell binary exists
196
this.PowerShellCapable = function ()
197
{
198
if (require('os').arch() == 'x64')
@@ -184,10 +204,14 @@ function vt()
204
return (require('fs').existsSync(process.env['windir'] + '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'));
205
}
206
}
207
+
208
+ // Start the PseudoConsole with the Command Prompt
209
this.Start = function Start(CONSOLE_SCREEN_WIDTH, CONSOLE_SCREEN_HEIGHT)
210
{
211
return (this.Create(process.env['windir'] + '\\System32\\cmd.exe', CONSOLE_SCREEN_WIDTH, CONSOLE_SCREEN_HEIGHT));
212
}
213
+
214
+ // Start the PseduoConsole with PowerShell
215
this.StartPowerShell = function StartPowerShell(CONSOLE_SCREEN_WIDTH, CONSOLE_SCREEN_HEIGHT)
216
{
217
if (require('os').arch() == 'x64')