网上好不容易找了个大概能看得懂的代码,可是好像原先就是错的,谁能帮忙改一下啊?谢谢
装上钩子以后是正常的,但是卸载完之后就出错了,系统就不正常了--------------------------------------------------------------------------------------------------
apihook.pas
--------------------
unit APIHook ;interface uses
SysUtils, Windows, WinSock, Dialogs;type
{ 要HOOK的API函数定义 }
TCreatePW = function (lpApplicationName: PWideChar; lpCommandLine: PWideChar;
lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
lpCurrentDirectory: PWideChar; const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation): BOOL; stdcall;
procedure HookAPI;
procedure UnHookAPI;var
ProcessHandle: HWND;
BaseAddress: array [0..2] of Pointer;
OldProc: array [0..2] of array [0..7] of Byte;
NewPorc: array [0..2] of array [0..7] of Byte;implementation{ 自定义的函数,用于覆盖系统的CreateProcessW函数 }
function MyCreatePW(lpApplicationName: PWideChar; lpCommandLine: PWideChar;
lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
lpCurrentDirectory: PWideChar; const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation): BOOL; stdcall;
var
nSize: Cardinal;
begin
{ 显示打开程序的命令行和文件名}
MessageBoxW(0, lpCommandLine ,lpApplicationName , 0);
WriteProcessMemory(ProcessHandle, BaseAddress[0], @OldProc[0], 8, nSize);//這一句是修改成原來函數的地址,讓程序能正常打開
Result := CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes,
lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
WriteProcessMemory(ProcessHandle, BaseAddress[0], @NewPorc[0], 8, nSize);//在程序正常打開後再修改成自定義函數的地址,使所有程序在下次打開時都要先調用自定義函數
end;procedure HookAPI;
var
DLLModule: THandle;
nSize: Cardinal;
Dat: DWORD;
Tmp : array [0..3] of Byte;
begin
ProcessHandle := DWORD(-1);
DLLModule := LoadLibrary('kernel32.dll');
{ 系统函数入口点地址 }
BaseAddress[0] := GetProcAddress(DLLModule, 'CreateProcessW');
Dat := DWORD(@MyCreatePW);
Move(Dat, Tmp, 4);
NewPorc[0][0] := $B8; { 汇编跳转指令 }
NewPorc[0][1] := Tmp[0]; { 跳转到自身的函数 }
NewPorc[0][2] := Tmp[1];
NewPorc[0][3] := Tmp[2];
NewPorc[0][4] := Tmp[3];
NewPorc[0][5] := $FF;
NewPorc[0][6] := $E0;
NewPorc[0][7] := 0;
{ 读取系统函数内存地址 }
ReadProcessMemory(ProcessHandle, BaseAddress[0], @OldProc[0], 8, nSize);
{ 用自己的函数地址覆盖系统的函数地址 }
WriteProcessMemory(ProcessHandle, BaseAddress[0], @NewPorc[0], 8, nSize);
CloseHandle(ProcessHandle);
end;procedure UnHookAPI;
var
nSize: Cardinal;
begin
{ 恢复所修改的地址 }
WriteProcessMemory(ProcessHandle, BaseAddress[0], @OldProc[0], 8, nSize); //主要是這句出了問題,為何無法恢復原來函數的地址??
end;end.
hook.dpr
//////////library hook;uses
SysUtils,
windows,
Messages,
APIHook in 'apihook.pas';type
PData = ^TData;
TData = record
Hook: THandle;
Hooked: Boolean;
end;var
DLLData: PData;{------------------------------------}
{过程名:HookProc
{过程功能:HOOK过程
{过程参数:nCode, wParam, lParam消息的相
{ 关参数
{------------------------------------}
procedure HookProc(nCode, wParam, lParam: LongWORD);stdcall;
begin
if not DLLData^.Hooked then
begin
HookAPI;
DLLData^.Hooked := True;
end;
//调用下一个Hook
CallNextHookEx(DLLData^.Hook, nCode, wParam, lParam);
end;
{------------------------------------}
{函数名:InstallHook
{函数功能:在指定窗口上安装HOOK
{函数参数:sWindow:要安装HOOK的窗口
{返回值:成功返回TRUE,失败返回FALSE
{------------------------------------}
function InstallHook(SWindow: LongWORD):Boolean;stdcall;
var
ThreadID: LongWORD;
begin
Result := False;
DLLData^.Hook := 0;
ThreadID := GetWindowThreadProcessId(sWindow, nil);
//给指定窗口挂上钩子
DLLData^.Hook := SetWindowsHookEx(WH_GETMESSAGE, @HookProc, Hinstance, 0);//ThreadID
if DLLData^.Hook > 0 then
Result := True //是否成功HOOK
else
exit;
end;{------------------------------------}
{过程名:UnHook
{过程功能:卸载HOOK
{过程参数:无
{------------------------------------}
procedure UnHook;stdcall;
begin
UnHookAPI;
//卸载Hook
UnhookWindowsHookEx(DLLData^.Hook);
end;{------------------------------------}
{过程名:DLL入口函数
{过程功能:进行DLL初始化,释放等
{过程参数:DLL状态
{------------------------------------}
procedure MyDLLHandler(Reason: Integer);
var
FHandle: LongWORD;
begin
case Reason of
DLL_PROCESS_ATTACH:
begin //建立文件映射,以实现DLL中的全局变量
FHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, $ffff, 'MYDLLDATA');
if FHandle = 0 then
if GetLastError = ERROR_ALREADY_EXISTS then
begin
FHandle := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'MYDLLDATA');
if FHandle = 0 then Exit;
end else Exit;
DLLData := MapViewOfFile(FHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if DLLData = nil then
CloseHandle(FHandle);
end;
DLL_PROCESS_DETACH:
begin
if Assigned(DLLData) then
begin
UnmapViewOfFile(DLLData);
DLLData := nil;
end;
end;
end;
end;{$R *.res}
exports
InstallHook, UnHook, HookProc;begin
DLLProc := @MyDLLHandler;
MyDLLhandler(DLL_PROCESS_ATTACH);
DLLData^.Hooked := False;
end.
装上钩子以后是正常的,但是卸载完之后就出错了,系统就不正常了--------------------------------------------------------------------------------------------------
apihook.pas
--------------------
unit APIHook ;interface uses
SysUtils, Windows, WinSock, Dialogs;type
{ 要HOOK的API函数定义 }
TCreatePW = function (lpApplicationName: PWideChar; lpCommandLine: PWideChar;
lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
lpCurrentDirectory: PWideChar; const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation): BOOL; stdcall;
procedure HookAPI;
procedure UnHookAPI;var
ProcessHandle: HWND;
BaseAddress: array [0..2] of Pointer;
OldProc: array [0..2] of array [0..7] of Byte;
NewPorc: array [0..2] of array [0..7] of Byte;implementation{ 自定义的函数,用于覆盖系统的CreateProcessW函数 }
function MyCreatePW(lpApplicationName: PWideChar; lpCommandLine: PWideChar;
lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
lpCurrentDirectory: PWideChar; const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation): BOOL; stdcall;
var
nSize: Cardinal;
begin
{ 显示打开程序的命令行和文件名}
MessageBoxW(0, lpCommandLine ,lpApplicationName , 0);
WriteProcessMemory(ProcessHandle, BaseAddress[0], @OldProc[0], 8, nSize);//這一句是修改成原來函數的地址,讓程序能正常打開
Result := CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes,
lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
WriteProcessMemory(ProcessHandle, BaseAddress[0], @NewPorc[0], 8, nSize);//在程序正常打開後再修改成自定義函數的地址,使所有程序在下次打開時都要先調用自定義函數
end;procedure HookAPI;
var
DLLModule: THandle;
nSize: Cardinal;
Dat: DWORD;
Tmp : array [0..3] of Byte;
begin
ProcessHandle := DWORD(-1);
DLLModule := LoadLibrary('kernel32.dll');
{ 系统函数入口点地址 }
BaseAddress[0] := GetProcAddress(DLLModule, 'CreateProcessW');
Dat := DWORD(@MyCreatePW);
Move(Dat, Tmp, 4);
NewPorc[0][0] := $B8; { 汇编跳转指令 }
NewPorc[0][1] := Tmp[0]; { 跳转到自身的函数 }
NewPorc[0][2] := Tmp[1];
NewPorc[0][3] := Tmp[2];
NewPorc[0][4] := Tmp[3];
NewPorc[0][5] := $FF;
NewPorc[0][6] := $E0;
NewPorc[0][7] := 0;
{ 读取系统函数内存地址 }
ReadProcessMemory(ProcessHandle, BaseAddress[0], @OldProc[0], 8, nSize);
{ 用自己的函数地址覆盖系统的函数地址 }
WriteProcessMemory(ProcessHandle, BaseAddress[0], @NewPorc[0], 8, nSize);
CloseHandle(ProcessHandle);
end;procedure UnHookAPI;
var
nSize: Cardinal;
begin
{ 恢复所修改的地址 }
WriteProcessMemory(ProcessHandle, BaseAddress[0], @OldProc[0], 8, nSize); //主要是這句出了問題,為何無法恢復原來函數的地址??
end;end.
hook.dpr
//////////library hook;uses
SysUtils,
windows,
Messages,
APIHook in 'apihook.pas';type
PData = ^TData;
TData = record
Hook: THandle;
Hooked: Boolean;
end;var
DLLData: PData;{------------------------------------}
{过程名:HookProc
{过程功能:HOOK过程
{过程参数:nCode, wParam, lParam消息的相
{ 关参数
{------------------------------------}
procedure HookProc(nCode, wParam, lParam: LongWORD);stdcall;
begin
if not DLLData^.Hooked then
begin
HookAPI;
DLLData^.Hooked := True;
end;
//调用下一个Hook
CallNextHookEx(DLLData^.Hook, nCode, wParam, lParam);
end;
{------------------------------------}
{函数名:InstallHook
{函数功能:在指定窗口上安装HOOK
{函数参数:sWindow:要安装HOOK的窗口
{返回值:成功返回TRUE,失败返回FALSE
{------------------------------------}
function InstallHook(SWindow: LongWORD):Boolean;stdcall;
var
ThreadID: LongWORD;
begin
Result := False;
DLLData^.Hook := 0;
ThreadID := GetWindowThreadProcessId(sWindow, nil);
//给指定窗口挂上钩子
DLLData^.Hook := SetWindowsHookEx(WH_GETMESSAGE, @HookProc, Hinstance, 0);//ThreadID
if DLLData^.Hook > 0 then
Result := True //是否成功HOOK
else
exit;
end;{------------------------------------}
{过程名:UnHook
{过程功能:卸载HOOK
{过程参数:无
{------------------------------------}
procedure UnHook;stdcall;
begin
UnHookAPI;
//卸载Hook
UnhookWindowsHookEx(DLLData^.Hook);
end;{------------------------------------}
{过程名:DLL入口函数
{过程功能:进行DLL初始化,释放等
{过程参数:DLL状态
{------------------------------------}
procedure MyDLLHandler(Reason: Integer);
var
FHandle: LongWORD;
begin
case Reason of
DLL_PROCESS_ATTACH:
begin //建立文件映射,以实现DLL中的全局变量
FHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, $ffff, 'MYDLLDATA');
if FHandle = 0 then
if GetLastError = ERROR_ALREADY_EXISTS then
begin
FHandle := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'MYDLLDATA');
if FHandle = 0 then Exit;
end else Exit;
DLLData := MapViewOfFile(FHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if DLLData = nil then
CloseHandle(FHandle);
end;
DLL_PROCESS_DETACH:
begin
if Assigned(DLLData) then
begin
UnmapViewOfFile(DLLData);
DLLData := nil;
end;
end;
end;
end;{$R *.res}
exports
InstallHook, UnHook, HookProc;begin
DLLProc := @MyDLLHandler;
MyDLLhandler(DLL_PROCESS_ATTACH);
DLLData^.Hooked := False;
end.
SetWindowsHookEx后,目标进程B收到消息,DLL被映射到B进程并调用HookProc
目标进程B里的HookProc调用InstallHook并把原始地址存到B.DLLData
两个进程DLL中的变量DLLData不是共享的,即调用SetWindowsHookEx的A进程里的DLLData<>被映射进程B里的DLLData
而UnHook时你访问的是A.DllData,在A里调用UnHook是不正确的解决方案:
1.定义两个消息,MSG_Hook MSG_UnHook;
2.修改HookProc,判断消息是MSG_Hook则装载API HOOK,是MSG_UnHook则卸载API HOOK;
3.A进程用SetWindowsHookEx装载Msg Hook后,发MSG_Hook给目标窗口,由B进程的HookProc装载API HOOK;
4.需要卸载API HOOK,A进程向目标窗口发MSG_UnHook,由B进程的HookProc收到并卸载API HOOK,然后A进程SetWindowsHookEx还原目标进程的Msg Hook
用MadHookCode吧~或类似的动态编码方法
$B8 xxxxx $FF $E0 0那些16进制数代表哪些汇编命令啊?