介绍

在密码学中,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; // 赋值 Sk[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-boxchar 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=这是一个用来加密的数据DataC:\Users\thunder>

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

void __cdecl rc4_init(char *s, char *key, unsigned int Len)
{char tmp; // STDF_1char 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_1unsigned 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 sha1def crypt(data, key):"""RC4 algorithm"""x = 0box = range(256)for i in range(256):x = (x + box[i] + ord(key[i % len(key)])) % 256box[i], box[x] = box[x], box[i]x = y = 0out = []for char in data:x = (x + 1) % 256y = (y + box[x]) % 256box[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 datadef 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

CTF密码学之RC4相关推荐

  1. CTF密码学总结(一)

    目录 CTF 密码学总结 题目类型总结: 简单密码类型: 复杂密码类型: 密码学脚本类总结: 单独的密文类型(优先使用ciphey工具) 多层传统加密混合: Bugku的密码学的入门题/.-:(摩斯密 ...

  2. [转]CTF密码学——常见编解码及加解密总结

    做了一些CTF密码学的题目,阅读了很多大神的博客,现在做个总结,不全面的之后补充. 目录 编码 进制表示 ASCII码对照表 unicode编码 URL编码 Escape/Unescape Base6 ...

  3. [CTF密码学]RSA相关题目解题方法与python脚本总结(附例题)

    目录 RSA算法概述 思路一.分解n得到p,q 例题:BUUCTF:[WUSTCTF2020]babyrsa 思路二.低加密指数攻击(e很小) 例题:BUUCTF DangrousRSA 思路三.低指 ...

  4. CTF密码学-编码基础知识点总结

    CTF密码学-编码基础知识点总结 0x01 目录 常见编码: 1.ASCII编码 2.Base64/32/16编码 3.shellcode编码 4.Quoted-printable编码 5.XXenc ...

  5. CTF密码学总结(二)

    目录 CTF 密码学总结 题目类型总结: 简单密码类型: 复杂密码类型: 文件相关类型: 算法类总结: 密码学脚本类总结: 单独的密文类型(优先使用ciphey工具) 多层传统加密混合: Bugku的 ...

  6. CTF密码学·置换密码,栅栏密码,曲路密码

    CTF密码学·置换密码,栅栏密码,曲路密码 1.置换密码 列置换 周期置换 2.栅栏密码 3.曲路密码 1.置换密码 置换密码(Permutation Cipher)又叫换位密码(Transposi- ...

  7. 杭电CTF 密码学(1)

    杭电CTF 密码学(1) 1.拿到 BAABAABBAAAAAAAABABBABABBBAABABAABBABBBAABBABAABAA 显而易见的培根密码,直接拿去翻译. 传说,丘比龙是丘比特的弟弟 ...

  8. CTF密码学Crypto1

    CTF密码学Crypto 1.Morse code(摩尔斯密码) 2. 栅栏密码 3. 恺撒密码 4.Ook!编码 5.Brainfuck编码 6.Base64编码 CTF解密工具: 1.http:/ ...

  9. CTF密码学题目初探(二)

    CTF密码学题目初探(二) 密码学总结(一) 1.换位加密 2.替换加密 密码学总结(一) 在上一篇文章里写了12种常见的编码,这一篇文章主要总结换位加密和替换加密. 1.换位加密 栅栏密码(Rail ...

最新文章

  1. SQL 进阶技巧(上)
  2. OpenYurt:延伸原生 Kubernetes 到边缘场景下的落地实践
  3. 如何给PDF文件交换页面?操作方法你知道吗?
  4. Lab01:Xv6 and Unix utilities
  5. windows上使用cmake 编译yaml-cpp源码,生成yam-cpp.lib
  6. WinCE的快速启动
  7. Android自定义视图二:如何绘制内容
  8. 快速安装配置zabbix_agent端
  9. 【Elasticsearch】如何使用 Elasticsearch 6.2 搜索中文、日文和韩文文本 - 第 2 部分: 多字段
  10. 震惊!谷歌专家爆料:Python和AI这回真的玩大了!网友:好方法!
  11. JavaScript 自定义年月日选择下拉框select选择的日期方法vue实现
  12. 【转载】Android 工具-adb原理
  13. 三种方法在地图上绘制网络图
  14. Java TCP小结
  15. c# 进程间的通信实现之一简单字符串收发
  16. linux运行raxml,在线和本地两种方法构建 RAxML 进化树方法和解读
  17. Sketch软件51.3 51.2 50.2 50 52 53 54 55 56 57 58正版激活码序列号 支持在线升级
  18. (八:2020.08.27)CVPR 2020 追踪之论文纲要(译)
  19. [yishen] 小慕读书web端学习笔记
  20. 如何给学生选择好的台灯?分享国AA级照度的护眼台灯

热门文章

  1. Android 10 根文件系统和编译系统(四):Android源码目录结构
  2. 独家揭秘:民生银行大数据体系架构设计与演进
  3. layui的form表单提交问题
  4. 内存分配器 mysql_MySQL内存管理,内存分配器和操作系统的示例分析
  5. 解决:jupyter notebook内核总是死亡
  6. 关于EAD: Elastic-Net Attacks to Deep Neural Networks via Adversarial Examples的理解
  7. restkeeper
  8. Unity Editor 基础篇(四):Handles
  9. Web3.0 教学基础一
  10. 环境(Environment)