mirror of https://github.com/n1nj4sec/pupy.git
New (psutil based) ps module
This commit is contained in:
parent
82da382ff1
commit
f8527fe339
|
@ -1,44 +1,192 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from pupylib.PupyModule import *
|
from pupylib.PupyModule import *
|
||||||
from pupylib.utils.rpyc_utils import obtain
|
from pupylib.utils.rpyc_utils import obtain
|
||||||
|
from pupylib.utils.term import terminal_size, colorize
|
||||||
from modules.lib.utils.shell_exec import shell_exec
|
from modules.lib.utils.shell_exec import shell_exec
|
||||||
|
import logging
|
||||||
|
|
||||||
__class_name__="PsModule"
|
__class_name__="PsModule"
|
||||||
|
|
||||||
|
ADMINS = ('NT AUTHORITY\SYSTEM', 'root')
|
||||||
|
|
||||||
|
def gen_columns(record, colinfo):
|
||||||
|
columns = {}
|
||||||
|
|
||||||
|
columns['name'] = record.get('name') or '?'
|
||||||
|
columns['cmdline'] = ' '.join([
|
||||||
|
x for x in record['cmdline'][1:] if x.strip()
|
||||||
|
]) if 'cmdline' in record else ''
|
||||||
|
columns['exe'] = record.get('exe') or '{{{}}}'.format(columns['name'])
|
||||||
|
columns['username'] = record.get('username') or ''
|
||||||
|
cpu = record.get('cpu_percent')
|
||||||
|
columns['cpu_percent'] = '{:3}%'.format(int(cpu)) if cpu is not None else ' '*4
|
||||||
|
mem = record.get('memory_percent')
|
||||||
|
columns['memory_percent'] = '{:3}%'.format(int(mem)) if mem is not None else ' '*4
|
||||||
|
|
||||||
|
if colinfo:
|
||||||
|
columns['username'] = '{{:{}}}'.format(colinfo['username']).format(columns['username'])
|
||||||
|
columns['pid'] = '{{:{}}}'.format(colinfo['pid']).format(record['pid'])
|
||||||
|
else:
|
||||||
|
columns['pid'] = '{}'.format(parent)
|
||||||
|
|
||||||
|
return columns
|
||||||
|
|
||||||
|
def gen_output_line(columns, info, record, width):
|
||||||
|
cpu = record.get('cpu_percent') or 0
|
||||||
|
mem = record.get('memory_percent') or 0
|
||||||
|
|
||||||
|
if record.get('self'):
|
||||||
|
color = "green"
|
||||||
|
elif cpu > 70 or mem > 50:
|
||||||
|
color = "red"
|
||||||
|
elif record.get('username') in ADMINS:
|
||||||
|
if record.get('connections'):
|
||||||
|
color = "magenta"
|
||||||
|
else:
|
||||||
|
color = "yellow"
|
||||||
|
elif record.get('connections'):
|
||||||
|
color = "cyan"
|
||||||
|
elif not record.get('same_user'):
|
||||||
|
color = "grey"
|
||||||
|
else:
|
||||||
|
color = None
|
||||||
|
|
||||||
|
template = ' '.join('{{{}}}'.format(x) for x in info)
|
||||||
|
output = template.format(**columns)
|
||||||
|
if width:
|
||||||
|
output = output[:width]
|
||||||
|
|
||||||
|
if color:
|
||||||
|
output = colorize(output, color)
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
def print_pstree(fout, parent, tree, data,
|
||||||
|
prefix='', indent='', width=80, colinfo={},
|
||||||
|
info=['exe', 'cmdline'], hide=[],
|
||||||
|
first=False):
|
||||||
|
if parent in data:
|
||||||
|
data[parent]['pid'] = parent
|
||||||
|
columns = gen_columns(data[parent], colinfo)
|
||||||
|
|
||||||
|
if ( columns['name'] in hide ) or ( columns['exe'] in hide ) or ( parent in hide ):
|
||||||
|
return
|
||||||
|
|
||||||
|
columns['prefix'] = prefix
|
||||||
|
|
||||||
|
before_tree = [ x for x in info if x in ('cpu_percent', 'memory_percent', 'username') ]
|
||||||
|
after_tree = [ x for x in info if x in ('exe', 'name', 'cmdline') ]
|
||||||
|
|
||||||
|
outcols = [ 'pid' ] + before_tree + [ 'prefix' ] + after_tree
|
||||||
|
|
||||||
|
fout.write(gen_output_line(columns, outcols, data[parent], width)+'\n')
|
||||||
|
|
||||||
|
if parent not in tree:
|
||||||
|
return
|
||||||
|
|
||||||
|
children = tree[parent][:-1]
|
||||||
|
|
||||||
|
for child in children:
|
||||||
|
print_pstree(
|
||||||
|
fout, child, tree, data,
|
||||||
|
prefix=indent+('┌' if first else '├'), indent=indent + '│ ', width=width,
|
||||||
|
colinfo=colinfo, info=info, hide=hide
|
||||||
|
)
|
||||||
|
|
||||||
|
child = tree[parent][-1]
|
||||||
|
print_pstree(
|
||||||
|
fout, child, tree, data,
|
||||||
|
prefix=indent+'└', indent=indent + ' ',
|
||||||
|
width=width, colinfo=colinfo,
|
||||||
|
info=info, hide=hide
|
||||||
|
)
|
||||||
|
|
||||||
|
def print_ps(fout, data, width=80, colinfo={},
|
||||||
|
info=['exe', 'cmdline'], hide=[]):
|
||||||
|
|
||||||
|
outcols = [ 'pid' ] + [
|
||||||
|
x for x in info if x in ('cpu_percent', 'memory_percent', 'username', 'exe', 'name', 'cmdline')
|
||||||
|
]
|
||||||
|
|
||||||
|
for process in sorted(data):
|
||||||
|
data[process]['pid'] = process
|
||||||
|
columns = gen_columns(data[process], colinfo)
|
||||||
|
|
||||||
|
if ( columns['name'] in hide ) or ( columns['exe'] in hide ) or ( process in hide ):
|
||||||
|
continue
|
||||||
|
|
||||||
|
fout.write(gen_output_line(columns, outcols, data[process], width)+'\n')
|
||||||
|
|
||||||
|
|
||||||
@config(cat="admin")
|
@config(cat="admin")
|
||||||
class PsModule(PupyModule):
|
class PsModule(PupyModule):
|
||||||
""" list processes """
|
""" list processes """
|
||||||
|
|
||||||
dependencies = {
|
dependencies = [ 'pupyps' ]
|
||||||
'windows': ['pupwinutils.processes']
|
|
||||||
}
|
|
||||||
|
|
||||||
def init_argparse(self):
|
def init_argparse(self):
|
||||||
self.arg_parser = PupyArgumentParser(prog="ps", description=self.__doc__)
|
self.arg_parser = PupyArgumentParser(prog="ps", description=self.__doc__)
|
||||||
self.arg_parser.add_argument('--all', '-a', action='store_true', help='more info')
|
self.arg_parser.add_argument('--tree', '-t', action='store_true', help='draw tree')
|
||||||
|
self.arg_parser.add_argument('-i', '--info', action='store_true', help='print more info')
|
||||||
|
self.arg_parser.add_argument('-x', '--hide', nargs='+', default=[], help='hide processes by pid/name/exe')
|
||||||
|
self.arg_parser.add_argument('-a', '--all', action='store_true', help='show kthread')
|
||||||
|
self.arg_parser.add_argument('-w', '--wide', action='store_true', help='show all arguments')
|
||||||
|
self.arg_parser.add_argument('-s', '--show', nargs='+', type=int, default=[],
|
||||||
|
help='show process (tree) by pid')
|
||||||
|
|
||||||
def run(self, args):
|
def run(self, args):
|
||||||
if self.client.is_windows():
|
width, _ = terminal_size()
|
||||||
outputlist=self.client.conn.modules["pupwinutils.processes"].enum_processes()
|
root, tree, data = self.client.conn.modules.pupyps.pstree()
|
||||||
outputlist=obtain(outputlist) #pickle the list of proxy objects with obtain is really faster
|
data = { int(k):v for k,v in obtain(data).iteritems() }
|
||||||
columns=['username', 'pid', 'arch', 'exe']
|
tree = { int(k):v for k,v in obtain(tree).iteritems() }
|
||||||
if args.all:
|
|
||||||
columns=['username', 'pid', 'arch', 'name', 'exe', 'cmdline', 'status']
|
colinfo = {'pid': 0}
|
||||||
for dic in outputlist:
|
for pid in data:
|
||||||
for c in columns:
|
l = len(str(pid))
|
||||||
if c in dic and dic[c] is None:
|
if colinfo['pid'] < l:
|
||||||
dic[c]=""
|
colinfo['pid'] = l
|
||||||
dic["cmdline"]=' '.join(dic['cmdline'][1:])
|
for column in data[pid]:
|
||||||
|
if '_percent' in column:
|
||||||
|
colinfo[column] = 4
|
||||||
|
continue
|
||||||
|
|
||||||
|
l = len(str(data[pid][column]))
|
||||||
|
if not column in colinfo:
|
||||||
|
colinfo[column] = l
|
||||||
|
else:
|
||||||
|
if colinfo[column] < l:
|
||||||
|
colinfo[column] = l
|
||||||
|
|
||||||
|
try:
|
||||||
|
info = ['exe', 'cmdline']
|
||||||
|
hide = [
|
||||||
|
int(x) if x.isdigit() else x for x in args.hide
|
||||||
|
]
|
||||||
|
show = [
|
||||||
|
int(x) if x.isdigit() else x for x in args.show
|
||||||
|
]
|
||||||
|
|
||||||
|
if not args.all and self.client.is_linux():
|
||||||
|
hide.append(2)
|
||||||
|
|
||||||
|
if args.info:
|
||||||
|
info = [ 'username', 'cpu_percent', 'memory_percent' ] + info
|
||||||
|
|
||||||
|
if args.tree:
|
||||||
|
show = show or [ root ]
|
||||||
|
|
||||||
|
for item in show:
|
||||||
|
print_pstree(
|
||||||
|
self.stdout, item, tree, data,
|
||||||
|
width=None if args.wide else width, colinfo=colinfo, info=info,
|
||||||
|
hide=hide, first=(item == root)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
for dic in outputlist:
|
data = [ x for x in data if x in args.show ] if args.show else data
|
||||||
if 'exe' in dic and not dic['exe'] and 'name' in dic and dic['name']:
|
print_ps(
|
||||||
dic['exe']=dic['name'].encode('utf-8', errors='replace')
|
self.stdout, data, width=None if args.wide else width,
|
||||||
if 'username' in dic and dic['username'] is None:
|
colinfo=colinfo, info=info, hide=hide
|
||||||
dic['username']=""
|
)
|
||||||
self.rawlog(self.formatter.table_format(outputlist, wl=columns))
|
|
||||||
elif self.client.is_android():
|
except Exception, e:
|
||||||
self.log(shell_exec(self.client, "ps"))
|
logging.exception(e)
|
||||||
elif self.client.is_darwin():
|
|
||||||
self.log(shell_exec(self.client, "ps aux"))
|
|
||||||
else:
|
|
||||||
self.log(shell_exec(self.client, "ps -aux"))
|
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import psutil
|
||||||
|
|
||||||
|
import collections
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def pstree():
|
||||||
|
data = {}
|
||||||
|
tree = {}
|
||||||
|
me = psutil.Process()
|
||||||
|
try:
|
||||||
|
my_user = me.username()
|
||||||
|
except:
|
||||||
|
my_user = None
|
||||||
|
|
||||||
|
for p in psutil.process_iter():
|
||||||
|
if not psutil.pid_exists(p.pid):
|
||||||
|
continue
|
||||||
|
|
||||||
|
data[p.pid] = p.as_dict([
|
||||||
|
'name', 'username', 'cmdline', 'exe',
|
||||||
|
'cpu_percent', 'memory_percent', 'connections'
|
||||||
|
])
|
||||||
|
|
||||||
|
if p.pid == me.pid:
|
||||||
|
data[p.pid]['self'] = True
|
||||||
|
elif my_user and data[p.pid].get('username') == my_user:
|
||||||
|
data[p.pid]['same_user'] = True
|
||||||
|
|
||||||
|
if 'connections' in data[p.pid]:
|
||||||
|
data[p.pid]['connections'] = bool(data[p.pid]['connections'])
|
||||||
|
|
||||||
|
try:
|
||||||
|
parent = p.parent()
|
||||||
|
ppid = parent.pid if parent else 0
|
||||||
|
if not ppid in tree:
|
||||||
|
tree[ppid] = [p.pid]
|
||||||
|
else:
|
||||||
|
tree[ppid].append(p.pid)
|
||||||
|
|
||||||
|
except (psutil.ZombieProcess):
|
||||||
|
data[p.pid]['name'] = '< Z: ' + data[p.pid]['name'] + ' >'
|
||||||
|
|
||||||
|
except (psutil.NoSuchProcess):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# on systems supporting PID 0, PID 0's parent is usually 0
|
||||||
|
if 0 in tree and 0 in tree[0]:
|
||||||
|
tree[0].remove(0)
|
||||||
|
|
||||||
|
return min(tree), tree, data
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print pstree()
|
Loading…
Reference in New Issue