AES加密

  • AES(Advanced Encryption Standard),高级加密标准,是一种对称加密算法,用于保护电子数据。
  • AES加密主要有以下特点
    • 对称加密:AES使用同一个密钥进行加密和解密,这意味着加密和解密的双方必须共享同一个密钥。
    • 分组加密:AES是一种分组加密算法,它将明文分成固定大小的块(通常是128比特),然后对每个块进行加密
    • 密钥长度:AES支持三种不同的密钥长度:128位、192位和256位。密钥越长,安全性越高,但相应的计算复杂度也会增加。
    • 算法结构:AES采用了一种称为“Rijndael”的算法。AES的加密过程包括多个轮的替换和置换操作,这些操作增加了数据的混淆和扩散效果
    • 应用广泛:由于其高效性和安全性,AES被广泛应用于各种领域,包括网络通信、文件加密、硬盘加密和无线通信等。
  • AES的分类:AES加密算法可以根据不同的工作模式具体分类
    • 块加密:AES-ECB模式
    • 块加密:AES-CBC模式
    • 块加密:AES-CFB模式
    • 块加密:AES-OFB模式
    • 块加密:AES-CTR模式
    • 流加密:AES-CTR模式
    • 流加密:AES-CFB模式
    • 流加密:AES-OFB模式
    • 特殊模式:AES-GCM模式
  • AES加密方式:AES加密方式是根据密钥的长度进行分类
    • AES-128
    • AES-192
    • AES-256

AES加解密过程

  • AES是对称加密,所以AES的解密函数与AES的加密函数是相同的

image-20240709133233385

image-20240709133244003

AES-ECB加密

AES-128 ECB加密—一看就懂,图文并茂-电子芯吧客(www.icxbk.com)

AES-ECB加解密过程

  • 分块处理:

    • 明文被分成固定大小的块,每块通常是128位(16字节)
    • 如果明文长度不是块大小的整数倍,最后一个块需要填充(通常使用PKCS#7填充
  • 密钥选取与生成:

    • AES加密算法支持三种不同的密钥长度,128位(16字节)、192位(24字节)和256位(32字节)
    • 使用随机数生成器来生成密钥,密钥是随机的以确保安全性。
  • 逐块加密:

    • 每个块独立地使用AES加密算法进行加密
    • 每个块单独加密,没有任何块之间的链接或依赖
  • AES-ECB加密步骤(以AES-128为例):对于初学者而言,只需要了解大致步骤即可,具体怎么进行加密的可以等后续再了解

image-20240709143534699

AES-ECB加密初步原理

  • AES-ECB加密首先输入明文
    • 将这些明文转化为16进制的ASCII值。
    • 将这些明文以16字节为一组进行分块处理。如果明文的字节数不是16进制,那么就会将最后一块明文块,按照某种填充方式,使其达到16字节

image-20240709145020534

  • 然后再随机生成一个密钥,或者自定义一个密钥,密钥的长度也必须满足128位、192位、256位
  • 然后明文块再与密钥一起,经过AES加密,输出密文块。密文块同样也是128bit

image-20240709145446628

  • ECB加密模式要注意的是,每个明文块都是使用相同的密钥进行加密的。这也就是说相同的明文会输出相同的密文。

image-20240709145739809

AES-ECB加密算法

AES-ECB加密的攻击

  • 初步了解了ECB加密的初步原理后,就可以尝试破解AES-ECB加密

选择明文攻击法

  • 该方法是利用相同的明文块经过加密后,会产生相同的明文块。这样就可以进行逐个字节的爆破,从而得到flag

例题

  • 以最近做过的一题国外CTF比赛为例子:
  • 题目描述如下:
image-20240709150619252
  • 中文翻译过来如下:

image-20240709150711801

  • 先nc一下连接靶机,看看靶机上的程序是如何运行的
    • 发现nc过后系统会将flag经过AES-ECB加密后的密文输出过来

image-20240709150943318

  • 然后再看密文上面的字,可以得到信息,用户可以输入base64编码的数据,然后靶机会重新加密,并输出重新加密过后的密文

image-20240709151143340

首先需要确定明文个数

  • 先将得到的密文进行base64解码,解码成16进制的形式

image-20240709152215899

  • 然后以两个十六进制数为1组,进行加密的明文一共有多少字节多少块
    • 发现密文解码后一共有48个字节,所以以16字节为一组的明文块,一共就有3块。初步得出明文flag的长度在32-48字节直接
1
2
3
a = '1F478C9B50E20C146B2204BDFBF8CD85D3439B280CB59A64E5E0EDD7D99F03C4BFC4606660026280E174A847FFB02A24'
print(len(a)//2)
# 48
  • 然后再进行明文填充,先输入a查看密文字节数有没改变,如果没有改变再输入aa。如果还是没有改变继续增加a的个数,然后输入进去,再检查发送过来的密文字节数
  • 这里发现当发送一个a过后密文的字节数就改变了,这就可以得到明文flag的长度为47个字节这里为什么为47个字节,而不是48个字节,是与明文块的填充方式有关
1
2
3
4
5
a
YQ==
Ox9sMgy8iPF+LWBlBwtjJGBSmwwwbV7xXyxQlUuyTQ3FLNVyTeQw42geSIGnLBj7YS+OVO/90ZQVLsGHBSULcQ==
3B1F6C320CBC88F17E2D6065070B632460529B0C306D5EF15F2C50954BB24D0DC52CD5724DE430E3681E4881A72C18FB612F8E54EFFDD194152EC18705250B71
64字节

image-20240709154556682

  • 然后确定了明文长度,就可以通过相同明文加密后的密文是相同的进行逐个字节爆破,最后得到flag
  • 逐个字节爆破过程如下,这里为了更好的演示就直接利用本题flag进行爆破演示 grodno{a50f00AES_1n_ECB_m0de_1s_hackableaf1aef}
image-20240709160012538
  • 爆破过程如下,先构造payload='aaaaaaaaaaaaaaa?(可见字符)aaaaaaaaaaaaaaag'
  • 然后对发送出来的密文块1,密文块2进行判断是否相同,如果相同即可得出可见字符(?)对应的字符是g,那么flag第一个字符就给爆破出来了

image-20240709161321126

  • 然后再进行第二个字符的爆破

image-20240709162040136

  • exp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from pwn import *
import base64
from Crypto.Cipher import AES
import string
def recv():
p.recvuntil(b'ciphertext (b64): ')
return base64.b64decode(p.recvline().strip())
def send(m):
p.sendline(base64.b64encode(m.encode('utf-8')))
p = remote('ctf.mf.grsu.by',9016)
p.recvuntil(b'secret ciphertext (b64): ')
enc_flag = base64.b64decode(p.recvline().strip())
print(enc_flag)
charr = string.printable
l = b'a'
length= 48
flag = ''
for i in range(47):
for ch in charr:
send('a'*(length-1)+flag+ch+'a'*(length-1))
res=recv()
panduan = res[:48]
en = res[48:96]
if panduan==en:
flag+=ch
length-=1
print(flag)
break
print(flag)

image-20240709163408498

改变密文顺序法

AES-CBC加密