zoukankan      html  css  js  c++  java
  • base64原理与逆向中的表现形式.

    Base64编码 变形Base64编码 实现与逆向分析

    一丶BASE64介绍

    1.1 BASE64简介

    ​ 所谓的BASE64 说白了就是有一个64个字符数组, 这64个字符分别是 小写a - z 大写A-Z 数字0-9 然后再加上"+" "/"符号来组成一个64字符的数组.但是其实我们有的时候还要加上"="作为字符,也就是说白了是65个字符,但是"="加密解密都会忽略所以就认为是64个字符.

    从64个字符里面取出当前字符就形成了编码过程

    下面说一下BASE64编码的过程

    • 第一步 将三个字节作为一组 也就是有24个进制位
    • 第二步 将三个字节转为四个字节 也就是24个进制位按照每6个字节一组的方式进行分割
    • 第三步 扩展为4个字节 主要就是分组之后是6个进制为一组,再把每个6进制前边加上00
    • 第四部 查表 根据base64编码表 然后进行查表动作.其索引就是按照6bit分组扩展为8bit的字节

    下面就以C语言为表来表达

    unsigned char base64_table[64]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 
    

    下面就实战转换 Man 这三个字符 如何进行编码的

    • 三字符转为4字符

    首先第一步就是将 M a n三个字符的Ascii提取出来. 第二步看一下其对应的8个bit位 第三步就是8bit 按照6bit分割

    第四步就是前边补0 但是其实不补也可以,因为补了0一样还是代表原数.

    那么在C/C++中的表现就可以用移位来进行编码.

    简单伪代码如下

    char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    	char Man[] = "Man";
    	char CodeTable[5] = { 0 };
    
    
    	int nindex = 0;
    	nindex = (Man[0] >> 0x2) & 0x3F;
    	CodeTable[0] = base64_table[nindex];
    
    
    	nindex = ((Man[0] & 0x03) << 4) | (Man[1] >> 4);
    	CodeTable[1] = base64_table[nindex];
    
    
    	nindex = ((Man[1] & 0x0F) << 2) | (Man[2] >> 6);
    	CodeTable[2] = base64_table[nindex];
    
    
    	nindex = ((Man[2] & 0x3F));
    	CodeTable[3] = base64_table[nindex];
    

    通过移位可以将三个转为4个 最终输出为TWFu 当然我们可以用循环做.这里是简单看如何转换的.

    • 2字节转为三字节

      当只有两个字节的情况下,其对应的ASCII编码有两个.是可以转换为 2个6bit加剩下4个bit的数据

      也就是可以将两组8bit转为三组.但是最后一组就剩下4个bit了. 所以最后一组我们要在前边补充两个0 后面补充两个0 来凑满8个字节 继续进行查表. 查表之后在最后一个字符后面添加一个"="

      伪代码如下:

      char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      	char Man[] = "Ma";
      	char CodeTable[5] = { 0 };
      
      
      	int nindex = 0;
      	nindex = (Man[0] >> 0x2) & 0x3F;
      	CodeTable[0] = base64_table[nindex];
      	nindex = ((Man[0] & 0x03) << 4) | (Man[1] >> 4);
      	CodeTable[1] = base64_table[nindex];
      
      
      	nindex = ((Man[1] & 0x0F) << 2);
      	CodeTable[2] = base64_table[nindex];
      	CodeTable[3] = '=';
      

      最终的输出结果就是 TWE=

      • 一字节转换

        一字节转换其原理就是 将一个字节转换为8个bit 按照6bit一组可以分为两组 最后一组前面除了加上两个0来扩充后面也要加上两个2来扩充,最终形成一个2个8bit字节.然后查表得出字符.但因为是一个字节所以后面两个字符要以'='结尾.

        伪代码如下:

        char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        	char Man[] = "M";
        	char CodeTable[5] = { 0 };
        
        
        	int nindex = 0;
        	nindex = (Man[0] >> 0x2) & 0x3F;
        	CodeTable[0] = base64_table[nindex];
        	nindex = ((Man[0] & 0x03) << 4) | (Man[1] >> 4);
        	CodeTable[1] = base64_table[nindex];
        
        
        	
        	CodeTable[2] = '=';
        	CodeTable[3] = '=';
        

        最终则是TQ==

    1.2 BASE64 c代码实现

    1.2.1 自实现base64编码

    使用C代码实现就很简单了,根据以上原理我们可以得出几个步骤

    1.传入要编码的字节以及对应长度

    2.以长度%3 %2 %1为分界线进行编码

    ​ 长度 = 3 则用3转化为4的方式

    ​ 长度 = 2 则用 2转化为3的方式 并且后面加一个=

    ​ 长度为1 则用 1转化为2的方式i并且后面加上两个=

    代码如下

    string b64_EnCode(char EnCodeByte[], int EnCodeLen)
    {
    	char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    	string EnCode;
    
    	char EnCode3Array[3] = {0};
    	int i = 0;
    	while (EnCodeLen--)
    	{
    		//每次获取一个字符 当获取到3个字符进行一次操作
    		EnCode3Array[i++] = *(EnCodeByte++);
    		if (i == 3)
    		{
    			EnCode += base64_table[(EnCode3Array[0] >>2)& 0x3F];
    			EnCode += base64_table[((EnCode3Array[0] & 0x03) << 4) | (EnCode3Array[1] >> 4)];
    			EnCode += base64_table[((EnCode3Array[1] & 0x0F) << 2) | (EnCode3Array[2] >> 6)];
    			EnCode += base64_table[((EnCode3Array[2] & 0x3F))];
    
    			//重置i
    			i = 0;
    		}
    	}
    
    	//然后判断是否是2个字节的情况与一个字节的情况
    	if (i)
    	{
    		//置零
    		for (int j = i; j < 3; j++)
    		{
    			EnCode3Array[j] = 0;
    		}
    
    		//判断i = 2 还是1
    		if (i == 2)
    		{
    
    			EnCode += base64_table[(EnCode3Array[0] >> 2) & 0x3F];
    			EnCode += base64_table[((EnCode3Array[0] & 0x03) << 4) | (EnCode3Array[1] >> 4)];
    			EnCode += base64_table[((EnCode3Array[1] & 0x0F) << 2)];
    			EnCode += '=';
    		}
    		if (i == 1)
    		{
    			EnCode += base64_table[(EnCode3Array[0] >> 2) & 0x3F];
    			EnCode += base64_table[((EnCode3Array[0] & 0x03) << 4) | (EnCode3Array[1] >> 4)];
    			EnCode += '=';
    			EnCode += '=';
    		}
    	}
    
    	return EnCode;
    }
    int main()
    {
    	
    	char Man[] = "HelloWorld1";
    
    	printf("%s
    ", b64_EnCode(Man,strlen(Man)).c_str());
    	
    	system("pause");
        return 0;
    }
    

    输出值为: SGVsbG9Xb3JsZDE=

    1.2.2 其它优秀实现

    上面是自己实现的 base64还有更多种实现,比如下面的移位也不一样但是结果是一样的.

    #include "base64.h"
    #include <iostream>
    
    // there are 64 characters
    static const std::string base64_chars =
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "abcdefghijklmnopqrstuvwxyz"
            "0123456789+/";
    
    
    static inline bool is_base64(unsigned char c) {
        return (isalnum(c) || (c == '+') || (c == '/'));
    }
    
    std::string base64_encode(const char *bytes_to_encode, unsigned int in_len) {
        std::string ret;
        int i = 0;
        int j = 0;
        unsigned char char_array_3[3];  // store 3 byte of bytes_to_encode
        unsigned char char_array_4[4];  // store encoded character to 4 bytes
    
        while (in_len--) {
            char_array_3[i++] = *(bytes_to_encode++);  // get three bytes (24 bits)
            if (i == 3) {
                // eg. we have 3 bytes as ( 0100 1101, 0110 0001, 0110 1110) --> (010011, 010110, 000101, 101110)
                char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; // get first 6 bits of first byte,
                char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); // get last 2 bits of first byte and first 4 bit of second byte
                char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); // get last 4 bits of second byte and first 2 bits of third byte
                char_array_4[3] = char_array_3[2] & 0x3f; // get last 6 bits of third byte
    
                for (i = 0; (i < 4); i++)
                    ret += base64_chars[char_array_4[i]];
                i = 0;
            }
        }
    
        if (i)
        {
            for (j = i; j < 3; j++)
                char_array_3[j] = '';
    
            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
    
            for (j = 0; (j < i + 1); j++)
                ret += base64_chars[char_array_4[j]];
    
            while ((i++ < 3))
                ret += '=';
    
        }
    
        return ret;
    
    }
    
    std::string base64_decode(const std::string& encoded_string) {
        size_t in_len = encoded_string.size();
        int i = 0;
        int j = 0;
        int in_ = 0;
        unsigned char char_array_4[4], char_array_3[3];
        std::string ret;
    
        while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
            char_array_4[i++] = encoded_string[in_]; in_++;
            if (i == 4) {
                for (i = 0; i < 4; i++)
                    char_array_4[i] = base64_chars.find(char_array_4[i]) & 0xff;
    
                char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
                char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
                char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
    
                for (i = 0; (i < 3); i++)
                    ret += char_array_3[i];
                i = 0;
            }
        }
    
        if (i) {
            for (j = 0; j < i; j++)
                char_array_4[j] = base64_chars.find(char_array_4[j]) & 0xff;
    
            char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
            char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
    
            for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
        }
    
        return ret;
    }
    

    ​ 待完成,b64变形 汇编中表现形式等等.先写开发.

  • 相关阅读:
    大数加法、乘法实现的简单版本
    hdu 4027 Can you answer these queries?
    zoj 1610 Count the Colors
    2018 徐州赛区网赛 G. Trace
    1495 中国好区间 尺取法
    LA 3938 动态最大连续区间 线段树
    51nod 1275 连续子段的差异
    caioj 1172 poj 2823 单调队列过渡题
    数据结构和算法题
    一个通用分页类
  • 原文地址:https://www.cnblogs.com/iBinary/p/14052616.html
Copyright © 2011-2022 走看看