0x01 原理
在python安全编程的世界当中,socket是和requests并驾齐驱,必须要掌握的一个模块。因为应用层上除了WEB的行为,你基本上都要使用socket去完成。
那么什么是socket呢?简单来说,就是区分同一服务器上不同应用程序的标识。其目的是为了完成从A主机上X进程到B主机上Y进程的通信。因此socket是工作在应用层和传输层之间的。如果你对什么是socket,什么是TCP,UDP不了解,建议阅读这篇文章,如果你从来没学过计算机网络,则请阅读这篇文章。
注意,socket和socket模块是不一样的,这篇文章主要介绍socket模块的使用。
0x02 使用
先让我们来看一个小小的Demo
|
|
首先socket.socket是一个类,我们将其实例化之后传递给s,而实例化的参数如下:
|
|
family用于指定套接族,type用于指定套接类型,proto用于指定协议。
family | 含义 |
---|---|
AF_UNIX | unix系统本地通信 |
AF_INET | ipv4通信 |
AF_INET6 | ipv6通信 |
type | 含义 |
---|---|
SOCK_STREAM | 基于TCP的流式socket通信 |
SOCK_DGRAM | 基于UDP的数据包式通信 |
SOCK_RAW | 原始套接字 |
以上只是一部分,更多细节请参考官方手册。
完成初始化之后,就可以调用socket类的方法了。
|
|
在上面的demo当中,调用了connect方法。该方法传入一个address参数,该参数为元组形式,包括地址以及端口。意思就是建立连接,只有建立连接之后才能有后续动作。
(注:python3.5之后该方法超时不再引发InterruptedError)
|
|
recv方法传入一个bufsize参数,指定接收内容的大小。执行成功返回bytes对象。
send则是相反,发送一个bytes对象到对应客户端。因此,发送或接收时注意不要发送str对象,而应发送bytes对象。
(注:在python2中则为发送接收str对象)
接下来开始服务器端的编写
|
|
这里调用了bind方法。作用在于绑定主机地址和端口号,建立一个服务端的socket进程。
(注:这里如果写localhost或是127.0.0.1只能本机访问,如果需要让别的主机访问,可以使用socket.gethostname()
。)
|
|
accept的方法是接受客户端发起的connect请求,该方法返回一个元组,包含一个新的socket对象以及地址对。在后续阶段,将使用这个新的socket对象与客户端进行交互。
|
|
最后,在使用完成之后,记得关闭套接字。
至此,一个基本的通过socket通信的程序已经基本完成。
0x03 补充
如果你还对socket的实际应用不太了解,建议多阅读exploit-db上面的一些EXP,相当多都用到了socket。
如前阵子的永恒之蓝,又如14年臭名昭著的心脏滴血。
当然socket的用途绝不仅限于编写EXP,但是通过阅读EXP,理解socket的本质,做到举一反三,对你非常有帮助。
如果你对socket的一些细节用法不太了解,请手动查阅官方文档。