Files
workphone-sdk/sdk/agent/hook/system_control.js

343 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* system_control.js - Frida系统控制扩展
* 功能截图、UI导航、页面检测、输入模拟
* 通过Frida直接调用Android内部API不依赖ADB
*/
'use strict';
rpc.exports = {
// ==================== 截图 ====================
takeScreenshot: function (params) {
/**
* 通过Android Shell命令截图并返回base64
* 使用Runtime.exec执行screencap需要Root或同进程权限
*/
try {
return Java.performNow(function () {
var savePath = (params && params.path) || '/sdcard/frida_screenshot.png';
var Runtime = Java.use('java.lang.Runtime');
var runtime = Runtime.getRuntime();
// 方案1: 直接用screencap命令
var process = runtime.exec(['sh', '-c', 'screencap -p ' + savePath]);
process.waitFor();
// 读取文件并转base64
var File = Java.use('java.io.File');
var file = File.$new(savePath);
if (!file.exists()) {
return { success: false, error: '截图文件不存在' };
}
var fileSize = file.length();
var FileInputStream = Java.use('java.io.FileInputStream');
var fis = FileInputStream.$new(file);
var bytes = Java.array('byte', new Array(parseInt(fileSize)).fill(0));
fis.read(bytes);
fis.close();
var Base64 = Java.use('android.util.Base64');
var b64 = Base64.encodeToString(bytes, 2); // NO_WRAP
return {
success: true,
path: savePath,
size: parseInt(fileSize),
base64_length: b64.length,
base64: b64.substring(0, 200) + '...(truncated)',
full_base64: b64,
};
});
} catch (e) {
return { success: false, error: String(e) };
}
},
takeScreenshotToFile: function (params) {
/**
* 截图保存到指定路径不返回base64避免传输大数据
*/
try {
return Java.performNow(function () {
var savePath = (params && params.path) || '/sdcard/frida_sc_' + Date.now() + '.png';
var Runtime = Java.use('java.lang.Runtime');
var runtime = Runtime.getRuntime();
var process = runtime.exec(['sh', '-c', 'screencap -p ' + savePath]);
process.waitFor();
var File = Java.use('java.io.File');
var file = File.$new(savePath);
if (file.exists()) {
return { success: true, path: savePath, size: parseInt(file.length()) };
}
return { success: false, error: '截图失败' };
});
} catch (e) {
return { success: false, error: String(e) };
}
},
// ==================== 页面检测 ====================
getCurrentActivity: function () {
/**
* 获取当前前台Activity名称
*/
try {
return Java.performNow(function () {
var ActivityThread = Java.use('android.app.ActivityThread');
var currentApp = ActivityThread.currentApplication();
var activities = [];
// 遍历所有Activity
Java.choose('android.app.Activity', {
onMatch: function (activity) {
if (!activity.isFinishing() && !activity.isDestroyed()) {
activities.push({
class: activity.getClass().getName(),
title: activity.getTitle() ? activity.getTitle().toString() : '',
visible: activity.hasWindowFocus(),
});
}
},
onComplete: function () {},
});
return {
success: true,
activities: activities,
foreground: activities.length > 0 ? activities[activities.length - 1].class : 'unknown',
};
});
} catch (e) {
return { success: false, error: String(e) };
}
},
// ==================== UI导航 ====================
navigateToChat: function (params) {
/**
* 导航到指定聊天窗口
* 通过微信内部Intent跳转
*/
try {
return Java.performNow(function () {
var wxid = (params && params.wxid) || 'filehelper';
var ctx = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
var Intent = Java.use('android.content.Intent');
var Uri = Java.use('android.net.Uri');
// 微信内部跳转到聊天页面
var intent = Intent.$new();
intent.setClassName('com.tencent.mm', 'com.tencent.mm.ui.chatting.ChattingUI');
intent.putExtra('Chat_User', wxid);
intent.addFlags(0x10000000); // FLAG_ACTIVITY_NEW_TASK
ctx.startActivity(intent);
return { success: true, navigated_to: 'ChattingUI', wxid: wxid };
});
} catch (e) {
return { success: false, error: String(e) };
}
},
navigateToContacts: function () {
/**
* 导航到通讯录页面
*/
try {
return Java.performNow(function () {
var ctx = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
var Intent = Java.use('android.content.Intent');
var intent = Intent.$new();
intent.setClassName('com.tencent.mm', 'com.tencent.mm.ui.LauncherUI');
intent.putExtra('LauncherUI.From.Shortcut.Msg', true);
intent.addFlags(0x10000000);
ctx.startActivity(intent);
return { success: true, navigated_to: 'Contacts' };
});
} catch (e) {
return { success: false, error: String(e) };
}
},
navigateToMe: function () {
/**
* 导航到"我"页面
*/
try {
return Java.performNow(function () {
var ctx = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
var Intent = Java.use('android.content.Intent');
var intent = Intent.$new();
intent.setClassName('com.tencent.mm', 'com.tencent.mm.ui.LauncherUI');
intent.addFlags(0x10000000);
ctx.startActivity(intent);
return { success: true, navigated_to: 'Me' };
});
} catch (e) {
return { success: false, error: String(e) };
}
},
navigateToMoments: function () {
/**
* 导航到朋友圈
*/
try {
return Java.performNow(function () {
var ctx = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
var Intent = Java.use('android.content.Intent');
var intent = Intent.$new();
intent.setClassName('com.tencent.mm', 'com.tencent.mm.plugin.sns.ui.SnsTimeLineUI');
intent.addFlags(0x10000000);
ctx.startActivity(intent);
return { success: true, navigated_to: 'Moments' };
});
} catch (e) {
return { success: false, error: String(e) };
}
},
// ==================== 输入模拟 ====================
simulateTap: function (params) {
/**
* 模拟点击通过shell input tap
*/
try {
return Java.performNow(function () {
var x = (params && params.x) || 0;
var y = (params && params.y) || 0;
var Runtime = Java.use('java.lang.Runtime');
var runtime = Runtime.getRuntime();
var process = runtime.exec(['sh', '-c', 'input tap ' + x + ' ' + y]);
process.waitFor();
return { success: true, tapped: { x: x, y: y } };
});
} catch (e) {
return { success: false, error: String(e) };
}
},
simulateInput: function (params) {
/**
* 模拟文本输入
*/
try {
return Java.performNow(function () {
var text = (params && params.text) || '';
var Runtime = Java.use('java.lang.Runtime');
var runtime = Runtime.getRuntime();
// 需要对特殊字符转义
var escaped = text.replace(/ /g, '%s').replace(/'/g, "\\'");
var process = runtime.exec(['sh', '-c', "input text '" + escaped + "'"]);
process.waitFor();
return { success: true, input: text };
});
} catch (e) {
return { success: false, error: String(e) };
}
},
simulateKeyEvent: function (params) {
/**
* 模拟按键事件(返回键=4, Home=3, 回车=66
*/
try {
return Java.performNow(function () {
var keycode = (params && params.keycode) || 4;
var Runtime = Java.use('java.lang.Runtime');
var runtime = Runtime.getRuntime();
var process = runtime.exec(['sh', '-c', 'input keyevent ' + keycode]);
process.waitFor();
return { success: true, keycode: keycode };
});
} catch (e) {
return { success: false, error: String(e) };
}
},
// ==================== 文件操作 ====================
readFileBase64: function (params) {
/**
* 读取手机上的文件并返回base64
*/
try {
return Java.performNow(function () {
var filePath = (params && params.path) || '';
if (!filePath) return { success: false, error: '缺少path参数' };
var File = Java.use('java.io.File');
var file = File.$new(filePath);
if (!file.exists()) return { success: false, error: '文件不存在: ' + filePath };
var fileSize = file.length();
if (fileSize > 5 * 1024 * 1024) {
return { success: false, error: '文件太大(>5MB): ' + fileSize };
}
var FileInputStream = Java.use('java.io.FileInputStream');
var fis = FileInputStream.$new(file);
var bytes = Java.array('byte', new Array(parseInt(fileSize)).fill(0));
fis.read(bytes);
fis.close();
var Base64 = Java.use('android.util.Base64');
var b64 = Base64.encodeToString(bytes, 2);
return { success: true, path: filePath, size: parseInt(fileSize), base64: b64 };
});
} catch (e) {
return { success: false, error: String(e) };
}
},
listFiles: function (params) {
/**
* 列出目录下的文件
*/
try {
return Java.performNow(function () {
var dirPath = (params && params.path) || '/sdcard/';
var File = Java.use('java.io.File');
var dir = File.$new(dirPath);
if (!dir.exists() || !dir.isDirectory()) {
return { success: false, error: '目录不存在: ' + dirPath };
}
var files = dir.listFiles();
var result = [];
var len = files ? files.length : 0;
for (var i = 0; i < Math.min(len, 50); i++) {
result.push({
name: files[i].getName(),
is_dir: files[i].isDirectory(),
size: files[i].isFile() ? parseInt(files[i].length()) : 0,
});
}
return { success: true, path: dirPath, count: len, files: result };
});
} catch (e) {
return { success: false, error: String(e) };
}
},
// ==================== 连接状态 ====================
getConnectionStatus: function () {
return {
success: true,
mode: 'frida_wireless',
transport: 'tcp',
pid: Process.id,
arch: Process.arch,
timestamp: Date.now(),
};
},
};