如何拦截一个进程的封包??请给我指一条明路
(最好的例子)

解决方案 »

  1.   

    别看这是封包这一问题,但是涉及的技术范围很广范,实现的方式也很多(比如说APIHOOK,VXD,Winsock2都可以实现),在这里我们不可能每种技术和方法都涉及,所以我在这里以Winsock2技术作详细讲解,就算作抛砖引玉。
        由于大多数读者对封包类编程不是很了解,我在这里就简单介绍一下相关知识:
        APIHooK:
        由于Windows的把内核提供的功能都封装到API里面,所以大家要实现功能就必须通过API,换句话说就是我们要想捕获数据封包,就必须先要得知道并且捕获这个API,从API里面得到封包信息。
        VXD:
        直接通过控制VXD驱动程序来实现封包信息的捕获,不过VXD只能用于win9X。
        winsock2:
        winsock是Windows网络编程接口,winsock工作在应用层,它提供与底层传输协议无关的高层数据传输编程接口,winsock2是winsock2.0提供的服务提供者接口,但只能在win2000下用。
        好了,我们开始进入winsock2封包式编程吧。
        在封包编程里面我准备分两个步骤对大家进行讲解:1、封包的捕获,2、封包的发送。
        首先我们要实现的是封包的捕获:
        Delphi的封装的winsock是1.0版的,很自然winsock2就用不成。如果要使用winsock2我们要对winsock2在Delphi里面做一个接口,才可以使用winsock2。
        1、如何做winsock2的接口?
        1)我们要先定义winsock2.0所用得到的类型,在这里我们以WSA_DATA类型做示范,大家可以举一仿三的来实现winsock2其他类型的封装。
        我们要知道WSA_DATA类型会被用于WSAStartup(wVersionRequired: word; var WSData: TWSAData): Integer;,大家会发现WSData是引用参数,在传入参数时传的是变量的地址,所以我们对WSA_DATA做以下封装:
      const 
        WSADESCRIPTION_LEN     =   256; 
        WSASYS_STATUS_LEN      =   128; 
      type 
        PWSA_DATA = ^TWSA_DATA; 
        WSA_DATA = record 
          wVersion: Word; 
          wHighVersion: Word; 
          szDescription: array[0..WSADESCRIPTION_LEN] of Char; 
          szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char; 
          iMaxSockets: Word; 
          iMaxUdpDg: Word; 
          lpVendorInfo: PChar; 
        end; 
        TWSA_DATA = WSA_DATA; 
        2)我们要从WS2_32.DLL引入winsock2的函数,在此我们也是以WSAStartup为例做函数引入:
       function WSAStartup(wVersionRequired: word; var WSData: TWSAData): Integer; stdcall;   implementation    const WinSocket2 = 'WS2_32.DLL'; 
       function WSAStartup; external winsocket name 'WSAStartup';    通过以上方法,我们便可以对winsock2做接口,下面我们就可以用winsock2做封包捕获了,不过首先要有一块网卡。因为涉及到正在运作的网络游戏安全问题,所以我们在这里以IP数据包为例做封包捕获,如果下面的某些数据类型您不是很清楚,请您查阅MSDN:
        1)我们要起动WSA,这时个要用到的WSAStartup函数,用法如下:
    INTEGER WSAStartup(
                       wVersionRequired: word,
                       WSData: TWSA_DATA
                      );
        2)使用socket函数得到socket句柄,m_hSocket:=Socket(AF_INET, SOCK_RAW, IPPROTO_IP); 用法如下:
    INTEGER socket(af: Integer, 
                   Struct: Integer, 
                   protocol: Integer
                  );    m_hSocket:=Socket(AF_INET, SOCK_RAW, IPPROTO_IP);在程序里m_hSocket为socket句柄,AF_INET,SOCK_RAW,IPPROTO_IP均为常量。    3)定义SOCK_ADDR类型,跟据我们的网卡IP给Sock_ADDR类型附值,然后我们使用bind函数来绑定我们的网卡,Bind函数用法如下:Type 
        IN_ADDR = record 
        S_addr : PChar;
       End;Type 
       TSOCK_ADDR = record 
        sin_family: Word;
        sin_port: Word;
        sin_addr : IN_ADDR
        sin_zero: array[0..7] of Char; 
       End;var
      LocalAddr:TSOCK_ADDR;  LocalAddr.sin_family: = AF_INET;
      LocalAddr.sin_port: = 0;
      LocalAddr.sin_addr.S_addr: = inet_addr('192.168.1.1'); //这里你自己的网卡的IP地址,而inet_addr这个函数是winsock2的函数。  bind(m_hSocket, LocalAddr, sizeof(LocalAddr));    4)用WSAIoctl来注册WSA的输入输出组件,其用法如下:INTEGER WSAIoctl(s:INTEGER, 
                     dwIoControlCode : INTEGER, 
                     lpvInBuffer :INTEGER,
                     cbInBuffer : INTEGER, 
                     lpvOutBuffer : INTEGER,
                     cbOutBuffer: INTEGER, 
                     lpcbBytesReturned : INTEGER, 
                     lpOverlapped : INTEGER, 
                     lpCompletionRoutine : INTEGER
                    );
        5)下面做死循环,在死循环块里,来实现数据的接收。但是徇环中间要用Sleep()做延时,不然程序会出错。
        6)在循环块里,用recv函数来接收数据,recv函数用法如下:
    INTEGER recv (s : INTEGER, 
                  buffer:Array[0..4095] of byte, 
                  length : INTEGER,
                  flags : INTEGER,
                 );
        7)在buffer里就是我们接收回来的数据了,如果我们想要知道数据是什么地方发来的,那么,我们要定义一定IP包结构,用CopyMemory()把IP信息从buffer里面读出来就可以了,不过读出来的是十六进制的数据需要转换一下。    看了封包捕获的全过程序,对你是不是有点起发,然而在这里要告诉大家的是封包的获得是很容易的,但是许多游戏的封包都是加密的,如果你想搞清楚所得到的是什么内容还需要自己进行封包解密。
      

  2.   

    http://www.csdn.net/develop/read_article.asp?id=22765