229 lines
4.8 KiB
Ruby
229 lines
4.8 KiB
Ruby
# -*- coding: binary -*-
|
|
|
|
#
|
|
# This is just a container class basically, that acts like File::Struct
|
|
#
|
|
# You must supply an initialize method that somehow populates the stathash..
|
|
#
|
|
|
|
module Rex
|
|
module Post
|
|
|
|
###
|
|
#
|
|
# This class emulates the ruby FileStat class against a remote entity in a
|
|
# generic fashion. Refer to the ruby documentation for expected behavior.
|
|
#
|
|
###
|
|
class FileStat
|
|
|
|
#
|
|
# Basic file types.
|
|
#
|
|
@@ftypes = [
|
|
'fifo', 'characterSpecial', 'directory',
|
|
'blockSpecial', 'file', 'link', 'socket'
|
|
]
|
|
|
|
attr_accessor :stathash
|
|
|
|
def initialize(buf='')
|
|
self.stathash = {}
|
|
update(buf) if (buf and not buf.empty?)
|
|
end
|
|
|
|
def dev
|
|
self.stathash['st_dev']
|
|
end
|
|
def ino
|
|
self.stathash['st_ino']
|
|
end
|
|
def mode
|
|
self.stathash['st_mode']
|
|
end
|
|
def nlink
|
|
self.stathash['st_nlink']
|
|
end
|
|
def uid
|
|
self.stathash['st_uid']
|
|
end
|
|
def gid
|
|
self.stathash['st_gid']
|
|
end
|
|
def rdev
|
|
self.stathash['st_rdev']
|
|
end
|
|
def size
|
|
self.stathash['st_size']
|
|
end
|
|
def blksize
|
|
self.stathash['st_blksize']
|
|
end
|
|
def blocks
|
|
self.stathash['st_blocks']
|
|
end
|
|
def atime
|
|
Time.at(self.stathash['st_atime'])
|
|
end
|
|
def mtime
|
|
Time.at(self.stathash['st_mtime'])
|
|
end
|
|
def ctime
|
|
Time.at(self.stathash['st_ctime'])
|
|
end
|
|
|
|
def update(buf)
|
|
skeys = %W{st_dev st_mode st_nlink st_uid st_gid st_rdev st_ino st_size st_ctime st_atime st_mtime}
|
|
svals = buf.unpack("VVVVVVQQQQQ")
|
|
skeys.each_index do |i|
|
|
self.stathash[ skeys[i] ] = svals[i]
|
|
end
|
|
end
|
|
|
|
#
|
|
# This handles the old 32bit st_size buf from old stageless meterpreters for backwards compatibility
|
|
# Maybe we can remove this in the future
|
|
#
|
|
def update32(buf)
|
|
skeys = %W{st_dev st_ino st_mode st_pad st_nlink st_uid st_gid st_rdev st_size st_ctime st_atime st_mtime}
|
|
svals = buf.unpack("VvvvvvvVVVVV")
|
|
skeys.each_index do |i|
|
|
self.stathash[ skeys[i] ] = svals[i]
|
|
end
|
|
end
|
|
|
|
#
|
|
# S_IFMT 0170000 bitmask for the file type bitfields
|
|
# S_IFSOCK 0140000 socket
|
|
# S_IFLNK 0120000 symbolic link
|
|
# S_IFREG 0100000 regular file
|
|
# S_IFBLK 0060000 block device
|
|
# S_IFDIR 0040000 directory
|
|
# S_IFCHR 0020000 character device
|
|
# S_IFIFO 0010000 fifo
|
|
#
|
|
|
|
# this is my own, just a helper...
|
|
def filetype?(mask)
|
|
return true if mode & 0170000 == mask
|
|
return false
|
|
end
|
|
|
|
def blockdev?
|
|
filetype?(060000)
|
|
end
|
|
def chardev?
|
|
filetype?(020000)
|
|
end
|
|
def directory?
|
|
filetype?(040000)
|
|
end
|
|
def file?
|
|
filetype?(0100000)
|
|
end
|
|
def pipe?
|
|
filetype?(010000) # ??? fifo?
|
|
end
|
|
def socket?
|
|
filetype(0140000)
|
|
end
|
|
def symlink?
|
|
filetype(0120000)
|
|
end
|
|
|
|
def ftype
|
|
return @@ftypes[(mode & 0170000) >> 13].dup
|
|
end
|
|
|
|
#
|
|
# S_ISUID 0004000 set UID bit
|
|
# S_ISGID 0002000 set GID bit (see below)
|
|
# S_ISVTX 0001000 sticky bit (see below)
|
|
# S_IRWXU 00700 mask for file owner permissions
|
|
# S_IRUSR 00400 owner has read permission
|
|
# S_IWUSR 00200 owner has write permission
|
|
# S_IXUSR 00100 owner has execute permission
|
|
# S_IRWXG 00070 mask for group permissions
|
|
# S_IRGRP 00040 group has read permission
|
|
# S_IWGRP 00020 group has write permission
|
|
# S_IXGRP 00010 group has execute permission
|
|
# S_IRWXO 00007 mask for permissions for others (not in group)
|
|
# S_IROTH 00004 others have read permission
|
|
# S_IWOTH 00002 others have write permisson
|
|
# S_IXOTH 00001 others have execute permission
|
|
#
|
|
|
|
def perm?(mask)
|
|
return true if mode & mask == mask
|
|
return false
|
|
end
|
|
|
|
def setgid?
|
|
perm?(02000)
|
|
end
|
|
def setuid?
|
|
perm?(04000)
|
|
end
|
|
def sticky?
|
|
perm?(01000)
|
|
end
|
|
|
|
def executable?
|
|
raise NotImplementedError
|
|
end
|
|
def executable_real?
|
|
raise NotImplementedError
|
|
end
|
|
def grpowned?
|
|
raise NotImplementedError
|
|
end
|
|
def owned?
|
|
raise NotImplementedError
|
|
end
|
|
def readable?
|
|
raise NotImplementedError
|
|
end
|
|
def readable_real?
|
|
raise NotImplementedError
|
|
end
|
|
def writeable?
|
|
raise NotImplementedError
|
|
end
|
|
def writeable_real?
|
|
raise NotImplementedError
|
|
end
|
|
|
|
#
|
|
# Return pretty information about a file's permissions.
|
|
#
|
|
def prettymode
|
|
m = mode
|
|
om = '%04o' % m
|
|
perms = ''
|
|
|
|
3.times {
|
|
perms = ((m & 01) == 01 ? 'x' : '-') + perms
|
|
perms = ((m & 02) == 02 ? 'w' : '-') + perms
|
|
perms = ((m & 04) == 04 ? 'r' : '-') + perms
|
|
m >>= 3
|
|
}
|
|
|
|
return "#{om}/#{perms}"
|
|
end
|
|
|
|
#
|
|
# Return pretty information about a file.
|
|
#
|
|
def pretty
|
|
" Size: #{size} Blocks: #{blocks} IO Block: #{blksize} Type: #{rdev}\n"\
|
|
"Device: #{dev} Inode: #{ino} Links: #{nlink}\n"\
|
|
" Mode: #{prettymode}\n"\
|
|
" Uid: #{uid} Gid: #{gid}\n"\
|
|
"Access: #{atime}\n"\
|
|
"Modify: #{mtime}\n"\
|
|
"Change: #{ctime}\n"
|
|
end
|
|
|
|
end
|
|
end; end # Post/Rex
|