超难的问题,关于tcp/ip数据包 ( 积分: 200 )

  • 主题发起人 主题发起人 fjx_jwf
  • 开始时间 开始时间
F

fjx_jwf

Unregistered / Unconfirmed
GUEST, unregistred user!
如何才能将一个http页面提交后送出的数据包中的源地址修改,
并重新发送出去,我不需要得到回应信息.
或者如何才能重新建一个ip头和tcp头,分不够可再加
 
如何才能将一个http页面提交后送出的数据包中的源地址修改,
并重新发送出去,我不需要得到回应信息.
或者如何才能重新建一个ip头和tcp头,分不够可再加
 
如果是连接“http页面”的ip,估计是改不了;
 
一个数据封包不是含有一个ip头吗,ip头中含有源ip地址和目标ip地址,我的意思就是将源ip地址修改后再发出去
 
先得截获HTTP的数据包,这个肯定得用到NDIS-HOOK技术,之后,修改IP头的程序在网上随便可以找到!
 
我已经堆获到数据包了,问题是如何修改,
 
有人能将下面这段代码改为发送tcp/ip包的吗,现在是udp包
发送raw IP类型的数据包
下面给出一个通过自定义源IP地址和源端口演示如何发送UDP数据包的例子,或许对你了解有所帮助.你也可以设计自己的协议,如发送SYN 数据浪涌,或其它类型的自定义协议。

{

Raw 数据包 Sender

使用:Delphi + Winsock 2



描述:

通过使用Raw sockets我们可以在internet上发送含有任意格式的数据包。它可以让你可能设计自己的协议。尽管可能接收有点困难,但黑客们可能用它来制造SYN数据浪涌。IP欺骗因此变得十分容易。



注意:

1。下面的源程序可能只在Win2000下可靠。

2。你只能发送Raw数据包。但不能接收。

3。运行此程序时你必须是管理员身份。

4。此源程序需要一个含有一个按钮和一个Memo元件的Form.



---------------------------------------------------------------------

在运行此程序前,你必须改变 SrcIP+SrcPort+DestIP+DestPort为合适的值。

---------------------------------------------------------------------

未弄明白此源程序之前请不要运行它。

---------------------------------------------------------------------

}



unit main;



interface



uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

StdCtrls, OleCtrls, Registry;



Const

SrcIP = '123.123.123.1';

SrcPort = 1234;

DestIP = '123.123.123.2';

DestPort = 4321;



Max_Message = 4068;

Max_Packet = 4096;



type



TPacketBuffer = Array[0..Max_Packet-1] of byte;



TForm1 = class(TForm)

Button1: TButton;

Memo1: TMemo;

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

procedure SendIt;

end;



// IP Header

type

T_IP_Header = record

ip_verlen : Byte;

ip_tos : Byte;

ip_totallength : Word;

ip_id : Word;

ip_offset : Word;

ip_ttl : Byte;

ip_protocol : Byte;

ip_checksum : Word;

ip_srcaddr : LongWord;

ip_destaddr : LongWord;

end;



// UDP Header

Type

T_UDP_Header = record

src_portno : Word;

dst_portno : Word;

udp_length : Word;

udp_checksum : Word;

end;



// Some Winsock 2 type declarations

u_char = Char;

u_short = Word;

u_int = Integer;

u_long = Longint;



SunB = packed record

s_b1, s_b2, s_b3, s_b4: u_char;

end;

SunW = packed record

s_w1, s_w2: u_short;

end;

in_addr = record

case integer of

0: (S_un_b: SunB);

1: (S_un_w: SunW);

2: (S_addr: u_long);

end;

TInAddr = in_addr;

Sockaddr_in = record

case Integer of

0: (sin_family: u_short;

sin_port: u_short;

sin_addr: TInAddr;

sin_zero: array[0..7] of Char);

1: (sa_family: u_short;

sa_data: array[0..13] of Char)

end;

TSockAddr = Sockaddr_in;

TSocket = u_int;



const

WSADESCRIPTION_LEN = 256;

WSASYS_STATUS_LEN = 128;



type

PWSAData = ^TWSAData;

WSAData = record // !!! also WSDATA

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;

TWSAData = WSAData;



// Define some winsock 2 functions

function closesocket(s: TSocket): Integer; stdcall;

function socket(af, Struct, protocol: Integer): TSocket; stdcall;

function sendto(s: TSocket; var Buf; len, flags: Integer; var addrto: TSockAddr;

tolen: Integer): Integer; stdcall;{}

function setsockopt(s: TSocket; level, optname: Integer; optval: PChar;

optlen: Integer): Integer; stdcall;

function inet_addr(cp: PChar): u_long; stdcall; {PInAddr;} { TInAddr }

function htons(hostshort: u_short): u_short; stdcall;

function WSAGetLastError: Integer; stdcall;

function WSAStartup(wVersionRequired: word; var WSData: TWSAData): Integer; stdcall;

function WSACleanup: Integer; stdcall;



const

AF_INET = 2; // internetwork: UDP, TCP, etc.



IP_HDRINCL = 2; // IP Header Include



SOCK_RAW = 3; // raw-protocol interface



IPPROTO_IP = 0; // dummy for IP

IPPROTO_TCP = 6; // tcp

IPPROTO_UDP = 17; // user datagram protocol

IPPROTO_RAW = 255; // raw IP packet



INVALID_SOCKET = TSocket(NOT(0));

SOCKET_ERROR = -1;



var

Form1: TForm1;



implementation



// Import Winsock 2 functions

const WinSocket = 'WS2_32.DLL';



function closesocket; external winsocket name 'closesocket';

function socket; external winsocket name 'socket';

function sendto; external winsocket name 'sendto';

function setsockopt; external winsocket name 'setsockopt';

function inet_addr; external winsocket name 'inet_addr';

function htons; external winsocket name 'htons';

function WSAGetLastError; external winsocket name 'WSAGetLastError';

function WSAStartup; external winsocket name 'WSAStartup';

function WSACleanup; external winsocket name 'WSACleanup';





{$R *.DFM}



//

// Function: checksum

//

// Description:

// This function calculates the 16-bit one's complement sum

// for the supplied buffer

//

function CheckSum(Var Buffer; Size : integer) : Word;

type

TWordArray = Array[0..1] of Word;

var

ChkSum : LongWord;

i : Integer;

begin

ChkSum := 0;

i := 0;

While Size > 1 do begin

ChkSum := ChkSum + TWordArray(Buffer);

inc(i);

Size := Size - SizeOf(Word);

end;



if Size=1 then ChkSum := ChkSum + Byte(TWordArray(Buffer));



ChkSum := (ChkSum shr 16) + (ChkSum and $FFFF);

ChkSum := ChkSum + (Chksum shr 16);



Result := Word(ChkSum);

end;





procedure BuildHeaders(

FromIP : String;

iFromPort : Word;

ToIP : String;

iToPort : Word;

StrMessage : String;

Var Buf : TPacketBuffer;

Var remote : TSockAddr;

Var iTotalSize : Word

);

Var

dwFromIP : LongWord;

dwToIP : LongWord;



iIPVersion : Word;

iIPSize : Word;

ipHdr : T_IP_Header;

udpHdr : T_UDP_Header;



iUdpSize : Word;

iUdpChecksumSize : Word;

cksum : Word;



Ptr : ^Byte;



procedure IncPtr(Value : Integer);

begin

ptr := pointer(integer(ptr) + Value);

end;



begin

// Convert ip address'ss



dwFromIP := inet_Addr(PChar(FromIP));

dwToIP := inet_Addr(PChar(ToIP));



// Initalize the IP header

//

iTotalSize := sizeof(ipHdr) + sizeof(udpHdr) + length(strMessage);



iIPVersion := 4;

iIPSize := sizeof(ipHdr) div sizeof(LongWord);

//

// IP version goes in the high order 4 bits of ip_verlen. The

// IP header length (in 32-bit words) goes in the lower 4 bits.

//

ipHdr.ip_verlen := (iIPVersion shl 4) or iIPSize;

ipHdr.ip_tos := 0; // IP type of service

ipHdr.ip_totallength := htons(iTotalSize); // Total packet len

ipHdr.ip_id := 0; // Unique identifier: set to 0

ipHdr.ip_offset := 0; // Fragment offset field

ipHdr.ip_ttl := 128; // Time to live

ipHdr.ip_protocol := $11; // Protocol(UDP)

ipHdr.ip_checksum := 0 ; // IP checksum

ipHdr.ip_srcaddr := dwFromIP; // Source address

ipHdr.ip_destaddr := dwToIP; // Destination address

//

// Initalize the UDP header

//

iUdpSize := sizeof(udpHdr) + length(strMessage);



udpHdr.src_portno := htons(iFromPort) ;

udpHdr.dst_portno := htons(iToPort) ;

udpHdr.udp_length := htons(iUdpSize) ;

udpHdr.udp_checksum := 0 ;

//

// Build the UDP pseudo-header for calculating the UDP checksum.

// The pseudo-header consists of the 32-bit source IP address,

// the 32-bit destination IP address, a zero byte, the 8-bit

// IP protocol field, the 16-bit UDP length, and the UDP

// header itself along with its data (padded with a 0 if

// the data is odd length).

//

iUdpChecksumSize := 0;



ptr := @buf[0];

FillChar(Buf, SizeOf(Buf), 0);



Move(ipHdr.ip_srcaddr, ptr^, SizeOf(ipHdr.ip_srcaddr));

IncPtr(SizeOf(ipHdr.ip_srcaddr));



iUdpChecksumSize := iUdpChecksumSize + sizeof(ipHdr.ip_srcaddr);



Move(ipHdr.ip_destaddr, ptr^, SizeOf(ipHdr.ip_destaddr));

IncPtr(SizeOf(ipHdr.ip_destaddr));



iUdpChecksumSize := iUdpChecksumSize + sizeof(ipHdr.ip_destaddr);



IncPtr(1);



Inc(iUdpChecksumSize);



Move(ipHdr.ip_protocol, ptr^, sizeof(ipHdr.ip_protocol));

IncPtr(sizeof(ipHdr.ip_protocol));

iUdpChecksumSize := iUdpChecksumSize + sizeof(ipHdr.ip_protocol);



Move(udpHdr.udp_length, ptr^, sizeof(udpHdr.udp_length));

IncPtr(sizeof(udpHdr.udp_length));

iUdpChecksumSize := iUdpChecksumSize + sizeof(udpHdr.udp_length);



move(udpHdr, ptr^, sizeof(udpHdr));

IncPtr(sizeof(udpHdr));

iUdpChecksumSize := iUdpCheckSumSize + sizeof(udpHdr);



Move(StrMessage[1], ptr^, Length(strMessage));

IncPtr(Length(StrMessage));



iUdpChecksumSize := iUdpChecksumSize + length(strMessage);



cksum := checksum(buf, iUdpChecksumSize);

udpHdr.udp_checksum := cksum;



//

// Now assemble the IP and UDP headers along with the data

// so we can send it

//

FillChar(Buf, SizeOf(Buf), 0);

Ptr := @Buf[0];



Move(ipHdr, ptr^, SizeOf(ipHdr)); IncPtr(SizeOf(ipHdr));

Move(udpHdr, ptr^, SizeOf(udpHdr)); IncPtr(SizeOf(udpHdr));

Move(StrMessage[1], ptr^, length(StrMessage));



// Apparently, this SOCKADDR_IN structure makes no difference.

// Whatever we put as the destination IP addr in the IP header

// is what goes. Specifying a different destination in remote

// will be ignored.

//

remote.sin_family := AF_INET;

remote.sin_port := htons(iToPort);

remote.sin_addr.s_addr := dwToIP;

end;



procedure TForm1.SendIt;

Var

sh : TSocket;

bOpt : Integer;

ret : Integer;

Buf : TPacketBuffer;

Remote : TSockAddr;

Local : TSockAddr;

iTotalSize : Word;

wsdata : TWSAdata;



begin

// Startup Winsock 2

ret := WSAStartup($0002, wsdata);

if ret<>0 then begin

memo1.lines.add('WSA Startup failed.');

exit;

end;

with memo1.lines do begin

add('WSA Startup:');

add('Desc.: '+wsData.szDescription);

add('Status: '+wsData.szSystemStatus);

end;



try

// Create socket

sh := Socket(AF_INET, SOCK_RAW, IPPROTO_UDP);

if (sh = INVALID_SOCKET) then begin

memo1.lines.add('Socket() failed: '+IntToStr(WSAGetLastError));

exit;

end;

Memo1.lines.add('Socket Handle = '+IntToStr(sh));



// Option: Header Include

bOpt := 1;

ret := SetSockOpt(sh, IPPROTO_IP, IP_HDRINCL, @bOpt, SizeOf(bOpt));

if ret = SOCKET_ERROR then begin

Memo1.lines.add('setsockopt(IP_HDRINCL) failed: '+IntToStr(WSAGetLastError));

exit;

end;



// Build the packet

BuildHeaders( SrcIP, SrcPort,

DestIP, DestPort,

'THIS IS A TEST PACKET',

Buf, Remote, iTotalSize );



// Send the packet

ret := SendTo(sh, buf, iTotalSize, 0, Remote, SizeOf(Remote));

if ret = SOCKET_ERROR then

Memo1.Lines.Add('sendto() failed: '+IntToStr(WSAGetLastError))

else

Memo1.Lines.Add('send '+IntToStr(ret)+' bytes.');



// Close socket

CloseSocket(sh);

finally

// Close Winsock 2

WSACleanup;

end;

end;



procedure TForm1.Button1Click(Sender: TObject);

begin

SendIt;

end;



end.
 
请问谁能将这段代码改为delphi代码呀
windows使用winsock2.0可直接修改源IP地址.以下是C++的代码.
直接在源IP字段加上随机IP就是IP欺骗了.
#include "stdafx.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include "mstcpip.h"
#pragma comment(lib,"ws2_32")
#define DEFAULT_DEST_PORT 139
#define DEST_HOST "192.168.5.109"
#define SEQ 0x28376839

typedef struct _iphdr
{
unsigned char h_lenver; //4位首部长度+4位IP版本号
unsigned char tos; //8位服务类型TOS
unsigned short total_len; //16位总长度(字节)
unsigned short ident; //16位标识
unsigned short frag_and_flags; //3位标志位
unsigned char ttl; //8位生存时间 TTL
unsigned char proto; //8位协议 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校验和
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HEADER;

typedef struct _tcphdr //定义TCP首部
{
USHORT th_sport; //16位源端口
USHORT th_dport; //16位目的端口
unsigned int th_seq; //32位序列号
unsigned int th_ack; //32位确认号
unsigned char th_lenres; //4位首部长度/6位保留字
unsigned char th_flag; //6位标志位
USHORT th_win; //16位窗口大小
USHORT th_sum; //16位校验和
USHORT th_urp; //16位紧急数据偏移量
}TCP_HEADER;

struct //定义TCP伪首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz;
char ptcl; //协议类型
unsigned short tcpl; //TCP长度
}psd_header;

SOCKET sockRaw = INVALID_SOCKET,
sockListen = INVALID_SOCKET;
struct sockaddr_in dest;

//SOCK错误处理程序
void CheckSockError(int iErrorCode, char *pErrorMsg)
{
if(iErrorCode==SOCKET_ERROR)
{
printf("%s Error:%d/n", pErrorMsg, GetLastError());
closesocket(sockRaw);
ExitProcess(-1);
}

}

//计算检验和
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;

while (size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}


//IP解包程序
int DecodeIPHeader(char *recvbuf, int bytes)
{
IP_HEADER *iphdr;
TCP_HEADER *tcphdr;
unsigned short iphdrlen;

iphdr = (IP_HEADER *)recvbuf;
iphdrlen = sizeof(unsigned long) * (iphdr->h_lenver & 0xf);
tcphdr = (TCP_HEADER*)(recvbuf + iphdrlen);

//是否来自目标IP
printf("%s/n",inet_ntoa(iphdr);
if(iphdr->sourceIP != dest.sin_addr.s_addr) return 0;

//序列号是否正确
//if((ntohl(tcphdr->th_ack) != (SEQ+1)) && (ntohl(tcphdr->th_ack) != SEQ)) return 0;

//RST/ACK - 无服务
if(tcphdr->th_flag == 20)
{
printf("./n");
return 1;
}

//SYN/ACK - 扫描到一个端口
if(tcphdr ->th_flag == 18)
{
printf("%d/n",ntohs(tcphdr->th_sport));
return 2;
}

return 1;
}

//主函数
int main(int argc,char **argv)
{
int iErrorCode;
int datasize;
struct hostent *hp;
IP_HEADER ip_header;
TCP_HEADER tcp_header;
char SendBuf[128]={0};
char RecvBuf[65535]={0};

//初始化SOCKET
WSADATA wsaData;
iErrorCode = WSAStartup(MAKEWORD(2,2),&wsaData);
CheckSockError(iErrorCode, "WSAStartup()");
sockRaw = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
CheckSockError(sockRaw, "socket()");
sockListen = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
CheckSockError(sockListen, "socket");

//设置IP头操作选项
BOOL bOpt = true;
iErrorCode = setsockopt(sockRaw,IPPROTO_IP,IP_HDRINCL,(char *)&bOpt,sizeof(bOpt));
CheckSockError(iErrorCode, "setsockopt()");

//获得本地IP
SOCKADDR_IN sa;unsigned char LocalName[256];

iErrorCode = gethostname((char*)LocalName,sizeof(LocalName)-1);
CheckSockError(iErrorCode, "gethostname()");
if((hp = gethostbyname((char*)LocalName)) == NULL)
{
CheckSockError(SOCKET_ERROR, "gethostbyname()");
}
memcpy(&sa.sin_addr.S_un.S_addr,hp->h_addr_list[0],hp->h_length);
sa.sin_family = AF_INET;
sa.sin_port = htons(7000);
iErrorCode = bind(sockListen, (PSOCKADDR)&sa, sizeof(sa));
CheckSockError(iErrorCode, "bind");

//设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包
DWORD dwBufferLen[10] ;
DWORD dwBufferInLen = 1 ;
DWORD dwBytesReturned = 0 ;
iErrorCode=WSAIoctl(sockListen, SIO_RCVALL,&dwBufferInLen, sizeof(dwBufferInLen),
&dwBufferLen, sizeof(dwBufferLen),&dwBytesReturned , NULL , NULL );
CheckSockError(iErrorCode, "Ioctl");

//获得目标主机IP
memset(&dest,0,sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(DEFAULT_DEST_PORT);
if((dest.sin_addr.s_addr = inet_addr(DEST_HOST)) == INADDR_NONE)
{
if((hp = gethostbyname(DEST_HOST)) != NULL)
{
memcpy(&(dest.sin_addr),hp->h_addr_list[0],hp->h_length);
dest.sin_family = hp->h_addrtype;
printf("dest.sin_addr = %s/n",inet_ntoa(dest.sin_addr));
}
else
{
CheckSockError(SOCKET_ERROR, "gethostbyname()");
}
}

//填充IP首部
ip_header.h_lenver=(4<<4 | sizeof(ip_header)/sizeof(unsigned long));
//高四位IP版本号,低四位首部长度
ip_header.total_len=htons(sizeof(IP_HEADER)+sizeof(TCP_HEADER)); //16位总长度(字节)
ip_header.ident=1; //16位标识
ip_header.frag_and_flags=0; //3位标志位
ip_header.ttl=128; //8位生存时间TTL
ip_header.proto=IPPROTO_TCP; //8位协议(TCP,UDP…)
ip_header.checksum=0; //16位IP首部校验和
ip_header.sourceIP=sa.sin_addr.s_addr; //32位源IP地址
ip_header.destIP=dest.sin_addr.s_addr; //32位目的IP地址

//填充TCP首部
tcp_header.th_sport=htons(7000); //源端口号
tcp_header.th_dport=htons(DEFAULT_DEST_PORT); //目的端口号
tcp_header.th_seq=htonl(SEQ); //SYN序列号
tcp_header.th_ack=0; //ACK序列号置为0
tcp_header.th_lenres=(sizeof(TCP_HEADER)/4<<4|0); //TCP长度和保留位
tcp_header.th_flag=2; //SYN 标志
tcp_header.th_win=htons(16384); //窗口大小
tcp_header.th_urp=0; //偏移
tcp_header.th_sum=0; //校验和

//填充TCP伪首部(用于计算校验和,并不真正发送)
psd_header.saddr=ip_header.sourceIP;
psd_header.daddr=ip_header.destIP;
psd_header.mbz=0;
psd_header.ptcl=IPPROTO_TCP;
psd_header.tcpl=htons(sizeof(tcp_header));

//计算TCP校验和,计算校验和时需要包括TCP pseudo header
memcpy(SendBuf,&psd_header,sizeof(psd_header));
memcpy(SendBuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header));
tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header));

//计算IP校验和
memcpy(SendBuf,&ip_header,sizeof(ip_header));
memcpy(SendBuf+sizeof(ip_header),&tcp_header,sizeof(tcp_header));
memset(SendBuf+sizeof(ip_header)+sizeof(tcp_header),0,4);
datasize=sizeof(ip_header)+sizeof(tcp_header);
ip_header.checksum=checksum((USHORT *)SendBuf,datasize);

//填充发送缓冲区
memcpy(SendBuf,&ip_header,sizeof(ip_header));

//发送TCP报文
iErrorCode=sendto(sockRaw,SendBuf,datasize,0,(struct sockaddr*) &dest,
sizeof(dest));
CheckSockError(iErrorCode, "sendto()");

//接收数据
DWORD timeout = 2000;
DWORD start = GetTickCount();
/*while(true)
{
//计时,2s超时
if((GetTickCount() - start) >= timeout) break;

memset(RecvBuf, 0, sizeof(RecvBuf));
//iErrorCode = recv(sockListen, RecvBuf, sizeof(RecvBuf), 0);
iErrorCode = recv(sockListen, RecvBuf, sizeof(RecvBuf), 0);
CheckSockError(iErrorCode, "recv");

if(DecodeIPHeader(RecvBuf,iErrorCode)) break;
}

//退出前清理
if(sockRaw != INVALID_SOCKET) closesocket(sockRaw);
WSACleanup();*/

while(true)
{
//计时,2s超时
if((GetTickCount() - start) >= timeout) break;

memset(RecvBuf, 0, sizeof(RecvBuf));
iErrorCode = recv(sockListen, RecvBuf, sizeof(RecvBuf), 0);
CheckSockError(iErrorCode, "recv");

if(int i = DecodeIPHeader(RecvBuf,iErrorCode))
{
if(i == 1) break;
tcp_header.th_flag=4; //RST 标志
//计算TCP校验和,计算校验和时需要包括TCP pseudo header
memcpy(SendBuf,&psd_header,sizeof(psd_header));
memcpy(SendBuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header));
tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header));

//计算IP校验和
memcpy(SendBuf,&ip_header,sizeof(ip_header));
memcpy(SendBuf+sizeof(ip_header),&tcp_header,sizeof(tcp_header));
memset(SendBuf+sizeof(ip_header)+sizeof(tcp_header),0,4);
datasize=sizeof(ip_header)+sizeof(tcp_header);
ip_header.checksum=checksum((USHORT *)S
 
我将前面那个发送udp数据的程序改为tcp了,单是有问题,老是发送失败。那位帮我瞧一下,错在那儿,我估计是在计算tcp头的长度和校验时有问题.源码如下:
unit senddata;
interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, OleCtrls, Registry;

Const
SrcIP = '202.108.249.138';//发送方IP地址
SrcPort = 3033; //发送方端口
DestIP = '202.108.147.001'; //目的IP地址
DestPort = 80; //目的端口

SEQ=0;
Max_Message = 4068;
Max_Packet = 4096;


type

TPacketBuffer = Array[0..Max_Packet-1] of byte;

TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Memo2: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure SendIt;
end;

// IP 头
type
T_IP_Header = record
ip_verlen : Byte;
ip_tos : Byte;
ip_totallength : Word;
ip_id : Word;
ip_offset : Word;
ip_ttl : Byte;
ip_protocol : Byte;
ip_checksum : Word;
ip_srcaddr : LongWord;
ip_destaddr : LongWord;
end;

// UDP 头
//tcp头
type t_tcp_header=record //定义TCP首部
TCP_Sport :word; //16位源端口
TCP_Dport :word; //16位目的端口
th_seq :longword; //32位序列号
th_ack :longword; //32位确认号
th_lenres :byte; //4位首部长度/6位保留字
th_flag :char; //6位标志位
th_win :word; //16位窗口大小
th_sum :word; //16位校验和
th_urp :word; //16位紧急数据偏移量
end;
type tpsd_header=record
saddr:longword;//源地址
daddr:longword;//目的地址
mbz:char; //
ptcl:char;//协议类型
tcpl:word;//tcp长度
end;
// 一些 Winsock 2 的类型声明
u_char = Char;
u_short = Word;
u_int = Integer;
u_long = Longint;

SunB = packed record
s_b1, s_b2, s_b3, s_b4: u_char;
end;
SunW = packed record
s_w1, s_w2: u_short;
end;
in_addr = record
case integer of
0: (S_un_b: SunB);
1: (S_un_w: SunW);
2: (S_addr: u_long);
end;
TInAddr = in_addr;
Sockaddr_in = record
case Integer of
0: (sin_family: u_short;
sin_port: u_short;
sin_addr: TInAddr;
sin_zero: array[0..7] of Char);
1: (sa_family: u_short;
sa_data: array[0..13] of Char)
end;
TSockAddr = Sockaddr_in;
TSocket = u_int;

const
WSADESCRIPTION_LEN = 256;
WSASYS_STATUS_LEN = 128;

type
PWSAData = ^TWSAData;
WSAData = record // WSDATA
wVersion: Word;
wHighVersion: Word;
szDescription: array[0..WSADESCRIPTION_LEN] of Char;
szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char;
iMaxSockets: Word;
iMaxtcpDg: Word;
lpVendorInfo: PChar;
end;
TWSAData = WSAData;

//定义一些 winsock 2 函数
function closesocket(s: TSocket): Integer; stdcall;
function socket(af, Struct, protocol: Integer): TSocket; stdcall;
function sendto(s: TSocket; var Buf; len, flags: Integer; var addrto: TSockAddr;
tolen: Integer): Integer; stdcall;{}
function setsockopt(s: TSocket; level, optname: Integer; optval: PChar;
optlen: Integer): Integer; stdcall;
function inet_addr(cp: PChar): u_long; stdcall; {PInAddr;} { TInAddr }
function htons(hostshort: u_short): u_short; stdcall;
function htonl(hostshort: u_short):u_short;stdcall;
function WSAGetLastError: Integer; stdcall;
function WSAStartup(wVersionRequired: word; var WSData: TWSAData): Integer; stdcall;
function WSACleanup: Integer; stdcall;

const
AF_INET = 2; // internetwork: UDP, TCP, etc.

IP_HDRINCL = 2; // IP Header Include

SOCK_RAW = 3; // raw-protocol interface

IPPROTO_IP = 0; // dummy for IP
IPPROTO_TCP = 6; // tcp
IPPROTO_UDP = 17; // user datagram protocol
IPPROTO_RAW = 255; // raw IP packet

INVALID_SOCKET = TSocket(NOT(0));
SOCKET_ERROR = -1;

var
Form1: TForm1;

implementation

// Import Winsock 2 functions
const WinSocket = 'WS2_32.DLL';

function closesocket; external winsocket name 'closesocket';
function socket; external winsocket name 'socket';
function sendto; external winsocket name 'sendto';
function setsockopt; external winsocket name 'setsockopt';
function inet_addr; external winsocket name 'inet_addr';
function htons; external winsocket name 'htons';
function htonl; external winsocket name 'htonl';
function WSAGetLastError; external winsocket name 'WSAGetLastError';
function WSAStartup; external winsocket name 'WSAStartup';
function WSACleanup; external winsocket name 'WSACleanup';


{$R *.DFM}

function CheckSum(Var Buffer; Size : integer) : Word;
type
TWordArray = Array[0..1] of Word;
var
ChkSum : LongWord;
i : Integer;
begin
ChkSum := 0;
i := 0;
While Size > 1 do begin
ChkSum := ChkSum + TWordArray(Buffer);
inc(i);
Size := Size - SizeOf(Word);
end;

if Size=1 then ChkSum := ChkSum + Byte(TWordArray(Buffer));

ChkSum := (ChkSum shr 16) + (ChkSum and $FFFF);
ChkSum := ChkSum + (Chksum shr 16);

Result := Word(ChkSum);
end;


procedure BuildHeaders(
FromIP : String;
iFromPort : Word;
ToIP : String;
iToPort : Word;
senddata : pchar;
Var Buf : TPacketBuffer;
Var remote : TSockAddr;
Var iTotalSize : Word
);
Var

dwFromIP : LongWord;
dwToIP : LongWord;

iIPVersion : Word;
iIPSize : Word;
ipHdr : T_IP_Header;
tcphdr:t_tcp_header;
psdhdr:tpsd_header;

itcpSize : Word;
itcpChecksumSize : Word;
cksum : Word;

Ptr : ^Byte;

procedure IncPtr(Value : Integer);
begin
ptr := pointer(integer(ptr) + Value);
end;

begin
// Convert ip address'ss

dwFromIP := inet_Addr(PChar(FromIP));
dwToIP := inet_Addr(PChar(ToIP));

// 初始化 IP 头
//
iTotalSize := sizeof(ipHdr) + sizeof(tcpHdr) + sizeof(senddata);

iIPVersion := 4;
iIPSize := sizeof(ipHdr) div sizeof(LongWord);

ipHdr.ip_verlen := (iIPVersion shl 4) or iIPSize;
ipHdr.ip_tos := 0; // IP type of service
ipHdr.ip_totallength := htons(iTotalSize); // Total packet len
ipHdr.ip_id := 0; // Unique identifier: set to 0
ipHdr.ip_offset := 0; // Fragment offset field
ipHdr.ip_ttl := 128; // Time to live
ipHdr.ip_protocol := $11; // Protocol(UDP)
ipHdr.ip_checksum := 0 ; // IP checksum
ipHdr.ip_srcaddr := dwFromIP; // Source address
ipHdr.ip_destaddr := dwToIP; // Destination address
// 初始化 tcp 头
tcphdr.TCP_Sport:=htons(SrcPort);
tcphdr.TCP_Dport:=htons(DestPort);
tcphdr.th_seq:=htonl(SEQ);
tcphdr.th_ack:=0;
tcphdr.th_lenres:=sizeof(tcphdr)+sizeof(senddata);
tcphdr.th_flag:='2';
tcphdr.th_win:=htons(16384);
tcphdr.th_urp:=0;
tcphdr.th_sum:=0;

//填充tcp伪首部(用于计算校验和,并不真正发送)
psdhdr.saddr:=iphdr.ip_srcaddr;
psdhdr.daddr:=iphdr.ip_destaddr;
psdhdr.mbz:=char(0);
psdhdr.ptcl:=char(IPPROTO_TCP);
psdhdr.tcpl:=htons(sizeof(tcphdr));
//计算tcp校验和,计算校验和时需要包括tcp pseudo header
itcpSize := sizeof(tcpHdr) + sizeof(senddata);
{udpHdr.src_portno := htons(iFromPort) ;
udpHdr.dst_portno := htons(iToPort) ;
udpHdr.udp_length := htons(iUdpSize) ;
udpHdr.udp_checksum := 0 ;
}
itcpChecksumSize := 0;

ptr := @buf[0];
FillChar(Buf, SizeOf(Buf), 0);

Move(ipHdr.ip_srcaddr, ptr^, SizeOf(ipHdr.ip_srcaddr));
IncPtr(SizeOf(ipHdr.ip_srcaddr));

itcpChecksumSize := itcpChecksumSize + sizeof(ipHdr.ip_srcaddr);

Move(ipHdr.ip_destaddr, ptr^, SizeOf(ipHdr.ip_destaddr));
IncPtr(SizeOf(ipHdr.ip_destaddr));

itcpChecksumSize := itcpChecksumSize + sizeof(ipHdr.ip_destaddr);

IncPtr(1);

Inc(itcpChecksumSize);

Move(ipHdr.ip_protocol, ptr^, sizeof(ipHdr.ip_protocol));
IncPtr(sizeof(ipHdr.ip_protocol));
itcpChecksumSize := itcpChecksumSize + sizeof(ipHdr.ip_protocol);


Move(itcpSize, ptr^, sizeof(itcpSize));
IncPtr(sizeof(itcpSize));
itcpChecksumSize := itcpChecksumSize + sizeof(itcpSize);

move(tcphdr, ptr^, sizeof(tcphdr));
IncPtr(sizeof(tcphdr));
itcpChecksumSize := itcpCheckSumSize + sizeof(tcpHdr);

Move(senddata[1], ptr^, sizeof(senddata));
IncPtr(sizeof(senddata));

itcpChecksumSize := itcpChecksumSize + length(senddata);

cksum := checksum(buf, itcpChecksumSize);
tcpHdr.th_sum:= cksum;

//
// 现在 IP 和 tcp 头OK了,我们可以把它发送出去。
//
FillChar(Buf, SizeOf(Buf), 0);
Ptr := @Buf[0];

Move(ipHdr, ptr^, SizeOf(ipHdr)); IncPtr(SizeOf(ipHdr));
Move(tcpHdr, ptr^, SizeOf(tcpHdr)); IncPtr(SizeOf(tcpHdr));
Move(senddata[1], ptr^, sizeof(senddata));


remote.sin_family := AF_INET;
remote.sin_port := htons(iToPort);
remote.sin_addr.s_addr := dwToIP;
end;

procedure TForm1.SendIt;
Var
sh : TSocket;
bOpt : Integer;
ret : Integer;
Buf : TPacketBuffer;
Remote : TSockAddr;
Local : TSockAddr;
iTotalSize : Word;
wsdata : TWSAdata;
str:widestring;
begin
// Startup Winsock 2
ret := WSAStartup($0002, wsdata);
if ret<>0 then begin
memo1.lines.add('WSA Startup failed.');
exit;
end;
with memo1.lines do begin
add('WSA Startup:');
add('Desc.: '+wsData.szDescription);
add('Status: '+wsData.szSystemStatus);
end;

try
// Create socket
sh := Socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
if (sh = INVALID_SOCKET) then begin
memo1.lines.add('Socket() failed: '+IntToStr(WSAGetLastError));
exit;
end;
Memo1.lines.add('Socket Handle = '+IntToStr(sh));

// Option: Header Include
bOpt := 1;
ret := SetSockOpt(sh, IPPROTO_IP, IP_HDRINCL, @bOpt, SizeOf(bOpt));
if ret = SOCKET_ERROR then begin
Memo1.lines.add('setsockopt(IP_HDRINCL) failed: '+IntToStr(WSAGetLastError));
exit;
end;
memo2.Lines.LoadFromFile('1.txt');
// Build the packet
BuildHeaders( SrcIP, SrcPort,
DestIP, DestPort,
pchar(memo2.text),
Buf, Remote, iTotalSize );

// Send the packet
ret := SendTo(sh, buf, iTotalSize, 0, Remote, SizeOf(Remote));
if ret = SOCKET_ERROR then
Memo1.Lines.Add('sendto() failed: '+IntToStr(WSAGetLastError))
else
Memo1.Lines.Add('send '+IntToStr(ret)+' bytes.');

// Close socket
CloseSocket(sh);
finally
// Close Winsock 2
WSACleanup;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
SendIt;
end;

end.
 
真没人帮忙吗
 
楼主真辛苦,可惜我不会.楼主搞这个应该明白user-agent方式吧.我想实现的是delphi程序在访问web页面的时候能够自己作http头,加些验证信息到header里面.楼主,您说可以实现么
 
如果我没有记错的话,修改TCP的IP头是可以用SetSockOpt来设置的!
 
我也听说过,可是到底是如何改的呢
 
后退
顶部