Example #1
0
    def find_function_symbol(self, task, address):
        """
        Match a function symbol to a functiona address.
        @param task: the task_struct
        @param address:  The function address
        @return: The function symbol or None
        """
        if self.symbols:
            for vma in task.get_proc_maps():
                if vma.vm_start <= address <= vma.vm_end:
                    #lib = vma.vm_file
                    lib = linux_common.get_path(task, vma.vm_file)
                    offset = address - vma.vm_start

                    #libsymbols = self.symbols[os.path.basename(lib)]
                    if type(lib) == list:
                        lib = ""
                    base = os.path.basename(lib)
                    #print(base)
                    #print("{:016x} {} {}".format(offset, base, lib))

                    if base in self.symbols:

                        if offset in self.symbols[base]:
                            debug.info("Instruction was a call to 0x{:016x} = {}@{}".format(address, self.symbols[base][offset], base ))
                            return self.symbols[base][offset]
                        elif address in self.symbols[base]:# for a function in the main binary, eg 0x40081e
                            debug.info("Instruction was a call to 0x{:016x} = {}@{}".format(address, self.symbols[base][address], base ))
                            return self.symbols[base][address]
                    break
        return None
Example #2
0
 def _fill_cache(self):
     for task in linux_pslist.linux_pslist(self._config).calculate():
         for filp, fd in task.lsof():
             filepath = linux_common.get_path(task, filp)
             if type(filepath) == str and filepath.find("socket:[") != -1:
                 to_add = filp.dentry.d_inode.i_ino.v()
                 self.fd_cache[to_add] = [task, filp, fd, filepath]
    def render_text(self, outfd, data):
        for task, vma in data:

            mm = task.mm

            if vma.vm_file:
                inode = vma.vm_file.dentry.d_inode
                sb = obj.Object("super_block", offset = inode.i_sb, vm = self.addr_space)
                dev = sb.s_dev
                ino = inode.i_ino
                pgoff = vma.vm_pgoff << 12
                fname = linux_common.get_path(task, vma.vm_file)
            else:
                (dev, ino, pgoff) = [0] * 3

                if vma.vm_start <= mm.start_brk and vma.vm_end >= mm.brk:
                    fname = "[heap]"

                elif vma.vm_start <= mm.start_stack and vma.vm_end >= mm.start_stack:
                    fname = "[stack]"

                else:
                    fname = ""

            outfd.write("{0:#8x}-{1:#8x} {2:3} {3:10d} {4:#2d}:{5:#2d} {6:#12d} {7}\n".format(
                    self.mask_number(vma.vm_start),
                    self.mask_number(vma.vm_end),
                    self.format_perms(vma.vm_flags),
                    pgoff,
                    self.MAJOR(dev),
                    self.MINOR(dev),
                    ino,
                    fname))
Example #4
0
 def _fill_cache(self):
     for task in linux_pslist.linux_pslist(self._config).calculate():
         for filp, fd in task.lsof():
             filepath = linux_common.get_path(task, filp)
             if type(filepath) == str and filepath.find("socket:[") != -1:
                 to_add = filp.dentry.d_inode.i_ino
                 self.fd_cache[to_add] = [task, filp, fd, filepath]
Example #5
0
    def render_text(self, outfd, data):

        self.table_header(outfd, [("Pid", "8"), ("FD", "8"), ("Path", "")])

        for (task, filp, fd) in data:
            self.table_row(outfd, task.pid, fd,
                           linux_common.get_path(task, filp))
Example #6
0
    def render_text(self, outfd, data):
        self.table_header(outfd, [
            ("Pid", "8"),
            ("Start", "#018x"),
            ("End", "#018x"),
            ("Flags", "6"),
            ("Pgoff", "[addr]"),
            ("Major", "6"),
            ("Minor", "6"),
            ("Inode", "10"),
            ("File Path", "80"),
        ])
        for task, vma in data:

            if vma.vm_file:
                inode = vma.vm_file.dentry.d_inode
                major, minor = inode.i_sb.major, inode.i_sb.minor
                ino = inode.i_ino
                pgoff = vma.vm_pgoff << 12
                fname = linux_common.get_path(task, vma.vm_file)
            else:
                (major, minor, ino, pgoff) = [0] * 4

                if vma.vm_start <= task.mm.start_brk and vma.vm_end >= task.mm.brk:
                    fname = "[heap]"
                elif vma.vm_start <= task.mm.start_stack and vma.vm_end >= task.mm.start_stack:
                    fname = "[stack]"
                else:
                    fname = ""

            self.table_row(outfd, task.pid, vma.vm_start, vma.vm_end,
                           str(vma.vm_flags), pgoff, major, minor, ino, fname)
    def check_open_files_fop(self, f_op_members, modules):
        # get all the members in file_operations, they are all function pointers
        openfiles = linux_lsof.linux_lsof(self._config).calculate()

        for (task, filp, i) in openfiles:
            for (hooked_member, hook_address) in self.verify_ops(filp.f_op, f_op_members, modules):
                name = "{0:s} {1:d} {2:s}".format(task.comm, i, linux_common.get_path(task, filp))
                yield (name, hooked_member, hook_address)
Example #8
0
    def check_open_files_fop(self, f_op_members, modules):
        # get all the members in file_operations, they are all function pointers
        openfiles = linux_lsof.linux_lsof(self._config).calculate()

        for (task, filp, i) in openfiles:
            for (hooked_member, hook_address) in self.verify_ops(filp.f_op, f_op_members, modules):
                name = "{0:s} {1:d} {2:s}".format(task.comm, i, linux_common.get_path(task, filp))
                yield (name, hooked_member, hook_address)
    def render_text(self, outfd, data):

        self.table_header(outfd, [("Pid", "8"),
                                  ("FD", "8"),
                                  ("Path", "")])

        for (task, filp, fd) in data:
            self.table_row(outfd, task.pid, fd, linux_common.get_path(task, filp))
Example #10
0
 def generator(self, data):
     for task in data:
         for filp, fd in task.lsof():
             yield (0, [
                 int(task.pid),
                 int(fd),
                 str(linux_common.get_path(task, filp))
             ])
Example #11
0
    def check_open_files_fop(self, f_op_members, modules):
        # get all the members in file_operations, they are all function pointers
        tasks = linux_pslist.linux_pslist(self._config).calculate()

        for task in tasks: 
            for filp, i in task.lsof():
                for (hooked_member, hook_type, hook_address) in self._is_inline_hooked(filp.f_op, f_op_members, modules):
                    name = "{0:s} {1:d} {2:s}".format(task.comm, i, linux_common.get_path(task, filp))
                    yield (name, hooked_member, hook_type, hook_address)
    def check_open_files_fop(self, f_op_members, modules):
        # get all the members in file_operations, they are all function pointers
        tasks = linux_pslist.linux_pslist(self._config).calculate()

        for task in tasks: 
            for filp, i in task.lsof():
                for (hooked_member, hook_type, hook_address) in self._is_inline_hooked(filp.f_op, f_op_members, modules):
                    name = "{0:s} {1:d} {2:s}".format(task.comm, i, linux_common.get_path(task, filp))
                    yield (name, hooked_member, hook_type, hook_address)
Example #13
0
def get_data_section(config, what):
    proc_maps = linux_proc_maps.linux_proc_maps(config).calculate()
    for task, vma in proc_maps:
        if not vma.vm_file:
            continue
        if not linux_common.get_path(task, vma.vm_file) == what:
            continue
        if not (vma.vm_flags & linux_flags.VM_READ and vma.vm_flags & linux_flags.VM_WRITE and not vma.vm_flags & linux_flags.VM_EXEC):
            continue
        yield task, vma
Example #14
0
 def generator(self, data):
     for task in data:
         for filp, fd in task.lsof():
             yield (0, [
                 Address(task.obj_offset),
                 str(task.comm),
                 int(task.pid),
                 int(fd),
                 str(linux_common.get_path(task, filp))
             ])
 def get_map_by_name(self, name, permissions='r-x'):
     """
     Find a memory mapping (vm_area) by its name (not exact match). Optionally, check permissions.
     @param name: The mapped name to find.
     @param permissions: Permissions in 'rwx' format
     @return: A (vm_start, vm_end, libname) tuple or None
     """
     # We use this to find libc
     for vma in self.task.get_proc_maps():
         libname = linux_common.get_path(self.task, vma.vm_file)
         # just look for partial name
         if str(vma.vm_flags) == permissions and name in libname:
             return vma.vm_start, vma.vm_end, libname
     return None
Example #16
0
 def get_map_by_name(self, name, permissions='r-x'):
     """
     Find a memory mapping (vm_area) by its name (not exact match). Optionally, check permissions.
     @param name: The mapped name to find.
     @param permissions: Permissions in 'rwx' format
     @return: A (vm_start, vm_end, libname) tuple or None
     """
     # We use this to find libc
     for vma in self.task.get_proc_maps():
         libname = linux_common.get_path(self.task, vma.vm_file)
         # just look for partial name
         if str(vma.vm_flags) == permissions and name in libname:
             return vma.vm_start, vma.vm_end, libname
     return None
Example #17
0
    def render_text(self, outfd, data):
        self.table_header(outfd, [
            ("Offset", "#018x"),
            ("Name", "30"),
            ("Pid", "8"),
            ("FD", "8"),
            ("Mode", "15"),
            ("Path", ""),
        ])

        for task in data:
            for filp, fd in task.lsof():
                self.table_row(outfd, Address(task.obj_offset), str(task.comm),
                               task.pid, fd, self.__toModeText(filp.f_mode),
                               linux_common.get_path(task, filp))
Example #18
0
    def _get_name(self, task, addr):
        hook_vma = None        
        hookdesc = "<Unknown mapping>"

        for i in task.get_proc_maps():
            if addr >= i.vm_start and addr < i.vm_end:
                hook_vma = i
                break          
          
        if hook_vma:
            if hook_vma.vm_file:
                hookdesc = linux_common.get_path(task, hook_vma.vm_file)
            else:
                hookdesc = '[{0:x}:{1:x},{2}]'.format(hook_vma.vm_start, hook_vma.vm_end, hook_vma.vm_flags)
        
        return (hook_vma, hookdesc)
Example #19
0
    def render_text(self, outfd, data):
        self.table_header(outfd, [("Offset","#018x"),
                                  ("Name","30"),
                                  ("Pid", "8"),
                                  ("FD", "8"),
                                  ("Mode", "15"),
                                  ("Path", ""),
                                  ])

        for task in data:
            for filp, fd in task.lsof(): 
                self.table_row(outfd,
                        Address(task.obj_offset),
                        str(task.comm),
                        task.pid,
                        fd,
                        self.__toModeText(filp.f_mode),
                        linux_common.get_path(task, filp))
Example #20
0
    def render_text(self, outfd, data):
       
        self.table_header(outfd, [("Start", "[addrpad]"),
                                  ("End",   "[addrpad]"),
                                  ("Flags", "6"),
                                  ("Pgoff", "6"),
                                  ("Major", "6"),
                                  ("Minor", "6"),
                                  ("Inode", "10"),
                                  ("File Path", "80"),                    
                                 ]) 
        for task, vma in data:

            mm = task.mm

            if vma.vm_file:
                inode = vma.vm_file.dentry.d_inode
                sb = obj.Object("super_block", offset = inode.i_sb, vm = self.addr_space)
                dev = sb.s_dev
                ino = inode.i_ino
                pgoff = vma.vm_pgoff << 12
                fname = linux_common.get_path(task, vma.vm_file)
            else:
                (dev, ino, pgoff) = [0] * 3

                if vma.vm_start <= mm.start_brk and vma.vm_end >= mm.brk:
                    fname = "[heap]"

                elif vma.vm_start <= mm.start_stack and vma.vm_end >= mm.start_stack:
                    fname = "[stack]"

                else:
                    fname = ""

            self.table_row(outfd,
                self.mask_number(vma.vm_start),
                self.mask_number(vma.vm_end),
                self.format_perms(vma.vm_flags),
                pgoff,
                self.MAJOR(dev),
                self.MINOR(dev),
                ino,
                fname)
Example #21
0
    def render_text(self, outfd, data):

        self.table_header(outfd, [
            ("Start", "[addrpad]"),
            ("End", "[addrpad]"),
            ("Flags", "6"),
            ("Pgoff", "6"),
            ("Major", "6"),
            ("Minor", "6"),
            ("Inode", "10"),
            ("File Path", "80"),
        ])
        for task, vma in data:

            mm = task.mm

            if vma.vm_file:
                inode = vma.vm_file.dentry.d_inode
                sb = obj.Object("super_block",
                                offset=inode.i_sb,
                                vm=self.addr_space)
                dev = sb.s_dev
                ino = inode.i_ino
                pgoff = vma.vm_pgoff << 12
                fname = linux_common.get_path(task, vma.vm_file)
            else:
                (dev, ino, pgoff) = [0] * 3

                if vma.vm_start <= mm.start_brk and vma.vm_end >= mm.brk:
                    fname = "[heap]"

                elif vma.vm_start <= mm.start_stack and vma.vm_end >= mm.start_stack:
                    fname = "[stack]"

                else:
                    fname = ""

            self.table_row(outfd, self.mask_number(vma.vm_start),
                           self.mask_number(vma.vm_end),
                           self.format_perms(vma.vm_flags), pgoff,
                           self.MAJOR(dev), self.MINOR(dev), ino, fname)
Example #22
0
    def dump_fd_info(self, task, sockets_type):

        fdinfoFile = open("fdinfo-2.json", "w")
        entries = []
        for file, fd in task.lsof():
            path = linux_common.get_path(task, file)
            element = {"id": 0, "flags": 0, "type": "", "fd": int(fd)}
            if "/dev/pts" in path:
                element["id"] = 1
                element["type"] = "TTY"
            elif "socket:[" in path:
                element["id"] = fd - 1
                element["type"] = sockets_type[fd]
            else:
                element["id"] = fd - 1
                element["type"] = "REG"

            entries.append(element)
        data = {"magic": "FDINFO", "entries": entries}
        fdinfoFile.write(json.dumps(data, indent=4, sort_keys=False))
        fdinfoFile.close()
Example #23
0
    def getShmid(self, progname, current_name, dic, task):
        if current_name == "" or "[" in current_name:
            return 0

        if progname not in dic:
            maxFd = 2
            for filp, fd in task.lsof():
                #self.table_row(outfd, Address(task.obj_offset), str(task.comm), task.pid, fd, linux_common.get_path(task, filp))
                if fd > maxFd and "/dev/pts/" not in linux_common.get_path(
                        task, filp):
                    maxFd = fd

            dic[progname] = maxFd

        if current_name in dic:

            return dic[current_name]

        else:
            dic[current_name] = len(dic) + dic[progname]
            return dic[current_name]
Example #24
0
    def render_text(self, outfd, data):
        self.table_header(outfd, [("Pid", "8"),
                                  ("Start", "#018x"),
                                  ("End",   "#018x"),
                                  ("Flags", "6"),
                                  ("Pgoff", "[addr]"),
                                  ("Major", "6"),
                                  ("Minor", "6"),
                                  ("Inode", "10"),
                                  ("File Path", "80"),                    
                                 ]) 
        for task, vma in data:

            if vma.vm_file:
                inode = vma.vm_file.dentry.d_inode
                major, minor = inode.i_sb.major, inode.i_sb.minor
                ino = inode.i_ino
                pgoff = vma.vm_pgoff << 12
                fname = linux_common.get_path(task, vma.vm_file)
            else:
                (major, minor, ino, pgoff) = [0] * 4

                if vma.vm_start <= task.mm.start_brk and vma.vm_end >= task.mm.brk:
                    fname = "[heap]"
                elif vma.vm_start <= task.mm.start_stack and vma.vm_end >= task.mm.start_stack:
                    fname = "[stack]"
                else:
                    fname = ""

            self.table_row(outfd, task.pid, 
                vma.vm_start,
                vma.vm_end,
                str(vma.vm_flags),
                pgoff,
                major,
                minor,
                ino,
                fname)
Example #25
0
    def render_text(self, outfd, data):
        dt = time.time()

	target_dport = self._config.dport
	decision = 'drop'
	#debug.info("Looking for dport == " + str(target_dport))

	# Load process name whitelist
	whitelist = open("DummyWhiteList.txt").read().splitlines()

	# Optional checking of hash for for shell code, disable by default
        global already_done
        pagesize = 4096
        do_hash_checks = False
        do_expl_checks = False

	# Iterrate through open file descriptors to look for application
	# that has an open socket, than match port number to that socket,
	# and finally compare application name to white list.
        for (task, filp, i) in data:
 
           # Optionally generate hash over each executable
           if do_hash_checks:
                if str(task.comm) not in already_done:

                    already_done.append(str(task.comm))
                    for vma in task.get_proc_maps():

                        if vma.vm_file:

                            if "r-x" in str(vma.vm_flags):

                                fname = str(linux_common.get_path(task, vma.vm_file))

                                if str(task.comm) in fname and ".so" not in fname:

                                    proc_as = task.get_process_address_space()
                                    start = vma.vm_start
                                    pages = ""

                                    while start < vma.vm_end:
                                        pages = pages + proc_as.zread(start, pagesize)
                                        start = start + pagesize

                                    debug.info("SHA1 for " + str(task.comm) + " is " + str(hashlib.sha1(pages).hexdigest()))
                                    break

           # End if hash checks

           # Optionally generate hash and check stack and heap for 0x00 sequences (shellcode)
           if do_expl_checks:
                if str(task.comm) not in already_done:

                    already_done.append(str(task.comm))
                    bufpages = ""

                    for vma in task.get_proc_maps():

                        if vma.vm_file:

                            # first hash
                            if "r-x" in str(vma.vm_flags):

                                fname = str(linux_common.get_path(task, vma.vm_file))

                                if str(task.comm) in fname and ".so" not in fname:

                                    proc_as = task.get_process_address_space()
                                    start = vma.vm_start
                                    pages = ""

                                    while start < vma.vm_end:
                                        pages = pages + proc_as.zread(start, pagesize)
                                        start = start + pagesize

                                    debug.info("SHA1 for " + str(task.comm) + " is " + str(hashlib.sha1(pages).hexdigest()))

                        # heap
                        elif vma.vm_start <= task.mm.start_brk and vma.vm_end >= task.mm.brk:

                                proc_as = task.get_process_address_space()
                                start = vma.vm_start

                                while start < vma.vm_end:
                                    bufpages = bufpages + proc_as.zread(start, pagesize)
                                    start = start + pagesize
                        # stack
                        elif vma.vm_start <= task.mm.start_stack and vma.vm_end >= task.mm.start_stack:

                                proc_as = task.get_process_address_space()
                                start = vma.vm_start

                                while start < vma.vm_end:
                                    bufpages = bufpages + proc_as.zread(start, pagesize)
                                    start = start + pagesize

                    hexstr = ":".join("{:02x}".format(ord(c)) for c in bufpages)
                    if "90:90:90:90:90:90:90" in hexstr:
                        debug.info("Shellcode for " + str(task.comm) + " found.")
                    else:
                        debug.info("Shellcode for " + str(task.comm) + " not found.")

           # End if hash and shell code checks

           # See if open file is a socket
           if filp.f_op == self.addr_space.profile.get_symbol("socket_file_ops") or filp.dentry.d_op == self.addr_space.profile.get_symbol("sockfs_dentry_operations"):
                
                iaddr = filp.dentry.d_inode
                skt = self.SOCKET_I(iaddr)
                inet_sock = obj.Object("inet_sock", offset = skt.sk, vm = self.addr_space)
                
                # We are only checking TCP sockets
                if inet_sock.protocol in ("TCP"):

                    state = inet_sock.state if inet_sock.protocol == "TCP" else ""
                    family = inet_sock.sk.__sk_common.skc_family
                    
                    # We are only checking IPv4
                    if family == socket.AF_INET:
                            
                        saddr = inet_sock.src_addr
                        if "0.0.0.0" not in str(saddr): 

                            sport = inet_sock.src_port 
                            dport = inet_sock.dst_port 
                            daddr = inet_sock.dst_addr

        		    #debug.info("Timestamp " + str(round((time.time() - dt), 2)) + "s")
                            debug.info("Daddr: " + str(daddr) + ", dport: " + str(dport) + ", saddr: " + str(saddr) + ", sport: " + str(sport) + ", status: " + str(state) + ", name: " + str(task.comm) + ", pid: " + str(task.pid))

			    # The port we are looking for is the destination port of the SYN/ACK packet,
			    # but on the target computer that is the source port of the original SYN
			    # connection, hence compare target_dport (packet) with sport (target)
			    if target_dport == sport:
				if str(task.comm) in whitelist:
					decision = 'accept'
					break

           # End checking for sockets

	# End of for loop

	debug.info("Done in " + str(round((time.time() - dt), 2)) + "s")

	# Last thing printed is the decision, accept or drop
	print decision
Example #26
0
    def calculate(self):
        linux_common.set_plugin_members(self)
        elfs = dict()
        ignore = frozenset(self._config.IGNORE)

        for task, elf, elf_start, elf_end, soname, needed in linux_elfs.linux_elfs.calculate(
                self):
            elfs[(task, soname)] = (elf, elf_start, elf_end, needed)

        for k, v in elfs.iteritems():
            task, soname = k
            elf, elf_start, elf_end, needed = v

            if elf._get_typename("hdr") == "elf32_hdr":
                elf_arch = 32
            else:
                elf_arch = 64

            needed_expanded = set([soname])
            if (task, None) in elfs:
                needed_expanded.add(None)
            # jmp slot can point to ELF itself if the fn hasn't been called yet (RTLD_LAZY)
            # can point to main binary (None above) if this is a plugin-style symbol
            while len(needed) > 0:
                dep = needed.pop(0)
                needed_expanded.add(dep)
                try:
                    needed += set(elfs[(task, dep)][3]) - needed_expanded
                except KeyError:
                    needed_expanded.remove(dep)

            for reloc in elf.relocations():
                rsym = elf.relocation_symbol(reloc)

                if rsym == None:
                    continue

                symbol_name = elf.symbol_name(rsym)
                if symbol_name == None:
                    symbol_name = "<N/A>"

                offset = reloc.r_offset

                if offset < elf_start:
                    offset = elf_start + offset

                if elf_arch == 32:
                    addr = obj.Object("unsigned int",
                                      offset=offset,
                                      vm=elf.obj_vm)
                else:
                    addr = obj.Object("unsigned long long",
                                      offset=offset,
                                      vm=elf.obj_vm)

                match = False
                for dep in needed_expanded:
                    _, dep_start, dep_end, _ = elfs[(task, dep)]
                    if addr >= dep_start and addr < dep_end:
                        match = dep

                hookdesc = ''
                vma = None
                for i in task.get_proc_maps():
                    if addr >= i.vm_start and addr < i.vm_end:
                        vma = i
                        break
                if vma:
                    if vma.vm_file:
                        hookdesc = linux_common.get_path(task, vma.vm_file)

                        if hookdesc in ignore:
                            continue
                    else:
                        hookdesc = '[{0:x}:{1:x},{2}]'.format(
                            vma.vm_start, vma.vm_end, vma.vm_flags)

                if hookdesc == "":
                    hookdesc = 'invalid memory'

                if match != False:
                    if self._config.ALL and match == soname:
                        hookdesc = '[RTLD_LAZY]'
                    hooked = False

                else:
                    hooked = True

                yield task, soname, elf, elf_start, elf_end, addr, symbol_name, hookdesc, hooked
Example #27
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        tasks = linux_pslist.linux_pslist(self._config).calculate()

        # Are we dealing with 32 or 64-bit pointers
        if self.addr_space.profile.metadata.get('memory_model',
                                                '32bit') == '32bit':
            pack_format = "<I"
            addr_sz = 4
        else:
            pack_format = "<Q"
            addr_sz = 8

        for task in tasks:
            proc_as = task.get_process_address_space()

            # In cases when mm is an invalid pointer
            if not proc_as:
                continue

            procvars = []
            for vma in task.get_proc_maps():
                if not (vma.vm_file and str(vma.vm_flags) == "rw-"
                        and linux_common.get_path(
                            task, vma.vm_file).find("bash") != -1):
                    continue

                env_start = 0
                for off in range(vma.vm_start, vma.vm_end):
                    # check the first index
                    addrstr = proc_as.read(off, addr_sz)
                    if not addrstr or len(addrstr) != addr_sz:
                        continue
                    addr = struct.unpack(pack_format, addrstr)[0]
                    # check first idx...
                    if addr:
                        firstaddrstr = proc_as.read(addr, addr_sz)
                        if not firstaddrstr or len(firstaddrstr) != addr_sz:
                            continue
                        firstaddr = struct.unpack(pack_format, firstaddrstr)[0]
                        buf = proc_as.read(firstaddr, 64)
                        if not buf:
                            continue
                        eqidx = buf.find("=")
                        if eqidx > 0:
                            nullidx = buf.find("\x00")
                            # single char name, =
                            if nullidx >= eqidx:
                                env_start = addr

                if env_start == 0:
                    continue

                envars = obj.Object(theType="Array",
                                    targetType="Pointer",
                                    vm=proc_as,
                                    offset=env_start,
                                    count=256)
                for var in envars:
                    if var:
                        varstr = proc_as.read(var, 1600)
                        eqidx = varstr.find("=")
                        idx = varstr.find("\x00")

                        if idx == -1 or eqidx == -1 or idx < eqidx:
                            break

                        varstr = varstr[:idx]

                        procvars.append(varstr)

                yield task, " ".join(procvars)

                break
Example #28
0
    def get_sock_info(self, task, addrspace):

        sockets_dic = {}
        sockets = []
        flags = []
        fds = []

        for inode, fd in task.lsof():
                path = linux_common.get_path(task, inode)
                if "socket:[" in path:
                    path = path.replace("[", "")
                    path = path.replace("]", "")
                    ino = path.split(":")[1]
                    fds.append(fd-1)
                    sockets.append(ino)
                    flags.append(inode.f_flags)

         

        i = 0
        for ents in task.netstat():
                if ents[0] == socket.AF_INET:
                    (node, proto, sock_saddr, sock_sport, sock_daddr, sock_dport, state) = ents[1]

                    sock_state = node.sk.__sk_common.skc_state
                    sock_proto = node.sk.sk_protocol
                    sock_family = node.sk.__sk_common.skc_family
                    sock_type = node.sk.sk_type

                    inet_sock = node.cast("inet_connection_sock")
                    sock_backlog = inet_sock.icsk_backoff
                    sock_sndbuf = node.sk.sk_sndbuf
                    sock_rcvbuf = node.sk.sk_rcvbuf

                    if node.sk.__sk_common.skc_reuse == 0:
                        sock_reuseaddr = False
                    else:
                        sock_reuseaddr = True

                    sock_priority = node.sk.sk_priority
                    sock_rowlat = node.sk.sk_rcvlowat
                    sock_mark = node.sk.sk_mark
                    sock_ino = sockets[i]
                    sock_flags = flags[i]
                    sock_id = fds[i]
                    i += 1

                    sockets_dic[sock_ino] = { 
                                                "id":int(sock_id),
                                                "ino":int(sock_ino),
                                                "family":int(sock_family),
                                                "type":int(sock_type),
                                                "proto":int(sock_proto),
                                                "state":int(sock_state),
                                                "src_port":int(sock_sport),
                                                "dst_port":int(sock_dport),
                                                "flags":"{0:#x}".format(sock_flags),
                                                "backlog":int(sock_backlog),
                                                "src_addr":[str(sock_saddr)],
                                                "dst_addr":[str(sock_daddr)],
                                                "opts":{
                                                            "so_sndbuf":int(sock_sndbuf),
                                                            "so_rcvbuf":int(sock_rcvbuf),
                                                            "so_snd_tmo_sec":0,
                                                            "so_snd_tmo_usec":0,
                                                            "so_rcv_tmo_sec":0,
                                                            "so_rcv_tmo_usec":0,
                                                            "reuseaddr": sock_reuseaddr,
                                                            "so_priority":int(sock_priority),
                                                            "so_rcvlowat":int(sock_rowlat),
                                                            "so_mark":int(sock_mark),
                                                            "so_passcred": False,
                                                            "so_passsec":False, 
                                                            "so_dontroute": False,
                                                            "so_no_check": False

                                                        },
                                                "ip_opts":{}
                                                }

                    if proto == "TCP":

                        # Readig values for tcp_info structure, this structure is used by CRIU, 
                        # but it's not a kernel structure,
                        # in kernel source (http://lxr.free-electrons.com/source/net/ipv4/tcp.c#L2644) 
                        # values are read using 2 different kernel structures (tcp_sock, inet_connection_sock)
                        # tcp_get_info: http://lxr.free-electrons.com/source/include/linux/tcp.h#L371
                        tcp_sock = node.cast("tcp_sock")

                        tcp_snd_wscale = tcp_sock.rx_opt.snd_wscale
                        tcp_rcv_wscale = tcp_sock.rx_opt.rcv_wscale
                        tcp_mss_clamp = tcp_sock.rx_opt.mss_clamp
                        tcp_mask = self.get_tcpi_options(tcp_sock)
                        tcp_inq_len = tcp_sock.rcv_nxt - tcp_sock.copied_seq
                        tcp_outq_len = tcp_sock.write_seq - tcp_sock.snd_una
                        tcp_inq_seq = tcp_sock.rcv_nxt
                        tcp_outq_seq = tcp_sock.write_seq
                        tcp_unsq_len = 0 #Not Found
                        tcp_timestamp = 0 #Not Found
                        
                        #Reading receive and write queues
                        #Is not useful because it's impossible to restore a transfer
                        #receiveQueue = self.read_queue(node.sk.sk_receive_queue, addrspace)
                        #writeQueue = self.read_queue(node.sk.sk_write_queue, addrspace)

                        tcp_stream_data = {
                                            "inq_len":int(tcp_inq_len),
                                            "inq_seq":int(tcp_inq_seq),
                                            "outq_len":int(tcp_outq_len),
                                            "outq_seq":int(tcp_outq_seq),
                                            "opt_mask":"{0:#x}".format(tcp_mask),
                                            "snd_wscale":int(tcp_snd_wscale),
                                            "mss_clamp":int(tcp_mss_clamp),
                                            "rcv_wscale":int(tcp_rcv_wscale),
                                            "timestamp":int(tcp_timestamp),
                                            "unsq_len":int(tcp_unsq_len),
                                            "extra":{"outq":"", "inq":""}
                                            #"extra":{"outq":base64.b64encode(str(writeQueue).encode('ascii')), "inq":base64.b64encode(str(receiveQueue).encode('ascii'))}

                                            }
                        sockets_dic[sock_ino]["tcp_stream"] = tcp_stream_data

        return sockets_dic
Example #29
0
 def generator(self, data):
     for task in data:
         for filp, fd in task.lsof():
             yield (0, [Address(task.obj_offset),str(task.comm),int(task.pid), int(fd), str(linux_common.get_path(task, filp))])
Example #30
0
 def generator(self, data):
     for task in data:
         for filp, fd in task.lsof(): 
             yield (0, [int(task.pid), int(fd), str(linux_common.get_path(task, filp))])
Example #31
0
    def calculate(self):
        linux_common.set_plugin_members(self)
        elfs = dict()
        ignore = frozenset(self._config.IGNORE)

        for task, elf, elf_start, elf_end, soname, needed in linux_elfs.linux_elfs.calculate(self):
            elfs[(task, soname)] = (elf, elf_start, elf_end, needed)

        for k, v in elfs.iteritems():
            task, soname = k
            elf, elf_start, elf_end, needed = v
          
            if elf._get_typename("hdr") == "elf32_hdr":
                elf_arch = 32
            else:
                elf_arch = 64
         
            needed_expanded = set([soname])
            if (task, None) in elfs:
                needed_expanded.add(None)
            # jmp slot can point to ELF itself if the fn hasn't been called yet (RTLD_LAZY)
            # can point to main binary (None above) if this is a plugin-style symbol
            while len(needed) > 0:
                dep = needed.pop(0)
                needed_expanded.add(dep)
                try:
                    needed += set(elfs[(task, dep)][3]) - needed_expanded
                except KeyError:
                    needed_expanded.remove(dep)

            for reloc in elf.relocations():
                rsym = elf.relocation_symbol(reloc)

                if rsym == None:
                    continue

                symbol_name = elf.symbol_name(rsym)
                if symbol_name == None:
                    symbol_name = "<N/A>"

                offset = reloc.r_offset
               
                if offset < elf_start:
                    offset = elf_start + offset

                if elf_arch == 32:
                    addr = obj.Object("unsigned int", offset = offset, vm = elf.obj_vm)
                else:
                    addr = obj.Object("unsigned long long", offset = offset, vm = elf.obj_vm)
                
                match = False
                for dep in needed_expanded:
                    _, dep_start, dep_end, _ = elfs[(task, dep)]
                    if addr >= dep_start and addr < dep_end:
                        match = dep

                hookdesc = ''
                vma = None
                for i in task.get_proc_maps():
                    if addr >= i.vm_start and addr < i.vm_end:
                        vma = i
                        break                    
                if vma:
                    if vma.vm_file:
                        hookdesc = linux_common.get_path(task, vma.vm_file)

                        if hookdesc in ignore:
                            continue
                    else:
                        hookdesc = '[{0:x}:{1:x},{2}]'.format(vma.vm_start, vma.vm_end, vma.vm_flags)
 
                if hookdesc == "":
                        hookdesc = 'invalid memory'
                
                if match != False:
                    if self._config.ALL and match == soname:
                        hookdesc = '[RTLD_LAZY]'
                    hooked = False 
                
                else:
                    hooked = True

                yield task, soname, elf, elf_start, elf_end, addr, symbol_name, hookdesc, hooked
Example #32
0
    def calculate(self):
        linux_common.set_plugin_members(self)
    
        tasks = linux_pslist.linux_pslist(self._config).calculate()
        
        # Are we dealing with 32 or 64-bit pointers
        if self.addr_space.profile.metadata.get('memory_model', '32bit') == '32bit':
            pack_format = "<I"
            addr_sz = 4
        else:
            pack_format = "<Q"
            addr_sz = 8
            
        for task in tasks:
            proc_as = task.get_process_address_space()
            
            # In cases when mm is an invalid pointer 
            if not proc_as:
                continue

            procvars = []
            for vma in task.get_proc_maps():
                if not (vma.vm_file and str(vma.vm_flags) == "rw-" and linux_common.get_path(task, vma.vm_file).find("bash") != -1):
                    continue

                env_start = 0
                for off in range(vma.vm_start, vma.vm_end):
                    # check the first index
                    addrstr = proc_as.read(off, addr_sz)
                    if not addrstr or len(addrstr) != addr_sz:
                        continue
                    addr = struct.unpack(pack_format, addrstr)[0]
                    # check first idx...
                    if addr:
                        firstaddrstr = proc_as.read(addr, addr_sz)
                        if not firstaddrstr or len(firstaddrstr) != addr_sz:
                            continue
                        firstaddr = struct.unpack(pack_format, firstaddrstr)[0]
                        buf = proc_as.read(firstaddr, 64)
                        if not buf:
                            continue
                        eqidx = buf.find("=")
                        if eqidx > 0:
                            nullidx = buf.find("\x00")
                            # single char name, =
                            if nullidx >= eqidx:
                                env_start = addr

                if env_start == 0:
                    continue

                envars = obj.Object(theType="Array", targetType="Pointer", vm=proc_as, offset=env_start, count=256)
                for var in envars:
                    if var:
                        varstr = proc_as.read(var, 1600)
                        eqidx = varstr.find("=")
                        idx = varstr.find("\x00")

                        if idx == -1 or eqidx == -1 or idx < eqidx:
                            break

                        varstr = varstr[:idx]

                        procvars.append(varstr) 

                yield task, " ".join(procvars)

                break
Example #33
0
    def render_text(self, outfd, data):
        if not self._config.PID:
            debug.error(
                "You have to specify a process to dump. Use the option -p.\n")

        file_name = "pages-1.img"
        file_path = os.path.join(self._config.DUMP_DIR, file_name)

        progName = ""
        shmidDic = {}
        procFiles = {}  #Files used in process
        procFilesExtr = {}  #Files that have to be extracted

        print "Creating pages file for process with PID: " + self._config.PID
        buildJson = True

        pagemap = open("pagemap-{0}.json".format(self._config.PID), "w")
        pagemapData = {"magic": "PAGEMAP", "entries": [{"pages_id": 1}]}

        mmFile = open("mm-{0}.json".format(self._config.PID), "w")
        mmData = {
            "magic":
            "MM",
            "entries": [{
                "mm_start_code": 0,
                "mm_end_code": 0,
                "mm_start_data": 0,
                "mm_end_data": 0,
                "mm_start_stack": 0,
                "mm_start_brk": 0,
                "mm_brk": 0,
                "mm_arg_start": 0,
                "mm_arg_end": 0,
                "mm_env_start": 0,
                "mm_env_end": 0,
                "exe_file_id": 0,
                "vmas": [],
                "dumpable": 1
            }]
        }

        regfilesFile = open("procfiles.json".format(self._config.PID), "w")
        regfilesData = {"entries": [], "pid": self._config.PID, "threads": []}

        self.table_header(outfd, [("Start", "#018x"), ("End", "#018x"),
                                  ("Number of Pages", "6"), ("File Path", "")])
        outfile = open(file_path, "wb")

        vmas = []

        for task, vma in data:
            savedTask = task
            (fname, major, minor, ino, pgoff) = vma.info(task)
            vmas.append(vma)
            #create heuristic for obtaining progname
            if "[" not in fname and ".so" not in fname and ino != 0 and ".cache" not in fname:
                progName = fname

        for vma in vmas:
            (fname, major, minor, ino, pgoff) = vma.info(savedTask)
            vmasData = {
                "start": "{0:#x}".format(vma.vm_start),
                "end": "{0:#x}".format(vma.vm_end),
                "pgoff": pgoff,
                "shmid": self.getShmid(progName, fname, shmidDic, savedTask),
                "prot": "{0}".format(self.protText(str(vma.vm_flags))),
                "flags": "{0}".format(self.flagsText(fname)),
                "status": "{0}".format(self.statusText(fname)),
                "fd": -1,
                "fdflags": "0x0"
            }

            #If VDSO number of pages of predecessor node have to be incremented
            if fname == "[vdso]":
                mmData["entries"][0]["vmas"][len(mmData["entries"][0]["vmas"])
                                             -
                                             1]["status"] += " | VMA_AREA_VVAR"
                pagemapData["entries"][len(pagemapData["entries"]) -
                                       1]["nr_pages"] += 2

            mmData["entries"][0]["vmas"].append(vmasData)

            #if Inode != 0, it's a file which have to be linked
            if ino != 0 and fname not in procFiles:
                procFiles[fname] = True
                idF = vmasData["shmid"]
                typeF = "local"
                nameF = fname
                if fname == progName:
                    #ELF is extracted
                    typeF = "elf"
                    nameF = savedTask.comm + ".dump"

                fileE = {"name": nameF, "id": idF, "type": typeF}
                regfilesData["entries"].append(fileE)

            #Shared Lib in exec mode not have to be dumped
            exLib = ".so" in fname and "x" in str(vma.vm_flags)

            #DUMP only what CRIU needs
            if str(
                    vma.vm_flags
            ) != "---" and fname != "[vdso]" and ".cache" not in fname and not exLib and "/lib/locale/" not in fname:
                npage = 0
                for page in self.read_addr_range_page(savedTask, vma.vm_start,
                                                      vma.vm_end):
                    outfile.write(page)
                    npage += 1
                pagemapData["entries"].append({
                    "vaddr":
                    "{0:#x}".format(vma.vm_start),
                    "nr_pages":
                    npage
                })
                self.table_row(outfd, vma.vm_start, vma.vm_end, npage, fname)

        outfile.close()

        #set Limit addresses for MM file
        print "Reading address ranges and setting limits"
        mm = savedTask.mm

        mmData["entries"][0]["mm_start_code"] = "{0:#x}".format(mm.start_code)
        mmData["entries"][0]["mm_end_code"] = "{0:#x}".format(mm.end_code)
        mmData["entries"][0]["mm_start_data"] = "{0:#x}".format(mm.start_data)
        mmData["entries"][0]["mm_end_data"] = "{0:#x}".format(mm.end_data)
        mmData["entries"][0]["mm_start_stack"] = "{0:#x}".format(
            mm.start_stack)
        mmData["entries"][0]["mm_start_brk"] = "{0:#x}".format(mm.start_brk)
        mmData["entries"][0]["mm_brk"] = "{0:#x}".format(mm.brk)
        mmData["entries"][0]["mm_arg_start"] = "{0:#x}".format(mm.arg_start)
        mmData["entries"][0]["mm_arg_end"] = "{0:#x}".format(mm.arg_end)
        mmData["entries"][0]["mm_env_start"] = "{0:#x}".format(mm.env_start)
        mmData["entries"][0]["mm_env_end"] = "{0:#x}".format(mm.env_end)
        mmData["entries"][0]["exe_file_id"] = shmidDic[progName]

        #Reading Auxilary Vector
        print "Reading Auxiliary Vector"
        saved_auxv = linux_dump_auxv.linux_dump_auxv(
            self._config).read_auxv(task)[:38]
        mmData["entries"][0]["mm_saved_auxv"] = saved_auxv

        #Files used by process: TYPE = EXTRACTED
        for filp, fd in task.lsof():
            fpath = linux_common.get_path(task, filp)
            if "/dev/pts" not in fpath:
                if "/" not in fpath:
                    if "socket:[" in fpath:
                        regfilesData["sockets"] = []
                        regfilesData["sockets"].append(fd - 1)
                    continue
                else:
                    fname = fpath.replace("/", "_")
                    fname += str(fd)
                    typeF = "extracted"
                    idF = fd - 1
                    fileE = {
                        "name": fname,
                        "id": idF,
                        "type": typeF,
                        "pos": long(filp.f_pos)
                    }
                    regfilesData["entries"].append(fileE)
                    procFilesExtr[fname] = "{0:#x}".format(filp.f_inode)

        print "Extracting Files: "
        self.dumpFile(procFilesExtr, savedTask)

        print "Building PsTree"
        self.buildPsTree(savedTask)

        for thread in savedTask.threads():
            regfilesData["threads"].append(int(str(thread.pid)))

        print "Searching registers values and threads states"
        self.readRegs(savedTask)

        pagemap.write(json.dumps(pagemapData, indent=4, sort_keys=False))
        pagemap.close()

        mmFile.write(json.dumps(mmData, indent=4, sort_keys=False))
        mmFile.close()

        regfilesFile.write(json.dumps(regfilesData, indent=4, sort_keys=False))
        regfilesFile.close()

        print "Searching Signal Handler and sigactions"
        self.dumpSignals(savedTask)

        sockets_type = {}

        print "Dumping Sockets"
        self.dumpSock(savedTask, sockets_type)

        print "Dumping Unix Sockets"
        self.dumpUnixSock(savedTask, sockets_type)

        print "Extracting File Descriptors info"
        self.dump_fd_info(savedTask, sockets_type)

        print "Dumping ELF file"
        self.dumpElf(outfd)