Esempio n. 1
0
 def __init__(self, pid=None, exe=None):
     if platform.system() != 'Linux':
         raise RuntimeError('incompatible platform')
     # Ensure that we are running in a version of python that matches the native architecture of the system.
     if platform.architecture()[0] == '32bit':
         if not architecture_is_32bit(platform.machine()):
             raise LinuxProcessError(
                 'Running a 32-bit version of Python on a non x86 system is not supported'
             )
     elif platform.architecture()[0] == '64bit':
         if not architecture_is_64bit(platform.machine()):
             raise LinuxProcessError(
                 'Running a 64-bit version of Python on a non x86-64 system is not supported'
             )
     else:
         raise LinuxProcessError('Could not determine the Python version')
     self._proc_h = None
     signal.signal(signal.SIGCHLD, self._signal_sigchld)
     if exe:
         self._proc_h = subprocess.Popen([exe],
                                         stdin=subprocess.PIPE,
                                         stdout=subprocess.PIPE,
                                         stderr=subprocess.PIPE,
                                         close_fds=True)
         pid = self._proc_h.pid
     if pid == -1:
         pid = os.fork()
         if pid == 0:
             select.select([], [], [], None)
         select.select([], [], [], 0.50)
     self.handle = pid
     self.pid = pid
     self.exe_file = os.readlink('/proc/' + str(self.pid) + '/exe')
     ei_ident = open(self.exe_file, 'rb').read(elf.constants.EI_NIDENT)
     ei_ident = map(ord, ei_ident)
     if ei_ident[elf.constants.EI_CLASS] == elf.constants.ELFCLASS32:
         self.__arch__ = 'x86'
     elif ei_ident[elf.constants.EI_CLASS] == elf.constants.ELFCLASS64:
         if architecture_is_32bit(platform.machine()):
             raise LinuxProcessError(
                 'Controlling a 64-bit process from a 32-bit process is not supported'
             )
         self.__arch__ = 'x86_64'
     else:
         raise LinuxProcessError('Unsupported EI_CLASS ' +
                                 str(ei_ident[elf.constants.EI_CLASS]))
     if self._ptrace(PTRACE_ATTACH) != 0:
         Exception('could not open PID')
     os.waitpid(pid, 0)
     self._installed_hooks = []
     self._update_maps()
Esempio n. 2
0
 def get_proc_attribute(self, attribute):
     requested_attribute = attribute
     if attribute.startswith('&'):
         attribute = attribute[1:] + '_addr'
     if attribute.startswith('elf_'):
         if architecture_is_32bit(self.__arch__):
             attribute = 'elf32_' + attribute[4:]
         elif architecture_is_64bit(self.__arch__):
             attribute = 'elf64_' + attribute[4:]
     if hasattr(self, '_get_attr_' + attribute):
         return getattr(self, '_get_attr_' + attribute)()
     elif not attribute.endswith('_addr') and attribute.startswith(
             'elf32_'):
         if hasattr(self, '_get_attr_' + attribute + '_addr'):
             address = getattr(self, '_get_attr_' + attribute + '_addr')()
             attribute = 'Elf32_' + attribute[6:].title()
             if hasattr(elf, attribute):
                 return self._read_structure_from_memory(
                     address, getattr(elf, attribute))
     elif not attribute.endswith('_addr') and attribute.startswith(
             'elf64_'):
         if hasattr(self, '_get_attr_' + attribute + '_addr'):
             address = getattr(self, '_get_attr_' + attribute + '_addr')()
             attribute = 'Elf64_' + attribute[6:].title()
             if hasattr(elf, attribute):
                 return self._read_structure_from_memory(
                     address, getattr(elf, attribute))
     raise ProcessError('Unknown Attribute: ' + requested_attribute)
Esempio n. 3
0
def main():
	parser = argparse.ArgumentParser(
		description='syringe: library & shellcode injection utility',
		conflict_handler='resolve',
		epilog='The PID argument can be specified as -1 to inject into the context of the syringe process.'
	)
	parser.add_argument('-l', '--load', dest='library', action='store', help='load the library in the target process')
	shellcode_group = parser.add_mutually_exclusive_group()
	shellcode_group.add_argument('-i', '--inject', dest='shellcode', action='store', help='inject code into the process')
	shellcode_group.add_argument('-f', '--inject-file', dest='shellcode_file', type=argparse.FileType('rb'), help='inject code from a file into the process')
	parser.add_argument('-d', '--decode', dest='decode', action='store', choices=('b64', 'hex', 'raw'), default='b64', help='decode the shellcode prior to execution')
	parser.add_argument('pid', action='store', type=int, help='process to control')
	arguments = parser.parse_args()

	try:
		process_h = NativeProcess(pid=arguments.pid)
	except ProcessError as error:
		print("[-] {0}".format(error.msg))
		return
	print("[+] Opened a handle to pid: {0}".format(arguments.pid))

	if arguments.library:
		try:
			lib_h = process_h.load_library(arguments.library)
		except ProcessError as error:
			print("[-] {0}".format(error.msg))
		else:
			print("[+] Loaded {0} with handle 0x{1:08x}".format(arguments.library, lib_h))

	if arguments.shellcode or arguments.shellcode_file:
		if arguments.shellcode:
			shellcode = arguments.shellcode
		else:
			shellcode = arguments.shellcode_file.read()
			arguments.shellcode_file.close()
		if arguments.decode == 'b64':
			shellcode = shellcode.decode('base64')
		elif arguments.decode == 'hex':
			shellcode = shellcode.decode('hex')
		stub = "" # no stub by default
		if architecture_is_32bit(process_h.arch):
			stub = "\x8b\x44\x24\x04" # mov eax,[esp+4]
		elif architecture_is_64bit(process_h.arch):
			stub = "\x48\x8b\x44\x24\x08" # mov rax,[rsp+8]

		shellcode_sz = align_up(len(stub + shellcode), 1024)
		address = process_h.allocate(size=shellcode_sz, address=0)
		print("[+] Allocated {0} bytes at 0x{1:08x}".format(shellcode_sz, address))
		process_h.protect(address, size=shellcode_sz)
		process_h.write_memory(address, stub + shellcode)
		thread_id = process_h.start_thread(address, (address + len(stub)))
		print("[+] Started thread at 0x{0:08x}".format(address))
		print("[*] Waiting for thread to complete...")
		try:
			process_h.join_thread(thread_id)
			print("[+] Thread completed")
		except ProcessError as err:
			print("[-] {0} {1}".format(err.__class__.__name__, err.msg))

	process_h.close()
Esempio n. 4
0
def jump_stub(address):
    arch = platform.machine()
    if utilities.architecture_is_32bit(arch):
        stub = b'\xb8' + struct.pack('I', address)  # mov eax, address
        stub += b'\xff\xe0'  # jmp eax
    elif utilities.architecture_is_64bit(arch):
        stub = b'\x48\xb8' + struct.pack('Q', address)  # mov rax, address
        stub += b'\xff\xe0'  # jmp rax
    return stub
def jump_stub(address):
	arch = platform.machine()
	if utilities.architecture_is_32bit(arch):
		stub = b'\xb8' + struct.pack('I', address)      # mov eax, address
		stub += b'\xff\xe0'                             # jmp eax
	elif utilities.architecture_is_64bit(arch):
		stub = b'\x48\xb8' + struct.pack('Q', address)  # mov rax, address
		stub += b'\xff\xe0'                             # jmp rax
	return stub
Esempio n. 6
0
def jump_stub(address):
    arch = platform.machine()
    if utilities.architecture_is_32bit(arch):
        #ff is jump near with absolute addr, and also requires addr to be loaded into register before jumping
        stub = b'\xb8' + struct.pack('I', address)  # mov eax, address
        stub += b'\xff\xe0'  # jmp eax
    elif utilities.architecture_is_64bit(arch):
        stub = b'\x48\xb8' + struct.pack('Q', address)  # mov rax, address
        stub += b'\xff\xe0'  # jmp rax
    return stub
Esempio n. 7
0
	def __init__(self, pid=None, exe=None):
		if platform.system() != 'Linux':
			raise RuntimeError('incompatible platform')
		# Ensure that we are running in a version of python that matches the native architecture of the system.
		if platform.architecture()[0] == '32bit':
			if not architecture_is_32bit(platform.machine()):
				raise LinuxProcessError('Running a 32-bit version of Python on a non x86 system is not supported')
		elif platform.architecture()[0] == '64bit':
			if not architecture_is_64bit(platform.machine()):
				raise LinuxProcessError('Running a 64-bit version of Python on a non x86-64 system is not supported')
		else:
			raise LinuxProcessError('Could not determine the Python version')
		self._proc_h = None
		signal.signal(signal.SIGCHLD, self._signal_sigchld)
		if exe:
			self._proc_h = subprocess.Popen([exe], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
			pid = self._proc_h.pid
		if pid == -1:
			pid = os.fork()
			if pid == 0:
				select.select([], [], [], None)
			select.select([], [], [], 0.50)
		self.handle = pid
		self.pid = pid
		self.exe_file = os.readlink('/proc/' + str(self.pid) + '/exe')
		ei_ident = open(self.exe_file, 'rb').read(elf.constants.EI_NIDENT)
		ei_ident = map(ord, ei_ident)
		if ei_ident[elf.constants.EI_CLASS] == elf.constants.ELFCLASS32:
			self.__arch__ = 'x86'
		elif ei_ident[elf.constants.EI_CLASS] == elf.constants.ELFCLASS64:
			if architecture_is_32bit(platform.machine()):
				raise LinuxProcessError('Controlling a 64-bit process from a 32-bit process is not supported')
			self.__arch__ = 'x86_64'
		else:
			raise LinuxProcessError('Unsupported EI_CLASS ' + str(ei_ident[elf.constants.EI_CLASS]))
		if self._ptrace(PTRACE_ATTACH) != 0:
			Exception('could not open PID')
		os.waitpid(pid, 0)
		self._installed_hooks = []
		self._update_maps()
Esempio n. 8
0
	def install_hook(self, mod_name, new_address, name=None, ordinal=None):
		if architecture_is_32bit(self.__arch__):
			lm_struct = elf.Elf32_Link_Map
			dyn_struct = elf.Elf32_Dyn
			sym_struct = elf.Elf32_Sym
		elif architecture_is_64bit(self.__arch__):
			lm_struct = elf.Elf64_Link_Map
			dyn_struct = elf.Elf64_Dyn
			sym_struct = elf.Elf64_Sym
		else:
			raise LinuxProcessError('unsupported architecture: ' + repr(self.__arch__))
		if ordinal:
			raise NotImplementedError('an ordinal is not supported for this implementation')
		if not name:
			raise RuntimeError('a name is required for this implementation')
		lm = self._read_structure_from_memory(self.get_proc_attribute('link_map_addr'), lm_struct)
		if os.path.isabs(mod_name):
			validate_name = lambda lm: bool(self.read_memory_string(lm.l_name) == mod_name)
		else:
			validate_name = lambda lm: bool(os.path.split(self.read_memory_string(lm.l_name))[-1].startswith(mod_name))
		while not validate_name(lm):
			if lm.l_next == 0:
				raise ProcessError('unable to locate shared library')
			lm = self._read_structure_from_memory(lm.l_next, lm_struct)
		idx = 0
		dyn = self._read_structure_from_memory(lm.l_ld, dyn_struct)
		nchains = 0
		strtab = 0
		symtab = 0
		while dyn.d_tag:
			idx += 1
			if dyn.d_tag == elf.constants.DT_HASH:
				#nchains = struct.unpack('I', self.read_memory(dyn.d_un.d_ptr + lm.l_addr + ctypes.sizeof(ctypes.c_int), ctypes.sizeof(ctypes.c_int)))[0]
				nchains = struct.unpack('I', self.read_memory(dyn.d_un.d_ptr + ctypes.sizeof(ctypes.c_int), ctypes.sizeof(ctypes.c_int)))[0]
			elif dyn.d_tag == elf.constants.DT_STRTAB:
				strtab = dyn.d_un.d_ptr
			elif dyn.d_tag == elf.constants.DT_SYMTAB:
				symtab = dyn.d_un.d_ptr
			dyn = self._read_structure_from_memory(lm.l_ld + (ctypes.sizeof(dyn_struct) * idx), dyn_struct)
		for idx in xrange(0, nchains):
			sym = self._read_structure_from_memory(symtab + (ctypes.sizeof(sym_struct) * idx), sym_struct)
			if (sym.st_info & 0xf) != elf.constants.STT_FUNC:
				continue
			if self.read_memory_string(strtab + sym.st_name) == name:
				sym_addr = (symtab + (ctypes.sizeof(sym_struct) * idx))
				old_address = lm.l_addr + sym.st_value
				sym.st_value = (lm.l_addr - new_address)
				self.write_memory(sym_addr, struct_pack(sym))
				hook = Hook('eat', (sym_addr + sym_struct.st_value.offset), old_address, new_address)
				self._installed_hooks.append(hook)
				return hook
		raise ProcessError('unable to locate function')
Esempio n. 9
0
	def install_hook(self, mod_name, new_address, name=None, ordinal=None):
		if architecture_is_32bit(self.__arch__):
			lm_struct = elf.Elf32_Link_Map
			dyn_struct = elf.Elf32_Dyn
			sym_struct = elf.Elf32_Sym
		elif architecture_is_64bit(self.__arch__):
			lm_struct = elf.Elf64_Link_Map
			dyn_struct = elf.Elf64_Dyn
			sym_struct = elf.Elf64_Sym
		else:
			raise LinuxProcessError('unsupported architecture: ' + repr(self.__arch__))
		if ordinal:
			raise NotImplementedError('an ordinal is not supported for this implementation')
		if not name:
			raise RuntimeError('a name is required for this implementation')
		lm = self._read_structure_from_memory(self.get_proc_attribute('link_map_addr'), lm_struct)
		if os.path.isabs(mod_name):
			validate_name = lambda lm: bool(self.read_memory_string(lm.l_name) == mod_name)
		else:
			validate_name = lambda lm: bool(os.path.split(self.read_memory_string(lm.l_name))[-1].startswith(mod_name))
		while not validate_name(lm):
			if lm.l_next == 0:
				raise ProcessError('unable to locate shared library')
			lm = self._read_structure_from_memory(lm.l_next, lm_struct)
		idx = 0
		dyn = self._read_structure_from_memory(lm.l_ld, dyn_struct)
		nchains = 0
		strtab = 0
		symtab = 0
		while dyn.d_tag:
			idx += 1
			if dyn.d_tag == elf.constants.DT_HASH:
				#nchains = struct.unpack('I', self.read_memory(dyn.d_un.d_ptr + lm.l_addr + ctypes.sizeof(ctypes.c_int), ctypes.sizeof(ctypes.c_int)))[0]
				nchains = struct.unpack('I', self.read_memory(dyn.d_un.d_ptr + ctypes.sizeof(ctypes.c_int), ctypes.sizeof(ctypes.c_int)))[0]
			elif dyn.d_tag == elf.constants.DT_STRTAB:
				strtab = dyn.d_un.d_ptr
			elif dyn.d_tag == elf.constants.DT_SYMTAB:
				symtab = dyn.d_un.d_ptr
			dyn = self._read_structure_from_memory(lm.l_ld + (ctypes.sizeof(dyn_struct) * idx), dyn_struct)
		for idx in xrange(0, nchains):
			sym = self._read_structure_from_memory(symtab + (ctypes.sizeof(sym_struct) * idx), sym_struct)
			if (sym.st_info & 0xf) != elf.constants.STT_FUNC:
				continue
			if self.read_memory_string(strtab + sym.st_name) == name:
				sym_addr = (symtab + (ctypes.sizeof(sym_struct) * idx))
				old_address = lm.l_addr + sym.st_value
				sym.st_value = (lm.l_addr - new_address)
				self.write_memory(sym_addr, struct_pack(sym))
				hook = Hook('eat', (sym_addr + sym_struct.st_value.offset), old_address, new_address)
				self._installed_hooks.append(hook)
				return hook
		raise ProcessError('unable to locate function')
Esempio n. 10
0
	def _get_attr_got_addr(self):
		if architecture_is_32bit(self.__arch__):
			dyn_struct = elf.Elf32_Dyn
		elif architecture_is_64bit(self.__arch__):
			dyn_struct = elf.Elf64_Dyn
		else:
			raise LinuxProcessError('unsupported architecture: ' + repr(self.__arch__))
		dyn_addr = self.get_proc_attribute('elf_dyn_addr')
		dyn = self._read_structure_from_memory(dyn_addr, dyn_struct)
		idx = 0
		while dyn.d_tag != elf.constants.DT_PLTGOT:
			idx += 1
			next_dyn_addr = dyn_addr + (ctypes.sizeof(dyn_struct) * idx)
			dyn = self._read_structure_from_memory(next_dyn_addr, dyn_struct)
		return dyn.d_un.d_ptr
Esempio n. 11
0
	def _get_attr_got_addr(self):
		if architecture_is_32bit(self.__arch__):
			dyn_struct = elf.Elf32_Dyn
		elif architecture_is_64bit(self.__arch__):
			dyn_struct = elf.Elf64_Dyn
		else:
			raise LinuxProcessError('unsupported architecture: ' + repr(self.__arch__))
		dyn_addr = self.get_proc_attribute('elf_dyn_addr')
		dyn = self._read_structure_from_memory(dyn_addr, dyn_struct)
		idx = 0
		while dyn.d_tag != elf.constants.DT_PLTGOT:
			idx += 1
			next_dyn_addr = dyn_addr + (ctypes.sizeof(dyn_struct) * idx)
			dyn = self._read_structure_from_memory(next_dyn_addr, dyn_struct)
		return dyn.d_un.d_ptr
Esempio n. 12
0
 def _call_function(self, function_address, *args):
     if len(args) > 6:
         raise Exception('can not pass more than 6 arguments')
     registers_backup = self._get_registers()
     if architecture_is_32bit(self.__arch__):
         registers = {'eip': function_address, 'eax': function_address}
         self._set_registers(registers)
         backup_sp = self.read_memory(registers_backup['esp'], 4)
         self.write_memory(registers_backup['esp'], '\x00\x00\x00\x00')
         for i in range(len(args)):
             stack_cursor = registers_backup['esp'] + ((i + 1) * 4)
             backup_sp += self.read_memory(stack_cursor, 4)
             if args[i] < 0:
                 self.write_memory(stack_cursor, struct.pack('i', args[i]))
             else:
                 self.write_memory(stack_cursor, struct.pack('I', args[i]))
         self._ptrace(PTRACE_CONT)
         wait_result = os.waitpid(self.pid, 0)
         self.write_memory(registers_backup['esp'], backup_sp)
         ending_ip = self._get_registers()['eip']
         result = self._get_registers()['eax']
     elif architecture_is_64bit(self.__arch__):
         registers = {'rip': function_address, 'rax': function_address}
         arg_registers = ['rdi', 'rsi', 'rdx', 'rcx', 'r8', 'r9']
         for i in range(len(args)):
             registers[arg_registers[i]] = args[i]
         self._set_registers(registers)
         backup_sp = self.read_memory(registers_backup['rsp'], 8)
         self.write_memory(registers_backup['rsp'],
                           '\x00\x00\x00\x00\x00\x00\x00\x00')
         self._ptrace(PTRACE_CONT)
         wait_result = os.waitpid(self.pid, 0)
         self.write_memory(registers_backup['rsp'], backup_sp)
         ending_ip = self._get_registers()['rip']
         result = self._get_registers()['rax']
     self._set_registers(registers_backup)
     if (os.WSTOPSIG(wait_result[1])
             == signal.SIGSEGV) and (ending_ip != 0):
         raise LinuxProcessError('segmentation fault')
     return result
Esempio n. 13
0
	def _call_function(self, function_address, *args):
		if len(args) > 6:
			raise Exception('can not pass more than 6 arguments')
		registers_backup = self._get_registers()
		if architecture_is_32bit(self.__arch__):
			registers = {'eip': function_address, 'eax': function_address}
			self._set_registers(registers)
			backup_sp = self.read_memory(registers_backup['esp'], 4)
			self.write_memory(registers_backup['esp'], '\x00\x00\x00\x00')
			for i in range(len(args)):
				stack_cursor = registers_backup['esp'] + ((i + 1) * 4)
				backup_sp += self.read_memory(stack_cursor, 4)
				if args[i] < 0:
					self.write_memory(stack_cursor, struct.pack('i', args[i]))
				else:
					self.write_memory(stack_cursor, struct.pack('I', args[i]))
			self._ptrace(PTRACE_CONT)
			wait_result = os.waitpid(self.pid, 0)
			self.write_memory(registers_backup['esp'], backup_sp)
			ending_ip = self._get_registers()['eip']
			result = self._get_registers()['eax']
		elif architecture_is_64bit(self.__arch__):
			registers = {'rip': function_address, 'rax': function_address}
			arg_registers = ['rdi', 'rsi', 'rdx', 'rcx', 'r8', 'r9']
			for i in range(len(args)):
				registers[arg_registers[i]] = args[i]
			self._set_registers(registers)
			backup_sp = self.read_memory(registers_backup['rsp'], 8)
			self.write_memory(registers_backup['rsp'], '\x00\x00\x00\x00\x00\x00\x00\x00')
			self._ptrace(PTRACE_CONT)
			wait_result = os.waitpid(self.pid, 0)
			self.write_memory(registers_backup['rsp'], backup_sp)
			ending_ip = self._get_registers()['rip']
			result = self._get_registers()['rax']
		self._set_registers(registers_backup)
		if (os.WSTOPSIG(wait_result[1]) == signal.SIGSEGV) and (ending_ip != 0):
			raise LinuxProcessError('segmentation fault')
		return result
Esempio n. 14
0
	def get_proc_attribute(self, attribute):
		requested_attribute = attribute
		if attribute.startswith('&'):
			attribute = attribute[1:] + '_addr'
		if attribute.startswith('elf_'):
			if architecture_is_32bit(self.__arch__):
				attribute = 'elf32_' + attribute[4:]
			elif architecture_is_64bit(self.__arch__):
				attribute = 'elf64_' + attribute[4:]
		if hasattr(self, '_get_attr_' + attribute):
			return getattr(self, '_get_attr_' + attribute)()
		elif not attribute.endswith('_addr') and attribute.startswith('elf32_'):
			if hasattr(self, '_get_attr_' + attribute + '_addr'):
				address = getattr(self, '_get_attr_' + attribute + '_addr')()
				attribute = 'Elf32_' + attribute[6:].title()
				if hasattr(elf, attribute):
					return self._read_structure_from_memory(address, getattr(elf, attribute))
		elif not attribute.endswith('_addr') and attribute.startswith('elf64_'):
			if hasattr(self, '_get_attr_' + attribute + '_addr'):
				address = getattr(self, '_get_attr_' + attribute + '_addr')()
				attribute = 'Elf64_' + attribute[6:].title()
				if hasattr(elf, attribute):
					return self._read_structure_from_memory(address, getattr(elf, attribute))
		raise ProcessError('Unknown Attribute: ' + requested_attribute)
Esempio n. 15
0
def main():
    parser = argparse.ArgumentParser(
        description='syringe: library & shellcode injection utility',
        conflict_handler='resolve',
        epilog=
        'The PID argument can be specified as -1 to inject into the context of the syringe process.'
    )
    parser.add_argument('-l',
                        '--load',
                        dest='library',
                        action='store',
                        help='load the library in the target process')
    shellcode_group = parser.add_mutually_exclusive_group()
    shellcode_group.add_argument('-i',
                                 '--inject',
                                 dest='shellcode',
                                 action='store',
                                 help='inject code into the process')
    shellcode_group.add_argument(
        '-f',
        '--inject-file',
        dest='shellcode_file',
        type=argparse.FileType('rb'),
        help='inject code from a file into the process')
    parser.add_argument('-d',
                        '--decode',
                        dest='decode',
                        action='store',
                        choices=('b64', 'hex', 'raw'),
                        default='b64',
                        help='decode the shellcode prior to execution')
    parser.add_argument('pid',
                        action='store',
                        type=int,
                        help='process to control')
    arguments = parser.parse_args()

    try:
        process_h = NativeProcess(pid=arguments.pid)
    except ProcessError as error:
        print("[-] {0}".format(error.msg))
        return
    print("[+] Opened a handle to pid: {0}".format(arguments.pid))

    if arguments.library:
        try:
            lib_h = process_h.load_library(arguments.library)
        except ProcessError as error:
            print("[-] {0}".format(error.msg))
        else:
            print("[+] Loaded {0} with handle 0x{1:08x}".format(
                arguments.library, lib_h))

    if arguments.shellcode or arguments.shellcode_file:
        if arguments.shellcode:
            shellcode = arguments.shellcode
        else:
            shellcode = arguments.shellcode_file.read()
            arguments.shellcode_file.close()
        if arguments.decode == 'b64':
            shellcode = shellcode.decode('base64')
        elif arguments.decode == 'hex':
            shellcode = shellcode.decode('hex')
        stub = ''  # no stub by default
        if architecture_is_32bit(process_h.arch):
            stub = b'\x8b\x44\x24\x04'  # mov eax,[esp+4]
        elif architecture_is_64bit(process_h.arch):
            stub = b'\x48\x8b\x44\x24\x08'  # mov rax,[rsp+8]

        shellcode_sz = align_up(len(stub + shellcode), 1024)
        address = process_h.allocate(size=shellcode_sz, address=0)
        print("[+] Allocated {0} bytes at 0x{1:08x}".format(
            shellcode_sz, address))
        process_h.protect(address, size=shellcode_sz)
        process_h.write_memory(address, stub + shellcode)
        thread_id = process_h.start_thread(address, (address + len(stub)))
        print("[+] Started thread at 0x{0:08x}".format(address))
        print("[*] Waiting for thread to complete...")
        try:
            process_h.join_thread(thread_id)
            print("[+] Thread completed")
        except ProcessError as err:
            print("[-] {0} {1}".format(err.__class__.__name__, err.msg))

    process_h.close()
Esempio n. 16
0
def architecture_is_supported(arch):
    return architecture_is_32bit(arch) or architecture_is_64bit(arch)
Esempio n. 17
0
	def _set_registers(self, registers={}):
		if not architecture_is_supported(self.__arch__):
			raise LinuxProcessError('unsupported architecture: ' + repr(self.__arch__))
		old_registers = self._get_registers()
		old_registers.update(registers)
		_raw_registers = (ctypes.c_ulong * 32)
		raw_registers = _raw_registers()
		# constants from sys/reg.h
		if architecture_is_32bit(platform.machine()):
			raw_registers[0] = old_registers['ebx']
			raw_registers[1] = old_registers['ecx']
			raw_registers[2] = old_registers['edx']
			raw_registers[3] = old_registers['esi']
			raw_registers[4] = old_registers['edi']
			raw_registers[5] = old_registers['ebp']
			raw_registers[6] = old_registers['eax']
			raw_registers[7] = old_registers['ds']
			raw_registers[8] = old_registers['es']
			raw_registers[9] = old_registers['fs']
			raw_registers[10] = old_registers['gs']
			raw_registers[11] = old_registers['orig_eax']
			raw_registers[12] = old_registers['eip']
			raw_registers[13] = old_registers['cs']
			raw_registers[14] = old_registers['eflags']
			raw_registers[15] = old_registers['esp']
			raw_registers[16] = old_registers['ss']
		elif architecture_is_64bit(platform.machine()):
			if architecture_is_32bit(self.__arch__):
				_raw_registers = (ctypes.c_ulong * 32)
				raw_registers = _raw_registers()
				if self._ptrace(PTRACE_GETREGS, 0, ctypes.byref(raw_registers)) != 0:
					raise LinuxProcessError('Error: PTRACE_GETREGS', errno=get_errno())
				raw_registers[4] = old_registers['ebp']
				raw_registers[5] = old_registers['ebx']
				raw_registers[10] = old_registers['eax']
				raw_registers[11] = old_registers['ecx']
				raw_registers[12] = old_registers['edx']
				raw_registers[13] = old_registers['esi']
				raw_registers[14] = old_registers['edi']
				raw_registers[15] = old_registers['orig_eax']
				raw_registers[16] = old_registers['eip']
				raw_registers[17] = old_registers['cs']
				raw_registers[18] = old_registers['eflags']
				raw_registers[19] = old_registers['esp']
				raw_registers[20] = old_registers['ss']
				raw_registers[23] = old_registers['ds']
				raw_registers[24] = old_registers['es']
				raw_registers[25] = old_registers['fs']
				raw_registers[26] = old_registers['gs']
			else:
				raw_registers[0] = old_registers['r15']
				raw_registers[1] = old_registers['r14']
				raw_registers[2] = old_registers['r13']
				raw_registers[3] = old_registers['r12']
				raw_registers[4] = old_registers['rbp']
				raw_registers[5] = old_registers['rbx']
				raw_registers[6] = old_registers['r11']
				raw_registers[7] = old_registers['r10']
				raw_registers[8] = old_registers['r9']
				raw_registers[9] = old_registers['r8']
				raw_registers[10] = old_registers['rax']
				raw_registers[11] = old_registers['rcx']
				raw_registers[12] = old_registers['rdx']
				raw_registers[13] = old_registers['rsi']
				raw_registers[14] = old_registers['rdi']
				raw_registers[15] = old_registers['orig_rax']
				raw_registers[16] = old_registers['rip']
				raw_registers[17] = old_registers['cs']
				raw_registers[18] = old_registers['eflags']
				raw_registers[19] = old_registers['rsp']
				raw_registers[20] = old_registers['ss']
				raw_registers[21] = old_registers['fs_base']
				raw_registers[22] = old_registers['gs_base']
				raw_registers[23] = old_registers['ds']
				raw_registers[24] = old_registers['es']
				raw_registers[25] = old_registers['fs']
				raw_registers[26] = old_registers['gs']
		if self._ptrace(PTRACE_SETREGS, 0, ctypes.byref(raw_registers)) != 0:
			raise LinuxProcessError('Error: PTRACE_SETREGS', errno=get_errno())
		return
Esempio n. 18
0
	def _get_function_address(self, mod_name, func_name):
		if architecture_is_32bit(self.__arch__):
			ehdr_struct = elf.Elf32_Ehdr
			shdr_struct = elf.Elf32_Shdr
			sym_struct = elf.Elf32_Sym
		elif architecture_is_64bit(self.__arch__):
			ehdr_struct = elf.Elf64_Ehdr
			shdr_struct = elf.Elf64_Shdr
			sym_struct = elf.Elf64_Sym
		else:
			raise LinuxProcessError('unsupported architecture: ' + repr(self.__arch__))

		ehdr_addr = None
		if os.path.isabs(mod_name):
			exe_maps = filter(lambda x: x.pathname == mod_name, self.maps.values())
			filename = mod_name
		else:
			exe_maps = filter(lambda x: x.pathname != None and os.path.basename(x.pathname).startswith(mod_name), self.maps.values())
			filename = exe_maps[0].pathname
		handle = open(filename, 'rb')
		ehdr = struct_unpack(ehdr_struct, handle.read(ctypes.sizeof(ehdr_struct)))

		# get the shdrs
		handle.seek(ehdr.e_shoff, os.SEEK_SET)
		data = handle.read(ehdr.e_shnum * ehdr.e_shentsize)
		_shdrs = (shdr_struct * ehdr.e_shnum)
		shdrs = _shdrs()
		ctypes.memmove(ctypes.byref(shdrs), data, len(data))

		strtab = 0
		symtab = 0
		for idx in range(len(shdrs)):
			shdr = shdrs[idx]
			if shdr.sh_type == elf.constants.SHT_SYMTAB or shdr.sh_type == elf.constants.SHT_DYNSYM:
				if not (shdr.sh_entsize and shdr.sh_size):
					continue
				symtab = idx
			elif shdr.sh_type == elf.constants.SHT_STRTAB:
				if idx != ehdr.e_shstrndx:
					strtab = idx
			if symtab == 0 or strtab == 0:
				continue
			symh = shdrs[symtab]
			strh = shdrs[strtab]
			handle.seek(strh.sh_offset, os.SEEK_SET)
			strsymtbl = handle.read(strh.sh_size)
			sym_num = symh.sh_size / symh.sh_entsize
			_syms = (sym_struct * sym_num)
			syms = _syms()
			handle.seek(symh.sh_offset, os.SEEK_SET)
			ctypes.memmove(ctypes.byref(syms), handle.read(ctypes.sizeof(syms)), ctypes.sizeof(syms))
			for idx in range(1, len(syms)):
				sym = syms[idx]
				name = ""
				if sym.st_name == 0:
					continue
				name_end = strsymtbl.find('\x00', sym.st_name)
				if strsymtbl[sym.st_name:name_end] != func_name:
					continue
				address = sym.st_value
				if filter(lambda mr: (address > mr.addr_low and address < mr.addr_high), exe_maps):
					return address
				else:
					return address + sorted(exe_maps, key=lambda mr: mr.addr_low)[0].addr_low
			strtab = 0
			symtab = 0
		raise ProcessError('unable to locate function')
Esempio n. 19
0
	def _get_attr_link_map_addr(self):
		got_addr = self.get_proc_attribute('got_addr')
		if architecture_is_32bit(self.__arch__):
			return struct.unpack('II', self.read_memory(got_addr, 8))[1]
		elif architecture_is_64bit(self.__arch__):
			return struct.unpack('QQ', self.read_memory(got_addr, 16))[1]
Esempio n. 20
0
 def _get_attr_link_map_addr(self):
     got_addr = self.get_proc_attribute('got_addr')
     if architecture_is_32bit(self.__arch__):
         return struct.unpack('II', self.read_memory(got_addr, 8))[1]
     elif architecture_is_64bit(self.__arch__):
         return struct.unpack('QQ', self.read_memory(got_addr, 16))[1]
Esempio n. 21
0
    def _get_function_address(self, mod_name, func_name):
        if architecture_is_32bit(self.__arch__):
            ehdr_struct = elf.Elf32_Ehdr
            shdr_struct = elf.Elf32_Shdr
            sym_struct = elf.Elf32_Sym
        elif architecture_is_64bit(self.__arch__):
            ehdr_struct = elf.Elf64_Ehdr
            shdr_struct = elf.Elf64_Shdr
            sym_struct = elf.Elf64_Sym
        else:
            raise LinuxProcessError('unsupported architecture: ' +
                                    repr(self.__arch__))

        ehdr_addr = None
        if os.path.isabs(mod_name):
            exe_maps = filter(lambda x: x.pathname == mod_name,
                              self.maps.values())
            filename = mod_name
        else:
            exe_maps = filter(
                lambda x: x.pathname != None and os.path.basename(x.pathname).
                startswith(mod_name), self.maps.values())
            filename = exe_maps[0].pathname
        handle = open(filename, 'rb')
        ehdr = struct_unpack(ehdr_struct,
                             handle.read(ctypes.sizeof(ehdr_struct)))

        # get the shdrs
        handle.seek(ehdr.e_shoff, os.SEEK_SET)
        data = handle.read(ehdr.e_shnum * ehdr.e_shentsize)
        _shdrs = (shdr_struct * ehdr.e_shnum)
        shdrs = _shdrs()
        ctypes.memmove(ctypes.byref(shdrs), data, len(data))

        strtab = 0
        symtab = 0
        for idx in range(len(shdrs)):
            shdr = shdrs[idx]
            if shdr.sh_type == elf.constants.SHT_SYMTAB or shdr.sh_type == elf.constants.SHT_DYNSYM:
                if not (shdr.sh_entsize and shdr.sh_size):
                    continue
                symtab = idx
            elif shdr.sh_type == elf.constants.SHT_STRTAB:
                if idx != ehdr.e_shstrndx:
                    strtab = idx
            if symtab == 0 or strtab == 0:
                continue
            symh = shdrs[symtab]
            strh = shdrs[strtab]
            handle.seek(strh.sh_offset, os.SEEK_SET)
            strsymtbl = handle.read(strh.sh_size)
            sym_num = symh.sh_size / symh.sh_entsize
            _syms = (sym_struct * sym_num)
            syms = _syms()
            handle.seek(symh.sh_offset, os.SEEK_SET)
            ctypes.memmove(ctypes.byref(syms),
                           handle.read(ctypes.sizeof(syms)),
                           ctypes.sizeof(syms))
            for idx in range(1, len(syms)):
                sym = syms[idx]
                name = ""
                if sym.st_name == 0:
                    continue
                name_end = strsymtbl.find('\x00', sym.st_name)
                if strsymtbl[sym.st_name:name_end] != func_name:
                    continue
                address = sym.st_value
                if filter(
                        lambda mr:
                    (address > mr.addr_low and address < mr.addr_high),
                        exe_maps):
                    return address
                else:
                    return address + sorted(
                        exe_maps, key=lambda mr: mr.addr_low)[0].addr_low
            strtab = 0
            symtab = 0
        raise ProcessError('unable to locate function')
Esempio n. 22
0
def architecture_is_supported(arch):
	return architecture_is_32bit(arch) or architecture_is_64bit(arch)
Esempio n. 23
0
 def _set_registers(self, registers={}):
     if not architecture_is_supported(self.__arch__):
         raise LinuxProcessError('unsupported architecture: ' +
                                 repr(self.__arch__))
     old_registers = self._get_registers()
     old_registers.update(registers)
     _raw_registers = (ctypes.c_ulong * 32)
     raw_registers = _raw_registers()
     # constants from sys/reg.h
     if architecture_is_32bit(platform.machine()):
         raw_registers[0] = old_registers['ebx']
         raw_registers[1] = old_registers['ecx']
         raw_registers[2] = old_registers['edx']
         raw_registers[3] = old_registers['esi']
         raw_registers[4] = old_registers['edi']
         raw_registers[5] = old_registers['ebp']
         raw_registers[6] = old_registers['eax']
         raw_registers[7] = old_registers['ds']
         raw_registers[8] = old_registers['es']
         raw_registers[9] = old_registers['fs']
         raw_registers[10] = old_registers['gs']
         raw_registers[11] = old_registers['orig_eax']
         raw_registers[12] = old_registers['eip']
         raw_registers[13] = old_registers['cs']
         raw_registers[14] = old_registers['eflags']
         raw_registers[15] = old_registers['esp']
         raw_registers[16] = old_registers['ss']
     elif architecture_is_64bit(platform.machine()):
         if architecture_is_32bit(self.__arch__):
             _raw_registers = (ctypes.c_ulong * 32)
             raw_registers = _raw_registers()
             if self._ptrace(PTRACE_GETREGS, 0,
                             ctypes.byref(raw_registers)) != 0:
                 raise LinuxProcessError('Error: PTRACE_GETREGS',
                                         errno=get_errno())
             raw_registers[4] = old_registers['ebp']
             raw_registers[5] = old_registers['ebx']
             raw_registers[10] = old_registers['eax']
             raw_registers[11] = old_registers['ecx']
             raw_registers[12] = old_registers['edx']
             raw_registers[13] = old_registers['esi']
             raw_registers[14] = old_registers['edi']
             raw_registers[15] = old_registers['orig_eax']
             raw_registers[16] = old_registers['eip']
             raw_registers[17] = old_registers['cs']
             raw_registers[18] = old_registers['eflags']
             raw_registers[19] = old_registers['esp']
             raw_registers[20] = old_registers['ss']
             raw_registers[23] = old_registers['ds']
             raw_registers[24] = old_registers['es']
             raw_registers[25] = old_registers['fs']
             raw_registers[26] = old_registers['gs']
         else:
             raw_registers[0] = old_registers['r15']
             raw_registers[1] = old_registers['r14']
             raw_registers[2] = old_registers['r13']
             raw_registers[3] = old_registers['r12']
             raw_registers[4] = old_registers['rbp']
             raw_registers[5] = old_registers['rbx']
             raw_registers[6] = old_registers['r11']
             raw_registers[7] = old_registers['r10']
             raw_registers[8] = old_registers['r9']
             raw_registers[9] = old_registers['r8']
             raw_registers[10] = old_registers['rax']
             raw_registers[11] = old_registers['rcx']
             raw_registers[12] = old_registers['rdx']
             raw_registers[13] = old_registers['rsi']
             raw_registers[14] = old_registers['rdi']
             raw_registers[15] = old_registers['orig_rax']
             raw_registers[16] = old_registers['rip']
             raw_registers[17] = old_registers['cs']
             raw_registers[18] = old_registers['eflags']
             raw_registers[19] = old_registers['rsp']
             raw_registers[20] = old_registers['ss']
             raw_registers[21] = old_registers['fs_base']
             raw_registers[22] = old_registers['gs_base']
             raw_registers[23] = old_registers['ds']
             raw_registers[24] = old_registers['es']
             raw_registers[25] = old_registers['fs']
             raw_registers[26] = old_registers['gs']
     if self._ptrace(PTRACE_SETREGS, 0, ctypes.byref(raw_registers)) != 0:
         raise LinuxProcessError('Error: PTRACE_SETREGS', errno=get_errno())
     return