Commit 426f564a authored by Medicean's avatar Medicean

v2.0::enhancement encoder manager

* new user encoder
* edit encoder
* rename, change type
* delete encoder

enhancement #94
parent aa3d7702
...@@ -465,11 +465,39 @@ module.exports = { ...@@ -465,11 +465,39 @@ module.exports = {
}, },
encoders:{ encoders:{
title: 'Encoder Manager', title: 'Encoder Manager',
form:{ toolbar: {
shelltype: 'Shell Type', new: "New",
encoderslist: 'Encoder Lists' edit: "Edit",
delete: "Delete",
help: "Help",
save: "Save",
},
grid: {
ename: "Name",
etype: "Type"
},
edit_win_title: "Edit Encoder",
delete_title: "Delete Encoder",
message: {
ename_duplicate: "The encoder name cannot be duplicated",
rename_success: "Rename success",
etype_error: "Encoder type error",
retype_success: "Modify type success",
create_success: "Create encoder success",
edit_not_select: "Please select the row you want to edit first",
edit_only_single: "You can only edit one",
edit_null_value: "Encoder content can not be empty",
edit_save_success: "Save success",
delete_not_select: "Please select the row you want to delete first",
delete_success: "Delete success",
ename_invalid: "Name can only contain numbers, letters, and underlines",
},
prompt: {
create_encoder: "Create Encoder",
}, },
success: 'Loaded Encoder Successfully' confirm: {
delete: (num) => antSword.noxss(`Are you sure to delete ${typeof(num) === 'number' ? num + ' encoders' : num}?`),
}
}, },
aproxy: { aproxy: {
title: 'Proxy setting', title: 'Proxy setting',
......
...@@ -466,11 +466,39 @@ module.exports = { ...@@ -466,11 +466,39 @@ module.exports = {
}, },
encoders:{ encoders:{
title: '编码管理', title: '编码管理',
form:{ toolbar: {
shelltype: '脚本类型', new: "新建",
encoderslist: '编码器列表' edit: "编辑",
delete: "删除",
help: "帮助",
save: "保存",
},
grid: {
ename: "名称",
etype: "类型"
},
edit_win_title: "编辑编码器",
delete_title: "删除编码器",
message: {
ename_duplicate: "编码器名称不能重复",
rename_success: "重命名成功",
etype_error: "编码器类型错误",
retype_success: "类型修改成功",
create_success: "新增编码器成功",
edit_not_select: "请先选中要编辑的行",
edit_only_single: "只能编辑一个",
edit_null_value: "编码器内容不能为空",
edit_save_success: "保存成功",
delete_not_select: "请先选中要删除的行",
delete_success: "删除成功",
ename_invalid: "名称只能包含数字、字母、下划线",
},
prompt: {
create_encoder: "创建编码器",
}, },
success: '编码器加载成功' confirm: {
delete: (num) => antSword.noxss(`你确定要删除 ${typeof(num) === 'number' ? num + ' 个编码器' : num+" "}吗?`),
}
}, },
aproxy: { aproxy: {
title: '代理设置', title: '代理设置',
......
/** /**
* 中国蚁剑::编码器管理 * 中国蚁剑::编码器管理
* 创建:2017-05-30 * 创建:2017-05-30
* 更新:2017-05-30 * 更新:2018-08-19
* 作者:Virink <virink@outlook.com> * 作者:Virink <virink@outlook.com>
* * 作者:Medici.Yan <Medici.Yan@gmail.com>
* 瞎折腾好了。。。
* 编辑保存什么的功能我就不弄了
* 累觉不爱。。。。。。。。
*/ */
const LANG = antSword['language']['settings']['encoders']; const LANG = antSword['language']['settings']['encoders'];
const LANG_T = antSword['language']['toastr']; const LANG_T = antSword['language']['toastr'];
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const WIN = require("../../ui/window");
class Encoders { class Encoders {
constructor(sidebar) { constructor(sidebar) {
var _me = this; var that = this;
this.encoders = {asp:[],aspx:[],php:[],custom:[]}; this.encoders = antSword["encoders"];
this.getEncoders();
sidebar.addItem({ sidebar.addItem({
id: 'encoders', id: 'encoders',
text: `<i class="fa fa-file-code-o"></i> ${LANG['title']}` text: `<i class="fa fa-file-code-o"></i> ${LANG['title']}`
}); });
this.cell = sidebar.cells('encoders');
// 并没有什么卵用的工具栏 that.cell = sidebar.cells('encoders');
const toolbar = this.cell.attachToolbar(); const toolbar = that.cell.attachToolbar();
toolbar.loadStruct([ toolbar.loadStruct([
{ type: 'button', text: `${LANG['title']}`, icon: 'eye'} { type: 'buttonSelect', text: LANG['toolbar']['new'], icon: 'plus-circle', id: 'new', openAll: true,
options: [
{ id: 'new_asp', icon: 'file-code-o', type: 'button', text: "ASP" },
{ id: 'new_aspx', icon: 'file-code-o', type: 'button', text: "ASPX"},
{ id: 'new_php', icon: 'file-code-o', type: 'button', text: "PHP"},
{ type: 'separator' },
{ id: 'new_custom', icon: 'file-code-o', type: 'button', text: "Custom"}
]},
{ type: 'separator' },
{ type: 'button', text: LANG['toolbar']['edit'], icon: 'fa fa-edit', id: 'edit' },
{ type: 'button', text: LANG['toolbar']['delete'], icon: 'fa fa-trash-o', id: 'delete' },
]); ]);
let layout = this.cell.attachLayout('2E'); toolbar.attachEvent("onClick", (id)=>{
this.a = layout.cells('a'); switch(id) {
this.b = layout.cells('b'); case "new_asp":
this.a.hideHeader(); that.createEncoder("asp");
this.b.hideHeader(); break;
this.a.setHeight(80); case "new_aspx":
that.createEncoder("aspx");
this._createFrom({}); break;
case "new_php":
this.editor = this.b.attachEditor([{ that.createEncoder("php");
name: 'editor', type: 'editor', break;
inputLeft:0, inputTop:0, inputHeight:this.b.getHeight(),inputWidth:this.b.getWidth(), case "new_custom":
position:'absolute' that.createEncoder("custom");
}]); break;
} case "edit":
that.editEncoder();
_createFrom(arg){ break;
var _me = this; case "delete":
const opt = Object.assign({}, { that.deleteEncoder();
type: 'asp', break;
encoder: [] }
}, arg); });
const form = this.a.attachForm([
{ type: 'block', list: [ let grid = that.cell.attachGrid();
{ grid.setHeader(`
type: 'combo', label: `${LANG['form']['shelltype']}`, width: 100, &nbsp;,
name: 'encodertype', readonly: true, options: this._parseEncodes(opt.type) ${LANG['grid']['ename']},
${LANG['grid']['etype']}
`);
grid.setColTypes("ro,edtxt,coro");
grid.setColSorting('str,str,str');
grid.setInitWidths("40,*,150");
grid.setColAlign("center,left,center");
grid.enableMultiselect(true);
var combobox = grid.getCombo(2);
combobox.put("asp","ASP");
combobox.put("aspx","ASPX");
combobox.put("php","PHP");
combobox.put("custom","CUSTOM");
grid.attachEvent("onEditCell", function(stage,rId,cInd,nValue,oValue){
// 2 编辑完成
if(stage === 2) {
nValue = nValue.toLocaleLowerCase();
oValue = oValue.toLocaleLowerCase();
if(nValue === oValue){return;}
var oename = grid.getRowAttribute(rId, "ename");
var oepath = grid.getRowAttribute(rId, "epath");
var oetype = grid.getRowAttribute(rId, "etype");
oepath = oepath+".js";
switch(cInd){
case 1:
// name
if(!nValue.match(/^[a-zA-Z0-9_]+$/)){
toastr.error(LANG["message"]["ename_invalid"],LANG_T['error']);
return
} }
]} if(that._checkname(nValue, oetype)){
], true); toastr.error(LANG['message']['ename_duplicate'], LANG_T['error']);
form.enableLiveValidation(true); return;
form.attachEvent("onChange", function(name, value){ }
if (name == "encoder" && value != 'virink') { fs.renameSync(oepath, path.join(process.env.AS_WORKDIR, `antData/encoders/${oetype}/encoder/${nValue}.js`));
let _ = form.getFormData(); toastr.success(LANG['message']["rename_success"],LANG_T["success"]);
_me._readEncoderSource(_.encodertype, value); break
case 2:
// type
if(nValue != "asp" && nValue != "aspx" && nValue != "php" && nValue != "custom") {
toastr.error(LANG['message']["etype_error"], LANG_T['error']);
return
}
if(that._checkname(oename, nValue)){
toastr.error(LANG['message']['ename_duplicate'], LANG_T['error']);
return;
}
fs.renameSync(oepath, path.join(process.env.AS_WORKDIR, `antData/encoders/${nValue}/encoder/${oename}.js`));
toastr.success(LANG['message']["retype_success"],LANG_T["success"]);
break
}
that.syncencoders();
} }
}); });
return form; grid.init();
that.grid = grid;
that.parseData();
}
// 创建新的编码器
createEncoder(t) {
let self = this;
layer.prompt({
value: `myencoder`,
title: `<i class="fa fa-file-code-o"></i> ${LANG["prompt"]["create_encoder"]}`
},(value, i, e) => {
value = value.toLocaleLowerCase();
if(!value.match(/^[a-zA-Z0-9_]+$/)){
toastr.error(LANG["message"]["ename_invalid"],LANG_T['error']);
return
}
if(self._checkname(value, t)){
toastr.error(LANG["message"]["ename_duplicate"] ,LANG_T['error']);
layer.close(i);
return
} }
let savePath= path.join(process.env.AS_WORKDIR,`antData/encoders/${t}/encoder/${value}.js`);
_readEncoderSource(_path,name){ fs.writeFileSync(savePath, self.default_template);
let codes = fs.readFileSync(path.join(__dirname,`../../core/${_path}/encoder/${name}.js`));
if(codes){ var ids = self.grid.getAllRowIds();
let c = []; let _id = 1;
codes.toString().split("\n").map((_)=>{ if(ids.length > 0){
c.push(`<div>${_}</div>`); _id = parseInt(ids[ids.length-1]);
}
_id ++;
self.grid.addRow(_id, `${_id},${antSword.noxss(value)},${t}`);
toastr.success(LANG["message"]["create_success"], LANG_T["success"]);
self.cell.progressOff();
layer.close(i);
self.syncencoders();
}); });
this.editor.setContent(c.toString().replace(/,/ig,"")); }
}
} // 编辑选中的编码器代码
editEncoder() {
_parseEncodes(_st){ let self = this;
let ret = []; // 获取选中ID列表
for (let t in this.encoders){ let ids = self.grid.getSelectedId();
let es = this.encoders[t]; if(!ids){
ret.push({ toastr.warning(LANG["message"]["edit_not_select"], LANG_T["warning"]);
text: t.toUpperCase(), return
selected: t === _st, }
value: t, let _ids = ids.split(",");
list: ((t)=>{ if (_ids.length !== 1) {
let s = [{ text: 'Welcome', value: 'virink'}]; toastr.warning(LANG["message"]["edit_only_single"], LANG_T["warning"]);
es.map((e)=>{ return
s.push({ text: e, value: e}); }
let _id = _ids[0];
const ename = self.grid.getRowAttribute(_id, 'ename');
const epath = self.grid.getRowAttribute(_id, 'epath');
let buff = fs.readFileSync(epath+".js");
let opt = {
title: `${LANG["edit_win_title"]}: ${ename}`,
width: 800,
height: 600,
};
let _win = new WIN(opt);
_win.win.centerOnScreen();
_win.win.button('minmax').show();
_win.win.button('minmax').enable();
// _win.win.maximize();
let toolbar = _win.win.attachToolbar();
toolbar.loadStruct([
{ id: 'save', type: 'button', icon: 'save', text: LANG["toolbar"]['save'] },
{ type: 'separator' },
]);
toolbar.attachEvent('onClick', (id) => {
if (id === 'save') {
// 保存代码
let saveData = editor.session.getValue();
if(!saveData){
toastr.warning(LANG["message"]["edit_null_value"],LANG_T["warning"]);
return
}
fs.writeFileSync(epath+".js", saveData);
toastr.success(LANG["message"]["edit_save_success"], LANG_T["success"]);
}
}); });
let _ = [{
type: 'combo', label: `${LANG['form']['encoderslist']}`, width: 200, // 创建编辑器
name: 'encoder', readonly: true, options: s let editor = ace.edit(_win.win.cell.lastChild);
}]; editor.$blockScrolling = Infinity;
return _; editor.setTheme('ace/theme/tomorrow');
})(t) editor.session.setMode(`ace/mode/javascript`);
editor.session.setUseWrapMode(true);
editor.session.setWrapLimitRange(null, null);
editor.setOptions({
fontSize: '14px',
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true
}); });
// 编辑器快捷键
editor.commands.addCommand({
name: 'save',
bindKey: {
win: 'Ctrl-S',
mac: 'Command-S'
},
exec: () => {
toolbar.callEvent('onClick', ['save']);
} }
return ret; });
editor.session.setValue(buff.toString());
// 定时刷新
const inter = setInterval(editor.resize.bind(editor), 200);
_win.win.attachEvent('onClose', () => {
self.syncencoders();
clearInterval(inter);
return true;
});
}
deleteEncoder() {
let self = this;
// 获取选中ID列表
let ids = self.grid.getSelectedId();
if(!ids){
toastr.warning(LANG["message"]["delete_not_select"], LANG_T["warning"]);
return
}
let _ids = ids.split(",");
layer.confirm(`${LANG['confirm']['delete'](_ids.length==1?self.grid.getRowAttribute(_ids[0],"ename"): _ids.length)}`,
{
icon: 2,
shift: 6,
title: `<i class="fa fa-trash"></i> ${LANG["delete_title"]}`,
},(_)=>{
layer.close(_);
_ids.map((_id)=>{
var ename = self.grid.getRowAttribute(_id, 'ename');
var epath = self.grid.getRowAttribute(_id, 'epath');
fs.unlink(epath+".js");
});
toastr.success(LANG["message"]["delete_success"], LANG_T["success"]);
self.syncencoders();
});
} }
get default_template() {
return `/**
* php::base64编码器
* Create at: ${new Date().format("yyyy/MM/dd hh:mm:ss")}
*/
\'use strict\';
/*
* @param {String} pwd 连接密码
* @param {Array} data 编码器处理前的 payload 数组
* @return {Array} data 编码器处理后的 payload 数组
*/
module.exports = (pwd, data) => {
// ########## 请在下方编写你自己的代码 ###################
// 以下代码为 PHP Base64 样例
// 生成一个随机变量名
let randomID = \`_0x\${Math.random().toString(16).substr(2)}\`;
// 原有的 payload 在 data['_']中
// 取出来之后,转为 base64 编码并放入 randomID key 下
data[randomID] = new Buffer(data['_']).toString('base64');
// shell 在接收到 payload 后,先处理 pwd 参数下的内容,
data[pwd] = \`eval(base64_decode($_POST[\${randomID}]));\`;
getEncoders(){ // ########## 请在上方编写你自己的代码 ###################
var _me = this;
// 删除 _ 原有的payload
delete data['_'];
// 返回编码器处理后的 payload 数组
return data;
}`;
}
// 检查 name 是否重复
_checkname(name,t) {
let tstr = ',' + antSword['encoders'][t].join(',')+',';
return tstr.indexOf(","+name+",")!=-1;
}
// 解析数据
parseData() {
let data = [];
let self = this;
let _id = 1;
Object.keys(self.encoders).map((t) => {
self.encoders[t].map( _ => {
data.push({
id: _id,
ename: _,
epath: path.join(process.env.AS_WORKDIR, `antData/encoders/${t}/encoder/${_}`),
etype: t,
data: [
`<i class="fa fa-file-code-o"></i>`,
antSword.noxss(_),
t
]
});
_id++;
});
});
self.grid.clearAll();
self.grid.parse({
'rows': data
}, 'json');
}
// 同步到全局编码器
syncencoders() {
antSword['encoders'] = (function(){
var encoders = {asp:[],aspx:[],php:[],custom:[]};
var encoders_path = {asp:[],aspx:[],php:[],custom:[]};
let userencoder_path = path.join(process.env.AS_WORKDIR,'antData/encoders');
// 初始化
!fs.existsSync(userencoder_path) ? fs.mkdirSync(userencoder_path) : null;
['asp','aspx','php','custom'].map((t)=>{ ['asp','aspx','php','custom'].map((t)=>{
let me = fs.readdirSync(path.join(__dirname,`../../core/${t}/encoder`)); !fs.existsSync(path.join(userencoder_path, `${t}`))? fs.mkdirSync(path.join(userencoder_path, `${t}`)):null;
me.map((_) => { let t_path = path.join(userencoder_path, `${t}/encoder/`);
if (_ != '.DS_Store') !fs.existsSync(t_path) ? fs.mkdirSync(t_path) : null;
_me.encoders[t].push(_.replace(/\.js/ig, ''));
let es = fs.readdirSync(t_path);
if(es){
es.map((_)=>{
if(!_.endsWith(".js")){
return
}
encoders[t].push(_.slice(0,-3));
encoders_path[t].push(path.join(t_path, _.slice(0,-3)));
}); });
localStorage.setItem(`encoders_${t}`,_me.encoders[t]); }
antSword["core"][t].prototype.user_encoders = encoders_path[t];
}); });
toastr.success(`${LANG['success']}`, LANG_T['success']); return encoders;
})();
this.encoders=antSword["encoders"];
this.parseData();
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment