BJDCTF-encode(rc4)

一道RC4的题目,还改了base64的表,顺便学了一下RC4加密

先查壳,一开始没查壳,分析了好久。。。。

upx壳,直接upx -d encode

   

拖进ida分析,大致的流程分为

1.输入flag,判断长度

2.对输入进行改表的base64加密

3.进行第一轮异或

4.进行rc4加密

 这里介绍一下RC4加密

在密码学中,RC4(来自Rivest Cipher 4的缩写)是一种流加密算法,密钥长度可变。它加解密使用相同的密钥,因此也属于对称加密算法。RC4是有线等效加密(WEP)中采用的加密算法,也曾经是TLS可采用的算法之一。
RC4的原理分三步
1.生成s_box
2.打乱s_box
3.根据s_box进行加密
RC4加密源码
import base64
def rc4_main(key = "init_key", message = "init_message"):
    # print("RC4加密主函数")
    s_box = rc4_init_sbox(key)
    crypt = str(rc4_excrypt(message, s_box))
    return  crypt
def rc4_init_sbox(key):
    s_box = list(range(256))  # 我这里没管秘钥小于256的情况,小于256不断重复填充即可
    # print("原来的 s 盒:%s" % s_box)
    j = 0
    for i in range(256):
        j = (j + s_box[i] + ord(key[i % len(key)])) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
    # print("混乱后的 s 盒:%s"% s_box)
    return s_box
def rc4_excrypt(plain, box):
    # print("调用加密程序成功。")
    res = []
    i = j = 0
    for s in plain:
        i = (i + 1) % 256
        j = (j + box[i]) % 256
        box[i], box[j] = box[j], box[i]
        t = (box[i] + box[j]) % 256
        k = box[t]
        res.append(chr(ord(s) ^ k))
    # print("res用于加密字符串,加密后是:%res" %res)
    cipher = "".join(res)
    # print("加密后的字符串是:%s" %cipher)
    # print("加密后的输出(经过编码):")
    # print(str(base64.b64encode(cipher.encode('utf-8')), 'utf-8'))
    return (str(base64.b64encode(cipher.encode('utf-8')), 'utf-8'))
# rc4_main("123456sh","123456sh")

RC4解密源码

import base64
def rc4_main(key = "init_key", message = "init_message"):
    # print("RC4解密主函数调用成功")
    s_box = rc4_init_sbox(key)
    crypt = rc4_excrypt(message, s_box)
    return crypt
def rc4_init_sbox(key):
    s_box = list(range(256))  # 我这里没管秘钥小于256的情况,小于256不断重复填充即可
    # print("原来的 s 盒:%s" % s_box)
    j = 0
    for i in range(256):
        j = (j + s_box[i] + ord(key[i % len(key)])) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
    # print("混乱后的 s 盒:%s"% s_box)
    return s_box
def rc4_excrypt(plain, box):
    # print("调用解密程序成功。")
    plain = base64.b64decode(plain.encode('utf-8'))
    plain = bytes.decode(plain)
    res = []
    i = j = 0
    for s in plain:
        i = (i + 1) % 256
        j = (j + box[i]) % 256
        box[i], box[j] = box[j], box[i]
        t = (box[i] + box[j]) % 256
        k = box[t]
        res.append(chr(ord(s) ^ k))
    # print("res用于解密字符串,解密后是:%res" %res)
    cipher = "".join(res)
    # print("解密后的字符串是:%s" %cipher)
    # print("解密后的输出(没经过任何编码):")
    return  cipher
# rc4_main("123456sh", "ABHCum92PMOXwqI=")

根据rc4的加密过程,s_box是由程序生成的,我们只需要将其dump出来,或者自己生成即可,然后把转换后的s_box和输入异或即可

 这里程序中给的compare数据为“E8D8BD91871A1E56F53F4889682F96142AF2AB8FED7ACFD5E”

这个数据是不准确的,首先是位数不够,因为输入是21位,然后经过base64变成28位,然后经过hex是56位,给出的compare数据只有49位

正确的数据应该是“E8D8BD91871A010E560F53F4889682F961420AF2AB08FED7ACFD5E00”

#wrong
E8D8BD91871A1E56F53F4889682F96142AF2AB8FED7ACFD5E
#true
E8D8BD91871A010E560F53F4889682F961420AF2AB08FED7ACFD5E00

下面是解密脚本

import base64
s = "E8D8BD91871A010E560F53F4889682F961420AF2AB08FED7ACFD5E00"
enc = bytes.fromhex(s)
#generate convert s_box 
def rc4_init_sbox(key):
    s_box = list(range(256))
    j = 0
    for i in range(256):
        j = (j + s_box[i] + ord(key[i % len(key)])) % 256
        s_box[i],s_box[j] = s_box[j],s_box[i]
    i = 0
    j = 0
    tmp = []
    for i in range(28):
        i = (i + 1) % 256
        j = (j + s_box[i]) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
        t = (s_box[i] + s_box[j]) % 256
        k = s_box[t]
        tmp.append(k)
    return tmp

s_box = rc4_init_sbox("Flag{This_a_Flag}")
tmp = []
for i in range(0,len(enc)) : 
    tmp.append(enc[i]^s_box[i])
s = "Flag{This_a_Flag}"
l = list(s)
flag = []
for i in range(0,len(tmp)):
    flag.append((tmp[i] ^ ord(l[i%len(s)]))&0x7f)
for i in flag:
    print(chr(i),end='')
print()

#change base s1
= b'0123456789+/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ=' s2 = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' tmp = [] for i in flag: tmp.append(chr(s2[s1.find(i)])) for i in tmp: print(i,end='') c = bytes([s2[s1.index(i)] for i in flag]) #base64 from base64 import b64decode print(b64decode("QkpEezB2MF9ZMHVfZzA3XzFUIX0="))

 

posted @ 2022-12-01 14:51  写在风中的信  阅读(62)  评论(0编辑  收藏  举报