zoukankan      html  css  js  c++  java
  • 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;
    }
    
    

    三丶RC4的逆向小技巧

    3.1 逆向特征

    • 首先根据原理我们可以看到会初始化一个256字节的数组
    • 其次会将一个key也填充到数组中
    • 函数的话大概率都是两个参数,一个是key 一个是keylen

    遇到上述特征可以认为是rc4

    反汇编中有xmm0 下面进行调用了两个函数 sub_401040

    观看数据区,看到这种大概率就是字符串,可以按A 或者R来进行转换看.

    image-20201123101016511

    转换后看到就是我们的加密数据以及rc4的key(pjrheldsadf)

    根据上述特征大概率就可以看出是rc4初始化函数. key填充到var_20C中. i填充到var_200中

    再往下看就可以明显的看到数据异或了.很简单也可以自己写一个进行逆向.

  • 相关阅读:
    robot framework 初始化清除
    python获取命令行参数
    行业基金
    Ubuntu关闭开机自启项
    ubuntu18.04安装adb
    JavaScript
    centos关闭开机自启项
    CSDN值得学习的专栏
    ubuntu和centos操作命令对比
    linux解压文件命令
  • 原文地址:https://www.cnblogs.com/iBinary/p/14023091.html
Copyright © 2011-2022 走看看