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;
}
三丶RC4的逆向小技巧
3.1 逆向特征
- 首先根據原理我們可以看到會初始化一個256字節的數組
- 其次會將一個key也填充到數組中
- 函數的話大概率都是兩個參數,一個是key 一個是keylen
遇到上述特征可以認為是rc4
反匯編中有xmm0 下面進行調用了兩個函數 sub_401040
觀看數據區,看到這種大概率就是字符串,可以按A 或者R來進行轉換看.
轉換后看到就是我們的加密數據以及rc4的key(pjrheldsadf)
根據上述特征大概率就可以看出是rc4初始化函數. key填充到var_20C中. i填充到var_200中
再往下看就可以明顯的看到數據異或了.很簡單也可以自己寫一個進行逆向.