Newsgroup: it.comp.programmare.win32
Titolo: SetWindowsHookEx

Non mi spiego perchè la SetWindowsHookEx non mi inietta la DLL in
processo. Qui sotto riporto il codice:
STARTER:
******************************
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <shlwapi.h>
#pragma comment(lib, "user32")
HINSTANCE DllHandle = NULL;
//**************************************
//* WinMain
//**************************************
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR
lpCmdLine,int nCmdShow)
{
		LPVOID lpInstallHook;
		DllHandle = LoadLibrary("kernel29.dll");
        if( DllHandle != NULL )
        {
            lpInstallHook = (LPVOID)GetProcAddress(DllHandle,
"InstallHook");
            if(lpInstallHook != NULL)
            {
                if(lpInstallHook)
                    return 0;
                MessageBox(0,"Can't install hook","Finestra di
dialogo",0);
            }
            else
                MessageBox(0,"Can't load hook functions","Finestra di
dialogo",0);
            FreeLibrary(DllHandle);
            DllHandle = NULL;
        }
	return 0;
}
DLL.def
*******************
EXPORTS
	InstallHook		@1
	UnistallHook	       @2
DLL.c
********************
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "user32")
#pragma comment(lib, "kernel32")
HINSTANCE glb_hModule;	//* Handle globale dell'istanza del modulo
HHOOK glb_hHook;		//* Handle globale per'hook
//
**************************************************************************************
//* UnistallHook()
//
**************************************************************************************
__declspec(dllexport) void CALLBACK UnistallHook ()
{
	if(glb_hHook)
	{
		UnhookWindowsHookEx(glb_hHook);
		glb_hHook = NULL;
	}
}
//
***************************************************************************************
//* HookProc
//
***************************************************************************************
LRESULT CALLBACK HookProc ( int nCode, WPARAM wParam, LPARAM lParam)
{
    static int c = 0;
	if(nCode < 0)
	{
		return CallNextHookEx(glb_hHook, nCode, wParam, lParam);
	}
	else if(nCode == HC_ACTION)
	{
		MessageBox(0,"sono nella procedura ","Finestra di dialogo",0);
	}
	return 0;
}
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
    switch (ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH:
		{
			glb_hModule = (HINSTANCE) hModule;
			glb_hHook = NULL;
			break;
		}
		case DLL_THREAD_ATTACH:
		case DLL_THREAD_DETACH:
		case DLL_PROCESS_DETACH:
		{
			UnistallHook();
			break;
		}
    }
    return TRUE;
}
//
*************************************************************************************
// * InstallHook()
//
*************************************************************************************
__declspec(dllexport) BOOL CALLBACK InstallHook (DWORD ThreadId)
{
	MessageBox(0,"sono nella InstallHook ","Finestra di dialogo",0);
	if(glb_hHook)
		return FALSE;
	glb_hHook = SetWindowsHookEx(WH_CBT, HookProc, glb_hModule,
ThreadId);
	if(glb_hHook)
		return TRUE;
	return FALSE;
}

Manca il codice che permette di trovare l'id del Thread. Scusatemi ma
è sbagliata pure la HookProc che sarebbe questa:
LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	MessageBox(0,"Sono nella Procedura","Finestra di Dialogo",0);
    if (nCode < 0)  // do not process message
        return CallNextHookEx(0, nCode, wParam, lParam);
    switch (nCode)
    {
        case HCBT_ACTIVATE:
			MessageBox(0,"","Finestra di Dialogo",0);
            break;
        case HCBT_CLICKSKIPPED:
			MessageBox(0,"","Finestra di Dialogo",0);
            break;
        case HCBT_CREATEWND:
			MessageBox(0,"","Finestra di Dialogo",0);
            break;
        case HCBT_DESTROYWND:
			MessageBox(0,"","Finestra di Dialogo",0);
            break;
        case HCBT_KEYSKIPPED:
			MessageBox(0,"","Finestra di Dialogo",0);
            break;
        case HCBT_MINMAX:
			MessageBox(0,"","Finestra di Dialogo",0);
            break;
        case HCBT_MOVESIZE:
			MessageBox(0,"","Finestra di Dialogo",0);
            break;
        case HCBT_QS:
			MessageBox(0,"","Finestra di Dialogo",0);
            break;
        case HCBT_SETFOCUS:
			MessageBox(0,"","Finestra di Dialogo",0);
            break;
        case HCBT_SYSCOMMAND:
			MessageBox(0,"","Finestra di Dialogo",0);
            break;
        default:
			MessageBox(0,"","Finestra di Dialogo",0);
            break;
    }
    return CallNextHookEx(0, nCode, wParam, lParam);
}

Questocodice non mi funziona. Supponendo che io voglia intercettare
come processo il NOTEPAD.EXE, se non ho capito male ogni volta che il
notepad viene massimazzato oiconizzato,ect,ect, dovrebbe spuntarmi una
MessageBox. Questonon succede. Non mi entra nemmeno nella DLL. Dove
Sbaglio? Potreste gentilmente aiutarmi.



                 if(lpInstallHook(...))
(il secondo if voleva probabilmente essere una chiamata alla funzione,
mentre per come hai scritto tu non fai che controllare una seconda volta
che il puntatore sia diverso da NULL)
non ho visto se ci sono altri errori, ho letto solo il main e ho notato
quei due; prova a correggerli, poi se ancora non funziona torna posta e
chiedi.
ciao
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

si ,ho sbagliato a scrivere io. Quella è una funzione. Ascolta potrei
utilizzare la SetWindowsHookEx per importare in qualche modo le
funzioni di una proxyDll o devo usare qualche altra tecnica. Se no,
quale tecnica potrei utilizzare.

Ulisse81 ha scritto:

non ho capito cosa tu intenda fare ne' cosa tu intenda con "proxyDll", ma
SetWindowsHookEx non importa funzioni: semplicemente registra una funzione
di callback affinché questa riceva determinate notifiche, ed in casi
particolari è necessario che la funzione di callback risieda in una DLL
che possa essere caricata da altri processi che fanno uso di user32.dll


> non ho capito cosa tu intenda fare ne' cosa tu intenda con "proxyDll"
io intendo una Dll fatta da me che possiede tutte le funzioni che
importa il Notepad nel mio caso.
Questa Dll  dovrebbe funzionare da filtro , quando il notepad chiama
per esempio la Writefile, vorrei io che richiamasse la WriteFile
dentro la mia Dll e non quella della Kernel32.dll. Ci penserà dopo la
mia WriteFile a richiamare la reale WriteFile.
Non sò se mi sono spiegato bene.
Mi domandavo come poter fare senza modificare l'eseguibile del
notepad.

Ulisse81 ha scritto:


ti stai interessando di API Hooking insomma (come si evince chiaramente
dagli altri messaggi che hai postato). non sei il primo su questo NG,
ricordo di aver risposto anche ad altri su questioni analoghe (ma facciamo
pure IDENTICHE).
se ricordo bene nelle mie risposte passate ho scritto (giustamente) che la
tecnica della Proxy DLL fa abbastanza schifo: nessuno ti garantisce di
avere la possibilità di installare la tua versione di kernel32.dll (sul
mio computer ad esempio agendo dal mio account non ce l'avresti, e penso
che non ce l'avresti neanche di default su qualsiasi installazione di
Windows Vista), senza contare che al primo aggiornamento di Windows Update
che patcha kernel32.dll la tua proxy DDL se ne va a donzelle.
se proprio non vuoi modificare il Notepad (chi può biasimarti in effetti,
visto che si trova nella stessa cartella di kernel32.dll :D) allora non ti
resta che far partire il tuo loader, registrare il tuo system-wide Windows
Hook, e dall'interno di esso scrivere i classici jump incondizionati
all'inizio delle API da hookare.
se ricordo bene in una risposta passata avevo anche messo in luce un
importante problema di performance/impiego delle risorse causato dall'API
hooking effettuato in questa maniera su "larga scala" (ovvero su tutti i o
molti dei processi presenti nel sistema): se ciascun processo scrive nelle
pagine di codice di uno stesso modulo allora ciascun processo causerà la
creazione di una sua copia della pagina modificata (cfr. protezione COW
delle pagine), venendo meno così la condivisione in memoria fisica di
quelle pagine. se tutti i processi hanno caricato user32.dll e tutti i
processi la modificano, ciascun processo avrà la sua copia in memoria
*fisica*.
la risposta a questo problema è che il modo corretto di patchare una
cosiddetta well-known DLL (diciamo orientativamente una DLL di sistema
caricata in quasi tutti i processi del sistema) non è farlo manualmente
modificandola in usermode, ma è quello di scrivere un driver che ne
rimpiazzi l'immagine in kernelmode una volta e per tutti i processi che la
usano.
vedi qui: 
http://www.codeproject.com/system/NoDeleteDelay.asp
le caratteristiche di questa tecnica:
a) devi farlo ad ogni avvio
b) di fatto *viene* fatto ad ogni avvio se il driver l'hai installato ad
esempio come SERVICE_AUTO_START (vedi API CreateService:
http://msdn2.microsoft.com/en-us/library/ms682450.aspx
)
c) devi avere i permessi per installare kernel drivers, e mi pare giusto:
non iniziare a chiedermi workarounds e non pensare di poter iniziare a
fare le tue lamerate sui computers di utenti un tantino più scafati di
quanto pensassi, perché a meno di bug/exploits (nel qual caso te la
sbrighi da solo) non c'è maniera :)


all'inizio delle API da hookare.
intendi dire che dovrebbe essere fattoin assembler....

 intendi dire che dovrebbe essere fattoin assembler....
è una delle possibili tecniche. controindicazioni: le stesse della
modifica della IAT a runtime (spreco di memoria fisica se lo fai in molti
processi), più anche possibili problemi dovuti al multithreading se non lo
fai in maniera accorta: mentre che tu inserisci i JMP un altro thread
potrebbe chiamare esattamente quella funzione e trovare codice assembly
non valido o disallineato, facendo così (nella maggior parte dei casi)
crashare l'intero processo; di conseguenza devi prendere precauzioni per
questa evenienza.


continuo nell'altro post "Process-wide API hooking"
guarda se per favore puoi darmi un consiglio.....