hook 了ZWSetSystemTime函数,普通状态下运行正常,但将程序从系统服务模式下重新启动,hook失效,并且导致很多其它应用软件出现运行时216错误,很奇怪。望大侠们指点一下,难道系统服务模式下,函数的入口地址跟普通模式下不一样?我是hook的ntdll.dll里的ZWSetSystemTime啊。我把源码发给大家看一下... library PKTimer;uses
  Windows,
  Messages,
  untAPIHOOK in 'untAPIHOOK.pas';const MapName='PKTimer';
UM_TIMECHANGE=WM_USER+1001;
type
  TShareMem=record
    HwndParent:Cardinal;
  end;
  PShareMem=^TShareMem;  TMySetSystemTime=function(_oldtime:PLargeInteger;_newtime:PLargeInteger):BOOL;stdcall;var
  hk_SetSystemTime:TAPIHook;
  msghk:HHOOK;
  hMap:Cardinal;
  dtp:PShareMem;
  LastTime:Cardinal;
//--------------------------
function MySetSystemTime(_oldtime:PLargeInteger;_newtime:PLargeInteger):BOOL;stdcall;
var
  dt:TCopyDataStruct;
  bf:array [0..MAX_PATH] of Char;
begin
  if GetTickCount-LastTime >50 then begin
    GetModuleFileName(0,bf,MAX_PATH);
    dt.cbData:=MAX_PATH;
    dt.lpData:=@bf;
    dt.dwData:=2007;
    //if SendMessage(dtp^.HwndParent,UM_TIMECHANGE,dt.cbData,LongInt(@dt))=1 then begin
    if SendMessage(dtp^.HwndParent,UM_TIMECHANGE,0,0)=1 then begin
      hk_SetSystemTime.FindOn;;
      Result:=TMySetSystemTime(hk_SetSystemTime.OldAddr)(_oldtime,_newtime);
      hk_SetSystemTime.FindOff;
    end else begin
      Result:=false;
    end;
  end else Result:=false;
  LastTime:=GetTickCount;
end;function HookProc(nCode,wParam,lParam:Cardinal):Cardinal;stdcall;
begin
  Result:=CallNextHookEx(msghk,nCode,wParam,lParam);
end;
procedure LockTime(HwndParent:Cardinal;ALock:BOOL);stdcall;
begin
  dtp^.HwndParent:=HwndParent;
  if ALock then
    msghk:=SetWindowsHookEx(WH_GETMESSAGE,@HookProc,HInstance,0)
  else
    UnhookWindowsHookEx(msghk);
end;
//--------------------------
procedure DllMain(nTag:Cardinal);
begin
  case nTag of
    DLL_PROCESS_ATTACH:begin
        hMap:=OpenFileMapping(FILE_MAP_ALL_ACCESS,false,MapName);
        if hMap=0 then hMap:=CreateFileMapping(THandle(-1),nil,PAGE_READWRITE,0,SizeOf(TShareMem),MapName);
        dtp:=MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,0);
        if dtp=nil then Exit;        hk_SetSystemTime:=TAPIHook.Create('ntdll.dll','ZwSetSystemTime',@MySetSystemTime);
        hk_SetSystemTime.HookAPI;
      end;
    DLL_PROCESS_DETACH:begin
        hk_SetSystemTime.UnHookAPI;
        hk_SetSystemTime.Free;        UnmapViewOfFile(dtp);
        CloseHandle(hMap);
      end;
  end;
end;
//--------------------------
exports
  LockTime;
begin
  DllProc:=@DllMain;
  DllMain(DLL_PROCESS_ATTACH);
end.procedure LockTime(HwndParent: Cardinal; ALock: BOOL); stdcall; external 'PKTimer.dll';然后在需要的地方调用
LockTime(Handle, true);最后当有ZWSetSystemTime被拦截时,发送UM_TIMECHANGE消息至HWndParnet,在主窗口处理该消息Hook的实现部分constructor TAPIHook.Create(ModuleName:PChar;OldFunName:PChar;NewFun:Pointer);
begin
  Self.F_ModuleName:=ModuleName;
  Self.F_OldFunName:=OldFunName;
  Self.F_NewFun:=NewFun;
end;procedure TAPIHook.HookAPI;
var
  DLLModule         : THandle;
begin
  Self.F_ProcessHandle := GetCurrentProcess;
  DLLModule := LoadLibrary(Self.F_ModuleName);
  OldAddr := GetProcAddress(DLLModule, Self.F_OldFunName); //取得API地址  JmpCode.JmpCode := $B8;
  JmpCode.MovEAX[0] := $FF;
  JmpCode.MovEAX[1] := $E0;
  JmpCode.MovEAX[2] := 0;  ReadProcessMemory(Self.F_ProcessHandle, OldAddr, @Oldproc[0], 8, dwSize);
  JmpCode.Address := Self.F_NewFun;
  WriteProcessMemory(Self.F_ProcessHandle, OldAddr, @JmpCode, 8, dwSize); //修改Send入口end;

解决方案 »

  1.   

    既然是普通进程运行正常而服务进程运行有问题,应该首先考虑与此有关的因素,不用急着贴DLL的代码。要Hook其它进程肯定要先让目标进程加载你的DLL,这一步是怎么实现的?
    另外,在Vista系统中,服务进程与用户进程不能通过DLL共享内存,XP系统好象没有这问题。
      

  2.   

    Delphi的帖子发到MFC版?
    某人很生气,后果很严重……开个玩笑……
    加载方式是怎么样的?按理说没用驱动,应该不会存在太大问题……
      

  3.   

    加载的部分就是通过这样的方式啊...procedure LockTime(HwndParent: Cardinal; ALock: BOOL); stdcall; external 'PKTimer.dll'; 然后在需要的地方调用 
    LockTime(Handle, true); 最后当有ZWSetSystemTime被拦截时,发送UM_TIMECHANGE消息至HWndParnet,在主窗口处理该消息
      

  4.   

    xp sp2,自动手动都一样!