【ECB模式攻击原理】
(参考https://zachgrace.com/posts/attacking-ecb/)
![[Crypto]ECB模式攻击](https://javaforall.net/wp-content/uploads/2020/11/2020110817443450.jpg)
XXXXXXAA AAAAAAAA AAAAAAXX
XXXXXXBA AAAAAAAA AAAAAAAX
XXXXXXBB AAAAAAAA AAAAAAAA
这时会得到填充块的一个密文输出,爆破最后一个字节,直到产生与刚才相同的密文输出,就可以确定未知字符串的一个字节,重复这个过程就可以得到完整的未知字符串。
【攻击方法】
向包含未知字符串的明文中插入数据,其实也是枚举验算的过程:
1.获取未知字符串的第一位
比输入name为1,
服务器生成未知字符串”hello, 1, your mission’s flag is: FLAGXXXXXX”的用ecb加密过的字符串S1给我们,
其中FLAGXXXXXX是我们希望得到的flag,通过观察题目程序可知,此处ECB使用的是16位的,
进而观察可知,16个字符的字符串加密后就变成32个字符的密文了。
就是说”hello, 1, your mission’s flag is: X”的最后一个X刚好是第32位,我们首先通过这个32字符的字符串获取一下加密过的encrypto, 也就是64个字符的字符串S2,那么这个S2必然是S1的前64位。
然而我们刚开始并不知道这个X是什么,于是我们枚举这个X,令X为一个ascii字符,
比如向服务器发送”hello, 1, your mission’s flag is: A”,获取密文,如果这个密文恰好是S1的前64位,那么A就是flag未知字符串的第一位,于是我们就激活成功教程了flag的第一位。
2.获取未知字符串的剩余位
因为A已经是flag的第一位,根据激活成功教程的原理,我们要把未知字符放在第32位(此处和第一步一样取一个合理的16的倍数)
那么我们只要把name的名字长度缩小一个字符就可以了
即此时变为 “hello, , your mission’s flag is: AX”
(可以对照第一步的字符“hello, 1, your mission’s flag is: A”)
依然枚举X即可,以此类推,获取全部的字符串(此处以”}”为结尾标志)
【代码】
主程序代码:
#!/usr/bin/env python # coding=utf-8 import conn import os number = 30 + 16 mess = "hello, 1, your mission's flag is: moeflag{" ans = "" while (number >= 0): found = False conn.remote("YourIp", 8001) conn.reads() mess = "1" * number conn.sends(mess) # print("发送 " + mess) initialdata = conn.reads() # print("原始 "+initialdata) blockdata = initialdata[0:128 + 32] # print("前端 \n"+blockdata) # print(initialdata) # print("----------") array = "mqmwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0{}_-~!@#$%^&*()-=+[]?><'|,./`\"m" #枚举的集合 for i in array: conn.reads() # print("尝试 "+i) mess = "hello, " + "1" * number + ", your mission's flag is: " + ans + i conn.sends(mess) data = conn.reads() # print(data) # print data if data[0:128 + 32] == blockdata: found = True print("发现 " + i) ans += i number = number - 1 if i == "}": number = -1 print("答案:" + ans) os.system("pause") # message=message+i break conn.close() if not found : print("没有找到~~") os.system("pause") print(ans)
组件conn的代码
import socket import os obj = None def remote(addr, ip): global obj obj = socket.socket() obj.connect((addr, ip)) def reads(): global obj ret_bytes = obj.recv(1024) ret_str = str(ret_bytes, encoding="utf-8") #print(ret_str) return ret_str def sends(content): global obj obj.sendall(bytes(content + "\n", encoding="utf-8")) def close(): global obj obj.close()
注:这两个代码需要放在同级目录下,只要运行main就可以了
【编写调试中的问题】
1.连接socket服务器后,能 收到服务器消息, 但是发送客户端发送数据后,却收不到服务器回复。
见https://blog.csdn.net/u0/article/details/
这可能是因为输入的字符串最后没有 换行符,导致服务器认为输入未结束。
2.程序运行到一定程度后没有输出反应:
可能有这么几个原因:
原因1:枚举的字符集合不够大,有些flag中例如“=”这样的数据没有包含进去。也可以采用转ascii,这样更完整,但是运算速度就降低了。
原因2:flag位数太大, 移位以后还不够,可以 分批运行程序,也可以扩大初始name的长度
3.本来也可以用python中的pwn来做,但是Windows下面用pip来安装pwn经常出现错误,linux下,更新了国内源后,即便下载成功,安装 也会出错。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/222163.html原文链接:https://javaforall.net
