線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2201
推到 Plurk!
推到 Facebook!

實現IP地址的隱藏

 
ddy
站務副站長


發表:262
回覆:2105
積分:1169
註冊:2002-07-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2002-12-04 01:35:41 IP:61.59.xxx.xxx 未訂閱
一、前言   本文主要介紹如何在程式中實現IP地址的隱藏。其實這篇東西不算我寫的。其中《IP頭結構》部分我懶得打字,故複製、粘貼了孤獨劍客的文章,先說聲謝謝!代碼部分參考了外國程式xes寫的一個程式。所以這只是學習過程中的一個副產品。既然程式已經做好了,就順便放上來跟大家一起交流,共同提高吧。本文只不過想說明一下IP資料的結構和發送機制。如果有人把它改為惡意IP攻擊工具,後果自負。     二、IP頭結構       我們知道,TCP/IP網路資料全部是通過封裝在IP資料包中在Internet網上傳送的,也就是封裝建立起一個包含IP頭和資料的IP資料報。一般來說,網路軟體總是以多個32位字產生IP頭,即使必須用附加的0填充IP頭。IP頭包含了傳輸IP資料包中封裝資料的所有必要資訊。IP頭的資料結構和描述如下:     成員 長度(Bit) 描述  Version 4 IP頭的版本號,目前是IPv4,最新是IPv6  Header Length 4 IP頭的長度,若沒有特殊選擇,IP頭總是20位元組長  Type of Service 8 服務類型,定義了資料傳輸的優先順序、延遲、吞吐量和可靠性等特性  Total Packet Length 16 IP包的長度,若沒有特殊選項,一般為20位元組長  Identification 16 IP包標識,主機使用它唯一確定每個發送的資料報  Flag 3 IP資料分割標誌  Fragment Offset 13 IP資料分割偏移  Time to Live 8 資料報在網路上的存活時間,每通過一個路由器,該數值減一  Protocol 8 TCP/IP協定類型,比如:ICMP為1,IGMP為2,TCP為6,UDP為17等  Header Checksum 16 頭部核對總和  Source IP Address 32 源IP地址  Destination IP Address 32 目的IP地址  Other ? 其他選項  Data ? 資料       實現自己定義的IP頭是一件非常有意義的事情,比如,通過改變IP頭裏的TOS的優先順序和TTL,你可以使自己的資料包有更強的傳輸能力和壽命,通過修改IP頭裏的源IP地址就可以隱藏自己機器的IP地址等等。象著名攻擊程式“淚滴TearDrop”就是通過故意製造系統不能處理的分片IP包而實現的,還有SYN Flooder和UDP Flooder就是通過產生隨機源IP實現欺騙的。     三、實現原理       一般來說,自定義IP頭是通過使用socket的庫函數setsockopt()的選項IP_HDRINCL來實現的,儘管這在unix和linux平臺上很容易實現,但遺憾的是在Windows平臺的Winsock1.1和Winsock2.0函數庫裏setsockopt()不支援IP_HDRINCL選項,所以在Windows 9x/NT裏是無法通過Winsock函數庫來實現IP頭自定義的,當然可以通過編寫虛擬設備驅動程式來實現,不過比較複雜,但Windows 2000的出現打破了這種局面,Windows2000的Winsock2.2函數庫裏全面支援setsockopt()的選項IP_HDRINCL,使得我們輕鬆就可以實現自定義的IP頭。實現方法如下:     四、代碼部分 
 
{ 
1. 本程式只能運行於 Window 2000. 
2. 你必須有 Administrator 許可權. 
3. 程式需要用到一個 button 和一個 memo. 
----------------------------------------------------------------------
運行程式前,請根據自己的需要改變 SrcIP、SrcPort、DestIP和DestPort的值 
----------------------------------------------------------------------
如果你看不懂以下代碼,最好不要去運行它。 
----------------------------------------------------------------------
} 
unit Unit1; 
interface 
uses 
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
StdCtrls, OleCtrls, Registry;     Const 
SrcIP = '123.123.123.1';//發送方IP地址 
SrcPort = 1234;         file://發送方埠 
DestIP = '127.0.0.2';   file://目的IP地址 
DestPort = 4321;        file://目的埠     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 頭 
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 頭 
Type 
T_UDP_Header = record 
src_portno : Word; 
dst_portno : Word; 
udp_length : Word; 
udp_checksum : Word; 
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; 
iMaxUdpDg: Word; 
lpVendorInfo: PChar; 
end; 
TWSAData = WSAData;     file://定義一些 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 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(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));     // 初始化 IP 頭 
// 
iTotalSize := sizeof(ipHdr)   sizeof(udpHdr)   length(strMessage);     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 
// 
// 初始化 UDP 頭 
// 
iUdpSize := sizeof(udpHdr)   length(strMessage);     udpHdr.src_portno := htons(iFromPort) ; 
udpHdr.dst_portno := htons(iToPort) ; 
udpHdr.udp_length := htons(iUdpSize) ; 
udpHdr.udp_checksum := 0 ;     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;     // 
// 現在 IP 和 UDP 頭OK了,我們可以把它發送出去。 
// 
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));     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.
--【KTop SNG新聞現場】--記者:ddy----------------------------------------- 請各位市民做好資源回收與垃圾分類,讓不良標題與不當發言在KTop 市消失 -------------------------------------------------------------------------
zw
一般會員


發表:21
回覆:25
積分:9
註冊:2003-04-28

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-05-23 17:37:44 IP:61.176.xxx.xxx 未訂閱
ddy你好! 这篇文章给出的代码编译时 ChkSum := ChkSum TWordArray(Buffer); if Size=1 then ChkSum := ChkSum Byte(TWordArray(Buffer)); 这两行有错,请问如何解决?屏蔽掉这两行并编译时MEMO显示DESC:WINSOCK2.0,请问是否此WINSOCK版本不支持代码中的函数(但我的系统是WIN2K呀),另外可否讲解一下给出的代码具体可利用在何处(仅仅是隐藏IP做攻击用吗?) 希望能够得到指点,谢谢你!!
zw
一般會員


發表:21
回覆:25
積分:9
註冊:2003-04-28

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-05-23 17:38:33 IP:61.176.xxx.xxx 未訂閱
ddy你好! 这篇文章给出的代码编译时 ChkSum := ChkSum TWordArray(Buffer); if Size=1 then ChkSum := ChkSum Byte(TWordArray(Buffer)); 这两行有错,请问如何解决?屏蔽掉这两行并编译时MEMO显示DESC:WINSOCK2.0,请问是否此WINSOCK版本不支持代码中的函数(但我的系统是WIN2K呀),另外可否讲解一下给出的代码具体可利用在何处(仅仅是隐藏IP做攻击用吗?) 希望能够得到指点,谢谢你!!
系統時間:2024-05-01 10:59:47
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!