Target Eye Revealed: Part 2 - Target Eye's Screen Capturing






4.96/5 (49 votes)
How Target Eye's screen capturing mechanism works
Voted Best C++ article of September 2012
Introduction
Screen Capturing is one of the main building blocks in any surveillance and monitoring product. Target Eye Monitoring System, developed since 2000 and till 2010, had its unique JPG screenshots. This article is the second one in the Target Eye Revealed series. The third article (following this one) is about the Shopping List mechanism. The fourth article is about Keyboard Capturing and the fifth article is about the Cover Story mechanism. The sixth article is about hiding files the Target Eye way.
Background
Target Eye Monitoring System, which I developed 12 years ago, was probably the first surveillance and monitoring tool for capturing activity of remote computers. The following description is taken from the original Business Plan of this venture:
Target Eye is a start-up company whose mission is to develop integrated software solutions for real-time monitoring of remote PCs, which are based on the company’s patent pending technologies (60/204,084 and 60/203,832). Our major product, Target Eye Monitoring System, is a software product that can continuously track, record, playback, analyze and report any activity performed on one or multiple remote PCs, in a way which is undetectable by their users. The software relies on a stream of rapidly captured, compressed full-screen images and continuous keystroke capturing to provide a comprehensive and accurate account of user activities, including local activities which do not generate any network traffic. In this way, the software can track and record activities, which are undetectable by systems relying on network traffic analysis. A smart agent module running on the monitored PCs uses a rule base to send alerts to the monitoring location(s) or perform pre-defined local operations. Monitoring can be performed from multiple locations. Major markets are law-enforcement.
Target Eye's Building Blocks
There are several terms and building blocks that sum up to the Target Eye Monitoring System:
- Target Eye Secret Agent - the covert part of the product that runs on the monitored computer
- Target Eye Operator - the authority that operates the Secret Agent (for example: a Law Enforcement agency)
- A Mission - a request to perform an action. There are many possible actions (for example, capturing the screen, as described in this article or searching and finding files, as described in this article).
- Target Eye Compiler - The tool that is used by the Target Eye Operator to customize a Secret Agent for performing specific tasks.
The Purpose of Screen Capturing
Screen Capturing serves one purpose which is to provide an accurate image of the activity that takes place on the monitored computer at a given moment. That is achieved by grabbing the image that is seen on the screen, and add to it a watermark which reflects any additional data that can help later on, to use the screenshot as an evidence: such additional data could be data and time stamp, timezone, a unique sequential number and any additional label such as the name of the active application or a certain key sequence that was captured as part of the "hot words" mechanism (for example: "Bin Laden
").
The Target Eye Screenshots Files
Screen capturing files should be small in size and yet readable. The JPG format provides the mechanism to setup a the image quality using a numeric value between 1 and 100. This value also creates a unique look for the screenshots which makes it next to impossible to forge such screens or manipulate them, ensuring that each screenshot file is genuine. Target Eye uses its own unique imperfect screens.
Taken by one of the first versions form May 2000. For the original image, press here.
This is a reduced size screenshot taken from my own laptop at December 2003. You can actually see the Visual C++ 6.0 with the Target Eye source code opened... To see the original image, click here.
Steps in Capturing the Screen
The following steps should be taken in order to capture a screen:
Get the DC
DC stands for Device Contents. The GetDC
function retrieves a handle to a device context (DC) for the client area of a specified window or for the entire screen. To get the DC of a given Window, call:
HDC hDC = GetDC(hWnd);
In our case, we pass "0
" to GetDC
, in order to capture the entire Desktop.
HDC hDC = GetDC(0);
The returned handle is used in subsequent GDI functions to draw in the DC. The device context is an opaque data structure, whose values are used internally by GDI.
Creating a Memory Compatible DC
Now we create a compatible allocated memory which is compatible with the DC we capture by calling:
HDC CreateCompatibleDC(
HDC hdc
);
We also store the width
and the height
of the area to be captured:
int ScreenWidth = GetDeviceCaps(CI.m_hScreenDC, HORZRES);
int ScreenHeight = GetDeviceCaps(CI.m_hScreenDC, VERTRES);
Creating a Compatible Bitmap
By calling CreateCompatibleBitmap
, we create a bitmap compatible with the device that is associated with the specified device context.
HBITMAP CreateCompatibleBitmap(
__in HDC hdc,
__in int nWidth,
__in int nHeight
);
SelectObject
is used to copy the data from the screen to memory.
HGDIOBJ SelectObject(
HDC hdc,
HGDIOBJ hgdiobj);
Calling BitBlt
The BitBlt
function is used for a bit-block transfer of the captured area, by transferring the entire data by each color into the destination device context.
BOOL BitBlt(
__in HDC hdcDest,
__in int nXDest,
__in int nYDest,
__in int nWidth,
__in int nHeight,
__in HDC hdcSrc,
__in int nXSrc,
__in int nYSrc,
__in DWORD dwRop
);
As this stage, we are ready to add the time stamp and any additional data on top of the captured image, as described in the following sections, but first, let's explain why and how we use ImgSource
.
ImgSource - The SDK used by Target Eye's Screen Capturing
Target Eye's screenshots are created with the help of a graphic library named ImgSource by Smaller Animals, a privately-held corporation, founded in 1993, and incorporated in 1999, based in Research Triangle Park, NC. I have a full source code license for this library, as products like Target Eye (and customers who buy it, like Law Enforcement agencies) require having full source code of all components, with no "black boxes".
Chris Losinger, the President, has provided a lot of help along the way since 2000. It should be noted that ImgSource
is not an open source library and is not a free product, but I strongly recommend it. Unregistered users can test the library but images will have a large red X drawn on them (including when it comes to the source code attached to this article). Along the many features this library has, here is a partial list:
Image File Functions
| Image Processing Functions
|
The CaptureScreen Function
Target Eye's screenshots are generated by calling CaptureScreen()
which is used to capture the entire screen into a JPG file kept in a local hidden location, and then send it to the FTP server.
The first version of Target Eye was released on May 2000 and had a simple screen capturing routine that saved the files in .bmp format, which is large in size, which makes it problematic if we wish to capture screens every minute... It was then replaced with a loosy JPG file, which did the job. The following function had gone a long way of many hours of QA, as Window's GDI consumes some memory, and if such routine is ran for days, due to bugs in GDI, the application will consume the computer's resources, but that was solved by carefully allocating and releasing the necessary resources and managing the memory allocation correctly.
static HDC ScreenDC=NULL;
static HDC hmemDC=NULL;
static HBITMAP hmemBM=NULL;
static HGLOBAL hRGB=NULL;
void SimpleCapture()
{
ScreenDC = GetWindowDC(0);
if (ScreenDC != NULL)
{
hmemDC = CreateCompatibleDC(ScreenDC);
if (hmemDC != NULL)
{
int ScreenWidth = GetDeviceCaps(ScreenDC, HORZRES);
int ScreenHeight = GetDeviceCaps(ScreenDC, VERTRES);
hmemBM = CreateCompatibleBitmap(ScreenDC, ScreenWidth, ScreenHeight);
if (hmemBM != NULL)
{
HGDIOBJ result=SelectObject(hmemDC, hmemBM); // copy screen to memory DC
if((ULONG)result!=0L && (ULONG)result!=GDI_ERROR)
{
GdiFlush();
if((BitBlt(hmemDC, 0, 0, ScreenWidth,
ScreenHeight, ScreenDC, 0, 0, SRCCOPY)))
{
hRGB = ISHBITMAPToRGB(hmemBM, (unsigned int *)&ScreenWidth,
(unsigned int *)&ScreenHeight, hmemDC, NULL);
if (hRGB)
{
// for grayscale
//.. RGB -> JPG
HISDEST hDest = ISOpenFileDest("c:\\test.jpg");
if(hDest!=NULL)
{
static ULONG ImageCount=0;
int Wrote=ISWriteJPG(hDest, (BYTE *)hRGB,
ScreenWidth, ScreenHeight, 25, 1, 24, NULL);
ISCloseDest(hDest);
TRACE("Created Image %ld\n",ImageCount++);
}
//.. clean up
GlobalFree(hRGB);
hRGB=NULL;
}
else
{
// handle error
}
}
}
DeleteObject(hmemBM);
hmemBM=NULL;
}
DeleteDC(hmemDC);
hmemDC=NULL;
}
DeleteDC(ScreenDC);
ScreenDC=NULL;
}
}
As you can see, the "Quality
" attribute set in this version is 25
(from 100
).
Creating the Header
Since versions 2003 and 2004 of Target Eye, a unique Header was created with valuable information about the screenshot. The header is created after the screen images are captured to memory, and just before the creation of the JPG file.
// Now we create the header which is stamped on top of the screen
sprintf(s,"%ld",cycle);
CString FormattedTime=(CString)CTime::GetCurrentTime().FormatGmt
(L" %A, %d.%m.%y Time Zone: %z %H:%M Label = ");
if(TextToWrite!="") FormattedTime+=TextToWrite;
FormattedTime += s;
HPEN hNewPen;
hNewPen=CreatePen(PS_SOLID, 1, RGB(233,238,45));
SelectObject(CI.m_hmemDC, hNewPen);
TextOut(CI.m_hmemDC,0,0,FormattedTime,FormattedTime.GetLength());
Naming the Files
A monitoring application should have a scheme for naming the various files it creates, including the screens captured. The function in the attached source code provides a very simple file naming scheme based on the text "Screen" followed by a sequential number and the ".jpg" extension.
CString ComposeFileName(int i)
{
CString result;
result.Format(L"%s%d%s",(CString)L"screen",i,(CString)L".jpg");
return result;
}
Target Eye uses a more sophisticated system which was based on counting the "cycles" (which are the times in which the application reaches the main event loop). The cycle occurs every X seconds, which are calculated as the minimal amount of time any information is requested to be captured. For example, if the operator requests that files will be copied every 5 minutes and screens will be captured every 10 minutes, then provided that there aren't any additional periodically information gathering requests, the cycle will be every 5 minutes. This is set using a Timer
.
Using the Source Code
The source code attached to this article is based on a newer version of Target Eye which is 100% Win32API (with no use of MFC), and UNICODE support. The following screenshot was created with the attached code, with the exception that before publishing this source code, I have removed my own personal License Key, so screenshots will have a red X on top of them.
Running a computer game (Bear in the Big Blue House), borrowed from my daughter Emma for continuous days, made it possible to ensure the screen capturing functionality is stable enough with no memory leaks.
History
- 12th June, 2014: Initial version
Michael Haephrati , CodeProject MVP 2013
©2000-2010 Target Eye LTD (UK)