Newsgroup: it.comp.programmare.win32
Titolo: Iniettarsi in un processo con una dll!

Salve a tutti,
ho un problema nel tentativo di iniettarmi in un processo con una dll!
la DLL contiene una funzione che viene esportata: SetHook che utilizzo per
settare un hook su un processo.
la DLL e' linkata implicitamente all'eseguibile (Starter)
la DLL contiene naturalmente anche le MsgProcedure per filtrare i messaggi
con gli hook.... in queste procedure devo utilizzare varie var (che io ho
dichiarato globali nella dll) come mutex, handle, bitmap e perche' no anche
un FILE di log per debuggare....
il funzionamento e' questo:
Starter crea il processo dell'applicazione in cui voglio iniettarmi (WordPad
per esempio)
Starter richiama "SetHook" della dll con cui cerco di installare un hook nel
processo di WordPad
CODICE STARTER :
{
FILE * logStarter;
/*apertura file di log*/
[....]
  PROCESS_INFORMATION pi;
 ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
 CreateProcess(NULL,
      "C:\\Program Files\\Windows NT\\Accessories\\wordpad\0",
        NULL,
      NULL,
      TRUE,
      0,
      NULL,
      NULL,
      &si,
      &pi))
    SetHook(pi.dwThreadId,logStarter)
}
nella dll la funzione setHook fa semplicemente questo:
BOOL WINAPI SetHook(DWORD dwThreadId,FILE * logfile) {
    g_hhook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hinstDll,
dwThreadId);
 if(!g_hhook)
 {
  fprintf(logfile,"Errore settaggio hook %d\n",GetLastError());
  return false;
 }
 g_hhook_sys = SetWindowsHookEx(WH_SYSMSGFILTER, GetMsgProcSys, g_hinstDll,
dwThreadId);
 if(!g_hhook_sys)
 {
 fprintf(logfile,"Errore settaggio hook sys%d\n",GetLastError());
  return false;
 }
 return true;
}
e gia' cosi ho dei problemi perche' le SetWindowsHookEx non funzionano
(errore nel parametro, vedi altro thread nel NG)
La domanda che piu' mi preme ora pero' e' "dove creo e inizializzo le var
globali che mi servono poi nelle MsgProcedure"? se le metto nel DllMain
questa inizializzazione viene eseguita quando parte Starter giusto?
e' corretto fare cosi'?
la dll viene iniettata nel processo del WordPad solo successivamente... le
variabili che creo nel DllMain sono ancora valide quando poi cerco di usarle
nella MsgProceudre?
io ho notato per esempio che l'utilizzo dei fprintf per loggare dei messaggi
fa crashare l'applicazione....
va beh, non sono stato molto chiaro ma spero che qualcuno sappia spiegarmi
qualcosa di piu' nell'utilizzo di questa tecnica.
Bye
Johnny

ho fatto un tentativo cosi:
nella setwindowshookex metto dwThreadId=0 cosi dovrebbe installare l'hook su
tutti i thread del desktop!
nel DllMain (che dovrebbe essere richiamato ogni volta che la dll viene
caricata dentro un processo, giusto?) controllo di trovarmi dentro il
processo di WordPad e a quel punto effettuo tutte le mie
inizializzazioni....
semplicemente eseguo la chiamata GetCommandLine e confronto il path con
quello di WordPad....
il problema e' che sembra che la dll venga inizializzata solo due volte: i
processi che trovo sono "MSDEV" e "starter" (la mia applicazione con cui
lancio WordPad e setto l'hook)
perche' DllMain non viene richiamato anche per ogni processo su cui viene
installato l'hook? (ammesso che l'hook si installi veramente... ma dal
valore di ritorno di SetWindowsHookEx sembra funzionare correttamente)
Bye
Johnny

 fa crashare l'applicazione....
Ripeto, sono valide se l'istanza e' la stessa.
Io di solito creo nella prima istanza - quella che installa a tutti
gli effetti l'hook - una mailslot, e faccio convogliare sulla mailslot
tutti i messaggi delle altre istanze.
Ciao,
Zello

...
ok, lasciamo perdere per un attimo i msg di log....
mi spieghi allora perche' se cerco di settare un hook globale (4o
parametro=0) non lo installa in tutti i processi attivi?
io vedo che viene installato solo su MSDEV e sull'altra mia applicazione che
serve da starter!
Bye
Johnny

 tutti i messaggi delle altre istanze.
La Dll e' linkata implicitamente all'avvio di Starter.... questa penso sia
una prima istanza
successivamente richiamo la funzione SetHook (esportata dalla dll) per
installare l'hook.... a questo punto la dll dovrebbe essere mappata in ogni
processo in cui viene installato (un istanza per ogni processo????)
comincio ad avere un po' di confusione in testa
comunque sei sicuro che non si possano installare hook in threads di
processi diversi da quelli in cui si effettua la SetWindowsHookEx?
guardando sul Richter (Advanced Windows) fa proprio un esempio che sembra
identico al mio:
si inietta nel processo di explorer con una piccola dll che contiene come
nel mio caso anche la funzione che gestisce l'installazione dell'hook.
Il suo programma linka implicitamente la dll (come me), trova l'ID del
thread principale di Explorer e lo passa ad una funzione "sethook".
La sethook effettua la chiamata:
SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hinstDll,dwThreadId);
tutto e' uguale a quello che ho fatto io. L'unica differenza sta nel fatto
che lui il processo di Explorer ce lo ha gia' attivo quando lancia la sua
applicazione, io invece creo WordPad dalla mia applicazione.
Bye
Johnny

 processi diversi da quelli in cui si effettua la SetWindowsHookEx?
Mea culpa. E' possibile, specificando sia dwThreadId sia hModule... Avevate
ragione tu e Richter...
In particolare, ho provato:
1) per prima cosa a creare WordPad usando CreateProcess;
2) a chiamare SetHook(TRUE) nella mia dll;
3) SetHook, a parte alcune cose utili in debug, ricava - via
FindWindow("WordPadClass",NULL), l'handle della finestra di WordPad [la
classe l'ho trovata con Spy++];
4) Usando GetWindowThreadProcessId trovo il ThreadId che ha creato la
finestra di WordPad;
5) Chiamo SetWindowsHookEx(WH_GETMESSAGE,
          (HOOKPROC)GetMsgProc,
          g_hInstance,
          dwThreadID);
(g_hInstance è ovviamente l'istanza della Dll, come ottenuta da WinMain)
E tutto pare funzionare correttamente: io ho due istanze di Dll, una nel mio
processo originale, e la seconda nell'address space di WordPad. Uso una
mailslot - ma potrei usare le named pipes o anche un MMF - per far
comunicare i due processi, e solo quello originario (che è un processo
console, per inciso) stampa a video i messaggi di Debug.
Ciao,
Zello

Bon, in breve, questo spezzone di codice a me funziona perfettamente:
void SetHook()
{
     STARTUPINFO si;
     PROCESS_INFORMATION pi;
     si.cb=sizeof(si);
     GetStartupInfo(&si);
     CreateProcess("F:\\Programmi\\Windows NT\\Accessori\\wordpad.exe",
                    NULL,
                    NULL,
                    NULL,
                    FALSE,
                    0,
                    NULL,
                    NULL,
                    &si,
                    &pi);
      WaitForInputIdle(pi.hProcess,INFINITE);  //attende che il processo
inizi
      hHook=SetWindowsHookEx(WH_GETMESSAGE,
                            (HOOKPROC)GetMsgProc,
                            g_hInstance,
                            pi.dwThreadId
                            );
}
Ciao,
Zello

> (g_hInstance è ovviamente l'istanza della Dll, come ottenuta da WinMain)
intendevi dire DllMain?
o proprio WinMain del processo "starter"
x debuggare credo seguirò il consiglio (letto in un altro thread) di far
apparire delle MessageBox.....
qualche controindicazione?
appena riesco provo a rifare il codice da capo....
poi ti faccio a sapere!
Bye
Johnny

 poi ti faccio a sapere!
Occhei, ciao,
Zello

 Occhei, ciao,
Funzia!
finalmente!
evidentemente c'erano troppi casini con i file di log che cercavo di aprire
o scrivere....
e finalmente sono anche riuscito ad individuare il momento in cui viene
eseguita DllMain nel processo di WordPad....
ho usato i MessageBox per debuggare... funzionano correttamente!
ora però, verificato che tutto funzia devo trovare il modo di ripristinare
il log su file.... ho intenzione infatti di spostare tutto il processo su
una WindowStation nascosta (e Desktop nascosto) quindi lì i MessageBox non
funzionano....
comunque grazie finora per l'attenzione dedicatami!
Bye
Johnny

lo so, un file di log non e' il modo migliore x debuggare ma almeno vorrei
capire cosa non funziona....
dunque, ho dichiarato un var globale nello "starter" di tipo FILE * con la
quale verifico il funzionamento nella fase di lancio del programma. Il tutto
funziona ma se provo passare quel puntatore di FILE alla procedura SetHook
il programma crasha, perche'?
Nella Dll poi ho bisogno di un file di log distinto. Visto che mi interessa
debuggare solo quando mi trovo iniettato nel processo di WordPad ho fatto
cosi:
ho dichiarato nella Dll una var globale FILE * logDll ;
nel DllMain (PROCESS_ATTACH) apro il file solo se mi trovo nel WordPad;
nella MsgProc (eseguita dall'hook iniettato in WordPad) scrivo i miei msg di
debug;
nel DllMain (PROCESS_DETACH) chiudo il file solo se mi trovo in WordPad;
in questo modo ci saranno delle var FILE * inutilizzate (per esempio x la
Dll che viene caricata nel processo dello Starter) ma che importa? tanto non
le uso.
Il problema e' che il file logDll.txt resta vuoto, come se non venisse
chiuso o nessuno vi scrivesse.
Che cosa sbaglio?
ecco un sunto del codice:
******
*DLL*
******
#include <stdio.h>
[...]
#pragma data_seg("Shared")
HHOOK g_hhook = NULL;
#pragma data_seg()
// Instruct the linker to make the Shared section
// readable, writable, and shared.
#pragma comment(linker, "/section:Shared,rws")
#define DEBUGDLL
#ifdef DEBUGDLL
#define MSG(X,Y) fprintf(m_logDll,X,Y)
#else
#define MSG(X,Y)
#endif
DWORD wordPadId=0;    //Id Thread WordPad
HWND m_hwndWordPad=NULL;
FILE * m_logDll = NULL;
BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, PVOID fImpLoad) {
 DWORD currentId; //Id Thread Corrente
   switch (fdwReason) {
      case DLL_PROCESS_ATTACH:
         // DLL is attaching to the address space of the current process.
         g_hinstDll = hinstDll;
       currentId=GetCurrentThreadId();
       HWND hwndWordPad; //Handle Finestra di WordPad
       hwndWordPad=FindWindow("WordPadClass",NULL);
       if (hwndWordPad)
       {
        //memorizzo handle globale
        m_hwndWordPad=hwndWordPad;
        //trovo il threadId di wordpad
       wordPadId=GetWindowThreadProcessId(hwndWordPad,NULL);
       if (wordPadId==currentId)
       {
        //INIZIALIZZAZIONE
        //apertura file di log
        m_logDll=fopen("C:\\logDll.txt","w+");
        if (!m_logDll)
             return false;
        else
             MSG("DllMain:File di log aperto!\n","");
        [...]
        }
        }
        break;
[...]
          case DLL_PROCESS_DETACH:
            currentId=GetCurrentThreadId();
            if (currentId==wordPadId)
            {
                 MSG("DllMain:Detach Processo WordPad\n","");
                 TerminaProcessi();    //qui faccio anche fclose(m_logDll)
            }
         // The calling process is detaching the DLL from its address space.
         break;
}
}
BOOL WINAPI SetHook(DWORD dwThreadId,FILE *log) {
   BOOL fOk = FALSE;
   if (dwThreadId != 0)
   {
      // Make sure that the hook is not already installed.
      if(g_hhook == NULL)
   {
  // Install the hook on the specified thread
  g_hhook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hinstDll,
    dwThreadId);
  fOk = (g_hhook != NULL);
#ifdef DEBUGDLL
  if (fOk)
   fprintf(log,"SetHook:Hook Installato correttamente!\n");        //credo
che questi fprintf facciano crashare il processo!
  else
   fprintf(log,"SetHook:Errore %d\n",GetLastError());
#endif
   }
   }
   else
   {
   //Disinstallo l'hook
      // Make sure that a hook has been installed.
      if (g_hhook != NULL)
   {
  fOk = UnhookWindowsHookEx(g_hhook);
#ifdef DEBUGDLL
  if (fOk)
   fprintf(log,"UnHook Ok\n");
  else
   fprintf(log,"UnHook Error %d\n",GetLastError());
#endif
      g_hhook = NULL;
   }
 }
   return(fOk);
}
***********************
**********
*STARTER*
**********
FILE *m_logStarter;
WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR
lpCmdLine,int nShowCmd)
{
         m_logStarter=fopen("C:\\logStarter.txt","w+");
         if (!m_logStarter)
         {
              MessageBox(NULL,"Errore apertura file
log\0","WinMain\0",MB_OK|MB_APPLMODAL);
              return -1;
         }
[...]
    if (!SetHook(pi.dwThreadId,m_logStarter))        //m_logStarter passato
qui come parametro da problemi!!!!!!
          MSG("WinMain:Errore SetHook!\n","");
  else
  {
          WaitForSingleObject(pi.hProcess,INFINITE);
          MSG("WinMain:WordPad Terminato!\n","");
          SetHook(0,m_logStarter);
          MSG("WinMain:SetHook(0) effettuato!\n","");
  }
      if (m_logStarter)
          fclose(m_logStarter);
   return true;
}
Bye
Johnny

Ok,
mi rispondo da solo, almeno in parte!
Il file logDll.txt rimaneva vuoto perche' il processo di WordPad ero
costretto a chiuderlo forzatamente con il TaskManager (gira in una
WindowStation nascosta e x ora non ho modo migliore x terminare il processo)
quindi probabilmente non veniva richiamato ill SetHook(0) e il relativo
DllMain PROCESS_DETACH.....
rimane comunque il problema del parametro FILE * passato a SetHook....
questo fa crashare l'applicazione....
why?
Bye
Johnny