RC4加密原理,代码解析,逆向小技巧.
目录
RC4加密原理
一丶RC4
1.1 rc4介绍
RC4是一种对称加密算法,加密和加密使用同一个函数. 其中关于其历史这里也不多说了.
自己查一下百度百科.
1.2 RC4原理以及代码介绍
RC4是很简单的一种加密算法, 主要就是分为两部分 RC4初始化 RC4加密
其实很简单.
1.2.1rc4初始化介绍
初始化分为以下几个步骤
- 初始化存储0-255字节的Sbox(其实就是一个数组)
- 填充key到256个字节数组中称为Tbox(你输入的key不满256个字节则初始化到256个字节)
- 交换s[i]与s[j] i 从0开始一直到255下标结束. j是 s[i]与T[i]组合得出的下标
代码如下
typedef struct _RC4INFO
{
unsigned char s_box[256]; //定义一个自己使用的结构体
unsigned char t_box[256];
}RC4_INFO,*PRC4_INFO;
/*
初始化函数 需要传入key 以及 keylen
主要有几个步骤
1.初始化Sbox
2.将key填充到Tbox中
3.组合sbox[i] 与 tbox[i] 然后进行交换
*/
void rc4_init(PRC4_INFO prc4,unsigned char key[], unsigned int keylen)
{
int i = 0;
int j = 0;
unsigned char tmp;
if (prc4 == NULL)
{
return;
}
//初始化sbox与 Tbox
for (i = 0; i < 256; i++)
{
prc4->s_box[i] = i;
prc4->t_box[i] = key[i % keylen];
}
//交换sbox
for (i = 0; i < 256; i++)
{
//得出j下标
j = (j + prc4->s_box[i] + prc4->t_box[i]) % 256;
//开始交换
tmp = prc4->s_box[i];
prc4->s_box[i] = prc4->s_box[j];
prc4->s_box[j] = tmp;
}
}
1.2.2 RC4加密
RC4加密其实就是遍历数据,将数据与sbox进行异或加密,而在此之前还需要交换一次sbox的数据
交换完之后 再把s[i] + s[j]的组合当做下标再去异或.
代码如下.
void rc4_crypt(
unsigned char data[], //要加密的数据
unsigned int datalen, //要加密的数据长度
unsigned char key[], //加密数据所用的Key
unsigned int keylen) //加密数据所用的key长度
{
int dn = 0; //data[n]的意思
int i = 0;
int j = 0; // i j 分别用于交换sbox[i] 和 sbox[j]
int t = 0; //t = s[i] + s[j]
unsigned char tmp;
RC4_INFO rc4;
rc4_init(&rc4, key, keylen);
for (dn = 0; dn < datalen; dn++)
{
i = (i + 1) % 256;
j = (j + rc4.s_box[i]) % 256;
//swap
tmp = rc4.s_box[i];
rc4.s_box[i] = rc4.s_box[j];
rc4.s_box[j] = tmp; //上边这部分就是在交换s[i]与s[j]
//下边这部分就是得到T下标用于交换
t = (rc4.s_box[i] + rc4.s_box[j]) % 256;
data[dn] ^= rc4.s_box[t];
}
}
1.2.3完整代码
/* This file was generated by the Hex-Rays decompiler.
Copyright (c) 2007-2019 Hex-Rays <info@hex-rays.com>
Detected compiler: Visual C++
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <intrin.h>
typedef struct _RC4INFO
{
unsigned char s_box[256];
unsigned char t_box[256];
}RC4_INFO,*PRC4_INFO;
void rc4_init(PRC4_INFO prc4,unsigned char key[], unsigned int keylen)
{
int i = 0;
int j = 0;
unsigned char tmp;
if (prc4 == NULL)
{
return;
}
//init sbox an KeyBox(Tbox)
for (i = 0; i < 256; i++)
{
prc4->s_box[i] = i;
prc4->t_box[i] = key[i % keylen];
}
//swap sbox
for (i = 0; i < 256; i++)
{
j = (j + prc4->s_box[i] + prc4->t_box[i]) % 256;
tmp = prc4->s_box[i];
prc4->s_box[i] = prc4->s_box[j];
prc4->s_box[j] = tmp;
}
}
void rc4_crypt(
unsigned char data[], //要加密的数据
unsigned int datalen, //要加密的数据长度
unsigned char key[], //加密数据所用的Key
unsigned int keylen) //加密数据所用的key长度
{
int dn = 0; //data[n]的意思
int i = 0;
int j = 0; // i j 分别用于交换sbox[i] 和 sbox[j]
int t = 0; //t = s[i] + s[j]
unsigned char tmp;
RC4_INFO rc4;
rc4_init(&rc4, key, keylen);
for (dn = 0; dn < datalen; dn++)
{
i = (i + 1) % 256;
j = (j + rc4.s_box[i]) % 256;
//swap
tmp = rc4.s_box[i];
rc4.s_box[i] = rc4.s_box[j];
rc4.s_box[j] = tmp;
//得到T下标用于交换
t = (rc4.s_box[i] + rc4.s_box[j]) % 256;
data[dn] ^= rc4.s_box[t];
}
}
void EntryBuffer(unsigned char data[],unsigned int datalen)
{
unsigned char key[] = "pjrHeldsadf";
rc4_crypt(data, datalen, key, sizeof(key) / sizeof(key[0]));
}
int main()
{
char Hell[] = "Hello你好sdfsdaf";
EntryBuffer((unsigned char*)Hell,sizeof(Hell)/sizeof(Hell[0])); //加密
EntryBuffer((unsigned char*)Hell,sizeof(Hell)/sizeof(Hell[0])); //在调用一次就是解密了
return 0;
}
1.2.4 C语言的加解密完整代码
三丶RC4的逆向小技巧
void swap(unsigned char *a, unsigned char *b) {
unsigned char temp = *a;
*a = *b;
*b = temp;
}
void rc4(unsigned char *key, int key_size, unsigned char *data,
int data_length) {
unsigned char S[256];
int i, j, k;
// 初始化S盒
for (i = 0; i < 256; i++) {
S[i] = i;
}
j = 0;
for (i = 0; i < 256; i++) {
j = (j + S[i] + key[i % key_size]) % 256;
swap(&S[i], &S[j]);
}
i = j = 0;
for (k = 0; k < data_length; k++) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
swap(&S[i], &S[j]);
data[k] ^= S[(S[i] + S[j]) % 256];
}
}
3.1 逆向特征
- 首先根据原理我们可以看到会初始化一个256字节的数组
- 其次会将一个key也填充到数组中
- 函数的话大概率都是两个参数,一个是key 一个是keylen
遇到上述特征可以认为是rc4
反汇编中有xmm0 下面进行调用了两个函数 sub_401040
观看数据区,看到这种大概率就是字符串,可以按A 或者R来进行转换看.
转换后看到就是我们的加密数据以及rc4的key(pjrheldsadf)
根据上述特征大概率就可以看出是rc4初始化函数. key填充到var_20C中. i填充到var_200中
再往下看就可以明显的看到数据异或了.很简单也可以自己写一个进行逆向.
作者:IBinary
坚持两字,简单,轻便,但是真正的执行起来确实需要很长很长时间.当你把坚持两字当做你要走的路,那么你总会成功. 想学习,有问题请加群.群号:725864912(收费)群名称: 逆向学习小分队 群里有大量学习资源. 以及定期直播答疑.有一个良好的学习氛围. 涉及到外挂反外挂病毒 司法取证加解密 驱动过保护 VT 等技术,期待你的进入。
详情请点击链接查看置顶博客 https://www.cnblogs.com/iBinary/p/7572603.html
本文来自博客园,作者:iBinary,未经允许禁止转载 转载前可联系本人.对于爬虫人员来说如果发现保留起诉权力.https://www.cnblogs.com/iBinary/p/14023091.html
欢迎大家关注我的微信公众号.不定期的更新文章.更新技术. 关注公众号后请大家养成 不白嫖的习惯.欢迎大家赞赏. 也希望在看完公众号文章之后 不忘 点击 收藏 转发 以及点击在看功能. QQ群: