30 April 2015

Anti - PasswordSpy - capturing the window procedure

There are several ways of protecting programs against PasswordSpy which could be regarded as the "godfather" of various sorts of software designed to enable the preview of the editing controls with a password. Below I present my own way of protecting a control of the ‘Edit’ class. It is a simple solution that requires capturing of the window procedure with a password. Programs of this type use IPC, by sending - to the editing window with a password - the WM_GETTEXT message using SendMessage (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam).
The third parameter of the function (wParam) is the size of the buffer to which the discovered passwords to be fit. It is the weak point that I used to protect the editing window with a password. By capturing the window PassEdit procedure, I have the opportunity to see how big the buffer is. If the length of the intruding buffer is different from the one we have programmed in our application, WM_GETTEXT for the window will not execute correctly.
The code below allows you to read the contents of the window with a password, only if the correct length of the buffer is provided; therefore, one has to declare the same length in all references to the data from the PassEdit window. The weak point of the solution is the possibility of using the same length of the buffer (in the case of PasswordSpy it is 128 characters) by the intruder, but the probability is rather low. Another interesting fact is that PasswordSpy is recognized as a threat by Symantec AntiVirus, however, not a heuristic method, but a simple signature determines the threat to be valid - so to use it, one must compile the code themselves or base their Spy on the available code. During the movement of the mouse over the main window, the data rewriting from PassEdit takes place. The code of the protection method was developed in DevC++
// copyright "Copyright © 2011, www.FiveWithFour.blogspot.com"

#include < windows.h >

HINSTANCE   hInstance;
HWND        hPassEdit, hEdit;
LONG        lEditProc;
DWORD       dwBuffSize = 200;
char        szClassName[ ] = "WindowsApp";

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK EditWndProc (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)
    {
    HWND hwnd;
    MSG messages;
    WNDCLASSEX wincl;

    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    if (!RegisterClassEx (&wincl))
        return 0;

    hwnd = CreateWindowEx(0, szClassName, "5w4 Anti-PasswordSpy example", WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT, 300, 240,
                          HWND_DESKTOP, NULL, hThisInstance, NULL);

    ShowWindow (hwnd, nFunsterStil);
    while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }
    return messages.wParam;
    }
    
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   {
   char   sBuff[dwBuffSize];

   switch (message)
      {
      case WM_CREATE:
         hPassEdit = CreateWindowEx(WS_EX_CLIENTEDGE,
                                    "Edit","",
                                    WS_CHILD|WS_VISIBLE|ES_PASSWORD,
                                    20,20,250,20,
                                    hwnd,NULL,hInstance,NULL);
         hEdit = CreateWindowEx(WS_EX_CLIENTEDGE,
                                "Edit","",
                                WS_CHILD|WS_VISIBLE,
                                20,50,250,20,
                                hwnd,NULL,hInstance,NULL);
         lEditProc = SetWindowLong(hPassEdit, GWL_WNDPROC, (LONG)EditWndProc); 
         break;
      case WM_COMMAND:
         break;
      case WM_MOUSEMOVE:
         SendMessage(hPassEdit, WM_GETTEXT, sizeof(sBuff), (LPARAM)sBuff);           
         SendMessage(hEdit, WM_SETTEXT, sizeof(sBuff), (LPARAM)sBuff);
         break;         
      case WM_DESTROY:
         PostQuitMessage(0);
         break;
      default:
         return DefWindowProc (hwnd, message, wParam, lParam);
      }
   return 0;
   }
   
LRESULT CALLBACK EditWndProc (HWND hEdit, UINT uMsg, WPARAM wParam, LPARAM lParam)
   {
   switch (uMsg)
      {
      case WM_GETTEXT:
         if ((DWORD)wParam == dwBuffSize)
            return CallWindowProc((WNDPROC)lEditProc, hPassEdit,uMsg, wParam, lParam);
         break;         
      default:
         return CallWindowProc((WNDPROC)lEditProc, hPassEdit,uMsg, wParam, lParam);
         break;
      }
   return 0;
   }