Example #1
0
 def __enter__(self):
     self.tfd = create_tap_if()
     self._tg_evt = IoctlAsync(IOCTL_TGWINK_PEND_INTR, self.dev.interface.cfgfd, 8)
     self._tap_evt = ReadAsync(self.tfd, 0x800, self.mm)
     self._hCon = GetStdHandle(STD_INPUT_HANDLE)
     self._events = (HANDLE * 3)(self._hCon, self._tg_evt.req.hEvent, self._tap_evt.req.hEvent)
     self._tg_evt.submit()
     return self
Example #2
0
class TapWinInterface(object):
    def __init__(self, dev):
        self.dev = dev
        self.mm = dev.interface.mm
        self._connected = False
        self._pending_completions = {}

    def __enter__(self):
        self.tfd = create_tap_if()
        self._tg_evt = IoctlAsync(IOCTL_TGWINK_PEND_INTR, self.dev.interface.cfgfd, 8)
        self._tap_evt = ReadAsync(self.tfd, 0x800, self.mm)
        self._hCon = GetStdHandle(STD_INPUT_HANDLE)
        self._events = (HANDLE * 3)(self._hCon, self._tg_evt.req.hEvent, self._tap_evt.req.hEvent)
        self._tg_evt.submit()
        return self
    
    def __exit__(self):
        self._tap_evt.reset(False)
        self._tg_evt.reset(False)
        del self._events
        del self._tap_evt
        del self._tg_evt

        del_tap_if(self.tfd)

    def _get_key(self):
        res = None
        cnt = DWORD(0)
        if not GetNumberOfConsoleInputEvents(self._hCon, pointer(cnt)):
            raise WinError()
        if 0 == cnt.value:
            return ''

        ir = (INPUT_RECORD * cnt.value)()
        rr = DWORD(0)
        
        if not ReadConsoleInput(self._hCon, cast(pointer(ir), POINTER(INPUT_RECORD)), cnt.value, pointer(rr)):
            raise WinError()

        if 0 == rr.value:
            print "[!] no input records available (??)"
            return ''

        for i in range(rr.value):
            if ir[i].EventType != KEY_EVENT:
                continue
            if not ir[i].Event.KeyEvent.bKeyDown:
                continue
            res = ir[i].Event.KeyEvent.uChar.AsciiChar
            return res
        return ''

    def _wait_for_something(self):
        while self._running:        
            res = WaitForMultipleObjectsEx(len(self._events), cast(pointer(self._events), POINTER(c_void_p)), False, INFINITE, True)
            if res < 3:
                return res
            if res == WAIT_FAILED:
                raise WinError()
        
    def _get_serial(self):
        serial = cast(self._tg_evt.buffer, POINTER(c_uint64)).contents.value
        self._tg_evt.reset()
        return serial
 
    def _get_packet(self):
        if self.verbose:
            print "[+] getting a packet from tap device...",
        pkt_len = self._tap_evt.pkt_len
        pkt = self._tap_evt.buffer
        self._tap_evt.reset()
        if self.verbose:
            print "read %d bytes" % pkt_len
        return (pkt, pkt_len)

    def _tap_write_completion(self, overlapped, pkt, errcode, written, overlapped_ptr):
        if self.verbose:
            print "[.] freeing sent packet at %x" % addressof(pkt)
        self.mm.free(addressof(pkt))
        del self._pending_completions[addressof(pkt)]

    def _write_pkt(self, pkt, length):
        if not self._connected:
            return
        o = OVERLAPPED(hEvent = CreateEvent(None, True, False, None))
        if self.verbose:
            print "[!] attempting to write to the tap device...",
        completion = FileIOCompletion(functools.partial(TapWinInterface._tap_write_completion, self, o, pkt))
        if not WriteFileEx(self.tfd, pkt, length, pointer(o), completion):
            raise WinError()
        else:
            self._pending_completions[addressof(pkt)] = completion
        if self.verbose:
            print "queued %d bytes" % len(pkt)

    def _set_tapdev_status(self, connected):
        if self.verbose:
            print "[+] setting tapdev status to %s" % ("up" if connected else "down")
        o = OVERLAPPED(hEvent = CreateEvent(None, True, False, None))
        try:
            val = c_int32(1 if connected else 0)
            if not DeviceIoControl(self.tfd, TAP_WIN_IOCTL_SET_MEDIA_STATUS, pointer(val), 4, pointer(val), 4, None, pointer(o)):
                err = get_last_error()
                if err == ERROR_IO_PENDING:
                    if WAIT_FAILED == WaitForSingleObject(o.hEvent, INFINITE):
                        raise WinError()
                elif err == 0:
                    pass
                else:
                    raise WinError(err)
            if connected:
                self._tap_evt.submit()
            else:
                self._tap_evt.reset(False)
            self._connected = connected
        finally:
            CloseHandle(o.hEvent)
Example #3
0
class TapWinInterface(object):
    def __init__(self, dev):
        self.dev = dev
        self.mm = dev.interface.mm
        self._connected = False
        self._wait_q = {}

    def __enter__(self):
        self.tfd = create_tap_if()
        self._tg_evt = IoctlAsync(IOCTL_TGWINK_PEND_INTR, self.dev.interface.cfgfd, 8)
        self._tap_evts = [ReadAsync(self.tfd, 0x800, self.mm),
                          ReadAsync(self.tfd, 0x800, self.mm)]
        self._hCon = GetStdHandle(STD_INPUT_HANDLE)
        self._events = (HANDLE * 4)(self._hCon, self._tg_evt.req.hEvent, self._tap_evts[0].req.hEvent, self._tap_evts[1].req.hEvent)
        self._tg_evt.submit()
        return self
    
    def __exit__(self):
        for t in self._tap_evts:
            t.reset(False)
        self._tg_evt.reset(False)
        del self._events
        del self._tap_evts
        del self._tg_evt

        del_tap_if(self.tfd)

    def _get_key(self):
        res = None
        cnt = DWORD(0)
        if not GetNumberOfConsoleInputEvents(self._hCon, pointer(cnt)):
            raise WinError()
        if 0 == cnt.value:
            return ''

        ir = (INPUT_RECORD * cnt.value)()
        rr = DWORD(0)
        
        if not ReadConsoleInput(self._hCon, cast(pointer(ir), POINTER(INPUT_RECORD)), cnt.value, pointer(rr)):
            raise WinError()

        if 0 == rr.value:
            print "[!] no input records available (??)"
            return ''

        for i in range(rr.value):
            if ir[i].EventType != KEY_EVENT:
                continue
            if not ir[i].Event.KeyEvent.bKeyDown:
                continue
            res = ir[i].Event.KeyEvent.uChar.AsciiChar
            return res
        return ''

    def _work_wait_q(self):
        if self.verbose:
            print "[+] processing wait queue..."
        completed = 0
        res = 0
        cnt = len(self._wait_q)
        while WAIT_TIMEOUT != res and cnt > 0:
            wait_handles = (HANDLE * cnt)(*self._wait_q.keys())
            res = WaitForMultipleObjects(cnt, cast(pointer(wait_handles), POINTER(c_void_p)), False, 0)
            if WAIT_FAILED == res:
                raise WinError()
            if res < cnt:
                k = wait_handles[res]
                self._wait_q[k]()
                del self._wait_q[k]
                completed += 1
                cnt -= 1
        if self.verbose:
            print "[+] cleaned %d items off the wait queue." % completed

    def _wait_for_something(self):
        res = WAIT_TIMEOUT
        if len(self._wait_q) > 50:
            self._work_wait_q()
        elif len(self._wait_q) > 0:
            res = WaitForMultipleObjects(4, cast(pointer(self._events), POINTER(c_void_p)), False, 0)
            if WAIT_TIMEOUT == res:
                self._work_wait_q()
        if WAIT_TIMEOUT == res:
            res = WaitForMultipleObjects(4, cast(pointer(self._events), POINTER(c_void_p)), False, INFINITE)
        if res < 2:
            return res
        if res < 4:
            self._tap_idx = res - 2
            return 2
        raise WinError()
        
    def _get_serial(self):
        serial = cast(self._tg_evt.buffer, POINTER(c_uint64)).contents.value
        self._tg_evt.reset()
        return serial
 
    def _get_packet(self):
        if self.verbose:
            print "[+] getting a packet from tap device...",
        pkt_len = self._tap_evts[self._tap_idx].pkt_len
        pkt = self._tap_evts[self._tap_idx].buffer
        self._tap_evts[self._tap_idx].reset()
        if self.verbose:
            print "read %d bytes" % pkt_len
        return (pkt, pkt_len)

    def __pkt_buf_free(self, overlapped, pkt):
        if self.verbose:
            print "[.] freeing sent packet at %x" % addressof(pkt)
        self.mm.free(addressof(pkt))
        CloseHandle(overlapped.hEvent)
        del overlapped

    def _write_pkt(self, pkt, length):
        if not self._connected:
            return
        o = OVERLAPPED(hEvent = CreateEvent(None, True, False, None))
        if self.verbose:
            print "[!] attempting to write to the tap device...",
        if not WriteFile(self.tfd, pkt, length, None, pointer(o)):
            err = get_last_error()
            if err > 0 and err != ERROR_IO_PENDING:
                raise WinError(err)
            self._wait_q[o.hEvent] = functools.partial(TapWinInterface.__pkt_buf_free, self, o, pkt)
        else:
            self.mm.free(addressof(pkt))
            CloseHandle(o.hEvent)
        if self.verbose:
            print "wrote %d bytes" % o.InternalHigh

    def _set_tapdev_status(self, connected):
        if self.verbose:
            print "[+] setting tapdev status to %s" % ("up" if connected else "down")
        o = OVERLAPPED(hEvent = CreateEvent(None, True, False, None))
        try:
            val = c_int32(1 if connected else 0)
            if not DeviceIoControl(self.tfd, TAP_WIN_IOCTL_SET_MEDIA_STATUS, pointer(val), 4, pointer(val), 4, None, pointer(o)):
                err = get_last_error()
                if err == ERROR_IO_PENDING:
                    if WAIT_FAILED == WaitForSingleObject(o.hEvent, INFINITE):
                        raise WinError()
                elif err == 0:
                    pass
                else:
                    raise WinError(err)
            if connected:
                for t in self._tap_evts:
                    t.submit()
            else:
                for t in self._tap_evts:
                    t.reset(False)
            self._connected = connected
        finally:
            CloseHandle(o.hEvent)