exoproc 0.6.8 → 0.6.9
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 +6 -6
- package/dist/cli.js +40 -51
- package/dist/index.js +76 -85
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
> One unified CLI and Model Context Protocol (MCP) server for thread hijacking, function detours, live memory manipulation, and C-to-shellcode compilation.
|
|
5
5
|
|
|
6
6
|
[](https://www.npmjs.com/package/exoproc)
|
|
7
|
-
[](https://github.com/
|
|
7
|
+
[](https://github.com/aksoyserkan/exoproc)
|
|
8
8
|
[](https://bun.sh)
|
|
9
9
|
[](LICENSE)
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Instant Setup for AI Agents
|
|
14
14
|
|
|
15
15
|
Exoproc connects your AI coding agents (**Claude Code, Cursor, Windsurf, Claude Desktop, Antigravity, Cline, OpenCode, Zed**) directly to live Windows x64 processes.
|
|
16
16
|
|
|
@@ -32,7 +32,7 @@ Restart your agent, and all 22 MCP tools will be immediately available.
|
|
|
32
32
|
|
|
33
33
|
---
|
|
34
34
|
|
|
35
|
-
##
|
|
35
|
+
## CLI Commands
|
|
36
36
|
|
|
37
37
|
Exoproc provides a unified terminal command-line tool:
|
|
38
38
|
|
|
@@ -57,7 +57,7 @@ exoproc run script.ts # Execute standalone automation script
|
|
|
57
57
|
|
|
58
58
|
---
|
|
59
59
|
|
|
60
|
-
##
|
|
60
|
+
## MCP Tools (22 Tools)
|
|
61
61
|
|
|
62
62
|
Exoproc exposes 22 high-performance tools over standard Model Context Protocol (stdio):
|
|
63
63
|
|
|
@@ -69,7 +69,7 @@ Exoproc exposes 22 high-performance tools over standard Model Context Protocol (
|
|
|
69
69
|
|
|
70
70
|
---
|
|
71
71
|
|
|
72
|
-
##
|
|
72
|
+
## Supported Agents
|
|
73
73
|
|
|
74
74
|
- **Claude Code:** `~/.claude.json` + `~/.claude/skills/exoproc/`
|
|
75
75
|
- **Cursor:** `~/.cursor/mcp.json` + `~/.cursor/rules/exoproc.mdc`
|
|
@@ -82,6 +82,6 @@ Exoproc exposes 22 high-performance tools over standard Model Context Protocol (
|
|
|
82
82
|
|
|
83
83
|
---
|
|
84
84
|
|
|
85
|
-
##
|
|
85
|
+
## License
|
|
86
86
|
|
|
87
87
|
[MIT](LICENSE) © Serkan
|
package/dist/cli.js
CHANGED
|
@@ -95445,7 +95445,7 @@ var init_dist8 = __esm(() => {
|
|
|
95445
95445
|
getSessionMetadata() {
|
|
95446
95446
|
return { ...this._sessionMetadata };
|
|
95447
95447
|
}
|
|
95448
|
-
toJSON() {
|
|
95448
|
+
toJSON(options) {
|
|
95449
95449
|
const chainLayers = [];
|
|
95450
95450
|
const visited = new Set;
|
|
95451
95451
|
const traverse = (start) => {
|
|
@@ -95469,12 +95469,13 @@ var init_dist8 = __esm(() => {
|
|
|
95469
95469
|
if (directNt && !visited.has(directNt)) {
|
|
95470
95470
|
traverse(directNt);
|
|
95471
95471
|
}
|
|
95472
|
+
const shouldHibernate = options?.hibernate ?? false;
|
|
95472
95473
|
const pipeline = [];
|
|
95473
95474
|
for (let i = chainLayers.length - 1;i >= 0; i--) {
|
|
95474
95475
|
const layer = chainLayers[i];
|
|
95475
95476
|
const type = layer.constructor?.name || "MiddlewareAccessor";
|
|
95476
95477
|
let state = undefined;
|
|
95477
|
-
if (typeof layer.hibernate === "function") {
|
|
95478
|
+
if (shouldHibernate && typeof layer.hibernate === "function") {
|
|
95478
95479
|
state = layer.hibernate();
|
|
95479
95480
|
} else if (typeof layer.saveState === "function") {
|
|
95480
95481
|
state = layer.saveState();
|
|
@@ -95500,7 +95501,7 @@ var init_dist8 = __esm(() => {
|
|
|
95500
95501
|
throw new Error("No target filePath specified for saveToFileSync() and no _sessionFilePath found");
|
|
95501
95502
|
}
|
|
95502
95503
|
const absPath = resolve3(targetPath);
|
|
95503
|
-
const session = this.toJSON();
|
|
95504
|
+
const session = this.toJSON({ hibernate: true });
|
|
95504
95505
|
withFileLockSync(absPath, () => {
|
|
95505
95506
|
const dir = dirname6(absPath);
|
|
95506
95507
|
if (!existsSync22(dir)) {
|
|
@@ -95519,7 +95520,7 @@ var init_dist8 = __esm(() => {
|
|
|
95519
95520
|
throw new Error("No target filePath specified for saveToFile() and no _sessionFilePath found");
|
|
95520
95521
|
}
|
|
95521
95522
|
const absPath = resolve3(targetPath);
|
|
95522
|
-
const session = this.toJSON();
|
|
95523
|
+
const session = this.toJSON({ hibernate: true });
|
|
95523
95524
|
await withFileLock(absPath, async () => {
|
|
95524
95525
|
const dir = dirname6(absPath);
|
|
95525
95526
|
if (!existsSync22(dir)) {
|
|
@@ -98159,8 +98160,6 @@ var init_dist10 = __esm(() => {
|
|
|
98159
98160
|
this.onceSuspendThread();
|
|
98160
98161
|
this.fetchContext();
|
|
98161
98162
|
this.savedContext = this.ctx.clone();
|
|
98162
|
-
const originalRip = this.savedContext.Rip;
|
|
98163
|
-
const originalJumpReg = this.savedContext[stubs.jumpRegKey];
|
|
98164
98163
|
if (this.options.isParked) {
|
|
98165
98164
|
nthreadLog.debug(`Thread ${this.tid} is already parked at 0x${this.savedContext.Rip.toString(16)}. Skipping jumpStub redirection.`);
|
|
98166
98165
|
if (!this.isCallRspSet()) {
|
|
@@ -98180,9 +98179,6 @@ var init_dist10 = __esm(() => {
|
|
|
98180
98179
|
nthreadLog.debug(`Parking thread ${this.tid} at spinStub 0x${stubs.spinStub.address.toString(16)}...`);
|
|
98181
98180
|
await this.root.call(stubs.jumpStub);
|
|
98182
98181
|
this.fetchContext();
|
|
98183
|
-
this.savedContext = this.ctx.clone();
|
|
98184
|
-
this.savedContext[stubs.jumpRegKey] = originalJumpReg;
|
|
98185
|
-
this.savedContext.Rip = originalRip;
|
|
98186
98182
|
if (!this.isCallRspSet()) {
|
|
98187
98183
|
const baseRsp = BigInt(this.getContext().Rsp);
|
|
98188
98184
|
const stackBegin = this.calcStackBegin();
|
|
@@ -98247,8 +98243,6 @@ var init_dist10 = __esm(() => {
|
|
|
98247
98243
|
this.onceSuspendThread();
|
|
98248
98244
|
this.fetchContext();
|
|
98249
98245
|
this.savedContext = this.ctx.clone();
|
|
98250
|
-
const originalRip = this.savedContext.Rip;
|
|
98251
|
-
const originalJumpReg = this.savedContext[stubs.jumpRegKey];
|
|
98252
98246
|
if (this.options.isParked) {
|
|
98253
98247
|
if (!this.isCallRspSet()) {
|
|
98254
98248
|
const stackBegin = this.calcStackBegin();
|
|
@@ -98267,9 +98261,6 @@ var init_dist10 = __esm(() => {
|
|
|
98267
98261
|
nthreadLog.debug(`Parking thread ${this.tid} at spinStub 0x${stubs.spinStub.address.toString(16)}...`);
|
|
98268
98262
|
this.root.callSync(stubs.jumpStub);
|
|
98269
98263
|
this.fetchContext();
|
|
98270
|
-
this.savedContext = this.ctx.clone();
|
|
98271
|
-
this.savedContext[stubs.jumpRegKey] = originalJumpReg;
|
|
98272
|
-
this.savedContext.Rip = originalRip;
|
|
98273
98264
|
if (!this.isCallRspSet()) {
|
|
98274
98265
|
const baseRsp = BigInt(this.getContext().Rsp);
|
|
98275
98266
|
const stackBegin = this.calcStackBegin();
|
|
@@ -98303,11 +98294,11 @@ var init_dist10 = __esm(() => {
|
|
|
98303
98294
|
this.nativeThread = undefined;
|
|
98304
98295
|
}
|
|
98305
98296
|
}
|
|
98306
|
-
|
|
98297
|
+
saveState() {
|
|
98307
98298
|
if (!this.nativeThread) {
|
|
98308
98299
|
throw new Error("NThread is not initialized or already closed");
|
|
98309
98300
|
}
|
|
98310
|
-
|
|
98301
|
+
return {
|
|
98311
98302
|
threadId: this.threadId,
|
|
98312
98303
|
callRsp: `0x${this.callRsp.toString(16)}`,
|
|
98313
98304
|
savedContext: this.savedContext.toBase64(),
|
|
@@ -98321,6 +98312,9 @@ var init_dist10 = __esm(() => {
|
|
|
98321
98312
|
addRsp28RetStub: `0x${this.stubs.addRsp28RetStub.address.toString(16)}`
|
|
98322
98313
|
}
|
|
98323
98314
|
};
|
|
98315
|
+
}
|
|
98316
|
+
hibernate() {
|
|
98317
|
+
const state = this.saveState();
|
|
98324
98318
|
this.nativeThread.close();
|
|
98325
98319
|
this.nativeThread = undefined;
|
|
98326
98320
|
this.markUninitialized();
|
|
@@ -111731,6 +111725,12 @@ var init_dist17 = __esm(() => {
|
|
|
111731
111725
|
}
|
|
111732
111726
|
}
|
|
111733
111727
|
onInitSync() {}
|
|
111728
|
+
onDeinitSync() {
|
|
111729
|
+
const t = this.getTarget();
|
|
111730
|
+
if (t !== this && t !== this.root && isInittableAccessor(t)) {
|
|
111731
|
+
t.deinitSync();
|
|
111732
|
+
}
|
|
111733
|
+
}
|
|
111734
111734
|
};
|
|
111735
111735
|
RacingHostAccessor = class RacingHostAccessor extends RedirectorHostAccessor {
|
|
111736
111736
|
racers = [];
|
|
@@ -111780,6 +111780,12 @@ var init_dist17 = __esm(() => {
|
|
|
111780
111780
|
this.initNextSync();
|
|
111781
111781
|
this.target = this.root;
|
|
111782
111782
|
}
|
|
111783
|
+
async onDeinit() {
|
|
111784
|
+
this.target = this;
|
|
111785
|
+
}
|
|
111786
|
+
onDeinitSync() {
|
|
111787
|
+
this.target = this;
|
|
111788
|
+
}
|
|
111783
111789
|
};
|
|
111784
111790
|
CallRedirectorAccessor = class CallRedirectorAccessor extends MiddlewareAccessor {
|
|
111785
111791
|
async alloc(size, address = null, protection = MemoryProtection.READWRITE, allocationType = MemoryState.COMMIT | MemoryState.RESERVE) {
|
|
@@ -113102,30 +113108,26 @@ var init_dist17 = __esm(() => {
|
|
|
113102
113108
|
onInitSync() {
|
|
113103
113109
|
this.bootstrapRoot.initSync();
|
|
113104
113110
|
}
|
|
113105
|
-
async
|
|
113106
|
-
try {
|
|
113107
|
-
await this.bootstrapRoot.deinit();
|
|
113108
|
-
} catch {}
|
|
113111
|
+
async deinit() {
|
|
113109
113112
|
try {
|
|
113110
|
-
|
|
113111
|
-
|
|
113112
|
-
|
|
113113
|
-
|
|
113114
|
-
|
|
113113
|
+
await super.deinit();
|
|
113114
|
+
} finally {
|
|
113115
|
+
try {
|
|
113116
|
+
await this.bootstrapRoot.deinit();
|
|
113117
|
+
} catch {}
|
|
113118
|
+
}
|
|
113115
113119
|
}
|
|
113116
|
-
|
|
113117
|
-
try {
|
|
113118
|
-
this.bootstrapRoot.deinitSync();
|
|
113119
|
-
} catch {}
|
|
113120
|
+
deinitSync() {
|
|
113120
113121
|
try {
|
|
113121
|
-
|
|
113122
|
-
|
|
113123
|
-
|
|
113124
|
-
|
|
113125
|
-
|
|
113122
|
+
super.deinitSync();
|
|
113123
|
+
} finally {
|
|
113124
|
+
try {
|
|
113125
|
+
this.bootstrapRoot.deinitSync();
|
|
113126
|
+
} catch {}
|
|
113127
|
+
}
|
|
113126
113128
|
}
|
|
113127
|
-
toJSON() {
|
|
113128
|
-
const session = super.toJSON();
|
|
113129
|
+
toJSON(options) {
|
|
113130
|
+
const session = super.toJSON(options);
|
|
113129
113131
|
session.accessorType = "IndirectNThreadHostAccessor";
|
|
113130
113132
|
try {
|
|
113131
113133
|
const nt = this.nthread;
|
|
@@ -113363,19 +113365,6 @@ async function closeAccessor(options) {
|
|
|
113363
113365
|
} catch (err) {
|
|
113364
113366
|
console.error("[closeAccessor] s.accessor.deinit error:", err);
|
|
113365
113367
|
}
|
|
113366
|
-
try {
|
|
113367
|
-
const nt = s.accessor?.nthread;
|
|
113368
|
-
if (nt && typeof nt.deinit === "function") {
|
|
113369
|
-
await nt.deinit();
|
|
113370
|
-
}
|
|
113371
|
-
} catch (err) {
|
|
113372
|
-
console.error("[closeAccessor] nt.deinit error:", err);
|
|
113373
|
-
}
|
|
113374
|
-
try {
|
|
113375
|
-
s.accessor.close();
|
|
113376
|
-
} catch (err) {
|
|
113377
|
-
console.error("[closeAccessor] s.accessor.close error:", err);
|
|
113378
|
-
}
|
|
113379
113368
|
try {
|
|
113380
113369
|
if (existsSync14(s.sessionFile)) {
|
|
113381
113370
|
unlinkSync5(s.sessionFile);
|
|
@@ -121623,8 +121612,8 @@ var package_default = {
|
|
|
121623
121612
|
publishConfig: {
|
|
121624
121613
|
access: "public"
|
|
121625
121614
|
},
|
|
121626
|
-
mcpName: "io.github.
|
|
121627
|
-
version: "0.6.
|
|
121615
|
+
mcpName: "io.github.aksoyserkan/exoproc",
|
|
121616
|
+
version: "0.6.9",
|
|
121628
121617
|
description: "Unified CLI and Model Context Protocol (MCP) server for native Windows x64 reverse engineering, thread hijacking, function redirection, memory inspection, and runtime instrumentation.",
|
|
121629
121618
|
main: "./dist/index.js",
|
|
121630
121619
|
bin: {
|
package/dist/index.js
CHANGED
|
@@ -94968,7 +94968,7 @@ var init_dist8 = __esm(() => {
|
|
|
94968
94968
|
getSessionMetadata() {
|
|
94969
94969
|
return { ...this._sessionMetadata };
|
|
94970
94970
|
}
|
|
94971
|
-
toJSON() {
|
|
94971
|
+
toJSON(options) {
|
|
94972
94972
|
const chainLayers = [];
|
|
94973
94973
|
const visited = new Set;
|
|
94974
94974
|
const traverse = (start) => {
|
|
@@ -94992,12 +94992,13 @@ var init_dist8 = __esm(() => {
|
|
|
94992
94992
|
if (directNt && !visited.has(directNt)) {
|
|
94993
94993
|
traverse(directNt);
|
|
94994
94994
|
}
|
|
94995
|
+
const shouldHibernate = options?.hibernate ?? false;
|
|
94995
94996
|
const pipeline = [];
|
|
94996
94997
|
for (let i = chainLayers.length - 1;i >= 0; i--) {
|
|
94997
94998
|
const layer = chainLayers[i];
|
|
94998
94999
|
const type = layer.constructor?.name || "MiddlewareAccessor";
|
|
94999
95000
|
let state = undefined;
|
|
95000
|
-
if (typeof layer.hibernate === "function") {
|
|
95001
|
+
if (shouldHibernate && typeof layer.hibernate === "function") {
|
|
95001
95002
|
state = layer.hibernate();
|
|
95002
95003
|
} else if (typeof layer.saveState === "function") {
|
|
95003
95004
|
state = layer.saveState();
|
|
@@ -95023,7 +95024,7 @@ var init_dist8 = __esm(() => {
|
|
|
95023
95024
|
throw new Error("No target filePath specified for saveToFileSync() and no _sessionFilePath found");
|
|
95024
95025
|
}
|
|
95025
95026
|
const absPath = resolve3(targetPath);
|
|
95026
|
-
const session = this.toJSON();
|
|
95027
|
+
const session = this.toJSON({ hibernate: true });
|
|
95027
95028
|
withFileLockSync(absPath, () => {
|
|
95028
95029
|
const dir = dirname6(absPath);
|
|
95029
95030
|
if (!existsSync22(dir)) {
|
|
@@ -95042,7 +95043,7 @@ var init_dist8 = __esm(() => {
|
|
|
95042
95043
|
throw new Error("No target filePath specified for saveToFile() and no _sessionFilePath found");
|
|
95043
95044
|
}
|
|
95044
95045
|
const absPath = resolve3(targetPath);
|
|
95045
|
-
const session = this.toJSON();
|
|
95046
|
+
const session = this.toJSON({ hibernate: true });
|
|
95046
95047
|
await withFileLock(absPath, async () => {
|
|
95047
95048
|
const dir = dirname6(absPath);
|
|
95048
95049
|
if (!existsSync22(dir)) {
|
|
@@ -97684,8 +97685,6 @@ var init_dist10 = __esm(() => {
|
|
|
97684
97685
|
this.onceSuspendThread();
|
|
97685
97686
|
this.fetchContext();
|
|
97686
97687
|
this.savedContext = this.ctx.clone();
|
|
97687
|
-
const originalRip = this.savedContext.Rip;
|
|
97688
|
-
const originalJumpReg = this.savedContext[stubs.jumpRegKey];
|
|
97689
97688
|
if (this.options.isParked) {
|
|
97690
97689
|
nthreadLog.debug(`Thread ${this.tid} is already parked at 0x${this.savedContext.Rip.toString(16)}. Skipping jumpStub redirection.`);
|
|
97691
97690
|
if (!this.isCallRspSet()) {
|
|
@@ -97705,9 +97704,6 @@ var init_dist10 = __esm(() => {
|
|
|
97705
97704
|
nthreadLog.debug(`Parking thread ${this.tid} at spinStub 0x${stubs.spinStub.address.toString(16)}...`);
|
|
97706
97705
|
await this.root.call(stubs.jumpStub);
|
|
97707
97706
|
this.fetchContext();
|
|
97708
|
-
this.savedContext = this.ctx.clone();
|
|
97709
|
-
this.savedContext[stubs.jumpRegKey] = originalJumpReg;
|
|
97710
|
-
this.savedContext.Rip = originalRip;
|
|
97711
97707
|
if (!this.isCallRspSet()) {
|
|
97712
97708
|
const baseRsp = BigInt(this.getContext().Rsp);
|
|
97713
97709
|
const stackBegin = this.calcStackBegin();
|
|
@@ -97772,8 +97768,6 @@ var init_dist10 = __esm(() => {
|
|
|
97772
97768
|
this.onceSuspendThread();
|
|
97773
97769
|
this.fetchContext();
|
|
97774
97770
|
this.savedContext = this.ctx.clone();
|
|
97775
|
-
const originalRip = this.savedContext.Rip;
|
|
97776
|
-
const originalJumpReg = this.savedContext[stubs.jumpRegKey];
|
|
97777
97771
|
if (this.options.isParked) {
|
|
97778
97772
|
if (!this.isCallRspSet()) {
|
|
97779
97773
|
const stackBegin = this.calcStackBegin();
|
|
@@ -97792,9 +97786,6 @@ var init_dist10 = __esm(() => {
|
|
|
97792
97786
|
nthreadLog.debug(`Parking thread ${this.tid} at spinStub 0x${stubs.spinStub.address.toString(16)}...`);
|
|
97793
97787
|
this.root.callSync(stubs.jumpStub);
|
|
97794
97788
|
this.fetchContext();
|
|
97795
|
-
this.savedContext = this.ctx.clone();
|
|
97796
|
-
this.savedContext[stubs.jumpRegKey] = originalJumpReg;
|
|
97797
|
-
this.savedContext.Rip = originalRip;
|
|
97798
97789
|
if (!this.isCallRspSet()) {
|
|
97799
97790
|
const baseRsp = BigInt(this.getContext().Rsp);
|
|
97800
97791
|
const stackBegin = this.calcStackBegin();
|
|
@@ -97828,11 +97819,11 @@ var init_dist10 = __esm(() => {
|
|
|
97828
97819
|
this.nativeThread = undefined;
|
|
97829
97820
|
}
|
|
97830
97821
|
}
|
|
97831
|
-
|
|
97822
|
+
saveState() {
|
|
97832
97823
|
if (!this.nativeThread) {
|
|
97833
97824
|
throw new Error("NThread is not initialized or already closed");
|
|
97834
97825
|
}
|
|
97835
|
-
|
|
97826
|
+
return {
|
|
97836
97827
|
threadId: this.threadId,
|
|
97837
97828
|
callRsp: `0x${this.callRsp.toString(16)}`,
|
|
97838
97829
|
savedContext: this.savedContext.toBase64(),
|
|
@@ -97846,6 +97837,9 @@ var init_dist10 = __esm(() => {
|
|
|
97846
97837
|
addRsp28RetStub: `0x${this.stubs.addRsp28RetStub.address.toString(16)}`
|
|
97847
97838
|
}
|
|
97848
97839
|
};
|
|
97840
|
+
}
|
|
97841
|
+
hibernate() {
|
|
97842
|
+
const state = this.saveState();
|
|
97849
97843
|
this.nativeThread.close();
|
|
97850
97844
|
this.nativeThread = undefined;
|
|
97851
97845
|
this.markUninitialized();
|
|
@@ -111853,6 +111847,12 @@ var init_dist17 = __esm(() => {
|
|
|
111853
111847
|
}
|
|
111854
111848
|
}
|
|
111855
111849
|
onInitSync() {}
|
|
111850
|
+
onDeinitSync() {
|
|
111851
|
+
const t = this.getTarget();
|
|
111852
|
+
if (t !== this && t !== this.root && isInittableAccessor(t)) {
|
|
111853
|
+
t.deinitSync();
|
|
111854
|
+
}
|
|
111855
|
+
}
|
|
111856
111856
|
};
|
|
111857
111857
|
RacingHostAccessor = class RacingHostAccessor extends RedirectorHostAccessor {
|
|
111858
111858
|
racers = [];
|
|
@@ -111902,6 +111902,12 @@ var init_dist17 = __esm(() => {
|
|
|
111902
111902
|
this.initNextSync();
|
|
111903
111903
|
this.target = this.root;
|
|
111904
111904
|
}
|
|
111905
|
+
async onDeinit() {
|
|
111906
|
+
this.target = this;
|
|
111907
|
+
}
|
|
111908
|
+
onDeinitSync() {
|
|
111909
|
+
this.target = this;
|
|
111910
|
+
}
|
|
111905
111911
|
};
|
|
111906
111912
|
CallRedirectorAccessor = class CallRedirectorAccessor extends MiddlewareAccessor {
|
|
111907
111913
|
async alloc(size, address = null, protection = MemoryProtection.READWRITE, allocationType = MemoryState.COMMIT | MemoryState.RESERVE) {
|
|
@@ -113224,30 +113230,26 @@ var init_dist17 = __esm(() => {
|
|
|
113224
113230
|
onInitSync() {
|
|
113225
113231
|
this.bootstrapRoot.initSync();
|
|
113226
113232
|
}
|
|
113227
|
-
async
|
|
113228
|
-
try {
|
|
113229
|
-
await this.bootstrapRoot.deinit();
|
|
113230
|
-
} catch {}
|
|
113233
|
+
async deinit() {
|
|
113231
113234
|
try {
|
|
113232
|
-
|
|
113233
|
-
|
|
113234
|
-
|
|
113235
|
-
|
|
113236
|
-
|
|
113235
|
+
await super.deinit();
|
|
113236
|
+
} finally {
|
|
113237
|
+
try {
|
|
113238
|
+
await this.bootstrapRoot.deinit();
|
|
113239
|
+
} catch {}
|
|
113240
|
+
}
|
|
113237
113241
|
}
|
|
113238
|
-
|
|
113239
|
-
try {
|
|
113240
|
-
this.bootstrapRoot.deinitSync();
|
|
113241
|
-
} catch {}
|
|
113242
|
+
deinitSync() {
|
|
113242
113243
|
try {
|
|
113243
|
-
|
|
113244
|
-
|
|
113245
|
-
|
|
113246
|
-
|
|
113247
|
-
|
|
113244
|
+
super.deinitSync();
|
|
113245
|
+
} finally {
|
|
113246
|
+
try {
|
|
113247
|
+
this.bootstrapRoot.deinitSync();
|
|
113248
|
+
} catch {}
|
|
113249
|
+
}
|
|
113248
113250
|
}
|
|
113249
|
-
toJSON() {
|
|
113250
|
-
const session = super.toJSON();
|
|
113251
|
+
toJSON(options) {
|
|
113252
|
+
const session = super.toJSON(options);
|
|
113251
113253
|
session.accessorType = "IndirectNThreadHostAccessor";
|
|
113252
113254
|
try {
|
|
113253
113255
|
const nt = this.nthread;
|
|
@@ -113496,19 +113498,6 @@ async function closeAccessor(options) {
|
|
|
113496
113498
|
} catch (err) {
|
|
113497
113499
|
console.error("[closeAccessor] s.accessor.deinit error:", err);
|
|
113498
113500
|
}
|
|
113499
|
-
try {
|
|
113500
|
-
const nt = s.accessor?.nthread;
|
|
113501
|
-
if (nt && typeof nt.deinit === "function") {
|
|
113502
|
-
await nt.deinit();
|
|
113503
|
-
}
|
|
113504
|
-
} catch (err) {
|
|
113505
|
-
console.error("[closeAccessor] nt.deinit error:", err);
|
|
113506
|
-
}
|
|
113507
|
-
try {
|
|
113508
|
-
s.accessor.close();
|
|
113509
|
-
} catch (err) {
|
|
113510
|
-
console.error("[closeAccessor] s.accessor.close error:", err);
|
|
113511
|
-
}
|
|
113512
113501
|
try {
|
|
113513
113502
|
if (existsSync14(s.sessionFile)) {
|
|
113514
113503
|
unlinkSync5(s.sessionFile);
|
|
@@ -136944,7 +136933,7 @@ class HostAccessor2 extends InittableMiddlewareAccessor2 {
|
|
|
136944
136933
|
getSessionMetadata() {
|
|
136945
136934
|
return { ...this._sessionMetadata };
|
|
136946
136935
|
}
|
|
136947
|
-
toJSON() {
|
|
136936
|
+
toJSON(options) {
|
|
136948
136937
|
const chainLayers = [];
|
|
136949
136938
|
const visited = new Set;
|
|
136950
136939
|
const traverse = (start) => {
|
|
@@ -136968,12 +136957,13 @@ class HostAccessor2 extends InittableMiddlewareAccessor2 {
|
|
|
136968
136957
|
if (directNt && !visited.has(directNt)) {
|
|
136969
136958
|
traverse(directNt);
|
|
136970
136959
|
}
|
|
136960
|
+
const shouldHibernate = options?.hibernate ?? false;
|
|
136971
136961
|
const pipeline = [];
|
|
136972
136962
|
for (let i = chainLayers.length - 1;i >= 0; i--) {
|
|
136973
136963
|
const layer = chainLayers[i];
|
|
136974
136964
|
const type = layer.constructor?.name || "MiddlewareAccessor";
|
|
136975
136965
|
let state = undefined;
|
|
136976
|
-
if (typeof layer.hibernate === "function") {
|
|
136966
|
+
if (shouldHibernate && typeof layer.hibernate === "function") {
|
|
136977
136967
|
state = layer.hibernate();
|
|
136978
136968
|
} else if (typeof layer.saveState === "function") {
|
|
136979
136969
|
state = layer.saveState();
|
|
@@ -136999,7 +136989,7 @@ class HostAccessor2 extends InittableMiddlewareAccessor2 {
|
|
|
136999
136989
|
throw new Error("No target filePath specified for saveToFileSync() and no _sessionFilePath found");
|
|
137000
136990
|
}
|
|
137001
136991
|
const absPath = resolve10(targetPath);
|
|
137002
|
-
const session = this.toJSON();
|
|
136992
|
+
const session = this.toJSON({ hibernate: true });
|
|
137003
136993
|
withFileLockSync2(absPath, () => {
|
|
137004
136994
|
const dir = dirname10(absPath);
|
|
137005
136995
|
if (!existsSync19(dir)) {
|
|
@@ -137018,7 +137008,7 @@ class HostAccessor2 extends InittableMiddlewareAccessor2 {
|
|
|
137018
137008
|
throw new Error("No target filePath specified for saveToFile() and no _sessionFilePath found");
|
|
137019
137009
|
}
|
|
137020
137010
|
const absPath = resolve10(targetPath);
|
|
137021
|
-
const session = this.toJSON();
|
|
137011
|
+
const session = this.toJSON({ hibernate: true });
|
|
137022
137012
|
await withFileLock2(absPath, async () => {
|
|
137023
137013
|
const dir = dirname10(absPath);
|
|
137024
137014
|
if (!existsSync19(dir)) {
|
|
@@ -139394,8 +139384,6 @@ class NThread2 extends InittableMiddlewareAccessor {
|
|
|
139394
139384
|
this.onceSuspendThread();
|
|
139395
139385
|
this.fetchContext();
|
|
139396
139386
|
this.savedContext = this.ctx.clone();
|
|
139397
|
-
const originalRip = this.savedContext.Rip;
|
|
139398
|
-
const originalJumpReg = this.savedContext[stubs.jumpRegKey];
|
|
139399
139387
|
if (this.options.isParked) {
|
|
139400
139388
|
nthreadLog2.debug(`Thread ${this.tid} is already parked at 0x${this.savedContext.Rip.toString(16)}. Skipping jumpStub redirection.`);
|
|
139401
139389
|
if (!this.isCallRspSet()) {
|
|
@@ -139415,9 +139403,6 @@ class NThread2 extends InittableMiddlewareAccessor {
|
|
|
139415
139403
|
nthreadLog2.debug(`Parking thread ${this.tid} at spinStub 0x${stubs.spinStub.address.toString(16)}...`);
|
|
139416
139404
|
await this.root.call(stubs.jumpStub);
|
|
139417
139405
|
this.fetchContext();
|
|
139418
|
-
this.savedContext = this.ctx.clone();
|
|
139419
|
-
this.savedContext[stubs.jumpRegKey] = originalJumpReg;
|
|
139420
|
-
this.savedContext.Rip = originalRip;
|
|
139421
139406
|
if (!this.isCallRspSet()) {
|
|
139422
139407
|
const baseRsp = BigInt(this.getContext().Rsp);
|
|
139423
139408
|
const stackBegin = this.calcStackBegin();
|
|
@@ -139482,8 +139467,6 @@ class NThread2 extends InittableMiddlewareAccessor {
|
|
|
139482
139467
|
this.onceSuspendThread();
|
|
139483
139468
|
this.fetchContext();
|
|
139484
139469
|
this.savedContext = this.ctx.clone();
|
|
139485
|
-
const originalRip = this.savedContext.Rip;
|
|
139486
|
-
const originalJumpReg = this.savedContext[stubs.jumpRegKey];
|
|
139487
139470
|
if (this.options.isParked) {
|
|
139488
139471
|
if (!this.isCallRspSet()) {
|
|
139489
139472
|
const stackBegin = this.calcStackBegin();
|
|
@@ -139502,9 +139485,6 @@ class NThread2 extends InittableMiddlewareAccessor {
|
|
|
139502
139485
|
nthreadLog2.debug(`Parking thread ${this.tid} at spinStub 0x${stubs.spinStub.address.toString(16)}...`);
|
|
139503
139486
|
this.root.callSync(stubs.jumpStub);
|
|
139504
139487
|
this.fetchContext();
|
|
139505
|
-
this.savedContext = this.ctx.clone();
|
|
139506
|
-
this.savedContext[stubs.jumpRegKey] = originalJumpReg;
|
|
139507
|
-
this.savedContext.Rip = originalRip;
|
|
139508
139488
|
if (!this.isCallRspSet()) {
|
|
139509
139489
|
const baseRsp = BigInt(this.getContext().Rsp);
|
|
139510
139490
|
const stackBegin = this.calcStackBegin();
|
|
@@ -139538,11 +139518,11 @@ class NThread2 extends InittableMiddlewareAccessor {
|
|
|
139538
139518
|
this.nativeThread = undefined;
|
|
139539
139519
|
}
|
|
139540
139520
|
}
|
|
139541
|
-
|
|
139521
|
+
saveState() {
|
|
139542
139522
|
if (!this.nativeThread) {
|
|
139543
139523
|
throw new Error("NThread is not initialized or already closed");
|
|
139544
139524
|
}
|
|
139545
|
-
|
|
139525
|
+
return {
|
|
139546
139526
|
threadId: this.threadId,
|
|
139547
139527
|
callRsp: `0x${this.callRsp.toString(16)}`,
|
|
139548
139528
|
savedContext: this.savedContext.toBase64(),
|
|
@@ -139556,6 +139536,9 @@ class NThread2 extends InittableMiddlewareAccessor {
|
|
|
139556
139536
|
addRsp28RetStub: `0x${this.stubs.addRsp28RetStub.address.toString(16)}`
|
|
139557
139537
|
}
|
|
139558
139538
|
};
|
|
139539
|
+
}
|
|
139540
|
+
hibernate() {
|
|
139541
|
+
const state = this.saveState();
|
|
139559
139542
|
this.nativeThread.close();
|
|
139560
139543
|
this.nativeThread = undefined;
|
|
139561
139544
|
this.markUninitialized();
|
|
@@ -152025,6 +152008,12 @@ class RedirectorHostAccessor2 extends HostAccessor {
|
|
|
152025
152008
|
}
|
|
152026
152009
|
}
|
|
152027
152010
|
onInitSync() {}
|
|
152011
|
+
onDeinitSync() {
|
|
152012
|
+
const t = this.getTarget();
|
|
152013
|
+
if (t !== this && t !== this.root && isInittableAccessor(t)) {
|
|
152014
|
+
t.deinitSync();
|
|
152015
|
+
}
|
|
152016
|
+
}
|
|
152028
152017
|
}
|
|
152029
152018
|
|
|
152030
152019
|
class RacingHostAccessor2 extends RedirectorHostAccessor2 {
|
|
@@ -152076,6 +152065,12 @@ class BootstrapHostAccessor2 extends RedirectorHostAccessor2 {
|
|
|
152076
152065
|
this.initNextSync();
|
|
152077
152066
|
this.target = this.root;
|
|
152078
152067
|
}
|
|
152068
|
+
async onDeinit() {
|
|
152069
|
+
this.target = this;
|
|
152070
|
+
}
|
|
152071
|
+
onDeinitSync() {
|
|
152072
|
+
this.target = this;
|
|
152073
|
+
}
|
|
152079
152074
|
}
|
|
152080
152075
|
|
|
152081
152076
|
class CallRedirectorAccessor2 extends MiddlewareAccessor {
|
|
@@ -153618,30 +153613,26 @@ class IndirectNThreadHostAccessor2 extends HostAccessor {
|
|
|
153618
153613
|
onInitSync() {
|
|
153619
153614
|
this.bootstrapRoot.initSync();
|
|
153620
153615
|
}
|
|
153621
|
-
async
|
|
153622
|
-
try {
|
|
153623
|
-
await this.bootstrapRoot.deinit();
|
|
153624
|
-
} catch {}
|
|
153616
|
+
async deinit() {
|
|
153625
153617
|
try {
|
|
153626
|
-
|
|
153627
|
-
|
|
153628
|
-
|
|
153629
|
-
|
|
153630
|
-
|
|
153618
|
+
await super.deinit();
|
|
153619
|
+
} finally {
|
|
153620
|
+
try {
|
|
153621
|
+
await this.bootstrapRoot.deinit();
|
|
153622
|
+
} catch {}
|
|
153623
|
+
}
|
|
153631
153624
|
}
|
|
153632
|
-
|
|
153633
|
-
try {
|
|
153634
|
-
this.bootstrapRoot.deinitSync();
|
|
153635
|
-
} catch {}
|
|
153625
|
+
deinitSync() {
|
|
153636
153626
|
try {
|
|
153637
|
-
|
|
153638
|
-
|
|
153639
|
-
|
|
153640
|
-
|
|
153641
|
-
|
|
153627
|
+
super.deinitSync();
|
|
153628
|
+
} finally {
|
|
153629
|
+
try {
|
|
153630
|
+
this.bootstrapRoot.deinitSync();
|
|
153631
|
+
} catch {}
|
|
153632
|
+
}
|
|
153642
153633
|
}
|
|
153643
|
-
toJSON() {
|
|
153644
|
-
const session = super.toJSON();
|
|
153634
|
+
toJSON(options) {
|
|
153635
|
+
const session = super.toJSON(options);
|
|
153645
153636
|
session.accessorType = "IndirectNThreadHostAccessor";
|
|
153646
153637
|
try {
|
|
153647
153638
|
const nt = this.nthread;
|
package/package.json
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"mcpName": "io.github.
|
|
7
|
-
"version": "0.6.
|
|
6
|
+
"mcpName": "io.github.aksoyserkan/exoproc",
|
|
7
|
+
"version": "0.6.9",
|
|
8
8
|
"description": "Unified CLI and Model Context Protocol (MCP) server for native Windows x64 reverse engineering, thread hijacking, function redirection, memory inspection, and runtime instrumentation.",
|
|
9
9
|
"main": "./dist/index.js",
|
|
10
10
|
"bin": {
|