Solved

Delphi DLL hook

Posted on 2003-12-07
11
31,045 Views
Last Modified: 2012-05-04
Anyone got a working example of a dll hook, basically i would like to do something like get the handle of a program (at runtime) and then process the messages like wm_close or mouse click and prevent it if it's even possible.

all i can find on the net are stupid keyloggers...

Thanx folks...
0
Comment
Question by:craig_capel
  • 4
  • 3
  • 2
  • +2
11 Comments
 
LVL 1

Expert Comment

by:fanar
Comment Utility
http://www.swissdelphicenter.com/en/showcode.php?id=1212
Check this out there is a link to down load the source also
0
 
LVL 2

Author Comment

by:craig_capel
Comment Utility
Nope...

For example something like this, this is where i find it's not possible..

Wnd:=Findwindow.... (Get notepad's handle, or something else)
SetHook(HandleToWindow);

The dll the runs, it then gets the messageproc of the new program, if if msg = wm_close then stop it.

I have a program in C++ which uses a DLL to monitor another applications wm messages and if it detects a mouse wheel it scrolls
it down (i use it on Delphi 3).

i will post the code in the next post
0
 
LVL 2

Author Comment

by:craig_capel
Comment Utility
//==========================================
// Matt Pietrek
// Microsoft Systems Journal, June 1997
// FILE: MouseWheel.CPP
//==========================================
#include <windows.h>
#include "mousewheel.h"

//=============================================================================
// Data
//=============================================================================

// Shared Data
#pragma data_seg(".shared")     // Make a new section that we'll make shared
HHOOK g_hHook=0;                // HHOOK from SetWindowsHook
UINT  g_WM_MOUSEWHEEL = 0;      // Window message for mousewheel scrolling
                                // Back to regular, non-shared data
char g_szRegPath[] = "Software\\WheatyProductions\\MouseWheel";
#pragma data_seg()

// Per process data
BOOL g_IsHookingProcess = FALSE;
BOOL g_okToAct = FALSE;
BOOL g_pageIncrements = FALSE;
unsigned g_incrementAmount = 1;

//=============================================================================
// Start of code
//=============================================================================

LRESULT CALLBACK GetMsgProc(
    int code,        // hook code
    WPARAM wParam,   // removal flag
    LPARAM lParam)   // address of structure with message
{
    LRESULT retValue = 0;

    // Be a good citizen, and call the other hooks
    retValue = CallNextHookEx( g_hHook, code, wParam, lParam );

    if ( FALSE == g_okToAct )    // Bail out if this process isn't one that
        return retValue;        // we care about

    LPMSG pMsg = (LPMSG)lParam;    // Make a ptr to the MSG structure for exam

    // If it's not a MOUSEWHEEL message, or if the app is just PEEK'ing,
    // bail out now.

    if ( g_WM_MOUSEWHEEL != pMsg->message || (wParam == PM_NOREMOVE) )
        return retValue;

    // By this point, we know a WM_MOUSEWHEEL message will be delivered.
    // Synthesize the appropriate WM_VSCROLL message(s) and post them

    WPARAM upDown;

    if ( g_pageIncrements )
        upDown = (short)HIWORD(pMsg->wParam) > 0 ? SB_PAGEUP : SB_PAGEDOWN;
    else
        upDown = (short)HIWORD(pMsg->wParam) > 0 ? SB_LINEUP : SB_LINEDOWN;

    for ( unsigned i = 0; i < g_incrementAmount; i++ )
        PostMessage(pMsg->hwnd, WM_VSCROLL, upDown,    0 );

    return 1;
}

UINT GetMouseWheelMsg( void )
{
    OSVERSIONINFO osvi;

    osvi.dwOSVersionInfoSize = sizeof(osvi);

    if ( !GetVersionEx(&osvi) )
        return WM_MOUSEWHEEL;            // Got a better idea?

    // NT 4 and later supports WM_MOUSEWHEEL
    if ( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId )
        if ( osvi.dwMajorVersion >= 4 )
            return WM_MOUSEWHEEL;

    // Future Win32 versions ( >= 5.0 ) should support WM_MOUSEWHEEL
    if ( osvi.dwMajorVersion >= 5 )
        return WM_MOUSEWHEEL;

    // Hmmm... an older version.  The mouse driver support app should
    // have registered a window message for it.  By registering the
    // same message, we should get back the same message number.
    // Note that "MSWHEEL_ROLLMSG" below is a #define taken from ZMOUSE.H,
    // which is from the "Intellimouse SDK".
   
    return RegisterWindowMessage( "MSWHEEL_ROLLMSG" );
}


BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,    // handle to DLL module
    DWORD fdwReason,    // reason for calling function
    LPVOID lpvReserved)    // reserved
{
    //=========================================================================
    // DLL Process attach
    //=========================================================================

    if ( fdwReason == DLL_PROCESS_ATTACH )
    {
        // We don't need thread notifications for what we're doing.  Thus, get
        // rid of them, thereby eliminating some of the overhead of this DLL,
        // which will end up in nearly every GUI process anyhow.
        DisableThreadLibraryCalls( hinstDLL );

        if ( lpvReserved )   // Is this main process that sets the hook and
        {                    // loads this DLL initially ???

            if ( g_hHook )        // If we've already hooked, fail the DllMain
                return FALSE;

            g_IsHookingProcess = TRUE;

            // Set a global GetMessage hook
            g_hHook = SetWindowsHookEx( WH_GETMESSAGE, (HOOKPROC)GetMsgProc,
                                        hinstDLL, 0 );

            g_WM_MOUSEWHEEL = GetMouseWheelMsg();
        }

        // Get the name of the parent process EXE, and uppercase it
        char szExeName[MAX_PATH];
        GetModuleFileName( 0, szExeName, sizeof(szExeName) );
        CharUpperBuff( szExeName, lstrlen(szExeName) );

        //
        // Determine if the parent process EXE's name is in the registry, under
        // our special key.  If not, we won't bother translating mousewheel
        // scroll messages into WM_VSCROLL messsages.
        //

        HKEY hKey;
        if (ERROR_SUCCESS==RegOpenKey( HKEY_CURRENT_USER, g_szRegPath, &hKey))
        {
            DWORD dwValue = 0;
            DWORD dType, cbValue = sizeof(dwValue);

            if ( ERROR_SUCCESS == RegQueryValueEx(  hKey, szExeName, 0, &dType,
                                                    (PBYTE)&dwValue, &cbValue))
            {
                g_incrementAmount = dwValue & MW_SCROLL_INCREMENT_MASK;
                g_pageIncrements = dwValue & MW_SCROLL_PAGE ? TRUE : FALSE;

                g_okToAct = TRUE;
            }

            RegCloseKey( hKey );
        }

        // else.... This process's EXE wasn't under our key.  Do nothing.
    }

    //=========================================================================
    // DLL Process detach
    //=========================================================================

    else if ( fdwReason == DLL_PROCESS_DETACH )
    {
        if ( g_IsHookingProcess && g_hHook )    // The main EXE that loaded
        {                                       // this DLL is shutting down,
            UnhookWindowsHookEx( g_hHook );     // so remove the hook
            g_hHook = 0;
        }
    }

    return TRUE;
}

//-------------------------------------------------------------
// Dummy startup routine that does nothing except call DllMain
// This cuts out all of the standard startup code crud that
// bloats the DLL, and makes it take longer to load
//-------------------------------------------------------------
extern "C" BOOL __stdcall _DllMainCRTStartup(
    HINSTANCE hinstDLL,     // handle to DLL module
    DWORD fdwReason,        // reason for calling function
    LPVOID lpvReserved)     // reserved
{
    return DllMain( hinstDLL, fdwReason, lpvReserved );
}

//----------------------------------------------------------------------------
// Dummy routine that allows the main EXE to have an implicit import of
// this DLL.
//----------------------------------------------------------------------------
void DoNothing(void)
{
}
0
 
LVL 1

Expert Comment

by:fanar
Comment Utility
SetWindowsHookEx(WH_GETMESSAGE, @PROC, hInstance, GetWindowThreadProcessId(startwnd,nil));

function PROC(nCode: Integer; wp: wParam; lp: lParam): LongInt; stdcall;
begin
    if (nCode >= HC_ACTION) then
//check to see if it is wm_mousemove or wm_etc
//check windows sdk help it has documentation on every hook
//if u can also check the help for setWindowsHookEx in the sdk
     pmsg(lp).message:=WM_NULL;//will cancell it
    Result := CallNextHookEx(buf^.hMSNHook, nCode, wp, lp);
   end;
end;

I have a working source with this. It blocks all the messages from notepad. But the source is very very messy cause i modified another hook to do that. So if u still want that i could post it later.
0
 
LVL 2

Author Comment

by:craig_capel
Comment Utility
Yes please.. i am more interesting in incerpting the wm_close as i intend on writing a hook to prevent
the shutdown of one of my old programs which i no longer the source for :(
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 5

Expert Comment

by:snehanshu
Comment Utility
craig_capel,
I think you could use CBT hooks for trapping HCBT_DESTROYWND or HCBT_SYSCOMMAND.
I had recently found this thread during my cleanup effort and had bookmarked it, hope it helps.

...Snehanshu
For CBT hook:
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20389057.html

0
 
LVL 1

Accepted Solution

by:
fanar earned 100 total points
Comment Utility
Hey here you go. This is the modiefied dll(I thnk Geubol translated it from c to delphi). This dll stops notepad from closing. Sorry for the mess its just with school exams and stuff that are coming up i dont have time for anything any more

library MSNHook;

uses
 Windows,
 Messages,sysutils;

type
 THookRec = record
   hMSNHook: HHOOK;
   hMSNWnd: HWND;
   oldProc: Integer;
 end;

var
 map: DWord;
 buf: ^THookRec;



function PROC(nCode: Integer; wp: wParam; lp: lParam): LongInt; stdcall;
begin
    if (nCode >= HC_ACTION) then
    if (nCode=HCBT_DESTROYWND)then
    begin
    Result:=1;
    exit;
    end;
    Result := CallNextHookEx(buf^.hMSNHook, nCode, wp, lp);

end;

// sets up hook
function SetHook: Boolean; stdcall; export;
var
startwnd:HWND;
begin
 try
   Result := false;
   if (not assigned(buf)) then
   begin
     map := CreateFileMapping(DWord(-1), nil, PAGE_READWRITE, 0, SizeOf(THookRec), 'HookRecMemBlock');
     buf := MapViewOfFile(map, FILE_MAP_ALL_ACCESS, 0, 0, 0);
     startwnd:=FindWindow('Notepad', nil);
     buf^.hMSNWnd:=startwnd;
     buf^.hMSNHook := SetWindowsHookEx(WH_CBT, @Proc, hInstance, GetWindowThreadProcessId(startwnd,nil));
     Result := true;
   end;
 except
   Result := false;
   MessageBox(0, 'error in SetHook', 'error', MB_OK);
 end;
end;

// removes hook
function RemoveHook: Boolean; stdcall; export;
begin
 Result := false;
 if (assigned(buf)) then
 begin

   if (buf^.hMSNHook <> 0) then UnhookWindowsHookEx(buf^.hMSNHook);
   buf^.hMSNHook := 0;
   UnmapViewOfFile(buf);
   buf := nil;
   Result := true;
 end;
end;

// DLL entry point
procedure DllEntry(dwReason: DWord);
begin
 Case dwReason of
   DLL_PROCESS_ATTACH:
   begin
     if (not assigned(buf)) then
     begin
       map := OpenFileMapping(FILE_MAP_ALL_ACCESS, false, 'HookRecMemBlock');
       buf := MapViewOfFile(map, FILE_MAP_ALL_ACCESS, 0, 0, 0);
       CloseHandle(map);
       map := 0;
     end;
   end;
   DLL_PROCESS_DETACH:
   begin
     UnmapViewOfFile(buf);
     buf := nil;
   end;
 end;
end;

exports
 SetHook,
 RemoveHook;

// main
begin
 DisableThreadLibraryCalls(hInstance);
 DllProc := @DLLEntry;
 DllEntry(DLL_PROCESS_ATTACH);
end.
0
 
LVL 2

Author Comment

by:craig_capel
Comment Utility
Muchos Gracias Senor.
0
 
LVL 5

Expert Comment

by:snehanshu
Comment Utility
Hmm,
Interesting to see how the working source of
>>SetWindowsHookEx(WH_GETMESSAGE, @PROC, hInstance, GetWindowThreadProcessId(startwnd,nil));
translated to
>>SetWindowsHookEx(WH_CBT, @Proc, hInstance, GetWindowThreadProcessId(startwnd,nil));
0
 

Expert Comment

by:bBK
Comment Utility
Just to follow solution :)
0
 
LVL 4

Expert Comment

by:tobjectpascal
Comment Utility
The solution is above, it's been answered already.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now