刷到一道有意思的base魔改,随手做个记录
一,题目链接
限时题目,只能用网盘来分享了,侵权联系删->百度网盘 请输入提取码
二,题目分析
(一)main函数
用ida打开题目后,找不到main函数,用【shift+12】追踪关键字符串可以找到它,按Y键改个名字看得比较舒服
下面很多变量和函数名字,是我分析完后按N键重命名的,看得比较舒服
有些基本看不懂的函数其实不用关心,对题目没影响(比如下图第20行的函数调用,似乎跟线程调用有关,反正跟解题没啥关系),要么是故意写出来干扰做题,要么是反调试之类的
(二)change_table()函数
名字是分析后重命名的,参数类型可以用Y键修改,明眼人都知道是char*指针
看代码不难分析出它在对标准表修改,所以需要写脚本获得变表,或者直接动调查看内容(这题没有设置反调试)
按源代码的逻辑很容易搓出变表的,等着后面要用到
table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' arr = list(table) for i in range(0, 16): arr[4 * i], arr[4 * i + 2] = arr[4 * i + 2], arr[4 * i] arr[4 * i + 1], arr[4 * i + 3] = arr[4*i + 3], arr[4 * i + 1] for i in arr: print(i,end='') #CDABGHEFKLIJOPMNSTQRWXUVabYZefcdijghmnklqropuvstyzwx23016745+/89
(三)base魔改加密函数
这题主要的难点就在分析和逆向这个魔改的base加密了,它其实是引入了一个key(我重命名的)
然后在base加密的过程中,对每次计算的索引格外加了key中的内容,这样一来不仅表不是标准表,索引的规则也被修改了,因此直接用python的base库解密api或者在线base解密是没办法解出flag的
因此必须要手写脚本,对base索引的这个流程中,减去题目中每次加密过程加上的key,让索引变成原来不加key的正常的索引
table = "CDABGHEFKLIJOPMNSTQRWXUVabYZefcdijghmnklqropuvstyzwx23016745+/89" # base64变表 cipher = "TqK1YUSaQryEMHaLMnWhYU+Fe0WPenqhRXahfkV6WE2fa3iRW197Za62eEaD" # 密文 _index = [] key = [1, 2, 3, 4] for i in range(len(cipher)): tmp = table.index(cipher[i]) - key[i % 4] # 减去加密时加上的key if tmp >= 0: _index.append(tmp) else: # 因为减去key会导致索引变成负数,+64保证在正常索引范围 _index.append(tmp + 64)
最后再按照正常base64加密的逻辑,每四个索引为一组,合并成一个单独的整数(通过对每个值左移相应的位数(
a
左移 18 位,b
左移 12 位,c
左移 6 位),然后使用按位或运算符(|
)结合这些结果,得到一个 24 位的整数根据得到的 24 位整数,通过右移操作从中提取出三个字节:
- 对于
j=0
,提取高位字节(8-15位)。- 对于
j=1
,提取中间字节(16-23位)。- 对于
j=2
,提取低位字节(24-31位)。使用
& 0xff
来确保获得的字节只保留最低的 8 位for i in range(0, len(_index), 4): a = _index[i] b = _index[i + 1] c = _index[i + 2] d = _index[i + 3] sum = a << 18 | b << 12 | c << 6 | d for j in range(3): print(chr((sum >> ((2 - j) * 8)) & 0xff), end="")
三,完整脚本
(一)变表
table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
arr = list(table)
for i in range(0, 16):
arr[4 * i], arr[4 * i + 2] = arr[4 * i + 2], arr[4 * i]
arr[4 * i + 1], arr[4 * i + 3] = arr[4*i + 3], arr[4 * i + 1]
for i in arr:
print(i,end='') #CDABGHEFKLIJOPMNSTQRWXUVabYZefcdijghmnklqropuvstyzwx23016745+/89
(二)魔改base
注:上文分析时展示脚本只适用于明文长度为3的倍数的情况,明文长度非3的倍数,则密文一定会出现'='字符,因此必须格外处理'='字符的情况
处理方法是去掉密文右边的'=',并添加一些未处理的判断,虽然本题的密文没有出现'='字符,但做题要举一反三,说不准下次就用上了
table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" # base64变表
cipher = "YWJjZGVmZw==" # 密文
cipher = cipher.rstrip('=') #去除密文多余的'='
_index = []
key = [1, 2, 3, 4]
for i in range(len(cipher)):
tmp = table.index(cipher[i])
_index.append(tmp)
print(_index)
for i in range(0, len(_index), 4):
a = _index[i]
b = _index[i + 1]
c = _index[i + 2] if i + 2 < len(_index) else 0 # 添加范围检查,为未处理部分设为0
d = _index[i + 3] if i + 3 < len(_index) else 0
sum = a << 18 | b << 12 | c << 6 | d
for j in range(3):
if i * 6 + j * 8 < len(cipher) * 8: # 检查是否超出原始编码长度
print(chr((sum >> ((2 - j) * 8)) & 0xff), end="")