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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章