Socket
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求
####常见的函数/方法/参数
socket.AF_INET #IPv4(默认)
socket.AF_INET6 #IPv6
socket.SOCK_STREAM #流式socket , for TCP
socket.SOCK_DGRAM #数据报式socket , for UDP
TCP客户端 编程
很多时候我们需要创建一个tcp客户端连接服务器,对服务器发送一些特殊的数据,进行fuzzz测试或者其他的任务,大多数时候我们都有现成的工具来使用,但是有的时候需要我们自己去写,比如写个poc或者exp,现在列一个简单的tcp客户端模型
1.socket.bind(adress)
socket.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址
2.socket.listen()
写服务端监听的时候需要监听并设置连接数
3.socket.setblocking(bool)
是否阻塞
4.socket.connect(address)
连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误、
5.socket.close()
关闭套接字
6.socket.send(string[,flag])
将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。
7.socket.sendall(string[,flag])
将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
8.socket.settimeout(timeout)
设置超时时间
9.soket.sendto(string[,flag],address)
将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。
10.socket.recv(bufsize[,flag])
接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。
11.socket.recvfrom(bufsize[.flag])
与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。
#coding=utf-8
import socket
import sys
host="www.baidu.com"
port=80
#建立一个socket对象
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 连接客户端
try:
ip=socket.gethostbyname(host)
print "服务器 ip is ",host
except Exception as e:
print "获取ip失败 原因是",e
if ip:
s.connect((ip,port))
try:
#Set the whole string
s.sendall("GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n")
print '消息发送成功'
except socket.error:
#Send failed
print 'Send failed'
sys.exit()
else:
sys.exit()
reply = s.recv(4096)
print reply
s.close()
当然很多时候我们要发送的数据是比较复杂的,而不是简单的"GET / HTTP/1.1\r\n\r\n"
比如可能是这个样子:
get_str = 'GET baidu.com HTTP/1.1\r\nHost: 80\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36\r\nAccept: */*\r\n\r\n'
实际使用中我们并不会这样我们并不会使用socket模块去模拟,尤其是作为安全人员,我们要快速的开发出合适的工具和脚本,而不是浪费时间像开发一样琢磨原理,这里仅仅作为例子描述
###UDP客户端 编程
做安全方面的开发,什么时候会使用到UDP协议呢,大多数的时候我们都是不需要的,但是如果做端口扫描的时候,或者是目标存活判断的时候,UPD是比TCP更快的,当然因为是无向连接,也就不那么准确。不管如何,介绍了TCP,就把UDP顺手介绍了
#coding=utf-8
import socket
t_host='127.0.0.1'
t_port=80
client =socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
client.sendto('AAAAAAA',(t_host,t_port))
data,addr=client.recvfrom(4096)
print data
思考:
为什么UDP不写个http协议的测试例子?
扩展:
1.什么是协议
网络协议为计算机网络中进行数据交换而建立的规则、标准或约定的集合。例如,网络中一个微机用户和一个大型主机的操作员进行通信,由于这两个数据终端所用字符集不同,因此操作员所输入的命令彼此不认识。为了能进行通信,规定每个终端都要将各自字符集中的字符先变换为标准字符集的字符后,才进入网络传送,到达目的终端之后,再变换为该终端字符集的字符。当然,对于不相容终端,除了需变换字符集字符外还需转换其他特性,如显示格式、行长、行数、屏幕滚动方式等也需作相应的变换
TCP服务端
tcp服务端编程和我们的课程关系不大,实际上我们做安全也不怎么会遇到,只是作为扩展内容陈列一下,下面是一个到处都可以找的到的服务端代码:
#服务端代码:
#coding=utf-8
import socket
import threading
import time
bind_ip = "127.0.0.1"
bind_port=8899
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((bind_ip,bind_port))
s.listen(5)
print "Waiting for connection..."
def tcplink(sock,addr):
print "Accept new connection from %s:%s..."% addr
sock.send('Welcome')
while True:
data =sock.recv(1024)
time.sleep(1)
if data== 'exit' or not data:
break
sock.send("hello,%s" % data)
sock.close()
print "connection from %s:%s closed. "% addr
while True:
#接受一个新的连接
sock,addr =s.accept()
#创建新的线程来处理TCP连接
t=threading.Thread(target=tcplink,args=(sock,addr))
t.start()
#客户端代码
#coding=utf-8
#2-01-client.py
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('127.0.0.1',8899))
#接受信息
print s.recv(1024)
for data in ['Michael','Tracy','Sarah']:
#发送数据
s.send(data)
print s.recv(1024)
s.send('exit')
s.close()