WINAPI HOOKs

Started by blackwinner, 04 de July , 2008, 12:42:16 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

blackwinner

O conceito parece difícil.. mas é simples.

O windows é um sistema operacional que trabalha através de mensagens.. quando uma janela é movida, um arquivo é deletado.. uma mensagem é enviada do mecanismo de controle de mensagens para a aplicação/objeto na qual a ação é realizada.. no entanto essa mensagem passa por várias sub-rotinas.. imagine que antes de atender seu telefone no hotel, uma recepsionista tem que passar o telefonema pra você.

Essas várias subrotinas que recebem a mensagem, são chamadas de hooks.
Uma recebe a mensagem antes da outra, que passa pra próxima hook procedure e assim subsequentemente.
A isso, dá-se o nome de hook chain(cadeia de hooks).

Para que uma aplicação compute uma tecla digitada, ela precisa primeiro saber se uma tecla foi digitada e qual tecla foi essa.
Para ela saber disso, uma hook precisa passar para ela a mensagem.
Então, entenda hooks como o ponto de ligação entre o message queue e uma aplicação/objeto/ação a ser tomada.

Continuing..
sergaralho.blogspot.com --> a informação como ela deve ser.. pura!

blackwinner

O windows separa as hooks existentes pelos tipos de mensagens que elas irão interceptar.
Um detalhe sobre as hooks, é que elas aumentam o processamento utilizado para manipular uma mensagem então usa-las pode e vai diminuir o desempenho do computador de quem usar.
Para quem pretende usa-las, elas devem ser usadas da forma mais simples para que ocupem a menor quantidade de recursos possíveis.

Como nós vamos conhecer um pouco de cada hook, vou explicar uma hook, seu funcionamento e passar para outra.. vamos começar com as mais simples.. embora as hooks relacionadas as mensagens do keyboard sejam largamente vistas como feitas para keyloggers, seu uso vai muito além disso podendo ser usada como gatilho/verificador em conjunto com sendkey e seus usos vão além do que eu posso dizer, vão até aonde sua imaginação mandar.

Quando queremos trabalhar com hooks, devemos saber como "instala-las".. isso se dá através da API  SetWindowsHookEx.

Vamos conhecer seu protótipo:

HHOOK SetWindowsHookEx(     
    int idHook,
    HOOKPROC lpfn,
    HINSTANCE hMod,
    DWORD dwThreadId
);
(msdn:http://msdn.microsoft.com/en-us/library/ms644990.aspx)

idHook é basicamente, o tipo de hook que você pretende usar.
Estes podem ser:
WH_CALLWNDPROC
WH_CALLWNDPROCRET
WH_CBT
WH_DEBUG
WH_FOREGROUNDIDLE
WH_GETMESSAGE
WH_JOURNALPLAYBACK
WH_JOURNALRECORD
WH_KEYBOARD
WH_KEYBOARD_LL
WH_MOUSE
WH_MOUSE_LL
WH_MSGFILTER
WH_SHELL
WH_SYSMSGFILTER


Não se assuste com o tamanho, vamos conhece-las uma a uma.

lpfn, o próprio nome diz tudo, é um ponteiro para uma função.. essa função é a função da nossa hook que recebera a mensagem, a tratará da forma adequada e enviara para a hook seguinte da chain

hMod, handle da dll que contém nossa hook procedure apontada por lpfn.. como na maioria dos casos nós vamos criar uma thread dentro do próprio processo do nosso programa, esse parâmetro será setado para NULL ou usaremos o GetModuleHandle(0) que retorna um handle pro nosso próprio módulo.

dwThreadId, é o id da thread a qual associaremos nossa hook.. como o que na maioria dos casos o que queremos é interceptar as mensagens de todas as threads existentes.. nós setaremos esse parametro para 0(zero) mas você pode conseguir o id de uma thread de várias formas, entre elas com uma toolsnapshot.

O valor de retorno é um HANDLE para uma hook procedure.(HHOOK)
Como hooks gastam muito desempenho(nos computadores de hoje em dia, nem tanto), nós usaremos esse handle para "desinstalar" a nossa hook quando quisermos.(o que deve ser feito o mais breve possível em hooks globais)
Independente do que queremos fazer com a hook procedure ou quanto tempo queremos mante-la.. nós sempre a desinstalaremos com UnhookWindowsHookEx(HHOOK)
O único parâmetro que essa API recebe, é um HHOOK.

Para desinstalar a hook, você pode antes verificar se uma hook foi instalada corretamente..
A API SetWindowsHook retorna um valor nulo se houver qualquer erro na instalação.(veremos isso na prática mais tarde)


Vale lembrar que a API SetWindowsHook também pode ser usada para dll injection em uma técnica beeem intrusiva.
sergaralho.blogspot.com --> a informação como ela deve ser.. pura!

blackwinner

O corpo de uma hook procedure é basicamente esse:
LRESULT CALLBACK HookProcedure(int,WPARAM,LPARAM);
Aonde LRESULT é um dos muitos nomes que o windows usa para parametros longos(no win64 é __int64 e nos anteriores é simplesmente um long)

CALLBACK é outro "apelido" para o tipo __stdcall(existem vários para esse tipo também assim como os outros)

WPARAM é um unsigned int ou unsigned __int64

e LPARAM é a mesma coisa que LRESULT.

Mas da onde vem os parâmetros passados para nossa hook procedure?
Normalmente eles vem de uma outra hook procedure anterior, e devem continuar sendo passado para a hook posterior a sua através da API CallNextHookEx(HHOOK, INT, WPARAM, LPARAM)
Aonde a maioria dos parâmetros são os que você recebeu na sua hook procedure com o adendo do handle da sua hook(HHOOK) no primeiro parâmetro.(ou último para os programadores de assembly, tanto faz)

Vamos então começar a fazer nosso primeiro programa usando hooking de teclas?

Nós já sabemos como é o corpo de uma hook procedure, qual API usar para chama-la e qual usar para desinstala-la.

Vamos utilizar isso junto então..

Primeiro declaramos os headers.
#include <windows.h>

Depois nós declaramos o protótipo da nossa hook procedure...

#include <windows.h>
LRESULT CALLBACK KeyboardProc(int,WPARAM,LPARAM);

E então, dentro da nossa main nós instalamos e desinstalamos nossa hook através das APIs que já vimos e logo após, declaramos o corpo da nossa Hook procedure.

int main()
{
 HHOOK hHk = SetWindowsHookEx(WH_KEYBOARD_LL,  KeyboardProc,0,0);
 UnhookWindowsHookEx(hHk);
}

LRESULT CALLBACK KeyboardProc(int iCode,WPARAM wParam,LPARAM lParam)
{
 
}

Mas ainda não está completo.
De fato, uma hook procedure atrelada as mensagens do teclado, só funcionará cada vez que houver uma mensagem relativa ao teclado a ser tratada.

Como foi dito antes, o windows é um sistema operacional que trabalha através de mensagens, então, nós temos que interceptar essas mensagens através de GetMessage.

Vamos olhar seu protótipo.

BOOL GetMessage(     
    LPMSG lpMsg,
    HWND hWnd,
    UINT wMsgFilterMin,
    UINT wMsgFilterMax
);
http://msdn.microsoft.com/en-us/library/ms644936(VS.85).aspx

Mais tarde eu vou explicar essa função já que o escopo desse tutorial não segue diretamente para como usar APIs relacionadas as mensagens do windows.. mas mais tarde eu vou mostra-los como usar essa API e outras para sniffar programas de uma maneira muito dificil de se detectar.
Enquanto isso, saibam que o primeiro parametro é uma referencia a um objeto da estrutura MSG que receberá detalhes das mensagens transmitidas pelo windows à aplicação.
Os outros 3 parâmetros podem ser NULL/0.

#include <windows.h>


LRESULT CALLBACK KeyboardProc(int,WPARAM,LPARAM);

int main()
{
 HHOOK hHk = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc,0,0);
 MSG msg;
 
 while(GetMessage(&msg, NULL, 0, 0) > 0)
 {
 
 }
 
 UnhookWindowsHookEx(hHk);
}

LRESULT CALLBACK KeyboardProc(int iCode,WPARAM wParam,LPARAM lParam)
{
 
}

A API GetMessage só retorna 0 ou -1 em casos de erro(-1) ou quando recebe uma WM_QUIT.

Pronto, o código já funciona.. mas se você reparar bem, enquanto o processo desse programa estiver ativo, você não vai conseguir digitar nenhuma tecla em lugar nenhum, isso é porque como eu disse, uma hook precisa chamar a outra e informa-la que uma tecla foi digitada e qual foi essa tecla.
Inclusive expliquei como fazer isso, então vamos dar uma rápida olhada no código completo que por enquanto não faz nada.

#include <windows.h>


LRESULT CALLBACK KeyboardProc(int,WPARAM,LPARAM);

int main()
{
 HHOOK hHk = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc,0,0);
 MSG msg;
 
 while(GetMessage(&msg, NULL, 0, 0) > 0)
 {
   
 }
 
 UnhookWindowsHookEx(hHk);
}

LRESULT CALLBACK KeyboardProc(int iCode,WPARAM wParam,LPARAM lParam)
{
 return CallNextHookEx(NULL, iCode, wParam, lParam);
}

Na próxima nós vamos aprender um pouco mais.. C Ya. =]
sergaralho.blogspot.com --> a informação como ela deve ser.. pura!

Alucard

olá muito bom o tutorial... eu já tinha escrevido uma vez sobre isso só que falei usando o vb6

http://www.darkers.com.br/forum/index.php?topic=9558.0
depois refiz o tutorial
http://docs.google.com/View?docID=dggsn ... on=_latest

Mas é realmente interessante esse assunto, dá para comandar legal as janelas, só ter um pouco de criatividade xD

valew

blackwinner

Opa, thks.. vo da uma lida nos seus :)
sergaralho.blogspot.com --> a informação como ela deve ser.. pura!