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 os
|
||||||
import time
|
import time
|
||||||
import socket
|
import socket
|
||||||
|
import pwd
|
||||||
|
import struct
|
||||||
|
import netaddr
|
||||||
|
import time
|
||||||
|
|
||||||
families = {
|
families = {
|
||||||
v:k[3:] for k,v in socket.__dict__.iteritems() if k.startswith('AF_')
|
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__':
|
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
|
res="\033[34m"+s+COLOR_STOP
|
||||||
elif color.lower()=="red":
|
elif color.lower()=="red":
|
||||||
res="\033[31m"+s+COLOR_STOP
|
res="\033[31m"+s+COLOR_STOP
|
||||||
|
elif color.lower()=="lightred":
|
||||||
|
res="\033[31;1m"+s+COLOR_STOP
|
||||||
elif color.lower()=="green":
|
elif color.lower()=="green":
|
||||||
res="\033[32m"+s+COLOR_STOP
|
res="\033[32m"+s+COLOR_STOP
|
||||||
|
elif color.lower()=="lightgreen":
|
||||||
|
res="\033[32;1m"+s+COLOR_STOP
|
||||||
elif color.lower()=="yellow":
|
elif color.lower()=="yellow":
|
||||||
res="\033[33m"+s+COLOR_STOP
|
res="\033[33m"+s+COLOR_STOP
|
||||||
elif color.lower()=="magenta":
|
elif color.lower()=="magenta":
|
||||||
|
|
Loading…
Reference in New Issue