mirror of
https://github.com/xenos1337/httptoolkit-patcher.git
synced 2026-07-16 00:24:24 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30ec13fbdc | ||
|
|
f139d9c2ba | ||
|
|
cde93879a2 | ||
|
|
a991b56c01 | ||
|
|
76decebe22 |
@@ -1,120 +0,0 @@
|
|||||||
name: Release Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- 'v*'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Build ${{ matrix.os }}
|
|
||||||
runs-on: ${{ matrix.runner }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: linux
|
|
||||||
runner: ubuntu-latest
|
|
||||||
targets: node18-linux-x64,node18-linux-arm64
|
|
||||||
- os: macos
|
|
||||||
runner: macos-latest
|
|
||||||
targets: node18-macos-x64,node18-macos-arm64
|
|
||||||
- os: windows
|
|
||||||
runner: windows-latest
|
|
||||||
targets: node18-win-x64
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '18'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Create dist directory
|
|
||||||
run: mkdir -p dist
|
|
||||||
|
|
||||||
- name: Build for ${{ matrix.os }}
|
|
||||||
run: |
|
|
||||||
npm run build
|
|
||||||
npx pkg dist/bundle.cjs --targets ${{ matrix.targets }} --compress GZip --out-path dist/
|
|
||||||
|
|
||||||
- name: List built files (debug - Unix)
|
|
||||||
if: matrix.os != 'windows'
|
|
||||||
run: ls -lah dist/
|
|
||||||
|
|
||||||
- name: List built files (debug - Windows)
|
|
||||||
if: matrix.os == 'windows'
|
|
||||||
shell: pwsh
|
|
||||||
run: Get-ChildItem -Path dist/ | Format-Table -AutoSize
|
|
||||||
|
|
||||||
- name: Rename executables (Linux)
|
|
||||||
if: matrix.os == 'linux'
|
|
||||||
run: |
|
|
||||||
[ -f dist/bundle-x64 ] && mv dist/bundle-x64 dist/httptoolkit-patcher-linux-x64
|
|
||||||
[ -f dist/bundle-arm64 ] && mv dist/bundle-arm64 dist/httptoolkit-patcher-linux-arm64
|
|
||||||
rm -f dist/bundle dist/bundle.cjs 2>/dev/null || true
|
|
||||||
|
|
||||||
- name: Rename executables (macOS)
|
|
||||||
if: matrix.os == 'macos'
|
|
||||||
run: |
|
|
||||||
[ -f dist/bundle-x64 ] && mv dist/bundle-x64 dist/httptoolkit-patcher-macos-x64
|
|
||||||
[ -f dist/bundle-arm64 ] && mv dist/bundle-arm64 dist/httptoolkit-patcher-macos-arm64
|
|
||||||
rm -f dist/bundle dist/bundle.cjs 2>/dev/null || true
|
|
||||||
|
|
||||||
- name: Rename executables (Windows)
|
|
||||||
if: matrix.os == 'windows'
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
if (Test-Path dist/bundle.exe) { Move-Item -Force dist/bundle.exe dist/httptoolkit-patcher.exe }
|
|
||||||
if (Test-Path dist/bundle-x64.exe) { Move-Item -Force dist/bundle-x64.exe dist/httptoolkit-patcher-win-x64.exe }
|
|
||||||
Remove-Item -Force dist/bundle.cjs -ErrorAction SilentlyContinue
|
|
||||||
|
|
||||||
- name: Upload artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: binaries-${{ matrix.os }}
|
|
||||||
path: dist/*
|
|
||||||
|
|
||||||
release:
|
|
||||||
name: Create Release
|
|
||||||
needs: build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Download all artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
pattern: binaries-*
|
|
||||||
path: artifacts
|
|
||||||
merge-multiple: true
|
|
||||||
|
|
||||||
- name: Prepare release files
|
|
||||||
run: |
|
|
||||||
mkdir -p release
|
|
||||||
cp artifacts/* release/ 2>/dev/null || find artifacts -type f -exec cp {} release/ \;
|
|
||||||
ls -lah release/
|
|
||||||
|
|
||||||
- name: Extract version from tag
|
|
||||||
id: get_version
|
|
||||||
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Create Release
|
|
||||||
uses: softprops/action-gh-release@v1
|
|
||||||
with:
|
|
||||||
files: release/*
|
|
||||||
draft: false
|
|
||||||
prerelease: false
|
|
||||||
generate_release_notes: true
|
|
||||||
name: Release ${{ steps.get_version.outputs.VERSION }}
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
@@ -26,64 +26,30 @@ Yes, but they most likely won't. Fixing this would require changing their entire
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. Install dependencies:
|
1. Install Node.js (if not already installed)
|
||||||
|
2. Install dependencies:
|
||||||
```bash
|
```bash
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
Build standalone executables for all platforms and architectures:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
This creates self-contained executables in the `dist/` directory:
|
|
||||||
|
|
||||||
**Windows:**
|
|
||||||
- `httptoolkit-patcher-win-x64.exe` (64-bit)
|
|
||||||
|
|
||||||
**Linux:**
|
|
||||||
- `httptoolkit-patcher-linux-x64` (x86_64/AMD64)
|
|
||||||
- `httptoolkit-patcher-linux-arm64` (ARM64/AArch64)
|
|
||||||
|
|
||||||
**macOS:**
|
|
||||||
- `httptoolkit-patcher-macos-x64` (Intel)
|
|
||||||
- `httptoolkit-patcher-macos-arm64` (Apple Silicon M Chip)
|
|
||||||
|
|
||||||
**Note:** These are standalone executables created with `pkg` that include Node.js runtime and all dependencies. No need to install Node.js separately!
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### From Source
|
**Patch HTTP Toolkit:**
|
||||||
|
|
||||||
**Patch:**
|
|
||||||
```bash
|
```bash
|
||||||
npm start
|
npm start
|
||||||
```
|
```
|
||||||
|
|
||||||
**Unpatch:**
|
**Unpatch/Restore:**
|
||||||
```bash
|
```bash
|
||||||
npm run unpatch
|
npm run unpatch
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using Prebuilt Executables
|
**Show help:**
|
||||||
|
|
||||||
Download the appropriate executable for your platform from [Releases](https://github.com/xenos1337/httptoolkit-patcher/releases), then:
|
|
||||||
|
|
||||||
**Windows:**
|
|
||||||
```cmd
|
|
||||||
httptoolkit-patcher-win-x64.exe
|
|
||||||
```
|
|
||||||
|
|
||||||
**Linux/macOS:**
|
|
||||||
```bash
|
```bash
|
||||||
chmod +x httptoolkit-patcher-linux-x64 # or your architecture
|
npm start help
|
||||||
./httptoolkit-patcher-linux-x64
|
|
||||||
```
|
```
|
||||||
|
|
||||||
That's it. The patcher handles everything automatically.
|
That's it. The patcher handles everything automatically and will request elevated permissions if needed.
|
||||||
|
|
||||||
## Technical Details
|
## Technical Details
|
||||||
|
|
||||||
@@ -96,7 +62,7 @@ That's it. The patcher handles everything automatically.
|
|||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
**Permission errors?** Run as admin/sudo or let the patcher request elevation.
|
**Permission errors?** The patcher will automatically request elevated permissions (admin/sudo).
|
||||||
|
|
||||||
**Already patched?** The patcher will ask if you want to repatch.
|
**Already patched?** The patcher will ask if you want to repatch.
|
||||||
|
|
||||||
@@ -104,27 +70,6 @@ That's it. The patcher handles everything automatically.
|
|||||||
|
|
||||||
**Anything else?** Open an issue on the [GitHub repository](https://github.com/xenos1337/httptoolkit-patcher/issues).
|
**Anything else?** Open an issue on the [GitHub repository](https://github.com/xenos1337/httptoolkit-patcher/issues).
|
||||||
|
|
||||||
## GitHub Release Workflow
|
|
||||||
|
|
||||||
This project includes an automated GitHub Actions workflow that builds and releases the patcher for all platforms.
|
|
||||||
|
|
||||||
### Creating a Release
|
|
||||||
|
|
||||||
1. Create and push a version tag:
|
|
||||||
```bash
|
|
||||||
git tag v2.0.1
|
|
||||||
git push origin v2.0.1
|
|
||||||
```
|
|
||||||
|
|
||||||
2. The GitHub Actions workflow will automatically:
|
|
||||||
- Build for all platforms and architectures (Windows x64, Linux x64/ARM64, macOS Intel/Apple Silicon)
|
|
||||||
- Create standalone native executables using pkg
|
|
||||||
- Create a GitHub release with all binaries as downloadable artifacts
|
|
||||||
|
|
||||||
### Manual Workflow Trigger
|
|
||||||
|
|
||||||
You can also manually trigger the release workflow from the GitHub Actions tab.
|
|
||||||
|
|
||||||
## Disclaimer
|
## Disclaimer
|
||||||
|
|
||||||
This tool is provided as-is. Use at your own risk. For educational purposes only.
|
This tool is provided as-is. Use at your own risk. For educational purposes only.
|
||||||
|
|||||||
@@ -15,19 +15,16 @@ const isLinux = process.platform === "linux";
|
|||||||
// Handle both ESM and pkg-bundled scenarios
|
// Handle both ESM and pkg-bundled scenarios
|
||||||
const __filename = (() => {
|
const __filename = (() => {
|
||||||
// Check if running as pkg bundle
|
// Check if running as pkg bundle
|
||||||
|
// @ts-ignore - pkg adds this property at runtime
|
||||||
if (process.pkg) {
|
if (process.pkg) {
|
||||||
return process.execPath;
|
return process.execPath;
|
||||||
}
|
}
|
||||||
// Check if import.meta.url exists (ESM)
|
// ESM: use import.meta.url
|
||||||
if (typeof import.meta !== 'undefined' && import.meta.url) {
|
return fileURLToPath(import.meta.url);
|
||||||
return fileURLToPath(import.meta.url);
|
|
||||||
}
|
|
||||||
// Fallback to __filename if in CommonJS
|
|
||||||
return typeof __filename !== 'undefined' ? __filename : process.argv[1];
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Check if running with elevated privileges
|
// Check if running with elevated privileges
|
||||||
const isElevated = () => {
|
function isElevated() {
|
||||||
if (isWin) {
|
if (isWin) {
|
||||||
try {
|
try {
|
||||||
execSync("net session", { stdio: "ignore" });
|
execSync("net session", { stdio: "ignore" });
|
||||||
@@ -38,10 +35,10 @@ const isElevated = () => {
|
|||||||
} else {
|
} else {
|
||||||
return process.getuid && process.getuid() === 0;
|
return process.getuid && process.getuid() === 0;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Helper function to prompt user for input
|
// Helper function to prompt user for input
|
||||||
const prompt = question => {
|
function prompt(question) {
|
||||||
const rl = readline.createInterface({
|
const rl = readline.createInterface({
|
||||||
input: process.stdin,
|
input: process.stdin,
|
||||||
output: process.stdout,
|
output: process.stdout,
|
||||||
@@ -52,10 +49,10 @@ const prompt = question => {
|
|||||||
resolve(answer);
|
resolve(answer);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
// Helper function to fetch content from URL
|
// Helper function to fetch content from URL
|
||||||
const fetchUrl = url => {
|
function fetchUrl(url) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
https
|
https
|
||||||
.get(url, res => {
|
.get(url, res => {
|
||||||
@@ -65,10 +62,10 @@ const fetchUrl = url => {
|
|||||||
})
|
})
|
||||||
.on("error", reject);
|
.on("error", reject);
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
// Helper function to remove directory recursively
|
// Helper function to remove directory recursively
|
||||||
const rm = dirPath => {
|
function rm(dirPath) {
|
||||||
if (!fs.existsSync(dirPath)) return;
|
if (!fs.existsSync(dirPath)) return;
|
||||||
if (!fs.lstatSync(dirPath).isDirectory()) return fs.rmSync(dirPath, { force: true });
|
if (!fs.lstatSync(dirPath).isDirectory()) return fs.rmSync(dirPath, { force: true });
|
||||||
for (const entry of fs.readdirSync(dirPath)) {
|
for (const entry of fs.readdirSync(dirPath)) {
|
||||||
@@ -77,10 +74,10 @@ const rm = dirPath => {
|
|||||||
else fs.rmSync(entryPath, { force: true });
|
else fs.rmSync(entryPath, { force: true });
|
||||||
}
|
}
|
||||||
fs.rmdirSync(dirPath);
|
fs.rmdirSync(dirPath);
|
||||||
};
|
}
|
||||||
|
|
||||||
// Find HTTP Toolkit installation path
|
// Find HTTP Toolkit installation path
|
||||||
const findAppPath = async () => {
|
async function findAppPath() {
|
||||||
const possiblePaths = isWin ? [path.join("C:", "Program Files", "HTTP Toolkit", "resources"), path.join("C:", "Program Files (x86)", "HTTP Toolkit", "resources")] : isMac ? ["/Applications/HTTP Toolkit.app/Contents/Resources"] : ["/opt/HTTP Toolkit/resources", "/opt/httptoolkit/resources"];
|
const possiblePaths = isWin ? [path.join("C:", "Program Files", "HTTP Toolkit", "resources"), path.join("C:", "Program Files (x86)", "HTTP Toolkit", "resources")] : isMac ? ["/Applications/HTTP Toolkit.app/Contents/Resources"] : ["/opt/HTTP Toolkit/resources", "/opt/httptoolkit/resources"];
|
||||||
|
|
||||||
for (const p of possiblePaths) {
|
for (const p of possiblePaths) {
|
||||||
@@ -109,20 +106,27 @@ const findAppPath = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return resourcesPath;
|
return resourcesPath;
|
||||||
};
|
}
|
||||||
|
|
||||||
// Request elevated permissions
|
// Request elevated permissions
|
||||||
const requestElevation = async () => {
|
async function requestElevation() {
|
||||||
console.log(chalk.yellowBright`[!] Requesting elevated permissions...`);
|
console.log(chalk.yellowBright`[!] Requesting elevated permissions...`);
|
||||||
|
|
||||||
|
// @ts-ignore - pkg adds this property at runtime
|
||||||
|
const isBundled = process.pkg;
|
||||||
|
|
||||||
if (isWin) {
|
if (isWin) {
|
||||||
// Windows: Use PowerShell to run as administrator
|
// Windows: Use PowerShell to run as administrator
|
||||||
const script = `Start-Process -FilePath "node" -ArgumentList '"${__filename}"' -Verb RunAs`;
|
let script;
|
||||||
|
if (isBundled) {
|
||||||
|
script = `Start-Process -FilePath "${__filename}" -Verb RunAs`;
|
||||||
|
} else {
|
||||||
|
script = `Start-Process -FilePath "node" -ArgumentList "${__filename}" -Verb RunAs`;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
spawn("powershell", ["-Command", script], {
|
console.log(chalk.greenBright`[+] Spawning PowerShell with script: ${script}`);
|
||||||
stdio: "inherit",
|
execSync(`powershell -Command "${script}"`, { stdio: "inherit" });
|
||||||
shell: true,
|
|
||||||
});
|
|
||||||
console.log(chalk.blueBright`[+] Restarting with administrator privileges...`);
|
console.log(chalk.blueBright`[+] Restarting with administrator privileges...`);
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -130,12 +134,30 @@ const requestElevation = async () => {
|
|||||||
console.error(chalk.redBright`[-] Please run as administrator manually`);
|
console.error(chalk.redBright`[-] Please run as administrator manually`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
} else if (isLinux) {
|
||||||
|
// Linux: Cannot auto-elevate with sudo, show instructions instead
|
||||||
|
console.log(chalk.yellowBright`[!] Elevated permissions are required for patching on Linux`);
|
||||||
|
console.log(chalk.yellowBright`[!] Please re-run this script with sudo:`);
|
||||||
|
if (isBundled) {
|
||||||
|
console.log(chalk.blueBright` sudo ${__filename}`);
|
||||||
|
} else {
|
||||||
|
console.log(chalk.blueBright` sudo node ${__filename}`);
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
} else {
|
} else {
|
||||||
|
// macOS: Try to elevate with sudo
|
||||||
console.log(chalk.blueBright`[+] Restarting with sudo...`);
|
console.log(chalk.blueBright`[+] Restarting with sudo...`);
|
||||||
try {
|
try {
|
||||||
const child = spawn("sudo", ["node", __filename], {
|
let child;
|
||||||
stdio: "inherit",
|
if (isBundled) {
|
||||||
});
|
child = spawn("sudo", [__filename], {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
child = spawn("sudo", ["node", __filename], {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
}
|
||||||
child.on("exit", code => process.exit(code || 0));
|
child.on("exit", code => process.exit(code || 0));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(chalk.redBright`[-] Failed to elevate permissions: ${e.message}`);
|
console.error(chalk.redBright`[-] Failed to elevate permissions: ${e.message}`);
|
||||||
@@ -143,20 +165,34 @@ const requestElevation = async () => {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Check if we have write permissions
|
// Check if we have write permissions
|
||||||
const checkPermissions = filePath => {
|
function checkPermissions(filePath) {
|
||||||
try {
|
try {
|
||||||
|
// Check write access to the file/directory
|
||||||
fs.accessSync(filePath, fs.constants.W_OK);
|
fs.accessSync(filePath, fs.constants.W_OK);
|
||||||
|
|
||||||
|
// Check if we can create directories
|
||||||
|
const testDirPath = path.join(path.dirname(filePath), `.test_${Date.now()}`);
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(testDirPath, { recursive: true });
|
||||||
|
fs.rmdirSync(testDirPath);
|
||||||
|
} catch (dirError) {
|
||||||
|
console.error(chalk.redBright`[-] Cannot create directories in ${path.dirname(filePath)}: ${dirError.message}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(chalk.greenBright`[+] Permissions check passed for ${filePath}`);
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.error(chalk.redBright`[-] Permissions check failed for ${filePath}: ${e.message}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Kill HTTP Toolkit processes
|
// Kill HTTP Toolkit processes
|
||||||
const killHttpToolkit = async () => {
|
async function killHttpToolkit() {
|
||||||
console.log(chalk.yellowBright`[+] Checking for running HTTP Toolkit processes...`);
|
console.log(chalk.yellowBright`[+] Checking for running HTTP Toolkit processes...`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -199,10 +235,10 @@ const killHttpToolkit = async () => {
|
|||||||
console.log(chalk.yellowBright`[!] Could not check/kill processes: ${e.message}`);
|
console.log(chalk.yellowBright`[!] Could not check/kill processes: ${e.message}`);
|
||||||
console.log(chalk.yellowBright`[!] If HTTP Toolkit is running, please close it manually`);
|
console.log(chalk.yellowBright`[!] If HTTP Toolkit is running, please close it manually`);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Unpatch/restore function
|
// Unpatch/restore function
|
||||||
const unpatchApp = async () => {
|
async function unpatchApp() {
|
||||||
console.log(chalk.blueBright`[+] HTTP Toolkit Unpatcher Started`);
|
console.log(chalk.blueBright`[+] HTTP Toolkit Unpatcher Started`);
|
||||||
|
|
||||||
// Step 1: Find app path
|
// Step 1: Find app path
|
||||||
@@ -229,13 +265,7 @@ const unpatchApp = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log(chalk.yellowBright`[!] Administrator/sudo privileges required for unpatching`);
|
console.log(chalk.yellowBright`[!] Administrator/sudo privileges required for unpatching`);
|
||||||
const answer = await prompt("Do you want to request elevated permissions? [Y/n]: ");
|
await requestElevation();
|
||||||
if (!answer || answer.toLowerCase() === "y" || answer.toLowerCase() === "yes") {
|
|
||||||
await requestElevation();
|
|
||||||
} else {
|
|
||||||
console.log(chalk.redBright`[-] Cannot proceed without write permissions`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4: Check if backup exists
|
// Step 4: Check if backup exists
|
||||||
@@ -270,10 +300,10 @@ const unpatchApp = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log(chalk.greenBright`[+] Successfully unpatched!`);
|
console.log(chalk.greenBright`[+] Successfully unpatched!`);
|
||||||
};
|
}
|
||||||
|
|
||||||
// Main patching function
|
// Main patching function
|
||||||
const patchApp = async () => {
|
async function patchApp() {
|
||||||
console.log(chalk.blueBright`[+] HTTP Toolkit Patcher Started`);
|
console.log(chalk.blueBright`[+] HTTP Toolkit Patcher Started`);
|
||||||
|
|
||||||
// Step 1: Find app path
|
// Step 1: Find app path
|
||||||
@@ -298,13 +328,7 @@ const patchApp = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log(chalk.yellowBright`[!] Administrator/sudo privileges required for patching`);
|
console.log(chalk.yellowBright`[!] Administrator/sudo privileges required for patching`);
|
||||||
const answer = await prompt("Do you want to request elevated permissions? [Y/n]: ");
|
await requestElevation();
|
||||||
if (!answer || answer.toLowerCase() === "y" || answer.toLowerCase() === "yes") {
|
|
||||||
await requestElevation();
|
|
||||||
} else {
|
|
||||||
console.log(chalk.redBright`[-] Cannot proceed without write permissions`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4: Backup app.asar
|
// Step 4: Backup app.asar
|
||||||
@@ -322,12 +346,19 @@ const patchApp = async () => {
|
|||||||
asar.extractAll(asarPath, extractPath);
|
asar.extractAll(asarPath, extractPath);
|
||||||
console.log(chalk.greenBright`[+] Extracted to ${extractPath}`);
|
console.log(chalk.greenBright`[+] Extracted to ${extractPath}`);
|
||||||
|
|
||||||
// Step 6: Check if preload.js exists
|
// Step 6: Check if preload.cjs or preload.js exists
|
||||||
const preloadPath = path.join(extractPath, "build", "preload.js");
|
let preloadPath = path.join(extractPath, "build", "preload.cjs");
|
||||||
if (!fs.existsSync(preloadPath)) {
|
if (!fs.existsSync(preloadPath)) {
|
||||||
console.error(chalk.redBright`[-] preload.js not found at ${preloadPath}`);
|
console.log(chalk.yellowBright`[!] preload.cjs not found, checking for preload.js...`);
|
||||||
rm(extractPath);
|
preloadPath = path.join(extractPath, "build", "preload.js");
|
||||||
process.exit(1);
|
if (!fs.existsSync(preloadPath)) {
|
||||||
|
console.error(chalk.redBright`[-] Neither preload.cjs nor preload.js found in ${path.join(extractPath, "build")}`);
|
||||||
|
rm(extractPath);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
console.log(chalk.greenBright`[+] Found preload.js`);
|
||||||
|
} else {
|
||||||
|
console.log(chalk.greenBright`[+] Found preload.cjs`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 7: Fetch inject.js from GitHub
|
// Step 7: Fetch inject.js from GitHub
|
||||||
@@ -340,7 +371,7 @@ const patchApp = async () => {
|
|||||||
}
|
}
|
||||||
console.log(chalk.greenBright`[+] Inject code fetched successfully`);
|
console.log(chalk.greenBright`[+] Inject code fetched successfully`);
|
||||||
|
|
||||||
// Step 8: Read preload.js and check if already patched
|
// Step 8: Read preload file and check if already patched
|
||||||
let preloadContent = fs.readFileSync(preloadPath, "utf-8");
|
let preloadContent = fs.readFileSync(preloadPath, "utf-8");
|
||||||
const isPatched = preloadContent.includes("injectPageContextHooks");
|
const isPatched = preloadContent.includes("injectPageContextHooks");
|
||||||
|
|
||||||
@@ -372,7 +403,7 @@ const patchApp = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (insertIndex === -1) {
|
if (insertIndex === -1) {
|
||||||
console.error(chalk.redBright`[-] Could not find insertion point (electron_1) in preload.js`);
|
console.error(chalk.redBright`[-] Could not find insertion point (electron_1) in ${path.basename(preloadPath)}`);
|
||||||
rm(extractPath);
|
rm(extractPath);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -381,9 +412,9 @@ const patchApp = async () => {
|
|||||||
preloadContent = lines.join("\n");
|
preloadContent = lines.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 9: Write patched preload.js
|
// Step 9: Write patched preload file
|
||||||
fs.writeFileSync(preloadPath, preloadContent, "utf-8");
|
fs.writeFileSync(preloadPath, preloadContent, "utf-8");
|
||||||
console.log(chalk.greenBright`[+] preload.js patched successfully`);
|
console.log(chalk.greenBright`[+] ${path.basename(preloadPath)} patched successfully`);
|
||||||
|
|
||||||
// Step 10: Repackage app.asar
|
// Step 10: Repackage app.asar
|
||||||
console.log(chalk.yellowBright`[+] Repackaging app.asar...`);
|
console.log(chalk.yellowBright`[+] Repackaging app.asar...`);
|
||||||
@@ -398,26 +429,38 @@ const patchApp = async () => {
|
|||||||
// Step 12: Open HTTP Toolkit as detached process
|
// Step 12: Open HTTP Toolkit as detached process
|
||||||
console.log(chalk.blueBright`[+] Opening HTTP Toolkit...`);
|
console.log(chalk.blueBright`[+] Opening HTTP Toolkit...`);
|
||||||
try {
|
try {
|
||||||
const command = isWin ? `"${path.resolve(appPath, "..", "HTTP Toolkit.exe")}"` : isMac ? 'open -a "HTTP Toolkit"' : "httptoolkit";
|
if (isLinux) {
|
||||||
const child = spawn(command, {
|
// Linux: Cannot auto-launch reliably, show manual instructions
|
||||||
stdio: "ignore",
|
console.log(chalk.yellowBright`[!] HTTP Toolkit has been successfully patched`);
|
||||||
shell: true,
|
console.log(chalk.yellowBright`[!] Please manually launch HTTP Toolkit from your applications menu or using the command:`);
|
||||||
detached: true,
|
console.log(chalk.blueBright` httptoolkit`);
|
||||||
});
|
} else {
|
||||||
child.unref(); // Completely detach the child process
|
const command = isWin ? `"${path.resolve(appPath, "..", "HTTP Toolkit.exe")}"` : isMac ? 'open -a "HTTP Toolkit"' : "httptoolkit";
|
||||||
console.log(chalk.greenBright`[+] HTTP Toolkit launched successfully`);
|
const child = spawn(command, {
|
||||||
|
stdio: "ignore",
|
||||||
|
shell: true,
|
||||||
|
detached: true,
|
||||||
|
});
|
||||||
|
child.unref();
|
||||||
|
console.log(chalk.greenBright`[+] HTTP Toolkit launched successfully`);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(chalk.yellowBright`[!] Could not auto-start HTTP Toolkit: ${e.message}`);
|
console.error(chalk.yellowBright`[!] Could not auto-start HTTP Toolkit: ${e.message}`);
|
||||||
console.log(chalk.blueBright`[+] Please start HTTP Toolkit manually`);
|
console.log(chalk.blueBright`[+] Please start HTTP Toolkit manually`);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Parse command line arguments
|
|
||||||
const args = process.argv.slice(2);
|
const args = process.argv.slice(2);
|
||||||
const command = args[0];
|
const command = args[0];
|
||||||
|
|
||||||
// Get the command name for display
|
const commandName = (() => {
|
||||||
const commandName = process.pkg ? path.basename(__filename) : 'node index.js';
|
// @ts-ignore - pkg adds this property at runtime
|
||||||
|
if (process.pkg) {
|
||||||
|
return path.basename(__filename);
|
||||||
|
} else {
|
||||||
|
return `node ${process.argv[1]}`;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
// Run the appropriate command
|
// Run the appropriate command
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|||||||
Generated
+1
-1963
File diff suppressed because it is too large
Load Diff
+2
-15
@@ -9,18 +9,7 @@
|
|||||||
"start": "node index.js",
|
"start": "node index.js",
|
||||||
"patch": "node index.js patch",
|
"patch": "node index.js patch",
|
||||||
"unpatch": "node index.js unpatch",
|
"unpatch": "node index.js unpatch",
|
||||||
"restore": "node index.js restore",
|
"restore": "node index.js restore"
|
||||||
"build": "esbuild index.js --bundle --platform=node --format=cjs --target=node18 --outfile=dist/bundle.cjs --external:@electron/asar --external:chalk"
|
|
||||||
},
|
|
||||||
"pkg": {
|
|
||||||
"targets": [
|
|
||||||
"node18-win-x64",
|
|
||||||
"node18-linux-x64",
|
|
||||||
"node18-linux-arm64",
|
|
||||||
"node18-macos-x64",
|
|
||||||
"node18-macos-arm64"
|
|
||||||
],
|
|
||||||
"outputPath": "dist"
|
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -28,8 +17,6 @@
|
|||||||
"chalk": "4"
|
"chalk": "4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.14.9",
|
"@types/node": "^20.14.9"
|
||||||
"esbuild": "^0.25.11",
|
|
||||||
"pkg": "^5.8.1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user