CTF密码学之RC4

介绍

在密码学中,RC4(来自Rivest Cipher 4的缩写)是一种流加密算法,密钥长度可变。它加解密使用相同的密钥,因此也属于对称加密算法。RC4是有线等效加密(WEP)中采用的加密算法,也曾经是TLS可采用的算法之一。

加密过程

参数作用
S-box(S)256长度的char型数组,定义为: unsigned char sBox[256]
Key(K)自定义的密钥,用来打乱 S-box
pData用来加密的数据
  1. 初始化 S (256字节的char型数组),key 是我们自定义的密钥,用来打乱 S ,i 确保 S-box 的每个元素都得到处理, j 保证 S-box 的搅乱是随机的

    /*初始化函数*/
    void rc4_init(unsigned char*s, unsigned char*key, unsigned long Len)
    {
    	int i = 0, j = 0;
    	char k[256] = { 0 };
    	unsigned char tmp = 0;
    	for (i = 0; i < 256; i++)
    	{
    		s[i] = i; // 赋值 S
    		k[i] = key[i%Len]; // 赋值 K 
    	}
    	for (i = 0; i < 256; i++)
    	{
    		j = (j + s[i] + k[i]) % 256; // 开始混淆
    		tmp = s[i]; 
    		s[i] = s[j]; // 交换s[i]和s[j]
    		s[j] = tmp;
    	}
    }
    
  2. 加密过程将 S-box 和明文进行 xor 运算,得到密文,解密过程也完全相同

    /*加解密*/
    void rc4_crypt(unsigned char*s, unsigned char*Data, unsigned long Len)
    {
    	int i = 0, j = 0, t = 0;
    	unsigned long k = 0;
    	unsigned char tmp;
    	for (k = 0; k < Len; k++)
    	{
    		i = (i + 1) % 256;
    		j = (j + s[i]) % 256;
    		tmp = s[i];
    		s[i] = s[j]; // 交换s[x]和s[y]
    		s[j] = tmp;
    		t = (s[i] + s[j]) % 256;
    		Data[k] ^= s[t];
    	}
    }
    

实现

下面是 C 实现的代码

#include<stdio.h>
#include<string.h>
typedef unsigned longULONG;

/*初始化函数*/
void rc4_init(unsigned char*s, unsigned char*key, unsigned long Len)
{
	int i = 0, j = 0;
	char k[256] = { 0 };
	unsigned char tmp = 0;
	for (i = 0; i < 256; i++)
	{
		s[i] = i;
		k[i] = key[i%Len];
	}
	for (i = 0; i < 256; i++)
	{
		j = (j + s[i] + k[i]) % 256;
		tmp = s[i];
		s[i] = s[j]; // 交换s[i]和s[j]
		s[j] = tmp;
	}
}

/*加解密*/
void rc4_crypt(unsigned char*s, unsigned char*Data, unsigned long Len)
{
	int i = 0, j = 0, t = 0;
	unsigned long k = 0;
	unsigned char tmp;
	for (k = 0; k < Len; k++)
	{
		i = (i + 1) % 256;
		j = (j + s[i]) % 256;
		tmp = s[i];
		s[i] = s[j]; // 交换s[x]和s[y]
		s[j] = tmp;
		t = (s[i] + s[j]) % 256;
		Data[k] ^= s[t];
	}
}

int main()
{
	unsigned char s[256] = { 0 }, s2[256] = { 0 }; // S-box
	char key[256] = { "justfortest" };
	char pData[512] = "这是一个用来加密的数据Data";
	unsigned long len = strlen(pData);
	int i;

	printf("pData=%s\n", pData);
	printf("key=%s,length=%d\n\n", key, strlen(key));
	rc4_init(s, (unsigned char*)key, strlen(key)); // 已经完成了初始化
	printf("完成对S[i]的初始化,如下:\n\n");
	for (i = 0; i < 256; i++)
	{
		printf("%02X", s[i]);
		if (i && (i + 1) % 16 == 0)putchar('\n');
	}
	printf("\n\n");
	for (i = 0; i < 256; i++) // 用s2[i]暂时保留经过初始化的s[i],很重要的!!!
	{
		s2[i] = s[i];
	}
	printf("已经初始化,现在加密:\n\n");
	rc4_crypt(s, (unsigned char*)pData, len); // 加密
	printf("pData=%s\n\n", pData);
	printf("已经加密,现在解密:\n\n");
	rc4_crypt(s2, (unsigned char*)pData, len); // 解密
	printf("pData=%s\n\n", pData);
	return 0;
}

运行结果如下

C:\Users\thunder>"D:\AlgorithmTest.exe"
pData=这是一个用来加密的数据Data
key=justfortest,length=11

完成对S[i]的初始化,如下:

21E0944A8CAA5C851A95374358840E32
EE3AF7C8F67F898BFF52235F3B51CAE6
31E2A570C698C046CE836EB91EBC9235
FD6B1CB62C2D69B565631B933EA60762
13EAE7775BA159DD745491C181B7FB49
66037D2E47331538F8A820AE22D2345A
64FA3F87714DFCBF2490D32ADF9EB85E
0A2780E40CAD1497E3D8C7F2F4424176
DC8D45A9789DE1B0D9044F0F36C3C5BE
4C7AEB6C4B8640E59A7919B39BABAFE8
C4AC8EFE963CEDEF0B091202BAB1D001
CB60D4F91D557BCC7544D750F17E67C9
88DB111826F0B299B4BB482BA41FF58A
C2E9A0CF5DDA6FCD57003D0830A2A316
9F0D6AF36D682F8FBD28A7DE4ED15373
7C2956D51706058225EC617210399CD6


已经初始化,现在加密:

pData=?獤       5Ws?g&W鋟覈?T?

已经加密,现在解密:

pData=这是一个用来加密的数据Data


C:\Users\thunder>

上面的代码是rc4加密字符串这是一个用来加密的数据Data,key = justfortest,我们放入IDA观察,初始化函数如下

void __cdecl rc4_init(char *s, char *key, unsigned int Len)
{
  char tmp; // STDF_1
  char k[256]; // [esp+DCh] [ebp-120h]
  int j; // [esp+1E4h] [ebp-18h]
  int i; // [esp+1F0h] [ebp-Ch]

  j = 0;
  k[0] = 0;
  j__memset(&k[1], 0, 0xFFu);
  for ( i = 0; i < 256; ++i )
  {
    s[i] = i;
    k[i] = key[i % Len];
  }
  for ( i = 0; i < 256; ++i )
  {
    j = (k[i] + j + (unsigned __int8)s[i]) % 256;
    tmp = s[i];
    s[i] = s[j];
    s[j] = tmp;
  }
}

加密函数如下

void __cdecl rc4_crypt(char *s, char *Data, unsigned int Len)
{
  char tmp; // STD3_1
  unsigned int k; // [esp+DCh] [ebp-2Ch]
  int j; // [esp+F4h] [ebp-14h]
  int i; // [esp+100h] [ebp-8h]

  i = 0;
  j = 0;
  for ( k = 0; k < Len; ++k )
  {
    i = (i + 1) % 256;
    j = (j + (unsigned __int8)s[i]) % 256;
    tmp = s[i];
    s[i] = s[j];
    s[j] = tmp;
    Data[k] ^= s[((unsigned __int8)s[j] + (unsigned __int8)s[i]) % 256];
  }
}

辨别

从IDA中可以看到有很多的 %256 操作,因为 s 盒的长度为256,所以这里很好判断,如果在CTF逆向过程中看到有多次 %256 的操作最后又有异或的话那可以考虑是否是RC4密码

解密

python实现如下

# -*- coding: utf-8 -*-
import random, base64
from hashlib import sha1
 
def crypt(data, key):
    """RC4 algorithm"""
    x = 0
    box = range(256)
    for i in range(256):
        x = (x + box[i] + ord(key[i % len(key)])) % 256
        box[i], box[x] = box[x], box[i]
    x = y = 0
    out = []
    for char in data:
        x = (x + 1) % 256
        y = (y + box[x]) % 256
        box[x], box[y] = box[y], box[x]
        out.append(chr(ord(char) ^ box[(box[x] + box[y]) % 256]))
 
    return ''.join(out)
 
 
def tencode(data, key, encode=base64.b64encode, salt_length=16):
    """RC4 encryption with random salt and final encoding"""
    salt = ''
    for n in range(salt_length):
        salt += chr(random.randrange(256))
    data = salt + crypt(data, sha1(key + salt).digest())
    if encode:
        data = encode(data)
    return data
 
 
def tdecode(data, key, decode=base64.b64decode, salt_length=16):
    """RC4 decryption of encoded data"""
    if decode:
        data = decode(data)
    salt = data[:salt_length]
    return crypt(data[salt_length:], sha1(key + salt).digest())
 
 
if __name__ == '__main__':
    # 需要解密的数据
    data = 'UUyFTj8PCzF6geFn6xgBOYSvVTrbpNU4OF9db9wMcPD1yDbaJw=='
    # 密钥
    key = 'welcometoicqedu'
    # 解码
    decoded_data = tdecode(data=data, key=key)
    print("明文是:")
    print decoded_data

输出如下

[Running] python -u "/home/thunder/Desktop/CTF/crypt/example/rc4_example/test.py"
明文是:
flag{rc4_l_keepgoing}

[Done] exited with code=0 in 0.14 seconds

在线解密网站:https://www.sojson.com/encrypt_rc4.html

参考链接:

https://blog.csdn.net/Fly_hps/article/details/79918495

https://baike.baidu.com/item/RC4/3454548?fr=aladdin

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值