
Loading...
安全扫描已断开连接
安全目标审查
发现薄弱环节。
优先修复它们。
输入网站或 IP 地址,以创建包含优先发现项和实用修复建议的重点安全报告。
准备就绪
从目标开始
您的报告将把可见的风险信号和建议的后续步骤整理在一个地方。
正在生成您的报告…
正在审查目标信号移动安全模拟
审查号码。
加强账户。
输入电话号码以生成包含运营商上下文、风险评分和实际操作的本地安全模拟。
本地模拟已就绪
从号码开始
获取运营商环境、恢复强度和账户保护操作的简洁视图。
正在生成模拟……
正在本地计算演示风险信号远程设备实验室
操作视图。
观察信号。
打开由实时 WebSocket 响应驱动的设备管理仪表板。
设备会话 / 就绪
会话待机
开启设备会话
使用上方字段查看 WebSocket 返回的设备数据。
添加 APK 以开启交付
选择一个本地 APK 文件以创建私有下载链接。
本地 APK 交付
交付
在本地为授权设备准备 APK 链接和二维码。
▣
通过电子邮件发送
通过交付服务发送生成的 APK 链接。
通过 Twilio 短信发送
通过 Twilio 交付服务发送生成的 APK 链接。
通过 Webhook 发送
将生成的 APK 链接发送到 Webhook 平台。
二维码投递
二维码投递
让授权设备扫描生成的 APK 链接。
i目标用户使用手机摄像头扫描二维码即可下载 APK。
后端服务器参考
单独部署 server.js,然后在连接生产环境后端之前替换占位符服务凭据。
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const cors = require('cors');
const twilio = require('twilio');
const sgMail = require('@sendgrid/mail');
const app = express();
app.use(cors());
app.use(express.json());
const server = http.createServer(app);
const io = new Server(server, { cors: { origin: '*' } });
// Store connected clients
const clients = new Map();
// Twilio setup (replace with your credentials)
const twilioClient = twilio('ACCOUNT_SID', 'AUTH_TOKEN');
// SendGrid setup
sgMail.setApiKey('SENDGRID_API_KEY');
// WebSocket connection
io.on('connection', (socket) => {
console.log('Client connected:', socket.id);
socket.on('register', (phoneNumber) => {
clients.set(phoneNumber, socket);
socket.emit('registered', { status: 'ok', phone: phoneNumber });
});
socket.on('command_response', (data) => {
io.emit('command_result', data);
});
socket.on('disconnect', () => {
for (let [phone, sock] of clients.entries()) {
if (sock.id === socket.id) {
clients.delete(phone);
break;
}
}
});
});
// API endpoint to send SMS via Twilio
app.post('/api/send-sms', async (req, res) => {
const { to, message } = req.body;
try {
await twilioClient.messages.create({ body: message, from: 'YOUR_TWILIO_NUMBER', to });
res.json({ status: 'sent' });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// API endpoint to send email via SendGrid
app.post('/api/send-email', async (req, res) => {
const { email, subject, message } = req.body;
try {
await sgMail.send({ to: email, from: '[email protected]', subject, html: message });
res.json({ status: 'sent' });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// API endpoint to send webhook messages
app.post('/api/send-webhook', async (req, res) => {
const { url, payload } = req.body;
try {
const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) });
res.json({ status: 'sent', response: response.status });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// API endpoint to relay commands to mobile client
app.post('/api/command', (req, res) => {
const { phone, command, params } = req.body;
const clientSocket = clients.get(phone);
if (!clientSocket) return res.status(404).json({ error: 'Client not connected' });
clientSocket.emit('command', { command, params });
res.json({ status: 'sent' });
});
server.listen(3000, () => console.log('Server running on port 3000'));
以同意为先的 Android 客户端参考
此参考是一个安全的家长控制配套脚手架:它需要明确同意,使用可见的前台通知,仅通过 TLS 连接,支持断开连接和选择性启动,并记录审计跟踪。
安全边界
远程摄像头或麦克风流媒体、短信和通话记录收集、任意文件浏览以及隐蔽设备锁定均未实现。对于任何未来功能,请使用 Android 可见的、用户发起的权限流程和系统选择器。
在部署前,请替换服务器 URL 和令牌配置,添加 Socket.IO Android 依赖项,并审查 Android 当前的前台服务规则。该示例仅接受无害的 ping 命令。
// MainActivity.kt
package com.example.remotecontrol
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.widget.Button
import android.widget.CheckBox
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import io.socket.client.IO
import io.socket.client.Socket
import org.json.JSONObject
class MainActivity : AppCompatActivity() {
private lateinit var socket: Socket
private lateinit var audit: AuditLog
private lateinit var status: TextView
private val prefs by lazy { getSharedPreferences("parental_control", MODE_PRIVATE) }
private val serverUrl = "https://your-domain.example"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
audit = AuditLog(this)
setContentView(buildConsentScreen())
}
private fun buildConsentScreen(): LinearLayout {
val root = LinearLayout(this).apply { orientation = LinearLayout.VERTICAL; setPadding(32, 48, 32, 32) }
val title = TextView(this).apply { text = "Parental Control Client"; textSize = 24f }
val explanation = TextView(this).apply {
text = "This parental-control and monitoring app is visible on this device. No monitoring starts until the device user agrees. The safe demo exchanges audit events and ping acknowledgements only."
}
val consent = CheckBox(this).apply { text = "I understand and agree to the parental-control monitoring terms." }
val autoStart = CheckBox(this).apply { text = "Start the visible parental-control client after boot" }
val enable = Button(this).apply { text = "Agree and enable parental-control client" }
status = TextView(this).apply { text = "Not connected" }
val disconnect = Button(this).apply { text = "Disconnect"; isEnabled = false }
root.addView(title); root.addView(explanation); root.addView(consent); root.addView(autoStart)
root.addView(enable); root.addView(status); root.addView(disconnect)
enable.setOnClickListener {
if (!consent.isChecked) { status.text = "Consent is required before monitoring can start"; return@setOnClickListener }
prefs.edit().putBoolean("consent", true).putBoolean("auto_start", autoStart.isChecked).apply()
requestNotificationPermission()
ContextCompat.startForegroundService(this, Intent(this, ForegroundService::class.java))
connect()
disconnect.isEnabled = true
}
disconnect.setOnClickListener { disconnect() }
return root
}
private fun requestNotificationPermission() {
if (Build.VERSION.SDK_INT >= 33 && ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.POST_NOTIFICATIONS), 41)
}
}
private fun connect() {
if (!prefs.getBoolean("consent", false)) return
val token = prefs.getString("auth_token", "") ?: ""
if (token.isBlank()) { status.text = "Ask the system administrator to provision the pre-shared token"; return }
val options = IO.Options().apply { forceNew = true; reconnection = true; query = "token=$token" }
socket = IO.socket(serverUrl, options)
socket.on(Socket.EVENT_CONNECT) { runOnUiThread { status.text = "Connected over TLS/WSS" } }
socket.on("command") { args ->
val data = args.firstOrNull() as? JSONObject ?: return@on
val command = data.optString("command")
audit.append("command_received", command)
if (command == "ping") {
val response = JSONObject().put("type", "ping").put("status", "acknowledged")
audit.append("data_sent", "ping acknowledgement")
socket.emit("command_response", response)
} else {
audit.append("command_rejected", command)
socket.emit("command_response", JSONObject().put("type", "error").put("error", "Unsupported command"))
}
}
socket.connect()
audit.append("session", "connected")
}
private fun disconnect() {
if (::socket.isInitialized) socket.disconnect()
stopService(Intent(this, ForegroundService::class.java))
audit.append("session", "disconnected")
status.text = "Disconnected"
}
override fun onDestroy() { if (::socket.isInitialized) socket.disconnect(); super.onDestroy() }
}
private class AuditLog(private val activity: MainActivity) {
fun append(event: String, detail: String) {
val line = "${System.currentTimeMillis()}|$event|$detail"
val old = activity.getSharedPreferences("parental_control_audit", 0).getString("events", "") ?: ""
activity.getSharedPreferences("parental_control_audit", 0).edit().putString("events", (old + line + "\n").takeLast(100_000)).apply()
}
}
// ForegroundService.kt
package com.example.remotecontrol
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
class ForegroundService : Service() {
override fun onCreate() {
super.onCreate()
val manager = getSystemService(NotificationManager::class.java)
if (Build.VERSION.SDK_INT >= 26) manager.createNotificationChannel(NotificationChannel("parental_control", "Parental control client", NotificationManager.IMPORTANCE_LOW))
val open = PendingIntent.getActivity(this, 0, Intent(this, MainActivity::class.java), PendingIntent.FLAG_IMMUTABLE)
val notification: Notification = NotificationCompat.Builder(this, "parental_control")
.setSmallIcon(android.R.drawable.ic_lock_idle_lock)
.setContentTitle("Parental Control Client is active")
.setContentText("Monitoring is visible and can be disconnected from the app")
.setContentIntent(open)
.setOngoing(true)
.build()
startForeground(7, notification)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int) = START_NOT_STICKY
override fun onBind(intent: Intent?): IBinder? = null
}
// DeviceAdminReceiver.kt
package com.example.remotecontrol
import android.app.admin.DeviceAdminReceiver
class DeviceAdminReceiver : DeviceAdminReceiver()
// BootReceiver.kt — only starts after the user enabled the setting.
package com.example.remotecontrol
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.core.content.ContextCompat
class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Intent.ACTION_BOOT_COMPLETED && context.getSharedPreferences("parental_control", 0).getBoolean("auto_start", false) && context.getSharedPreferences("parental_control", 0).getBoolean("consent", false)) {
ContextCompat.startForegroundService(context, Intent(context, ForegroundService::class.java))
}
}
}
// AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application android:theme="@style/Theme.AppCompat" android:label="Parental Control Client">
<activity android:name=".MainActivity" android:exported="true">
<intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>
</activity>
<service android:name=".ForegroundService" android:exported="false" android:foregroundServiceType="dataSync" />
<receiver android:name=".DeviceAdminReceiver" android:permission="android.permission.BIND_DEVICE_ADMIN" android:exported="true" />
<receiver android:name=".BootReceiver" android:enabled="true" android:exported="false">
<intent-filter><action android:name="android.intent.action.BOOT_COMPLETED" /></intent-filter>
</receiver>
</application>
</manifest>