def old_inject(self, dll, apc): arg = KERNEL32.VirtualAllocEx(self.h_process, None, len(dll) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) if not arg: log.error("VirtualAllocEx failed when injecting process with " "pid %d, injection aborted (Error: %s)", self.pid, get_error_string(KERNEL32.GetLastError())) return False bytes_written = c_int(0) if not KERNEL32.WriteProcessMemory(self.h_process, arg, dll + "\x00", len(dll) + 1, byref(bytes_written)): log.error("WriteProcessMemory failed when injecting process with " "pid %d, injection aborted (Error: %s)", self.pid, get_error_string(KERNEL32.GetLastError())) return False kernel32_handle = KERNEL32.GetModuleHandleA("kernel32.dll") load_library = KERNEL32.GetProcAddress(kernel32_handle, "LoadLibraryA") if apc or self.suspended: if not self.h_thread: log.info("No valid thread handle specified for injecting " "process with pid %d, injection aborted.", self.pid) return False if not KERNEL32.QueueUserAPC(load_library, self.h_thread, arg): log.error("QueueUserAPC failed when injecting process with " "pid %d (Error: %s)", self.pid, get_error_string(KERNEL32.GetLastError())) return False else: new_thread_id = c_ulong(0) thread_handle = KERNEL32.CreateRemoteThread(self.h_process, None, 0, load_library, arg, 0, byref(new_thread_id)) if not thread_handle: log.error("CreateRemoteThread failed when injecting process " "with pid %d (Error: %s)", self.pid, get_error_string(KERNEL32.GetLastError())) return False else: KERNEL32.CloseHandle(thread_handle) return True
def execute(self, path, args=None, suspended=False, kernel_analysis=False): """Execute sample process. @param path: sample path. @param args: process args. @param suspended: is suspended. @return: operation status. """ if not os.access(path, os.X_OK): log.error( 'Unable to access file at path "%s", ' "execution aborted", path) return False startup_info = STARTUPINFO() startup_info.cb = sizeof(startup_info) # STARTF_USESHOWWINDOW startup_info.dwFlags = 1 # SW_SHOWNORMAL startup_info.wShowWindow = 1 process_info = PROCESS_INFORMATION() arguments = '"' + path + '" ' if args: arguments += args creation_flags = CREATE_NEW_CONSOLE if suspended: self.suspended = True creation_flags += CREATE_SUSPENDED created = KERNEL32.CreateProcessW(path, arguments, None, None, None, creation_flags, None, os.getenv("TEMP"), byref(startup_info), byref(process_info)) if created: self.pid = process_info.dwProcessId self.h_process = process_info.hProcess self.thread_id = process_info.dwThreadId self.h_thread = process_info.hThread log.info( 'Successfully executed process from path "%s" with ' 'arguments "%s" with pid %d', path, args or "", self.pid) if kernel_analysis: return self.kernel_analyze() return True else: log.error( 'Failed to execute process from path "%s" with ' 'arguments "%s" (Error: %s)', path, args, get_error_string(KERNEL32.GetLastError()), ) return False
def execute(self, path, args=None, suspended=False, kernel_analysis=False): """Execute sample process. @param path: sample path. @param args: process args. @param suspended: is suspended. @return: operation status. """ if not os.access(path, os.X_OK): log.error("Unable to access file at path \"%s\", " "execution aborted", path) return False startup_info = STARTUPINFO() startup_info.cb = sizeof(startup_info) # STARTF_USESHOWWINDOW startup_info.dwFlags = 1 # SW_SHOWNORMAL startup_info.wShowWindow = 1 process_info = PROCESS_INFORMATION() arguments = "\"" + path + "\" " if args: arguments += args creation_flags = CREATE_NEW_CONSOLE if suspended: self.suspended = True creation_flags += CREATE_SUSPENDED created = KERNEL32.CreateProcessA(path, arguments, None, None, None, creation_flags, None, os.getenv("TEMP"), byref(startup_info), byref(process_info)) if created: self.pid = process_info.dwProcessId self.h_process = process_info.hProcess self.thread_id = process_info.dwThreadId self.h_thread = process_info.hThread log.info("Successfully executed process from path \"%s\" with " "arguments \"%s\" with pid %d", path, args or "", self.pid) if kernel_analysis: return self.kernel_analyze() return True else: log.error("Failed to execute process from path \"%s\" with " "arguments \"%s\" (Error: %s)", path, args, get_error_string(KERNEL32.GetLastError())) return False
def execute(self, path, args=None, suspended=False): """Execute sample process. @param path: sample path. @param args: process args. @param suspended: is suspended. @return: operation status. """ if not os.access(path, os.X_OK): log.error("Unable to access file at path \"%s\", " "execution aborted", path) return False startup_info = STARTUPINFO() startup_info.cb = sizeof(startup_info) process_info = PROCESS_INFORMATION() if args: arguments = "\"" + path + "\" " + args else: arguments = None creation_flags = CREATE_NEW_CONSOLE if suspended: self.suspended = True creation_flags += CREATE_SUSPENDED created = KERNEL32.CreateProcessA(path, arguments, None, None, None, creation_flags, None, os.getenv("TEMP"), byref(startup_info), byref(process_info)) if created: self.pid = process_info.dwProcessId self.h_process = process_info.hProcess self.thread_id = process_info.dwThreadId self.h_thread = process_info.hThread log.info("Successfully executed process from path \"%s\" with " "arguments \"%s\" with pid %d", path, args, self.pid) return True else: log.error("Failed to execute process from path \"%s\" with " "arguments \"%s\" (Error: %s)", path, args, get_error_string(KERNEL32.GetLastError())) return False
def execute(self, path, args=None, suspended=False): """Execute sample process. @param path: sample path. @param args: process args. @param suspended: is suspended. @return: operation status. """ if not os.access(path, os.X_OK): log.error("Unable to access file at path \"%s\", execution aborted" % path) return False startup_info = STARTUPINFO() startup_info.cb = sizeof(startup_info) process_info = PROCESS_INFORMATION() if args: arguments = "\"" + path + "\" " + args else: arguments = None creation_flags = CREATE_NEW_CONSOLE if suspended: self.suspended = True creation_flags += CREATE_SUSPENDED created = KERNEL32.CreateProcessA(path, arguments, None, None, None, creation_flags, None, None, byref(startup_info), byref(process_info)) if created: self.pid = process_info.dwProcessId self.h_process = process_info.hProcess self.thread_id = process_info.dwThreadId self.h_thread = process_info.hThread log.info("Successfully executed process from path \"%s\" with " "arguments \"%s\" with pid %d" % (path, args, self.pid)) return True else: log.error("Failed to execute process from path \"%s\" with " "arguments \"%s\" (Error: %s)" % (path, args, get_error_string(KERNEL32.GetLastError()))) return False
def execute(self, path, args=None, dll=None, free=False, curdir=None, source=None, mode=None, maximize=False, env=None, trigger=None): """Execute sample process. @param path: sample path. @param args: process args. @param dll: dll path. @param free: do not inject our monitor. @param curdir: current working directory. @param source: process identifier or process name which will become the parent process for the new process. @param mode: monitor mode - which functions to instrument. @param maximize: whether the GUI should be maximized. @param env: environment variables. @param trigger: trigger to indicate analysis start @return: operation status. """ if not os.access(path, os.X_OK): log.error("Unable to access file at path %r, execution aborted!", path) return False is32bit = self.is32bit(path=path) if not dll: if is32bit: dll = "monitor-x86.dll" else: dll = "monitor-x64.dll" dllpath = os.path.abspath(os.path.join("bin", dll)) if not os.path.exists(dllpath): log.warning("No valid DLL specified to be injected, " "injection aborted.") return False if source: if isinstance(source, (int, long)) or source.isdigit(): inject_is32bit = self.is32bit(pid=int(source)) else: inject_is32bit = self.is32bit(process_name=source) else: inject_is32bit = is32bit if inject_is32bit: inject_exe = os.path.join("bin", "inject-x86.exe") else: inject_exe = os.path.join("bin", "inject-x64.exe") argv = [ inject_exe, "--app", self.shortpath(path), "--only-start", ] if args: argv += ["--args", self._encode_args(args)] if curdir: argv += ["--curdir", self.shortpath(curdir)] if source: if isinstance(source, (int, long)) or source.isdigit(): argv += ["--from", "%s" % source] else: argv += ["--from-process", source] if maximize: argv += ["--maximize"] try: output = subprocess_checkoutput(argv, env) self.pid, self.tid = map(int, output.split()) except Exception: log.error( "Failed to execute process from path %r with " "arguments %r (Error: %s)", path, argv, get_error_string(KERNEL32.GetLastError())) return False # Report this PID to the kernel driver (if present). zer0m0n.addpid(self.pid) if is32bit: inject_exe = os.path.join("bin", "inject-x86.exe") else: inject_exe = os.path.join("bin", "inject-x64.exe") argv = [ inject_exe, "--resume-thread", "--pid", "%s" % self.pid, "--tid", "%s" % self.tid, ] if free: argv.append("--free") else: argv += [ "--apc", "--dll", dllpath, "--config", self.drop_config(mode=mode, trigger=trigger), ] try: subprocess_checkoutput(argv, env) except Exception: log.error( "Failed to execute process from path %r with " "arguments %r (Error: %s)", path, argv, get_error_string(KERNEL32.GetLastError())) return False log.info( "Successfully executed process from path %r with " "arguments %r and pid %d", path, args or "", self.pid) return True
def inject(self, dll=None, apc=False): """Cuckoo DLL injection. @param dll: Cuckoo DLL path. @param apc: APC use. """ if not self.pid: log.warning("No valid pid specified, injection aborted") return False if not self.is_alive(): log.warning("The process with pid %s is not alive, " "injection aborted", self.pid) return False if not dll: dll = "cuckoomon.dll" dll = randomize_dll(os.path.join("dll", dll)) if not dll or not os.path.exists(dll): log.warning("No valid DLL specified to be injected in process " "with pid %d, injection aborted.", self.pid) return False arg = KERNEL32.VirtualAllocEx(self.h_process, None, len(dll) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) if not arg: log.error( "VirtualAllocEx failed when injecting process with " "pid %d, injection aborted (Error: %s)", self.pid, get_error_string(KERNEL32.GetLastError()), ) return False bytes_written = c_int(0) if not KERNEL32.WriteProcessMemory(self.h_process, arg, dll + "\x00", len(dll) + 1, byref(bytes_written)): log.error( "WriteProcessMemory failed when injecting process with " "pid %d, injection aborted (Error: %s)", self.pid, get_error_string(KERNEL32.GetLastError()), ) return False kernel32_handle = KERNEL32.GetModuleHandleA("kernel32.dll") load_library = KERNEL32.GetProcAddress(kernel32_handle, "LoadLibraryA") config_path = os.path.join(os.getenv("TEMP"), "%s.ini" % self.pid) with open(config_path, "w") as config: cfg = Config("analysis.conf") cfgoptions = cfg.get_options() # The first time we come up with a random startup-time. if Process.first_process: # This adds 1 up to 30 times of 20 minutes to the startup # time of the process, therefore bypassing anti-vm checks # which check whether the VM has only been up for <10 minutes. Process.startup_time = random.randint(1, 30) * 20 * 60 * 1000 config.write("host-ip={0}\n".format(cfg.ip)) config.write("host-port={0}\n".format(cfg.port)) config.write("pipe={0}\n".format(PIPE)) config.write("results={0}\n".format(PATHS["root"])) config.write("analyzer={0}\n".format(os.getcwd())) config.write("first-process={0}\n".format("1" if Process.first_process else "0")) config.write("startup-time={0}\n".format(Process.startup_time)) config.write("shutdown-mutex={0}\n".format(SHUTDOWN_MUTEX)) config.write("force-sleepskip={0}\n".format(cfgoptions.get("force-sleepskip", "0"))) Process.first_process = False if apc or self.suspended: log.debug("Using QueueUserAPC injection.") if not self.h_thread: log.info( "No valid thread handle specified for injecting " "process with pid %d, injection aborted.", self.pid, ) return False if not KERNEL32.QueueUserAPC(load_library, self.h_thread, arg): log.error( "QueueUserAPC failed when injecting process with " "pid %d (Error: %s)", self.pid, get_error_string(KERNEL32.GetLastError()), ) return False else: event_name = "CuckooEvent%d" % self.pid self.event_handle = KERNEL32.CreateEventA(None, False, False, event_name) if not self.event_handle: log.warning("Unable to create notify event..") return False log.debug("Using CreateRemoteThread injection.") new_thread_id = c_ulong(0) thread_handle = KERNEL32.CreateRemoteThread( self.h_process, None, 0, load_library, arg, 0, byref(new_thread_id) ) if not thread_handle: log.error( "CreateRemoteThread failed when injecting process " "with pid %d (Error: %s)", self.pid, get_error_string(KERNEL32.GetLastError()), ) KERNEL32.CloseHandle(self.event_handle) self.event_handle = None return False else: KERNEL32.CloseHandle(thread_handle) log.info("Successfully injected process with pid %d." % self.pid) return True
def inject(self, dll=None, apc=False): """Cuckoo DLL injection. @param dll: Cuckoo DLL path. @param apc: APC use. """ if not self.pid: log.warning("No valid pid specified, injection aborted") return False if not self.is_alive(): log.warning( "The process with pid %s is not alive, " "injection aborted", self.pid) return False if not dll: dll = "cuckoomon.dll" dll = randomize_dll(os.path.join("dll", dll)) if not dll or not os.path.exists(dll): log.warning( "No valid DLL specified to be injected in process " "with pid %d, injection aborted.", self.pid) return False arg = KERNEL32.VirtualAllocEx(self.h_process, None, len(dll) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) if not arg: log.error( "VirtualAllocEx failed when injecting process with " "pid %d, injection aborted (Error: %s)", self.pid, get_error_string(KERNEL32.GetLastError())) return False bytes_written = c_int(0) if not KERNEL32.WriteProcessMemory(self.h_process, arg, dll + "\x00", len(dll) + 1, byref(bytes_written)): log.error( "WriteProcessMemory failed when injecting process with " "pid %d, injection aborted (Error: %s)", self.pid, get_error_string(KERNEL32.GetLastError())) return False kernel32_handle = KERNEL32.GetModuleHandleA("kernel32.dll") load_library = KERNEL32.GetProcAddress(kernel32_handle, "LoadLibraryA") config_path = os.path.join(os.getenv("TEMP"), "%s.ini" % self.pid) with open(config_path, "w") as config: cfg = Config("analysis.conf") cfgoptions = cfg.get_options() # The first time we come up with a random startup-time. if Process.first_process: # This adds 1 up to 30 times of 20 minutes to the startup # time of the process, therefore bypassing anti-vm checks # which check whether the VM has only been up for <10 minutes. Process.startup_time = random.randint(1, 30) * 20 * 60 * 1000 config.write("host-ip={0}\n".format(cfg.ip)) config.write("host-port={0}\n".format(cfg.port)) config.write("pipe={0}\n".format(PIPE)) config.write("results={0}\n".format(PATHS["root"])) config.write("analyzer={0}\n".format(os.getcwd())) config.write("first-process={0}\n".format( "1" if Process.first_process else "0")) config.write("startup-time={0}\n".format(Process.startup_time)) config.write("shutdown-mutex={0}\n".format(SHUTDOWN_MUTEX)) config.write("force-sleepskip={0}\n".format( cfgoptions.get("force-sleepskip", "0"))) Process.first_process = False if apc or self.suspended: log.info("Using QueueUserAPC injection.") if not self.h_thread: log.info( "No valid thread handle specified for injecting " "process with pid %d, injection aborted.", self.pid) return False if not KERNEL32.QueueUserAPC(load_library, self.h_thread, arg): log.error( "QueueUserAPC failed when injecting process with " "pid %d (Error: %s)", self.pid, get_error_string(KERNEL32.GetLastError())) return False log.info("Successfully injected process with pid %d." % self.pid) else: event_name = "CuckooEvent%d" % self.pid self.event_handle = KERNEL32.CreateEventA(None, False, False, event_name) if not self.event_handle: log.warning("Unable to create notify event..") return False log.info("Using CreateRemoteThread injection.") new_thread_id = c_ulong(0) thread_handle = KERNEL32.CreateRemoteThread( self.h_process, None, 0, load_library, arg, 0, byref(new_thread_id)) if not thread_handle: log.error( "CreateRemoteThread failed when injecting process " "with pid %d (Error: %s)", self.pid, get_error_string(KERNEL32.GetLastError())) KERNEL32.CloseHandle(self.event_handle) self.event_handle = None return False else: KERNEL32.CloseHandle(thread_handle) return True
def execute(self, path, args=None, dll=None, free=False, curdir=None, source=None, mode=None, maximize=False): """Execute sample process. @param path: sample path. @param args: process args. @param dll: dll path. @param free: do not inject our monitor. @param curdir: current working directory. @param source: process identifier or process name which will become the parent process for the new process. @param mode: monitor mode - which functions to instrument. @param maximize: whether the GUI should be maximized. @return: operation status. """ if not os.access(path, os.X_OK): log.error( "Unable to access file at path \"%s\", " "execution aborted", path) return False is32bit = self.is32bit(path=path) if not dll: if is32bit: dll = "monitor-x86.dll" else: dll = "monitor-x64.dll" dllpath = os.path.abspath(os.path.join("bin", dll)) if not os.path.exists(dllpath): log.warning("No valid DLL specified to be injected, " "injection aborted.") return False if is32bit: inject_exe = os.path.join("bin", "inject-x86.exe") else: inject_exe = os.path.join("bin", "inject-x64.exe") argv = [inject_exe, "--app", self.shortpath(path)] if args: argv += ["--args", self._encode_args(args)] if free: argv += ["--free"] else: argv += [ "--apc", "--dll", dllpath, "--config", self.drop_config(mode=mode) ] if curdir: argv += ["--curdir", self.shortpath(curdir)] if source: if isinstance(source, (int, long)) or source.isdigit(): argv += ["--from", "%s" % source] else: argv += ["--from-process", source] if maximize: argv += ["--maximize"] try: self.pid = int(subprocess.check_output(argv)) except Exception: log.error( "Failed to execute process from path %r with " "arguments %r (Error: %s)", path, argv, get_error_string(KERNEL32.GetLastError())) return False log.info( "Successfully executed process from path %r with " "arguments %r and pid %d", path, args or "", self.pid) return True
def execute(self, path, args=None, dll=None, free=False, curdir=None, source=None, mode=None, maximize=False, env=None, trigger=None): """Execute sample process. @param path: sample path. @param args: process args. @param dll: dll path. @param free: do not inject our monitor. @param curdir: current working directory. @param source: process identifier or process name which will become the parent process for the new process. @param mode: monitor mode - which functions to instrument. @param maximize: whether the GUI should be maximized. @param env: environment variables. @param trigger: trigger to indicate analysis start @return: operation status. """ if not os.access(path, os.X_OK): log.error("Unable to access file at path \"%s\", " "execution aborted", path) return False is32bit = self.is32bit(path=path) if not dll: if is32bit: dll = "monitor-x86.dll" else: dll = "monitor-x64.dll" dllpath = os.path.abspath(os.path.join("bin", dll)) if not os.path.exists(dllpath): log.warning("No valid DLL specified to be injected, " "injection aborted.") return False if source: if isinstance(source, (int, long)) or source.isdigit(): inject_is32bit = self.is32bit(pid=int(source)) else: inject_is32bit = self.is32bit(process_name=source) else: inject_is32bit = is32bit if inject_is32bit: inject_exe = os.path.join("bin", "inject-x86.exe") else: inject_exe = os.path.join("bin", "inject-x64.exe") argv = [ inject_exe, "--app", self.shortpath(path), "--only-start", ] if args: argv += ["--args", self._encode_args(args)] if curdir: argv += ["--curdir", self.shortpath(curdir)] if source: if isinstance(source, (int, long)) or source.isdigit(): argv += ["--from", "%s" % source] else: argv += ["--from-process", source] if maximize: argv += ["--maximize"] try: output = subprocess_checkoutput(argv, env) self.pid, self.tid = map(int, output.split()) except Exception: log.error("Failed to execute process from path %r with " "arguments %r (Error: %s)", path, argv, get_error_string(KERNEL32.GetLastError())) return False if is32bit: inject_exe = os.path.join("bin", "inject-x86.exe") else: inject_exe = os.path.join("bin", "inject-x64.exe") argv = [ inject_exe, "--resume-thread", "--pid", "%s" % self.pid, "--tid", "%s" % self.tid, ] if free: argv.append("--free") else: argv += [ "--apc", "--dll", dllpath, "--config", self.drop_config(mode=mode, trigger=trigger), ] try: subprocess_checkoutput(argv, env) except Exception: log.error("Failed to execute process from path %r with " "arguments %r (Error: %s)", path, argv, get_error_string(KERNEL32.GetLastError())) return False log.info("Successfully executed process from path %r with " "arguments %r and pid %d", path, args or "", self.pid) return True
def inject(self, dll=os.path.join("dll", "cuckoomon.dll"), apc=False): """Cuckoo DLL injection. @param dll: Cuckoo DLL path. @param apc: APC use. """ if self.pid == 0: log.warning("No valid pid specified, injection aborted") return False if not self.is_alive(): log.warning("The process with pid %d is not alive, injection " "aborted" % self.pid) return False dll = randomize_dll(dll) if not dll or not os.path.exists(dll): log.warning("No valid DLL specified to be injected in process " "with pid %d, injection aborted" % self.pid) return False arg = KERNEL32.VirtualAllocEx(self.h_process, None, len(dll) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) if not arg: log.error("VirtualAllocEx failed when injecting process with " "pid %d, injection aborted (Error: %s)" % (self.pid, get_error_string(KERNEL32.GetLastError()))) return False bytes_written = c_int(0) if not KERNEL32.WriteProcessMemory(self.h_process, arg, dll + '\x00', len(dll) + 1, byref(bytes_written)): log.error("WriteProcessMemory failed when injecting process " "with pid %d, injection aborted (Error: %s)" % (self.pid, get_error_string(KERNEL32.GetLastError()))) return False kernel32_handle = KERNEL32.GetModuleHandleA("kernel32.dll") load_library = KERNEL32.GetProcAddress(kernel32_handle, "LoadLibraryA") config_path = os.path.join(os.getenv("TEMP"), "%s.ini" % self.pid) with open(config_path, "w") as config: cfg = Config("analysis.conf") config.write("host-ip={0}\n".format(cfg.ip)) config.write("host-port={0}\n".format(cfg.port)) config.write("pipe={0}\n".format(PIPE)) config.write("results={0}\n".format(PATHS["root"])) config.write("analyzer={0}\n".format(os.getcwd())) config.write("first-process={0}\n".format(Process.first_process)) Process.first_process = False if apc or self.suspended: log.info("Using QueueUserAPC injection") if not self.h_thread: log.info("No valid thread handle specified for injecting " "process with pid %d, injection aborted" % self.pid) return False if not KERNEL32.QueueUserAPC(load_library, self.h_thread, arg): log.error("QueueUserAPC failed when injecting process " "with pid %d (Error: %s)" % (self.pid, get_error_string(KERNEL32.GetLastError()))) return False log.info("Successfully injected process with pid %d" % self.pid) else: event_name = 'CuckooEvent%d' % self.pid self.event_handle = KERNEL32.CreateEventA(None, False, False, event_name) if not self.event_handle: log.warning('Unable to create notify event..') return False log.info("Using CreateRemoteThread injection") new_thread_id = c_ulong(0) thread_handle = KERNEL32.CreateRemoteThread(self.h_process, None, 0, load_library, arg, 0, byref(new_thread_id)) if not thread_handle: log.error("CreateRemoteThread failed when injecting " + "process with pid %d (Error: %s)" % (self.pid, get_error_string(KERNEL32.GetLastError()))) KERNEL32.CloseHandle(self.event_handle) self.event_handle = None return False else: KERNEL32.CloseHandle(thread_handle) return True
def execute(self, path, args=None, dll=None, free=False, curdir=None, source=None): """Execute sample process. @param path: sample path. @param args: process args. @param dll: dll path. @param free: do not inject our monitor. @param curdir: current working directory. @param source: process identifier or process name which will become the parent process for the new process. @return: operation status. """ if not os.access(path, os.X_OK): log.error("Unable to access file at path \"%s\", " "execution aborted", path) return False is32bit = self.is32bit(path=path) if not dll: if is32bit: dll = "monitor-x86.dll" else: dll = "monitor-x64.dll" dllpath = os.path.abspath(os.path.join("bin", dll)) if not os.path.exists(dllpath): log.warning("No valid DLL specified to be injected, " "injection aborted.") return False if is32bit: inject_exe = os.path.join("bin", "inject-x86.exe") else: inject_exe = os.path.join("bin", "inject-x64.exe") argv = [inject_exe, "--app", self.shortpath(path)] if args: argv += ["--args", self._encode_args(args)] if free: argv += ["--free"] else: argv += ["--apc", "--dll", dllpath, "--config", self.drop_config()] if curdir: argv += ["--curdir", self.shortpath(curdir)] if source: if isinstance(source, (int, long)) or source.isdigit(): argv += ["--from", "%s" % source] else: argv += ["--from-process", source] try: self.pid = int(subprocess.check_output(argv)) except Exception: log.error("Failed to execute process from path %r with " "arguments %r (Error: %s)", path, argv, get_error_string(KERNEL32.GetLastError())) return False log.info("Successfully executed process from path %r with " "arguments %r with pid %d", path, args or "", self.pid) return True
def execute(self, path, args=None, suspended=False, kernel_analysis=False): """Execute sample process. @param path: sample path. @param args: process args. @param suspended: is suspended. @return: operation status. """ if not os.access(path, os.X_OK): log.error('Unable to access file at path "%s", execution aborted', path) return False startup_info = STARTUPINFO() startup_info.cb = sizeof(startup_info) # STARTF_USESHOWWINDOW startup_info.dwFlags = 1 # SW_SHOWNORMAL startup_info.wShowWindow = 1 process_info = PROCESS_INFORMATION() arguments = f'"{path}" ' if args: arguments += args creation_flags = CREATE_NEW_CONSOLE if suspended: self.suspended = True creation_flags += CREATE_SUSPENDED # Use the custom execution directory if provided, otherwise launch in the same location # where the sample resides (default %TEMP%) if "executiondir" in self.options.keys(): execution_directory = self.options["executiondir"] elif "curdir" in self.options.keys(): execution_directory = self.options["curdir"] else: execution_directory = os.getenv("TEMP") # Try to create the custom directories so that the execution path is deemed valid create_custom_folders(execution_directory) created = KERNEL32.CreateProcessW(path, arguments, None, None, None, creation_flags, None, execution_directory, byref(startup_info), byref(process_info)) if created: self.pid = process_info.dwProcessId self.h_process = process_info.hProcess self.thread_id = process_info.dwThreadId self.h_thread = process_info.hThread log.info( 'Successfully executed process from path "%s" with arguments "%s" with pid %d', path, args or "", self.pid) if kernel_analysis: return self.kernel_analyze() return True else: log.error( 'Failed to execute process from path "%s" with arguments "%s" (Error: %s)', path, args, get_error_string(KERNEL32.GetLastError()), ) return False
def inject(self, dll=os.path.join("dll", "cuckoomon.dll"), apc=False): """Cuckoo DLL injection. @param dll: Cuckoo DLL path. @param apc: APC use. """ if self.pid == 0: log.warning("No valid pid specified, injection aborted") return False if not self.is_alive(): log.warning("The process with pid %d is not alive, injection " "aborted" % self.pid) return False dll = randomize_dll(dll) if not dll or not os.path.exists(dll): log.warning("No valid DLL specified to be injected in process " "with pid %d, injection aborted" % self.pid) return False arg = KERNEL32.VirtualAllocEx(self.h_process, None, len(dll) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) if not arg: log.error("VirtualAllocEx failed when injecting process with " "pid %d, injection aborted (Error: %s)" % (self.pid, get_error_string(KERNEL32.GetLastError()))) return False bytes_written = c_int(0) if not KERNEL32.WriteProcessMemory(self.h_process, arg, dll + '\x00', len(dll) + 1, byref(bytes_written)): log.error("WriteProcessMemory failed when injecting process " "with pid %d, injection aborted (Error: %s)" % (self.pid, get_error_string(KERNEL32.GetLastError()))) return False kernel32_handle = KERNEL32.GetModuleHandleA("kernel32.dll") load_library = KERNEL32.GetProcAddress(kernel32_handle, "LoadLibraryA") config_path = os.path.join(os.getenv("TEMP"), "%s.ini" % self.pid) with open(config_path, "w") as config: cfg = Config("analysis.conf") config.write("host-ip={0}\n".format(cfg.ip)) config.write("host-port={0}\n".format(cfg.port)) config.write("pipe={0}\n".format(PIPE)) config.write("results={0}\n".format(PATHS["root"])) config.write("analyzer={0}\n".format(os.getcwd())) config.write("first-process={0}\n".format(Process.first_process)) Process.first_process = False if apc or self.suspended: log.info("Using QueueUserAPC injection") if not self.h_thread: log.info("No valid thread handle specified for injecting " "process with pid %d, injection aborted" % self.pid) return False if not KERNEL32.QueueUserAPC(load_library, self.h_thread, arg): log.error( "QueueUserAPC failed when injecting process " "with pid %d (Error: %s)" % (self.pid, get_error_string(KERNEL32.GetLastError()))) return False log.info("Successfully injected process with pid %d" % self.pid) else: event_name = 'CuckooEvent%d' % self.pid self.event_handle = KERNEL32.CreateEventA(None, False, False, event_name) if not self.event_handle: log.warning('Unable to create notify event..') return False log.info("Using CreateRemoteThread injection") new_thread_id = c_ulong(0) thread_handle = KERNEL32.CreateRemoteThread( self.h_process, None, 0, load_library, arg, 0, byref(new_thread_id)) if not thread_handle: log.error( "CreateRemoteThread failed when injecting " + "process with pid %d (Error: %s)" % (self.pid, get_error_string(KERNEL32.GetLastError()))) KERNEL32.CloseHandle(self.event_handle) self.event_handle = None return False else: KERNEL32.CloseHandle(thread_handle) return True
def execute(self, path, args=None, dll=None, free=False, curdir=None, source=None, mode=None, maximize=False): """Execute sample process. @param path: sample path. @param args: process args. @param dll: dll path. @param free: do not inject our monitor. @param curdir: current working directory. @param source: process identifier or process name which will become the parent process for the new process. @param mode: monitor mode - which functions to instrument. @param maximize: whether the GUI should be maximized. @return: operation status. """ if not os.access(path, os.X_OK): log.error("Unable to access file at path \"%s\", " "execution aborted", path) return False if source: source_is32bit = self.is32bit(process_name=source) else: source_is32bit = self.is32bit(pid=os.getpid()) sample_is32bit = self.is32bit(path=path) if not dll: if sample_is32bit: dll = "monitor-x86.dll" else: dll = "monitor-x64.dll" dllpath = os.path.abspath(os.path.join("bin", dll)) if not os.path.exists(dllpath): log.warning("No valid DLL specified to be injected, " "injection aborted.") return False if source_is32bit: inject_exe = os.path.join("bin", "inject-x86.exe") else: inject_exe = os.path.join("bin", "inject-x64.exe") # The --free is required because otherwise we have to provide a DLL # to inject even though we won't be injecting anything at this point. argv = [ inject_exe, "--app", self.shortpath(path), "--only-start", "--free", ] if args: argv += ["--args", self._encode_args(args)] if curdir: argv += ["--curdir", self.shortpath(curdir)] if maximize: argv += ["--maximize"] if source: argv += ["--from-process", source] else: argv += ["--from", "%s" % os.getpid()] try: pid, tid = subprocess.check_output(argv).strip().split() except Exception: log.error("Failed to execute process from path %r with " "arguments %r (Error: %s)", path, argv, get_error_string(KERNEL32.GetLastError())) return False if free: return True if sample_is32bit: inject_exe = os.path.join("bin", "inject-x86.exe") else: inject_exe = os.path.join("bin", "inject-x64.exe") argv = [ inject_exe, "--apc", "--dll", dllpath, "--pid", pid, "--tid", tid, "--resume-thread", "--config", self.drop_config(mode=mode), ] try: self.pid = int(subprocess.check_output(argv)) except Exception: log.error("Failed to execute process from path %r with " "arguments %r (Error: %s)", path, argv, get_error_string(KERNEL32.GetLastError())) return False log.info("Successfully executed process from path %r with " "arguments %r and pid %d", path, args or "", self.pid) return True