python3实现的rtsp客户端脚本
一、说明
此客户端使用python3编写
此客户端实现RTSP的OPTIONS, DESCRIBE, SETUP , PLAY, GET_PARAMETER,TEARDOWN方法,未实现ANNOUNCE,PAUSE,SET_PARAMETER,REDIRECT,RECORD
RTSP就是针对一个URL,或是依次或是有选择地执行以上11种请求;要做渗透测试,没很多可测的,也就测试URL中的参数和各请求方法的请求头参数有没有溢出
此客户端自动依次执行请求:OPTIONS--DESCRIBE(2次)--SETUP(2次)--PLAY--GET_PARAMETER(5次)--TEARDOWN
RTSP有Basic和Digest两种验证方法,此客户端实现默认使用Digest方法,如果想换用Basic方法请将config_dict['auth_method']的值由‘Digest’修改为‘Basic’
总体执行效果如下图所示
二、客户端源代码
V1.0版本(20180525):
import base64
import socket
import hashlib
import time global config_dict
config_dict = {
'server_username': 'admin',
'server_password': '',
'server_ip': '10.10.6.94',
'server_port': 554,
'server_path': '/chIP=1&streamType=main/',
'cseq': 2,
'user_agent': 'LibVLC/3.0.2 (LIVE555 Streaming Media v2016.11.28)',
'buffer_len': 1024,
'auth_method': 'Digest',
'header_modify_allow': False,
'options_header_modify': False,
'describe_header_modify': False,
'describe_auth_header_modify': False,
'setup_header_modify': False,
'setup_session_header_modify': False,
'play_header_modify': False,
'get_parameter_header_modify': False,
'teardown_header_modify': False
} def gen_response_value(url,public_method,realm,nonce):
frist_pre_md5_value = hashlib.md5((config_dict['server_username'] + ':' + realm + ':' + config_dict['server_password']).encode()).hexdigest()
first_post_md5_value = hashlib.md5((public_method+':' + url).encode()).hexdigest()
response_value = hashlib.md5((frist_pre_md5_value + ':' + nonce + ':' + first_post_md5_value).encode()).hexdigest()
return response_value def gen_options_header():
global config_dict
str_options_header = 'OPTIONS rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict[
'server_path'] + ' RTSP/1.0\r\n'
str_options_header += 'CSeq: ' + str(config_dict['cseq']) + '\r\n'
str_options_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_options_header += '\r\n'
return str_options_header def gen_describe_header():
global config_dict
str_describe_header = 'DESCRIBE rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict[
'server_path'] + ' RTSP/1.0\r\n'
str_describe_header += 'CSeq: ' + str(config_dict['cseq'] + 1) + '\r\n'
str_describe_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_describe_header += 'Accept: application/sdp\r\n'
str_describe_header += '\r\n'
return str_describe_header def gen_describe_auth_header(url,realm,nonce):
global config_dict
public_method = 'DESCRIBE'
str_describe_auth_header = 'DESCRIBE rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict['server_path'] + ' RTSP/1.0\r\n'
str_describe_auth_header += 'CSeq: ' + str(config_dict['cseq'] + 2) + '\r\n'
if config_dict['auth_method'] == 'Basic':
auth_64 = base64.b64encode((config_dict['server_username'] + ":" + config_dict['server_password']).encode("utf-8")).decode()
str_describe_auth_header += 'Authorization: Basic '+auth_64 + ' \r\n'
else:
response_value = gen_response_value(url, public_method, realm, nonce)
str_describe_auth_header += 'Authorization: Digest username="'+config_dict['server_username']+'", realm="'+realm+'", nonce="'+nonce+'", uri="'+url+'", response="'+response_value+'"\r\n'
str_describe_auth_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_describe_auth_header += 'Accept: application/sdp\r\n'
str_describe_auth_header += '\r\n'
return str_describe_auth_header def gen_setup_header(url, realm, nonce):
global config_dict
public_method = 'SETUP'
str_setup_header = 'SETUP rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict['server_path'] + 'trackID=0 RTSP/1.0\r\n'
str_setup_header += 'CSeq: ' + str(config_dict['cseq'] + 3) + '\r\n'
if config_dict['auth_method'] == 'Basic':
auth_64 = base64.b64encode((config_dict['server_username'] + ":" + config_dict['server_password']).encode("utf-8")).decode()
str_setup_header += 'Authorization: Basic '+auth_64 + ' \r\n'
else:
response_value = gen_response_value(url, public_method, realm, nonce)
str_setup_header += 'Authorization: Digest username="'+config_dict['server_username']+'", realm="'+realm+'", nonce="'+nonce+'", uri="'+url+'", response="'+response_value+'"\r\n'
str_setup_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_setup_header += 'Transport: RTP/AVP;unicast;client_port=50166-50167\r\n'
str_setup_header += '\r\n'
return str_setup_header def gen_setup_session_header(url, realm, nonce,session):
global config_dict
public_method = 'SETUP'
str_setup_session_header = 'SETUP rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict[
'server_path'] + '/trackID=1 RTSP/1.0\r\n'
str_setup_session_header += 'CSeq: ' + str(config_dict['cseq'] + 4) + '\r\n'
if config_dict['auth_method'] == 'Basic':
auth_64 = base64.b64encode((config_dict['server_username'] + ":" + config_dict['server_password']).encode("utf-8")).decode()
str_setup_session_header += 'Authorization: Basic '+auth_64 + ' \r\n'
else:
response_value = gen_response_value(url, public_method, realm, nonce)
str_setup_session_header += 'Authorization: Digest username="'+config_dict['server_username']+'", realm="'+realm+'", nonce="'+nonce+'", uri="'+url+'", response="'+response_value+'"\r\n'
str_setup_session_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_setup_session_header += 'Transport: RTP/AVP;unicast;client_port=50168-50169\r\n'
str_setup_session_header += 'Session: '+session+'\r\n'
str_setup_session_header += '\r\n'
return str_setup_session_header def gen_play_header(url, realm, nonce,session):
global config_dict
public_method = 'PLAY'
str_play_header = 'PLAY rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict[
'server_path'] + ' RTSP/1.0\r\n'
str_play_header += 'CSeq: ' + str(config_dict['cseq'] + 5) + '\r\n'
if config_dict['auth_method'] == 'Basic':
auth_64 = base64.b64encode((config_dict['server_username'] + ":" + config_dict['server_password']).encode("utf-8")).decode()
str_play_header += 'Authorization: Basic '+auth_64 + ' \r\n'
else:
response_value = gen_response_value(url, public_method, realm, nonce)
str_play_header += 'Authorization: Digest username="'+config_dict['server_username']+'", realm="'+realm+'", nonce="'+nonce+'", uri="'+url+'", response="'+response_value+'"\r\n'
str_play_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_play_header += 'Session: '+session+'\r\n'
str_play_header += 'Range: npt=0.000-\r\n'
str_play_header += '\r\n'
return str_play_header def gen_get_parameter_header(url, realm, nonce, session,count):
global config_dict
public_method = 'GET_PARAMETER'
str_get_parameter_header = 'GET_PARAMETER rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict[
'server_path'] + ' RTSP/1.0\r\n'
str_get_parameter_header += 'CSeq: ' + str(config_dict['cseq'] + 6+int(count)) + '\r\n'
if config_dict['auth_method'] == 'Basic':
auth_64 = base64.b64encode((config_dict['server_username'] + ":" + config_dict['server_password']).encode("utf-8")).decode()
str_get_parameter_header += 'Authorization: Basic '+auth_64 + ' \r\n'
else:
response_value = gen_response_value(url, public_method, realm, nonce)
str_get_parameter_header += 'Authorization: Digest username="' + config_dict[
'server_username'] + '", realm="' + realm + '", nonce="' + nonce + '", uri="' + url + '", response="' + response_value + '"\r\n'
str_get_parameter_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_get_parameter_header += 'Session: ' + session + '\r\n'
str_get_parameter_header += '\r\n'
return str_get_parameter_header def gen_teardown_header(url, realm, nonce, session):
global config_dict
public_method = 'TEARDOWN'
str_teardown_header = 'TEARDOWN rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict['server_path'] + ' RTSP/1.0\r\n'
str_teardown_header += 'CSeq: ' + str(config_dict['cseq'] + 11) + '\r\n'
if config_dict['auth_method'] == 'Basic':
auth_64 = base64.b64encode((config_dict['server_username'] + ":" + config_dict['server_password']).encode("utf-8")).decode()
str_teardown_header += 'Authorization: Basic '+auth_64 + ' \r\n'
else:
response_value = gen_response_value(url, public_method, realm, nonce)
str_teardown_header += 'Authorization: Digest username="' + config_dict[
'server_username'] + '", realm="' + realm + '", nonce="' + nonce + '", uri="' + url + '", response="' + response_value + '"\r\n'
str_teardown_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_teardown_header += 'Session: ' + session + '\r\n'
str_teardown_header += '\r\n'
return str_teardown_header def add_header_according_to_protocol(str_header):
str_header = str_header[0:len(str_header)-2]
str_header += 'Accept: application/rtsl, application/sdp;level=2'
str_header += 'Accept-Encoding: \r\n'
str_header += 'Accept-Language: \r\n'
str_header += 'Authorization: \r\n'
str_header += 'Bandwidth: 1*DIGIT \r\n'
str_header += 'Blocksize: \r\n'
str_header += 'Cache-Control: no-cache \r\n'
str_header += 'Conference: 199702170042.SAA08642@obiwan.arl.wustl.edu%20Starr \r\n'
str_header += 'Connection: \r\n'
str_header += 'Content-Base: \r\n'
str_header += 'Content-Encoding: \r\n'
str_header += 'Content-Language: \r\n'
str_header += 'Content-Length: 20 \r\n'
str_header += 'Content-Location: \r\n'
str_header += 'Content-Type: \r\n'
str_header += 'Date: \r\n'
str_header += 'Expires: Thu, 01 Dec 1994 16:00:00 GMT \r\n'
str_header += 'From: \r\n'
str_header += 'If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT \r\n'
str_header += 'Last-Modified: \r\n'
str_header += 'Proxy-Require: \r\n'
str_header += 'Referer: \r\n'
str_header += 'Require: funky-feature \r\n'
str_header += 'Scale: -3.5 \r\n'
str_header += 'Speed: 2.5 \r\n'
str_header += 'Transport: RTP/AVP;unicast;client_port=3456-3457;mode="PLAY" \r\n'
str_header += 'User-Agent: \r\n'
str_header += 'Via: \r\n'
str_header += 'Range: npt=2\r\n'
str_header += '\r\n'
return str_header def exec_full_request():
socket_send = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_send.settimeout(5)
socket_send.connect((config_dict['server_ip'], config_dict['server_port'])) url = 'rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict['server_path'] print('now start to check options operation')
str_options_header = gen_options_header()
if config_dict['header_modify_allow'] & config_dict['options_header_modify']:
str_options_header = add_header_according_to_protocol(str_options_header)
socket_send.send(str_options_header.encode())
msg_recv = socket_send.recv(config_dict['buffer_len']).decode()
if '200 OK' in msg_recv:
print('OPTIONS request is OK')
else:
print('OPTIONS request is BAD')
str_describe_header = gen_describe_header()
if config_dict['header_modify_allow'] & config_dict['describe_header_modify']:
str_describe_header = add_header_according_to_protocol(str_describe_header)
socket_send.send(str_describe_header.encode())
msg_recv = socket_send.recv(config_dict['buffer_len']).decode()
if msg_recv.find('401 Unauthorized') == -1 & False:
msg_recv_dict = msg_recv.split('\r\n')
print('first DESCRIBE request occur error: ')
print(msg_recv_dict[0])
else:
print('first DESCRIBE is ok,now we will execute second DESCRIBE for auth')
realm_pos = msg_recv.find('realm')
realm_value_begin_pos = msg_recv.find('"', realm_pos)+1
realm_value_end_pos = msg_recv.find('"', realm_pos + 8)
realm_value = msg_recv[realm_value_begin_pos:realm_value_end_pos]
nonce_pos = msg_recv.find('nonce')
nonce_value_begin_pos = msg_recv.find('"', nonce_pos)+1
nonce_value_end_pos = msg_recv.find('"', nonce_pos + 8)
nonce_value = msg_recv[nonce_value_begin_pos:nonce_value_end_pos]
str_describe_auth_header = gen_describe_auth_header(url, realm_value, nonce_value)
if config_dict['header_modify_allow'] & config_dict['describe_auth_header_modify']:
str_describe_auth_header = add_header_according_to_protocol(str_describe_auth_header)
socket_send.send(str_describe_auth_header.encode())
msg_recv = socket_send.recv(config_dict['buffer_len']).decode()
if msg_recv.find('200 OK') == -1:
msg_recv_dict = msg_recv.split('\r\n')
print('second DESCRIBE request occur error: ')
print(msg_recv_dict[0])
else:
print('second DESCRIBE is ok,now we will execute first SETUP for session')
str_setup_header = gen_setup_header(url, realm_value, nonce_value)
if config_dict['header_modify_allow'] & config_dict['setup_header_modify']:
str_setup_header = add_header_according_to_protocol(str_setup_header)
socket_send.send(str_setup_header.encode())
msg_recv = socket_send.recv(config_dict['buffer_len']).decode()
if msg_recv.find('200 OK') == -1:
msg_recv_dict = msg_recv.split('\r\n')
print('first SETUP request occur error: ')
print(msg_recv_dict[0])
else:
print('first SETUP is ok,now we will execute second SETUP')
session_pos = msg_recv.find('Session')
session_value_begin_pos = msg_recv.find(' ',session_pos+8)+1
session_value_end_pos = msg_recv.find(';',session_pos+8)
session_value = msg_recv[session_value_begin_pos:session_value_end_pos]
str_setup_session_header = gen_setup_session_header(url, realm_value, nonce_value,session_value)
if config_dict['header_modify_allow'] & config_dict['setup_session_header_modify']:
str_setup_session_header = add_header_according_to_protocol(str_setup_session_header)
socket_send.send(str_setup_session_header.encode())
msg_recv = socket_send.recv(config_dict['buffer_len']).decode()
if msg_recv.find('200 OK') == -1:
msg_recv_dict = msg_recv.split('\r\n')
print('first SETUP request occur error: ')
print(msg_recv_dict[0])
else:
print('second SETUP is ok, now we wil execute PLAY')
str_play_header = gen_play_header(url, realm_value, nonce_value, session_value)
if config_dict['header_modify_allow'] & config_dict['play_header_modify']:
str_play_header = add_header_according_to_protocol(str_play_header)
socket_send.send(str_play_header.encode())
msg_recv = socket_send.recv(config_dict['buffer_len']).decode()
if msg_recv.find('200 OK') == -1:
msg_recv_dict = msg_recv.split('\r\n')
print('PLAY request occur error: ')
print(msg_recv_dict[0])
else:
print('PLAY is ok, we will execute GET_PARAMETER every 10 seconds and 5 times total')
for i in range(2):
str_get_parameter_header = gen_get_parameter_header(url, realm_value, nonce_value, session_value,str(i))
if config_dict['header_modify_allow'] & config_dict['get_parameter_header_modify']:
str_get_parameter_header = add_header_according_to_protocol(str_get_parameter_header)
socket_send.send(str_get_parameter_header.encode())
msg_recv = socket_send.recv(config_dict['buffer_len']).decode()
msg_recv_dict = msg_recv.split('\r\n')
print(str(i)+'*10:'+msg_recv_dict[0])
time.sleep(10)
print('now we will execute TEARDOWN to disconnect with server')
str_teardown_header = gen_teardown_header(url, realm_value, nonce_value, session_value)
if config_dict['header_modify_allow'] & config_dict['teardown_header_modify']:
str_teardown_header = add_header_according_to_protocol(str_teardown_header)
socket_send.send(str_teardown_header.encode())
msg_recv = socket_send.recv(config_dict['buffer_len']).decode()
print(msg_recv)
print('program execute finished, thank you')
socket_send.close() exec_full_request()
V1.1版本(20180614):
import socket
import hashlib
import base64
import time config_dict = {
'server_username': 'admin', #RTSP用户名
'server_password': '', #RTSP用户名对应密码
'server_ip': '10.10.6.92', #RTSP服务器IP地址
'server_port': 554, #RTSP服务器使用端口
'server_path': '/chIP=1&streamType=main/', #URL中端口之后的部份,测试发现不同服务器对这部份接受的值是不一样的,也就是说自己使用时很可能得自己修改这部份的值
'cseq': 2, #RTSP使用的请求起始序列码,不需要改动
'user_agent': 'LibVLC/3.0.2 (LIVE555 Streaming Media v2016.11.28)', #自定义请求头部
'buffer_len': 1024, #用于接收服务器返回数据的缓冲区的大小
'auth_method': 'Digest', #RTSP使用的认证方法,Basic/Digest
'header_normal_modify_allow': False, #是否允许拼接其他协议规定的请求头的总开关,请些请求头的值为正常值(大多是RFC给出的示例)
'header_overload_modify_allow': False, #是否允许拼接其他协议规定的请求头的总开关,请些请求头的值为超长字符串
'options_header_modify': True, #OPTIONS请求中,是否允许拼接其他协议规定的请求头的开关
'describe_header_modify': True, #第一次DESCRIBE请求中,是否允许拼接其他协议规定的请求头的开关
'describe_auth_header_modify': True, #第二次DESCRIBE请求中,是否允许拼接其他协议规定的请求头的开关
'setup_header_modify': True, #第一次SETUP请求中,是否允许拼接其他协议规定的请求头的开关
'setup_session_header_modify': True, #第二次SETUP请求中,是否允许拼接其他协议规定的请求头的开关
'play_header_modify': True, #PLAY请求中,是否允许拼接其他协议规定的请求头的开关
'get_parameter_header_modify': True, #GET PARAMETER请求中,是否允许拼接其他协议规定的请求头的开关
'teardown_header_modify': True #TEARDOWN请求中,是否允许拼接其他协议规定的请求头的开关
} class RtspClient():
def __init__(self):
# self.socket_send = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# self.socket_send.settimeout(5)
# self.socket_send.connect((config_dict['server_ip'], config_dict['server_port']))
pass #用于Digest认证方式时生成response的值
def gen_response_value(self,url,public_method,realm,nonce):
frist_pre_md5_value = hashlib.md5((config_dict['server_username'] + ':' + realm + ':' + config_dict['server_password']).encode()).hexdigest()
first_post_md5_value = hashlib.md5((public_method+':' + url).encode()).hexdigest()
response_value = hashlib.md5((frist_pre_md5_value + ':' + nonce + ':' + first_post_md5_value).encode()).hexdigest()
return response_value #生成options请求头部
def gen_options_header(self):
global config_dict
str_options_header = 'OPTIONS rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict[
'server_path'] + ' RTSP/1.0\r\n'
str_options_header += 'CSeq: ' + str(config_dict['cseq']) + '\r\n'
str_options_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_options_header += '\r\n'
return str_options_header #生成第一次describe请求头部
def gen_describe_header(self):
global config_dict
str_describe_header = 'DESCRIBE rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict[
'server_path'] + ' RTSP/1.0\r\n'
str_describe_header += 'CSeq: ' + str(config_dict['cseq'] + 1) + '\r\n'
str_describe_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_describe_header += 'Accept: application/sdp\r\n'
str_describe_header += '\r\n'
return str_describe_header #生成第二次describe请求头部
def gen_describe_auth_header(self,url,realm,nonce):
global config_dict
public_method = 'DESCRIBE'
str_describe_auth_header = 'DESCRIBE rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict['server_path'] + ' RTSP/1.0\r\n'
str_describe_auth_header += 'CSeq: ' + str(config_dict['cseq'] + 2) + '\r\n'
if config_dict['auth_method'] == 'Basic':
auth_64 = base64.b64encode((config_dict['server_username'] + ":" + config_dict['server_password']).encode("utf-8")).decode()
str_describe_auth_header += 'Authorization: Basic '+auth_64 + ' \r\n'
else:
response_value = self.gen_response_value(url, public_method, realm, nonce)
str_describe_auth_header += 'Authorization: Digest username="'+config_dict['server_username']+'", realm="'+realm+'", nonce="'+nonce+'", uri="'+url+'", response="'+response_value+'"\r\n'
str_describe_auth_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_describe_auth_header += 'Accept: application/sdp\r\n'
str_describe_auth_header += '\r\n'
return str_describe_auth_header #生成第一次setup请求头部
def gen_setup_header(self,url, realm, nonce):
global config_dict
public_method = 'SETUP'
str_setup_header = 'SETUP rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict['server_path'] + 'trackID=0 RTSP/1.0\r\n'
str_setup_header += 'CSeq: ' + str(config_dict['cseq'] + 3) + '\r\n'
if config_dict['auth_method'] == 'Basic':
auth_64 = base64.b64encode((config_dict['server_username'] + ":" + config_dict['server_password']).encode("utf-8")).decode()
str_setup_header += 'Authorization: Basic '+auth_64 + ' \r\n'
else:
response_value = self.gen_response_value(url, public_method, realm, nonce)
str_setup_header += 'Authorization: Digest username="'+config_dict['server_username']+'", realm="'+realm+'", nonce="'+nonce+'", uri="'+url+'", response="'+response_value+'"\r\n'
str_setup_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_setup_header += 'Transport: RTP/AVP;unicast;client_port=50166-50167\r\n'
str_setup_header += '\r\n'
return str_setup_header #生成第二次setup请求头部
def gen_setup_session_header(self,url, realm, nonce,session):
global config_dict
public_method = 'SETUP'
str_setup_session_header = 'SETUP rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict[
'server_path'] + 'trackID=1 RTSP/1.0\r\n'
str_setup_session_header += 'CSeq: ' + str(config_dict['cseq'] + 4) + '\r\n'
if config_dict['auth_method'] == 'Basic':
auth_64 = base64.b64encode((config_dict['server_username'] + ":" + config_dict['server_password']).encode("utf-8")).decode()
str_setup_session_header += 'Authorization: Basic '+auth_64 + ' \r\n'
else:
response_value = self.gen_response_value(url, public_method, realm, nonce)
str_setup_session_header += 'Authorization: Digest username="'+config_dict['server_username']+'", realm="'+realm+'", nonce="'+nonce+'", uri="'+url+'", response="'+response_value+'"\r\n'
str_setup_session_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_setup_session_header += 'Transport: RTP/AVP;unicast;client_port=50168-50169\r\n'
str_setup_session_header += 'Session: '+session+'\r\n'
str_setup_session_header += '\r\n'
return str_setup_session_header #生成play请求头部
def gen_play_header(self,url, realm, nonce,session):
global config_dict
public_method = 'PLAY'
str_play_header = 'PLAY rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict[
'server_path'] + ' RTSP/1.0\r\n'
str_play_header += 'CSeq: ' + str(config_dict['cseq'] + 5) + '\r\n'
if config_dict['auth_method'] == 'Basic':
auth_64 = base64.b64encode((config_dict['server_username'] + ":" + config_dict['server_password']).encode("utf-8")).decode()
str_play_header += 'Authorization: Basic '+auth_64 + ' \r\n'
else:
response_value = self.gen_response_value(url, public_method, realm, nonce)
str_play_header += 'Authorization: Digest username="'+config_dict['server_username']+'", realm="'+realm+'", nonce="'+nonce+'", uri="'+url+'", response="'+response_value+'"\r\n'
str_play_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_play_header += 'Session: '+session+'\r\n'
str_play_header += 'Range: npt=0.000-\r\n'
str_play_header += '\r\n'
return str_play_header #生成GET_PARAMETER请求头部
def gen_get_parameter_header(self,url, realm, nonce, session,count):
global config_dict
public_method = 'GET_PARAMETER'
str_get_parameter_header = 'GET_PARAMETER rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict[
'server_path'] + ' RTSP/1.0\r\n'
str_get_parameter_header += 'CSeq: ' + str(config_dict['cseq'] + 6+int(count)) + '\r\n'
if config_dict['auth_method'] == 'Basic':
auth_64 = base64.b64encode((config_dict['server_username'] + ":" + config_dict['server_password']).encode("utf-8")).decode()
str_get_parameter_header += 'Authorization: Basic '+auth_64 + ' \r\n'
else:
response_value = self.gen_response_value(url, public_method, realm, nonce)
str_get_parameter_header += 'Authorization: Digest username="' + config_dict[
'server_username'] + '", realm="' + realm + '", nonce="' + nonce + '", uri="' + url + '", response="' + response_value + '"\r\n'
str_get_parameter_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_get_parameter_header += 'Session: ' + session + '\r\n'
str_get_parameter_header += '\r\n'
return str_get_parameter_header #生成teardown请求头部
def gen_teardown_header(self,url, realm, nonce, session):
global config_dict
public_method = 'TEARDOWN'
str_teardown_header = 'TEARDOWN rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict['server_path'] + ' RTSP/1.0\r\n'
str_teardown_header += 'CSeq: ' + str(config_dict['cseq'] + 11) + '\r\n'
if config_dict['auth_method'] == 'Basic':
auth_64 = base64.b64encode((config_dict['server_username'] + ":" + config_dict['server_password']).encode("utf-8")).decode()
str_teardown_header += 'Authorization: Basic '+auth_64 + ' \r\n'
else:
response_value = self.gen_response_value(url, public_method, realm, nonce)
str_teardown_header += 'Authorization: Digest username="' + config_dict[
'server_username'] + '", realm="' + realm + '", nonce="' + nonce + '", uri="' + url + '", response="' + response_value + '"\r\n'
str_teardown_header += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
str_teardown_header += 'Session: ' + session + '\r\n'
str_teardown_header += '\r\n'
return str_teardown_header #拼接rtsp协议的其他请求头,以测试程序对这些请求头部的处理是否有问题;这个方法与add_overload_header_according_to_protocol是互斥的
def add_normal_header_according_to_protocol(self,str_header):
str_header = str_header[0:len(str_header)-2]
str_header += 'Accept: application/rtsl, application/sdp;level=-2'
str_header += 'Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0\r\n'
str_header += 'Accept-Language: da, en-gb;q=0.8, en;q=0.7\r\n'
str_header += 'Bandwidth: 4000 \r\n'
str_header += 'Blocksize: 4000 \r\n'
str_header += 'Cache-Control: no-cache;max-stale \r\n'
str_header += 'Conference: 199702170042.SAA08642@obiwan.arl.wustl.edu%20Starr \r\n'
str_header += 'Connection: close\r\n'
str_header += 'Content-Base: gzip\r\n'
str_header += 'Content-Encoding: gzip\r\n'
str_header += 'Content-Language: mi,en\r\n'
str_header += 'Content-Length: 2034953454546565 \r\n'
str_header += 'Content-Location: /etc/passwd\r\n'
str_header += 'Content-Type: text/html; charset=ISO-8859-4gg\r\n'
str_header += 'Date: Tue, 15 Nov 1995x 08:12:31 GMT\r\n'
str_header += 'Expires: Thu, 01 Dec 1994 16:00:00 GMT \r\n'
str_header += 'From: webmaster@w3.org\r\n'
str_header += 'If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT \r\n'
str_header += 'Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT\r\n'
str_header += 'Proxy-Require: funky-feature\r\n'
str_header += 'Referer: http://www.w3.org/hypertext/DataSources/Overview.html\r\n'
str_header += 'Require: funky-feature \r\n'
str_header += 'Scale: -3.5 \r\n'
str_header += 'Speed: 2.5 \r\n'
str_header += 'Transport: RTP/AVP;unicast;client_port=3456-3457;mode="PLAY" \r\n'
str_header += 'Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)\r\n'
str_header += 'Range: npt=2\r\n'
str_header += '\r\n'
return str_header #拼接rtsp协议的其他请求头,并将这些请求头的字赋为超长字符串,以测试程序对这些请求头部的处理是否有缓冲区溢出问题;这个方法与add_normal_header_according_to_protocol是互斥的
def add_overload_header_according_to_protocol(self,str_header):
str_header = str_header[0:len(str_header) - 2]
str_header += 'Accept: application/rtsl012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789, application/sdp;level=-2012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'
str_header += 'Accept-Encoding: gzip01234567890123456789012345678901234567890123456789;q=1.0012345678901234567890123456789012345678901234567890123456789, identity; q=0.5012345678901234567890123456789, *;q=0012345678901234567890123456789\r\n'
str_header += 'Accept-Language: da, en-gb;q=0.80123456789012345678901234567890123456789, en;q=0.7012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\r\n'
str_header += 'Bandwidth: 400001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 \r\n'
str_header += 'Blocksize: 4000012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 \r\n'
str_header += 'Cache-Control: no-cache;max-stale \r\n'
str_header += 'Conference: 199702170042.SAA08642@obiwan.arl.wustl.edu%20Starr01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 \r\n'
str_header += 'Connection: 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789close\r\n'
str_header += 'Content-Base: 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789gzip\r\n'
str_header += 'Content-Encoding: 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789gzip\r\n'
str_header += 'Content-Language: 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789mi,en\r\n'
str_header += 'Content-Length: 203495345454656501234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 \r\n'
str_header += 'Content-Location: /etc/passwd01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\r\n'
str_header += 'Content-Type: text/html012345678901234567890123456789012345678901234567890123456789; charset=012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789ISO-8859-4gg\r\n'
str_header += 'Date: Tue, 15 Nov 1995x 08:12:310123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 GMT\r\n'
str_header += 'Expires: Thu, 01 Dec 1994 16012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789:00:00 GMT \r\n'
str_header += 'From: webmaster@w30123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.org\r\n'
str_header += 'If-Modified-Since: Sat, 29 Oct 1994 19:43:31012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 GMT \r\n'
str_header += 'Last-Modified: Tue, 15 Nov 1994 120123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789:45:26 GMT\r\n'
str_header += 'Proxy-Require: funky-feature\r\n'
str_header += 'Referer: http://www.w3.org/hypertext/DataSources/Overview.html\r\n'
str_header += 'Require: funky-feature0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 \r\n'
str_header += 'Scale: -0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567893.5 \r\n'
str_header += 'Speed: 20123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.5 \r\n'
str_header += 'Transport: RTP/AVP;unicast;client_port=3456-345012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567897;mode="01234567890123456789PLAY" \r\n'
str_header += 'Via: 1.0 fred, 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567891.1 nowhere.com (Apache/0123456789012345678901234567891.1)\r\n'
str_header += 'Range: npt=20123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\r\n'
str_header += '\r\n'
return str_header #执行一次完整的rtsp播放请求,OPTIONS/DESCRIBE/SETUP/PLAY/GET PARAMETER/TEARDOWN,如果某个请求不正确则中止
#此方法推荐用于则试服务端是否正确实现RTSP服务
def exec_full_request(self):
self.socket_send = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket_send.settimeout(5)
self.socket_send.connect((config_dict['server_ip'], config_dict['server_port'])) url = 'rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict['server_path'] print('now start to check options operation')
str_options_header = self.gen_options_header()
if config_dict['header_normal_modify_allow'] & config_dict['options_header_modify']:
str_options_header = self.add_normal_header_according_to_protocol(str_options_header)
elif config_dict['header_overload_modify_allow'] & config_dict['options_header_modify']:
str_options_header = self.add_overload__header_according_to_protocol(str_options_header)
self.socket_send.send(str_options_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
if '200 OK' in msg_recv:
print('OPTIONS request is OK')
else:
print('OPTIONS request is BAD')
str_describe_header = self.gen_describe_header()
if config_dict['header_normal_modify_allow'] & config_dict['describe_header_modify']:
str_describe_header = self.add_normal_header_according_to_protocol(str_describe_header)
elif config_dict['header_overload_modify_allow'] & config_dict['describe_header_modify']:
str_describe_header = self.add_overload__header_according_to_protocol(str_describe_header)
self.socket_send.send(str_describe_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
if msg_recv.find('401 Unauthorized') == -1 & False:
msg_recv_dict = msg_recv.split('\r\n')
print('first DESCRIBE request occur error: ')
print(msg_recv_dict[0])
else:
print('first DESCRIBE is ok,now we will execute second DESCRIBE for auth')
realm_pos = msg_recv.find('realm')
realm_value_begin_pos = msg_recv.find('"', realm_pos)+1
realm_value_end_pos = msg_recv.find('"', realm_pos + 8)
realm_value = msg_recv[realm_value_begin_pos:realm_value_end_pos]
nonce_pos = msg_recv.find('nonce')
nonce_value_begin_pos = msg_recv.find('"', nonce_pos)+1
nonce_value_end_pos = msg_recv.find('"', nonce_pos + 8)
nonce_value = msg_recv[nonce_value_begin_pos:nonce_value_end_pos]
str_describe_auth_header = self.gen_describe_auth_header(url, realm_value, nonce_value)
if config_dict['header_normal_modify_allow'] & config_dict['describe_auth_header_modify']:
str_describe_auth_header = self.add_normal_header_according_to_protocol(str_describe_auth_header)
elif config_dict['header_overload_modify_allow'] & config_dict['describe_auth_header_modify']:
str_describe_auth_header = self.add_overload__header_according_to_protocol(str_describe_auth_header)
self.socket_send.send(str_describe_auth_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
if msg_recv.find('200 OK') == -1:
msg_recv_dict = msg_recv.split('\r\n')
print('second DESCRIBE request occur error: ')
print(msg_recv_dict[0])
else:
print('second DESCRIBE is ok,now we will execute first SETUP for session')
str_setup_header = self.gen_setup_header(url, realm_value, nonce_value)
if config_dict['header_normal_modify_allow'] & config_dict['setup_header_modify']:
str_setup_header = self.add_normal_header_according_to_protocol(str_setup_header)
elif config_dict['header_overload_modify_allow'] & config_dict['setup_header_modify']:
str_setup_header = self.add_overload__header_according_to_protocol(str_setup_header)
self.socket_send.send(str_setup_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
if msg_recv.find('200 OK') == -1:
msg_recv_dict = msg_recv.split('\r\n')
print('first SETUP request occur error: ')
print(msg_recv_dict[0])
else:
print('first SETUP is ok,now we will execute second SETUP')
session_pos = msg_recv.find('Session')
session_value_begin_pos = msg_recv.find(' ',session_pos+8)+1
session_value_end_pos = msg_recv.find(';',session_pos+8)
session_value = msg_recv[session_value_begin_pos:session_value_end_pos]
str_setup_session_header = self.gen_setup_session_header(url, realm_value, nonce_value,session_value)
if config_dict['header_normal_modify_allow'] & config_dict['setup_session_header_modify']:
str_setup_session_header = self.add_normal_header_according_to_protocol(str_setup_session_header)
elif config_dict['header_overload_modify_allow'] & config_dict['setup_session_header_modify']:
str_setup_session_header = self.add_overload_header_according_to_protocol(str_setup_session_header)
self.socket_send.send(str_setup_session_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
if msg_recv.find('200 OK') == -1:
msg_recv_dict = msg_recv.split('\r\n')
print('second SETUP request occur error: ')
print(msg_recv_dict[0])
else:
print('second SETUP is ok, now we wil execute PLAY')
str_play_header = self.gen_play_header(url, realm_value, nonce_value, session_value)
if config_dict['header_normal_modify_allow'] & config_dict['play_header_modify']:
str_play_header = self.add_normal_header_according_to_protocol(str_play_header)
elif config_dict['header_overload_modify_allow'] & config_dict['play_header_modify']:
str_play_header = self.add_overload_header_according_to_protocol(str_play_header)
self.socket_send.send(str_play_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
if msg_recv.find('200 OK') == -1:
msg_recv_dict = msg_recv.split('\r\n')
print('PLAY request occur error: ')
print(msg_recv_dict[0])
else:
print('PLAY is ok, we will execute GET_PARAMETER every 10 seconds and 5 times total')
for i in range(2):
str_get_parameter_header = self.gen_get_parameter_header(url, realm_value, nonce_value, session_value,str(i))
if config_dict['header_normal_modify_allow'] & config_dict['get_parameter_header_modify']:
str_get_parameter_header = self.add_normal_header_according_to_protocol(str_get_parameter_header)
elif config_dict['header_overload_modify_allow'] & config_dict['get_parameter_header_modify']:
str_get_parameter_header = self.add_overload_header_according_to_protocol(str_get_parameter_header)
self.socket_send.send(str_get_parameter_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
msg_recv_dict = msg_recv.split('\r\n')
print(str(i)+'*10:'+msg_recv_dict[0])
time.sleep(10)
print('\nnow we will execute TEARDOWN to disconnect with server')
str_teardown_header = self.gen_teardown_header(url, realm_value, nonce_value, session_value)
if config_dict['header_normal_modify_allow'] & config_dict['teardown_header_modify']:
str_teardown_header = self.add_normal_header_according_to_protocol(str_teardown_header)
elif config_dict['header_overload_modify_allow'] & config_dict['teardown_header_modify']:
str_teardown_header = self.add_overload_header_according_to_protocol(str_teardown_header)
self.socket_send.send(str_teardown_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
print(msg_recv)
print('program execute finished, thank you')
self.socket_send.close() #强制依次执行OPTIONS/DESCRIBE/SETUP/PLAY/GET PARAMETER/TEARDOWN,某个请求报错也进行下一个请求
#此方法推荐用于测试服务端是否有溢出漏洞
def exec_force_request(self):
self.socket_send = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket_send.settimeout(5)
self.socket_send.connect((config_dict['server_ip'], config_dict['server_port'])) url = 'rtsp://' + config_dict['server_ip'] + ':' + str(config_dict['server_port']) + config_dict['server_path'] print('now start to check options operation')
str_options_header = self.gen_options_header()
if config_dict['header_normal_modify_allow'] & config_dict['options_header_modify']:
str_options_header = self.add_normal_header_according_to_protocol(str_options_header)
elif config_dict['header_overload_modify_allow'] & config_dict['options_header_modify']:
str_options_header = self.add_overload_header_according_to_protocol(str_options_header)
self.socket_send.send(str_options_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
msg_recv_dict = msg_recv.split('\r\n')
print('the OPTIONS response is :')
print(msg_recv_dict[0])
print('\nnow we will execute first DESCRIBE request')
str_describe_header = self.gen_describe_header()
if config_dict['header_normal_modify_allow'] & config_dict['describe_header_modify']:
str_describe_header = self.add_normal_header_according_to_protocol(str_describe_header)
elif config_dict['header_overload_modify_allow'] & config_dict['describe_header_modify']:
str_describe_header = self.add_overload_header_according_to_protocol(str_describe_header)
self.socket_send.send(str_describe_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
msg_recv_dict = msg_recv.split('\r\n')
print('the first DESCRIBE response is :')
print(msg_recv_dict[0])
print('\nnow we will execute second DESCRIBE for auth')
realm_value = 'RTSP SERVER'
nonce_value = 'e29027990294f81b941b04a7ac78c196'
str_describe_auth_header = self.gen_describe_auth_header(url, realm_value, nonce_value)
if config_dict['header_normal_modify_allow'] & config_dict['describe_auth_header_modify']:
str_describe_auth_header = self.add_normal_header_according_to_protocol(str_describe_auth_header)
elif config_dict['header_overload_modify_allow'] & config_dict['describe_auth_header_modify']:
str_describe_auth_header = self.add_overload_header_according_to_protocol(str_describe_auth_header)
self.socket_send.send(str_describe_auth_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
msg_recv_dict = msg_recv.split('\r\n')
print('the second DESCRIBE response is :')
print(msg_recv_dict[0])
print('\nnow we will execute first SETUP for session')
str_setup_header = self.gen_setup_header(url, realm_value, nonce_value)
if config_dict['header_normal_modify_allow'] & config_dict['setup_header_modify']:
str_setup_header = self.add_normal_header_according_to_protocol(str_setup_header)
elif config_dict['header_overload_modify_allow'] & config_dict['setup_header_modify']:
str_setup_header = self.add_overload_header_according_to_protocol(str_setup_header)
self.socket_send.send(str_setup_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
msg_recv_dict = msg_recv.split('\r\n')
print('the first SETUP response is :')
print(msg_recv_dict[0])
print('\nnow we will execute second SETUP')
session_value = ''
str_setup_session_header = self.gen_setup_session_header(url, realm_value, nonce_value, session_value)
if config_dict['header_normal_modify_allow'] & config_dict['setup_session_header_modify']:
str_setup_session_header = self.add_normal_header_according_to_protocol(str_setup_session_header)
elif config_dict['header_overload_modify_allow'] & config_dict['setup_session_header_modify']:
str_setup_session_header = self.add_overload_header_according_to_protocol(str_setup_session_header)
self.socket_send.send(str_setup_session_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
msg_recv_dict = msg_recv.split('\r\n')
print('the second SETUP response is :')
print(print(msg_recv_dict[0]))
print('\nnow we wil execute PLAY')
str_play_header = self.gen_play_header(url, realm_value, nonce_value, session_value)
if config_dict['header_normal_modify_allow'] & config_dict['play_header_modify']:
str_play_header = self.add_normal_header_according_to_protocol(str_play_header)
elif config_dict['header_overload_modify_allow'] & config_dict['play_header_modify']:
str_play_header = self.add_overload_header_according_to_protocol(str_play_header)
self.socket_send.send(str_play_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
msg_recv_dict = msg_recv.split('\r\n')
print('the PLAY response is :')
print(msg_recv_dict[0])
print('\nnow we will execute GET_PARAMETER')
str_get_parameter_header = self.gen_get_parameter_header(url, realm_value, nonce_value, session_value, '')
if config_dict['header_normal_modify_allow'] & config_dict['get_parameter_header_modify']:
str_get_parameter_header = self.add_normal_header_according_to_protocol(str_get_parameter_header)
elif config_dict['header_overload_modify_allow'] & config_dict['get_parameter_header_modify']:
str_get_parameter_header = self.add_overload_header_according_to_protocol(str_get_parameter_header)
self.socket_send.send(str_get_parameter_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
msg_recv_dict = msg_recv.split('\r\n')
print('the GET_PARAMETER response is :')
print(msg_recv_dict[0])
print('\nnow we will execute TEARDOWN to disconnect with server')
str_teardown_header = self.gen_teardown_header(url, realm_value, nonce_value, session_value)
if config_dict['header_normal_modify_allow'] & config_dict['teardown_header_modify']:
str_teardown_header = self.add_normal_header_according_to_protocol(str_teardown_header)
elif config_dict['header_overload_modify_allow'] & config_dict['teardown_header_modify']:
str_teardown_header = self.add_overload_header_according_to_protocol(str_teardown_header)
self.socket_send.send(str_teardown_header.encode())
msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
msg_recv_dict = msg_recv.split('\r\n')
print('the GET_PARAMETER response is :')
print(msg_recv_dict[0])
print('program execute finished, thank you')
self.socket_send.close() def __del__(self):
# self.socket_send.close()
pass if __name__ == '__main__':
rtsp_client = RtspClient()
rtsp_client.exec_full_request()
#rtsp_client.exec_force_request()
参考:
https://www.cnblogs.com/MikeZhang/archive/2012/10/29/rtspTcpClient_DSS_20121029.html
https://blog.csdn.net/joeblackzqq/article/details/22383005
https://docs.python.org/3/library/index.html
https://tools.ietf.org/html/rfc2326#page-40
python3实现的rtsp客户端脚本的更多相关文章
- CentOS7 安装Python3,开发SocketIO 客户端
CentOS7安装Python3,开发SocketIO 客户端 参考:https://blog.csdn.net/lovefengruoqing/article/details/79284573 步骤 ...
- webControls与客户端脚本路径
网上有用的资料不多,在一本电子书中摘抄了内容如下 webControls配置节只有一个clientScriptsLocation属性,此属性用于指定ASP.NET客户端脚本的默认存放路径.这些文件是包 ...
- 教你50招提升ASP.NET性能(八):检查你使用了什么客户端脚本
(14)Review what client scripts you are using 招数14: 检查你使用了什么客户端脚本 Out of the box, many ASP.NET projec ...
- PHP漏洞全解(三)-客户端脚本植入
本文主要介绍针对PHP网站的客户端脚本植入攻击方式.所谓客户端脚本植入攻击,是指将可以执行的脚本插入到表单.图片.动画或超链接文字等对象内.当用户打开这些对象后,黑客所植入的脚本就会被执行,进而开始攻 ...
- 客户端脚本语言javascript
2015.11.27 客户端脚本语言javascript. (叫这个名字的原因.想要攀高枝,希望变得和他一样通用.关于名字之间的关系类似于雷锋和雷峰塔,巴基斯坦和卡巴斯基,苏格拉底跟格拉苏蒂的关系一 ...
- 【ASP.NET】从服务器端注册客户端脚本
一.在Asp.net 服务端处理脚本,一般都用 ClientScriptManager ,即web窗体服务端的this.ClientScript.该对象比较常用的方法: 1.RegisterArray ...
- js前台与后台数据交互-后台调前台(后台调用、注册客户端脚本)
转自:http://blog.csdn.net/wang379275614/article/details/17049721 客户端脚本一般都在前台,这里讲的是(1)在后台调用前台定义的脚本(2)在后 ...
- 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(五)用户接口层之提取媒体流数据
当RTSP客户端向RTSP服务端发送完PLAY命令后,RTSP服务端就会另外开启UDP端口(SDP协商定义的端口)发送RTP媒体流数据包.这些数据包之间会间隔一段时间(毫秒级)陆续被发送到RTSP客户 ...
- 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(四)用户接口层之处理SDP报文
当RTSP客户端向RTSP服务端发送DESCRIBE命令时,服务端理应当回复一条SDP报文. 该SDP报文中包含RTSP服务端的基本信息.所能提供的音视频媒体类型以及相应的负载能力,以下是一段SDP示 ...
随机推荐
- React组件导入的两种方式(动态导入组件的实现)
一. react组件两种导入方式 React组件可以通过两种方式导入另一个组件 import(常用) import component from './component' require const ...
- 基于 Python 和 Pandas 的数据分析(1)
基于 Python 和 Pandas 的数据分析(1) Pandas 是 Python 的一个模块(module), 我们将用 Python 完成接下来的数据分析的学习. Pandas 模块是一个高性 ...
- 蚂蚁金服 Service Mesh 渐进式迁移方案|Service Mesh Meetup 实录
小蚂蚁说: 本文是基于在 Service Mesher Meetup 上海站的主题分享<蚂蚁金服 Service Mesh 渐进式迁移方案>内容整理,完整的分享 PPT 获取方式见文章底部 ...
- [Python]IO密集型任务 VS 计算密集型任务
所谓IO密集型任务,是指磁盘IO.网络IO占主要的任务,计算量很小.比如请求网页.读写文件等.当然我们在Python中可以利用sleep达到IO密集型任务的目的. 所谓计算密集型任务,是指CPU计算占 ...
- XMind 8 Update 7 Pro 激活码
XMind Update Pro 邮箱:x@iroader 序列号: XAka34A2rVRYJ4XBIU35UZMUEEF64CMMIYZCK2FZZUQNODEKUHGJLFMSLIQMQUCUB ...
- 封装微信小程序支付
<?php /** * User: Eden * Date: 2019/3/21 * 共有内容 */ namespace Common\Service; use Think\Exception; ...
- django 消息框架 message
在网页应用中,我们经常需要在处理完表单或其它类型的用户输入后,显示一个通知信息给用户. 对于这个需求,Django提供了基于Cookie或者会话的消息框架messages,无论是匿名用户还是认证的用户 ...
- R语言矩阵栅格显示矩阵颜色显示
效果如下:
- webpack初识
1.什么是Webpack WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等) ...
- 修改Anaconda中的Jupyter Notebook默认工作路径
这二天,安装了anaconda想更改jupyter的工作路径,在网上找了一下 方式1. 打开Windows的cmd,在cmd中输入jupyter notebook --generate-config如 ...