def load_library(self, libpath): libpath = os.path.abspath(libpath) libpath_len = align_up(len(libpath) + 1, 0x200) LoadLibraryA = self.k32.GetProcAddress( self.k32.GetModuleHandleA("kernel32.dll"), "LoadLibraryA") RemotePage = self.k32.VirtualAllocEx(self.handle, None, len(libpath) + 1, flags("MEM_COMMIT"), flags("PAGE_EXECUTE_READWRITE")) if not RemotePage: raise WindowsProcessError( 'Error: failed to allocate space for library name in the target process' ) self.k32.WriteProcessMemory(self.handle, RemotePage, libpath, len(libpath), None) RemoteThread = self.k32.CreateRemoteThread(self.handle, None, 0, LoadLibraryA, RemotePage, 0, None) self.k32.WaitForSingleObject(RemoteThread, -1) exitcode = wintypes.DWORD(0) self.k32.GetExitCodeThread(RemoteThread, ctypes.byref(exitcode)) self.k32.VirtualFreeEx(self.handle, RemotePage, len(libpath), flags("MEM_RELEASE")) if exitcode.value == 0: raise WindowsProcessError('Error: failed to load: ' + repr(libpath)) self._update_maps() return exitcode.value
def __init__(self, os_name=None): """ :param str os_name: The name of the Windows operating system for which to resolve syscall names to numbers. """ if process_is_wow64(): raise RuntimeError('python running in WOW64 is not supported') self._syscall_db_con = None if os_name is None: os_name = self.__name_map.get(platform.platform()) if os_name is not None: self._syscall_db_con = sqlite3.connect(self._syscall_db_path, check_same_thread=False) if not self._syscall_db_con.execute( 'SELECT COUNT(os_name) FROM syscalls WHERE arch = ? AND os_name = ?', ( self._syscall_arch, os_name, )).fetchone()[0]: raise ValueError( 'no syscall numbers available in the database for ' + os_name) self.os_name = os_name process_h = WindowsProcess(pid=-1) shellcode_sz = align_up(len(self._syscall_stub), 1024) self.address = process_h.allocate(size=shellcode_sz) process_h.write_memory(self.address, self._syscall_stub) process_h.protect(self.address, size=shellcode_sz, permissions='PAGE_EXECUTE_READ') self._syscall = self._syscall_prototype(self.address)
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()
def main(): parser = argparse.ArgumentParser( description='memgrep: memory search utility', conflict_handler='resolve') parser.add_argument('pid', action='store', type=int, help='process to control') parser.add_argument('search_data', action='store', help='data to search for') parser.add_argument('-e', '--encoding', default='utf-8', help='the encoding of search_data') arguments = parser.parse_args() search_data = arguments.search_data.encode(arguments.encoding) if len(search_data) < 4: print( '[-] searching for less than 4 bytes will yield too many results') return 0 process_h = NativeProcess(pid=arguments.pid) print("[*] searching {0} regions of memory".format(len(process_h.maps))) num_matches = 0 num_skips = 0 num_errors = 0 for mem_region in process_h.maps.values(): print("[*] searching 0x{0:08x} - 0x{1:08x} (0x{2:08x} bytes)".format( mem_region.addr_low, mem_region.addr_high, mem_region.size)) if not mem_region.is_readable: print("[-] skipped unreadable region at 0x{0:08x}".format( mem_region.addr_low)) num_skips += 1 continue try: data = process_h.read_memory(mem_region.addr_low, mem_region.size) except ProcessError as error: print("[-] encountered {0} while reading at 0x{1:08x}".format( error.__class__.__name__, mem_region.addr_low)) num_errors += 1 continue cursor = data.find(search_data) while cursor != -1: data_slice = data[align_down(cursor):align_up(cursor + len(search_data))] low_addr = align_down(mem_region.addr_low + align_down(cursor)) print("[+] found match at 0x{0:08x}".format(mem_region.addr_low + cursor)) num_matches += 1 print_hexdump(data_slice, low_addr) cursor = data.find(search_data, cursor + 1) process_h.close() print("[*] summary - matches: {0} errors: {1} skipped regions: {2}".format( num_matches, num_errors, num_skips))
def __init__(self, syscall_map=None): self.syscall_map = syscall_map process_h = WindowsProcess(pid=-1) shellcode_sz = align_up(len(syscall_stub), 1024) self.address = process_h.allocate(size=shellcode_sz) process_h.write_memory(self.address, syscall_stub) process_h.protect(self.address, size=shellcode_sz, permissions='PAGE_EXECUTE_READ') self._syscall = syscall_prototype(self.address)
def main(): parser = ArgumentParser(description='python_injector: inject python code into a process', conflict_handler='resolve') parser.add_argument('shellcode', action='store', help='python code to inject into the process') parser.add_argument('pid', action='store', type=int, help='process to inject into') arguments = parser.parse_args() if not sys.platform.startswith('win'): print('[-] This tool is only available on Windows') return # get a handle the the process 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)) # find and inject the python library python_lib = "python{0}{1}.dll".format(sys.version_info.major, sys.version_info.minor) python_lib = ctypes.util.find_library(python_lib) if python_lib: print("[*] Found Python library at: {0}".format(python_lib)) else: print('[-] Failed to find the Python library') return print('[*] Injecting Python into the process...') try: python_lib_h = process_h.load_library(python_lib) except ProcessError as error: print("[-] {0}".format(error.msg)) return else: print("[+] Loaded {0} with handle 0x{1:08x}".format(python_lib, python_lib_h)) # resolve the necessary functions k32 = ctypes.windll.kernel32 local_handle = k32.GetModuleHandleA(python_lib) py_initialize_ex = python_lib_h + (k32.GetProcAddress(local_handle, 'Py_InitializeEx') - local_handle) py_run_simple_string = python_lib_h + (k32.GetProcAddress(local_handle, 'PyRun_SimpleString') - local_handle) print('[*] Resolved address:') print(" - Py_InitializeEx: 0x{0:08x}".format(py_initialize_ex)) print(" - PyRun_SimpleString: 0x{0:08x}".format(py_run_simple_string)) # call remote functions to initialize and run via remote threads thread_h = process_h.start_thread(py_initialize_ex, 0) process_h.join_thread(thread_h) shellcode = arguments.shellcode shellcode_addr = process_h.allocate(size=align_up(len(shellcode)), permissions='PAGE_READWRITE') process_h.write_memory(shellcode_addr, shellcode) thread_h = process_h.start_thread(py_run_simple_string, shellcode_addr) process_h.join_thread(thread_h) process_h.close()
def load_library(self, libpath): libpath = os.path.abspath(libpath) libpath_len = align_up(len(libpath) + 1, 0x200) LoadLibraryA = self.k32.GetProcAddress(self.k32.GetModuleHandleA("kernel32.dll"), "LoadLibraryA") RemotePage = self.k32.VirtualAllocEx(self.handle, None, len(libpath) + 1, flags("MEM_COMMIT"), flags("PAGE_EXECUTE_READWRITE")) if not RemotePage: raise WindowsProcessError('Error: failed to allocate space for library name in the target process') self.k32.WriteProcessMemory(self.handle, RemotePage, libpath, len(libpath), None) RemoteThread = self.k32.CreateRemoteThread(self.handle, None, 0, LoadLibraryA, RemotePage, 0, None) self.k32.WaitForSingleObject(RemoteThread, -1) exitcode = wintypes.DWORD(0) self.k32.GetExitCodeThread(RemoteThread, ctypes.byref(exitcode)) self.k32.VirtualFreeEx(self.handle, RemotePage, len(libpath), flags("MEM_RELEASE")) if exitcode.value == 0: raise WindowsProcessError('Error: failed to load: ' + repr(libpath)) self._update_maps() return exitcode.value
def main(): parser = ArgumentParser(description='memgrep: memory search utility', conflict_handler='resolve') parser.add_argument('pid', action='store', type=int, help='process to control') parser.add_argument('search_data', action='store', help='data to search for') arguments = parser.parse_args() search_data = arguments.search_data if len(search_data) < 4: print('[-] searching for less than 4 bytes will yield too many results') return 0 process_h = NativeProcess(pid=arguments.pid) print("[*] searching {0} regions of memory".format(len(process_h.maps))) num_matches = 0 num_skips = 0 num_errors = 0 mem_region_keys = process_h.maps.keys() mem_region_keys.sort() for mr in mem_region_keys: mem_region = process_h.maps[mr] print("[*] searching 0x{0:04x} bytes at 0x{1:08x}".format(mem_region.size, mem_region.addr_low)) if not mem_region.is_readable: print("[-] skipped unreadable region at 0x{0:08x}".format(mem_region.addr_low)) num_skips += 1 continue try: data = process_h.read_memory(mem_region.addr_low, mem_region.size) except ProcessError as err: print("[-] encountered {0} while reading at 0x{1:08x}".format(err.__class__.__name__, mem_region.addr_low)) num_errors += 1 continue cursor = data.find(search_data) while cursor != -1: data_slice = data[align_down(cursor):align_up(cursor + len(search_data))] low_addr = align_down(mem_region.addr_low + align_down(cursor)) print("[+] found match at 0x{0:08x}".format(mem_region.addr_low + cursor)) num_matches += 1 print_hexdump(data_slice, low_addr) cursor = data.find(search_data, cursor + 1) process_h.close() print("[*] summary - matches: {0} errors: {1} skipped regions: {2}".format(num_matches, num_errors, num_skips))
def __init__(self, os_name=None): """ :param str os_name: The name of the Windows operating system for which to resolve syscall names to numbers. """ if process_is_wow64(): raise RuntimeError('python running in WOW64 is not supported') self._syscall_db_con = None if os_name is not None: self._syscall_db_con = sqlite3.connect(self._syscall_db_path, check_same_thread=False) if not self._syscall_db_con.execute('SELECT COUNT(os_name) FROM syscalls WHERE arch = ? AND os_name = ?', (self._syscall_arch, os_name,)).fetchone()[0]: raise ValueError('no syscall numbers available in the database for ' + os_name) self.os_name = os_name process_h = WindowsProcess(pid=-1) shellcode_sz = align_up(len(self._syscall_stub), 1024) self.address = process_h.allocate(size=shellcode_sz) process_h.write_memory(self.address, self._syscall_stub) process_h.protect(self.address, size=shellcode_sz, permissions='PAGE_EXECUTE_READ') self._syscall = self._syscall_prototype(self.address)
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()
def main(): parser = argparse.ArgumentParser( description='python_injector: inject python code into a process', conflict_handler='resolve') parser.add_argument('script_path', action='store', help='python script to inject into the process') parser.add_argument('procname', action='store', help='process to inject into') parser.epilog = 'The __name__ variable will be set to "__mayhem__".' arguments = parser.parse_args() if not sys.platform.startswith('win'): print('[-] This tool is only available on Windows') return proc_pid = getpid(arguments.procname) if proc_pid is None: print("Cant find process") sys.exit(1) else: print(f"PID is : {proc_pid}") # get a handle the the process try: process_h = WindowsProcess(pid=proc_pid) except ProcessError as error: print("[-] {0}".format(error.msg)) return print("[+] Opened a handle to pid: {0}".format(proc_pid)) # find and inject the python library python_lib = "python{0}{1}.dll".format(sys.version_info.major, sys.version_info.minor) python_lib = ctypes.util.find_library(python_lib) if python_lib: print("[*] Found Python library at: {0}".format(python_lib)) else: print('[-] Failed to find the Python library') return print('[*] Injecting Python into the process...') try: python_lib_h = process_h.load_library(python_lib) except ProcessError as error: print("[-] {0}".format(error.msg)) return else: print("[+] Loaded {0} with handle 0x{1:08x}".format( python_lib, python_lib_h)) # resolve the necessary functions local_handle = m_k32.GetModuleHandleW(python_lib) py_initialize_ex = python_lib_h + ( m_k32.GetProcAddress(local_handle, b'Py_InitializeEx') - local_handle) py_run_simple_string = python_lib_h + (m_k32.GetProcAddress( local_handle, b'PyRun_SimpleString') - local_handle) print('[*] Resolved addresses:') print(" - Py_InitializeEx: 0x{0:08x}".format(py_initialize_ex)) print(" - PyRun_SimpleString: 0x{0:08x}".format(py_run_simple_string)) # call remote functions to initialize and run via remote threads thread_h = process_h.start_thread(py_initialize_ex, 0) process_h.join_thread(thread_h) print('[*] Initialized Python in the host process') print("[*] Waiting for client to connect on \\\\.\\pipe\\{0}".format( PIPE_NAME)) injection_stub = INJECTION_STUB_TEMPLATE injection_stub = injection_stub.format(path=_escape( os.path.abspath(arguments.script_path)), pipe_name=PIPE_NAME) injection_stub = injection_stub.encode('utf-8') + b'\x00' alloced_addr = process_h.allocate(size=utilities.align_up( len(injection_stub)), permissions='PAGE_READWRITE') process_h.write_memory(alloced_addr, injection_stub) thread_h = process_h.start_thread(py_run_simple_string, alloced_addr) client = NamedPipeClient.from_named_pipe(PIPE_NAME) print('[*] Client connected on named pipe') while True: message = client.read() if message is None: break sys.stdout.write(message.decode('utf-8')) client.close() process_h.join_thread(thread_h) process_h.close()
def main(): parser = argparse.ArgumentParser(description='python_injector: inject python code into a process', conflict_handler='resolve') parser.add_argument('script_path', action='store', help='python script to inject into the process') parser.add_argument('pid', action='store', type=int, help='process to inject into') parser.epilog = 'The __name__ variable will be set to "__mayhem__".' arguments = parser.parse_args() if not sys.platform.startswith('win'): print('[-] This tool is only available on Windows') return # get a handle the the process try: process_h = WindowsProcess(pid=arguments.pid) except ProcessError as error: print("[-] {0}".format(error.msg)) return print("[+] Opened a handle to pid: {0}".format(arguments.pid)) # find and inject the python library python_lib = "python{0}{1}.dll".format(sys.version_info.major, sys.version_info.minor) python_lib = ctypes.util.find_library(python_lib) if python_lib: print("[*] Found Python library at: {0}".format(python_lib)) else: print('[-] Failed to find the Python library') return print('[*] Injecting Python into the process...') try: python_lib_h = process_h.load_library(python_lib) except ProcessError as error: print("[-] {0}".format(error.msg)) return else: print("[+] Loaded {0} with handle 0x{1:08x}".format(python_lib, python_lib_h)) # resolve the necessary functions local_handle = m_k32.GetModuleHandleW(python_lib) py_initialize_ex = python_lib_h + (m_k32.GetProcAddress(local_handle, b'Py_InitializeEx') - local_handle) py_run_simple_string = python_lib_h + (m_k32.GetProcAddress(local_handle, b'PyRun_SimpleString') - local_handle) print('[*] Resolved addresses:') print(" - Py_InitializeEx: 0x{0:08x}".format(py_initialize_ex)) print(" - PyRun_SimpleString: 0x{0:08x}".format(py_run_simple_string)) # call remote functions to initialize and run via remote threads thread_h = process_h.start_thread(py_initialize_ex, 0) process_h.join_thread(thread_h) print('[*] Initialized Python in the host process') print("[*] Waiting for client to connect on \\\\.\\pipe\\{0}".format(PIPE_NAME)) injection_stub = INJECTION_STUB_TEMPLATE injection_stub = injection_stub.format( path=_escape(os.path.abspath(arguments.script_path)), pipe_name=PIPE_NAME ) injection_stub = injection_stub.encode('utf-8') + b'\x00' alloced_addr = process_h.allocate(size=utilities.align_up(len(injection_stub)), permissions='PAGE_READWRITE') process_h.write_memory(alloced_addr, injection_stub) thread_h = process_h.start_thread(py_run_simple_string, alloced_addr) client = NamedPipeClient.from_named_pipe(PIPE_NAME) print('[*] Client connected on named pipe') while True: message = client.read() if message is None: break sys.stdout.write(message.decode('utf-8')) client.close() process_h.join_thread(thread_h) process_h.close()