/* CPPDOC_BEGIN_EXCLUDE */ /*************************************************************************** OxYD Socket v0.1 File : OxYDSocket.cpp Versions : - v0.1 (20/01/2003) : Initial release --------------------------------------------------------------------------- Copyright (C) 2003 Grégory WILMES -- Engage Security (http://www.engagesecurity.com) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ /* CPPDOC_END_EXCLUDE */ #include "stdafx.h" #include "OxYDSocket.h" BOOL CALLBACK GetWindowProcX(HWND hWnd, LPARAM lParam); BOOL CALLBACK GetWindowProc(HWND hWnd, LPARAM lParam); //HWND GetWindow(); HWND GetChildWindow(HWND hWnd, CString strCmp); char szTitle[256]; stat winds[1000]; unsigned int nCount = 0; HWND m_hWndTmp = 0; HANDLE hProcess; /** * The constructor. Initializes all variables to their default value. */ COxYDSocket::COxYDSocket() { m_hWnd = 0; m_hWndUrl = 0; m_pWnd = 0; m_pWndUrl = 0; m_nLastError = -1; m_bBrowserRunning = FALSE; m_strRemoteAddress.Empty(); m_strRemotePort.Empty(); m_strWindowOldText.Empty(); } /** * The destructor. Shutdown OxYD Socket. */ COxYDSocket::~COxYDSocket() { ShutDown(); } /** * Check is the browser is already running. * * @return BOOL : Browser state (TRUE = Up, FALSE = Down) */ BOOL COxYDSocket::IsBrowserRunning() { return m_bBrowserRunning; } /** * Initializes OxYD Socket. * * @param strRemoteAddress CString : Remote address * @param strRemotePort CString : Remote port (default = 80) * @return BOOL : Connecting state (TRUE = Ok, FALSE = Error) */ BOOL COxYDSocket::Connect(CString strRemoteAddress, CString strRemotePort) { if(m_hWnd == 0) { char szBuffer[512], szBufferCLSID[512]; long nLen = sizeof(szBuffer), nLenCLSID = sizeof(szBuffer); int nPos, nCount = 0; CString strRunningDir; STARTUPINFO stInfo; PROCESS_INFORMATION prInfo; BOOL bResult; // Find browser path // %HOMEDRIVE%%HOMEPATH% // ( ex : "C:\Program Files\Internet Explorer\IEXPLORE.EXE" ) if(RegQueryValue(HKEY_CLASSES_ROOT, "htmlfile\\CLSID", szBufferCLSID, &nLenCLSID) != ERROR_SUCCESS) { m_nLastError = ERROR__UNABLE_TO_QUERY_VALUE_FROM_REGISTRY; return FALSE; } sprintf(szBuffer, "CLSID\\%s\\DefaultIcon", szBufferCLSID); if(RegQueryValue(HKEY_CLASSES_ROOT, szBuffer, szBuffer, &nLen) != ERROR_SUCCESS) { m_nLastError = ERROR__UNABLE_TO_QUERY_VALUE_FROM_REGISTRY; return FALSE; } strRunningDir = szBuffer; if( (nPos = strRunningDir.Find(',')) == -1 ) { m_nLastError = ERROR__UNABLE_TO_FIND_BROWSER_RUNNING_DIRECTORY; return FALSE; } strRunningDir = strRunningDir.Left(nPos); // Check if Internet Explorer is the default browser if(strRunningDir.Right(strlen(BROWSER_EXE)) != BROWSER_EXE) { m_nLastError = ERROR__WRONG_DEFAULT_BROWSER; return FALSE; } // Launch browser (create process) ZeroMemory(&stInfo, sizeof(stInfo)); stInfo.cb = sizeof(stInfo); stInfo.dwFlags = STARTF_USESHOWWINDOW; #ifdef _DEBUG stInfo.wShowWindow = SW_SHOW; #else stInfo.wShowWindow = SW_HIDE; #endif bResult = CreateProcess(NULL, (LPSTR)(LPCSTR)strRunningDir, NULL, NULL, TRUE, CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS, NULL, NULL, &stInfo, &prInfo); if(bResult == FALSE) { m_nLastError = ERROR__UNABLE_TO_CREATE_A_NEW_PROCESS; return FALSE; } hProcess = prInfo.hProcess; // Try to find process (browser) window m_hWndTmp = 0; while(m_hWndTmp == 0) { if(EnumWindows((WNDENUMPROC)GetWindowProcX, (LPARAM)prInfo.dwProcessId) == 0) { // Failed to enumerates all top-level windows m_nLastError = ERROR__FAILED_TO_ENUMERATES_ALL_TOPLEVEL_WINDOWS; return FALSE; } if(m_hWndTmp == 0) { if(nCount++ > 200) // 50ms * 200 = 10s { TerminateProcess(hProcess, 0); m_nLastError = ERROR__FAILED_TO_FIND_BROWSER_WINDOW; return FALSE; } Sleep(50); } } m_hWnd = m_hWndTmp; } if(m_hWnd != 0) { RECT Rect; m_strRemoteAddress = strRemoteAddress; m_strRemotePort = strRemotePort; // Get browser window handle m_pWnd = CWnd::FromHandle(m_hWnd); // Hide browser window m_pWnd->GetWindowRect(&m_Rect); memcpy(&Rect, &m_Rect, sizeof(RECT)); #ifndef _DEBUG Rect.left -= 5000; Rect.right -= 5000; m_pWnd->MoveWindow(&Rect, TRUE); #endif // Get current window title m_pWnd->GetWindowText(m_strWindowOldText); // Get Url (edit) window handle if(m_hWndUrl = GetChildWindow(m_hWnd, "Edit")) { m_pWndUrl = CWnd::FromHandle(m_hWndUrl); // Set tool window style (invisible in taskbar) #ifndef _DEBUG m_pWnd->ModifyStyleEx(0, WS_EX_TOOLWINDOW, 0); #endif m_bBrowserRunning = TRUE; } else { m_nLastError = ERROR__FAILED_TO_ENUMERATES_ALL_TOPLEVEL_WINDOWS; m_bBrowserRunning = FALSE; } } else m_bBrowserRunning = FALSE; return m_bBrowserRunning; } /** * Initializes OxYD Socket. * * @param strRemoteAddress CString : Remote address * @param nRemotePort unsigned short : Remote port (default = 80) * @return BOOL : Connecting state (TRUE = Ok, FALSE = Error) */ BOOL COxYDSocket::Connect(CString strRemoteAddress, unsigned short nRemotePort) { CString strRemotePort; strRemotePort.Format("%u"); return Connect(strRemoteAddress, strRemotePort); } /** * Shutdown OxYD Socket if still running. * * @return BOOL : Shutdown state (TRUE = Ok, FALSE = Error) */ BOOL COxYDSocket::ShutDown() { if(IsBrowserRunning()) { // Hide browser window #ifndef _DEBUG m_pWnd->ShowWindow(SW_HIDE); /*// Remove tool window style (visible in taskbar) m_pWnd->ModifyStyleEx(WS_EX_TOOLWINDOW, 0, 0); // Show browser window m_pWnd->ShowWindow(SW_SHOW);*/ #endif m_pWnd->MoveWindow(&m_Rect, TRUE); //PostMessage(m_hWnd, WM_CLOSE, 0, 0); // Soft method to close the browser if(TerminateProcess(hProcess, 0) == 0) { m_nLastError = ERROR__UNABLE_TO_TERMINATE_THE_PROCESS; return FALSE; } m_hWnd = m_hWndTmp = 0; m_bBrowserRunning = FALSE; return TRUE; } return FALSE; } /** * Send a packet with OxYD Socket. * * @param strTxt CString : String to send * @return BOOL : Sending state (TRUE = Ok, FALSE = Error) */ BOOL COxYDSocket::SendRaw(CString strTxt) { if(IsBrowserRunning()) { //DataToHex((LPSTR)(LPCSTR)strTxt, strlen(strTxt), strTxt); // Set Url text //m_pWndUrl->SetWindowText((LPCTSTR)(m_strRemoteAddress + "/" + strTxt)); // Nothing happened with this method... if( m_strRemotePort.IsEmpty() || (m_strRemotePort == "80") ) m_pWndUrl->SendMessage(WM_SETTEXT, 0, (LPARAM)(LPCTSTR)("http://" + m_strRemoteAddress + "/" + strTxt)); else m_pWndUrl->SendMessage(WM_SETTEXT, 0, (LPARAM)(LPCTSTR)("http://" + m_strRemoteAddress + ":" + m_strRemotePort + "/" + strTxt)); // Simulate 'Enter' key (VK_ENTER = 13) m_pWndUrl->SendMessage(WM_KEYDOWN, 13, 0); m_pWndUrl->SendMessage(WM_CHAR, 13, 0); m_pWndUrl->SendMessage(WM_KEYUP, 13, 0); return TRUE; } m_nLastError = ERROR__THE_BROWSER_IS_NOT_RUNNING; return FALSE; } /** * Receive a packet with OxYD Socket. * * @param strTxt &CString : String to receive * @return BOOL : Receiving state (TRUE = Ok, FALSE = Error) */ BOOL COxYDSocket::ReceiveRaw(CString &strTxt) { if(IsBrowserRunning()) { CString strWindowText; const int nLen = strlen(BROWSER); // Get browser window text do { Sleep(50); m_pWnd->GetWindowText(strWindowText); } while(strWindowText == m_strWindowOldText); if(strWindowText.Right(nLen) == BROWSER) strWindowText = strWindowText.Left(strlen(strWindowText) -nLen); else { m_nLastError = ERROR__THE_BROWSER_IS_NOT_RUNNING; return FALSE; } //HexToData(strWindowText, (LPSTR)(LPCSTR)strWindowText); strTxt = m_strWindowOldText = strWindowText; return TRUE; } m_nLastError = ERROR__THE_BROWSER_IS_NOT_RUNNING; return FALSE; } /** * Return remote address. * * @return CString : Remote address */ CString COxYDSocket::GetRemoteAddress() { return m_strRemoteAddress; } /** * Return remote port. * * @return CString : Remote port */ CString COxYDSocket::GetRemotePort() { return m_strRemotePort; } /** * Get last error number. * * @return int : Last error number */ int COxYDSocket::GetLastError() { return m_nLastError; } /** * Get last error string from error number. * * @return CString : Last error (string format) */ CString COxYDSocket::FormatMessage(int nLastError) { CString strLastError; if(nLastError == -1) nLastError = m_nLastError; if(nLastError == ERROR__UNKNOWN_ERROR) strLastError = "Unknown error"; // else if(nLastError == ERROR__UNABLE_TO_CREATE_VALUE_KEY) // strLastError = "Unable to create value key"; else if(nLastError == ERROR__UNABLE_TO_QUERY_VALUE_FROM_REGISTRY) strLastError = "Unable to query value from registry"; else if(nLastError == ERROR__UNABLE_TO_FIND_BROWSER_RUNNING_DIRECTORY) strLastError = "Unable to find browser running directory"; else if(nLastError == ERROR__WRONG_DEFAULT_BROWSER) strLastError = "Wrong default browser"; else if(nLastError == ERROR__UNABLE_TO_CREATE_A_NEW_PROCESS) strLastError = "Unable to create a new process"; else if(nLastError == ERROR__FAILED_TO_ENUMERATES_ALL_TOPLEVEL_WINDOWS) strLastError = "Failed to enumerates all top-level windows"; else if(nLastError == ERROR__FAILED_TO_FIND_BROWSER_WINDOW) strLastError = "Failed to find browser window"; else if(nLastError == ERROR__UNABLE_TO_TERMINATE_THE_PROCESS) strLastError = "Unable to terminate the process"; else if(nLastError == ERROR__THE_BROWSER_IS_NOT_RUNNING) strLastError = "The browser is not running"; else strLastError = "Unknown error code !"; return strLastError; } /** * GetWindowProcX * * @param hWnd * @param lParam * @return BOOL */ BOOL CALLBACK GetWindowProcX(HWND hWnd, LPARAM lParam) { DWORD dwID; GetWindowThreadProcessId(hWnd, &dwID); if(dwID == (DWORD)lParam) { CString strWindowText; GetWindowText(hWnd, szTitle, sizeof(szTitle) -1); strWindowText = szTitle; if(strWindowText.Right(strlen(BROWSER)) == BROWSER) m_hWndTmp = hWnd; } return TRUE; } /** * GetWindowProc * * @param hWnd * @param lParam * @return BOOL */ BOOL CALLBACK GetWindowProc(HWND hWnd, LPARAM lParam) { GetWindowText(hWnd, szTitle, sizeof(szTitle) -1); winds[nCount].hWnd = hWnd; // winds[nCount].strText = szTitle; nCount++; return TRUE; } /** * GetChildWindow * * @param hWnd * @param strCmp * @return HWND */ HWND GetChildWindow(HWND hWnd, CString strCmp) { char szClassName[1024]; nCount = 0; if(EnumChildWindows(hWnd, (WNDENUMPROC)GetWindowProc, 0) == 0) { // Failed to enumerates all top-level windows return 0; } while(EnumChildWindows(winds[nCount -1].hWnd, (WNDENUMPROC)GetWindowProc, 0) != 0); for(unsigned int i = 0; i < nCount; i++) { if(GetClassName(winds[i].hWnd, szClassName, sizeof(szClassName) -1)) { if(strcmp(szClassName, strCmp) == 0) return winds[i].hWnd; } } return 0; }