• 前言

    在计算机数据的存储和传输中,使用Base编码是非常常见的,各类语言的HTTP请求库都提供了Base编码和解码的接口,使用了这么久的Base编码,也该来探寻一下它的实现原理了QWQ。

编码原理

不论是Base16,32,还是64,它们都是用的同一种原理进行编码,基本分为两大部分:

  1. 对应算法。

    1. 将数据转化为ASCII的二进制编码
    2. 后将所有的二进制全部串起来,4个(Base32位5个,Base64位6个)二进制位为一组,转化成对应十进制数(最后一组不足在低位补0)。
    3. 根据十进制数值找到Base16编码表里面对应的字符(Base32二进制编码总位数不足40位,Base64不足24位,都需要在最后添加“=”)
  2. 对应表格(以Base16为例)。

脚标编码值 脚标编码值
00 88
11 99
22 10A
33 11B
44 12C
55 13D
66 14E
77 15F

举个栗子:
Base16:
image
Base64:
image

代码实现

  • IDA逆向代码
    函数开头是如下形式,基本可确定是Base编码操作:
    	v2 = a2/3;
    	v3 = 0;
    	if(a2%3 > 0)
    		v2 ++;
    	v4 = 4*v2+1; //v4为长度
    			//编码的数据长度为3的倍数时, len = strlen(srt_in)/3*4
    			//编码数据长度不为3的倍数时,len = strlen((str_in)/3+1)*4)
    

    因此,只需要根据使用的字符集,即可看出具体是哪一种Base编码。

  • python实现
    	import base64
    	original = 'ljz is yyy'
    	print("1  original:  ",type(original),original)
    	print("2  original.encode('utf-8'):  ",type(original.encode('utf-8')),original.encode('utf-8'))
    	str_encode = base64.b16encode(original.encode('utf-8'))
    	print("3  str_encode:  ",type(str_encode),str_encode)
    	print("4  str(str_encode,'utf-8'):  ",type(str(str_encode,'utf-8')),str(str_encode,'utf-8'))
    	str_decode = base64.b16decode(str_encode)
    	print("5  str_decode:  ",type(str_decode),str_decode)
    	print(str(str_decode,'utf-8'))
    
  • 自定义编码表
    在Base转换时,可以根据自定义字典进行转换,Python脚本如下:
    两个方法:
    	str.maketrans(intab, outtab)  //用于创建字符映射的转换表
    	intab -- 字符串中被替代的字符组成的字符串。
    	outtab -- 用来替换的字符串。
    	后者替换前者
    	#第三个参数此处不讨论
    
    	xxx.translate(table[, deletechars])  //根据参数table给出的表转换字符串的字符
    	table -- 翻译表,翻译表是通过maketrans方法转换而来。
    	deletechars -- 字符串中要过滤的字符列表。#第二个参数此处不讨论
    

    实例:

    	import base64
    	origin = 'ljz is yyy'
    	biao1 = str.maketrans("0123456789ABCDEF","abcdef0123456789")
    	str_encode = base64.b16encode(origin.encode('utf-8'))
    	encode = str(str_encode,'utf-8').translate(biao1)
    	print(encode)
    	biao2 = str.maketrans("abcdef0123456789","0123456789ABCDEF")
    	str_decode = base64.b16decode(encode.translate(biao2).encode('utf-8'))
    	print(str(str_decode,'utf-8'))
    

总结

Base编码的对比:

名称下标数字二进制位数编码表字符是否补全“=”
Base1640 ~ 9,A ~ F不会
Base3252 ~ 7,A ~ Z
Base6460 ~ 9,A ~ Z,a ~ z

What is broken can be reforged.