3.18学习——RC4加密的学习(理论+例题)

RC4加密原理

RC4算法是一种对称算法,这个算法最基本的原理通俗的说就是对一串字符串进行两次异或得到的结果还是其本身,下面看加密过程
RC4的加解密分为初始化、产生密钥流、加解密三部分

1、先初始化状态向量S(初始化S盒)

S盒中填充了256个字节,然后按照升序赋值:0,1,2,···,255;

2、输入初始密钥

这个密钥由作者输入,长度任意,但是如果小于256个字节,就会进行填充,例如:输入12345,那么密钥就会是12345 12345 12345···,这样得到的内容一般被规定为T

3、混淆s盒——KSA过程

将T填充到S盒中,将T中的字符转化为ASCII码,接着运用公式:

j = (j + s_box[i] + 当前密钥字符的ASCII值) % 256

例如:输入密钥为Key(ASCII码为75,101,121),初始S盒数据为s=[0,1,2,···,255],密钥为T=[K,e,y,K,e,···,e]
计算j
1.当i=0时
j = (0 + 0 + 75) % 256 = 75;
那么根据公式,就交换0和75的位置,那么S盒就变成了[75,1,2,···,0,76,···,255]
2.当i=1时
j = (75 + 1 + 101) % 256 = 177;
根据公式就是S盒中的1和177交换位置
以此类推,重复执行255次得到被打乱的S盒

4.计算密钥流字节——PRGA流程

当完成了混淆S盒后才会进入这个环节,会初始化i和j
i=0;j=0
这里用到了这个公式:

密钥流字节 = S[(S[i] + S[j]) % 8]

还是举例来说:
假设混淆后的S盒为(为了简化计算,假设s盒有8个字节)

[66,88,25,63,···,36]

对于第一个密钥流字节
更新i

i = (0 + 1) % 8 = 1

更新j

j = (0 + s_box[1]) % 8 = (0 + 88) % 8 = 0  

交换i与j,那么就更新了S盒

[88,66,25,63,···,36]

接着就是用上面的那个公式
第一个字节=(88+66)%8=2,这个2对应s盒中的25,将其转化为16进制0x17,以此类推就完成对每一个字符的加密

尝试用Python实现RC4加解密

根据上面提到的原理便可以用python写一个这样的加解密脚本

def KSA(key):
    key = key.encode('utf-8')
    s_box = list(range(256))  # 初始化S盒
    j = 0
    for i in range(256):
        j = (j + s_box[i] + key[i % len(key)]) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]  # 交换元素
    return s_box

def PRGA(s_box):
    i = 0
    j = 0
    while True:
        i = (i + 1) % 256
        j = (j + s_box[i]) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
        yield s_box[(s_box[i] + s_box[j]) % 256]  # 生成密钥流

def RC4_process(data: bytes, key: str) -> bytes:
    """RC4加密/解密函数"""
    s_box = KSA(key)
    key_stream = PRGA(s_box)
    return bytes([byte ^ next(key_stream) for byte in data])

# 用户交互
mode = input("请选择模式(1加密/2解密):").strip()
key = input("输入密钥:").strip()

if mode == '1':
    plaintext = input("输入明文:").strip()
    cipher_bytes = RC4_process(plaintext.encode('utf-8'), key)
    print("加密结果为:", cipher_bytes.hex())
    
elif mode == '2':
    cipher_hex = input("输入密文:").strip()
    try:
        cipher_bytes = bytes.fromhex(cipher_hex)
        decrypted_bytes = RC4_process(cipher_bytes, key)
        print("解密结果:", decrypted_bytes.decode('utf-8', errors='replace'))
    except ValueError:
        print("错误:无效的十六进制格式!")
        
else:
    print("无效的模式选择!")

验证:
在这里插入图片描述

例题

1.[SWPUCTF 2021 新生赛]简简单单的解密

这题就是单纯考察对RC4加密的认识,明文和密钥都给了,只需要使用脚本即可在这里插入图片描述

2.[GHCTF 2025]FishingKit

先查壳,发现没壳,用ida打开查看主调函数。
在这里插入图片描述可以看到,这里是比较了V4和一串字符,就去追踪与V4加密有关的那个函数sub_7FF7CABD1150在这里插入图片描述发现要求出a1的值,观察了一下出现了a1到a1[9],推断a由10个字节组成,我的理解是一个15元一次方程组联立求解得到每一个字节,根据查询搜索,得知可以用Z3数组约束法来求解在这里插入图片描述解得DeluxeBait
接着回去看主调函数,发现好像一直都是一个函数,就回去看汇编流程图在这里插入图片描述看到strcmp()函数和str1,str2,感觉像是第二个判断条件,倒着追踪上去,发现sub_7FF7CABD2460函数是一个RC4加密在这里插入图片描述继续追踪在这里插入图片描述这里可以确定是RC4加密,但是是个变种,因为这里按照加密流程是先进行RC4加密,之后再与0x14进行异或
先找到str2的值在这里插入图片描述在这里插入图片描述

逆向的话需要将这个加密流程倒过来,先与0x14异或,再进行RC4解密
在这里插入图片描述结果发现解了个寂寞,回去在比较处下了个断点,F7步入看看是怎么比较的,结果发现这里调用了jmp(无条件跳转),来到了sub_7FF7CABD1CE0在这里插入图片描述在这里插入图片描述进去看看,发现是一个新的加密过程,发现24位密文是byte_7FF7CABD63C8,点进去没发现内容,发现是交叉引用,就用交叉引用看看在这里插入图片描述但是单纯用交叉引用也找不到,就采用在引用地址处下断点动调来找在这里插入图片描述这里可以发现,当步入这个函数时右边RCX里储存了密文,就可以在RCX里面直接读取密文,接下来去找加密思路
定位到加密函数地址sub_7FF6CF801CE0在这里插入图片描述根据搜索和AI,得知是xtea加密算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值