Click here to Skip to main content
1,822 members
Articles / Multimedia / C++
Article

Spy Inside (SpyInside) a portable monitoring application

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
4 Oct 2013CPOL 12.4K   2  
An example of a small and easy to implement monitoring application

Introduction

Monitoring applications can be used for Parental Control or just as a safe guard for your own computer, while you are away. It can be helpful to even find out what you have done, deleted text, etc.


Background

The purpose of this project is to create a small application which will run in the background and capture screenshots periodically along with the text typed. Pressing ALT+U terminates it. Plain and simple.


The CConsoleWindow class

The purpose of this class is to allow dumping text such as trace calls into a console window.

C++
typedef enum {    
    endl     // new line
}ConsoleWndConstant;
 
class CConsoleWnd
{
    HANDLE m_hConsoleWnd;
public:
    CConsoleWnd();
    
    const CConsoleWnd& operator<<(ConsoleWndConstant nConstant) const;
    const CConsoleWnd& operator<<(LPCSTR lpsz) const;
    const CConsoleWnd& operator<<(LPCWSTR lpsz) const;
    const CConsoleWnd& operator<<(int nNum) const;
    const CConsoleWnd& operator<<(unsigned long lNum) const;
    const CConsoleWnd& operator<<(__int64 nNum) const;
    const CConsoleWnd& operator<<(unsigned __int64 uNum) const;
    const CConsoleWnd& operator<<(double dNum) const;
    const CConsoleWnd& operator<<(float fNum) const;
    const CConsoleWnd& operator<<(const void* ptr) const;
    const CConsoleWnd& operator<<(TCHAR tChar) const;
};  

The CMouseTracker class

This class handles grabbing data from the mouse but initiate the capture of screens.

C++
class CMouseTracker
<pre>{
    BOOL m_bIsRunning;
public:
    int m_xPos;
    int m_yPos;
    UINT m_uLastMsg;
public:
    CMouseTracker();
    void Start();
    void Stop();
};

The ScreenSnapshot class

This class handles capturing the screens which includes also the place of the mouse cursor.

C++
class CScreenSnapshot
<pre>{
    DWORD m_dwAddEntity;
    int m_nImageQuality;
    CString m_strUserName;
    CString m_strComputerName;
    TCHAR m_szActiveAppName[100];
    CBitmap m_bmpResult;
public:
    CImageList m_ImageListSingle;
public:
    CScreenSnapshot();
    CScreenSnapshot(DWORD dwAddEntity, int nImageQuality);
    void operator=(const CScreenSnapshot& ScreenSnapshot);
    enum AddEntity {
        addUserName      = 0x00000002,
        addComputerName  = 0x00000004,
        addActiveAppName = 0x00000008,
        addAll           = 0xFFFFFFFF
    };
    
    void Snapshot(const SCREENSHOT_INFO* pScreenshotInfo); 
};

Handling Bitmaps using CBitMap

This CBitMap class handles all functionalists and manipulations on bitmaps including saving them as a .bmp file.

C++
class CBitmap
{
    HBITMAP m_hBitmap;
public:
    CBitmap();
    CBitmap(HBITMAP hbmp);
    operator HBITMAP() const;
    
    void CreateCompatible(HDC hDC, int nWidth, int nHeight);
    void Stretch(int nDesiredWidth, int nDesiredHeight);                   // The bitmap must not be selected with a DC
    
    void Copy(HBITMAP hbmp);
    BOOL Compare(HBITMAP hbmp); 
    void CreateMask(HBITMAP hbmp);
    void SaveToFile(LPCWSTR lpszFileName, int nQuality = 10) const;
    void Delete();
}; 

Handling Hotwords via CHotwords

The CHotwords class is used to define how hot words are treated. A hot word is a sequence of keys which triggers an action as a result of being typed. For example, typing "quit" will quit the application. 

 class CHotwords
{
	CString m_strHotwords;
	CHotwordEvent* m_pHotwordEvents;
public:
	int m_nCount;                                 // Do NOT access this member directly
public:
	CHotwords();
	CHotwords(const CHotwords& src);
	void operator=(const CHotwords& src);
	CString GetHotwords() const;
	void Add(LPCTSTR lpszHotword, const CHotwordEvent& HotwordEvent);
	~CHotwords();
	friend class CKeyRecorder;
}; 

There could be other triggers which will follow a certain key word. In this demonstration, (and please be careful when using it...), typing "reboot" anywhere, will reboot your PC! 

Recording keystrokes via CKeyRecorder 

The CKeyRecorder class is used to capture keystrokes and convert them to their correct character based on the current key-map. That way, if a user uses a multilingual keyboard, such as Hebrew-English, and the same key can means different characters, the class will know to which character to convert it. 

class CKeyRecorder 
{
public:
	CHotwords m_Hotwords;
	static DWORD s_dwCatchHotwordsThreadId;
    static DWORD s_dwRecorderThreadId;
    static DWORD s_dwHandleHotwordThreadId;
	static BOOL s_bIsRunning;
    static HHOOK s_hKeyHook;
	static HANDLE s_hFile;
	static HWND s_hWndMainWnd;
public:
	CKeyRecorder();
	CKeyRecorder(const CHotwords& Hotwords);
	void operator=(const CKeyRecorder& KeyRecorder);
	void Start(HWND hWndMainWnd);
	void Stop();
	const CHotwordEvent* GetHotwordEvent(int nIndex) const;
	friend class CLocalQuota;
	friend class CDataSender;
};

There are two additional classes used in conjunction with other classes which takes care of two tasks:

1. Maintaining a Quota, to prevent overloading the monitored computer with too much data, taking care of various scenarios such as what to do when quota is reached, and what to do if afterward, the quota is released and there is free space, etc. All of the above is done via CLocalQuota

2. Taking care of transmitting data to a server, or via email or using any other way. That is done via another class named CDataSender.

These 2 aren't covered in the scope of this article.

ATL / MFC alternative 

You will find in this source code a complete replacement of many of the ATL or MFC classes. That can be a nightmare in many cases Smile | :)  as it is not advised to reinvent the wheel, but in this case,  these were tested, debugged and fixed for around a year and the advantage is speed and compact side, as you don't have to link or use MFC DLL or static library, and same goes with ATL. 

Tracing via WriteToLog 

A while ago I have developed this small routine which is very useful for tracing and logging activities and errors. It is used like printf or TRACE and saves the output into one continuous file. 

void WriteToLog(LPCTSTR lpText, ...)
{
	FILE* file;
	CTime time = CTime::ApiGetCurrentLocalTime();
	CString strMsg;
	va_list ptr;
	va_start(ptr, lpText);
	strMsg.VFormat(lpText, ptr);
	CString strDate = time.FormatDate(_T("d/MM/yyyy"));
	CString strTime = time.FormatTime(_T("hh:mm:ss tt"));
	
	CString strTrace;
	strTrace.Format(_T("%s %s: %s"), (LPCTSTR)strTime, (LPCTSTR)strDate, (LPCTSTR)strMsg);
	
	file = _tfopen(LOG_FILENAME, L"a");
	if (file)
	{
		_ftprintf(file, _T("\n%s\n"), (LPCTSTR)strTrace);
		fclose(file);
	}
}

 Handling captured screens via CImageList

CImageList is a class developed as part of this project which can be used to maintain a list of image files, allowing each file to be moved, removed, added, and obtained. 

class CImageList
{
	HIMAGELIST m_hImageList;
public:
	CImageList();                                             // Default constructor sets m_hImageList to null
	CImageList(HIMAGELIST hImageList);                        // Attaches an image list handle
    CImageList(WORD ID, UINT cxImage, COLORREF clrMask,       // Loads a bitmap from the resource and creates the image list, clrMask is used to create a bitmap mask, you can use any RGB color or one of CImageList::ColorFlag
		UINT uGrowCount = 0);  
	CImageList(LPCTSTR lpszFileName, UINT cxImage,            // Loads a bitmap from a file and creates the image list, clrMask is used to create a bitmap mask, you can use any RGB color or one of CImageList::ColorFlag
		COLORREF clrMask, UINT uGrowCount = 0); 
	operator HIMAGELIST() const;                              // Casting operator returns the wrapped handle
	void operator=(HIMAGELIST hImageList);                    // Re-Attaches an image list handle
	enum ImageListFlags {
		// [Use one of the below flags]
		ilColor         = ILC_COLOR,                          // Use the default behavior if none of the other imageListCOLOR* flags is specified
		ilColor4        = ILC_COLOR4,                         // Use a 4-bit (16-color) device-independent bitmap (DIB) 
		ilColor8        = ILC_COLOR8,                         // Use an 8-bit device-independent bitmap (DIB) 
		ilColor16       = ILC_COLOR16,                        // Use a 16-bit device-independent bitmap (DIB) 
		ilColor24       = ILC_COLOR24,                        // Use a 24-bit device-independent bitmap (DIB)  
		ilColor32       = ILC_COLOR32,                        // Use a 32-bit device-independent bitmap (DIB) 
		ilColorDDB      = ILC_COLORDDB,                       // Use a device-dependent bitmap
        // [Mask flag can be used with one of the above flags]
		ilMask          = ILC_MASK,                           // Use masks, the image list will contain two images for each image index for for the mask (monochrome bitmap) and the another for color bitmap	
	}; 
    
	enum ColorFlag {                             // Color flags can be one of them
		colorNone       = CLR_NONE,          // In Load and Add means NO mask. In draw member functions: bkColor means No background color (the image is drawn transparently). And as fgColor means NO blend color (the image is blended with the color of the destination device context)
		colorDefault    = CLR_DEFAULT        // In Load and Add means the mask color is the pixel color of the left upper corner of the bitmap. In draw member functions: bkColor means the image is drawn using the background color of the image list. And as fgColor means the image is drawn using the system highlight color as the foreground color
	};
	BOOL Create(DWORD dwImageListFlags, UINT cxImage,         // Creates an empty image list, uImageCount is the initial count for the images, uGrowCount the number of images that to expand the image list 
		UINT cyImage, UINT uImagesCount, UINT uGrowCount = 0); 
	
	BOOL Load(WORD ID, UINT cxImage, COLORREF clrMask,        // Loads a bitmap from the resource and creates an image list, clrMask is used to create a bitmap mask, you can use any RGB color or one of CImageList::ColorFlag
		UINT uGrowCount = 0); 
	
	BOOL Load(LPCTSTR lpszFileName, UINT cxImage,             // Loads a bitmap from a file and creates an image list, clrMask is used to create a bitmap mask, you can use any RGB color or one of CImageList::ColorFlag
		COLORREF clrMask, UINT uGrowCount = 0); 
	int Add(HICON hIcon);                                     // Adds an icon or a cursor to the image list and returns the image index, it returns -1 if there is an error
	int Add(HBITMAP hbmpImage, HBITMAP hbmpMask);             // Adds a bitmap to the image list and returns the image index, it returns -1 if there is an error, if the image list does not support masks then pass NULL to the hbmpMask
	int Add(HBITMAP hbmpImage, COLORREF clrMask);             // Adds a bitmap to the image list and creates a mask for the bitmap and returns the image index, it returns -1 if there is an error, clrMask is used to create a bitmap mask, you can use any RGB color or one of CImageList::ColorFlag
    
	BOOL Replace(int nImageIndex, HBITMAP hbmpImage, HBITMAP hbmpMask); // Replaces one bitmap in the image list with another 
	BOOL Replace(int nImageIndex, HICON hIcon);               // Replaces one icon or a cursor in the image list with another 
	BOOL Remove(int nImageIndex);                             // Removes an image from the image list, and shifts the images indexes, so each image will have (its index - 1)
    BOOL Empty();                                             // Empties the image list, removes all images in the image list
	BOOL Copy(int nDstImageIndex, HIMAGELIST hSrcImageList, int nSrcImageIndex); // Copies one image from the source image list to the wrapped image list (destination)
	BOOL Swap(int nDstImageIndex, HIMAGELIST hSrcImageList, int nSrcImageIndex); // Swaps (exchanges) images between the source image list and the wrapped image list (nDstImageList is the index for the wrapped image list)
		
	int GetImageCount() const;                                // Returns the number of images in the image list
	BOOL GetImageInfo(int nImageIndex, IMAGEINFO* pii) const; // Retrieve information about an image in the image list
  	
	enum DrawStyle {                                          // Draw styles 
		drawBlend25          = ILD_BLEND25,                   // Draws the image, blending 25 percent with the system highlight color (Focus), the image list should have a mask
		drawBlend50          = ILD_BLEND50,                   // Draws the image, blending 50 percent with the system highlight color (Selected), the image list should have a mask
		drawMask             = ILD_MASK,                      // Draws the mask 
		drawNormal           = ILD_NORMAL,                    // Draws the image using the background color for the image list
		drawTransparent      = ILD_TRANSPARENT,               // Draws the image transparently using the mask, regardless of the background color, the image list should have a mask
	};
    
	COLORREF SetBkColor(COLORREF clrBk);                      // Use it if you perform a masked drawing operations AND the background color of the destination is solid color. This function is for optimazing the performance. The function returns the prevoius bk color (if any)
    COLORREF GetBkColor() const;                              // Returns the current back color of the image list that was prevoiusly set by the SetBkColor member function 
	BOOL Draw(HDC hdcDst, int nImageIndex,                    // Draws an image list item into the specified device context
		const POINT& pt,                                      // Contains the coordinates at which to draw the image  
		DWORD dwDrawStyle                                     // It can be one flag of CImageList::DrawStyle
		) const; 
	BOOL DrawEx(HDC hdcDst, int nImageIndex,                  // Draws an image list item into the specified device context, it blends the image with specified color  
		const POINT& pt,                                      // Contains the coordinates at which to draw the image  
		const SIZE& size,                                     // Contains the width and height portions of the image to draw, if the width and height are zeros then the entire image will draw 
		COLORREF clrBk,                                       // Background color of the image, it can be an RGB color or one flag of CImageList::ColorFlag
		COLORREF clrFg,                                       // Foreground color of the image, it can be an RGB color or one flag of CImageList::ColorFlag
		DWORD dwDrawStyle                                     // It can be one flag of CImageList::DrawStyle
		) const;
	HIMAGELIST Duplicate() const;                             // Creates a duplicate for the wrapped image list
	BOOL Destroy();                                           // Destroys the m_hImageList and frees memory
};

 More details to come...

  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Michael Haephrati
United States United States
Michael Haephrati, born in 1964, an entrepreneur, inventor and a musician. Haephrati worked on many ventures starting from HarmonySoft, designing Rashumon, the first Graphical Multi-lingual word processor for Amiga computer.

Worked with Amdocs and managed several software projects, among them one for the Ministry of Tourism in New Zealand. During 1995-1996 he worked as a Contractor with Apple at Cupertino. After returning to Israel, worked as a Project Manager with Top Image Systems (mostly with JCC, Nicosia), and then at a research institute made the fist steps developing the credit scoring field in Israel. He founded Target Scoring and developed a credit scoring system named ThiS, based on geographical statistical data, participating VISA CAL, Isracard, Bank Leumi and Bank Discount (Target Scoring, being the VP Business Development of a large Israeli institute).
During 2000, he founded Target Eye, and developed the first remote PC surveillance and monitoring system, named Target Eye.

Other ventures included: Data Cleansing (as part of the DataTune system which was implemented in many organizations.


Also a Code Project Member since Sunday, March 16, 2003 (10 years, 5 months)
20 Sep 2013: Best C++ article of August 2013
25 Jan 2013: Code Project - Best C++ article of December 2012
31 Dec 2012: CodeProject MVP 2013

Comments and Discussions

 
-- There are no messages in this forum --