Api hook, proteção de arquivo
Nildo, essa eh pra vc, que manja tudo de api hook. Quero hookar a função deletefile da kernel32.dll, afim de mostrar o nome do arquivo que esta sendo deletado num showmessage, e queria que isso funcionasse independente do meu programa estar em foco ou não, ou seja, para o sistem inteiro.
o codigo abaixo está errado, alé de soente funcionar com a funçao deletefile chamada de dentro do programa, dá um access violation estranho, não sei porque. Vc poderia me dar uma luz? estou usando o madshi.
unit protegepasta;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, madcodehook, shellapi, StdCtrls, madremote;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
DeleteFileNextHookA : function (filename: pchar): longint;
DeleteFileNextHookW : function (filename: pchar): longint;
function DeleteFileProcA (filename: pchar): longint;
function DeleteFileProcW(filename: pchar): longint;
implementation
{$R *.dfm}
function DeleteFileProcW(filename: pchar): longint;
begin
showmessage(filename);
result := 0;
end;
function DeleteFileProcA(filename: pchar): longint;
begin
showmessage(filename);
result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
HookAPI(´kernel32.dll´, ´DeleteFileA´, @DeleteFileProcA, @DeleteFileNextHookA);
deletefile(´C:\Documents and Settings\rubio\Desktop\teste\teste.txt´);
end;Agradeço de antemão!
Vitor Rubio
Respostas
Nildo
20/06/2005
Primeiramente, você pode utilizar a minha biblioteca ( www.ProjetoBMS.net ) :D
Mas vamos ao que interessa, você esqueceu de colocar o STDCALL e também usou VCL dentro do CallBack (não pode!)
O código abaixo deve funcionar:
unit protegepasta;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, madcodehook, shellapi, StdCtrls, madremote;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
DeleteFileNextHookA : function (filename: pchar): longint; stdcall;
DeleteFileNextHookW : function (filename: pchar): longint; stdcall;
implementation
{$R *.dfm}
function DeleteFileProcW(filename: pchar): longint; stdcall;
begin
// Substituimos aqui VCL pela API MessageBox
MessageBox( 0, filename, ´Atenção´, 0 );
result := 0;
end;
function DeleteFileProcA(filename: pchar): longint; stdcall;
begin
// Substituimos aqui VCL pela API MessageBox
MessageBox( 0, filename, ´Atenção´, 0 );
result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
HookAPI(´kernel32.dll´, ´DeleteFileA´, @DeleteFileProcA, @DeleteFileNextHookA);
deletefile(´C:\Documents and Settings\rubio\Desktop\teste\teste.txt´);
end;Nildo
20/06/2005
unit protegepasta;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, BmsApiHook, shellapi, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
DeleteFileNextHookA : function (filename: pchar): longint; stdcall;
DeleteFileNextHookW : function (filename: pchar): longint; stdcall;
implementation
{$R *.dfm}
function DeleteFileProcW(filename: pchar): longint; stdcall;
begin
// Substituimos aqui VCL pela API MessageBox
MessageBox( 0, filename, ´Atenção´, 0 );
result := 0;
end;
function DeleteFileProcA(filename: pchar): longint; stdcall;
begin
// Substituimos aqui VCL pela API MessageBox
MessageBox( 0, filename, ´Atenção´, 0 );
result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
BmsHookAPI(´kernel32.dll´, ´DeleteFileA´, @DeleteFileProcA, @DeleteFileNextHookA);
deletefile(´C:\Documents and Settings\rubio\Desktop\teste\teste.txt´);
end;Vitor Rubio
20/06/2005
faltou stdcall..... burrice minha :$
agora uma duvida: porque funções da vcl não funcionam dentro do callback?
Já estou usando a sua biblioteca ^^
Só mais uma pergunta: fiz hooks para as funções deletefile, movefile e shfileopeation, porém elas só funcionam quando meu programa está em foco, como eu devo fazer para funcionar em todo o windows?
se for via dll, as funções de callback ficam na dll e os hooks no programa principal ou é de outro jeito?
Valew cara!
Nildo
20/06/2005
Porque os CallBacks são chamados de dentro da DLL que está a API que você chamou, e essa DLL não possui VCL (no caso a Kernel32.dll).
[quote:a46a87623d=´vitor^_^´]Já estou usando a sua biblioteca ^^[/quote:a46a87623d]
:D
[quote:a46a87623d=´vitor^_^´]Só mais uma pergunta: fiz hooks para as funções deletefile, movefile e shfileopeation, porém elas só funcionam quando meu programa está em foco, como eu devo fazer para funcionar em todo o windows?
se for via dll, as funções de callback ficam na dll e os hooks no programa principal ou é de outro jeito?
[/quote:a46a87623d]
Seu CallBack deve estar dentro da DLL, e a chamada para a BmsHookApi deve estar na sua DLL também (entre o Begin e o End). Então, no seu programa, você deve injetar essa DLL nos processos que você quer que o Hook tenha efeito. Na minha biblioteca eu implementei uma rotina que faz isso para você, basta você chamar a
BmsRemoteLoadLibrary( TODOS_PROCESSOS, ´c:\blabla\SuaDLL.dll´ );
Essa DLL vai ser carregada em todo o sistema operacional (todos os processos), inclusive os processos que abrirão futuramente, até que você chame a BmsRemoteUnloadLibrary.
Massuda
20/06/2005
Teve um post anterior do vitor^_^ sobre como impedir que uma pasta/arquivo seja excluída e porisso imagino que este tópico seja parte de um esquema para evitar a exclusão da pasta/arquivo (ou ao menos para logar que isso aconteceu...).
Já percebi que é impossível determinar se o hook está ou não instalado, mas seria possível criar um outro hook para tapear o hook que evita/loga a exclusão?
Nildo
20/06/2005
É possível saber;
É possível tapear; :wink:
Nildo
20/06/2005
Porém, tudo é feito na memória. Isso é: A DLL que está no HD não foi alterada, logo, se eu soubesse a posição da API na DLL que está no HD (na memória eu pego pelo GetProcAddress), então eu poderia facilmente desfazer qualquer hook de qualquer biblioteca independente do método utilizado. Funcionaria como um Deshookador global, ou um protetor contra Hooks.
Espero que isso tenha respondido sua pergunta, massuda.
Massuda
20/06/2005
Vitor Rubio
20/06/2005
Bom, nildo, desculpa te aborrecer com outra dúvida tão básica, mas, eu queria saber: que função faz o contrário da
BmsRemoteLoadLibrary( TODOS_PROCESSOS,
ou seja, descarrega a biblioteca?
porque qdo eu uso essa função no evento oncreate da form acontece um acces violation e abre aquela janela do debugger com os hexadecimais?
ah! Não se preocupem, não estou fazendo nenhum virus ou coisa parecida, estou apenas fazendo um anti-cunhado, ou anti-irmao-caçula, sabe? seguinte, o que eu quero fazer é: Sempre q o cara mala deleta uma pasta com certo nome, a pasta ao invés de ser deletada é movida pra dentro de outra pasta oculta e do sistema, e essa pasta, se ele tentar deletar, vai receber uma mensagem dizendo que esta pasta é uma pasta importantíssima do windows e não pode ser deletada, senão comprometerá o funcionamento do sistema...... hehe, é só uma bricadeira pra eu aprender um pouco mesmo.
Mas o mala não pode perceber que os arquivos não estão sendo deletados como ele gostaria que fosse, e nem pode visualizar a pasta secreta. Pesquisei por hooks porque, como o massuda disse, eu tinha postado essa dúvida antes e me mandaram pesquisar hooks :shock: até 2 dias atrás eu nem sabia conceitualmente o que era isso... mas toda vez que eu pergunto sobre isso pra alguém, esse alguém me pergunta: ´o que vc pretende com isso?´ ....... afinal, o que há de tão místico nos hooks? huahauaha
[/code]
Nildo
20/06/2005
BmsRemoteLoadLibrary( TODOS_PROCESSOS,
ou seja, descarrega a biblioteca?[/quote:ab2aaa2f70]
BmsRemoteUnloadLibrary( TODOS_PROCESSOS
Qual seu sistema operacional? Delphi? Service pack? Voce pode me mandar seu projeto pra eu dar uma verificada? O fonte do EXE e da DLL para bruno@projetobms.net
Té +
Nerdex
20/06/2005
procedure TForm1.Button1Click(Sender: TObject); begin BmsHookAPI(´kernel32.dll´, ´DeleteFileA´, @DeleteFileProcA, @DeleteFileNextHookA); deletefile(´C:\Documents and Settings\rubio\Desktop\teste\teste.txt´); end;
Olá ... Eu estou começando com o Hook agora ... e, eu reparei neste exemplo que a ´ação´ de deletar o arquivo, parte da própria aplicação, onde recebe a notificação pela APIHook ... tudo bem...
No meu caso ... desejo capturar uma notificação externa a aplicação (acredito que seja este o real objetivo do pacote). Enfim ... gostaria de um exemplo que eu recebesse a notificação automaticamente de um arquivo que alguém deletou pelo WinExplorer ... por exemplo.
Já fiz testes numa rede interna ... e não obtive resultados ...
Nildo
20/06/2005
Olá NerdeX, vou desenvolver então um outro aplicativo de demonstração onde notifique o executável sobre as exclusões e permite que o usuário possa bloquear ou não. Assim que terminar eu coloco aqui o Link para baixar.
Obrigado!
Nildo
20/06/2005
Ok NerdeX, finalizei o Demo. Porém descobri um bugzinho na biblioteca e amanhã de manhã eu vou disponibilizar a atualização da biblioteca e também o novo aplicativo de demonstração.
Um abraço!
Nildo
20/06/2005
http://www.projetobms.net/downloads.php?id=8
E por favor, atualize a biblioteca antes de utilizar:
http://www.projetobms.net/downloads.php?id=1
Um abraço, e espero que funcione hehehehe
Vitor Rubio
20/06/2005
Fiz ums modificações no meu código pra ficar mais simples, estou hookando a api shFileOperation, para impedira que uma pasta seja deletada pelo explore, e ao invés disso seja movida para outra pasta, assim o usuario que tentou deletar vai pensar que foi deletado mesmo.
Abaixo vai o código da minha dll
library protegeDll;
uses
SysUtils,
Classes,
shellapi,
windows,
bmsapihook;
var
FileOperationNextHookA: function(op: _SHFILEOPSTRUCTA): dword; stdcall;
FileOperationNextHookW: function(op: _SHFILEOPSTRUCTW): dword; stdcall;
function FileOperationHookProcA(op: _SHFILEOPSTRUCTA): dword;
begin
if extractfilename(op.pFrom) = ´zica´ then
begin
op.pTo := ´c:\temp\zica´;
if op.wFunc = fo_delete then
op.wFunc := FO_MOVE;
MessageBox(0, op.pFrom, ´Atenção´, 0);
end;
result := SHFileOperation(op);
end;
function FileOperationHookProcW(op: _SHFILEOPSTRUCTW): dword;
begin
if extractfilename(op.pFrom) = ´zica´ then
begin
op.pTo := ´c:\temp\zica´;
if op.wFunc = fo_delete then
op.wFunc := FO_MOVE;
MessageBox(0, pchar(op.pFrom), ´Atenção´, 0);
end;
result := SHFileOperationW(op);
end;
{$R *.res}
begin
bmsHookAPI(´shell32.dll´, ´SHFileOperationA´, @FileOperationHookProcA,
@FileOperationNextHookA);
bmsHookAPI(´shell32.dll´, ´SHFileOperationW´, @FileOperationHookProcW,
@FileOperationNextHookW);
end.
Agora, o código do programa, com o loadLibrary no oncreate
procedure TForm1.FormCreate(Sender: TObject); begin BmsRemoteLoadLibrary( TODOS_PROCESSOS, pathexe+´protegeDll.dll´); end;
Seguinte: se eu dou um run pra debugar o projeto, abre aquela tela que eu falei, se eu compilo depois executo, dá um erro de buffer overflow ou coisa parecida.
Será que é o mesmo problema do nerdex?
Vitor Rubio
20/06/2005
Valew pela força!!
Nildo
20/06/2005
Apenas alguns detalhes, remova a declaração da unit ´classes´, não é necessário. Quanto ao problema, por favor, atualize a versão do seu BmsApiHook pois arrumei um erro crítico. A nova versão é [b:0645d16f23]0.3.2[/b:0645d16f23].
Bom, na sua unit, as funções [b:0645d16f23]FileOperationHookProcA[/b:0645d16f23] e [b:0645d16f23]FileOperationHookProcW[/b:0645d16f23] TAMBÉM devem estar declaradas com o [b:0645d16f23]stdcall[/b:0645d16f23].
Mais uma coisa, quando mechendo com PWideChar (as APIs que terminam com W trabalham com PWideChar ao invez de PAnsiChar), voce deve fazer transformações para String usando [b:0645d16f23]WideCharToString[/b:0645d16f23], pois simplesmente usando Typecast não funciona!
Um abraço! Qualquer coisa pode perguntar
Vitor Rubio
20/06/2005
foi burrice minha mesmo :oops:
com relação aos widechars etc.. eu não sabia mesmo
seguinte, como eu só uso windows XP, só preciso usar as api´s terminadas em w, certo?
pois bem, aqui está minha variável de hook:
FileOperationNextHookW: function(op: _SHFILEOPSTRUCTW): longint; stdcall;
minha função de callback:
function FileOperationHookProcW(op: _SHFILEOPSTRUCTW): longint; stdcall; begin if (MessageBoxW(0, ´teste´, ´tem certeza q vc vai fazer isso?´, MB_ICONQUESTION or MB_YESNO) = idYes) then result := FileOperationNextHookW(op) else result := 0; end;
como eu faço entre o begin e end:
bmsHookAPI(´shell32.dll´, ´SHFileOperationW´, @FileOperationHookProcW, @FileOperationNextHookW);
o que acontece? minha mensagem mostra normalmente, mas após eu clicar em não ele dá a mensagem ´explorer encontrou um ero e deverá ser fechado´, ou seja, a famigerada tela de erro do xp que pergunta se vc quer enviar.
E eu não consigo dar um messagebox no op.pFrom, que seria o nome do arquivo.
tentei fazer a função retornar longint e dword, e não deu certo nenhum dos dois.
Valeu pela força!!!!
Nildo
20/06/2005
Nildo
20/06/2005
A declaração que você fez está errada. Você deve colocar exatamente a mesma declaração. Se você abrir a unit [b:4f592f1c36]ShellApi[/b:4f592f1c36], vai ver que a declaração da [b:4f592f1c36]SHFileOperationW[/b:4f592f1c36] é:
function SHFileOperationW(const lpFileOp: TSHFileOpStructW): Integer; stdcall;
Então, substituindo as declarações na sua DLL fica:
library protegeDll;
uses
shellapi,
Windows,
bmsapihook;
var
FileOperationNextHookW: function(const lpFileOp: TSHFileOpStructW): Integer; stdcall;
function FileOperationHookProcW(const lpFileOp: TSHFileOpStructW): Integer; stdcall;
begin
if (MessageBoxA(0, PChar( WideCharToString( lpFileOp.pFrom ) ), ´tem certeza q vc vai fazer isso?´, MB_ICONQUESTION or MB_YESNO) = idYes) then
result := FileOperationNextHookW(lpFileOp)
else
result := 0;
end;
{$R *.res}
begin
BmsHookAPI(´shell32.dll´, ´SHFileOperationW´, @FileOperationHookProcW, @FileOperationNextHookW);
end.Um forte abraço e espero que isso resolva!
Nildo
20/06/2005
Na verdade o winXP, internamente, só usa as APIs que terminam com W, e o win98 usam as que terminam com A. Mas você pode usar a que voce quiser. já que por padrão, as declarações sem A e W que estão no [b:7927806641]windows.pas[/b:7927806641], usam as que terminam com A.
Adriano Santos
20/06/2005
Alguém pode me dizer onde consigo mais informações sobre Hooks?
Algo básico, tudo que achei era meio avançado e não sei nada.
valeu
Nildo
20/06/2005
Estou terminando de editar alguns documentos sobre o assunto, em português. Vou notificar a galera neste tópico assim que terminar e atualizar as informações no meu site.
Um abraço!
Nerdex
20/06/2005
Estou tentando encontrar a curto prazo e de uma forma prática, o modo para que eu possa capturar a notificação da conclusão de um download via FTP, ou seja: ´o aparecimento de um arquivo X numa pasta Y´ ... Se possível, pode me informar o caminho das pedras e a API que melhor realiza esta captura...
Abraço
Nildo
20/06/2005
Fico feliz que tenha gostado! Foram mais de 2 anos estudando sobre o assunto para poder oferecer maior comodidade ao programador :wink:
Seguinte NerdeX... Não existem APIs para FTP, os clients utilizam a WinSock com o protocolo do FTP. Então você deve instalar um Hook nas APIs da Winsock: [b:1e3cfbaf73]send[/b:1e3cfbaf73], [b:1e3cfbaf73]recv[/b:1e3cfbaf73] (para win9x), [b:1e3cfbaf73]WSARecv[/b:1e3cfbaf73] (para winXP+). O comando que é enviado em forma de String para baixar um arquivo de um FTP é:
RETR arquivo.ext
No momento em que cair no CallBack da API Send, você deve salvar o SocketID (vem como parâmetro) em alguma variável, e também fazer um parse do texto enviado para salvar em outra variável apenas o ´arquivo.ext´.
A partir deste momento, o servidor vai começar a enviar para o Client, em algum um outro ID, o conteúdo do arquivo. Quando o arquivo for completamente enviado, o servidor vai enviar uma string (por aquela ID que você salvou) assim:
226-File successfully transferred #1310 226 0.000 seconds (measured here), [Taxa de transferencia] Kbytes per second 1310
Mas eu aconselho analizar somente o [b:1e3cfbaf73]226[/b:1e3cfbaf73] que está no começo do pacote, pois ele indica que o arquivo foi transferido com sucesso. [color=FF0000:1e3cfbaf73]Então neste momento você já sabe que o arquivo foi transferido[/color:1e3cfbaf73]!
Porém, cabe ao próprio Client de FTP juntar os pacotes pertencentes ao arquivo recebido, e jogá-lo em um arquivo no HD. Então como saber onde foi salvo? Você deve instalar um Hook nas APIs [b:1e3cfbaf73]CreateFileA[/b:1e3cfbaf73]/[b:1e3cfbaf73]CreateFileW[/b:1e3cfbaf73], e ver se o arquivo sendo criado é aquele que eu falei pra voce salvar em uma variável (enviado pelo pacote [b:1e3cfbaf73]RETR arquivo.ext[/b:1e3cfbaf73]).
Eu não sei se ele vai criar o arquivo no momento em que começou a baixar ou no momento que terminou (provavelmente quando começou a baixar), então cabe a você analisar a forma de pensar numa lógica. Capacidade você tem ;-)
Espero que isso tenha te ajudado. Um forte abraço! Qualquer coisa estamos aí.
Massuda
20/06/2005
Nerdex
20/06/2005
Nildo
20/06/2005
Misael
20/06/2005
Agora achei bastante [color=red:1e9e9a1b13]importante e interessante[/color:1e9e9a1b13] este tópico de API Hook, já fiz o download do seu projeto e irei estudar.....Parabéns pelo projeto :!: :!:
:arrow: Só gostaria de confirmar com vc se a API é essa mesmo? :?: , pois eu ainda não tenho um manual de referência... rsrs
Nildo
20/06/2005
Olá!!
Cara, nunca cheguei a mecher nesta API. Não posso te afirmar :cry:
Massuda
20/06/2005
Nildo
20/06/2005
Concordo com você, mas como você vai saber se o arquivo foi baixado pelo FTP? :wink:
Massuda
20/06/2005
Só não gosto de usar canhão para matar mosca. Além disso, hooks tendem a exigir um código mais bem feito que o usual, senão há risco de você causar bugs no (coloque o nome da sua aplicação favorita aqui) que ninguém será capaz de resolver, tudo por causa de um hook cheio de bugs.
Nildo
20/06/2005
Só não gosto de usar canhão para matar mosca. Além disso, hooks tendem a exigir um código mais bem feito que o usual, senão há risco de você causar bugs no (coloque o nome da sua aplicação favorita aqui) que ninguém será capaz de resolver, tudo por causa de um hook cheio de bugs.[/quote:f1f88708fb]
Sim, se for somente notificação de arquivos, o mais viável é utilizar as engines do windows
Vitor Rubio
20/06/2005
function SHFileOperationW(const lpFileOp: TSHFileOpStructW): Integer; stdcall;
library protegeDll; ... function FileOperationHookProcW(const lpFileOp: TSHFileOpStructW): Integer; stdcall; begin if (MessageBoxA(0, PChar( WideCharToString( lpFileOp.pFrom ) ), ´tem certeza q vc vai fazer isso?´, MB_ICONQUESTION or MB_YESNO) = idYes) then result := FileOperationNextHookW(lpFileOp) else result := 0; end; ... begin BmsHookAPI(´shell32.dll´, ´SHFileOperationW´, @FileOperationHookProcW, @FileOperationNextHookW); end.
Cara, obrigadaço!! funcionou perfeitamente e eu ainda fiquei pasmo com o monte de coisas que dá pra fazer com isso. Realmente a sua biblioteca é uma maravilha ^^
agora, sem querer abusar (rsrs)
o código que você mandou eu troquei por
function FileOperationHookProcW(const lpFileOp: TSHFileOpStructW): Integer; stdcall; begin if lpFileOp.wFunc = fo_delete then if (MessageBoxA(0, PChar( WideCharToString( lpFileOp.pFrom ) ), ´tem certeza q vc vai fazer isso?´, MB_ICONQUESTION or MB_YESNO) = idYes) then result := FileOperationNextHookW(lpFileOp) else result := 0; end;
fiz isso para somente dar a mensagem quando a operação for fo_delete, beleza, funcionou. Aí eu tentei fazer o seguinte: mudar a operação para fo_move para mover para uma outra pasta (era esse meu objetivo), só que pra fazer isso eu tenho que colocar no lpFileOp.pto o destino da pasta, que é ´c:\temp´... só que isso dá uma mensagem tipo: ´left side cannot be assigned to´ e não deixa fazer. Tentei criar outra estrutura lpFileOpB temporária, copiar todos os valores para ela usar ela para fazer a operação, mas..... deu zica, deu uns paus que fazem o winxp travar e tudo :oops: vou ver se dá pra fazer de outra forma, mas a princípio... eu devo ter feito salada com os widechars .... não sei muito bem trabalhar com isso. Se você tiver uma luz...
Ah, outra dúvida: se eu hookar a api findfileA ou W, para não fazer nada quando o nome do arquivo for ´x.txt´ ou pasta ´dir´ , isso impediria que o ícone do arquivo aparecesse no explorer?
Valeu Nildo, obrigadão!!!!
Michael
20/06/2005
Vendo o crescente interesse da comunidade Delphi sobre o tema API Hooking, e com a devida autorização do editor Guinther Pauli, vou dar uma notícia em primeira mão.
Estou escrevendo um artigo sobre o assunto para a revista ClubeDelphi, abordando: conceitos iniciais, o que é API Hooking, como funciona, quais os métodos disponíveis, as diferenças entre eles, as regras a serem obedecidas e, é claro, exemplos práticos de sua utilização, com a biblioteca do meu amigo Bruno Martins, [b:0be585264f]bmsAPIHooking[/b:0be585264f], tratando, inclusive, de InterProcess Comunication (IPC).
Aguardem as próximas edições da revista!
[]´s
Nildo
20/06/2005
Ok, alterei e consegui fazer funcionar aqui, estou adaptando ela pra colocar aqui pra você ver. Ficou bem legal :)
Você deve hookar a FindFileA/W e a FindNextFileA/W.
No CallBack, a primeira coisa a fazer é chamar a API original (FindFileA_Next, e afins), verificar se for o nome que você quer esconder. Se for, você chama NOVAMENTE a APi original. Se nao for, voce nao faz nada.
Isso vai fazer com que seu arquivo fique escondido.
Nildo
20/06/2005
function FileOperationHookProcW(const lpFileOp: TSHFileOpStructW): Integer; stdcall; const // Informe a pasta de destino com a Barra no final PastaDestino = ´c:\teste\´; var // Estruta "buffer" NovoFileOp: TSHFileOpStructW; sArquivo : string; begin if lpFileOp.wFunc = fo_delete then begin //Copiamos o conteudo da estrutura para nosso Buffer CopyMemory( @NovoFileOp, @lpFileOp, SizeOf( TSHFileOpStructW ) ); // Damos um nome ao arquivo de destino sArquivo := PastaDestino + ExtractFileName( WideCharToString( NovoFileOp.pFrom ) ); NovoFileOp.wFunc := FO_MOVE; // Copia o arquivo de destino para o "pTO" NovoFileOp.pTo := AllocMem( Length( sArquivo ) ); StringToWideChar( sArquivo, NovoFileOp.pTo, Length( sArquivo ) + 1 ); Result := FileOperationNextHookW( NovoFileOp ); end else result := FileOperationNextHookW(lpFileOp); end;
Espero que fucnione :wink:
Vitor Rubio
20/06/2005
Os meus erros foram:
1° Eu não concatenei o nome original do arquivo com o pasta onde ele deveria ser salvo.
2° Eu não conhecia a função copyMemory (q vergonha :oops: )
3° para colocar o conteudo (q já tava errado) no pto eu usei StringToWideChar, mas esqueci de somar um no length(arquivo)...
4° Eu prometo que vou estudar melhor as operações com ponteiros :), já estou procurando tópicos no forum pra isso!
Valew!!!!
Misael
20/06/2005
Blz... Michael
Vou ficar aguadando ansiosamente por essa materia nas próximas edições do Clube Delphi :lol: :lol:
Nildo
20/06/2005
Baixem em:
http://www.projetobms.net/
Vitor Rubio
20/06/2005
brincadeira viu?
Nildo
20/06/2005
brincadeira viu?[/quote:a01cf52dfc]
Hahahahahhah Seria legal! E também é possível :D Mas melhor deixar queto hehehehe
Vitor Rubio
20/06/2005
Mais tarde colocarei opções para proibir o acesso, travar com senha, não mostrar os arquivos protegidos etc. Estou demorando pra terminar pq estou fazendo por hobby, meio sem tempo, mas em pbreve eu pretendo também hookar as apis deletefile e findfile, findnext.. etc...
A string que ele restringe por enquanto é fixa, assim que eu arrumar um jeito de pegar uma string do registro sem usar o tregistry eu mudo isso.
Abaixo vai o fonte pra quem quiser.
function FileOperationHookProcW(const lpFileOp: TSHFileOpStructW): Integer; stdcall; const PastaDestino = ´c:\WindowsBoot\´; NomePastaDestino = ´WindowsBoot´; var NovoFileOp: TSHFileOpStructW; sArquivo: string; begin if (pos(NomePastaDestino, widechartostring(lpFileOp.pFrom)) <> 0) and (lpFileOp.wFunc <> FO_COPY) then result := 0 else begin if (pos(´protegida´, widechartostring(lpFileOp.pFrom)) <> 0) then begin if (lpFileOp.wFunc = FO_RENAME) then result := 0 else if (lpFileOp.wFunc = fo_delete) then begin CopyMemory(@NovoFileOp, @lpFileOp, SizeOf(TSHFileOpStructW)); sArquivo := PastaDestino + ExtractFileName(WideCharToString(NovoFileOp.pFrom)); NovoFileOp.wFunc := FO_MOVE; NovoFileOp.pTo := AllocMem(Length(sArquivo)); StringToWideChar(sArquivo, NovoFileOp.pTo, Length(sArquivo) + 1); Result := FileOperationNextHookW(NovoFileOp); end else result := FileOperationNextHookW(lpFileOp); end else result := FileOperationNextHookW(lpFileOp); end; end;
agora o programa:
procedure TfrmProtect.FormCreate(Sender: TObject); begin with tregistry.Create do begin RootKey := HKEY_LOCAL_MACHINE; if not openkey(´SOFTWARE\Microsoft\Windows\CurrentVersion\Run´, true) then begin MessageBox(0, ´Não foi possível instalar o protect...´+#13+10+ ´deu uma zica, sei lá´, ´Xiiii´, MB_ICONWARNING or MB_OK or MB_TASKMODAL); closekey; free; close; exit; end; if not ValueExists(´AntiMala´) then //verifica se existe o registro begin WriteString(´AntiMala´, application.ExeName+ ´ /oculto´); SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0); end; CloseKey; free; end; if not DirectoryExists(drive+´\WindowsBoot\´) then ForceDirectories(drive+´\WindowsBoot\´); SetaAtributos(drive+´\WindowsBoot´,filegetattr(drive+´\WindowsBoot´) or faHidden or faSysFile); end; procedure TfrmProtect.FormActivate(Sender: TObject); begin if paramstr(1) = ´/oculto´ then begin application.ShowMainForm := false; showwindow(findwindow(nil, pchar(frmProtect.Caption)), sw_hide); showwindow(findwindow(nil, pchar(application.Name)), Sw_hide); showwindow(findwindow(nil, pchar(filenamenoext(application.exeName))), Sw_hide); end; BmsRemoteLoadLibrary( TODOS_PROCESSOS, pathexe+´protegeDll.dll´); end;
procedure setaatributos (pra colocar tudo na pasta como sistems e oculto)
procedure SetaAtributos(arquivo: string; atributos: word); var i: integer; listaAtrib: tstringlist; begin listaAtrib := TStringlist.Create; listaDir(arquivo, listaAtrib, ´.´); for i := 0 to listaAtrib.Count - 1 do begin if DirectoryExists(listaatrib.Strings[i]) then begin filesetattr(listaatrib.Strings[i], atributos); SetaAtributos(listaatrib.Strings[i] + ´\*.*´, atributos); continue; end; if fileexists(listaatrib.Strings[i]) then filesetattr(listaatrib.Strings[i], atributos); end; end;
espero que esse código seja útil pra quem é tão iniciante quanto eu ^^
Vitor Rubio
20/06/2005
As vezes, usando o debug do delphi, na hora de dar um ´UnloadLibrary´, ocorre uma exception, daquelas feias, e trava o programa, ou ele pede pelo arquivo bms***.pas
Outra coisa, como saber se uma função já está hookada e quantas vezes ela está hookada, para dar o ´unloadLibrary´ corretamente.
Um programa pode descarregar uma dll que foi carregada por outro?
Nildo, num outro tópico, não me lembro bem o assunto, você citava que tinha desenvolvido sua biblioteca para apihooking depois de muito tempo de estudo. Gostaria de saber o que você estudou, por onde começou e se foi um caminho muito difícil/longo pra chegar onde vc chegou. Só uns conselhos mesmo beleza?
Valeu!!!
Nildo
20/06/2005
É que o tratamento de threads quando está debugando é meio estranho, não estudei a fundo esse tratamento para poder evitar quaisquer erros. Vou estudar mais sobre isso pra ver o porque acontece.
[quote:d647a5c5af=´vitor^_^´]Outra coisa, como saber se uma função já está hookada e quantas vezes ela está hookada, para dar o ´unloadLibrary´ corretamente.[/quote:d647a5c5af]
Ainda não fiz uma função para saber, mas eu vou fazer assim que tiver um tempo sobrando! Mas... quanto ao BmsRemoteUnloadLibrary, você pode chamar apenas uma vez, todas as funções hookadas vão ser deshookadas.
[quote:d647a5c5af=´vitor^_^´]Um programa pode descarregar uma dll que foi carregada por outro?[/quote:d647a5c5af]
Pode :D
[quote:d647a5c5af=´vitor^_^´]Nildo, num outro tópico, não me lembro bem o assunto, você citava que tinha desenvolvido sua biblioteca para apihooking depois de muito tempo de estudo. Gostaria de saber o que você estudou, por onde começou e se foi um caminho muito difícil/longo pra chegar onde vc chegou. Só uns conselhos mesmo beleza?[/quote:d647a5c5af]
Pra começar, estruturas PE. Depois passei a entender como o processador funciona, internamente, os comandos que ele interpreta. Me levou a aprender assembly. Dai eu passei a estudar como funcionava internamente o windows, os kerneis do 98 e XP, como funciona um kernel, como o código é executado pelo processador, como funcionam as DLLs, como funciona internamente o carregamento de um arquivo na memória, bastante coisa sobre memória e Windows. Como todas as versões do WIndows trata os dados na memória (muita diferença entre o 98 e o XP). Dai comecei a pensar em como isso poderia ser feito. Dai fui fazendo, fazendo, fazendo, conforme foi aparecendo os problemas fui atras das soluções (algumas fizeram eu perder semanas..), tive até que estudar drivers pro windows pensar que partes do meu código está sendo executado do sistema operacional (pra obter acesso a determinadas áreas), e assim foi indo :D
Vitor Rubio
20/06/2005
No programinha que eu fiz, que eu mandei o código, se vc der o loadlibrary 5 vezes e der o unload uma vez só, a função ainda vai estar funcionando, tem que fazer unload 5 vezes pra função voltar ao normal.
Pelo menos aki aconteceu isso, com windows XP SP1.
Ooooloko! :shock:
Nildo
20/06/2005
Mas deve ser assim. Quando deshookar, ele só pode deshookar o que foi hookado por ele. É um padrão
Vitor Rubio
20/06/2005
como se nota, o meu programa serve para impedir que um arquivo seja deletado. Mas do jeito que está hoje, ele só impede a deleção do arquivo se ele estiver dentro de um path com um nome específico.
eu gostaria de saber: se eu colocar uma variavel global na unit da minha dll e passar um valor pra ela, ela sempre vai manter o último valor atribuido a ela e vai sempre estar atualizada caso o sistema dispare alguma das funções hookadas, ou quando o sistema chamar uma função a dll vai ser reiniciada/recarregada e minha variavel volta pro valor inicial?
outra coisa: queria colocar nessa variavel uma string gigante contendo a lista de todos os arquivos/ diretorios que o programa vai proteger. como gravar e ler no registro do windows sem usar o tregistry, mas usando a api direto?
eu ainda não posso usar a vcl na minha dll de hook?
Valeu pela força!
Nildo
20/06/2005
Você pode usar variáveis globais. Porém, note que, quando você injeta a DLL em todo o sistema operacional, é a mesma coisa que carregar uma cópia da sua DLL em cada aplicativo que está sendo executado. Então a variável global dentro da DLL, é a mesma coisa que uma variavel global dentro de cada EXE, isso é, se você alterar o valor dela pela DLL injetada no Explorer.exe, a variavel global da DLL no Calc.exe por exemplo não vai sofrer o efeito da que foi alterada pelo Explorer.exe. Tem como fazer para ter efeito em todo o sistema operacional também, basta criar mapeamento de arquivos com uma flag especial não documentada.
[quote:c51b587123=´vitor^_^´]outra coisa: queria colocar nessa variavel uma string gigante contendo a lista de todos os arquivos/ diretorios que o programa vai proteger.[/quote:c51b587123]
Olha cara.. Quando se está fazendo um Hook, você está ´atrapalhando´ o fluxo do sistema operacional. O Windows não foi feito achando que alguém ia lá e iria hookas as APIs dele. Então, o quanto menos de esforço você fizer em sua DLL melhor, para não atrapalhar o fluxo de sincronização dos dados do SO. Então eu aconselho, nesse caso, fazer um IPC, que comunica com seu executável, para seu novo processo verificar o nome do arquivo entre uma lista gigante (dentro do EXE) e voltar uma resposta verdadeira ou falsa para sua DLL.
[quote:c51b587123=´vitor^_^´]como gravar e ler no registro do windows sem usar o tregistry, mas usando a api direto?[/quote:c51b587123]
TRegistry não é VCL. Portanto você pode usá-la a vontade dentro da sua DLL de hook. Mas evite usar dentro de CallBacks para não atrapalhar o fluxo, como dito anteriormente.
[quote:c51b587123=´vitor^_^´]eu ainda não posso usar a vcl na minha dll de hook?[/quote:c51b587123]
Não :P
Vitor Rubio
20/06/2005
Nildo
20/06/2005
IPC é InterProcess Communication. É um esquema de Pergunta-Resposta baseada em Buffer. Por exemplo:
DLL > Exe, o nome ´teste´ esta na lista? Salva o resultado na var bLISTA.
EXE > bLista = Verdadeiro
DLL > Valeu! Voce me disse que está. Agora vou continuar a execução aqui!
Mrmick
20/06/2005
E será que o nildo ou alguém mais falar mais sobre IPC ou indicar algum tutorial/artigo/apostila algo assim. Para poder entendê-lo melhor?
abraços
Nildo
20/06/2005
Edições 68, 69 e 70 da revista ClubeDelphi. Artigos escritos pelo Michael Benford
Sourcecode
20/06/2005
Nildo
20/06/2005
Você pode fazer Hooking das APIs do .NET normalmente com a BmsApiHook