Skip to content

Instantly share code, notes, and snippets.

@truekonrads
Last active August 22, 2020 01:03
Show Gist options
  • Select an option

  • Save truekonrads/3be3f0bbd9c22cf4ad8c to your computer and use it in GitHub Desktop.

Select an option

Save truekonrads/3be3f0bbd9c22cf4ad8c to your computer and use it in GitHub Desktop.
A quick and dirty Linux utmp record carver
#!/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