有没有windows下c语言实现udp协议的代码
Windows下C语言的Socket编程例子(TCP和UDP)
一。 TCP
server端:
复制代码
1 #include "stdafx.h"
2 #include stdio.h
3 #include winsock2.h
4
5 #pragma comment(lib,"ws2_32.lib")
6
7 int main(int argc, char* argv[])
8 {
9 //初始化WSA
10 WORD sockVersion = MAKEWORD(2,2);
11 WSADATA wsaData;
12 if(WSAStartup(sockVersion, wsaData)!=0)
13 {
14 return 0;
15 }
16
17 //创建套接字
18 SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
19 if(slisten == INVALID_SOCKET)
20 {
21 printf("socket error !");
22 return 0;
23 }
24
25 //绑定IP和端口
26 sockaddr_in sin;
27 sin.sin_family = AF_INET;
28 sin.sin_port = htons(8888);
29 sin.sin_addr.S_un.S_addr = INADDR_ANY;
30 if(bind(slisten, (LPSOCKADDR)sin, sizeof(sin)) == SOCKET_ERROR)
31 {
32 printf("bind error !");
33 }
34
35 //开始监听
36 if(listen(slisten, 5) == SOCKET_ERROR)
37 {
38 printf("listen error !");
39 return 0;
40 }
41
42 //循环接收数据
43 SOCKET sClient;
44 sockaddr_in remoteAddr;
45 int nAddrlen = sizeof(remoteAddr);
46 char revData[255];
47 while (true)
48 {
49 printf("等待连接...\n");
50 sClient = accept(slisten, (SOCKADDR *)remoteAddr, nAddrlen);
51 if(sClient == INVALID_SOCKET)
52 {
53 printf("accept error !");
54 continue;
55 }
56 printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));
57
58 //接收数据
59 int ret = recv(sClient, revData, 255, 0);
60 if(ret 0)
61 {
62 revData[ret] = 0x00;
63 printf(revData);
64 }
65
66 //发送数据
67 char * sendData = "你好,TCP客户端!\n";
68 send(sClient, sendData, strlen(sendData), 0);
69 closesocket(sClient);
70 }
71
72 closesocket(slisten);
73 WSACleanup();
74 return 0;
75 }
复制代码
client端:
复制代码
1 #include "stdafx.h"
2 #include WINSOCK2.H
3 #include STDIO.H
4
5 #pragma comment(lib,"ws2_32.lib")
6
7
8 int main(int argc, char* argv[])
9 {
10 WORD sockVersion = MAKEWORD(2,2);
11 WSADATA data;
12 if(WSAStartup(sockVersion, data) != 0)
13 {
14 return 0;
15 }
16
17 SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
18 if(sclient == INVALID_SOCKET)
19 {
20 printf("invalid socket !");
21 return 0;
22 }
23
24 sockaddr_in serAddr;
25 serAddr.sin_family = AF_INET;
26 serAddr.sin_port = htons(8888);
27 serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
28 if (connect(sclient, (sockaddr *)serAddr, sizeof(serAddr)) == SOCKET_ERROR)
29 {
30 printf("connect error !");
31 closesocket(sclient);
32 return 0;
33 }
34 char * sendData = "你好,TCP服务端,我是客户端!\n";
35 send(sclient, sendData, strlen(sendData), 0);
36
37 char recData[255];
38 int ret = recv(sclient, recData, 255, 0);
39 if(ret 0)
40 {
41 recData[ret] = 0x00;
42 printf(recData);
43 }
44 closesocket(sclient);
45 WSACleanup();
46 return 0;
47 }
复制代码
二. UDP
SERVER 端
复制代码
1 #include "stdafx.h"
2 #include stdio.h
3 #include winsock2.h
4
5 #pragma comment(lib, "ws2_32.lib")
6
7 int main(int argc, char* argv[])
8 {
9 WSADATA wsaData;
10 WORD sockVersion = MAKEWORD(2,2);
11 if(WSAStartup(sockVersion, wsaData) != 0)
12 {
13 return 0;
14 }
15
16 SOCKET serSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
17 if(serSocket == INVALID_SOCKET)
18 {
19 printf("socket error !");
20 return 0;
21 }
22
23 sockaddr_in serAddr;
24 serAddr.sin_family = AF_INET;
25 serAddr.sin_port = htons(8888);
26 serAddr.sin_addr.S_un.S_addr = INADDR_ANY;
27 if(bind(serSocket, (sockaddr *)serAddr, sizeof(serAddr)) == SOCKET_ERROR)
28 {
29 printf("bind error !");
30 closesocket(serSocket);
31 return 0;
32 }
33
34 sockaddr_in remoteAddr;
35 int nAddrLen = sizeof(remoteAddr);
36 while (true)
37 {
38 char recvData[255];
39 int ret = recvfrom(serSocket, recvData, 255, 0, (sockaddr *)remoteAddr, nAddrLen);
40 if (ret 0)
41 {
42 recvData[ret] = 0x00;
43 printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));
44 printf(recvData);
45 }
46
47 char * sendData = "一个来自服务端的UDP数据包\n";
48 sendto(serSocket, sendData, strlen(sendData), 0, (sockaddr *)remoteAddr, nAddrLen);
49
50 }
51 closesocket(serSocket);
52 WSACleanup();
53 return 0;
54 }
复制代码
CLIENT 端
复制代码
1 #include "stdafx.h"
2 #include stdio.h
3 #include winsock2.h
4
5 #pragma comment(lib, "ws2_32.lib")
6
7 int main(int argc, char* argv[])
8 {
9 WORD socketVersion = MAKEWORD(2,2);
10 WSADATA wsaData;
11 if(WSAStartup(socketVersion, wsaData) != 0)
12 {
13 return 0;
14 }
15 SOCKET sclient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
16
17 sockaddr_in sin;
18 sin.sin_family = AF_INET;
19 sin.sin_port = htons(8888);
20 sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
21 int len = sizeof(sin);
22
23 char * sendData = "来自客户端的数据包.\n";
24 sendto(sclient, sendData, strlen(sendData), 0, (sockaddr *)sin, len);
25
26 char recvData[255];
27 int ret = recvfrom(sclient, recvData, 255, 0, (sockaddr *)sin, len);
28 if(ret 0)
29 {
30 recvData[ret] = 0x00;
31 printf(recvData);
32 }
33
34 closesocket(sclient);
35 WSACleanup();
36 return 0;
37 }
渗透测试之端口扫描
端口扫描:端口对应网络服务及应用端程序
服务端程序的漏洞通过端口攻入
发现开放的端口
更具体的攻击面
UDP端口扫描:
如果收到ICMP端口不可达,表示端口关闭
如果没有收到回包,则证明端口是开放的
和三层扫描IP刚好相反
Scapy端口开发扫描
命令:sr1(IP(dst="192.168.45.129")/UDP(dport=53),timeout=1,verbose=1)
nmap -sU 192.168.45.129
TCP扫描:基于连接的协议
三次握手:基于正常的三次握手发现目标是否在线
隐蔽扫描:发送不完整的数据包,不建立完整的连接,如ACK包,SYN包,不会在应用层访问,
僵尸扫描:不和目标系统产生交互,极为隐蔽
全连接扫描:建立完整的三次握手
所有的TCP扫描方式都是基于三次握手的变化来判断目标系统端口状态
隐蔽扫描:发送SYN数据包,如果收到对方发来的ACK数据包,证明其在线,不与其建立完整的三次握手连接,在应用层日志内不记录扫描行为,十分隐蔽,网络层审计会被发现迹象
僵尸扫描:是一种极其隐蔽的扫描方式,实施条件苛刻,对于扫描发起方和被扫描方之间,必须是需要实现地址伪造,必须是僵尸机(指的是闲置系统,并且系统使用递增的IPID)早期的win xp,win 2000都是递增的IPID,如今的LINUX,WINDOWS都是随机产生的IPID
1,扫描者向僵尸机发送SYN+ACY,僵尸机判断未进行三次握手,所以返回RST包,在RST数据包内有一个IPID,值记为X,那么扫描者就会知道被扫描者的IPID
2,扫描者向目标服务器发送SYN数据包,并且伪装源地址为僵尸机,如果目标服务器端口开放,那么就会向僵尸机发送SYN+ACK数据包,那么僵尸机也会发送RST数据包,那么其IPID就是X+1(因为僵尸机足够空闲,这个就为其收到的第二个数据包)
3,扫描者再向僵尸机发送SYN+ACK,那么僵尸机再次发送RST数据包,IPID为X+2,如果扫描者收到僵尸机的IPID为X+2,那么就可以判断目标服务器端口开放
使用scapy发送数据包:首先开启三台虚拟机,
kali虚拟机:192.168.45.128
Linux虚拟机:192.168.45.129
windows虚拟机:192.168.45.132
发送SYN数据包:
通过抓包可以查看kali给linux发送syn数据包
linux虚拟机返回Kali虚拟机SYN+ACK数据包
kali系统并不知道使用者发送了SYN包,而其莫名其妙收到了SYN+ACK数据包,便会发RST包断开连接
也可以使用下列该命令查看收到的数据包的信息,收到对方相应的SYN+ACK数据包,scapy默认从本机的80端口往目标系统的20号端口发送,当然也可以修改
如果向目标系统发送一个 随机端口:
通过抓包的获得:1,kali向linux发送SYN数据包,目标端口23456,
2,Linux系统由自己的23456端口向kali系统的20号端口返回RST+ACK数据包,表示系统端口未开放会话结束
使用python脚本去进行scapy扫描
nmap做隐蔽端口扫描:
nmap -sS 192.168.45.129 -p 80,21,110,443 #扫描固定的端口
nmap -sS 192.168.45.129 -p 1-65535 --open #扫描该IP地址下1-65535端口扫描,并只显示开放的端口
nmap -sS 192.168.45.129 -p --open #参数--open表示只显示开放的端口
nmap -sS -iL iplist.txt -p 80
由抓包可知,nmap默认使用-sS扫描,发送SYN数据包,即nmap=nmap -sS
hping3做隐蔽端口扫描:
hping3 192.168.45.129 --scan 80 -S #参数--scan后面接单个端口或者多个端口.-S表示进行SYN扫描
hping3 192.168.45.129 --scan 80,21,25,443 -S
hping3 192.168.45.129 --scan 1-65535 -S
由抓包可得:
hping3 -c 100 -S --spoof 192.168.45.200 -p ++1 192.168.45.129
参数-c表示发送数据包的数量
参数-S表示发送SYN数据包
--spoof:伪造源地址,后面接伪造的地址,
参数-p表示扫描的端口,++1表示每次端口号加1,那么就是发送SYN从端口1到端口100
最后面跟的是目标IP
通过抓包可以得知地址已伪造,但对于linux系统(192.168.45.129)来说,它收到了192.168.45.200的SYN数据包,那么就会给192.168.45.200回复SYN+ACK数据包,但该地址却是kali伪造的地址,那么要查看目标系统哪些端口开放,必须登陆地址为kali伪造的地址即(192.168.45.200)进行抓包
hping3和nmap扫描端口的区别:1,hping3结果清晰明了
2,nmap首先对IP进行DNS反向解析,如果没成功,那么便会对其端口发送数据包,默认发送SYN数据包
hping3直接向目标系统的端口发送SYN数据包,并不进行DNS反向解析
全连接端口扫描:如果单独发送SYN数据包被被过滤,那么就使用全连接端口扫描,与目标建立三次握手连接,结果是最准确的,但容易被入侵检测系统发现
response=sr1(IP(dst="192.168.45.129")/TCP(dport=80,flags="S"))
reply=sr1(IP(dst="192.168.45.129")/TCP(dport=80,flags="A",ack=(response[TCP].seq+1)))
抓包情况:首先kali向Linux发送SYN,Linux回复SYN+ACK给kali,但kali的系统内核不清楚kali曾给linux发送给SYN数据包,那么kali内核莫名其妙收到SYN+ACK包,那么便会返回RST请求断开数据包给Linux,三次握手中断,如今kali再给Linux发ACK确认数据包,Linux莫名其妙收到了ACK数据包,当然也会返回RST请求断开数据包,具体抓包如下:
那么只要kali内核在收到SYN+ACK数据包之后,不发RST数据包,那么就可以建立完整的TCP三次握手,判断目标主机端口是否开放
因为iptables存在于Linux内核中,通过iptables禁用内核发送RST数据包,那么就可以实现
使用nmap进行全连接端口扫描:(如果不指定端口,那么nmap默认会扫描1000个常用的端口,并不是1-1000号端口)
使用dmitry进行全连接端口扫描:
dmitry:功能简单,但功能简便
默认扫描150个最常用的端口
dmitry -p 192.168.45.129 #参数-p表示执行TCP端口扫描
dmitry -p 192.168.45.129 -o output #参数-o表示把结果保存到一个文本文档中去
使用nc进行全连接端口扫描:
nc -nv -w 1 -z 192.168.45.129 1-100: 1-100表示扫描1-100号端口
参数-n表示不对Ip地址进行域名解析,只把其当IP来处理
参数-v表示显示详细信息
参数-w表示超时时间
-z表示打开用于扫描的模式
如何通过端口扫描发现目标主机的状态
端口扫描是指某些别有用心的人发送一组端口扫描消息,试图以此侵入某台计算机,并了解其提供的计算机网络服务类型(这些网络服务均与端口号相关)。端口扫描是计算机解密高手喜欢的一种方式。攻击者可以通过它了解到从哪里可探寻到攻击弱点。实质上,端口扫描包括向每个端口发送消息,一次只发送一个消息。接收到的回应类型表示是否在使用该端口并且可由此探寻弱点。
扫描器是一种自动检测远程或本地主机安全性弱点的程序,通过使用扫描器你可以不留痕迹的发现远程服务器的各种TCP端口的分配及提供的服务和它们的软件版本!这就能让我们间接的或直观的了解到远程主机所存在的安全问题。
一个端口就是一个潜在的通信通道,也就是一个入侵通道。对目标计算机进行端口扫描,能得到许多有用的信息。进行扫描的方法很多,可以是手工进行扫描,也可以用端口扫描软件进行扫描。
在手工进行扫描时,需要熟悉各种命令。对命令执行后的输出进行分析。用扫描软件进行扫描时,许多扫描器软件都有分析数据的功能。
通过端口扫描,可以得到许多有用的信息,从而发现系统的安全漏洞。
以上定义只针对网络通信端口,端口扫描在某些场合还可以定义为广泛的设备端口扫描,比如某些管理软件可以动态扫描各种计算机外设端口的开放状态,并进行管理和监控,这类系统常见的如USB管理系统、各种外设管理系统等。
2扫描工具编辑
扫描器是一种自动检测远程或本地主机安全性弱点的程序,通过使用扫描器你可以不留痕迹的发现远程服务器的各种TCP端口的分配及提供的服务和它们的软件版本!这就能让我们间接的或直观的了解到远程主机所存在的安全问题。
3工作原理编辑
扫描器通过选用远程TCP/IP不同的端口的服务,并记录目标给予的回答,通过这种方法,可以搜集到很多关于目标主机的各种有用的信息(比如:是否能用匿名登陆!是否有可写的FTP目录,是否能用TELNET,HTTPD是用ROOT还是nobady在跑.
4技术分类编辑
1、开放扫描;
2、半开放扫描;
3、隐蔽扫描。
5其它相关编辑
作用
扫描器并不是一个直接的攻击网络漏洞的程序,它仅仅能帮助我们发现目标机的某些内在的弱点。一个好的扫描器能对它得到的数据进行分析,帮助我们查找目标主机的漏洞。但它不会提供进入一个系统的详细步骤。
扫描器应该有三项功能:发现一个主机或网络的能力;一旦发现一台主机,有发现什么服务正运行在这台主机上的能力;通过测试这些服务,发现漏洞的能力。
编写扫描器程序必须要很多TCP/IP程序编写和C,Perl和或SHELL语言的知识。需要一些Socket编程的背景,一种在开发客户/服务应用程序的方法。开发一个扫描器是一个雄心勃勃的项目,通常能使程序员感到很满意。
端口号
代理服务器常用以下端口:
⑴. HTTP协议代理服务器常用端口号:80/8080/3128/8081/9080
⑵. SOCKS代理协议服务器常用端口号:1080
⑶. FTP(文件传输)协议代理服务器常用端口号:21
⑷. Telnet(远程登录)协议代理服务器常用端口:23
HTTP服务器,默认的端口号为80/tcp(木马Executor开放此端口);
HTTPS(securely transferring web pages)服务器,默认的端口号为443/tcp 443/udp;
Telnet(不安全的文本传送),默认端口号为23/tcp(木马Tiny Telnet Server所开放的端口);
FTP,默认的端口号为21/tcp(木马Doly Trojan、Fore、Invisible FTP、WebEx、WinCrash和Blade Runner所开放的端口);
TFTP(Trivial File Transfer Protocol),默认的端口号为69/udp;
SSH(安全登录)、SCP(文件传输)、端口重定向,默认的端口号为22/tcp;
SMTP Simple Mail Transfer Protocol (E-mail),默认的端口号为25/tcp(木马Antigen、Email Password Sender、Haebu Coceda、Shtrilitz Stealth、WinPC、WinSpy都开放这个端口);
POP3 Post Office Protocol (E-mail) ,默认的端口号为110/tcp;
WebLogic,默认的端口号为7001;
Webshpere应用程序,默认的端口号为9080;
webshpere管理工具,默认的端口号为9090;
JBOSS,默认的端口号为8080;
TOMCAT,默认的端口号为8080;
WIN2003远程登陆,默认的端口号为3389;
Symantec AV/Filter for MSE,默认端口号为 8081;
Oracle 数据库,默认的端口号为1521;
ORACLE EMCTL,默认的端口号为1158;
Oracle XDB(XML 数据库),默认的端口号为8080;
Oracle XDB FTP服务,默认的端口号为2100;
MS SQL*SERVER数据库server,默认的端口号为1433/tcp 1433/udp;
MS SQL*SERVER数据库monitor,默认的端口号为1434/tcp 1434/udp;
QQ,默认的端口号为1080/udp[1]
扫描分类
TCP connect() 扫描
这是最基本的TCP扫描。操作系统提供的connect()系统调用,用来与每一个感兴趣的目标计算机的端口进行连接。如果端口处于侦听状态,那么connect()就能成功。否则,这个端口是不能用的,即没有提供服务。这个技术的一个最大的优点是,你不需要任何权限。系统中的任何用户都有权利使用这个调用。另一个好处就是速度。如果对每个目标端口以线性的方式,使用单独的connect()调用,那么将会花费相当长的时间,你可以通过同时打开多个套接字,从而加速扫描。使用非阻塞I/O允许你设置一个低的时间用尽周期,同时观察多个套接字。但这种方法的缺点是很容易被发觉,并且被过滤掉。目标计算机的logs文件会显示一连串的连接和连接是出错的服务消息,并且能很快的使它关闭。
TCP SYN扫描
这种技术通常认为是“半开放”扫描,这是因为扫描程序不必要打开一个完全的TCP连接。扫描程序发送的是一个SYN数据包,好象准备打开一个实际的连接并等待反应一样(参考TCP的三次握手建立一个TCP连接的过程)。一个SYN|ACK的返回信息表示端口处于侦听状态。一个RST返回,表示端口没有处于侦听态。如果收到一个SYN|ACK,则扫描程序必须再发送一个RST信号,来关闭这个连接过程。这种扫描技术的优点在于一般不会在目标计算机上留下记录。但这种方法的一个缺点是,必须要有root权限才能建立自己的SYN数据包。
TCP FIN 扫描
有的时候有可能SYN扫描都不够秘密。一些防火墙和包过滤器会对一些指定的端口进行监视,有的程序能检测到这些扫描。相反,FIN数据包可能会没有任何麻烦的通过。这种扫描方法的思想是关闭的端口会用适当的RST来回复FIN数据包。另一方面,打开的端口会忽略对FIN数据包的回复。这种方法和系统的实现有一定的关系。有的系统不管端口是否打开,都回复RST,这样,这种扫描方法就不适用了。并且这种方法在区分Unix和NT时,是十分有用的。
IP段扫描
这种不能算是新方法,只是其它技术的变化。它并不是直接发送TCP探测数据包,是将数据包分成两个较小的IP段。这样就将一个TCP头分成好几个数据包,从而过滤器就很难探测到。但必须小心。一些程序在处理这些小数据包时会有些麻烦。
TCP 反向 ident扫描
ident 协议允许(rfc1413)看到通过TCP连接的任何进程的拥有者的用户名,即使这个连接不是由这个进程开始的。因此你能,举个例子,连接到http端口,然后用identd来发现服务器是否正在以root权限运行。这种方法只能在和目标端口建立了一个完整的TCP连接后才能看到。
FTP 返回攻击
FTP协议的一个有趣的特点是它支持代理(proxy)FTP连接。即入侵者可以从自己的计算机和目标主机的FTP server-PI(协议解释器)连接,建立一个控制通信连接。然后,请求这个server-PI激活一个有效的server-DTP(数据传输进程)来给Internet上任何地方发送文件。对于一个User-DTP,这是个推测,尽管RFC明确地定义请求一个服务器发送文件到另一个服务器是可以的。给许多服务器造成打击,用尽磁盘,企图越过防火墙”。
我们利用这个的目的是从一个代理的FTP服务器来扫描TCP端口。这样,你能在一个防火墙后面连接到一个FTP服务器,然后扫描端口(这些原来有可能被阻塞)。如果FTP服务器允许从一个目录读写数据,你就能发送任意的数据到发现的打开的端口。[2]
对于端口扫描,这个技术是使用PORT命令来表示被动的User DTP正在目标计算机上的某个端口侦听。然后入侵者试图用LIST命令列出当前目录,结果通过Server-DTP发送出去。如果目标主机正在某个端口侦听,传输就会成功(产生一个150或226的回应)。否则,会出现"425 Can't build data connection: Connection refused."。然后,使用另一个PORT命令,尝试目标计算机上的下一个端口。这种方法的优点很明显,难以跟踪,能穿过防火墙。主要缺点是速度很慢,有的FTP服务器最终能得到一些线索,关闭代理功能。
这种方法能成功的情景:
220 xxxx. FTP server (Version wu-2.4⑶ Wed Dec 14 ...) ready.
220 xxx.xxx. FTP server ready.
220 xx.Telcom. FTP server (Version wu-2.4⑶ Tue Jun 11 ...) ready.
220 lem FTP server (SunOS 4.1) ready.
220 xxx. FTP server (Version wu-2.4⑾ Sat Apr 27 ...) ready.
220 elios FTP server (SunOS 4.1) ready
这种方法不能成功的情景:
220 wcarchive. FTP server (Version DG-2.0.39 Sun May 4 ...) ready.
220 xxx.xx.xx. Version wu-2.4.2-academ[BETA-12]⑴ Fri Feb 7
220 ftp Microsoft FTP Service (Version 3.0).
220 xxx FTP server (Version wu-2.4.2-academ[BETA-11]⑴ Tue Sep 3 ...) ready.
220 xxx.FTP server (Version wu-2.4.2-academ[BETA-13]⑹ ...) ready.
不能扫描
这种方法与上面几种方法的不同之处在于使用的是UDP协议。由于这个协议很简单,所以扫描变得相对比较困难。这是由于打开的端口对扫描探测并不发送一个确认,关闭的端口也并不需要发送一个错误数据包。幸运的是,许多主机在你向一个未打开的UDP端口发送一个数据包时,会返回一个ICMP_PORT_UNREACH错误。这样你就能发现哪个端口是关闭的。UDP和ICMP错误都不保证能到达,因此这种扫描器必须还实现在一个包看上去是丢失的时候能重新传输。这种扫描方法是很慢的,因为RFC对ICMP错误消息的产生速率做了规定。同样,这种扫描方法需要具有root权限。
扫描
当非root用户不能直接读到端口不能到达错误时,Linux能间接地在它们到达时通知用户。比如,对一个关闭的端口的第二个write()调用将失败。在非阻塞的UDP套接字上调用recvfrom()时,如果ICMP出错还没有到达时回返回EAGAIN-重试。如果ICMP到达时,返回ECONNREFUSED-连接被拒绝。这就是用来查看端口是否打开的技术。
这并不是真正意义上的扫描。但有时通过ping,在判断在一个网络上主机是否开机时非常有用。[2]
0条大神的评论