├── _example_.py ├── _example_hardwareid.py ├── LICENSE ├── README.md ├── _right_click.py ├── stroke.py ├── consts.py ├── interception.py ├── .gitignore └── _example_mathpointer.py /_example_.py: -------------------------------------------------------------------------------- 1 | from interception import * 2 | from consts import * 3 | 4 | if __name__ == "__main__": 5 | c = interception() 6 | c.set_filter(interception.is_keyboard,interception_filter_key_state.INTERCEPTION_FILTER_KEY_UP.value) 7 | while True: 8 | device = c.wait() 9 | stroke = c.receive(device) 10 | if type(stroke) is key_stroke: 11 | print(stroke.code) 12 | c.send(device,stroke) 13 | # hwid = c.get_HWID(device) 14 | # print(u"%s" % hwid) 15 | -------------------------------------------------------------------------------- /_example_hardwareid.py: -------------------------------------------------------------------------------- 1 | from interception import * 2 | from consts import * 3 | 4 | SCANCODE_ESC = 0x01 5 | 6 | if __name__ == "__main__": 7 | c = interception() 8 | c.set_filter(interception.is_keyboard,interception_filter_key_state.INTERCEPTION_FILTER_KEY_UP.value | interception_filter_key_state.INTERCEPTION_FILTER_KEY_DOWN.value) 9 | c.set_filter(interception.is_mouse,interception_filter_mouse_state.INTERCEPTION_FILTER_MOUSE_LEFT_BUTTON_DOWN.value) 10 | while True: 11 | device = c.wait() 12 | stroke = c.receive(device) 13 | c.send(device,stroke) 14 | if stroke is None or (interception.is_keyboard(device) and stroke.code == SCANCODE_ESC): 15 | break 16 | print(c.get_HWID(device)) 17 | c._destroy_context() 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 cob_258 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This repository is unmaintained since 2019, check [pyintercept][frk] by Kenny Hommel for an up to date version 2 | # interception_py 3 | This is a port (not a [wrapper][wrp]) of [interception][c_ception] dll to python, it communicates directly with interception's driver 4 | 5 | ### why not using the wrapper? 6 | * it's very slow and some strokes are lost 7 | * fast strokes made python crash (some heap allocation errors) 8 | 9 | To make it run you should install the driver from [c-interception][c_ception] 10 | 11 | ### example 12 | ```py 13 | 14 | from interception import * 15 | 16 | if __name__ == "__main__": 17 | c = interception() 18 | c.set_filter(interception.is_keyboard,interception_filter_key_state.INTERCEPTION_FILTER_KEY_UP.value) 19 | while True: 20 | device = c.wait() 21 | stroke = c.receive(device) 22 | if type(stroke) is key_stroke: 23 | print(stroke.code) 24 | c.send(device,stroke) 25 | ``` 26 | 27 | 28 | [wrp]: https://github.com/cobrce/interception_wrapper 29 | [c_ception]: https://github.com/oblitum/Interception 30 | [frk]: https://github.com/kennyhml/pyintercept 31 | -------------------------------------------------------------------------------- /_right_click.py: -------------------------------------------------------------------------------- 1 | from interception import * 2 | from win32api import GetSystemMetrics 3 | 4 | # get screen size 5 | screen_width = GetSystemMetrics(0) 6 | screen_height = GetSystemMetrics(1) 7 | 8 | # create a context for interception to use to send strokes, in this case 9 | # we won't use filters, we will manually search for the first found mouse 10 | context = interception() 11 | 12 | # loop through all devices and check if they correspond to a mouse 13 | mouse = 0 14 | for i in range(MAX_DEVICES): 15 | if interception.is_mouse(i): 16 | mouse = i 17 | break 18 | 19 | # no mouse we quit 20 | if (mouse == 0): 21 | print("No mouse found") 22 | exit(0) 23 | 24 | 25 | # we create a new mouse stroke, initially we use set right button down, we also use absolute move, 26 | # and for the coordinate (x and y) we use center screen 27 | mstroke = mouse_stroke(interception_mouse_state.INTERCEPTION_MOUSE_RIGHT_BUTTON_DOWN.value, 28 | interception_mouse_flag.INTERCEPTION_MOUSE_MOVE_ABSOLUTE.value, 29 | 0, 30 | int((0xFFFF * screen_width/2) / screen_width), 31 | int((0xFFFF * screen_height/2) / screen_height), 32 | 0) 33 | 34 | context.send(mouse,mstroke) # we send the key stroke, now the right button is down 35 | 36 | mstroke.state = interception_mouse_state.INTERCEPTION_MOUSE_RIGHT_BUTTON_UP.value # update the stroke to release the button 37 | context.send(mouse,mstroke) #button right is up -------------------------------------------------------------------------------- /stroke.py: -------------------------------------------------------------------------------- 1 | import struct 2 | 3 | class stroke(): 4 | 5 | @property 6 | def data(self): 7 | raise NotImplementedError 8 | 9 | @property 10 | def data_raw(self): 11 | raise NotImplementedError 12 | 13 | 14 | class mouse_stroke(stroke): 15 | 16 | fmt = 'HHhiiI' 17 | fmt_raw = 'HHHHIiiI' 18 | state = 0 19 | flags = 0 20 | rolling = 0 21 | x = 0 22 | y = 0 23 | information = 0 24 | 25 | def __init__(self,state,flags,rolling,x,y,information): 26 | super().__init__() 27 | self.state =state 28 | self.flags = flags 29 | self.rolling = rolling 30 | self.x = x 31 | self.y = y 32 | self.information = information 33 | 34 | @staticmethod 35 | def parse(data): 36 | return mouse_stroke(*struct.unpack(mouse_stroke.fmt,data)) 37 | 38 | @staticmethod 39 | def parse_raw(data): 40 | unpacked= struct.unpack(mouse_stroke.fmt_raw,data) 41 | return mouse_stroke( 42 | unpacked[2], 43 | unpacked[1], 44 | unpacked[3], 45 | unpacked[5], 46 | unpacked[6], 47 | unpacked[7]) 48 | 49 | @property 50 | def data(self): 51 | data = struct.pack(self.fmt, 52 | self.state, 53 | self.flags, 54 | self.rolling, 55 | self.x, 56 | self.y, 57 | self.information) 58 | return data 59 | 60 | @property 61 | def data_raw(self): 62 | data = struct.pack(self.fmt_raw, 63 | 0, 64 | self.flags, 65 | self.state, 66 | self.rolling, 67 | 0, 68 | self.x, 69 | self.y, 70 | self.information) 71 | 72 | return data 73 | 74 | class key_stroke(stroke): 75 | 76 | fmt = 'HHI' 77 | fmt_raw = 'HHHHI' 78 | code = 0 79 | state = 0 80 | information = 0 81 | 82 | def __init__(self,code,state,information): 83 | super().__init__() 84 | self.code = code 85 | self.state = state 86 | self.information = information 87 | 88 | 89 | @staticmethod 90 | def parse(data): 91 | return key_stroke(*struct.unpack(key_stroke.fmt,data)) 92 | 93 | @staticmethod 94 | def parse_raw(data): 95 | unpacked= struct.unpack(key_stroke.fmt_raw,data) 96 | return key_stroke(unpacked[1],unpacked[2],unpacked[4]) 97 | 98 | @property 99 | def data(self): 100 | data = struct.pack(self.fmt,self.code,self.state,self.information) 101 | return data 102 | @property 103 | def data_raw(self): 104 | data = struct.pack(self.fmt_raw,0,self.code,self.state,0,self.information) 105 | return data -------------------------------------------------------------------------------- /consts.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | class interception_key_state(Enum): 4 | INTERCEPTION_KEY_DOWN = 0x00 5 | INTERCEPTION_KEY_UP = 0x01 6 | INTERCEPTION_KEY_E0 = 0x02 7 | INTERCEPTION_KEY_E1 = 0x04 8 | INTERCEPTION_KEY_TERMSRV_SET_LED = 0x08 9 | INTERCEPTION_KEY_TERMSRV_SHADOW = 0x10 10 | INTERCEPTION_KEY_TERMSRV_VKPACKET = 0x20 11 | 12 | class interception_filter_key_state(Enum): 13 | INTERCEPTION_FILTER_KEY_NONE = 0x0000 14 | INTERCEPTION_FILTER_KEY_ALL = 0xFFFF 15 | INTERCEPTION_FILTER_KEY_DOWN = interception_key_state.INTERCEPTION_KEY_UP.value 16 | INTERCEPTION_FILTER_KEY_UP = interception_key_state.INTERCEPTION_KEY_UP.value << 1 17 | INTERCEPTION_FILTER_KEY_E0 = interception_key_state.INTERCEPTION_KEY_E0.value << 1 18 | INTERCEPTION_FILTER_KEY_E1 = interception_key_state.INTERCEPTION_KEY_E1.value << 1 19 | INTERCEPTION_FILTER_KEY_TERMSRV_SET_LED = interception_key_state.INTERCEPTION_KEY_TERMSRV_SET_LED.value << 1 20 | INTERCEPTION_FILTER_KEY_TERMSRV_SHADOW = interception_key_state.INTERCEPTION_KEY_TERMSRV_SHADOW.value << 1 21 | INTERCEPTION_FILTER_KEY_TERMSRV_VKPACKET = interception_key_state.INTERCEPTION_KEY_TERMSRV_VKPACKET.value << 1 22 | 23 | class interception_mouse_state (Enum): 24 | INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN = 0x001 25 | INTERCEPTION_MOUSE_LEFT_BUTTON_UP = 0x002 26 | INTERCEPTION_MOUSE_RIGHT_BUTTON_DOWN = 0x004 27 | INTERCEPTION_MOUSE_RIGHT_BUTTON_UP = 0x008 28 | INTERCEPTION_MOUSE_MIDDLE_BUTTON_DOWN = 0x010 29 | INTERCEPTION_MOUSE_MIDDLE_BUTTON_UP = 0x020 30 | 31 | INTERCEPTION_MOUSE_BUTTON_1_DOWN = INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN 32 | INTERCEPTION_MOUSE_BUTTON_1_UP = INTERCEPTION_MOUSE_LEFT_BUTTON_UP 33 | INTERCEPTION_MOUSE_BUTTON_2_DOWN = INTERCEPTION_MOUSE_RIGHT_BUTTON_DOWN 34 | INTERCEPTION_MOUSE_BUTTON_2_UP = INTERCEPTION_MOUSE_RIGHT_BUTTON_UP 35 | INTERCEPTION_MOUSE_BUTTON_3_DOWN = INTERCEPTION_MOUSE_MIDDLE_BUTTON_DOWN 36 | INTERCEPTION_MOUSE_BUTTON_3_UP = INTERCEPTION_MOUSE_MIDDLE_BUTTON_UP 37 | 38 | INTERCEPTION_MOUSE_BUTTON_4_DOWN = 0x040 39 | INTERCEPTION_MOUSE_BUTTON_4_UP = 0x080 40 | INTERCEPTION_MOUSE_BUTTON_5_DOWN = 0x100 41 | INTERCEPTION_MOUSE_BUTTON_5_UP = 0x200 42 | 43 | INTERCEPTION_MOUSE_WHEEL = 0x400 44 | INTERCEPTION_MOUSE_HWHEEL = 0x800 45 | 46 | class interception_filter_mouse_state(Enum): 47 | INTERCEPTION_FILTER_MOUSE_NONE = 0x0000 48 | INTERCEPTION_FILTER_MOUSE_ALL = 0xFFFF 49 | 50 | INTERCEPTION_FILTER_MOUSE_LEFT_BUTTON_DOWN = interception_mouse_state.INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN.value 51 | INTERCEPTION_FILTER_MOUSE_LEFT_BUTTON_UP = interception_mouse_state.INTERCEPTION_MOUSE_LEFT_BUTTON_UP.value 52 | INTERCEPTION_FILTER_MOUSE_RIGHT_BUTTON_DOWN = interception_mouse_state.INTERCEPTION_MOUSE_RIGHT_BUTTON_DOWN.value 53 | INTERCEPTION_FILTER_MOUSE_RIGHT_BUTTON_UP = interception_mouse_state.INTERCEPTION_MOUSE_RIGHT_BUTTON_UP.value 54 | INTERCEPTION_FILTER_MOUSE_MIDDLE_BUTTON_DOWN = interception_mouse_state.INTERCEPTION_MOUSE_MIDDLE_BUTTON_DOWN.value 55 | INTERCEPTION_FILTER_MOUSE_MIDDLE_BUTTON_UP = interception_mouse_state.INTERCEPTION_MOUSE_MIDDLE_BUTTON_UP.value 56 | 57 | INTERCEPTION_FILTER_MOUSE_BUTTON_1_DOWN = interception_mouse_state.INTERCEPTION_MOUSE_BUTTON_1_DOWN.value 58 | INTERCEPTION_FILTER_MOUSE_BUTTON_1_UP = interception_mouse_state.INTERCEPTION_MOUSE_BUTTON_1_UP.value 59 | INTERCEPTION_FILTER_MOUSE_BUTTON_2_DOWN = interception_mouse_state.INTERCEPTION_MOUSE_BUTTON_2_DOWN.value 60 | INTERCEPTION_FILTER_MOUSE_BUTTON_2_UP = interception_mouse_state.INTERCEPTION_MOUSE_BUTTON_2_UP.value 61 | INTERCEPTION_FILTER_MOUSE_BUTTON_3_DOWN = interception_mouse_state.INTERCEPTION_MOUSE_BUTTON_3_DOWN.value 62 | INTERCEPTION_FILTER_MOUSE_BUTTON_3_UP = interception_mouse_state.INTERCEPTION_MOUSE_BUTTON_3_UP.value 63 | 64 | INTERCEPTION_FILTER_MOUSE_BUTTON_4_DOWN = interception_mouse_state.INTERCEPTION_MOUSE_BUTTON_4_DOWN.value 65 | INTERCEPTION_FILTER_MOUSE_BUTTON_4_UP = interception_mouse_state.INTERCEPTION_MOUSE_BUTTON_4_UP.value 66 | INTERCEPTION_FILTER_MOUSE_BUTTON_5_DOWN = interception_mouse_state.INTERCEPTION_MOUSE_BUTTON_5_DOWN.value 67 | INTERCEPTION_FILTER_MOUSE_BUTTON_5_UP = interception_mouse_state.INTERCEPTION_MOUSE_BUTTON_5_UP.value 68 | 69 | INTERCEPTION_FILTER_MOUSE_WHEEL = interception_mouse_state.INTERCEPTION_MOUSE_WHEEL.value 70 | INTERCEPTION_FILTER_MOUSE_HWHEEL = interception_mouse_state.INTERCEPTION_MOUSE_HWHEEL.value 71 | INTERCEPTION_FILTER_MOUSE_MOVE = 0x1000 72 | 73 | class interception_mouse_flag(Enum): 74 | INTERCEPTION_MOUSE_MOVE_RELATIVE = 0x000 75 | INTERCEPTION_MOUSE_MOVE_ABSOLUTE = 0x001 76 | INTERCEPTION_MOUSE_VIRTUAL_DESKTOP = 0x002 77 | INTERCEPTION_MOUSE_ATTRIBUTES_CHANGED = 0x004 78 | INTERCEPTION_MOUSE_MOVE_NOCOALESCE = 0x008 79 | INTERCEPTION_MOUSE_TERMSRV_SRC_SHADOW = 0x100 -------------------------------------------------------------------------------- /interception.py: -------------------------------------------------------------------------------- 1 | from ctypes import * 2 | from stroke import * 3 | from consts import * 4 | 5 | MAX_DEVICES = 20 6 | MAX_KEYBOARD = 10 7 | MAX_MOUSE = 10 8 | 9 | k32 = windll.LoadLibrary('kernel32') 10 | 11 | class interception(): 12 | _context = [] 13 | k32 = None 14 | _c_events = (c_void_p * MAX_DEVICES)() 15 | 16 | def __init__(self): 17 | try: 18 | for i in range(MAX_DEVICES): 19 | _device = device(k32.CreateFileA(b'\\\\.\\interception%02d' % i, 20 | 0x80000000,0,0,3,0,0), 21 | k32.CreateEventA(0, 1, 0, 0), 22 | interception.is_keyboard(i)) 23 | self._context.append(_device) 24 | self._c_events[i] = _device.event 25 | 26 | except Exception as e: 27 | self._destroy_context() 28 | raise e 29 | 30 | def wait(self,milliseconds =-1): 31 | 32 | result = k32.WaitForMultipleObjects(MAX_DEVICES,self._c_events,0,milliseconds) 33 | if result == -1 or result == 0x102: 34 | return 0 35 | else: 36 | return result 37 | 38 | def set_filter(self,predicate,filter): 39 | for i in range(MAX_DEVICES): 40 | if predicate(i): 41 | result = self._context[i].set_filter(filter) 42 | 43 | def get_HWID(self,device:int): 44 | if not interception.is_invalid(device): 45 | try: 46 | return self._context[device].get_HWID().decode("utf-16") 47 | except: 48 | pass 49 | return "" 50 | 51 | def receive(self,device:int): 52 | if not interception.is_invalid(device): 53 | return self._context[device].receive() 54 | 55 | def send(self,device: int,stroke : stroke): 56 | if not interception.is_invalid(device): 57 | self._context[device].send(stroke) 58 | 59 | @staticmethod 60 | def is_keyboard(device): 61 | return device+1 > 0 and device+1 <= MAX_KEYBOARD 62 | 63 | @staticmethod 64 | def is_mouse(device): 65 | return device+1 > MAX_KEYBOARD and device+1 <= MAX_KEYBOARD + MAX_MOUSE 66 | 67 | @staticmethod 68 | def is_invalid(device): 69 | return device+1 <= 0 or device+1 > (MAX_KEYBOARD + MAX_MOUSE) 70 | 71 | def _destroy_context(self): 72 | for device in self._context: 73 | device.destroy() 74 | 75 | class device_io_result: 76 | result = 0 77 | data = None 78 | data_bytes = None 79 | def __init__(self,result,data): 80 | self.result = result 81 | if data!=None: 82 | self.data = list(data) 83 | self.data_bytes = bytes(data) 84 | 85 | 86 | def device_io_call(decorated): 87 | def decorator(device,*args,**kwargs): 88 | command,inbuffer,outbuffer = decorated(device,*args,**kwargs) 89 | return device._device_io_control(command,inbuffer,outbuffer) 90 | return decorator 91 | 92 | class device(): 93 | handle=0 94 | event=0 95 | is_keyboard = False 96 | _parser = None 97 | _bytes_returned = (c_int * 1)(0) 98 | _c_byte_500 = (c_byte * 500)() 99 | _c_int_2 = (c_int * 2)() 100 | _c_ushort_1 = (c_ushort * 1)() 101 | _c_int_1 = (c_int * 1)() 102 | _c_recv_buffer = None 103 | 104 | def __init__(self, handle, event,is_keyboard:bool): 105 | self.is_keyboard = is_keyboard 106 | if is_keyboard: 107 | self._c_recv_buffer = (c_byte * 12)() 108 | self._parser = key_stroke 109 | else: 110 | self._c_recv_buffer = (c_byte * 24)() 111 | self._parser = mouse_stroke 112 | 113 | if handle == -1 or event == 0: 114 | raise Exception("Can't create device") 115 | self.handle=handle 116 | self.event =event 117 | 118 | if self._device_set_event().result == 0: 119 | raise Exception("Can't communicate with driver") 120 | 121 | def destroy(self): 122 | if self.handle != -1: 123 | k32.CloseHandle(self.handle) 124 | if self.event!=0: 125 | k32.CloseHandle(self.event) 126 | 127 | @device_io_call 128 | def get_precedence(self): 129 | return 0x222008,0,self._c_int_1 130 | 131 | @device_io_call 132 | def set_precedence(self,precedence : int): 133 | self._c_int_1[0] = precedence 134 | return 0x222004,self._c_int_1,0 135 | 136 | @device_io_call 137 | def get_filter(self): 138 | return 0x222020,0,self._c_ushort_1 139 | 140 | @device_io_call 141 | def set_filter(self,filter): 142 | self._c_ushort_1[0] = filter 143 | return 0x222010,self._c_ushort_1,0 144 | 145 | @device_io_call 146 | def _get_HWID(self): 147 | return 0x222200,0,self._c_byte_500 148 | 149 | def get_HWID(self): 150 | data = self._get_HWID().data_bytes 151 | return data[:self._bytes_returned[0]] 152 | 153 | @device_io_call 154 | def _receive(self): 155 | return 0x222100,0,self._c_recv_buffer 156 | 157 | def receive(self): 158 | data = self._receive().data_bytes 159 | return self._parser.parse_raw(data) 160 | 161 | def send(self,stroke:stroke): 162 | if type(stroke) == self._parser: 163 | self._send(stroke) 164 | 165 | @device_io_call 166 | def _send(self,stroke:stroke): 167 | memmove(self._c_recv_buffer,stroke.data_raw,len(self._c_recv_buffer)) 168 | return 0x222080,self._c_recv_buffer,0 169 | 170 | @device_io_call 171 | def _device_set_event(self): 172 | self._c_int_2[0] = self.event 173 | return 0x222040,self._c_int_2,0 174 | 175 | def _device_io_control(self,command,inbuffer,outbuffer)->device_io_result: 176 | res = k32.DeviceIoControl(self.handle,command,inbuffer, 177 | len(bytes(inbuffer)) if inbuffer != 0 else 0, 178 | outbuffer, 179 | len(bytes(outbuffer)) if outbuffer !=0 else 0, 180 | self._bytes_returned,0) 181 | 182 | return device_io_result(res,outbuffer if outbuffer !=0 else None) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /_example_mathpointer.py: -------------------------------------------------------------------------------- 1 | from interception import * 2 | from consts import * 3 | from math import * 4 | from win32api import GetSystemMetrics 5 | from datetime import datetime 6 | from time import sleep 7 | 8 | esc = 0x01 9 | num_0 = 0x0B 10 | num_1 = 0x02 11 | num_2 = 0x03 12 | num_3 = 0x04 13 | num_4 = 0x05 14 | num_5 = 0x06 15 | num_6 = 0x07 16 | num_7 = 0x08 17 | num_8 = 0x09 18 | num_9 = 0x0A 19 | scale = 15 20 | screen_width = GetSystemMetrics(0) 21 | screen_height = GetSystemMetrics(1) 22 | 23 | def delay(): 24 | sleep(0.001) 25 | 26 | class point(): 27 | x = 0 28 | y = 0 29 | def __init__(self,x,y): 30 | self.x = x 31 | self.y = y 32 | 33 | def circle(t): 34 | f = 10 35 | return point(scale * f * cos(t), scale * f *sin(t)) 36 | 37 | def mirabilis(t): 38 | f= 1 / 2 39 | k = 1 / (2 * pi) 40 | 41 | return point(scale * f * (exp(k * t) * cos(t)), 42 | scale * f * (exp(k * t) * sin(t))) 43 | 44 | def epitrochoid(t): 45 | f = 1 46 | R = 6 47 | r = 2 48 | d = 1 49 | c = R + r 50 | 51 | return point(scale * f * (c * cos(t) - d * cos((c * t) / r)), 52 | scale * f * (c * sin(t) - d * sin((c * t) / r))) 53 | 54 | def hypotrochoid(t): 55 | f = 10 / 7 56 | R = 5 57 | r = 3 58 | d = 5 59 | c = R - r 60 | 61 | return point(scale * f * (c * cos(t) + d * cos((c * t) / r)), 62 | scale * f * (c * sin(t) - d * sin((c * t) / r))) 63 | 64 | def hypocycloid(t): 65 | f = 10 / 3 66 | R = 3 67 | r = 1 68 | c = R - r 69 | 70 | return point(scale * f * (c * cos(t) + r * cos((c * t) / r)), 71 | scale * f * (c * sin(t) - r * sin((c * t) / r))) 72 | 73 | def bean(t): 74 | f = 10 75 | c = cos(t) 76 | s = sin(t) 77 | 78 | return point(scale * f * ((pow(c, 3) + pow(s, 3)) * c), 79 | scale * f * ((pow(c, 3) + pow(s, 3)) * s)) 80 | 81 | def Lissajous(t): 82 | f = 10 83 | a = 2 84 | b = 3 85 | 86 | return point(scale * f * (sin(a * t)), scale * f * (sin(b * t))) 87 | 88 | def epicycloid(t): 89 | f = 10 / 42 90 | R = 21 91 | r = 10 92 | c = R + r 93 | 94 | return point(scale * f * (c * cos(t) - r * cos((c * t) / r)), 95 | scale * f * (c * sin(t) - r * sin((c * t) / r))) 96 | 97 | def rose(t): 98 | f = 10 99 | R = 1 100 | k = 2 / 7 101 | 102 | return point(scale * f * (R * cos(k * t) * cos(t)), 103 | scale * f * (R * cos(k * t) * sin(t))) 104 | 105 | def butterfly(t): 106 | f = 10 / 4 107 | c = exp(cos(t)) - 2 * cos(4 * t) + pow(sin(t / 12), 5) 108 | 109 | return point(scale * f * (sin(t) * c), scale * f * (cos(t) * c)) 110 | 111 | def math_track(context:interception, mouse : int, 112 | center,curve, t1, t2, # changed params order 113 | partitioning): 114 | delta = t2 - t1 115 | position = curve(t1) 116 | mstroke = mouse_stroke(interception_mouse_state.INTERCEPTION_MOUSE_LEFT_BUTTON_UP.value, 117 | interception_mouse_flag.INTERCEPTION_MOUSE_MOVE_ABSOLUTE.value, 118 | 0, 119 | int((0xFFFF * center.x) / screen_width), 120 | int((0xFFFF * center.y) / screen_height), 121 | 0) 122 | 123 | context.send(mouse,mstroke) 124 | 125 | mstroke.state = 0 126 | mstroke.x = int((0xFFFF * (center.x + position.x)) / screen_width) 127 | mstroke.y = int((0xFFFF * (center.y - position.y)) / screen_height) 128 | 129 | context.send(mouse,mstroke) 130 | 131 | j = 0 132 | for i in range(partitioning+2): 133 | if (j % 250 == 0): 134 | delay() 135 | mstroke.state = interception_mouse_state.INTERCEPTION_MOUSE_LEFT_BUTTON_UP.value 136 | context.send(mouse,mstroke) 137 | 138 | delay() 139 | mstroke.state = interception_mouse_state.INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN.value 140 | context.send(mouse,mstroke) 141 | if i > 0: 142 | i = i-2 143 | 144 | position = curve(t1 + (i * delta)/partitioning) 145 | mstroke.x = int((0xFFFF * (center.x + position.x)) / screen_width) 146 | mstroke.y = int((0xFFFF * (center.y - position.y)) / screen_height) 147 | context.send(mouse,mstroke) 148 | delay() 149 | j = j + 1 150 | 151 | delay() 152 | mstroke.state = interception_mouse_state.INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN.value 153 | context.send(mouse,mstroke) 154 | 155 | delay() 156 | mstroke.state = interception_mouse_state.INTERCEPTION_MOUSE_LEFT_BUTTON_UP.value 157 | context.send(mouse,mstroke) 158 | 159 | delay() 160 | mstroke.state = 0 161 | mstroke.x = int((0xFFFF * center.x) / screen_width) 162 | mstroke.y = int((0xFFFF * center.y) / screen_height) 163 | context.send(mouse,mstroke) 164 | 165 | curves = { num_0 : (circle,0,2*pi,200), 166 | num_1 : (mirabilis,-6*pi,6*pi,200), 167 | num_2 : (epitrochoid,0, 2 * pi, 200), 168 | num_3 : (hypotrochoid, 0, 6 * pi, 200), 169 | num_4 : (hypocycloid,0, 2 * pi, 200), 170 | num_5 : (bean, 0, pi, 200), 171 | num_6 : (Lissajous, 0, 2 * pi, 200), 172 | num_7 : (epicycloid, 0, 20 * pi, 1000), 173 | num_8 : (rose,0, 14 * pi, 500), 174 | num_9 : (butterfly, 0, 21 * pi, 2000), 175 | } 176 | 177 | 178 | notice = '''NOTICE: This example works on real machines. 179 | Virtual machines generally work with absolute mouse 180 | positioning over the screen, which this samples isn't\n" 181 | prepared to handle. 182 | 183 | Now please, first move the mouse that's going to be impersonated. 184 | ''' 185 | 186 | steps = '''Impersonating mouse %d 187 | Now: 188 | - Go to Paint (or whatever place you want to draw) 189 | - Select your pencil 190 | - Position your mouse in the drawing board 191 | - Press any digit (not numpad) on your keyboard to draw an equation 192 | - Press ESC to exit.''' 193 | 194 | def main(): 195 | 196 | mouse = 0 197 | position = point(screen_width // 2, screen_height // 2) 198 | context = interception() 199 | context.set_filter(interception.is_keyboard, 200 | interception_filter_key_state.INTERCEPTION_FILTER_KEY_DOWN.value | 201 | interception_filter_key_state.INTERCEPTION_FILTER_KEY_UP.value) 202 | context.set_filter(interception.is_mouse, 203 | interception_filter_mouse_state.INTERCEPTION_FILTER_MOUSE_MOVE.value ) 204 | 205 | print(notice) 206 | 207 | while True: 208 | 209 | device = context.wait() 210 | if interception.is_mouse(device): 211 | if mouse == 0: 212 | mouse = device 213 | print( steps % (device - 10)) 214 | 215 | mstroke = context.receive(device) 216 | 217 | position.x += mstroke.x 218 | position.y += mstroke.y 219 | 220 | if position.x < 0: 221 | position.x = 0 222 | if position.x > screen_width - 1: 223 | position.x = screen_width -1 224 | 225 | if position.y <0 : 226 | position.y = 0 227 | if position.y > screen_height - 1: 228 | position.y = screen_height -1 229 | 230 | mstroke.flags = interception_mouse_flag.INTERCEPTION_MOUSE_MOVE_ABSOLUTE.value 231 | mstroke.x = int((0xFFFF * position.x) / screen_width) 232 | mstroke.y = int((0xFFFF * position.y) / screen_height) 233 | 234 | context.send(device,mstroke) 235 | 236 | if mouse and interception.is_keyboard(device): 237 | kstroke = context.receive(device) 238 | 239 | if kstroke.code == esc: 240 | return 241 | 242 | if kstroke.state == interception_key_state.INTERCEPTION_KEY_DOWN.value: 243 | if kstroke.code in curves: 244 | math_track(context,mouse,position,*curves[kstroke.code]) 245 | else: 246 | context.send(device,kstroke) 247 | 248 | elif kstroke.state == interception_key_state.INTERCEPTION_KEY_UP.value: 249 | if not kstroke.code in curves: 250 | context.send(device,kstroke) 251 | else: 252 | context.send(device,kstroke) 253 | 254 | 255 | if __name__ == "__main__": 256 | main() --------------------------------------------------------------------------------