CTF-reverse_RC4那些事儿
0x00 RC4加密知识点
推荐看这位up主的视频https://www.bilibili.com/video/BV1G64y1Y7p4/?spm_id_from=333.1391.0.0&p=2
简单来说RC4算法包括两部分KSA(利用Key生成S盒)和PRGA(利用S盒生成密钥流):
KSA:
- 初始化S(一般是0-255)
- 初始化K(循环填充密钥key)
- 利用K来打乱S
PRGA:
生成密钥流进行异或加密
所以我们的思路就是按照原来的KSA和PGRA算法来得到密钥流,利用异或加密的对称性求解,下面以几道题来深入理解ctf中的rc4解密套路
0x01 [GHCTF 2024 新生赛]UP+
1.做题过程
拖入DIE中,32位,upx壳
用upx -d
解壳发现报错
我们用010editor打开,将ZVM修改为UPX(55 50 58)
再次upx -d
脱壳
在ida中打开,发现是很标准的RC4算法:
于是手搓脚本
2.EXP
key='justfortest'
S=[]
K=[]
enc_flag=[0x42,0xFD,0x55,0x61,0xB9,0x27,0x6F,0xF5,0xB6,0x86,0x23,0xA9,0xEF,0x1C,0x4,0x9F,0xD4,0x16,0x87,0xD6,0x54,0x68,0xBC,0x2,0x15,0x6D,0x30,0x8,0x4B,0x61,0x4C,0x5E]#这里注意xmmword_402140在前面,xmmword_402130在后面
flag=[]
v5=0
for i in range(0,256):S.append(i)K.append(ord(key[i%len(key)]))
for i in range(0,256):v5=(v5+S[i]+K[i])%256temp=S[v5]S[v5]=S[i]S[i]=temp#以上是KSA算法,就是copy伪码
i,j=0,0
for k in range(0,len(enc_flag)):i=(i+1)%256j=(S[i]+j)%256S[i],S[j]=S[j],S[i]flag.append(enc_flag[k]^S[(S[i]+S[j])%256])#这里是PGRA算法,注意密钥流并不是一次性生成的,而是边加密边生成的
print("".join(map(chr,flag)))
这里值得注意的是刚开始我以为密钥流是一次性生成的,最后再依次加密,但是加密过程其实是在密钥流生成的过程中进行的
Get_flag:NSSCTF{4950b6562657477e6685828e537f43e5}
3.其他
当然在cyberchef中可以直接梭(找到密文,密钥即可)
只是这道题比较典型,手搓脚本可以更好地理解rc4算法的逻辑,今后识别到rc4算法,只需要找到密文和密钥就可以到cyberchef中一把梭了
0x02 [SWPUCTF 2022 新生赛]pypy
1.做题思路
得到一个pyc文件,在在线网站反编译python反编译 - 在线工具
题目比较简单,直接在源码的基础上写脚本,只需要把输入的text换为后面的res数组就可以了,这道题先是生成的密钥流再逐个异或的,而不是边生成边异或
2.EXP
def init_S():for i in range(256):S.append(i)
def init_T():global KeyKey = 'abcdefg'keylen = len(Key)for i in range(256):tmp = Key[i % keylen]T.append(tmp)
def swap_S():j = 0for i in range(256):j = (j + S[i] + ord(T[i])) % 256tmp = S[i]S[i] = S[j]S[j] = tmp
def Get_KeyStream():txtlen = len(text)(j, t) = (0, 0)for i in range(txtlen):i = i % 256j = (j + S[i]) % 256tmp = S[i]S[i] = S[j]S[j] = tmpt = (S[i] + S[j]) % 256KeyStream.append(S[t])
def Get_code():res = []for i in range(len(text)):res.append(text[i] ^ KeyStream[i])return res
if __name__ == '__main__':T = []S = []Key = []PlainText = ''CryptoText = ''KeyStream = []# text = input('please input you flag:\n')text=[84,91,254,48,129,210,135,132,112,234,208,15,213,39,108,253,86,118,248]init_S()init_T()swap_S()Get_KeyStream()res = Get_code()print("".join(map(chr, res)))# for i, ele in enumerate(res):# if not ele == [# 84,# 91,# 254,# 48,# 129,# 210,# 135,# 132,# 112,# 234,# 208,# 15,# 213,# 39,# 108,# 253,# 86,# 118,# 248][i]:# print('bad')# exit()# print('good')
Get_flag:NSSCTF{this_is_rc4}
0x03 [LitCTF 2025]easy_rc4
1.做题思路
ida打开
这里看到又是’FenKey!!‘,多留了一个心眼,按x查看引用情况,发现只有这个函数引用了,所以key就是’FenKey!!’
看了rc4_init和标准的KSA是一样的,但是PRGA魔改了
问题不大,还是提取密文和密钥,到cyberchef中,多加个异或就行了:
Get_flag:LitCTF{71bb2a06417a5306ba297ddcfce7b1b0}
(www动调还不是很熟练,很多师傅都用的是动调,后面还得学啊)
0x04 写在最后的
做了几道RC4的题,其实这就是一个对称加密,可能会魔改。一般思路就是找到key和密文,上cyberchef梭,或者编写脚本进行破解,还有就是动调(这个还不太会),但是RC4一般不会作为一个单独的考点出现,可能会和upx壳,反动调等等其他知识点出现,但是本次练习主要是学习一下RC4的最最最基本原理,后面会学习其他的相关知识。