吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3939|回复: 3
收起左侧

[会员申请] 申请ID:win32的无君

[复制链接]
吾爱游客  发表于 2020-5-25 19:07
1.申请ID:win32的无君
2.个人邮箱: wujunxxw@126.com
3.本科大一学生,原创首发文章:使用winpcap遍历网络设备,并在链路层直接发送TCP/SYN包

winpcap是一个功能强大的API,它为我们提供了直接访问计算机网络底层的能力。最近因为某些特殊需求,要发送一些篡改过的TCP/SYN包,首先想到的就是使用winpcap来实现。现在我已经完成了这个项目,那就趁热打铁给大家分享一下我的经验与方法吧。
如果要完整地讲解winpcap,以一篇帖子的篇幅是远远不够的。下面只以最简洁扼要的方式,讲述实现这个功能(发包)所要明白的知识。
本文仅供学习研究使用,禁止用作非法用途,如有不妥之处请告之,本人会在第一时间修改删除。

1、winpcap环境的建立
                  winpcap官网地址:https://www.winpcap.org/
                  首先,我们要从官网上下载两个zip,分别是 winpcap的驱动程序winpcap SDK。前者解压直接安装,后者包含了编译winpcap程序所必需的头文件、库文件和一些程序示例。
                  安装完驱动程序后,我们还得将 头文件 和 库文件 放置在IDE正确的路径,否则就include不到这些函数了。我使用的是VS2019,路径可以在项目->属性->VC++目录中找到。
                                                                                           55.png

                  双击“包含目录”条目,会给出这个目录在你计算机内的绝对路径。把sdk中的头文件拖动到这个路径下就可以啦。库文件同理。
                    注意:winpcap只支持32位程序。将       7MKQKORZD9SXM3%]DNPS57S.png        这个东西设置为x86,以避免可能出现的问题。

2、遍历网络设备,打开一个接口
                   在传输什么东西之前,winpcap必须使用某个网络设备的名称(一串最长为512的char字符串)来打开这个网络设备的接口。
                   这串字符当然不建议手动输入,我们可以使用pcap_findalldevs();来遍历系统上的所有网络设备的属性。
                   这个函数通过指针的方式,将系统上第一个网络设备的属性传递到一个名为pcap_if_t的结构里。
                   然后通过pcap_if_t->next这种调用,我们又可以找到下一个网络设备的pcap_if_t。这样就实现了设备的遍历。直到pcap_if_t->next为NULL时,那么它就是系统上最后一个设备了。
                   当遍历完成后,我们使用pcap_freealldevs();关掉winpcap对网络设备的遍历。
                   话不多说,我们直接上代码。
[C++] 纯文本查看 复制代码
struct DEVS_NAME
{
	char szDevName[512];
};
int GetAllDevs(DEVS_NAME devsList[])
{        int nDevsNum = 0;
        pcap_if_t* alldevs;
        char errbuf[PCAP_ERRBUF_SIZE];
        if (pcap_findalldevs(&alldevs, errbuf) == -1)
        {
                return -1;
                printf("error in pcap_findalldevs_ex: %s\n", errbuf);
        }
        for (pcap_if_t* d = alldevs; d != NULL; d = d->next)
        {
                strcpy(devsList[nDevsNum].szDevName, d->name);
                nDevsNum++;
        }
        pcap_freealldevs(alldevs);

        return nDevsNum;
}

                   这个自定义函数能自动对系统上所有网络设备进行遍历,并将它们的名称通过指针输出到一个自定义结构中。返回值为系统上网络设备的数量。

                   然后我们可以使用pcap_open_live();函数打开某个设备。代码示例:
[C++] 纯文本查看 复制代码
char szError[PCAP_ERRBUF_SIZE];
pcap_t* handleD = pcap_open_live(szDevName, 65536, 1, 1000, szError);

                   pcap_open_live();接受5个参数,分别是设备名称、接口传输的最大字节数、是否处于混杂模式、超时时间(毫秒为单位),以及错误警告文本。
                   如果设备打开成功,这个函数将返回一个pcap_t句柄。否则返回NULL。


3、发送第一个TCP包
                    我们使用wireshark抓一个网站的TCP/SYN包,如图
                                                                   OG(S$A8)S9L7B5LLLRGE{4K.png
                    我们先尝试用自己的代码把这个包原封不动地发出去。
                    将TCP包的全部原文以16进制的形式复制下来,然后粘贴到我们的程序里,使用pcap_sendpacket();这个函数发包。代码如下:
[C++] 纯文本查看 复制代码
byte packet[66] = { 
0xb8,0xf8,0x83,0xbf,0xc5,0x7c,0x84,0x3a,
0x4b,0x6d,0xd3,0x88,0x08,0x00,0x45,0x00,
0x00,0x34,0x73,0xb4,0x40,0x00,0x80,0x06,
0x1e,0xfd,0xc0,0xa8,0x00,0x73,0x68,0x81,
0x3e,0x76,0x1a,0x1e,0x01,0xbb,0x84,0x93,
0x20,0x10,0x00,0x00,0x00,0x00,0x80,0x02,
0x20,0x00,0x26,0x87,0x00,0x00,0x02,0x04,
0x05,0xb4,0x01,0x03,0x03,0x02,0x01,0x01,
0x04,0x02 };
pcap_sendpacket(handleD, packet, sizeof(packet));

                    pcap_sendpacket();的三个参数分别为打开的设备的句柄、要发送的包、包的大小。
                    数据包将不经过任何加工,直接由链路层发送到路由器上。
                    用wireshark开始抓包,并运行这个程序。
                                                               79YO[GK4SB1DG6PDH99I(PU.png
                   我们看到程序已经发包成功了,并收到了这个网站的回复。


4、IP头、TCP头、两个校验和
                   由于篇幅所限,关于TCP/IP协议,本文不进行过多赘述。想要对它们深入了解的朋友可以在互联网上收集资料,或等我另起一篇文章对此进行详细解释。
                   总而言之,我们从计算机发出去的TCP包由“以太网报头”、“IP报头”、“TCP报头”三个部分组成。为了防止长途传输中可能的错误,“IP报头”、“TCP报头”都是要计算"校验和"的。既然我们要篡改TCP包中的数据,那么校验和也必须得重新计算了,否则网站那边的路由器一算,诶,校验和不对,这个包就直接被丢掉了。
                   校验和的算法:
                                      1.把校验和字段置为0。
                                      2.把整个报文分割成16bits(4Bytes)的小块。
                                      3.将这些小块求和,得到一个16bits+的数。
                                      4.将16bit以上的位加回16bit里面。
                                      5.所得数求反码。
                   计算代码如下:
[C++] 纯文本查看 复制代码
unsigned short CheckSum(unsigned short packet[], int size)
{
	unsigned long cksum = 0;
	while (size > 1)
	{
		cksum += *packet++;
		size -= sizeof(USHORT);
	}
	if (size)
	{
		cksum += *(UCHAR*)packet;
	}
	cksum = (cksum >> 16) + (cksum & 0xFFFF);
	cksum += (cksum >> 16);

	return (USHORT)(~cksum);
}

                   这个代码可以计算从输入的指针开始、到长度为size的数列的校验和。





(小部分代码摘录并修改自https://github.com/wangzhenshan3/SYN-Flood/blob/master/SYN-Flood.cpp,感谢原作者)

p.s:第一次写教程,就发在了这个大牛林立的论坛上,令我不胜惶恐。若有谬误之处,还请大神指出,本人将在第一时间修改。

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

anandyuan 发表于 2020-5-26 17:38
楼主厉害
Hmily 发表于 2020-5-29 14:56

抱歉,未能达到申请要求,申请不通过,可以关注论坛官方微信(吾爱破解论坛),等待开放注册通知。
吾爱游客  发表于 2020-5-29 18:19
呃,好像有点急功近利了。那我改天把IP、TCP的分段,以及伪首部,还有网络防火墙给说一说吧
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 12:59

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表