def _create_event(): """ Creates a Win32 unnamed Event . http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx """ return windll.kernel32.CreateEventA(pointer(SECURITY_ATTRIBUTES()), BOOL(True), BOOL(False), None)
def __init__(self, pipe_name, read_callback, done_callback): self.pipe_name = pipe_name self.read_callback = read_callback self.done_callback = done_callback self.done = False self.handle = windll.kernel32.CreateFileW(pipe_name, GENERIC_READ, 0, None, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, None) if self.handle == INVALID_HANDLE_VALUE: error_code = windll.kernel32.GetLastError() raise Exception('Invalid pipe handle. Error code=%r.' % error_code) # Create overlapped structure and event. self._overlapped = OVERLAPPED() self._event = windll.kernel32.CreateEventA( None, # Default security attributes. BOOL(True), # Manual reset event. BOOL(True), # initial state = signaled. None # Unnamed event object. ) self._overlapped.hEvent = self._event self._reading = Event() # Start reader coroutine. ensure_future(self._async_reader())
def InsertHandle(self, handle, callback): if handle is None: CreateEventW = ctypes.windll.kernel32.CreateEventW CreateEventW.restype = HANDLE handle = CreateEventW(None, BOOL(), BOOL(), None) if not handle: raise ctypes.WinError() self.waitables[handle] = callback return handle
def create_win32_event(): """ Creates a Win32 unnamed Event . http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx """ return windll.kernel32.CreateEventA( pointer(SECURITY_ATTRIBUTES()), BOOL(True), # Manual reset event. BOOL(False), # Initial state. None # Unnamed event object. )
def create_event(): """ Create Win32 event. """ event = windll.kernel32.CreateEventA( None, # Default security attributes. BOOL(True), # Manual reset event. BOOL(True), # Initial state = signaled. None # Unnamed event object. ) if not event: raise Exception('event creation failed.') return event
def GetProcessName(hwnd): if not isinstance(hwnd, HWND): hwnd = HWND(hwnd) lpdwProcessId = DWORD() _GetWindowThreadProcessId(hwnd, ctypes.byref(lpdwProcessId)) hProcess = _OpenProcess(DWORD(PROCESS_QUERY_INFORMATION), BOOL(False), lpdwProcessId) lpdwSize = DWORD(MAX_PATH) lpExeName = ctypes.create_string_buffer(MAX_PATH) _QueryFullProcessImageName(hProcess, DWORD(0), lpExeName, ctypes.byref(lpdwSize)) if sys.version_info[0] == 2: res = '' else: res = b'' for i in range(260): if sys.version_info[0] == 2: if lpExeName[i] == '\x00': continue else: if lpExeName[i] == b'\x00': continue res += lpExeName[i] if res: res = os.path.split(res)[-1] return res
def write_message_bytes_to_pipe(pipe_handle, data): overlapped = OVERLAPPED() overlapped.hEvent = create_event() try: c_written = DWORD() success = windll.kernel32.WriteFile(pipe_handle, create_string_buffer(data), len(data), byref(c_written), byref(overlapped)) if success: return error_code = windll.kernel32.GetLastError() if error_code == ERROR_IO_PENDING: yield From(wait_for_event(overlapped.hEvent)) success = windll.kernel32.GetOverlappedResult( pipe_handle, byref(overlapped), byref(c_written), BOOL(False)) if not success: error_code = windll.kernel32.GetLastError() if error_code == ERROR_BROKEN_PIPE: raise BrokenPipeError else: raise Exception( 'Writing overlapped IO failed. error_code=%r' % error_code) elif error_code == ERROR_BROKEN_PIPE: raise BrokenPipeError finally: windll.kernel32.CloseHandle(overlapped.hEvent)
def wait_for_handles(handles: List[HANDLE], timeout: int = INFINITE) -> Optional[HANDLE]: """ Waits for multiple handles. (Similar to 'select') Returns the handle which is ready. Returns `None` on timeout. http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx Note that handles should be a list of `HANDLE` objects, not integers. See this comment in the patch by @quark-zju for the reason why: ''' Make sure HANDLE on Windows has a correct size Previously, the type of various HANDLEs are native Python integer types. The ctypes library will treat them as 4-byte integer when used in function arguments. On 64-bit Windows, HANDLE is 8-byte and usually a small integer. Depending on whether the extra 4 bytes are zero-ed out or not, things can happen to work, or break. ''' This function returns either `None` or one of the given `HANDLE` objects. (The return value can be tested with the `is` operator.) """ arrtype = HANDLE * len(handles) handle_array = arrtype(*handles) ret: int = windll.kernel32.WaitForMultipleObjects(len(handle_array), handle_array, BOOL(False), DWORD(timeout)) if ret == WAIT_TIMEOUT: return None else: return handles[ret]
def GetProcessName(hwnd): if not isinstance(hwnd, HWND): hwnd = HWND(hwnd) lpdwProcessId = DWORD() _GetWindowThreadProcessId(hwnd, ctypes.byref(lpdwProcessId)) hProcess = _OpenProcess( DWORD(PROCESS_QUERY_INFORMATION), BOOL(False), lpdwProcessId ) lpdwSize = DWORD(MAX_PATH) lpExeName = ctypes.create_string_buffer(MAX_PATH) _QueryFullProcessImageName( hProcess, DWORD(0), lpExeName, ctypes.byref(lpdwSize) ) res = str(lpExeName) if res: res = os.path.split(res)[-1] return res
def __init__(self, pid, auto_eject=True): self.id = pid self.handle = OpenProcess( PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION, False, pid) self.injected = {} self.auto_eject = auto_eject if not self.handle: raise WinError() if IsWow64Process is None: self.bits = 32 else: wow64 = BOOL() if not IsWow64Process(self.handle, byref(wow64)): raise WinError() if wow64: self.bits = 32 else: self.bits = 64 assert self.bits == 32 or sys.maxsize > 2**32
def fop(files): import ctypes from ctypes.wintypes import HWND, UINT, LPCWSTR, BOOL class SHFILEOPSTRUCTW(ctypes.Structure): _fields_ = [ ("hwnd", HWND), ("wFunc", UINT), ("pFrom", LPCWSTR), ("pTo", LPCWSTR), ("fFlags", ctypes.c_uint), ("fAnyOperationsAborted", BOOL), ("hNameMappings", ctypes.c_uint), ("lpszProgressTitle", LPCWSTR), ] SHFileOperationW = ctypes.windll.shell32.SHFileOperationW SHFileOperationW.argtypes = [ctypes.POINTER(SHFILEOPSTRUCTW)] pFrom = u'\x00'.join(files) + u'\x00' args = SHFILEOPSTRUCTW(wFunc=UINT(3), pFrom=LPCWSTR(pFrom), pTo=None, fFlags=64, fAnyOperationsAborted=BOOL()) out = SHFileOperationW(ctypes.byref(args))
def windowsExit(): global stopped, running, sentReport if not stopped: stopped = True print("Exiting...") windows_utils.SetConsoleCtrlHandler(None, BOOL(True)) if not sentReport: print("Waiting for report descriptor to be sent first") t = time() while time() < t + 15 and not sentReport: sleep(1) if sentReport: print("Ready to uninstall") sleep(1) if not sentReport: print( "Report still not sent. There may be some difficulties in disconnecting." ) running = False usb_container.running = False usb_container.detach() print("Bye!") windows_utils.ExitProcess(0) return False return True
def __init__(self, process_id: int, inherit_handle: bool = False, desired_access: int = PROCESS_ALL_ACCESS): """ Attempt to open a handle for the given PID with requested access level. Raises a WinError if it fails. see msdn doc for OpenProcess for more information about process handles. :param process_id: the id of the process to open :param inherit_handle: whether children should inherit permissions :param desired_access: a windows flag specifying """ super().__init__() self._id = process_id self._inherit_handle = inherit_handle self._desired_access = PROCESS_ALL_ACCESS self._handle = _open_process(DWORD(desired_access), BOOL(inherit_handle), DWORD(process_id)) @property def pid(self) -> int: return self._id
def is64bitProc(process_handle): is64 = BOOL() res = IsWow64Process(process_handle, ctypes.byref(is64)) if res == 0: logging.warning('Failed to get process version info!') WinError(get_last_error()) return not bool(is64.value)
def kill_pid(pid): K32DLL.OpenProcess.restype = HANDLE handle = K32DLL.OpenProcess(PROCESS_TERMINATE, BOOL(False), DWORD(pid)) try: exit_status = ctypes.c_int32() K32DLL.TerminateProcess(handle, byref(exit_status)) finally: K32DLL.CloseHandle(handle)
def can_get_admin_access(): """ Check if the user may be able to get administrator access. Returns True if the user is in the administrator's group. Otherwise returns False """ SECURITY_MAX_SID_SIZE = 68 WinBuiltinAdministratorsSid = 26 ERROR_NO_SUCH_LOGON_SESSION = 1312 ERROR_PRIVILEGE_NOT_HELD = 1314 TokenLinkedToken = 19 # On XP or lower this is equivalent to has_root() # Note: sys.getwindowsversion() does work on every system if sys.getwindowsversion()[0] < 6: return bool(IsUserAnAdmin()) # On Vista or higher, there's the whole UAC token-splitting thing. # Many thanks for Junfeng Zhang for the workflow: htttp://blogs.msdn.com/junfeng/archive/2007/01/26/how-to-tell-if-the-current-user-is-in-administrators-group-programmatically.aspx # Get the token for the current process. proc = GetCurrentProcess() try: token = HANDLE() OpenProcessToken(proc, TOKEN_QUERY, byref(token)) try: # Get the administrators SID. sid = create_string_buffer(SECURITY_MAX_SID_SIZE) sz = DWORD(SECURITY_MAX_SID_SIZE) target_sid = WinBuiltinAdministratorsSid CreateWellKnownSid(target_sid, None, byref(sid), byref(sz)) # Check whether the token has that SID directly. has_admin = BOOL() CheckTokenMembership(None, byref(sid), byref(has_admin)) if has_admin.value: return True # Get the linked token. Failure may mean no linked token. lToken = HANDLE() try: cls = TokenLinkedToken GetTokenInformation(token, cls, byref(lToken), sizeof(lToken), byref(sz)) except WindowsError, e: if e.winerror == ERROR_NO_SUCH_LOGON_SESSION: return False elif e.winerror == ERROR_PRIVILEGE_NOT_HELD: return False else: raise # Check if the linked token has the admin SID try: CheckTokenMembership(lToken, byref(sid), byref(has_admin)) return bool(has_admin.value) finally: CloseHandle(lToken) finally: CloseHandle(token)
def read_message_bytes_from_pipe(pipe_handle): """ (coroutine) Read message from this pipe. Return bytes. """ overlapped = OVERLAPPED() overlapped.hEvent = create_event() try: buff = create_string_buffer(BUFSIZE + 1) c_read = DWORD() success = windll.kernel32.ReadFile(pipe_handle, buff, DWORD(BUFSIZE), byref(c_read), byref(overlapped)) if success: buff[c_read.value] = b'\0' raise Return(buff.value) error_code = windll.kernel32.GetLastError() if error_code == ERROR_IO_PENDING: yield From(wait_for_event(overlapped.hEvent)) success = windll.kernel32.GetOverlappedResult( pipe_handle, byref(overlapped), byref(c_read), BOOL(False)) if success: buff[c_read.value] = b'\0' raise Return(buff.value) else: error_code = windll.kernel32.GetLastError() if error_code == ERROR_BROKEN_PIPE: raise BrokenPipeError elif error_code == ERROR_MORE_DATA: more_data = yield From( read_message_bytes_from_pipe(pipe_handle)) raise Return(buff.value + more_data) else: raise Exception( 'reading overlapped IO failed. error_code=%r' % error_code) elif error_code == ERROR_BROKEN_PIPE: raise BrokenPipeError elif error_code == ERROR_MORE_DATA: more_data = yield From(read_message_bytes_from_pipe(pipe_handle)) raise Return(buff.value + more_data) else: raise Exception('Reading pipe failed, error_code=%s' % error_code) finally: windll.kernel32.CloseHandle(overlapped.hEvent)
def __init__(self, dwProcessId): self.is_open = False self.hProcess = NULL self.dwProcessId = dwProcessId self.bInheritHandle = BOOL(False) self.dwDesiredAccess = DWORD( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE )
def get_colorization_color(): dwmapi = WinDLL("dwmapi", use_last_error=True) DwmGetColorizationColor = dwmapi.DwmGetColorizationColor DwmGetColorizationColor.restype = c_int DwmGetColorizationColor.argtypes = [PDWORD, PBOOL] color = DWORD() opaque = BOOL() r = DwmGetColorizationColor(byref(color), byref(opaque)) log("DwmGetColorizationColor(..)=%i", r) if r: return None return color.value
def InsertHandle(self, handle, callback): """InsertHandle(handle, callback) -> handle Insert a handle to a waitable object. If 'handle' is None, a new event object will be created. The 'callback' is a class instance with the following function defined: def OnObjectSignaled(self, handle, abandoned) If 'abandoned' is False, the 'handle' is signaled. A weak reference to the callback is held, so if the callback function is destroyed, the handle is removed from the waitables list as well. """ if handle is None: CreateEventW = ctypes.windll.kernel32.CreateEventW CreateEventW.restype = HANDLE handle = CreateEventW(None, BOOL(), BOOL(), None) if not handle: raise ctypes.WinError() self.waitables[handle] = callback return handle
def open_event(event_name: str, desired_access: int = EVENT_ALL_ACCESS, inherit_handle: bool = False) -> HANDLE: """ Attempts to open an event object with the given name at the requested access level. The name must easily convert to ascii. :param event_name: a name to open. must be convertible to ascii :param desired_access: :param inherit_handle: whether child processes get access to the handle. :return: a handle for the event if successful """ return _open_event(DWORD(desired_access), BOOL(inherit_handle), LPCSTR(bytes(event_name, 'ASCII')))
def RtlAdjustPrivilege(privilige_id, enable = True, thread_or_process = False): """ privilige_id: int """ _RtlAdjustPrivilege = windll.ntdll.RtlAdjustPrivilege _RtlAdjustPrivilege.argtypes = [ULONG, BOOL, BOOL, POINTER(BOOL)] _RtlAdjustPrivilege.restype = NTSTATUS CurrentThread = thread_or_process # enable for whole process Enabled = BOOL() status = _RtlAdjustPrivilege(privilige_id, enable, CurrentThread, ctypes.byref(Enabled)) if status != STATUS_SUCCESS: raise Exception(NtError(status)) return True
def EnumProcesses(): buf_count = 256 while True: buf = (DWORD * buf_count)() buf_size = DWORD(0) buf_size = sizeof(buf) res_size = DWORD(0) res = BOOL() res = Psapi.EnumProcesses(byref(buf), buf_size, byref(res_size)) if not res: raise OSError('EnumProcesses failed') if res_size.value >= buf_size: buf_count *= 2 continue count = res_size.value // (buf_size // buf_count) return buf[:count]
def wait_for_handles(handles: List[int], timeout: int = INFINITE) -> Optional[HANDLE]: """ Waits for multiple handles. (Similar to 'select') Returns the handle which is ready. Returns `None` on timeout. http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx """ arrtype = HANDLE * len(handles) handle_array = arrtype(*handles) ret = windll.kernel32.WaitForMultipleObjects( len(handle_array), handle_array, BOOL(False), DWORD(timeout)) if ret == WAIT_TIMEOUT: return None else: h = handle_array[ret] return h
def main(pid=None): PROCESS_TERMINATE = 0x0001 PROCESS_QUERY_INFORMATION = 0x0400 JOB_OBJECT_ALL_ACCESS = 0x1F001F hProc = HANDLE() result = BOOL() kernel32 = windll.kernel32 hProc = kernel32.OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, None, pid) hJobObject = kernel32.OpenJobObjectW(JOB_OBJECT_ALL_ACCESS, 1, LPCWSTR("fuzzjob")) if hJobObject == None: # this process is not in the fuzzjob, bail exit() kernel32.IsProcessInJob(hProc, hJobObject, byref(result)) if result.value: kernel32.TerminateJobObject(hJobObject, 0xC0000005)
def EnumProcessModulesEx(hProcess): buf_count = 256 LPDWORD while True: buf = (HMODULE * buf_count)() buf_size = DWORD(sizeof(buf)) needed = DWORD(0) res = BOOL() res = Psapi.EnumProcessModulesEx(hProcess, byref(buf), buf_size, byref(needed), LIST_MODULES_ALL) if not res: raise OSError('EnumProcessModulesEx failed') if buf_size < needed.value: buf_count = needed.value // (buf_size // buf_count) continue count = needed.value // (buf_size // buf_count) return map(HMODULE, buf[:count])
def RtlAdjustPrivilege(privilige_id, enable=True, thread_or_process=False): """ privilige_id: int """ _RtlAdjustPrivilege = windll.ntdll.RtlAdjustPrivilege _RtlAdjustPrivilege.argtypes = [ULONG, BOOL, BOOL, POINTER(BOOL)] _RtlAdjustPrivilege.restype = NTSTATUS CurrentThread = thread_or_process #False = enable for whole process, True = current thread only Enabled = BOOL() status = _RtlAdjustPrivilege(privilige_id, enable, CurrentThread, ctypes.byref(Enabled)) if status != 0: raise Exception('Failed call to RtlAdjustPrivilege! Status: %s' % status) return Enabled.value
def RtlAdjustPrivilege(): NTSTATUS = LONG POINTER = c.POINTER SE_DEBUG = 20 STATUS_SUCCESS = 0 _RtlAdjustPrivilege = windll.ntdll.RtlAdjustPrivilege _RtlAdjustPrivilege.argtypes = [ULONG, BOOL, BOOL, POINTER(BOOL)] _RtlAdjustPrivilege.restype = NTSTATUS Enabled = BOOL() status = _RtlAdjustPrivilege(SE_DEBUG, True, False, c.byref(Enabled)) if status == STATUS_SUCCESS: print("Enable debug privilege successfully") else: print( "Fail to enable debug privilege, check your privilege is admin or not" ) return True
def WinStationConnect(hServer, SessionID, TargetSessionID, Password="", Wait=False): if hServer is None: hServer = win32ts.WTS_CURRENT_SERVER_HANDLE if SessionID is None: SessionID = win32ts.WTS_CURRENT_SESSION if TargetSessionID is None: TargetSessionID = win32ts.WTS_CURRENT_SESSION res = winsta.WinStationConnectW(HANDLE(hServer), ULONG(SessionID), ULONG(TargetSessionID), LPWSTR(Password or ""), BOOL(Wait)) if res != 1: raise Win32Error(func="WinStationConnect")
def _async_reader(self): buffer_size = 65536 c_read = DWORD() buffer = ctypes.create_string_buffer(buffer_size + 1) while True: # Wait until `start_reading` is called. yield From(self._reading.wait()) # Call read. success = windll.kernel32.ReadFile(self.handle, buffer, DWORD(buffer_size), ctypes.byref(c_read), ctypes.byref(self._overlapped)) if success: buffer[c_read.value] = b'\0' self.read_callback(buffer.value.decode('utf-8', 'ignore')) else: error_code = windll.kernel32.GetLastError() # Pending I/O. Wait for it to finish. if error_code == ERROR_IO_PENDING: # Wait for event. yield From(self._wait_for_event()) # Get pending data. success = windll.kernel32.GetOverlappedResult( self.handle, ctypes.byref(self._overlapped), ctypes.byref(c_read), BOOL(False)) if success: buffer[c_read.value] = b'\0' self.read_callback( buffer.value.decode('utf-8', 'ignore')) elif error_code == ERROR_BROKEN_PIPE: self.stop_reading() self.done_callback() self.done = False return