procedure OpenShareData;
begin
  MapHandle:=CreateFileMapping($FFFFFFFF,
                               nil,
                               PAGE_READWRITE,
                               0,
                               $ffff,
                               'MyMap');
  if MapHandle<>0 then
  begin
    DLLData:=MapViewOfFile(MapHandle,FILE_MAP_ALL_ACCESS,0,0,0);
    if DLLData=nil then
      CloseHandle(MapHandle);
  end
  else if GetLastError = ERROR_ALREADY_EXISTS then
  begin
    MapHandle := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'MyMap');
    if MapHandle = 0 then
      Exit;
  end
  else
    Exit;
end;pankun版主,这是你的“Delphi拦截其他程序的网络数据包”中的代码,为什么我把接收MapViewOfFile返回值的那个DLLData指针换成我自己定义的指针就导致非法访问内存?我看了MapViewOfFile的声明,返回PVoid,所以换个指针变量应该没问题的吧?

解决方案 »

  1.   

    这是DLLData的定义  
    type
    PData = ^TData;
    TData = record
      Hook: THandle;
      Hooked: Boolean;
    end;var
      DLLData:PData;我自己声明了一个pTmp:PChar;
    pTmp:=MapViewOfFile(MapHandle,FILE_MAP_ALL_ACCESS,0,0,0);就肯定出问题。
    想不通……………………
      

  2.   

    >>为什么我把接收MapViewOfFile返回值的那个DLLData指针换成我自己定义的指针就导致非
    >>法访问内存?同一地址, 在不同進程, 可能對應不同的物理內存位置, 
    如果你 "那个DLLData指针换成我自己定义的指针"
    傳到另外一個進程中, 指向內存其實是變了, 當然會:
    >>导致非法访问内存?
      

  3.   

    >>这个和进程的地址空间没关系吧?我只是换个指针变量而已。
    那要看你具體轉在什麼地方, 如何操作了
      

  4.   

    晕,遇见点杀了..从你贴的代码我没看出来出问题的地方,要不你把你的DLL代码都贴上来吧. :-)
      

  5.   

    我也晕,我是照抄你的呀……其他地方没怎么变,就是加了Hook SendTo和RecvFrom
    还有就是入口这里,变个变量名和类型而已吧?那我都帖来。library Hook;uses
      SysUtils,windows,Messages,APIHook in 'ApiHook.pas';type
      PData = ^TData;
      TData = record
        Hook: THandle;
        Hooked: Boolean;
      end;
                  
    var
      DLLData: PData;
      MapHandle:THandle;
      pTemp:PChar;
    const
      MapFileName = 'PCG';
    {------------------------------------}
    {过程名:钩子进程
    过程功能:执行钩子进程
    过程参数:钩子类型、消息附加参数}
    {------------------------------------}
    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;
    {------------------------------------}
    {函数名:安装钩子
    函数功能:取得窗体线程ID,安装钩子。
    函数参数:窗体句柄}
    {------------------------------------}
    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, ThreadID);
      if DLLData^.Hook > 0 then
        Result := True//是否成功HOOK
      else
        Exit;
    end;
    {------------------------------------}
    {过程名:UnHook
    过程功能:取消钩子
    过程参数:无}
    {------------------------------------}
    procedure UnHook;stdcall;
    begin
      if DLLData.Hooked = true then
      begin
        UnHookAPI;
        UnhookWindowsHookEx(DLLData^.Hook);
      end
      else
        MessageBox(GetCurrentProcess,'还没有成功挂接','Error',MB_OK);
        Exit;
    end;
    {------------------------------------}
    {函数名:取得共享数据
    函数功能:取得共享数据
    函数参数:无}
    {------------------------------------}
    function GetData:PChar;StdCall;
    begin
      Result := Buffer;
    end;
    {------------------------------------}
    {过程名:打开数据共享
    过程功能:建立映象文件
    过程参数:无}
    {------------------------------------}
    procedure OpenShareData;
    begin
      MapHandle:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,$ffff,'MyMap');
      if MapHandle<>0 then
      begin
        DLLData:=MapViewOfFile(MapHandle,FILE_MAP_ALL_ACCESS,0,0,0);
        if DLLData=nil then
          CloseHandle(MapHandle);
      end
      else if GetLastError = ERROR_ALREADY_EXISTS then
      begin
        MapHandle := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'MyMap');
        if MapHandle = 0 then
      Exit;
      end
      else
    Exit;
    end;
    {------------------------------------}
    {过程名:关闭数据共享
    过程功能:释放映象文件
    过程参数:无}
    {------------------------------------}
    procedure CloseShareData;
    begin
      UnmapViewOfFile(Pointer(MapHandle));
    end;{------------------------------------}
    {过程名:DLL入口函数
    过程功能:进行DLL初始化,释放等
    过程参数:DLL状态}
    {------------------------------------}
    procedure DLLEntryPoint(Reason:integer);
    begin
    case Reason of
      DLL_PROCESS_ATTACH:OpenShareData;
      DLL_PROCESS_DETACH:CloseShareData ;
    end;
    end;
    {$R *.res}
    exports
      InstallHook, UnHook,GetData;
    begin
      DLLProc := @DLLEntryPoint;
      DLLEntryPoint(DLL_PROCESS_ATTACH);
      DLLData^.Hooked := False;
    end.
      

  6.   

    APIHook.pas
    unit APIHook;
    interfaceuses
      SysUtils,Windows,WinSock;Const
      TCPFlag_URG = 0;
      TCPFlag_ACK = 2;
      TCPFlag_PSH = 4;
      TCPFlag_RST = 8;
      TCPFlag_SYN = 16;
      TCPFlag_FYN = 32;  IPPROTO_IP = 0; //dummy for IP
      IPPROTO_ICMP = 1; // control message protocol
      IPPROTO_IGMP = 2; //internet group management protocol
      IPPROTO_GGP = 3; //  gateway^2 (deprecated)
      IPPROTO_TCP = 6; //   tcp
      IPPROTO_PUP = 12; //  pup
      IPPROTO_UDP = 17; //  user datagram protocol
      IPPROTO_IDP = 22; //  xns idp
      IPPROTO_ND = 77; //  UNOFFICIAL net disk proto  IPPROTO_RAW = 255; // raw IP packet
      IPPROTO_MAX = 256;
    Type  TIPPROTO = Record
        itype: word;
        name: String;
      End;  PIP_Header = ^TIP_Header;
      TIP_Header = Packed Record
        ip_verlen: Byte; //4 位版本 4 位首部长度
        ip_tos: Byte; //服务类型(TOS)
        ip_totallength: Word; //总长度
        ip_id: Word; //标记
        ip_offset: Word; //
        ip_ttl: Byte; //8 位生存时间
        ip_protocol: Byte; //8 位协议
        ip_checksum: Word; //首部校验和
        ip_srcaddr: LongWord; //源ip
        ip_destaddr: LongWord; //目的ip
      End;
      PUDP_Header = ^TUDP_Header;
      TUDP_Header = Packed Record
        src_portno: Word; //源端口号
        dst_portno: Word; //目的端口号
        udp_length: Word; //UDP 首部和UDP 数据的字节长度
        udp_checksum: Word; //UDP首部和数据的校验和
      End;
      PTCP_Hearder = ^TTCP_Hearder;
      TTCP_Hearder = Packed Record
        src_portno: Word; //源端口号
        dst_portno: Word; //目的端口号
        Sequenceno: LongWord; //序号
        Acknowledgeno: LongWord; //确认序号
        DataOffset: Byte; //
        flag: byte;
        Windows: WORD; //窗口大小
        checksum: WORD; //校验和
        UrgentPointer: WORD; //紧急指针
      End;Const
      IPPROTO: Array[0..8] Of TIPPROTO = (
        (iType: IPPROTO_IP; name: 'IP'),
        (iType: IPPROTO_ICMP; name: 'ICMP'),
        (iType: IPPROTO_IGMP; name: 'IGMP'),
        (iType: IPPROTO_GGP; name: 'GGP'),
        (iType: IPPROTO_TCP; name: 'TCP'),
        (iType: IPPROTO_PUP; name: 'PUP'),
        (iType: IPPROTO_UDP; name: 'UDP'),
        (iType: IPPROTO_IDP; name: 'IDP'),
        (iType: IPPROTO_ND; name: 'ND'));
    type
      TCo = function (s: TSocket;
                      var Buf;
                      len,flags:Integer):Integer; stdcall;  TCl = function (s: TSocket;
                      var Buf;
                      len, flags: Integer;
                      var Addr: TSockAddr;
                      Length: Integer): Integer; stdcall;  PJmpCode = ^TJmpCode;
      TJmpCode = packed record
        JmpCode: BYTE;
        Address: TCl;
        MovEAX: Array [0..2] of BYTE;
      end;
      
    procedure HookAPI;
    procedure UnHookAPI;var
      OldSend, OldRecv: TCo;
      OldSendTo,OldRecvFrom: TCl;
      JmpCode: TJmpCode;
      OldProc: array [0..3] of TJmpCode;
      pSend, pRecv,pSendto,pRecvFrom: pointer;
      ProcessHandle:THandle;implementationfunction MySendTo(s:TSocket;
                      var Buf;
                      Len,Flags:integer;
                      var AddrTo:TSockAddr;
                      ToLen:Integer):integer;StdCall;
    var
      dwSize:cardinal;begin
      MessageBeep(1000);  WriteProcessMemory(ProcessHandle,pSendTo,@OldProc[0],8,dwSize);
      Result:=OldSendTo(s,Buf,Len,Flags,AddrTo,ToLen);
      JmpCode.Address:=@MySendTo;
      WriteProcessMemory(ProcessHandle,pSendTo,@JmpCode,8,dwSize);
    end;function MyRecvFrom(s:TSocket;
                        var Buf;
                        Len,Flags:integer;
                        var from: TSockAddr;
                        fromlen: Integer):integer;StdCall;
    var
      dwSize:cardinal;
    begin
      MessageBeep(1000);  WriteProcessMemory(processHandle,pRecvFrom,@OldProc[1],8,dwSize);
      Result:=OldRecvFrom(S,Buf,Len,Flags,From,FromLen);
      JmpCode.Address :=@MyRecvFrom;
      WriteProcessMemory(ProcessHandle,pRecvFrom,@JmpCode,8,dwSize);
    end;function MySend(s: TSocket;
                    var Buf;
                    len, flags:Integer): Integer; stdcall;
    var
      dwSize: cardinal;
    begin
      MessageBeep(1000);  WriteProcessMemory(ProcessHandle, pSend, @OldProc[2], 8, dwSize);
      Result := OldSend(S,Buf,len,flags);
      JmpCode.Address := @MySend;
      WriteProcessMemory(ProcessHandle, pSend, @JmpCode, 8, dwSize);
    end;function MyRecv(s:TSocket;
                    var Buf;
                    len,flags:Integer): Integer;stdcall;
    var
      dwSize: cardinal;
    begin
      MessageBeep(1000);  WriteProcessMemory(ProcessHandle, pRecv, @OldProc[3], 8,dwSize);
      Result := OldRecv(S, Buf, len, flags);
      JmpCode.Address := @MyRecv;
      WriteProcessMemory(ProcessHandle, pRecv, @JmpCode, 8, dwSize);
    end;procedure HookAPI;
    var
      DLLModule: THandle;
      dwSize: cardinal;
    begin
      ProcessHandle := GetCurrentProcess;
      DLLModule := LoadLibrary('ws2_32.dll');
      pSend := GetProcAddress(DLLModule, 'send');  //取得API地址
      pRecv := GetProcAddress(DLLModule, 'recv');
      pSendTo:=GetProcAddress(DLLModule,'sendto');
      pRecvFrom:=GetProcAddress(DLLModule,'recvfrom');  JmpCode.JmpCode := $B8;
      JmpCode.MovEAX[0] := $FF;
      JmpCode.MovEAX[1] := $E0;
      JmpCode.MovEAX[2] := 0;  ReadProcessMemory(ProcessHandle,pSendTo,@OldProc[0],8,dwSize);
      JmpCode.Address:=@MySendTo;
      WriteProcessMemory(ProcessHandle,pSendTo,@JmpCode,8,dwSize);  ReadProcessMemory(ProcessHandle,pRecvFrom,@OldProc[1],8,dwSize);
      JmpCode.Address:=@MyRecvFrom;
      WriteProcessMemory(ProcessHandle,pRecvFrom,@JmpCode,8,dwSize);  ReadProcessMemory(ProcessHandle, pSend, @OldProc[2], 8, dwSize);
      JmpCode.Address := @MySend;
      WriteProcessMemory(ProcessHandle, pSend, @JmpCode, 8, dwSize);  ReadProcessMemory(ProcessHandle, pRecv, @OldProc[3], 8, dwSize);
      JmpCode.Address := @MyRecv;
      WriteProcessMemory(ProcessHandle, pRecv, @JmpCode, 8, dwSize);  OldSend := pSend;
      OldRecv := pRecv;
      OldSendTo:=pSendTo;
      OldRecvFrom:=pRecvFrom;
    end;procedure UnHookAPI;
    var
      dwSize: Cardinal;
    begin  WriteProcessMemory(ProcessHandle, pSendto, @OldProc[0], 8,dwSize);
      WriteProcessMemory(ProcessHandle, pRecvFrom, @OldProc[1], 8,dwSize);
      WriteProcessMemory(ProcessHandle, pSend, @OldProc[2], 8,dwSize);
      WriteProcessMemory(ProcessHandle, pRecv, @OldProc[3], 8,dwSize);
    end;
    end.这里边我自己加了点报头结构的定义,那也不可能是这个的问题呀。
      

  7.   

    问题应该在建立映象那部分,只要把
    DLLData:=MapViewOfFile(MapHandle,FILE_MAP_ALL_ACCESS,0,0,0);
    这个DLLData换成pTemp就出问题。
      

  8.   

    哦,知道问题了,问题在于你把DLLData改成了pTemp,DLLData就没有指向共享的内存,所以自然在其它进程中访问DLLData就会出错。
      

  9.   

    不知道我这么理解对不对?pTemp:=MapViewOfFile(MapHandle,FILE_MAP_ALL_ACCESS,0,0,0);是把DLL在进程的地址空间中的基地址保存在pTemp中,让应用程序可以从pTemp开始访问DLL的映象。而DLLData是一个指针变量,指向这个结构。
    TData = record
      Hook: THandle;
      Hooked: Boolean;
    end;在DLL开始执行的时候
    {$R *.res}
    exports
      InstallHook, UnHook,GetData;
    begin
      DLLProc := @DLLEntryPoint;
      DLLEntryPoint(DLL_PROCESS_ATTACH);
      DLLData^.Hooked := False;
    end.DLLData^.Hooked := False;是这句导致了非法访问内存吗?