seabox 0.1.0-beta.1

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/lib/unsign.js ADDED
@@ -0,0 +1,184 @@
1
+ /**
2
+ * unsign.js
3
+ * Remove code signatures from executables before injection.
4
+ * This prevents signature corruption during postject injection.
5
+ */
6
+
7
+ const { execFile } = require('child_process');
8
+ const { promisify } = require('util');
9
+
10
+ const execFileAsync = promisify(execFile);
11
+
12
+ /**
13
+ * Check if a signing tool is available on the system.
14
+ * @param {string} platform - Target platform (win32, linux, darwin)
15
+ * @returns {Promise<{available: boolean, tool: string|null}>}
16
+ */
17
+ async function checkSignToolAvailability(platform) {
18
+ const tools = {
19
+ win32: 'signtool.exe',
20
+ darwin: 'codesign',
21
+ linux: 'osslsigncode'
22
+ };
23
+
24
+ const tool = tools[platform];
25
+ if (!tool) {
26
+ return { available: false, tool: null };
27
+ }
28
+
29
+ try {
30
+ // Try to execute the tool with a version/help flag to check availability
31
+ if (platform === 'win32') {
32
+ await execFileAsync('where', ['signtool.exe']);
33
+ } else if (platform === 'darwin') {
34
+ await execFileAsync('which', ['codesign']);
35
+ } else if (platform === 'linux') {
36
+ await execFileAsync('which', ['osslsigncode']);
37
+ }
38
+ return { available: true, tool };
39
+ } catch (error) {
40
+ return { available: false, tool };
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Remove signature from a Windows executable using signtool.
46
+ * @param {string} exePath - Path to the executable
47
+ * @returns {Promise<{success: boolean, message: string}>}
48
+ */
49
+ async function removeWindowsSignature(exePath) {
50
+ try {
51
+ const { stdout, stderr } = await execFileAsync('signtool.exe', ['remove', '/s', exePath]);
52
+
53
+ const output = (stdout + stderr).toLowerCase();
54
+
55
+ // Check if successfully removed
56
+ if (output.includes('successfully')) {
57
+ return { success: true, message: 'Signature removed successfully' };
58
+ }
59
+
60
+ // Check if there was no signature
61
+ if (output.includes('no signature') || output.includes('not signed')) {
62
+ return { success: true, message: 'Binary was not signed (no signature to remove)' };
63
+ }
64
+
65
+ return { success: true, message: stdout || 'Signature removal completed' };
66
+ } catch (error) {
67
+ const errorMsg = error.message || error.stderr || '';
68
+
69
+ // Not an error if there was no signature to begin with
70
+ if (errorMsg.includes('No signature') || errorMsg.includes('not signed')) {
71
+ return { success: true, message: 'Binary was not signed (no signature to remove)' };
72
+ }
73
+
74
+ return { success: false, message: `Failed to remove signature: ${errorMsg}` };
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Remove signature from a macOS executable using codesign.
80
+ * @param {string} exePath - Path to the executable
81
+ * @returns {Promise<{success: boolean, message: string}>}
82
+ */
83
+ async function removeMacSignature(exePath) {
84
+ try {
85
+ // On macOS, use --remove-signature flag
86
+ const { stdout, stderr } = await execFileAsync('codesign', ['--remove-signature', exePath]);
87
+
88
+ return { success: true, message: 'Signature removed successfully' };
89
+ } catch (error) {
90
+ const errorMsg = error.message || error.stderr || '';
91
+
92
+ // Not an error if there was no signature
93
+ if (errorMsg.includes('not signed') || errorMsg.includes('no signature')) {
94
+ return { success: true, message: 'Binary was not signed (no signature to remove)' };
95
+ }
96
+
97
+ return { success: false, message: `Failed to remove signature: ${errorMsg}` };
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Remove signature from a Linux executable.
103
+ * Note: Linux binaries are rarely signed, but osslsigncode can handle Authenticode signatures.
104
+ * @param {string} exePath - Path to the executable
105
+ * @returns {Promise<{success: boolean, message: string}>}
106
+ */
107
+ async function removeLinuxSignature(exePath) {
108
+ try {
109
+ // osslsigncode can remove Authenticode signatures (used for cross-platform PE files)
110
+ const { stdout, stderr } = await execFileAsync('osslsigncode', ['remove-signature', exePath]);
111
+
112
+ return { success: true, message: 'Signature removed successfully' };
113
+ } catch (error) {
114
+ const errorMsg = error.message || error.stderr || '';
115
+
116
+ // Not an error if there was no signature
117
+ if (errorMsg.includes('not signed') || errorMsg.includes('no signature')) {
118
+ return { success: true, message: 'Binary was not signed (no signature to remove)' };
119
+ }
120
+
121
+ return { success: false, message: `Failed to remove signature: ${errorMsg}` };
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Remove code signature from an executable before injection.
127
+ * This is critical to prevent signature corruption during postject injection.
128
+ * @param {string} exePath - Path to the executable
129
+ * @param {string} platform - Target platform (win32, linux, darwin)
130
+ * @returns {Promise<void>}
131
+ */
132
+ async function removeSignature(exePath, platform) {
133
+ //console.log('Checking for code signature removal tools...');
134
+
135
+ const { available, tool } = await checkSignToolAvailability(platform);
136
+
137
+ if (!available) {
138
+ console.warn(`⚠️ Warning: Signature removal tool not found for ${platform}`);
139
+ console.warn(` Tool needed: ${tool || 'unknown'}`);
140
+ console.warn(` The binary may have an existing signature that will be corrupted during injection.`);
141
+
142
+ if (platform === 'win32') {
143
+ console.warn(` Install Windows SDK to get signtool.exe`);
144
+ console.warn(` Download from: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/`);
145
+ } else if (platform === 'darwin') {
146
+ console.warn(` Install Xcode Command Line Tools to get codesign`);
147
+ console.warn(` Run: xcode-select --install`);
148
+ } else if (platform === 'linux') {
149
+ console.warn(` Install osslsigncode: apt-get install osslsigncode (Debian/Ubuntu)`);
150
+ }
151
+
152
+ console.warn('');
153
+ return;
154
+ }
155
+
156
+ console.log(`Found ${tool}, attempting to remove signature...`);
157
+
158
+ let result;
159
+ if (platform === 'win32') {
160
+ result = await removeWindowsSignature(exePath);
161
+ } else if (platform === 'darwin') {
162
+ result = await removeMacSignature(exePath);
163
+ } else if (platform === 'linux') {
164
+ result = await removeLinuxSignature(exePath);
165
+ } else {
166
+ console.warn(`⚠️ Warning: Unsupported platform for signature removal: ${platform}`);
167
+ return;
168
+ }
169
+
170
+ if (result.success) {
171
+ console.log(`✓ ${result.message}`);
172
+ } else {
173
+ console.warn(`⚠️ Warning: ${result.message}`);
174
+ console.warn(` Continuing anyway, but the executable may have signature issues.`);
175
+ }
176
+ }
177
+
178
+ module.exports = {
179
+ removeSignature,
180
+ checkSignToolAvailability,
181
+ removeWindowsSignature,
182
+ removeMacSignature,
183
+ removeLinuxSignature
184
+ };
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "seabox",
3
+ "version": "0.1.0-beta.1",
4
+ "description": "Node.js Single Executable Application (SEA) builder tool with native and library extraction",
5
+ "main": "lib/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "seabox": "bin/seabox.js",
9
+ "seabox-rebuild": "bin/seabox-rebuild.js"
10
+ },
11
+ "scripts": {
12
+ "clean": "rimraf dist",
13
+ "prepublishOnly": "",
14
+ "test": "mocha"
15
+ },
16
+ "keywords": [
17
+ "sea",
18
+ "build",
19
+ "builder",
20
+ "single-executable",
21
+ "SEA",
22
+ "native",
23
+ "module",
24
+ "dll",
25
+ "packaging",
26
+ "node",
27
+ "postject"
28
+ ],
29
+ "author": "Meirion Hughes",
30
+ "license": "MIT",
31
+ "dependencies": {
32
+ "adm-zip": "^0.5.16",
33
+ "glob": "^10.0.0",
34
+ "postject": "^1.0.0-alpha.6",
35
+ "tar": "^6.2.1"
36
+ },
37
+ "devDependencies": {
38
+ "chai": "^6.2.1",
39
+ "javascript-obfuscator": "^4.1.1",
40
+ "mocha": "^11.7.5",
41
+ "node-api-headers": "^1.2.0",
42
+ "rimraf": "^6.0.1"
43
+ },
44
+ "engines": {
45
+ "node": ">=18.0.0"
46
+ }
47
+ }