CH340串口通信CH9329 模拟真实键盘鼠标 可防游戏检测

// 键盘按键编码定义

#define KEY_A 0x04
#define KEY_B 0x05
#define KEY_C 0x06
#define KEY_D 0x07
#define KEY_E 0x08
#define KEY_F 0x09
#define KEY_G 0x0A
#define KEY_H 0x0B
#define KEY_I 0x0C
#define KEY_J 0x0D
#define KEY_K 0x0E
#define KEY_L 0x0F
#define KEY_M 0x10
#define KEY_N 0x11
#define KEY_O 0x12
#define KEY_P 0x13
#define KEY_Q 0x14
#define KEY_R 0x15
#define KEY_S 0x16
#define KEY_T 0x17
#define KEY_U 0x18
#define KEY_V 0x19
#define KEY_W 0x1A
#define KEY_X 0x1B
#define KEY_Y 0x1C
#define KEY_Z 0x1D

// 数字按键编码定义
#define KEY_· 0x35
#define KEY_1 0x1E
#define KEY_2 0x1F
#define KEY_3 0x20
#define KEY_4 0x21
#define KEY_5 0x22
#define KEY_6 0x23
#define KEY_7 0x24
#define KEY_8 0x25
#define KEY_9 0x26
#define KEY_0 0x27

// 功能按键编码定义
#define KEY_F1 0x3A
#define KEY_F2 0x3B
#define KEY_F3 0x3C
#define KEY_F4 0x3D
#define KEY_F5 0x3E
#define KEY_F6 0x3F
#define KEY_F7 0x40
#define KEY_F8 0x41
#define KEY_F9 0x42
#define KEY_F10 0x43
#define KEY_F11 0x44
#define KEY_F12 0x45

#define KEY_ESC 0x29
#define KEY_BACKSPACE 0x2A
#define KEY_TAB 0x2B
#define KEY_ENTER 0x28
#define KEY_SPACE 0x2C // 键盘的空格键
#define KEY_MINUS 0x2D // 键盘的 - 键
#define KEY_EQUAL 0x2E // 键盘的 = 键
#define KEY_LEFT_BRACKET 0x2F // 键盘的 [ 键
#define KEY_RIGHT_BRACKET 0x30 // 键盘的 ] 键
#define KEY_BACKSLASH 0x31 // 键盘的 \ 键
#define KEY_SEMICOLON 0x33 // 键盘的 ; 键
#define KEY_QUOTE 0x34 // 键盘的 ' 键
#define KEY_COMMA 0x36 // 键盘的 , 键
#define KEY_PERIOD 0x37 // 键盘的 . 键
#define KEY_SLASH 0x38 // 键盘的 / 键
#define KEY_CAPS_LOCK 0x39
#define KEY_PRINT_SCREEN 0x46
#define KEY_SCROLL_LOCK 0x47
#define KEY_PAUSE 0x48
#define KEY_INSERT 0x49
#define KEY_HOME 0x4A
#define KEY_PAGE_UP 0x4B
#define KEY_DELETE 0x4C
#define KEY_END 0x4D
#define KEY_PAGE_DOWN 0x4E
#define KEY_RIGHT 0x4F
#define KEY_LEFT 0x50
#define KEY_DOWN 0x51
#define KEY_UP 0x52
#define KEY_NUM_LOCK 0x53
#define KEY_NUM_SLASH 0x54 // 键盘的小键盘 / 键
#define KEY_NUM_ASTERISK 0x55 // 键盘的小键盘 * 键
#define KEY_NUM_MINUS 0x56 // 键盘的小键盘 - 键
#define KEY_NUM_PLUS 0x57 // 键盘的小键盘 + 键
#define KEY_NUM_ENTER 0x58
#define KEY_NUM_1 0x59
#define KEY_NUM_2 0x5A
#define KEY_NUM_3 0x5B
#define KEY_NUM_4 0x5C
#define KEY_NUM_5 0x5D
#define KEY_NUM_6 0x5E
#define KEY_NUM_7 0x5F
#define KEY_NUM_8 0x60
#define KEY_NUM_9 0x61
#define KEY_NUM_0 0x62
#define KEY_NUM_PERIOD 0x63 // 键盘的小数点键 

// 其他可能的特殊功能编码定义(已确认)
#define KEY_WIN_LEFT 0x08
#define KEY_WIN_RIGHT 0x80
#define KEY_ALT_LEFT 0xE2
#define KEY_ALT_RIGHT 0xE6
#define KEY_SHIFT_LEFT 0xE1
#define KEY_SHIFT_RIGHT 0xE5
#define KEY_CTRL_LEFT 0xE0
#define KEY_CTRL_RIGHT 0xE4

//  CH9329 接收数据包结构体,由14个 unsigned char 构成

typedef struct CH9329_ReceiveDataFrame {
  unsigned char frameHeader1; // 帧头(固定2字节,0x57 0xAB)
  unsigned char frameHeader2;
  unsigned char addressCode; // 地址码(1字节)
  unsigned char commandCode; // 命令码(1字节)
  unsigned char dataLength; // 后续数据长度(1字节)
  union DataPacket{        // 后续数据部分(8个字节),用联合体(union)根据命令码适配不同的数据结构
    struct KeyData{        // 普通键盘数据包相关数据结构(示例,对应CMD_SEND_KB_GENERAL_DATA等类似键盘命令)
      unsigned char ControlKeys; // 控制键(1字节=8二进制位), bit7--bit0 每个bin位表示1个按键,
                   // 具体:r_win、r_alt、r_shift、r_ctrl、l_win、l_alt、l_shift、l_ctrl
      unsigned char Key_Reserved1; // 1个字节 0x00, 该字节必须为0x00;
      unsigned char KeyValues1; // 第3-8 个字节:6 个字节普通按键值,最多可以表示6 个按键按下,如果无按键按 下则填写0x00;
      unsigned char KeyValues2;
      unsigned char KeyValues3;
      unsigned char KeyValues4;
      unsigned char KeyValues5;
      unsigned char KeyValues6;
      }KeyData;
     struct absMouseData{
      unsigned char absMouseXYMode; // 鼠标坐标模式(1字节),相对鼠标坐标:0x01 或 绝对鼠标坐标:0x02
      unsigned char absMouseKey; // 鼠标按键状态(1字节),bit2--bit0 每个bin位表示1个按键,具体:中键、右键、左键
      unsigned char X_Hi; // 鼠标X轴绝对坐标的高位(1字节)
      unsigned char X_Lo; // 鼠标X轴绝对坐标的低位(1字节)
      unsigned char Y_Hi; // 鼠标Y轴绝对坐标的高位(1字节)
      unsigned char Y_Lo; // 鼠标Y轴绝对坐标的低位(1字节)
      unsigned char absWheelStatus; // 鼠标滚轮状态(1字节),具体:(0x01-0x7F)向上、(0x81-xFF)向下滚动的齿数, 0x00表示无滚动
      unsigned char absMS_Reserved1; // 空余1个字节 0x00, 该字节必须为0x00;
      }absMouseData;
    struct relMouseData {
      unsigned char relMouseXYMode; // 鼠标坐标模式(1字节),相对鼠标坐标:0x01 或 绝对鼠标坐标:0x02
      unsigned char relMouseKey; // 鼠标按键状态(1字节),bit2--bit0 每个bin位表示1个按键,具体:中键、右键、左键
      unsigned char Xoffset; // 鼠标X方向移动(1字节) [0x01-0x7F]表示向右移动、[0x81-0xFF]表示向左移动,.0x00表示无移动,0x100 - [...] 为实际移动像素值
      unsigned char Yoffset; // 鼠标Y方向移动(1字节) [0x01-0x7F]表示向右移动、[0x81-0xFF]表示向左移动,.0x00表示无移动
      unsigned char relWheelStatus; // 鼠标滚轮状态(1字节),具体:(0x01-0x7F)向上、(0x81-xFF)向下滚动的齿数, 0x00表示无滚动
      unsigned char relMS_Reserved1; // 空余1个字节 0x00, 该字节必须为0x00;
      unsigned char relMS_Reserved2; // 空余1个字节 0x00, 该字节必须为0x00;
      unsigned char relMS_Reserved3; // 空余1个字节 0x00, 该字节必须为0x00;
   }relMouseData;
  }DataPacket;
  unsigned char checksum; // 累加和(1字节)== (frameHeader1 + frameHeader2 + addressCode + commandCode + dataLength + 后续数据部分)
}SendDataFrame, *PDataFrame;


 //  CH340 串口 向 9329 发送  信息 模拟 键盘和鼠标 
//   实测 向英雄联盟 发送   有效
//        HANDLE openSerialPort(const wchar_t* portName, DWORD baudRate) 打开串口
//        SendDataFrame ConstructKeyEncode(const int ControlKey, const int GeneralKey1, const int GeneralKey2)  构建发送数据包
//      void* CH340rxCH9329(HANDLE hSerial, void* rxBuffer) 读串口数据
//    void CH340txCH9329(HANDLE hSerial, SendDataFrame* data)  写串口数据

HANDLE openSerialPort(const wchar_t* portName, DWORD baudRate) {
  HANDLE hSerial = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  if (hSerial == INVALID_HANDLE_VALUE) {
    std::cout << "无法打开串口" << std::endl;
    return INVALID_HANDLE_VALUE;
  }

// 设置串口参数
  DCB dcbSerialParams = { 0 };
  dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
  if (!GetCommState(hSerial, &dcbSerialParams)) {
    std::cout << "无法获取串口参数" << std::endl;
    CloseHandle(hSerial);
    return INVALID_HANDLE_VALUE;
  }

  dcbSerialParams.BaudRate = baudRate;
  dcbSerialParams.ByteSize = 8;
  dcbSerialParams.StopBits = ONE5STOPBITS;
  dcbSerialParams.Parity = NOPARITY;
  if (!SetCommState(hSerial, &dcbSerialParams)) {
    std::cout << "无法设置串口参数" << std::endl;
    CloseHandle(hSerial);
  return INVALID_HANDLE_VALUE;
  }

  COMMTIMEOUTS timeouts = { 0 };
  timeouts.ReadIntervalTimeout = 50;
  timeouts.ReadTotalTimeoutConstant = 50;
  timeouts.ReadTotalTimeoutMultiplier = 10;
  timeouts.WriteTotalTimeoutConstant = 50;
  timeouts.WriteTotalTimeoutMultiplier = 10;
  if (!SetCommTimeouts(hSerial, &timeouts)) {
    std::cout << "无法设置串口超时" << std::endl;
    CloseHandle(hSerial);
    return INVALID_HANDLE_VALUE;
  }

  return hSerial;
}


//  构建发送数据包即CH9329接收数据    自动计算 校验和
SendDataFrame ConstructKeyEncode(const int ControlKey, const int GeneralKey1, const int GeneralKey2) {
  SendDataFrame baseData;
  baseData = { 0x57, 0xAB, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C }; // 基础键 = 释放键

  if (ControlKey) {
    baseData.DataPacket.KeyData.ControlKeys = ControlKey;
    baseData.checksum += baseData.DataPacket.KeyData.ControlKeys;  // 累加到校验和
    if (GeneralKey1) {
      baseData.DataPacket.KeyData.KeyValues1 = GeneralKey1 ;
      baseData.checksum += baseData.DataPacket.KeyData.KeyValues1;
    }
    if (GeneralKey2) {
      baseData.DataPacket.KeyData.KeyValues2 = GeneralKey2 ;
      baseData.checksum += baseData.DataPacket.KeyData.KeyValues2;
    }
  }  else {
    if (GeneralKey1) {
      baseData.DataPacket.KeyData.KeyValues1 = GeneralKey1 ;
      baseData.checksum += baseData.DataPacket.KeyData.KeyValues1;
    }
    if (GeneralKey2) {
      baseData.DataPacket.KeyData.KeyValues2 = GeneralKey2 ;
      baseData.checksum += baseData.DataPacket.KeyData.KeyValues2;
    }
  }
  return baseData;
}

 

//  发送构建的数据
void CH340txCH9329(HANDLE hSerial, SendDataFrame* data) {
  PurgeComm(hSerial, PURGE_RXCLEAR); // 清理串口的接收rx缓存和发送tx缓存
  PurgeComm(hSerial, PURGE_TXCLEAR);

  DWORD bytesWritten;
  BOOL success = WriteFile(hSerial, (void*)data, sizeof(SendDataFrame), &bytesWritten, NULL);
  if (success == 0 ) {
    std::cout << "写入失败" << std::endl;
  }  else {

  }

  return;
}

 

/////  使用示例 英雄联盟 无法屏蔽按键操作

  const wchar_t* lpPort = L"COM4";
  HANDLE hCom = openSerialPort(lpPort, 9600);
  SendDataFrame* CH340SendData = new SendDataFrame[sizeof(SendDataFrame)];
  *CH340SendData = ConstructKeyEncode(0, KEY_CAPS_LOCK, 0);
  CH340toCH9329(hCom, CH340SendData);

结合其他截图功能(后台截图、全屏截图),可以实现后台截图分析游戏画面,发送按键释放技能,自动战斗

posted @ 2025-01-10 09:45  O-Y  阅读(841)  评论(0)    收藏  举报