Skip to content

Commit

Permalink
support frida-tools installed by pipx
Browse files Browse the repository at this point in the history
  • Loading branch information
ChiChou committed Nov 2, 2024
1 parent 0f5a5a4 commit 675f15d
Show file tree
Hide file tree
Showing 12 changed files with 142 additions and 84 deletions.
71 changes: 47 additions & 24 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -444,13 +444,14 @@
"devDependencies": {
"@types/node": "^22.8.1",
"@types/vscode": "^1.94.0",
"@types/which": "^3.0.4",
"@typescript-eslint/eslint-plugin": "^8.11.0",
"@typescript-eslint/parser": "^8.11.0",
"eslint": "^9.13.0",
"typescript": "^5.6.3"
},
"dependencies": {
"lookpath": "^1.2.2"
"which": "^5.0.0"
},
"extensionDependencies": [
"ms-python.python"
Expand Down
5 changes: 3 additions & 2 deletions src/commands/android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { tmpdir } from 'os';
import ADB from '../driver/adb';
import { DeviceItem, TargetItem } from '../providers/devices';
import { logger } from '../logger';
import { python3Path, sleep } from '../utils';
import { interpreter, sleep } from '../utils';
import { run } from '../term';

function getServerPath() {
Expand Down Expand Up @@ -35,14 +35,15 @@ export async function startServer(target: TargetItem) {
const py = join(__dirname, '..', '..', 'backend', 'android', 'get-frida.py');
const tmp = join(tmpdir(), `frida-server-${abi}`);

const shellPath = await interpreter();
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: 'Downloading frida-server',
cancellable: false
}, async (progress) => {
await run({
name: `Download frida-server`,
shellPath: python3Path(),
shellPath,
shellArgs: [py, abi, tmp]
});
progress.report({ message: 'Done' });
Expand Down
6 changes: 3 additions & 3 deletions src/commands/boilerplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as vscode from 'vscode';

import { AppItem, ProcessItem } from '../providers/devices';
import { run } from '../term';
import { cmd, expandDevParam, python3Path, resource } from '../utils';
import { cmd, expandDevParam, interpreter, resource } from '../utils';


async function create(template: string) {
Expand All @@ -29,11 +29,11 @@ async function create(template: string) {
}

const args = ['-m', 'frida_tools.creator', '-t', template];

const shellPath = await interpreter();
await run({
cwd: dest,
name: 'Create Project',
shellPath: python3Path(),
shellPath,
shellArgs: args
});

Expand Down
4 changes: 2 additions & 2 deletions src/commands/objection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { launch } from '../driver/frida';
import { AppItem, ProcessItem, TargetItem } from "../providers/devices";
import { run } from '../term';
import { DeviceType } from '../types';
import { python3Path } from '../utils';
import { interpreter } from '../utils';

export async function explore(target: TargetItem) : Promise<void> {
if (!target) {
Expand Down Expand Up @@ -47,7 +47,7 @@ export async function explore(target: TargetItem) : Promise<void> {
}

const shellArgs = ['-m', 'objection.console.cli', '-g', gadget, ...device, 'explore'];
const shellPath = python3Path();
const shellPath = await interpreter('objection');
run({
name,
shellArgs,
Expand Down
6 changes: 3 additions & 3 deletions src/commands/repl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import { terminate } from '../driver/frida';
import { all, connect, disconnect } from '../driver/remote';
import { AppItem, DeviceItem, ProcessItem, TargetItem } from '../providers/devices';
import { DeviceType } from '../types';
import { expandDevParam, python3Path, refresh, sleep } from '../utils';
import { expandDevParam, interpreter, refresh } from '../utils';

const terminals = new Set<vscode.Terminal>();

function repl(args: string[], id: string) {
async function repl(args: string[], id: string) {
const name = `Frida - ${id}`;
const shellPath = python3Path();
const shellPath = await interpreter();
const py = path.join(__dirname, '..', '..', 'backend', 'pause.py');
const shellArgs = [py, shellPath, '-m', 'frida_tools.repl', ...args];
const term = vscode.window.createTerminal({
Expand Down
5 changes: 3 additions & 2 deletions src/commands/syslog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { OutputChannel, window } from 'vscode';
import { driverScript, lockdownSyslog, os } from '../driver/backend';
import { AppItem, ProcessItem, TargetItem } from "../providers/devices";
import { DeviceType } from '../types';
import { python3Path, refresh } from '../utils';
import { interpreter, refresh } from '../utils';

const active: { [key: string]: OutputChannel } = {};

Expand Down Expand Up @@ -51,7 +51,8 @@ export async function show(node: TargetItem) {
lockdownSyslog(node.device.id, bundleOrPid);
} else if (type === 'linux' || type === 'macos') {
const args = [driverScript(), 'syslog', '--device', node.device.id, ...bundleOrPid];
cmdChannel(`Output: ${node.data.name} (${node.device.name})`, python3Path(), args).show();
const python3 = await interpreter();
cmdChannel(`Output: ${node.data.name} (${node.device.name})`, python3, args).show();
} else if (type === 'android') {
if (node.data.pid > 0) {
const args = ['-s', node.device.id, 'logcat', `--pid=${node.data.pid}`];
Expand Down
32 changes: 8 additions & 24 deletions src/driver/backend.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { join } from "path";
import { execFile } from 'child_process';
import { window } from 'vscode';

import { asParam } from './remote';
import { logger } from '../logger';
import { run } from '../term';
import { python3Path } from '../utils';
import { interpreter } from '../utils';
import { App, Device, Process } from '../types';
import { AppItem, ProcessItem, TargetItem } from '../providers/devices';

Expand All @@ -14,28 +13,12 @@ const py = join(base, 'driver.py');

export const driverScript = () => py;

function askInstallFrida() {
window.showErrorMessage(`Frida python module not detected. Please check your Python interpreter setting,
or pip install frida-tools. Do you want to install now?`, 'Install', 'Cancel')
.then(selected => {
if (selected === 'Install') {
run({
env: { PIP_BREAK_SYSTEM_PACKAGES: '1' }, // Externally Managed Environments
shellPath: python3Path(),
shellArgs: ['-m', 'pip', 'install', 'frida-tools']
});
}
});
}

export function exec(...args: string[]): Promise<any> {
const remoteDevices = asParam();
return new Promise((resolve, reject) => {
execFile(python3Path(), [py, ...remoteDevices, ...args], { maxBuffer: 1024 * 1024 * 20 }, (err, stdout, stderr) => {

return interpreter().then(path => new Promise((resolve, reject) => {
execFile(path, [py, ...remoteDevices, ...args], { maxBuffer: 1024 * 1024 * 20 }, (err, stdout, stderr) => {
if (err) {
if (stderr.includes('Unable to import frida')) {
askInstallFrida();
}
logger.appendLine(`Error: Failed to execute driver, arguments: ${args.join(' ')}`);
logger.appendLine(stderr);
logger.appendLine(`Exited with ${err.code}`);
Expand All @@ -44,7 +27,7 @@ export function exec(...args: string[]): Promise<any> {
resolve(JSON.parse(stdout));
}
});
});
}));
}

export function devices() {
Expand Down Expand Up @@ -89,10 +72,11 @@ export function rpc(target: TargetItem, method: string, ...args: string[]) {
return exec('rpc', '--device', target.device.id, ...bundleOrPid, method, ...args);
}

export function lockdownSyslog(id: string, bundleOrPid: string[]) {
export async function lockdownSyslog(id: string, bundleOrPid: string[]) {
const shellPath = await interpreter();
return run({
name: `Syslog: ${bundleOrPid}`,
shellPath: python3Path(),
shellPath,
shellArgs: [py, 'syslog2', '--device', id, ...bundleOrPid]
});
}
11 changes: 7 additions & 4 deletions src/driver/frida.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { execFile } from 'child_process';
import { python3Path } from '../utils';
import { interpreter } from '../utils';


function deviceParam(device: string) {
Expand All @@ -11,9 +11,11 @@ function deviceParam(device: string) {

export async function launch(device: string, bundle: string): Promise<Number> {
const params = ['-f', bundle, ...deviceParam(device), bundle, '-q', '-e', 'Process.id'];
const py3 = await interpreter();
const args = ['-m', 'frida_tools.repl', ...params];

return new Promise((resolve, reject) => {
execFile(python3Path(), args, {}, (err, stdout) => {
execFile(py3, args, {}, (err, stdout) => {
if (err) {
reject(err);
} else {
Expand All @@ -27,10 +29,11 @@ export async function launch(device: string, bundle: string): Promise<Number> {
});
}

export function terminate(device: string, target: string) {
export async function terminate(device: string, target: string) {
const py3 = await interpreter('frida-kill');
const args = ['-m', 'frida_tools.kill', ...deviceParam(device), target];
return new Promise((resolve, reject) => {
execFile(python3Path(), args, {}, (err, stdout) => {
execFile(py3, args, {}, (err, stdout) => {
if (err) {
reject(err);
} else {
Expand Down
50 changes: 50 additions & 0 deletions src/shebang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { promises as fs } from 'node:fs';

const SHEBANG_UNIX = '#!';
const BUF_SHEBANG_UNIX = Buffer.from(SHEBANG_UNIX);
const PE_MAGIC = Buffer.from('MZ');

const ZIP_SIGNATURE = Buffer.from([0x50, 0x4B, 0x05, 0x06]);

// https://bitbucket.org/vinay.sajip/simple_launcher/src/2e1c7592574c4f42062fd3a5b1051ec02da4b543/launcher.c#lines-177

// typedef struct {
// DWORD sig;
// DWORD unused_disk_nos;
// DWORD unused_numrecs;
// DWORD cdsize;
// DWORD cdoffset;
// } ENDCDR;

function parseWindowsLauncher(buffer: Buffer) {
const end = buffer.lastIndexOf(ZIP_SIGNATURE);
if (end === -1) throw new Error('Invalid archive');

const cdsize = buffer.readUInt16LE(end + 12);
const cdoffset = buffer.readUInt32LE(end + 16);
const endOfShebang = end - cdsize - cdoffset;

const shebang = buffer.lastIndexOf(BUF_SHEBANG_UNIX, endOfShebang);
const line = buffer.subarray(shebang, endOfShebang).toString().trim();
return interpreter(line);
}

function interpreter(line: string) {
if (!line.startsWith(SHEBANG_UNIX)) throw new Error('Invalid shebang');
return line.substring(SHEBANG_UNIX.length);
}

export default async function shebang(path: string) {
const buffer = await fs.readFile(path);
const magic = buffer.subarray(0, SHEBANG_UNIX.length);

if (magic.compare(BUF_SHEBANG_UNIX) === 0) {
const lineEnd = buffer.indexOf('\n');
return interpreter(buffer.subarray(0, lineEnd).toString());
} else if (magic.compare(PE_MAGIC) === 0) {
return parseWindowsLauncher(buffer);
}

throw new Error('Invalid file format');
}

Loading

0 comments on commit 675f15d

Please sign in to comment.