Last active
August 22, 2020 01:03
-
-
Save truekonrads/3be3f0bbd9c22cf4ad8c to your computer and use it in GitHub Desktop.
A quick and dirty Linux utmp record carver
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/python | |
| # Copyright 2015 Konrads Smelkovs <[email protected]> KPMG LLP | |
| # All liability disclaimed. Use at your own risk. | |
| """ | |
| A quick and dirty Linux utmp record carver | |
| """ | |
| import re,struct,sys,ipaddress, binascii | |
| from datetime import datetime | |
| wtmp=file(sys.argv[1],"rb") | |
| ut_type_def={ | |
| 0 : "empty", # No valid user accounting information | |
| 1 : "Run Level", # The system's runlevel | |
| 2 : "Boot Time", # Time of system boot | |
| 3 : "New Time", # Time after system clock changed | |
| 4 : "Old Time", # Time when system clock changed | |
| 5 : "Init", # Process spawned by the init process | |
| 6 : "Login", # Session leader of a logged in user | |
| 7 : "User Process", # Normal process | |
| 8 : "Process End", # Terminated process | |
| 9 : "Accounting" # Accouting | |
| } | |
| def printwtmp(match): | |
| record=match.groupdict() | |
| ut_type=struct.unpack("h",record['ut_type'])[0] | |
| print "UT_TYPE: {}: {}".format(ut_type,ut_type_def[ut_type]) | |
| ut_pid=struct.unpack("I",record['ut_pid'])[0] | |
| print "UT_PID: {}".format(ut_pid) | |
| print "UT_LINE: '{}'".format(record['ut_line'].replace("\x00","")) | |
| print "UT_ID: '{}'".format(record['ut_id'].replace("\x00","")) | |
| print "UT_USER: '{}'".format(record['ut_user'].replace("\x00","")) | |
| print "UT_HOST: '{}'".format(record['ut_host'].replace("\x00","")) | |
| tv_sec=struct.unpack("l",record['tv_sec'])[0] | |
| tv_sec_time=datetime.utcfromtimestamp(tv_sec) | |
| tv_usec=struct.unpack("l",record['tv_usec'])[0] | |
| print "UT_TV: {}.{} ({})".format(tv_sec_time,tv_usec,tv_sec) | |
| ip=ipaddress.IPv4Address(record['ut_addr_v6'][0:4]) | |
| print "IP: {}".format(ip) | |
| def chunk_producer(feed,chunksize=1024): | |
| # pos=0 | |
| chunk=feed.read(chunksize) | |
| yield chunk | |
| while True: | |
| tmp=feed.read(chunksize/2) | |
| if len(tmp)==0: | |
| break | |
| right=chunk[chunksize/2+1:chunksize] | |
| chunk=right+tmp | |
| yield chunk | |
| pattern=re.compile(""" | |
| (?P<ut_type>[\x00-\x09]\x00) | |
| (?P<ut_pid>[\x00-\xff]{4}) | |
| (?P<ut_pad>[\x00-\xff]{2}) | |
| (?P<ut_line>[a-z]{3}[:\w\-/\x00]{29}) | |
| (?P<ut_id>[\x00\w\-/]{4}) | |
| (?P<ut_user>\w[\x00\w\-]{31}) | |
| (?P<ut_host>[\x00\w\-.]{256}) | |
| (?P<ut_exit>[\x00-\xff]{4}) | |
| (?P<ut_session>[\x00-\xff]{4}) | |
| (?P<tv_sec>[\x00-\xff]{4}) | |
| (?P<tv_usec>[\x00-\xff]{4}) | |
| (?P<ut_addr_v6>[\x00-\xff]{16}) | |
| (?P<unused>[\x00]{20}) | |
| """,re.X) | |
| for chunk in chunk_producer(wtmp): | |
| matches=[m for m in pattern.finditer(chunk)] | |
| # out=[m.groupdict() for m in ] | |
| # print len(matches) | |
| if len(matches): | |
| for e in matches: | |
| try: | |
| printwtmp(e) | |
| except Exception,e: | |
| print str(e) | |
| # raise e | |
| print "Matching CHUNK: {}".format( binascii.hexlify(chunk)) | |
| # for k,v in e.groupdict(): | |
| # pass | |
| # print "{} '{}'".format(k,v) | |
| # print "Len of ut_line {}".format(len(out[[]]) | |
| # for e in out: | |
| # print e['ut_user'] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment