devicely 2.1.4 → 2.1.5
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/bin/devicely.js +105 -1
- package/lib/androidDeviceDetection.js +276 -1
- package/lib/appMappings.js +337 -1
- package/lib/deviceDetection.js +394 -1
- package/lib/devices.js +54 -1
- package/lib/doctor.js +94 -1
- package/lib/executor.js +104 -1
- package/lib/logger.js +35 -1
- package/lib/scriptLoader.js +75 -1
- package/lib/server.js +3483 -1
- package/package.json +3 -12
- package/scripts/compile-shell-scripts.js +208 -0
- package/scripts/encrypt-shell-simple.js +75 -0
- package/scripts/obfuscate-shell.js +160 -0
- package/scripts/shell/android_device_control +0 -0
- package/scripts/shell/android_device_control.sh +848 -0
- package/scripts/shell/apps_presets.conf +271 -0
- package/scripts/shell/connect_android_usb +0 -0
- package/scripts/shell/connect_android_usb_multi_final +0 -0
- package/scripts/shell/connect_android_usb_multi_final.sh +289 -0
- package/scripts/shell/connect_android_wireless +0 -0
- package/scripts/shell/connect_android_wireless.sh +58 -0
- package/scripts/shell/connect_android_wireless_multi_final +0 -0
- package/scripts/shell/connect_android_wireless_multi_final.sh +476 -0
- package/scripts/shell/connect_ios_usb +0 -0
- package/scripts/shell/connect_ios_usb_multi_final +0 -0
- package/scripts/shell/connect_ios_usb_multi_final.sh +4225 -0
- package/scripts/shell/connect_ios_wireless_multi_final +0 -0
- package/scripts/shell/connect_ios_wireless_multi_final.sh +4167 -0
- package/scripts/shell/create_production_scripts +0 -0
- package/scripts/shell/create_production_scripts.sh +38 -0
- package/scripts/shell/devices.conf +24 -0
- package/scripts/shell/diagnose_wireless_ios +0 -0
- package/scripts/shell/find_element_coordinates +0 -0
- package/scripts/shell/find_wda +0 -0
- package/scripts/shell/install_uiautomator2 +0 -0
- package/scripts/shell/install_uiautomator2.sh +93 -0
- package/scripts/shell/ios_device_control +0 -0
- package/scripts/shell/ios_device_control.sh +220 -0
- package/scripts/shell/organize_project +0 -0
- package/scripts/shell/organize_project.sh +59 -0
- package/scripts/shell/pre-publish-check +0 -0
- package/scripts/shell/pre-publish-check.sh +238 -0
- package/scripts/shell/publish +0 -0
- package/scripts/shell/publish-to-npm +0 -0
- package/scripts/shell/publish-to-npm.sh +366 -0
- package/scripts/shell/publish.sh +100 -0
- package/scripts/shell/setup +0 -0
- package/scripts/shell/setup.sh +121 -0
- package/scripts/shell/setup_android +0 -0
- package/scripts/shell/start +0 -0
- package/scripts/shell/start.sh +59 -0
- package/scripts/shell/sync-to-npm-package-final +0 -0
- package/scripts/shell/sync-to-npm-package-final.sh +60 -0
- package/scripts/shell/test-local-package.sh +95 -0
- package/scripts/shell/test_android_locators +0 -0
- package/scripts/shell/test_connect +0 -0
- package/scripts/shell/test_device_detection +0 -0
- package/scripts/shell/test_fixes +0 -0
- package/scripts/shell/test_getlocators_fix +0 -0
- package/scripts/shell/test_recording_feature +0 -0
- package/scripts/shell/verify-shell-protection +0 -0
- package/scripts/shell/verify-shell-protection.sh +73 -0
- package/scripts/shell/verify_distribution +0 -0
- package/lib/package-lock.json +0 -1678
- package/lib/package.json +0 -30
- package/lib/screenshots/screenshot_ios_iPhone17_20260205_225900.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260205_225942.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260205_231101.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260205_232911.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260208_095103.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260208_095720.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115040.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115047.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115118.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115125.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115143.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_120107.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_120118.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_120137.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_120201.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_134529.png +0 -0
- package/scripts/shell/android_device_control.enc +0 -1
- package/scripts/shell/connect_android_usb_multi_final.enc +0 -1
- package/scripts/shell/connect_android_wireless.enc +0 -1
- package/scripts/shell/connect_android_wireless_multi_final.enc +0 -1
- package/scripts/shell/connect_ios_usb_multi_final.enc +0 -1
- package/scripts/shell/connect_ios_wireless_multi_final.enc +0 -1
- package/scripts/shell/ios_device_control.enc +0 -1
package/package.json
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devicely",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5",
|
|
4
4
|
"description": "Devicely - One Command, All Devices. AI Powered Mobile Automation for iOS and Android",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"devicely": "./bin/devicely.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"
|
|
11
|
-
"build": "node scripts/build-simple.js",
|
|
12
|
-
"build:obfuscated": "node scripts/build.js",
|
|
13
|
-
"compile:shell": "node scripts/compile-shell-scripts.js",
|
|
14
|
-
"verify:protection": "cd .. && ./verify-shell-protection.sh",
|
|
15
|
-
"postinstall": "node scripts/postinstall.js",
|
|
16
|
-
"prepack": "echo '📦 Packing for distribution...'"
|
|
10
|
+
"postinstall": "node scripts/postinstall.js"
|
|
17
11
|
},
|
|
18
12
|
"keywords": [
|
|
19
13
|
"ios",
|
|
@@ -79,8 +73,5 @@
|
|
|
79
73
|
"preferGlobal": true,
|
|
80
74
|
"publishConfig": {
|
|
81
75
|
"access": "public"
|
|
82
|
-
},
|
|
83
|
-
"devDependencies": {
|
|
84
|
-
"javascript-obfuscator": "^5.2.1"
|
|
85
76
|
}
|
|
86
|
-
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shell Script Compiler using shc
|
|
5
|
+
* Compiles shell scripts to binary executables for protection
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { execSync, spawn } = require('child_process');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const os = require('os');
|
|
12
|
+
|
|
13
|
+
const SCRIPTS_DIR = path.join(__dirname, 'shell');
|
|
14
|
+
const DIST_SHELL_DIR = path.join(__dirname, '../dist/scripts/shell');
|
|
15
|
+
|
|
16
|
+
// Ensure dist directory structure exists
|
|
17
|
+
function ensureDistStructure() {
|
|
18
|
+
const dirs = [
|
|
19
|
+
path.join(__dirname, '../dist'),
|
|
20
|
+
path.join(__dirname, '../dist/scripts'),
|
|
21
|
+
DIST_SHELL_DIR
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
dirs.forEach(dir => {
|
|
25
|
+
if (!fs.existsSync(dir)) {
|
|
26
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Check if shc is installed
|
|
32
|
+
function checkShcInstalled() {
|
|
33
|
+
try {
|
|
34
|
+
execSync('which shc', { stdio: 'pipe' });
|
|
35
|
+
return true;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Install shc if not present
|
|
42
|
+
function installShc() {
|
|
43
|
+
console.log('📥 Installing shc (Shell Script Compiler)...');
|
|
44
|
+
|
|
45
|
+
const platform = os.platform();
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
if (platform === 'darwin') {
|
|
49
|
+
console.log(' Using Homebrew to install shc...');
|
|
50
|
+
execSync('brew install shc', { stdio: 'inherit' });
|
|
51
|
+
} else if (platform === 'linux') {
|
|
52
|
+
console.log(' Installing shc on Linux...');
|
|
53
|
+
// Try different package managers
|
|
54
|
+
try {
|
|
55
|
+
execSync('sudo apt-get update && sudo apt-get install -y shc', { stdio: 'inherit' });
|
|
56
|
+
} catch (e) {
|
|
57
|
+
try {
|
|
58
|
+
execSync('sudo yum install -y shc', { stdio: 'inherit' });
|
|
59
|
+
} catch (e2) {
|
|
60
|
+
console.error('❌ Could not install shc. Please install manually.');
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
console.error('❌ Unsupported platform for automatic shc installation.');
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
console.log('✅ shc installed successfully!');
|
|
69
|
+
return true;
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error('❌ Failed to install shc:', error.message);
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Compile a single shell script
|
|
77
|
+
function compileShellScript(scriptPath, outputDir) {
|
|
78
|
+
const scriptName = path.basename(scriptPath, '.sh');
|
|
79
|
+
const outputBinary = path.join(outputDir, scriptName);
|
|
80
|
+
|
|
81
|
+
console.log(`🔒 Compiling: ${scriptName}.sh -> ${scriptName} (binary)`);
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
// Copy script to output directory first
|
|
85
|
+
const tempScript = path.join(outputDir, path.basename(scriptPath));
|
|
86
|
+
fs.copyFileSync(scriptPath, tempScript);
|
|
87
|
+
|
|
88
|
+
// Compile with shc
|
|
89
|
+
// -f: input file
|
|
90
|
+
// -o: output binary file
|
|
91
|
+
// -r: make binary relocatable (not require original .sh file)
|
|
92
|
+
// -v: verbose
|
|
93
|
+
const cmd = `shc -r -f "${tempScript}" -o "${outputBinary}"`;
|
|
94
|
+
execSync(cmd, { stdio: 'pipe' });
|
|
95
|
+
|
|
96
|
+
// Make binary executable
|
|
97
|
+
fs.chmodSync(outputBinary, 0o755);
|
|
98
|
+
|
|
99
|
+
// Clean up temporary files created by shc
|
|
100
|
+
const tempFiles = [
|
|
101
|
+
tempScript + '.x.c', // C source file
|
|
102
|
+
tempScript // Original script copy
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
tempFiles.forEach(file => {
|
|
106
|
+
if (fs.existsSync(file)) {
|
|
107
|
+
fs.unlinkSync(file);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
console.log(` ✓ Binary created: ${scriptName}`);
|
|
112
|
+
return true;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error(` ❌ Failed to compile ${scriptName}:`, error.message);
|
|
115
|
+
// Copy the original script as fallback
|
|
116
|
+
fs.copyFileSync(scriptPath, path.join(outputDir, path.basename(scriptPath)));
|
|
117
|
+
console.log(` ⚠️ Fallback: Copied original script`);
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Compile all shell scripts
|
|
123
|
+
function compileAllScripts() {
|
|
124
|
+
console.log('\n🛡️ Shell Script Protection Starting...\n');
|
|
125
|
+
|
|
126
|
+
// Ensure dist structure exists
|
|
127
|
+
ensureDistStructure();
|
|
128
|
+
|
|
129
|
+
// Check/install shc
|
|
130
|
+
if (!checkShcInstalled()) {
|
|
131
|
+
console.log('⚠️ shc not found. Attempting to install...');
|
|
132
|
+
if (!installShc()) {
|
|
133
|
+
console.error('❌ Cannot proceed without shc. Exiting...');
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
console.log('✅ shc is installed');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Ensure output directory exists
|
|
141
|
+
if (!fs.existsSync(DIST_SHELL_DIR)) {
|
|
142
|
+
fs.mkdirSync(DIST_SHELL_DIR, { recursive: true });
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Get all shell scripts
|
|
146
|
+
if (!fs.existsSync(SCRIPTS_DIR)) {
|
|
147
|
+
console.error(`❌ Scripts directory not found: ${SCRIPTS_DIR}`);
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const shellScripts = fs.readdirSync(SCRIPTS_DIR)
|
|
152
|
+
.filter(file => file.endsWith('.sh'))
|
|
153
|
+
.map(file => path.join(SCRIPTS_DIR, file));
|
|
154
|
+
|
|
155
|
+
if (shellScripts.length === 0) {
|
|
156
|
+
console.log('⚠️ No shell scripts found to compile');
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
console.log(`\n📋 Found ${shellScripts.length} shell scripts to compile\n`);
|
|
161
|
+
|
|
162
|
+
let successCount = 0;
|
|
163
|
+
let failCount = 0;
|
|
164
|
+
|
|
165
|
+
// Compile each script
|
|
166
|
+
shellScripts.forEach(scriptPath => {
|
|
167
|
+
if (compileShellScript(scriptPath, DIST_SHELL_DIR)) {
|
|
168
|
+
successCount++;
|
|
169
|
+
} else {
|
|
170
|
+
failCount++;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// Summary
|
|
175
|
+
console.log('\n' + '='.repeat(60));
|
|
176
|
+
console.log('📊 Compilation Summary');
|
|
177
|
+
console.log('='.repeat(60));
|
|
178
|
+
console.log(`✅ Successfully compiled: ${successCount}`);
|
|
179
|
+
if (failCount > 0) {
|
|
180
|
+
console.log(`⚠️ Failed compilations: ${failCount}`);
|
|
181
|
+
}
|
|
182
|
+
console.log('='.repeat(60));
|
|
183
|
+
|
|
184
|
+
// Remove .sh files from distribution (keep only binaries)
|
|
185
|
+
console.log('\n🗑️ Removing .sh files from distribution (keeping only binaries)...');
|
|
186
|
+
const shFiles = fs.readdirSync(DIST_SHELL_DIR).filter(f => f.endsWith('.sh'));
|
|
187
|
+
shFiles.forEach(shFile => {
|
|
188
|
+
const filePath = path.join(DIST_SHELL_DIR, shFile);
|
|
189
|
+
fs.unlinkSync(filePath);
|
|
190
|
+
console.log(` ✓ Removed: ${shFile}`);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
console.log('\n✅ Shell script protection complete!');
|
|
194
|
+
console.log(`📁 Protected scripts in: ${DIST_SHELL_DIR}`);
|
|
195
|
+
console.log(`🛡️ Only binary executables remain (${successCount} files)\n`);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Run if called directly
|
|
199
|
+
if (require.main === module) {
|
|
200
|
+
try {
|
|
201
|
+
compileAllScripts();
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.error('❌ Error during compilation:', error);
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
module.exports = { compileAllScripts, compileShellScript };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Simple Shell Script Encryption
|
|
5
|
+
* Encrypts .sh files to .enc files that are decrypted at runtime
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const crypto = require('crypto');
|
|
11
|
+
|
|
12
|
+
// Generate encryption key
|
|
13
|
+
function generateKey() {
|
|
14
|
+
const pkg = require('../package.json');
|
|
15
|
+
// Use only package name for consistent key across versions
|
|
16
|
+
return crypto.createHash('sha256').update(pkg.name + 'devicely-encryption-key-v1').digest();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Encrypt a file
|
|
20
|
+
function encryptFile(inputPath, outputPath) {
|
|
21
|
+
const content = fs.readFileSync(inputPath, 'utf8');
|
|
22
|
+
const key = generateKey();
|
|
23
|
+
const iv = crypto.randomBytes(16);
|
|
24
|
+
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
|
25
|
+
|
|
26
|
+
let encrypted = cipher.update(content, 'utf8', 'hex');
|
|
27
|
+
encrypted += cipher.final('hex');
|
|
28
|
+
|
|
29
|
+
const data = JSON.stringify({
|
|
30
|
+
iv: iv.toString('hex'),
|
|
31
|
+
content: encrypted
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
fs.writeFileSync(outputPath, data);
|
|
35
|
+
console.log(` ✓ ${path.basename(inputPath)} → ${path.basename(outputPath)}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Encrypt all shell scripts
|
|
39
|
+
function encryptShellScripts(sourceDir, outputDir) {
|
|
40
|
+
console.log('🔐 Encrypting shell scripts...\n');
|
|
41
|
+
|
|
42
|
+
if (!fs.existsSync(outputDir)) {
|
|
43
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const scripts = [
|
|
47
|
+
'android_device_control.sh',
|
|
48
|
+
'connect_android_usb_multi_final.sh',
|
|
49
|
+
'connect_android_wireless.sh',
|
|
50
|
+
'connect_android_wireless_multi_final.sh',
|
|
51
|
+
'connect_ios_usb_multi_final.sh',
|
|
52
|
+
'connect_ios_wireless_multi_final.sh',
|
|
53
|
+
'ios_device_control.sh'
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
let encrypted = 0;
|
|
57
|
+
scripts.forEach(script => {
|
|
58
|
+
const srcPath = path.join(sourceDir, script);
|
|
59
|
+
if (fs.existsSync(srcPath)) {
|
|
60
|
+
const encPath = path.join(outputDir, script.replace('.sh', '.enc'));
|
|
61
|
+
encryptFile(srcPath, encPath);
|
|
62
|
+
encrypted++;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
console.log(`\n✅ Encrypted ${encrypted} shell scripts\n`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = { encryptShellScripts };
|
|
70
|
+
|
|
71
|
+
if (require.main === module) {
|
|
72
|
+
const srcDir = path.join(__dirname, '../../');
|
|
73
|
+
const outDir = path.join(__dirname, '../dist/scripts/shell');
|
|
74
|
+
encryptShellScripts(srcDir, outDir);
|
|
75
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shell Script Obfuscator
|
|
5
|
+
* Obfuscates shell scripts using base64 encoding and encryption
|
|
6
|
+
* Cross-platform compatible
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const crypto = require('crypto');
|
|
12
|
+
|
|
13
|
+
// Generate a key from package info (consistent across installations)
|
|
14
|
+
function generateKey() {
|
|
15
|
+
const pkg = require('../package.json');
|
|
16
|
+
return crypto.createHash('sha256').update(pkg.name + pkg.version).digest();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Encrypt script content
|
|
20
|
+
function encryptScript(content) {
|
|
21
|
+
const key = generateKey();
|
|
22
|
+
const iv = crypto.randomBytes(16);
|
|
23
|
+
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
|
24
|
+
|
|
25
|
+
let encrypted = cipher.update(content, 'utf8', 'hex');
|
|
26
|
+
encrypted += cipher.final('hex');
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
iv: iv.toString('hex'),
|
|
30
|
+
content: encrypted
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Create wrapper script that decrypts and executes
|
|
35
|
+
function createWrapper(scriptName, encrypted) {
|
|
36
|
+
return `#!/bin/bash
|
|
37
|
+
# Protected Shell Script - Devicely
|
|
38
|
+
# This script is encrypted for code protection
|
|
39
|
+
|
|
40
|
+
SCRIPT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
|
|
41
|
+
NODE_BIN="node"
|
|
42
|
+
|
|
43
|
+
# Check if node is available
|
|
44
|
+
if ! command -v node &> /dev/null; then
|
|
45
|
+
echo "Error: Node.js is required to run Devicely"
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Decrypt and execute
|
|
50
|
+
$NODE_BIN -e "
|
|
51
|
+
const crypto = require('crypto');
|
|
52
|
+
const pkg = require('$SCRIPT_DIR/../../package.json');
|
|
53
|
+
|
|
54
|
+
function generateKey() {
|
|
55
|
+
return crypto.createHash('sha256').update(pkg.name + pkg.version).digest();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function decrypt(iv, content) {
|
|
59
|
+
const key = generateKey();
|
|
60
|
+
const decipher = crypto.createDecipheriv('aes-256-cbc', key, Buffer.from(iv, 'hex'));
|
|
61
|
+
let decrypted = decipher.update(content, 'hex', 'utf8');
|
|
62
|
+
decrypted += decipher.final('utf8');
|
|
63
|
+
return decrypted;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const encrypted = {
|
|
67
|
+
iv: '${encrypted.iv}',
|
|
68
|
+
content: '${encrypted.content}'
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const script = decrypt(encrypted.iv, encrypted.content);
|
|
72
|
+
const { spawn } = require('child_process');
|
|
73
|
+
|
|
74
|
+
// Get arguments passed to this wrapper
|
|
75
|
+
// When called as: node -e "..." -- arg1 arg2
|
|
76
|
+
// process.argv is: ['/path/to/node', 'arg1', 'arg2', ...]
|
|
77
|
+
// So we need slice(1) not slice(2)
|
|
78
|
+
const args = process.argv.slice(1);
|
|
79
|
+
|
|
80
|
+
// Create a temporary file for the decrypted script
|
|
81
|
+
const tmpScript = require('path').join(require('os').tmpdir(), 'devicely_' + Date.now() + '.sh');
|
|
82
|
+
require('fs').writeFileSync(tmpScript, script, { mode: 0o755 });
|
|
83
|
+
|
|
84
|
+
// Execute the decrypted script with arguments using spawn
|
|
85
|
+
const child = spawn(tmpScript, args, {
|
|
86
|
+
stdio: 'inherit',
|
|
87
|
+
env: process.env
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
child.on('exit', (code) => {
|
|
91
|
+
// Clean up temp file
|
|
92
|
+
try { require('fs').unlinkSync(tmpScript); } catch(e) {}
|
|
93
|
+
process.exit(code || 0);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
child.on('error', (error) => {
|
|
97
|
+
// Clean up temp file on error
|
|
98
|
+
try { require('fs').unlinkSync(tmpScript); } catch(e) {}
|
|
99
|
+
console.error('Error executing script:', error);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
});
|
|
102
|
+
"
|
|
103
|
+
`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Obfuscate all shell scripts
|
|
107
|
+
function obfuscateShellScripts(shellDir, outputDir) {
|
|
108
|
+
console.log('🔐 Obfuscating shell scripts...');
|
|
109
|
+
|
|
110
|
+
if (!fs.existsSync(shellDir)) {
|
|
111
|
+
console.error('❌ Shell scripts directory not found');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!fs.existsSync(outputDir)) {
|
|
116
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const shellScripts = fs.readdirSync(shellDir).filter(f => f.endsWith('.sh'));
|
|
120
|
+
|
|
121
|
+
if (shellScripts.length === 0) {
|
|
122
|
+
console.log('⚠️ No shell scripts found');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let processed = 0;
|
|
127
|
+
shellScripts.forEach(script => {
|
|
128
|
+
try {
|
|
129
|
+
const scriptPath = path.join(shellDir, script);
|
|
130
|
+
const content = fs.readFileSync(scriptPath, 'utf8');
|
|
131
|
+
|
|
132
|
+
// Encrypt the script
|
|
133
|
+
const encrypted = encryptScript(content);
|
|
134
|
+
|
|
135
|
+
// Create wrapper script
|
|
136
|
+
const wrapper = createWrapper(script, encrypted);
|
|
137
|
+
|
|
138
|
+
// Write wrapper to output
|
|
139
|
+
const outputPath = path.join(outputDir, script);
|
|
140
|
+
fs.writeFileSync(outputPath, wrapper);
|
|
141
|
+
fs.chmodSync(outputPath, 0o755);
|
|
142
|
+
|
|
143
|
+
console.log(` ✓ ${script} → encrypted wrapper`);
|
|
144
|
+
processed++;
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error(` ❌ Failed to obfuscate ${script}:`, error.message);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
console.log(`✅ Obfuscated ${processed} shell scripts`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
module.exports = { obfuscateShellScripts };
|
|
154
|
+
|
|
155
|
+
// Run if called directly
|
|
156
|
+
if (require.main === module) {
|
|
157
|
+
const shellSrc = path.join(__dirname, 'shell');
|
|
158
|
+
const distShell = path.join(__dirname, '../dist/scripts/shell');
|
|
159
|
+
obfuscateShellScripts(shellSrc, distShell);
|
|
160
|
+
}
|
|
Binary file
|