现在的位置: 首页 > 综合 > 正文

Socket SYN攻击之比尔否定

2013年09月01日 ⁄ 综合 ⁄ 共 4996字 ⁄ 字号 评论关闭

        原来在Windows 2000下的SYN攻击很简单:

  FillChar( LocalAdr, sizeof(LocalAdr), 0 );
  LocalAdr.sin_family := AF_INET;
  LocalAdr.sin_port := htons( LOCAL_PORT );
  LocalAdr.sin_addr.S_addr := inet_addr('192.168.1.12');  //换成你的IP

  FillChar( RemotAdr, sizeof(RemotAdr), 0 );
  RemotAdr.sin_family := AF_INET;
  RemotAdr.sin_port := htons( REMOT_PORT );
  RemotAdr.sin_addr.S_addr := inet_addr( PChar(Edit1.Text) );

  //
  //创建一个接收数据用的socket
  //
  RecvSock := socket( AF_INET, SOCK_RAW, IPPROTO_IP );//Can not be -> IPPROTO_RAW

  //bind是必须的,否则无法SIO_RCVALL
  bind( RecvSock, @LocalAdr, sizeof(LocalAdr) );

  //SIO_RCVALL -> 使用此参数的套接字必须同一个明确的本地接口bind,并且,
  //    套接字地址家族必须是AF_INET. 类型必须是SOCK_RAW. 协议必须是IPPROTO_IP
  arg := 1;
  if ioctlsocket( RecvSock, SIO_RCVALL, arg ) = SOCKET_ERROR then
  begin
    ErrMsg( 'ioctlsocket() failed with error ' + IntToStr(WSAGetLastError) );
    exit;
  end;

  if WSAAsyncSelect( RecvSock, handle, WM_SOCKet,FD_READ )=SOCKET_ERROR then
  begin
    ErrMsg( 'WSAAsyncSelect() failed with error ' + IntToStr(WSAGetLastError) );
    exit;
  end;

  //
  //创建一个发送数据用的socket
  //
  SendSock := socket( AF_INET, SOCK_RAW, IPPROTO_IP );//Also can be -> IPPROTO_RAW

  //在Windows NT4、Windows 98中,SOCK_RAW时,只能使用IPPROTO_IGMP和IPPROTO_ICMP
  //在Windows 2000中,SOCK_RAW时,可以使用IPPROTO_UDP、IPPROTO_IP以及IPPROTO_RAW
  //  但是必须使用套接字选项IP_HDRINCL!!!
  arg := 1;
  if setsockopt( sendsock, IPPROTO_IP, IP_HDRINCL, @arg, sizeof(arg) )= SOCKET_ERROR then
  begin
    ErrMsg( 'setsockopt() failed with error ' + IntToStr(WSAGetLastError) );
    exit;
  end;

  //socket创建好了,分配内存
  cbData := 0;
  pIPHdr := AllocMem( sizeof(YIPHeader) + sizeof(YTCPHeader) + cbData );
  pTCPHdr := PTCPHeader( PChar(pIPHdr) + sizeof(YIPHeader) );
  pData := PChar(pTCPHdr) + sizeof(YTCPHeader);

  //开始SYN->ACK
  dwSeq := RAW_INIT_SEQ;
  dwAck := 0;
  dwFlg := 2; //00000010  SYN=1 用来发起一个连接

  FillIPHeader( pIPHdr, IPPROTO_TCP, cbData, 11111, RemotAdr.sin_addr.S_addr,
      LocalAdr.sin_addr.S_addr );

  FillTCPHeader( pTCPHdr, cbData, RemotAdr.sin_port, LocalAdr.sin_port,
      dwSeq, dwAck, dwFlg, RemotAdr.sin_addr.S_addr, LocalAdr.sin_addr.S_addr );

  if sendto( SendSock, pIPHdr^, sizeof(YIPHeader) + sizeof(YTCPHeader) + cbData,
         0, RemotAdr, sizeof(RemotAdr) ) = SOCKET_ERROR then
  begin
    ErrMsg( 'sendto() failed with error ' + IntToStr(WSAGetLastError) );
    exit;
  end;

  if recv( RecvSock, RecvBuf[0], MAX_PACKET_SIZE, 0 )= SOCKET_ERROR then
  begin
    errmsg( 'Call recv() failed with error '+IntToStr(WSAGetLastError) );
    exit;
  end;

   DecodeTCPReply( @RecvBuf[0], DestSeq, DestAck );   

  dwSeq := DestAck;
  dwAck := DestSeq+1;
  dwFlg := 16; //00010000  ACK=1

  FillIPHeader( pIPHdr, IPPROTO_TCP, cbData, 11111, RemotAdr.sin_addr.S_addr,
      LocalAdr.sin_addr.S_addr );

  FillTCPHeader( pTCPHdr, cbData, RemotAdr.sin_port, LocalAdr.sin_port,
      dwSeq, dwAck, dwFlg, RemotAdr.sin_addr.S_addr, LocalAdr.sin_addr.S_addr );

  if sendto( SendSock, pIPHdr^, sizeof(YIPHeader) + sizeof(YTCPHeader) + cbData,
         0, RemotAdr, sizeof(RemotAdr) ) = SOCKET_ERROR then
  begin
    ErrMsg( 'sendto() failed with error ' + IntToStr(WSAGetLastError) );
    exit;
  end;

呵呵,以上是TCP三次握手的代码,应该没有什么问题吧?

但是在XP SP1下,根本接收不到服务器返回的任何数据~~~~~~~用IRIS监视一下,原来XP接收到服务器的ACK报文以后竟然自动发送了一个RST报文~~~~~~我倒~~~

附上几个函数:

//填充IP Header
procedure FillIPHeader( pip: PIPHeader; pro: U8; datalen,id,destip,fromip: U32 );
var
  extln : u8;
begin
  case pro of
    IPPROTO_TCP : extln := sizeof(YTCPHeader);
    IPPROTO_UDP : extln := sizeof(YUDPHeader);
  else
    extln := sizeof(YIPHeader);//IPPROTO_IP
  end;

  pip^.u8verlen := ( 4 shl 4 ) or (sizeof(YIPHeader) div sizeof(u32));
  pip^.u8tos := 0;
  pip^.u16totallen := htons( u16(sizeof(YIPHeader) + extln + datalen) );
  pip^.u16id := htons( u16(id) );
  pip^.u16offset := htons(1 shl 14);//do not fragment
  pip^.u8ttl := 128;
  pip^.u8protol := pro;
  pip^.u16checksum := 0;
  pip^.u32srcaddr := fromip;
  pip^.u32destaddr := destip;
  pip^.u16checksum := CheckSum( PU16(pip), sizeof(YIPHeader) );
end;

//填充UDP Header
procedure FillUDPHeader( pudp: PUDPHeader; datalen: u32; destport, fromport: U32 );
begin
  pudp^.u16fromport := fromport;
  pudp^.u16destport := destport;
  pudp^.u16totlen := htons( sizeof(YUDPHeader) + datalen );
  pudp^.u16chksum := 0;
end;

//
//  填充TCP Header,ptcp是指向TCP header的指针,要发送的数据应该在TCP header后
//  即:piphdr := allocmem( sizeof(IPHeader)+sizeof(TCPHeader)+datasize );
//      ptcphdr := PByte(piphdr) + sizeof(IPHeader);
//      pdata := PByte(ptcphdr) + sizeof(TCPHeader);
//
procedure FillTCPHeader( ptcp: PTCPHeader; datalen, destport, fromport, seq,
          ack, flag, destip, fromip: U32 );
var
  buf : TByteArray;
  psd : YPSDHeader;
begin
  ptcp^.u16fromport := fromport;
  ptcp^.u16destport := destport;
  ptcp^.u32seq := htonl( seq );
  ptcp^.u32ack := htonl( ack );
  ptcp^.u8hdrlen := ( (sizeof(YTCPHeader) div sizeof(u32)) shl 4 ) or 0;
  ptcp^.u8flag := u8( flag );
  ptcp^.u16wndsize := htons( RAW_WND_SIZE );
  ptcp^.u16chksum := 0;
  ptcp^.u16urgptr := 0;

  psd.u32fromaddr := fromip;
  psd.u32destaddr := destip;
  psd.u8mbz := 0;
  psd.u8ptcl := IPPROTO_TCP;
  psd.u16length := htons( sizeof(YTCPHeader) + datalen );

  Move( psd, buf[0], sizeof(psd) );
  Move( ptcp^, buf[sizeof(psd)], sizeof(YTCPHeader) + datalen );
  ptcp^.u16chksum := CheckSum( PU16(@buf[0]),
      sizeof(psd) + sizeof(YTCPHeader) + datalen );
end;

function DecodeTCPReply( pbuf: PChar; var DestSeq, DestAck: u32 ):bool;
var
  pIpHdr   : PChar;
  pTcphdr : PTCPHeader;
begin
  pIpHdr := pbuf;
  Inc( pIpHdr, (PIPHeader(pIpHdr)^.u8verlen and $0F) * 4 );
  pTcpHdr := PTCPHeader(pIpHdr);

  result := true;
  DestSeq := ntohl(ptcphdr^.u32seq);
  DestAck := ntohl(ptcphdr^.u32ack);
end;

抱歉!评论已关闭.