本文编写于 96 天前,最后修改于 96 天前,其中某些信息可能已经过时。

在校赛出了个base64换表,好像writeup写得不够清楚导致被问了好几回,这里仔细写一下qwq
其实很简单

base64位编码过程

  1. 将字节数对齐成3的倍数,不足以0对齐位数,按缺少补=

  1. 按6位一个数值理解为一个数值作为索引查找base64码表

自己写的一个易于理解的浅显易懂的base64实现

b64encode=lambda s: (lambda s1,lack:''.join(list(map(lambda s: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'[int(s,2)],[s1[i*6:i*6+6] for i in range(int(len(s1)/6)-lack)])))+'='*lack)(''.join(list(map(lambda a: '{:08b}'.format(ord(a)),s)))+(-len(s)%3)*8*'0',-len(s)%3)
print(b64encode('gamous'))
#Output:  Z2Ftb3Vz

在这我们也可以很轻松地替换这个普通base64中的码表,实现一个换表base64

那么根据编码过程,我们可以构造一个指定输入,使得编码过程按我们想定的一个顺序输出索引0 -索引64 的码元

print(b64encode('\x00\x10\x83'))
#Output: ABCD

当然,这里我们需要注意的是0是bad char,如果放在字符串头会在传递的时候任意被截断,所以我们可以 倒置着构造

getIndexStr= lambda a: '{:06b}'.format(a)
flow=''
for i in range(64):
    flow+=getIndexStr(63-i)
flow.ljust((0-len(flow)%8),'0')
res = []
while len(flow) > 0:
    res.append(flow[:8])
    flow =flow[8:]
owo=''
for i in res:
  owo+='\\x{:02x}'.format(int(i,2))
print(owo)
#Output:'\xff\xef\x7c\xef\xae\x78\xdf\x6d\x74\xcf\x2c\x70\xbe\xeb\x6c\xae\xaa\x68\x9e\x69\x64\x8e\x28\x60\x7d\xe7\x5c\x6d\xa6\x58\x5d\x65\x54\x4d\x24\x50\x3c\xe3\x4c\x2c\xa2\x48\x1c\x61\x44\x0c\x20\x40'

使用这个构造的字符串可以轻松地dump下换表base64的码表

print(b64encode('\xff\xef\x7c\xef\xae\x78\xdf\x6d\x74\xcf\x2c\x70\xbe\xeb\x6c\xae\xaa\x68\x9e\x69\x64\x8e\x28\x60\x7d\xe7\x5c\x6d\xa6\x58\x5d\x65\x54\x4d\x24\x50\x3c\xe3\x4c\x2c\xa2\x48\x1c\x61\x44\x0c\x20\x40')[::-1])
#Output: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

可能在逆向时有一点点用叭Orz