最简单的编码(Ezbase.zip,base64魔改)

刷到一道有意思的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="")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值