He realizado un Hook a la API GetClipboardData como me propuse
aquí. No ha sido fácil. He de agradecer a
cHackAll por su interés en el tema y su ayuda, así como el
tutorial que ha publicado.
Parte de la programación está en ensamblador, me hacía ilusión volver a usarlo, hacía mucho tiempo que lo tenía apartado. El resto de la programación la he escrito en Builder. He tenido problemas cuendo la API era llamada desde un mensaje WM_PASTE, se alteraba la pila, pero lo solucioné, al menos en las pruebas que he realizado.
La dll:
Código:
#include <windows.h>
//---------------------------------------------------------------------------
void HookGetClipboardData(UINT uFormat, HANDLE ClipboardHandle)
{
char MSG[256];
strcpy(MSG, "Esto es la prueba del Hook\n");
if(uFormat == CF_TEXT){
strcat(MSG, "En el clipboard tenemos: \n\n");
if(ClipboardHandle) strcat(MSG, (char*)ClipboardHandle);
}
MessageBox(0, MSG, "Hook API GetClipboardData", MB_OK);
}
__declspec(naked)
void HGetClipboardData()
{
asm{
jmp Sigue
Salto_API:
// Llamo a la Call de la API original:
db 0E9h, 00, 00, 00, 00 // JMP al Call_de_API_Original
uFormat: dd 0
Handle: dd 0
RetAPI: dd 0
PilaRet: dd 0
Temporal: dd 0
Sigue:
// Preparo el salto al Hook al finalizar la API
mov dword Ptr PilaRet, ebp // Guardo la posición de la pila para retorno
add dword Ptr PilaRet, 4
push [ebp]+8 // Guardo parámetro uFormat
pop dword Ptr uFormat
push [ebp]+4 // Guardo Dirección de retorno de la API original
pop dword Ptr RetAPI
mov [ebp]+4, offset HPostAPI // Coloco la nueva dirección de retorno en la
pila
jmp Salto_API // Salto a completar la API original
// Despues de ejecutar la API GetClipboardData se ejecutará el Hook
HPostAPI:
mov esp, dword Ptr PilaRet // restauro el valor de la pila
mov dword Ptr Handle, eax // Guardo el valor Handle de retorno
// Lamada a la función Hook
push eax // Paso Handle devuelto por API
push dword Ptr uFormat // Paso uFormat
call HookGetClipboardData // EL HOOK
pop dword Ptr Temporal // Retiro los parámetros pasados
pop dword Ptr Temporal
// Terminación
mov eax, dword Ptr Handle // Coloco el valor de retorno
pop dword Ptr Temporal // Retiro el antiguo retorno.
push dword Ptr RetAPI // Restauro la dirección retorno original
ret 4
}
}
void InstallHook()
{
DWORD OldProtect;
BYTE* APIAddress = (BYTE*)GetProcAddress(GetModuleHandle("User32.dll"),
"GetClipboardData");
DWORD* HookCall = (DWORD*)((BYTE*)HGetClipboardData + 0x06);
DWORD* APICall = (DWORD*)(APIAddress + 0x12); //APICall =
(DWORD*)(0x7E3B0D7A + 0x12);
// Autorizo escribir en HGetClipboardData
VirtualProtectEx((void*)-1, (BYTE*)HookCall, 4, PAGE_EXECUTE_READWRITE,
&OldProtect);
*HookCall = (DWORD)APICall + 4 + *APICall - (DWORD)HookCall-4;
VirtualProtectEx((void*)-1, (BYTE*)HookCall, 4, OldProtect, 0);
// Autorizo escribir en la API GetClipboardData
VirtualProtectEx((void*)-1, (BYTE*)APICall, 4, PAGE_EXECUTE_READWRITE,
&OldProtect);
*APICall = (DWORD)((BYTE*)HGetClipboardData - (BYTE*)APICall) - 4;
VirtualProtectEx((void*)-1, (BYTE*)APICall, 4, OldProtect, 0);
}
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
InstallHook();
break;
case DLL_PROCESS_DETACH:
break;
}
return 1;
}
El programa de prueba:
Código:
#include <windows.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma argsused
WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
HANDLE H = LoadLibrary("GetClipboardData.dll");
OpenClipboard(0);
char* Text = (char*)GetClipboardData(CF_TEXT);
CloseClipboard();
}
Para mi esto ha sido un juego muy satisfactorio y he aprendido mucho.
Saludos.
