本项目使用arduino对python进行了键盘映射,可以实现python传按键信息给开发板,开发板输入真实键盘信息到电脑中。
应用场景:现在市面上的养成类PC电脑游戏中玩家都会需要脚本来解决一些复杂繁琐的事情,例如:角色打怪练级,完成每日任务,跑图等等。而现如今的游戏都有针对模拟按键脚本的检测机制,普通的模拟按键脚本根本无法绕过检测机制运行,而真实键盘的按键信息可以完美的解决容易被游戏系统检测的问题。使用本项目的键盘信息输入方式可以绕过绝大多数游戏的键盘按键脚本的检测机制。
项目需求:
1、一个开发板,作者使用的是树莓派PICO RP2040
2、pycharm IDE
3、python3.8环境
教程:
首先去官网下载安装Arduino IDE
进入IDE,打开key_attack.ino
key_attack.ino代码
#define OSX 0
#define WINDOWS 1
#define UBUNTU 2
#include "Keyboard.h"
#include "Mouse.h"
#include <FastLED.h>
#define LED_PIN 18 //GP18
#define NUM_LEDS 3
CRGB leds[NUM_LEDS];
// change this to match your platform:
int platform = WINDOWS;
char **split(const char *source, char flag)
{
char **pt;
int j, n = 0;
int count = 1;
int len = strlen(source);
// 动态分配一个 *tmp,静态的话,变量len无法用于下标
char *tmp = (char*)malloc((len + 1) * sizeof(char));
tmp[0] = '\0';
for (int i = 0; i < len; ++i)
{
if (source[i] == flag && source[i+1] == '\0')
continue;
else if (source[i] == flag && source[i+1] != flag)
count++;
}
// 多分配一个char*,是为了设置结束标志
pt = (char**)malloc((count+1) * sizeof(char*));
count = 0;
for (int i = 0; i < len; ++i)
{
if (i == len - 1 && source[i] != flag)
{
tmp[n++] = source[i];
tmp[n] = '\0'; // 字符串末尾添加空字符
j = strlen(tmp) + 1;
pt[count] = (char*)malloc(j * sizeof(char));
strcpy(pt[count++], tmp);
}
else if (source[i] == flag)
{
j = strlen(tmp);
if (j != 0)
{
tmp[n] = '\0'; // 字符串末尾添加空字符
pt[count] = (char*)malloc((j+1) * sizeof(char));
strcpy(pt[count++], tmp);
// 重置tmp
n = 0;
tmp[0] = '\0';
}
}
else
tmp[n++] = source[i];
}
// 释放tmp
free(tmp);
// 设置结束标志
pt[count] = NULL;
return pt;
}
void setup() {
// make pin 2 an input and turn on the pull-up resistor so it goes high unless
// connected to ground:
Serial.begin(9600);
Keyboard.begin();
Mouse.begin();
}
void cue_light_gp25() {
digitalWrite(25,HIGH);
delay(20);
digitalWrite(25,LOW);
delay(20);
}
void loop() {
if (Serial.available() > 0) {
String comdata = "";
while (Serial.available() > 0) {
comdata += char(Serial.read());
}
if (comdata[0] == '0') {
if (comdata == "0_KEY_LEFT_ARROW") {
Keyboard.release(KEY_LEFT_ARROW);
} else if (comdata == "0_KEY_RIGHT_ARROW") {
Keyboard.release(KEY_RIGHT_ARROW);
} else if (comdata == "0_KEY_LEFT_CTRL") {
Keyboard.release(KEY_LEFT_CTRL);
} else if (comdata == "0_KEY_LEFT_SHIFT") {
Keyboard.release(KEY_LEFT_SHIFT);
} else if (comdata == "0_KEY_LEFT_ALT") {
Keyboard.release(KEY_LEFT_ALT);
} else if (comdata == "0_KEY_UP_ARROW") {
Keyboard.release(KEY_UP_ARROW);
} else if (comdata == "0_KEY_DOWN_ARROW") {
Keyboard.release(KEY_DOWN_ARROW);
} else if (comdata == "0_KEY_BACKSPACE") {
Keyboard.release(KEY_BACKSPACE);
} else if (comdata == "0_KEY_TAB") {
Keyboard.release(KEY_TAB);
} else if (comdata == "0_KEY_ESC") {
Keyboard.release(KEY_ESC);
} else if (comdata == "0_KEY_INSERT") {
Keyboard.release(KEY_INSERT);
} else if (comdata == "0_KEY_DELETE") {
Keyboard.release(KEY_DELETE);
} else if (comdata == "0_KEY_PAGE_UP") {
Keyboard.release(KEY_PAGE_UP);
} else if (comdata == "0_KEY_PAGE_DOWN") {
Keyboard.release(KEY_PAGE_DOWN);
} else if (comdata == "0_KEY_HOME") {
Keyboard.release(KEY_HOME);
} else if (comdata == "0_KEY_END") {
Keyboard.release(KEY_END);
} else if (comdata == "0_KEY_CAPS_LOCK") {
Keyboard.release(KEY_CAPS_LOCK);
} else if (comdata == "0_KEY_KP_ENTER") {
Keyboard.release(KEY_KP_ENTER);
} else if (comdata == "0_KEY_F1") {
Keyboard.release(KEY_F1);
} else if (comdata == "0_KEY_F2") {
Keyboard.release(KEY_F2);
} else if (comdata == "0_KEY_F3") {
Keyboard.release(KEY_F3);
} else if (comdata == "0_KEY_F4") {
Keyboard.release(KEY_F4);
} else if (comdata == "0_KEY_F5") {
Keyboard.release(KEY_F5);
} else if (comdata == "0_KEY_F6") {
Keyboard.release(KEY_F6);
} else if (comdata == "0_KEY_F7") {
Keyboard.release(KEY_F7);
} else if (comdata == "0_KEY_F8") {
Keyboard.release(KEY_F8);
} else if (comdata == "0_KEY_F9") {
Keyboard.release(KEY_F9);
} else if (comdata == "0_KEY_F10") {
Keyboard.release(KEY_F10);
} else if (comdata == "0_KEY_F11") {
Keyboard.release(KEY_F11);
} else if (comdata == "0_KEY_F12") {
Keyboard.release(KEY_F12);
} else if (comdata == "0_ALL") {
Keyboard.releaseAll();
} else if (comdata.length() == 3) {
Keyboard.release(comdata[2]);
}
} else if (comdata[0] == '1') {
if (comdata == "1_KEY_LEFT_ARROW") {
Keyboard.press(KEY_LEFT_ARROW);
} else if (comdata == "1_KEY_RIGHT_ARROW") {
Keyboard.press(KEY_RIGHT_ARROW);
} else if (comdata == "1_KEY_LEFT_CTRL") {
Keyboard.press(KEY_LEFT_CTRL);
} else if (comdata == "1_KEY_LEFT_SHIFT") {
Keyboard.press(KEY_LEFT_SHIFT);
} else if (comdata == "1_KEY_LEFT_ALT") {
Keyboard.press(KEY_LEFT_ALT);
} else if (comdata == "1_KEY_UP_ARROW") {
Keyboard.press(KEY_UP_ARROW);
} else if (comdata == "1_KEY_DOWN_ARROW") {
Keyboard.press(KEY_DOWN_ARROW);
} else if (comdata == "1_KEY_BACKSPACE") {
Keyboard.press(KEY_BACKSPACE);
} else if (comdata == "1_KEY_TAB") {
Keyboard.press(KEY_TAB);
} else if (comdata == "1_KEY_ESC") {
Keyboard.press(KEY_ESC);
} else if (comdata == "1_KEY_INSERT") {
Keyboard.press(KEY_INSERT);
} else if (comdata == "1_KEY_DELETE") {
Keyboard.press(KEY_DELETE);
} else if (comdata == "1_KEY_PAGE_UP") {
Keyboard.press(KEY_PAGE_UP);
} else if (comdata == "1_KEY_PAGE_DOWN") {
Keyboard.press(KEY_PAGE_DOWN);
} else if (comdata == "1_KEY_HOME") {
Keyboard.press(KEY_HOME);
} else if (comdata == "1_KEY_END") {
Keyboard.press(KEY_END);
} else if (comdata == "1_KEY_CAPS_LOCK") {
Keyboard.press(KEY_CAPS_LOCK);
} else if (comdata == "1_KEY_KP_ENTER") {
Keyboard.press(KEY_KP_ENTER);
} else if (comdata == "1_KEY_F1") {
Keyboard.press(KEY_F1);
} else if (comdata == "1_KEY_F2") {
Keyboard.press(KEY_F2);
} else if (comdata == "1_KEY_F3") {
Keyboard.press(KEY_F3);
} else if (comdata == "1_KEY_F4") {
Keyboard.press(KEY_F4);
} else if (comdata == "1_KEY_F5") {
Keyboard.press(KEY_F5);
} else if (comdata == "1_KEY_F6") {
Keyboard.press(KEY_F6);
} else if (comdata == "1_KEY_F7") {
Keyboard.press(KEY_F7);
} else if (comdata == "1_KEY_F8") {
Keyboard.press(KEY_F8);
} else if (comdata == "1_KEY_F9") {
Keyboard.press(KEY_F9);
} else if (comdata == "1_KEY_F10") {
Keyboard.press(KEY_F10);
} else if (comdata == "1_KEY_F11") {
Keyboard.press(KEY_F11);
} else if (comdata == "1_KEY_F12") {
Keyboard.press(KEY_F12);
} else if (comdata.length() == 3) {
Keyboard.press(comdata[2]);
}
} else if (comdata[0] == '2') {
if (comdata == "2_KEY_LEFT_ARROW") {
Keyboard.write(KEY_LEFT_ARROW);
} else if (comdata == "2_KEY_RIGHT_ARROW") {
Keyboard.write(KEY_RIGHT_ARROW);
} else if (comdata == "2_KEY_LEFT_CTRL") {
Keyboard.write(KEY_LEFT_CTRL);
} else if (comdata == "2_KEY_LEFT_SHIFT") {
Keyboard.write(KEY_LEFT_SHIFT);
} else if (comdata == "2_KEY_LEFT_ALT") {
Keyboard.write(KEY_LEFT_ALT);
} else if (comdata == "2_KEY_UP_ARROW") {
Keyboard.write(KEY_UP_ARROW);
} else if (comdata == "2_KEY_DOWN_ARROW") {
Keyboard.write(KEY_DOWN_ARROW);
} else if (comdata == "2_KEY_BACKSPACE") {
Keyboard.write(KEY_BACKSPACE);
} else if (comdata == "2_KEY_TAB") {
Keyboard.write(KEY_TAB);
} else if (comdata == "2_KEY_ESC") {
Keyboard.write(KEY_ESC);
} else if (comdata == "2_KEY_INSERT") {
Keyboard.write(KEY_INSERT);
} else if (comdata == "2_KEY_DELETE") {
Keyboard.write(KEY_DELETE);
} else if (comdata == "2_KEY_PAGE_UP") {
Keyboard.write(KEY_PAGE_UP);
} else if (comdata == "2_KEY_PAGE_DOWN") {
Keyboard.write(KEY_PAGE_DOWN);
} else if (comdata == "2_KEY_HOME") {
Keyboard.write(KEY_HOME);
} else if (comdata == "2_KEY_END") {
Keyboard.write(KEY_END);
} else if (comdata == "2_KEY_CAPS_LOCK") {
Keyboard.write(KEY_CAPS_LOCK);
} else if (comdata == "2_KEY_KP_ENTER") {
Keyboard.write(KEY_KP_ENTER);
} else if (comdata == "2_KEY_F1") {
Keyboard.write(KEY_F1);
} else if (comdata == "2_KEY_F2") {
Keyboard.write(KEY_F2);
} else if (comdata == "2_KEY_F3") {
Keyboard.write(KEY_F3);
} else if (comdata == "2_KEY_F4") {
Keyboard.write(KEY_F4);
} else if (comdata == "2_KEY_F5") {
Keyboard.write(KEY_F5);
} else if (comdata == "2_KEY_F6") {
Keyboard.write(KEY_F6);
} else if (comdata == "2_KEY_F7") {
Keyboard.write(KEY_F7);
} else if (comdata == "2_KEY_F8") {
Keyboard.write(KEY_F8);
} else if (comdata == "2_KEY_F9") {
Keyboard.write(KEY_F9);
} else if (comdata == "2_KEY_F10") {
Keyboard.write(KEY_F10);
} else if (comdata == "2_KEY_F11") {
Keyboard.write(KEY_F11);
} else if (comdata == "2_KEY_F12") {
Keyboard.write(KEY_F12);
} else if (comdata.length() == 3) {
Keyboard.write(comdata[2]);
}
} else if (comdata[0] == 'M' && comdata[1] == '1') {
if (comdata == "M1_MOUSE_LEFT") {
Mouse.press(MOUSE_LEFT);
} else if (comdata == "M1_MOUSE_RIGHT") {
Mouse.press(MOUSE_RIGHT);
} else if (comdata == "M1_MOUSE_MIDDLE") {
Mouse.press(MOUSE_MIDDLE);
} else if (comdata == "M1_MOUSE_ALL") {
Mouse.press(MOUSE_ALL);
}
} else if (comdata[0] == 'M' && comdata[1] == '0') {
if (comdata == "M0_MOUSE_LEFT") {
Mouse.release(MOUSE_LEFT);
} else if (comdata == "M0_MOUSE_RIGHT") {
Mouse.release(MOUSE_RIGHT);
} else if (comdata == "M0_MOUSE_MIDDLE") {
Mouse.release(MOUSE_MIDDLE);
} else if (comdata == "M0_MOUSE_ALL") {
Mouse.release(MOUSE_ALL);
}
}
}
delay(10);
}
选择自己插到电脑上的开发板
然后点击验证
验证成功的输出信息提示大致如下
点击上传,上传成功的输出信息提示大致如下
现在ino文件就已经上传到了开发板上面了
接下来我们使用pycharm打开项目文件夹
打开device.py
device.py代码
import datetime
import serial
ser = serial.Serial()
port = 'com9' # 自己电脑上开发板的端口号
port_status = False
def port_open_recv(): # 对串口的参数进行配置
# activate_window(window_title) # 激活窗口
ser.close()
ser.port = port
ser.baudrate = 9600
ser.bytesize = 8
ser.stopbits = 1
ser.parity = "N" # 奇偶校验位
ser.open()
if ser.isOpen():
print("当前时间为:", datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "串口已打开.")
else:
print("当前时间为:", datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "串口打开失败.")
def port_close(): # 关闭串口
ser.close()
if ser.isOpen():
print("当前时间为:", datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "串口关闭失败.")
else:
print("当前时间为:", datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "串口已关闭.")
def send(send_data, key_type=2):
"""
对Arduino开发板发送对应类型的按键信息,部分按键没有做映射,请选择比较常见的按键
:param key_type: 默认参数为2,可输入字符串形式 0:释放按键,1:按住按键,2:按下并马上释放按键(无延迟),M0:鼠标释放,M1:鼠标按住
:param send_data: 要发送按键信息.
"""
if ser.isOpen():
send_data = str(key_type) + "_" + send_data
ser.write(send_data.encode('utf-8')) # 编码
else:
print("当前时间为:", datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "Send failed")
将port = ‘com9’ 改为自己电脑上开发板的端口号
当前开发板的端口号可以在Arduino IDE的右下角直接看到
插拔开发板,以及更换插口,有概率端口号会被修改,请在代码中重新改成自己的端口号
然后运行main.py进行demo测试即可
board.py代码
from interception.device import *
from time import sleep
import random
import pyautogui as pag
LEFT_CTRL = 'KEY_LEFT_CTRL'
LEFT_SHIFT = 'KEY_LEFT_SHIFT'
LEFT_ALT = 'KEY_LEFT_ALT'
UP_ARROW = 'KEY_UP_ARROW'
DOWN_ARROW = 'KEY_DOWN_ARROW'
LEFT_ARROW = 'KEY_LEFT_ARROW'
RIGHT_ARROW = 'KEY_RIGHT_ARROW'
BACKSPACE = 'KEY_BACKSPACE'
SPACE = ' '
TAB = 'KEY_TAB'
ESC = 'KEY_ESC'
INSERT = 'KEY_INSERT'
DELETE = 'KEY_DELETE'
PAGE_UP = 'KEY_PAGE_UP'
PAGE_DOWN = 'KEY_PAGE_DOWN'
HOME = 'KEY_HOME'
END = 'KEY_END'
CAPS_LOCK = 'KEY_CAPS_LOCK'
ENTER = 'KEY_KP_ENTER'
F1 = 'KEY_F1'
F2 = 'KEY_F2'
F3 = 'KEY_F3'
F4 = 'KEY_F4'
F5 = 'KEY_F5'
F6 = 'KEY_F6'
F7 = 'KEY_F7'
F8 = 'KEY_F8'
F9 = 'KEY_F9'
F10 = 'KEY_F10'
F11 = 'KEY_F11'
F12 = 'KEY_F12'
def delay_time(first, last): # 随机延迟区间
sleep(generate_random(first, last))
def generate_random(first, last):
return random.randint(first, last) * 0.001
def press(key, continuous=50, delay=50):
send(key, key_type=1)
delay_time(continuous, continuous + 10)
send(key, key_type=0)
delay_time(delay, delay + 10)
def hold(key):
send(key, key_type=1)
delay_time(60, 70)
def release(key):
send(key, key_type=0)
delay_time(60, 70)
def release_all():
send("ALL", key_type=0)
delay_time(60, 70)
def move2(x, y):
pag.moveTo(x, y)
main.py代码
from interception.board import *
def doing():
# demo
# 输入w
press("w")
# 全选
hold(LEFT_CTRL)
press("a")
# 释放LEFT_CTRL
release(LEFT_CTRL)
if __name__ == '__main__':
port_open_recv()
sleep(3)
doing()
port_close()
完整项目下载
链接:https://pan.baidu.com/s/1s3Cvw8LMngPxBTjJzeluXw?pwd=45yh
提取码:45yh