@jshookmcp/jshook 0.1.6 → 0.1.7
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/LICENSE +661 -661
- package/dist/index.js +0 -0
- package/dist/modules/captcha/AICaptchaDetector.js +185 -185
- package/dist/modules/process/MacProcessManager.js +25 -25
- package/dist/modules/process/memory/availability.js +49 -49
- package/dist/modules/process/memory/injector.js +185 -185
- package/dist/modules/process/memory/reader.js +50 -50
- package/dist/modules/process/memory/scanner.js +165 -165
- package/dist/modules/process/memory/writer.js +54 -54
- package/dist/native/scripts/linux/enum-windows.sh +12 -12
- package/dist/native/scripts/macos/enum-windows.applescript +22 -22
- package/dist/native/scripts/windows/enum-windows-by-class.ps1 +51 -51
- package/dist/native/scripts/windows/enum-windows.ps1 +44 -44
- package/dist/native/scripts/windows/inject-dll.ps1 +21 -21
- package/dist/server/domains/browser/definitions.tools.page-core.js +53 -53
- package/dist/server/domains/browser/definitions.tools.runtime.js +40 -40
- package/dist/server/domains/browser/definitions.tools.security.js +76 -76
- package/dist/server/domains/transform/handlers.impl.transform-base.js +102 -102
- package/dist/server/domains/workflow/handlers.impl.workflow-base.js +51 -51
- package/package.json +26 -43
- package/src/native/scripts/linux/enum-windows.sh +12 -12
- package/src/native/scripts/macos/enum-windows.applescript +22 -22
- package/src/native/scripts/windows/enum-windows-by-class.ps1 +51 -51
- package/src/native/scripts/windows/enum-windows.ps1 +44 -44
- package/src/native/scripts/windows/inject-dll.ps1 +21 -21
|
@@ -156,130 +156,130 @@ function buildMemoryScanScript(pid, pattern, patternType) {
|
|
|
156
156
|
const { patternBytes, mask } = buildPatternBytesAndMask(pattern, patternType);
|
|
157
157
|
const patternArray = patternBytes.join(',');
|
|
158
158
|
const maskArray = mask.join(',');
|
|
159
|
-
return `
|
|
160
|
-
Add-Type @"
|
|
161
|
-
using System;
|
|
162
|
-
using System.Runtime.InteropServices;
|
|
163
|
-
using System.Collections.Generic;
|
|
164
|
-
using System.ComponentModel;
|
|
165
|
-
|
|
166
|
-
public class MemoryScanner {
|
|
167
|
-
[DllImport("kernel32.dll", SetLastError = true)]
|
|
168
|
-
public static extern IntPtr OpenProcess(int access, bool inherit, int pid);
|
|
169
|
-
|
|
170
|
-
[DllImport("kernel32.dll", SetLastError = true)]
|
|
171
|
-
public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr addr, byte[] buffer, int size, out int read);
|
|
172
|
-
|
|
173
|
-
[DllImport("kernel32.dll", SetLastError = true)]
|
|
174
|
-
public static extern int VirtualQueryEx(IntPtr hProcess, IntPtr addr, out MEMORY_BASIC_INFORMATION info, int size);
|
|
175
|
-
|
|
176
|
-
[DllImport("kernel32.dll", SetLastError = true)]
|
|
177
|
-
public static extern bool CloseHandle(IntPtr handle);
|
|
178
|
-
|
|
179
|
-
const int PROCESS_VM_READ = 0x0010;
|
|
180
|
-
const int PROCESS_QUERY_INFORMATION = 0x0400;
|
|
181
|
-
|
|
182
|
-
[StructLayout(LayoutKind.Sequential)]
|
|
183
|
-
public struct MEMORY_BASIC_INFORMATION {
|
|
184
|
-
public IntPtr BaseAddress;
|
|
185
|
-
public IntPtr AllocationBase;
|
|
186
|
-
public uint AllocationProtect;
|
|
187
|
-
public IntPtr RegionSize;
|
|
188
|
-
public uint State;
|
|
189
|
-
public uint Protect;
|
|
190
|
-
public uint Type;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const uint MEM_COMMIT = 0x1000;
|
|
194
|
-
const uint PAGE_READONLY = 0x02;
|
|
195
|
-
const uint PAGE_READWRITE = 0x04;
|
|
196
|
-
const uint PAGE_WRITECOPY = 0x08;
|
|
197
|
-
const uint PAGE_EXECUTE_READ = 0x20;
|
|
198
|
-
const uint PAGE_EXECUTE_READWRITE = 0x40;
|
|
199
|
-
|
|
200
|
-
public static List<string> ScanMemory(int pid, byte[] pattern, byte[] mask, int maxResults = 10000) {
|
|
201
|
-
var results = new List<string>();
|
|
202
|
-
IntPtr hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, false, pid);
|
|
203
|
-
if (hProcess == IntPtr.Zero) {
|
|
204
|
-
int error = Marshal.GetLastWin32Error();
|
|
205
|
-
throw new Win32Exception(error, "Failed to open process. Run as Administrator.");
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
try {
|
|
209
|
-
IntPtr addr = IntPtr.Zero;
|
|
210
|
-
MEMORY_BASIC_INFORMATION info;
|
|
211
|
-
int infoSize = Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION));
|
|
212
|
-
int scannedRegions = 0;
|
|
213
|
-
|
|
214
|
-
while (VirtualQueryEx(hProcess, addr, out info, infoSize) == infoSize) {
|
|
215
|
-
scannedRegions++;
|
|
216
|
-
bool isReadable = (info.State == MEM_COMMIT) &&
|
|
217
|
-
((info.Protect & PAGE_READONLY) != 0 ||
|
|
218
|
-
(info.Protect & PAGE_READWRITE) != 0 ||
|
|
219
|
-
(info.Protect & PAGE_WRITECOPY) != 0 ||
|
|
220
|
-
(info.Protect & PAGE_EXECUTE_READ) != 0 ||
|
|
221
|
-
(info.Protect & PAGE_EXECUTE_READWRITE) != 0);
|
|
222
|
-
|
|
223
|
-
if (isReadable && info.RegionSize.ToInt64() > 0 && info.RegionSize.ToInt64() < 1073741824) {
|
|
224
|
-
long regionSize = info.RegionSize.ToInt64();
|
|
225
|
-
if (regionSize > 16777216) regionSize = 16777216; // bound scan window per region (16MB)
|
|
226
|
-
byte[] buffer = new byte[(int)regionSize];
|
|
227
|
-
int bytesRead;
|
|
228
|
-
|
|
229
|
-
if (ReadProcessMemory(hProcess, info.BaseAddress, buffer, buffer.Length, out bytesRead)) {
|
|
230
|
-
for (int i = 0; i <= bytesRead - pattern.Length; i++) {
|
|
231
|
-
if (PatternMatch(buffer, i, pattern, mask)) {
|
|
232
|
-
long foundAddr = info.BaseAddress.ToInt64() + i;
|
|
233
|
-
results.Add("0x" + foundAddr.ToString("X"));
|
|
234
|
-
if (results.Count >= maxResults) break;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
if (results.Count >= maxResults) break;
|
|
241
|
-
if (scannedRegions >= 50000) break;
|
|
242
|
-
long baseAddr = info.BaseAddress.ToInt64();
|
|
243
|
-
long regionSizeRaw = info.RegionSize.ToInt64();
|
|
244
|
-
if (regionSizeRaw <= 0) break;
|
|
245
|
-
long nextAddr = baseAddr + regionSizeRaw;
|
|
246
|
-
if (nextAddr <= baseAddr) break;
|
|
247
|
-
addr = new IntPtr(nextAddr);
|
|
248
|
-
if (addr.ToInt64() >= 0x7FFFFFFF0000) break;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return results;
|
|
252
|
-
} finally {
|
|
253
|
-
CloseHandle(hProcess);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
private static bool PatternMatch(byte[] buffer, int offset, byte[] pattern, byte[] mask) {
|
|
258
|
-
for (int i = 0; i < pattern.Length; i++) {
|
|
259
|
-
if (mask[i] == 1 && buffer[offset + i] != pattern[i]) {
|
|
260
|
-
return false;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
return true;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
"@
|
|
267
|
-
|
|
268
|
-
try {
|
|
269
|
-
$patternBytes = @(${patternArray})
|
|
270
|
-
$maskBytes = @(${maskArray})
|
|
271
|
-
$results = [MemoryScanner]::ScanMemory(${pid}, $patternBytes, $maskBytes, 1000)
|
|
272
|
-
@{
|
|
273
|
-
success = $true;
|
|
274
|
-
addresses = $results;
|
|
275
|
-
stats = @{
|
|
276
|
-
patternLength = $patternBytes.Length;
|
|
277
|
-
resultsFound = $results.Count
|
|
278
|
-
}
|
|
279
|
-
} | ConvertTo-Json -Compress
|
|
280
|
-
} catch {
|
|
281
|
-
@{ success = $false; error = $_.Exception.Message } | ConvertTo-Json -Compress
|
|
282
|
-
}
|
|
159
|
+
return `
|
|
160
|
+
Add-Type @"
|
|
161
|
+
using System;
|
|
162
|
+
using System.Runtime.InteropServices;
|
|
163
|
+
using System.Collections.Generic;
|
|
164
|
+
using System.ComponentModel;
|
|
165
|
+
|
|
166
|
+
public class MemoryScanner {
|
|
167
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
168
|
+
public static extern IntPtr OpenProcess(int access, bool inherit, int pid);
|
|
169
|
+
|
|
170
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
171
|
+
public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr addr, byte[] buffer, int size, out int read);
|
|
172
|
+
|
|
173
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
174
|
+
public static extern int VirtualQueryEx(IntPtr hProcess, IntPtr addr, out MEMORY_BASIC_INFORMATION info, int size);
|
|
175
|
+
|
|
176
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
177
|
+
public static extern bool CloseHandle(IntPtr handle);
|
|
178
|
+
|
|
179
|
+
const int PROCESS_VM_READ = 0x0010;
|
|
180
|
+
const int PROCESS_QUERY_INFORMATION = 0x0400;
|
|
181
|
+
|
|
182
|
+
[StructLayout(LayoutKind.Sequential)]
|
|
183
|
+
public struct MEMORY_BASIC_INFORMATION {
|
|
184
|
+
public IntPtr BaseAddress;
|
|
185
|
+
public IntPtr AllocationBase;
|
|
186
|
+
public uint AllocationProtect;
|
|
187
|
+
public IntPtr RegionSize;
|
|
188
|
+
public uint State;
|
|
189
|
+
public uint Protect;
|
|
190
|
+
public uint Type;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const uint MEM_COMMIT = 0x1000;
|
|
194
|
+
const uint PAGE_READONLY = 0x02;
|
|
195
|
+
const uint PAGE_READWRITE = 0x04;
|
|
196
|
+
const uint PAGE_WRITECOPY = 0x08;
|
|
197
|
+
const uint PAGE_EXECUTE_READ = 0x20;
|
|
198
|
+
const uint PAGE_EXECUTE_READWRITE = 0x40;
|
|
199
|
+
|
|
200
|
+
public static List<string> ScanMemory(int pid, byte[] pattern, byte[] mask, int maxResults = 10000) {
|
|
201
|
+
var results = new List<string>();
|
|
202
|
+
IntPtr hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, false, pid);
|
|
203
|
+
if (hProcess == IntPtr.Zero) {
|
|
204
|
+
int error = Marshal.GetLastWin32Error();
|
|
205
|
+
throw new Win32Exception(error, "Failed to open process. Run as Administrator.");
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
try {
|
|
209
|
+
IntPtr addr = IntPtr.Zero;
|
|
210
|
+
MEMORY_BASIC_INFORMATION info;
|
|
211
|
+
int infoSize = Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION));
|
|
212
|
+
int scannedRegions = 0;
|
|
213
|
+
|
|
214
|
+
while (VirtualQueryEx(hProcess, addr, out info, infoSize) == infoSize) {
|
|
215
|
+
scannedRegions++;
|
|
216
|
+
bool isReadable = (info.State == MEM_COMMIT) &&
|
|
217
|
+
((info.Protect & PAGE_READONLY) != 0 ||
|
|
218
|
+
(info.Protect & PAGE_READWRITE) != 0 ||
|
|
219
|
+
(info.Protect & PAGE_WRITECOPY) != 0 ||
|
|
220
|
+
(info.Protect & PAGE_EXECUTE_READ) != 0 ||
|
|
221
|
+
(info.Protect & PAGE_EXECUTE_READWRITE) != 0);
|
|
222
|
+
|
|
223
|
+
if (isReadable && info.RegionSize.ToInt64() > 0 && info.RegionSize.ToInt64() < 1073741824) {
|
|
224
|
+
long regionSize = info.RegionSize.ToInt64();
|
|
225
|
+
if (regionSize > 16777216) regionSize = 16777216; // bound scan window per region (16MB)
|
|
226
|
+
byte[] buffer = new byte[(int)regionSize];
|
|
227
|
+
int bytesRead;
|
|
228
|
+
|
|
229
|
+
if (ReadProcessMemory(hProcess, info.BaseAddress, buffer, buffer.Length, out bytesRead)) {
|
|
230
|
+
for (int i = 0; i <= bytesRead - pattern.Length; i++) {
|
|
231
|
+
if (PatternMatch(buffer, i, pattern, mask)) {
|
|
232
|
+
long foundAddr = info.BaseAddress.ToInt64() + i;
|
|
233
|
+
results.Add("0x" + foundAddr.ToString("X"));
|
|
234
|
+
if (results.Count >= maxResults) break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (results.Count >= maxResults) break;
|
|
241
|
+
if (scannedRegions >= 50000) break;
|
|
242
|
+
long baseAddr = info.BaseAddress.ToInt64();
|
|
243
|
+
long regionSizeRaw = info.RegionSize.ToInt64();
|
|
244
|
+
if (regionSizeRaw <= 0) break;
|
|
245
|
+
long nextAddr = baseAddr + regionSizeRaw;
|
|
246
|
+
if (nextAddr <= baseAddr) break;
|
|
247
|
+
addr = new IntPtr(nextAddr);
|
|
248
|
+
if (addr.ToInt64() >= 0x7FFFFFFF0000) break;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return results;
|
|
252
|
+
} finally {
|
|
253
|
+
CloseHandle(hProcess);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private static bool PatternMatch(byte[] buffer, int offset, byte[] pattern, byte[] mask) {
|
|
258
|
+
for (int i = 0; i < pattern.Length; i++) {
|
|
259
|
+
if (mask[i] == 1 && buffer[offset + i] != pattern[i]) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
"@
|
|
267
|
+
|
|
268
|
+
try {
|
|
269
|
+
$patternBytes = @(${patternArray})
|
|
270
|
+
$maskBytes = @(${maskArray})
|
|
271
|
+
$results = [MemoryScanner]::ScanMemory(${pid}, $patternBytes, $maskBytes, 1000)
|
|
272
|
+
@{
|
|
273
|
+
success = $true;
|
|
274
|
+
addresses = $results;
|
|
275
|
+
stats = @{
|
|
276
|
+
patternLength = $patternBytes.Length;
|
|
277
|
+
resultsFound = $results.Count
|
|
278
|
+
}
|
|
279
|
+
} | ConvertTo-Json -Compress
|
|
280
|
+
} catch {
|
|
281
|
+
@{ success = $false; error = $_.Exception.Message } | ConvertTo-Json -Compress
|
|
282
|
+
}
|
|
283
283
|
`.trim();
|
|
284
284
|
}
|
|
285
285
|
async function scanMemoryWindows(pid, pattern, patternType) {
|
|
@@ -497,47 +497,47 @@ async function scanMemoryMac(pid, pattern, patternType) {
|
|
|
497
497
|
const tag = `${pid}_${Date.now()}`;
|
|
498
498
|
const pyFile = `/tmp/lldb_scan_${tag}.py`;
|
|
499
499
|
const cmdFile = `/tmp/lldb_scan_${tag}.txt`;
|
|
500
|
-
const pyScript = `
|
|
501
|
-
import lldb, json, sys
|
|
502
|
-
|
|
503
|
-
def __lldb_init_module(debugger, internal_dict):
|
|
504
|
-
proc = debugger.GetSelectedTarget().GetProcess()
|
|
505
|
-
pat = bytes([${byteList}])
|
|
506
|
-
mask = [${maskList}]
|
|
507
|
-
results = []
|
|
508
|
-
rl = proc.GetMemoryRegions()
|
|
509
|
-
for i in range(rl.GetSize()):
|
|
510
|
-
info = lldb.SBMemoryRegionInfo()
|
|
511
|
-
rl.GetMemoryRegionAtIndex(i, info)
|
|
512
|
-
if not info.IsReadable():
|
|
513
|
-
continue
|
|
514
|
-
s = info.GetRegionBase()
|
|
515
|
-
sz = info.GetRegionEnd() - s
|
|
516
|
-
if sz > 32 * 1024 * 1024:
|
|
517
|
-
continue
|
|
518
|
-
err = lldb.SBError()
|
|
519
|
-
data = proc.ReadMemory(s, sz, err)
|
|
520
|
-
if not err.Success():
|
|
521
|
-
continue
|
|
522
|
-
n = len(pat)
|
|
523
|
-
for j in range(len(data) - n + 1):
|
|
524
|
-
match = True
|
|
525
|
-
for k in range(n):
|
|
526
|
-
if mask[k] == 1 and data[j+k] != pat[k]:
|
|
527
|
-
match = False
|
|
528
|
-
break
|
|
529
|
-
if match:
|
|
530
|
-
results.append(hex(s + j))
|
|
531
|
-
if len(results) >= 1000:
|
|
532
|
-
break
|
|
533
|
-
if len(results) >= 1000:
|
|
534
|
-
break
|
|
535
|
-
sys.stdout.write('SCAN_RESULT:' + json.dumps({
|
|
536
|
-
'success': True,
|
|
537
|
-
'addresses': results,
|
|
538
|
-
'stats': {'patternLength': len(pat), 'resultsFound': len(results)}
|
|
539
|
-
}) + '\\n')
|
|
540
|
-
sys.stdout.flush()
|
|
500
|
+
const pyScript = `
|
|
501
|
+
import lldb, json, sys
|
|
502
|
+
|
|
503
|
+
def __lldb_init_module(debugger, internal_dict):
|
|
504
|
+
proc = debugger.GetSelectedTarget().GetProcess()
|
|
505
|
+
pat = bytes([${byteList}])
|
|
506
|
+
mask = [${maskList}]
|
|
507
|
+
results = []
|
|
508
|
+
rl = proc.GetMemoryRegions()
|
|
509
|
+
for i in range(rl.GetSize()):
|
|
510
|
+
info = lldb.SBMemoryRegionInfo()
|
|
511
|
+
rl.GetMemoryRegionAtIndex(i, info)
|
|
512
|
+
if not info.IsReadable():
|
|
513
|
+
continue
|
|
514
|
+
s = info.GetRegionBase()
|
|
515
|
+
sz = info.GetRegionEnd() - s
|
|
516
|
+
if sz > 32 * 1024 * 1024:
|
|
517
|
+
continue
|
|
518
|
+
err = lldb.SBError()
|
|
519
|
+
data = proc.ReadMemory(s, sz, err)
|
|
520
|
+
if not err.Success():
|
|
521
|
+
continue
|
|
522
|
+
n = len(pat)
|
|
523
|
+
for j in range(len(data) - n + 1):
|
|
524
|
+
match = True
|
|
525
|
+
for k in range(n):
|
|
526
|
+
if mask[k] == 1 and data[j+k] != pat[k]:
|
|
527
|
+
match = False
|
|
528
|
+
break
|
|
529
|
+
if match:
|
|
530
|
+
results.append(hex(s + j))
|
|
531
|
+
if len(results) >= 1000:
|
|
532
|
+
break
|
|
533
|
+
if len(results) >= 1000:
|
|
534
|
+
break
|
|
535
|
+
sys.stdout.write('SCAN_RESULT:' + json.dumps({
|
|
536
|
+
'success': True,
|
|
537
|
+
'addresses': results,
|
|
538
|
+
'stats': {'patternLength': len(pat), 'resultsFound': len(results)}
|
|
539
|
+
}) + '\\n')
|
|
540
|
+
sys.stdout.flush()
|
|
541
541
|
`;
|
|
542
542
|
await fs.writeFile(pyFile, pyScript, 'utf8');
|
|
543
543
|
await fs.writeFile(cmdFile, `command script import ${pyFile}\nprocess detach\n`, 'utf8');
|
|
@@ -5,60 +5,60 @@ import { execAsync, executePowerShellScript, } from '../../process/memory/types.
|
|
|
5
5
|
async function writeMemoryWindows(pid, address, data) {
|
|
6
6
|
try {
|
|
7
7
|
const hexData = data.toString('hex').toUpperCase();
|
|
8
|
-
const psScript = `
|
|
9
|
-
Add-Type @"
|
|
10
|
-
using System;
|
|
11
|
-
using System.Runtime.InteropServices;
|
|
12
|
-
using System.ComponentModel;
|
|
13
|
-
|
|
14
|
-
public class MemoryWriter {
|
|
15
|
-
[DllImport("kernel32.dll", SetLastError = true)]
|
|
16
|
-
public static extern IntPtr OpenProcess(int access, bool inherit, int pid);
|
|
17
|
-
|
|
18
|
-
[DllImport("kernel32.dll", SetLastError = true)]
|
|
19
|
-
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr addr, byte[] buffer, int size, out int written);
|
|
20
|
-
|
|
21
|
-
[DllImport("kernel32.dll", SetLastError = true)]
|
|
22
|
-
public static extern bool CloseHandle(IntPtr handle);
|
|
23
|
-
|
|
24
|
-
const int PROCESS_VM_WRITE = 0x0020;
|
|
25
|
-
const int PROCESS_VM_OPERATION = 0x0008;
|
|
26
|
-
|
|
27
|
-
public static int WriteMemory(int pid, long address, string hexData) {
|
|
28
|
-
IntPtr hProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, false, pid);
|
|
29
|
-
if (hProcess == IntPtr.Zero) {
|
|
30
|
-
int error = Marshal.GetLastWin32Error();
|
|
31
|
-
throw new Win32Exception(error, "Failed to open process. Run as Administrator.");
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
byte[] buffer = new byte[hexData.Length / 2];
|
|
36
|
-
for (int i = 0; i < hexData.Length; i += 2) {
|
|
37
|
-
buffer[i / 2] = Convert.ToByte(hexData.Substring(i, 2), 16);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
int bytesWritten;
|
|
41
|
-
bool success = WriteProcessMemory(hProcess, (IntPtr)address, buffer, buffer.Length, out bytesWritten);
|
|
42
|
-
|
|
43
|
-
if (!success) {
|
|
44
|
-
int error = Marshal.GetLastWin32Error();
|
|
45
|
-
throw new Win32Exception(error, "Failed to write memory");
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return bytesWritten;
|
|
49
|
-
} finally {
|
|
50
|
-
CloseHandle(hProcess);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
"@
|
|
55
|
-
|
|
56
|
-
try {
|
|
57
|
-
$bytesWritten = [MemoryWriter]::WriteMemory(${pid}, ${address}, "${hexData}")
|
|
58
|
-
@{ success = $true; bytesWritten = $bytesWritten } | ConvertTo-Json -Compress
|
|
59
|
-
} catch {
|
|
60
|
-
@{ success = $false; error = $_.Exception.Message } | ConvertTo-Json -Compress
|
|
61
|
-
}
|
|
8
|
+
const psScript = `
|
|
9
|
+
Add-Type @"
|
|
10
|
+
using System;
|
|
11
|
+
using System.Runtime.InteropServices;
|
|
12
|
+
using System.ComponentModel;
|
|
13
|
+
|
|
14
|
+
public class MemoryWriter {
|
|
15
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
16
|
+
public static extern IntPtr OpenProcess(int access, bool inherit, int pid);
|
|
17
|
+
|
|
18
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
19
|
+
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr addr, byte[] buffer, int size, out int written);
|
|
20
|
+
|
|
21
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
22
|
+
public static extern bool CloseHandle(IntPtr handle);
|
|
23
|
+
|
|
24
|
+
const int PROCESS_VM_WRITE = 0x0020;
|
|
25
|
+
const int PROCESS_VM_OPERATION = 0x0008;
|
|
26
|
+
|
|
27
|
+
public static int WriteMemory(int pid, long address, string hexData) {
|
|
28
|
+
IntPtr hProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, false, pid);
|
|
29
|
+
if (hProcess == IntPtr.Zero) {
|
|
30
|
+
int error = Marshal.GetLastWin32Error();
|
|
31
|
+
throw new Win32Exception(error, "Failed to open process. Run as Administrator.");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
byte[] buffer = new byte[hexData.Length / 2];
|
|
36
|
+
for (int i = 0; i < hexData.Length; i += 2) {
|
|
37
|
+
buffer[i / 2] = Convert.ToByte(hexData.Substring(i, 2), 16);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
int bytesWritten;
|
|
41
|
+
bool success = WriteProcessMemory(hProcess, (IntPtr)address, buffer, buffer.Length, out bytesWritten);
|
|
42
|
+
|
|
43
|
+
if (!success) {
|
|
44
|
+
int error = Marshal.GetLastWin32Error();
|
|
45
|
+
throw new Win32Exception(error, "Failed to write memory");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return bytesWritten;
|
|
49
|
+
} finally {
|
|
50
|
+
CloseHandle(hProcess);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
"@
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
$bytesWritten = [MemoryWriter]::WriteMemory(${pid}, ${address}, "${hexData}")
|
|
58
|
+
@{ success = $true; bytesWritten = $bytesWritten } | ConvertTo-Json -Compress
|
|
59
|
+
} catch {
|
|
60
|
+
@{ success = $false; error = $_.Exception.Message } | ConvertTo-Json -Compress
|
|
61
|
+
}
|
|
62
62
|
`;
|
|
63
63
|
const { stdout } = await executePowerShellScript(psScript, { maxBuffer: 1024 * 1024 });
|
|
64
64
|
const _trimmed = stdout.trim();
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# enum-windows.sh
|
|
3
|
-
# Linux window enumeration script (placeholder)
|
|
4
|
-
|
|
5
|
-
TARGET_PID=$1
|
|
6
|
-
|
|
7
|
-
# Use xdotool or wmctrl for window enumeration
|
|
8
|
-
# This is a placeholder for future implementation
|
|
9
|
-
|
|
10
|
-
if command -v xdotool &> /dev/null; then
|
|
11
|
-
xdotool search --pid "$TARGET_PID" --name "" get-window-name
|
|
12
|
-
fi
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# enum-windows.sh
|
|
3
|
+
# Linux window enumeration script (placeholder)
|
|
4
|
+
|
|
5
|
+
TARGET_PID=$1
|
|
6
|
+
|
|
7
|
+
# Use xdotool or wmctrl for window enumeration
|
|
8
|
+
# This is a placeholder for future implementation
|
|
9
|
+
|
|
10
|
+
if command -v xdotool &> /dev/null; then
|
|
11
|
+
xdotool search --pid "$TARGET_PID" --name "" get-window-name
|
|
12
|
+
fi
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
-- enum-windows.applescript
|
|
2
|
-
-- macOS window enumeration script (placeholder)
|
|
3
|
-
|
|
4
|
-
param TargetPid
|
|
5
|
-
|
|
6
|
-
-- AppleScript implementation for window enumeration
|
|
7
|
-
-- This is a placeholder for future implementation
|
|
8
|
-
|
|
9
|
-
tell application "System Events"
|
|
10
|
-
set windowList to {}
|
|
11
|
-
repeat with proc in (every process whose unix id is TargetPid)
|
|
12
|
-
repeat with win in windows of proc
|
|
13
|
-
set end of windowList to {¬
|
|
14
|
-
title: name of win, ¬
|
|
15
|
-
position: position of win, ¬
|
|
16
|
-
size: size of win ¬
|
|
17
|
-
}
|
|
18
|
-
end repeat
|
|
19
|
-
end repeat
|
|
20
|
-
end tell
|
|
21
|
-
|
|
22
|
-
return windowList
|
|
1
|
+
-- enum-windows.applescript
|
|
2
|
+
-- macOS window enumeration script (placeholder)
|
|
3
|
+
|
|
4
|
+
param TargetPid
|
|
5
|
+
|
|
6
|
+
-- AppleScript implementation for window enumeration
|
|
7
|
+
-- This is a placeholder for future implementation
|
|
8
|
+
|
|
9
|
+
tell application "System Events"
|
|
10
|
+
set windowList to {}
|
|
11
|
+
repeat with proc in (every process whose unix id is TargetPid)
|
|
12
|
+
repeat with win in windows of proc
|
|
13
|
+
set end of windowList to {¬
|
|
14
|
+
title: name of win, ¬
|
|
15
|
+
position: position of win, ¬
|
|
16
|
+
size: size of win ¬
|
|
17
|
+
}
|
|
18
|
+
end repeat
|
|
19
|
+
end repeat
|
|
20
|
+
end tell
|
|
21
|
+
|
|
22
|
+
return windowList
|
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
param(
|
|
2
|
-
[string]$ClassPattern
|
|
3
|
-
)
|
|
4
|
-
|
|
5
|
-
Add-Type @"
|
|
6
|
-
using System;
|
|
7
|
-
using System.Runtime.InteropServices;
|
|
8
|
-
public class Win32 {
|
|
9
|
-
[DllImport("user32.dll")] public static extern IntPtr FindWindowEx(IntPtr parent, IntPtr childAfter, string className, string title);
|
|
10
|
-
[DllImport("user32.dll")] public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int pid);
|
|
11
|
-
[DllImport("user32.dll")] public static extern int GetWindowText(IntPtr hWnd, System.Text.StringBuilder text, int count);
|
|
12
|
-
[DllImport("user32.dll")] public static extern int GetClassName(IntPtr hWnd, System.Text.StringBuilder className, int maxCount);
|
|
13
|
-
}
|
|
14
|
-
"@
|
|
15
|
-
|
|
16
|
-
$windows = @()
|
|
17
|
-
$hwnd = [IntPtr]::Zero
|
|
18
|
-
while ($true) {
|
|
19
|
-
$hwnd = [Win32]::FindWindowEx([IntPtr]::Zero, $hwnd, $null, $null)
|
|
20
|
-
if ($hwnd -eq [IntPtr]::Zero) { break }
|
|
21
|
-
|
|
22
|
-
$className = New-Object System.Text.StringBuilder 256
|
|
23
|
-
[Win32]::GetClassName($hwnd, $className, 256) | Out-Null
|
|
24
|
-
$classNameStr = $className.ToString()
|
|
25
|
-
|
|
26
|
-
# Support wildcard pattern matching
|
|
27
|
-
$isMatch = $false
|
|
28
|
-
if ($ClassPattern -eq $classNameStr) {
|
|
29
|
-
$isMatch = $true
|
|
30
|
-
} elseif ($ClassPattern.Contains('*')) {
|
|
31
|
-
# Convert wildcard pattern to regex
|
|
32
|
-
$regexPattern = [regex]::Escape($ClassPattern).Replace('\*', '.*')
|
|
33
|
-
if ($classNameStr -match $regexPattern) {
|
|
34
|
-
$isMatch = $true
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if ($isMatch) {
|
|
39
|
-
$windowPid = 0
|
|
40
|
-
[Win32]::GetWindowThreadProcessId($hwnd, [ref]$windowPid) | Out-Null
|
|
41
|
-
$title = New-Object System.Text.StringBuilder 256
|
|
42
|
-
[Win32]::GetWindowText($hwnd, $title, 256) | Out-Null
|
|
43
|
-
$windows += @{
|
|
44
|
-
Handle = $hwnd.ToString()
|
|
45
|
-
Title = $title.ToString()
|
|
46
|
-
ClassName = $classNameStr
|
|
47
|
-
ProcessId = $windowPid
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
$windows | ConvertTo-Json -Compress
|
|
1
|
+
param(
|
|
2
|
+
[string]$ClassPattern
|
|
3
|
+
)
|
|
4
|
+
|
|
5
|
+
Add-Type @"
|
|
6
|
+
using System;
|
|
7
|
+
using System.Runtime.InteropServices;
|
|
8
|
+
public class Win32 {
|
|
9
|
+
[DllImport("user32.dll")] public static extern IntPtr FindWindowEx(IntPtr parent, IntPtr childAfter, string className, string title);
|
|
10
|
+
[DllImport("user32.dll")] public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int pid);
|
|
11
|
+
[DllImport("user32.dll")] public static extern int GetWindowText(IntPtr hWnd, System.Text.StringBuilder text, int count);
|
|
12
|
+
[DllImport("user32.dll")] public static extern int GetClassName(IntPtr hWnd, System.Text.StringBuilder className, int maxCount);
|
|
13
|
+
}
|
|
14
|
+
"@
|
|
15
|
+
|
|
16
|
+
$windows = @()
|
|
17
|
+
$hwnd = [IntPtr]::Zero
|
|
18
|
+
while ($true) {
|
|
19
|
+
$hwnd = [Win32]::FindWindowEx([IntPtr]::Zero, $hwnd, $null, $null)
|
|
20
|
+
if ($hwnd -eq [IntPtr]::Zero) { break }
|
|
21
|
+
|
|
22
|
+
$className = New-Object System.Text.StringBuilder 256
|
|
23
|
+
[Win32]::GetClassName($hwnd, $className, 256) | Out-Null
|
|
24
|
+
$classNameStr = $className.ToString()
|
|
25
|
+
|
|
26
|
+
# Support wildcard pattern matching
|
|
27
|
+
$isMatch = $false
|
|
28
|
+
if ($ClassPattern -eq $classNameStr) {
|
|
29
|
+
$isMatch = $true
|
|
30
|
+
} elseif ($ClassPattern.Contains('*')) {
|
|
31
|
+
# Convert wildcard pattern to regex
|
|
32
|
+
$regexPattern = [regex]::Escape($ClassPattern).Replace('\*', '.*')
|
|
33
|
+
if ($classNameStr -match $regexPattern) {
|
|
34
|
+
$isMatch = $true
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if ($isMatch) {
|
|
39
|
+
$windowPid = 0
|
|
40
|
+
[Win32]::GetWindowThreadProcessId($hwnd, [ref]$windowPid) | Out-Null
|
|
41
|
+
$title = New-Object System.Text.StringBuilder 256
|
|
42
|
+
[Win32]::GetWindowText($hwnd, $title, 256) | Out-Null
|
|
43
|
+
$windows += @{
|
|
44
|
+
Handle = $hwnd.ToString()
|
|
45
|
+
Title = $title.ToString()
|
|
46
|
+
ClassName = $classNameStr
|
|
47
|
+
ProcessId = $windowPid
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
$windows | ConvertTo-Json -Compress
|