def SvcDoRun(self): if hasattr(sys, "frozen"): this_dir = os.path.dirname(win32api.GetModuleFileName(None)) else: this_dir = os.path.dirname(os.path.abspath(__file__)) # TODO: maybe it is better to run this in a job object too with open(os.path.join(this_dir, 'npm.log'), 'w') as npm_log: subprocess.check_call('npm install', cwd=this_dir, shell=True, stdin=None, stdout=npm_log, stderr=subprocess.STDOUT) security_attributes = win32security.SECURITY_ATTRIBUTES() security_attributes.bInheritHandle = True startup = win32process.STARTUPINFO() startup.dwFlags |= win32process.STARTF_USESTDHANDLES startup.hStdInput = None startup.hStdOutput = win32file.CreateFile( os.path.join(this_dir, "service_stderr.log"), win32file.GENERIC_WRITE, win32file.FILE_SHARE_READ, security_attributes, win32file.CREATE_ALWAYS, 0, None) startup.hStdError = win32file.CreateFile( os.path.join(this_dir, "service_stdout.log"), win32file.GENERIC_WRITE, win32file.FILE_SHARE_READ, security_attributes, win32file.CREATE_ALWAYS, 0, None) (hProcess, hThread, processId, threadId) = win32process.CreateProcess( None, r'"C:\Program Files\nodejs\node.exe" node_worker.js', None, None, True, win32process.CREATE_SUSPENDED | win32process.CREATE_BREAKAWAY_FROM_JOB, None, this_dir, startup) assert not win32job.IsProcessInJob(hProcess, None) self.hJob = win32job.CreateJobObject(None, "") extended_info = win32job.QueryInformationJobObject( self.hJob, win32job.JobObjectExtendedLimitInformation) extended_info['BasicLimitInformation'][ 'LimitFlags'] = win32job.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | win32job.JOB_OBJECT_LIMIT_BREAKAWAY_OK win32job.SetInformationJobObject( self.hJob, win32job.JobObjectExtendedLimitInformation, extended_info) win32job.AssignProcessToJobObject(self.hJob, hProcess) win32process.ResumeThread(hThread) win32api.CloseHandle(hThread) signalled = win32event.WaitForMultipleObjects( [self.hWaitStop, hProcess], False, win32event.INFINITE) if signalled == win32event.WAIT_OBJECT_0 + 1 and win32process.GetExitCodeProcess( hProcess) != 0: servicemanager.LogErrorMsg( self._svc_name_ + " process exited with non-zero status " + str(win32process.GetExitCodeProcess(hProcess))) win32api.CloseHandle(hProcess) win32api.CloseHandle(self.hJob) win32api.CloseHandle(self.hWaitStop) win32api.CloseHandle(startup.hStdOutput) win32api.CloseHandle(startup.hStdError)
def resume_thread(hThread): """ @param hThread HANDLE @return bool """ try: return win32process.ResumeThread(hThread) >= 0 #except pywintypes.error, e: except Exception, e: dwarn(e) return False
def onKeyboardEvent(self, event): if event.Key == 'F9': thread.start_new_thread(self.change_argv, ()) if event.Key == 'F10': if self.suspended: print "Press F10 to pause." win32process.ResumeThread(self.handle) self.suspended = False else: print "Press F10 to continue." win32process.SuspendThread(self.handle) self.suspended = True if event.Key == 'F8': win32api.PostThreadMessage(win32api.GetCurrentThreadId(), win32con.WM_QUIT, 0, 0) if event.Key == 'F12': print 'killed thread' self.suspended = False terminate_thread(int(self.tid)) self.handle, self.tid = win32process.beginthreadex( None, 0, self.main, (), 0) return True
def main(): # escape list of arguments command = _win32_arglist_to_string(sys.argv[1:]) # create job hJob = win32job.CreateJobObject(None, '') extended_info = win32job.QueryInformationJobObject( hJob, win32job.JobObjectExtendedLimitInformation) extended_info['BasicLimitInformation'][ 'LimitFlags'] = win32job.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE win32job.SetInformationJobObject( hJob, win32job.JobObjectExtendedLimitInformation, extended_info) # associate job with completion port hIoPort = win32file.CreateIoCompletionPort(win32file.INVALID_HANDLE_VALUE, None, 0, 1) # pywin32 is missing support for JOBOBJECT_ASSOCIATE_COMPLETION_PORT, therefore # we call it through ctypes port = JOBOBJECT_ASSOCIATE_COMPLETION_PORT() port.CompletionKey = hJob.handle port.CompletionPort = hIoPort.handle assert bool( ctypes.windll.kernel32.SetInformationJobObject( ctypes.wintypes.HANDLE(hJob.handle), ctypes.c_int(JobObjectAssociateCompletionPortInformation), ctypes.byref(port), ctypes.sizeof(JOBOBJECT_ASSOCIATE_COMPLETION_PORT))) # create process suspended si = win32process.STARTUPINFO() hProcess, hThread, processId, threadId = win32process.CreateProcess( None, command, None, None, True, win32process.CREATE_BREAKAWAY_FROM_JOB | win32process.CREATE_SUSPENDED, None, None, si) # add process to job win32job.AssignProcessToJobObject(hJob, hProcess) # resume process win32process.ResumeThread(hThread) win32api.CloseHandle(hThread) win32api.CloseHandle(hProcess) # wait for job termination numberOfBytes = ctypes.wintypes.DWORD(0) completionKey = ctypes.wintypes.HANDLE(0) overlapped = OVERLAPPED() while True: # calling this through pywin32 crashes the program, therefore we call it through ctypes res = bool( ctypes.windll.kernel32.GetQueuedCompletionStatus( ctypes.wintypes.HANDLE(hIoPort.handle), ctypes.byref(numberOfBytes), ctypes.byref(completionKey), ctypes.byref(overlapped), ctypes.wintypes.DWORD(win32event.INFINITE))) if not res or (bytes(completionKey) == bytes( ctypes.c_void_p(hJob.handle)) and bytes(numberOfBytes) == bytes( ctypes.c_ulong( win32job.JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO))): break
def startBackgroundProcess(self): """Method to start a process running in the background. """ with process_lock: # security attributes for pipes sAttrs = win32security.SECURITY_ATTRIBUTES() sAttrs.bInheritHandle = 1 # create pipes for the process to write to hStdin_r, hStdin = win32pipe.CreatePipe(sAttrs, 0) hStdout = win32file.CreateFile( self.stdout, win32file.GENERIC_WRITE | win32file.GENERIC_READ, win32file.FILE_SHARE_DELETE | win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE, sAttrs, win32file.CREATE_ALWAYS, win32file.FILE_ATTRIBUTE_NORMAL, None) hStderr = win32file.CreateFile( self.stderr, win32file.GENERIC_WRITE | win32file.GENERIC_READ, win32file.FILE_SHARE_DELETE | win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE, sAttrs, win32file.CREATE_ALWAYS, win32file.FILE_ATTRIBUTE_NORMAL, None) try: # set the info structure for the new process. StartupInfo = win32process.STARTUPINFO() StartupInfo.hStdInput = hStdin_r StartupInfo.hStdOutput = hStdout StartupInfo.hStdError = hStderr StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES # Create new handles for the thread ends of the pipes. The duplicated handles will # have their inheritence properties set to false so that any children inheriting these # handles will not have non-closeable handles to the pipes pid = win32api.GetCurrentProcess() tmp = win32api.DuplicateHandle(pid, hStdin, pid, 0, 0, win32con.DUPLICATE_SAME_ACCESS) win32file.CloseHandle(hStdin) hStdin = tmp # start the process, and close down the copies of the process handles # we have open after the process creation (no longer needed here) old_command = command = self.__quotePath(self.command) for arg in self.arguments: command = '%s %s' % (command, self.__quotePath(arg)) # Windows CreateProcess maximum lpCommandLine length is 32,768 # http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx if len(command) >= 32768: # pragma: no cover raise ValueError( "Command line length exceeded 32768 characters: %s..." % command[:1000]) dwCreationFlags = 0 if IS_PRE_WINDOWS_8: # pragma: no cover # In case PySys is itself running in a job, might need to explicitly breakaway from it so we can give # it its own, but only for old pre-windows 8/2012, which support nested jobs dwCreationFlags = dwCreationFlags | win32process.CREATE_BREAKAWAY_FROM_JOB if self.command.lower().endswith(('.bat', '.cmd')): # If we don't start suspended there's a slight race condition but due to some issues with # initially-suspended processes hanging (seen many years ago), to be safe, only bother to close the # race condition for shell scripts (which is the main use case for this anyway) dwCreationFlags = dwCreationFlags | win32con.CREATE_SUSPENDED self.__job = self._createParentJob() try: self.__hProcess, self.__hThread, self.pid, self.__tid = win32process.CreateProcess( None, command, None, None, 1, dwCreationFlags, self.environs, os.path.normpath(self.workingDir), StartupInfo) except pywintypes.error as e: raise ProcessError("Error creating process %s: %s" % (old_command, e)) try: if not self.disableKillingChildProcesses: win32job.AssignProcessToJobObject( self.__job, self.__hProcess) else: self.__job = None # pragma: no cover except Exception as e: # pragma: no cover # Shouldn't fail unless process already terminated (which can happen since # if we didn't use SUSPENDED there's an inherent race here) if win32process.GetExitCodeProcess( self.__hProcess) == win32con.STILL_ACTIVE: log.warning( 'Failed to associate process %s with new job: %s (this may prevent automatic cleanup of child processes)' % (self, e)) # force use of TerminateProcess not TerminateJobObject if this failed self.__job = None if (dwCreationFlags & win32con.CREATE_SUSPENDED) != 0: win32process.ResumeThread(self.__hThread) finally: win32file.CloseHandle(hStdin_r) win32file.CloseHandle(hStdout) win32file.CloseHandle(hStderr) # set the handle to the stdin of the process self.__stdin = hStdin
def resume_child(self): """Un-pauses the main thread of the child process.""" handle = windll.kernel32.OpenThread(win32con.THREAD_SUSPEND_RESUME, 0, self.child_tid) win32process.ResumeThread(handle)
def CreateProcess(self, *args, **kwargs): hp, ht, pid, tid = self._oldapi.CreateProcess(*args, **kwargs) win32job.AssignProcessToJobObject(self._job, hp) win32process.ResumeThread(ht) return hp, ht, pid, tid
def change_argv(self): win32process.SuspendThread(self.handle) self.new_argv = raw_input("\r\nInput argument:") win32process.ResumeThread(self.handle)
sys.exit(30) hProcess = processInfo[0] #### Associate the process with the job try: win32job.AssignProcessToJobObject(hJob, hProcess) except pywintypes.error, e: print 'AssignProcessToJobObject failed, err=%s' % e[0] sys.exit(33) #### Resume the process hThread = processInfo[1] if not win32process.ResumeThread(hThread): print 'ResumeThread failed, err=%s' % e[0] sys.exit(36) win32api.CloseHandle(hThread) #### Wait on the process and get the exit code try: win32event.WaitForSingleObject(hProcess, win32event.INFINITE) except pywintypes.error, e: print 'WaitForSingleObject failed, err=%s' % e[0] sys.exit(40) exitCode = win32process.GetExitCodeProcess(hProcess)
si.hStdInput=pp[0] si.hStdOutput=pp[1] si.hStdError=pp[2] si.wShowWindow=win32con.SW_HIDE si.dwFlags = win32process.STARTF_USESHOWWINDOW | win32con.STARTF_USESTDHANDLES cmd=" ".join(argv) win32api.SetLastError(0) #PyHANDLE, PyHANDLE, int, int = CreateProcess(appName, commandLine , processAttributes , threadAttributes , bInheritHandles , dwCreationFlags , newEnvironment , currentDirectory , startupinfo ) try: pi= win32process.CreateProcess(None,cmd,None,None,True,win32con.CREATE_SUSPENDED,None,RootDir,si) except pywintypes.error , e: ret[1]=e[2] return ret #pi (hProcess, hThread, dwProcessId, dwThreadId) win32process.ResumeThread(pi[1]) #hThread win32api.CloseHandle(pi[1]) while True: exitCode=win32process.GetExitCodeProcess(pi[0]) pmc=win32process.GetProcessMemoryInfo(pi[0]) ft=win32process.GetProcessTimes(pi[0]) ret[3]=mem = round(float(pmc["PeakPagefileUsage"]) / 1024 / 1024,2) ret[2]=time= round(float(ft["UserTime"]) / WIN32_PROCESS_TIMES_TICKS_PER_SECOND,2) print exitCode,ret if limit is not None and time>limit[0]: ret[1]=u"超过时间限制" CloseProcess(pi) return ret if limit is not None and mem>limit[1]: ret[1]=u"超过内存限制"
def each_with_type(self, target, file_type): self.process_created = threading.Event() self.paths = { "word": "{}\\{}".format(self.office_path, "WINWORD.EXE"), "rtf": "{}\\{}".format(self.office_path, "WINWORD.EXE"), "html": "{}\\{}".format(self.office_path, "WINWORD.EXE"), "excel": "{}\\{}".format(self.office_path, "EXCEL.EXE"), "powerpoint": "{}\\{}".format(self.office_path, "POWERPOINT.EXE"), "javascript": "C:\\Windows\\system32\\wscript.exe", "vbscript": "C:\\Windows\\system32\\wscript.exe", } self.files = set() self.results = {"actions": []} monkey = ClickThread() monkey.click_on( "Microsoft Excel", "Yes", "is in a different format than specified by the file extension", ) monkey.click_on( "Microsoft Word", "OK", "command cannot be performed because a dialog box is open") monkey.click_on("Microsoft Word", "No", "start Word in safe mode") monkey.click_on("Microsoft Word", "Yes", "caused a serious error") monkey.click_on("File In Use", "OK", "locked for editing") monkey.click_on("Microsoft Word", "Yes", "that may refer to other files") monkey.click_on("Microsoft Excel", "Yes", "that may refer to other files") monkey.click_on("Microsoft Word", "Yes", "Do you want to start") monkey.click_on("Microsoft Excel", "Yes", "Do you want to start") monkey.close("Activation Wizard") monkey.start() try: target = self.set_extension(target, file_type) executable = self.paths[file_type] cmdline = "\"{}\" \"{}\"".format(executable, target) # Start the process in a paused state process = win32process.CreateProcess( executable, cmdline, None, None, False, win32process.CREATE_SUSPENDED, None, None, win32process.STARTUPINFO(), ) # Add hooks with Frida to trace interesting API calls session = frida.attach(process[2]) script = session.create_script(FRIDA_SCRIPT) script.on('message', self.callback) script.load() # Resume the process so that it executes win32process.ResumeThread(process[1]) # Let the process execute for a while if self.stop_on_process_creation: self.process_created.wait(self.timeout) else: sleep(self.timeout) # Stop Frida session and kill process session.detach() win32api.TerminateProcess(process[0], -1) finally: monkey.stop() monkey.join() for i, dropped_file in enumerate(self.files): if self.add_to_support_files: basename = dropped_file.split("\\")[-1].split("/")[-1] self.add_support_file("{}_{}".format(i, basename), dropped_file) if self.add_to_extracted_files: self.add_extracted_file(dropped_file) del self.files # Restore the VM if we did not catch a process creation if not self.process_created.is_set(): self.should_restore = True return len(self.results["actions"]) > 0