Artigo Clube Delphi 69 - API Hooking
Parte II - Trocando informações entre processos com IPC
No artigo anterior, vimos os conceitos iniciais sobre API Hooking, como funciona, os métodos existentes, regras de hooking etc. Dentre essas regras, havia uma que proibia o uso de recursos da VCL dentro de um callback. Isso pode ser tornar um grande problema, limitando muito nossa criatividade ao se trabalhar com hooks. Exibir um simples formulário para o usuário torna-se uma tarefa impossível. Felizmente, somos programadores Delphi e como sempre há uma saída. E se chama IPC (Inter Process Communication).
O leitor deve estar pensando como o IPC pode nos ajudar a resolver o problema apresentado. De fato, continua sendo proibido usar VCL dentro da DLL. O "truque" consiste em mandar uma mensagem para outro processo, livre de regras e impedimentos e pedir para ele fazer o que queremos.
A forma mais simples de trocar mensagens entre processos no Windows é através da API SendMessage. Porém, existem casos em que API's interativas (veja quadro), como essa, não são permitidas dentro de um callback (veja o tópico Regras a serem obedecidas, no artigo anterior). Portanto, ao menos que você tenha absoluta certeza de que sua DLL não irá hookar nenhuma API ilegal, a melhor saída é usar IPC.
Nota: IPC leva vantagem sobre SendMessage também em outra situação: aplicações console. Nesse tipo de aplicação não se pode usar SendMessage, simplesmente porque ela não funciona.
API's interativas
API's interativas são aqueles que interagem diretamente com o usuário, através de mensagens na tela, gráficos etc. Já API's não interativas são exatamente o contrário: executam processamento nos bastidores do sistema operacional, sem se manifestar visualmente.
A comunicação entre processos com IPC consiste basicamente em mandar uma mensagem para um endereço específico, de dentro de um processo, e fazer outro acessar esse mesmo endereço para fazer a leitura. É claro, que para isso funcionar de fato muita coisa deve ser feita, da mesma forma que com as técnicas de API Hooking. Mas, novamente, não precisamos nos preocupar com isso, pois já o fizeram por nós.
BmsAPIHook, mais uma vez
A mesma biblioteca do colega Bruno Martins Stuani que usamos para injetar DLL em processos e hookar suas API's (veja edição anterior) nos fornece tudo o que é necessário para cria e usar IPC.
Há apenas três funções que fazem todo o "trabalho sujo":
function BmsCriaSecaoIpc(idSecao: PChar;
Callback: TBmsIpcCallback): Boolean;
function BmsDestroiSecaoIpc(idSecao: PChar): Boolean;
function BmsComunicaIpc(idSecao: PChar; Buffer: Pointer;
Tamanho: Integer; Resposta: Pointer;
TamResposta: Integer): Boolean;
Vejamos os parâmetros disponíveis, começando pela BmsCriaSecaoIPC:
· idSecao: Nome da seção servirá para fazer referência às mensagens. Deve ser único no sistema operacional;
· Callback: Ponteiro para uma estrutura do tipo TBmsIpcCallback.
A estrutura citada anteriormente é definida com o seguinte código:
TBmsIpcCallback = procedure(Buffer: Pointer;
TamBuffer: Integer; Resposta: Pointer;
TamResposta: Integer;); stdcall;
Para especificar esse último parâmetro, deve ser criada uma procedure exatamente igual à estrutura citada e passá-la para a função por referência. Veja um exemplo: