zoukankan      html  css  js  c++  java
  • base64学习笔记

    base64学习笔记

    定义

    ​ Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。

    作用

    ​ 我们先来看一张ASCII码表:点击查看源网页

    ​ 由于有些系统只能使用ASCII字符,那么对于控制字符,或者exe,jpg,pdf这样的文件如果用记事本打开,会出现一堆乱码,因为二进制文件包含很多无法显示和打印的字符,所以,如果要让文本软件能处理二进制数据,就需要一个二进制到字符串的转换方法,这样就可以利用可以打印的字符表示不能打印的字符了,而base64 就是最常见的一个方法。

    base64算法的实现过程

    首先准备一个具有64个字符的索引表:

    img

    ​ Base64的码表只有64个字符, 如果要表达64个字符的话,使用6个bit即可完全表示(2的6次方为64),因为Base64的编码只需6个bit即可表示,而正常的字符是使用8个bit表示, 8和6的最小公倍数是24,所以4个Base64字符可以表示3个标准的ASCII字符,如果是字符的话就先转化为ASCII码再表示。

    ​ 那么对于二进制的处理,只需要每三个字节(24bit)一组即可转化为base64编码。

    base64-encode

    这样我们得到4个数字作为索引,然后查表,获得相应的4个字符,就是编码后的字符串。

    例如字符串abc的转码:

    字符串      a        b         c
    ASCII      97       98        99
    8bit   01100001  01100010  01100011
    6bit     011000    010110    001001    100011
    base64 00011000  00010110  00001001  00100011
    十进制      24        22          9        35
    对应编码     Y         W          J         j 
           
    

    还有一个问题:如果字符串长度不是3怎么办?

    我们考虑用两个base64表示一个字符或者用三个base64表示两个字符(在二进制后面补0凑够6的倍数即可),然后在后面添加=号,例如字符A的表示:

    字符串      A
    ASCII      65
    8bit      01000001(发现长度不是6的倍数,在后面补0变成010000010000)
    6bit        010000   010000
    base64    00010000 000100000
    十进制     16       16
    对应编码   Q        Q        =       =
        
    字符串      B           C
    ASCII      66          67
    8bit      01000010     01000011 00(补两个0变成010000100100001100)
    6bit        010000   100100   001100
    base64    00010000 00100100 00001100
    十进制     16       36        12
    对应编码   Q        k         M        =
    
    

    代码实现:

    Python内置的base64可以直接进行base64的编解码:

    import base64
    base64.b64encode('binary\x00string')
    # 'YmluYXJ5AHN0cmluZw=='
    base64.b64decode('YmluYXJ5AHN0cmluZw==')
    # 'binary\x00string'
    
    

    由于标准的Base64编码后可能出现字符+/,在URL中就不能直接作为参数,所以又有一种"url safe"的base64编码,其实就是把字符+/分别变成-_

    base64.b64encode('i\xb7\x1d\xfb\xef\xff')
    # 'abcd++//'
    base64.urlsafe_b64encode('i\xb7\x1d\xfb\xef\xff')
    # 'abcd--__'
    base64.urlsafe_b64decode('abcd--__')
    # 'i\xb7\x1d\xfb\xef\xff'
    

    喜闻乐见的CTFbase64换表处理方法

    一般base64索引表是约定的,在线编码解码遵从的也都是该表,但是有的题会把索引表改了

    1. 自己写一个python脚本进行base64转码

    # coding:utf-8
    
    s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    # 在这里修改base64索引表
    
    def My_base64_encode(inputs):
    	# 将字符串转化为2进制
    	bin_str = []
    	for i in inputs:
    		x = str(bin(ord(i))).replace('0b', '')
    		bin_str.append('{:0>8}'.format(x))
    	#print(bin_str)
    	# 输出的字符串
    	outputs = ""
    	# 不够三倍数,需补齐的次数
    	nums = 0
    	while bin_str:
    		#每次取三个字符的二进制
    		temp_list = bin_str[:3]
    		if(len(temp_list) != 3):
    			nums = 3 - len(temp_list)
    			while len(temp_list) < 3:
    				temp_list += ['0' * 8]
    		temp_str = "".join(temp_list)
    		#print(temp_str)
    		# 将三个8字节的二进制转换为4个十进制
    		temp_str_list = []
    		for i in range(0,4):
    			temp_str_list.append(int(temp_str[i*6:(i+1)*6],2))
    		#print(temp_str_list)
    		if nums:
    			temp_str_list = temp_str_list[0:4 - nums]
    			
    		for i in temp_str_list:
    			outputs += s[i]
    		bin_str = bin_str[3:]
    	outputs += nums * '='
    	print("Encrypted String:\n%s "%outputs)
    	
    def My_base64_decode(inputs):
    	# 将字符串转化为2进制
    	bin_str = []
    	for i in inputs:
    		if i != '=':
    			x = str(bin(s.index(i))).replace('0b', '')
    			bin_str.append('{:0>6}'.format(x))
    	#print(bin_str)
    	# 输出的字符串
    	outputs = ""
    	nums = inputs.count('=')
    	while bin_str:
    		temp_list = bin_str[:4]
    		temp_str = "".join(temp_list)
    		#print(temp_str)
    		# 补足8位字节
    		if(len(temp_str) % 8 != 0):
    			temp_str = temp_str[0:-1 * nums * 2]
    		# 将四个6字节的二进制转换为三个字符
    		for i in range(0,int(len(temp_str) / 8)):
    			outputs += chr(int(temp_str[i*8:(i+1)*8],2))
    		bin_str = bin_str[4:]	
    	print("Decrypted String:\n%s "%outputs)
    	
    print()
    print("     *************************************")
    print("     *    (1)encode         (2)decode    *")	
    print("     *************************************")
    print()
    
    
    num = input("Please select the operation you want to perform:\n")
    if(num == "1"):
    	input_str = input("Please enter a string that needs to be encrypted: \n")
    	My_base64_encode(input_str)
    else:
    	input_str = input("Please enter a string that needs to be decrypted: \n")
    	My_base64_decode(input_str)
    
    
    1. 给你base64,让你解码,那么直接照着加密表倒回去

    利用python的maketrans和translate函数,建立一个改表到原表的映射,先转成原表的索引再decode即可

    import base64
    ens = 'Please enter a string that needs to be decrypted'
    intab = 'Please enter the encoded_index' #换表
    outtab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' #原表
    transtab = str.maketrans(intab,outtab)
    ens = ens.translate(transtab)
    print(base64.b64decode(ens).decode())
    

    buuctf [FlareOn3]Challenge1

    接下来是一道base64换表裸题。

    没壳直接扔进IDA反编译:

    int __cdecl main(int argc, const char **argv, const char **envp)
    {
      char Buffer[128]; // [esp+0h] [ebp-94h] BYREF
      char *Str1; // [esp+80h] [ebp-14h]
      char *Str2; // [esp+84h] [ebp-10h]
      HANDLE StdHandle; // [esp+88h] [ebp-Ch]
      HANDLE hFile; // [esp+8Ch] [ebp-8h]
      DWORD NumberOfBytesWritten; // [esp+90h] [ebp-4h] BYREF
    
      hFile = GetStdHandle(0xFFFFFFF5);
      StdHandle = GetStdHandle(0xFFFFFFF6);
      Str2 = "x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q";
      WriteFile(hFile, "Enter password:\r\n", '\x12', &NumberOfBytesWritten, 0);
      ReadFile(StdHandle, Buffer, 0x80u, &NumberOfBytesWritten, 0);
      Str1 = (char *)sub_401260(Buffer, NumberOfBytesWritten - 2);
      if ( !strcmp(Str1, Str2) )
        WriteFile(hFile, "Correct!\r\n", 0xBu, &NumberOfBytesWritten, 0);
      else
        WriteFile(hFile, "Wrong password\r\n", 0x11u, &NumberOfBytesWritten, 0);
      return 0;
    }
    

    flag放在buffer里,加密后得到str1,和
    比较

    看到

    立马反应过来是base64换表,根据上面的知识,直接套exp

    import base64
    ens = 'x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q'
    intab = 'ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/'
    outtab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    transtab = str.maketrans(intab,outtab)
    
    ens = ens.translate(transtab)
    print(base64.b64decode(ens).decode())
    

    得到flag{sh00ting_phish_in_a_barrel@flare-on.com}

  • 相关阅读:
    uploadify插件的功能应用
    dropify插件的字符串
    VCC、VDD和VSS
    Bootloader升级方式一————擦、写flash在RAM中运行
    Can DBC文件翻译
    CANdbc编辑器的下载和入门介绍
    CAN协议,系统结构和帧结构
    数据帧
    自动驾驶技术之——无人驾驶中的CAN总线
    can物理信号-----------显性和隐性
  • 原文地址:https://www.cnblogs.com/THRANDUil/p/15620023.html
Copyright © 2011-2022 走看看