實現IP地址的隱藏 |
|
ddy
站務副站長 發表:262 回覆:2105 積分:1169 註冊:2002-07-13 發送簡訊給我 |
一、前言
本文主要介紹如何在程式中實現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 發送簡訊給我 |
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 發送簡訊給我 |
ddy你好!
这篇文章给出的代码编译时
ChkSum := ChkSum TWordArray(Buffer);
if Size=1 then ChkSum := ChkSum Byte(TWordArray(Buffer));
这两行有错,请问如何解决?屏蔽掉这两行并编译时MEMO显示DESC:WINSOCK2.0,请问是否此WINSOCK版本不支持代码中的函数(但我的系统是WIN2K呀),另外可否讲解一下给出的代码具体可利用在何处(仅仅是隐藏IP做攻击用吗?)
希望能够得到指点,谢谢你!!
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |