2025/12/24 星期三

以后有产出的发随笔,没产出的发日记嘻嘻。。really a genius!
今天完成两个CTF题目,为了迎战周末的CTF国赛
题目之一:base64隐写
base64隐写是指,当我们的字符串或数字什么东西转成base64编码的时候,按比特位来算它必须是6bit的倍数,不满6bit的补0
例如对a进行base64编码:
1:a的ascii码为97,换算成二进制为01100001
2:按6位一组来分,变成011000 01
3:这时发现后面只有01不足6位,所以需要在后面补齐0,变成010000
4:此时会将上面转换的011000 010000 转换成10进制数字(相当于左边补2个0,最大值为2^6-1=63,对于base64码表的0-63位共64个字符)
5:将上面的实践中数字在base64码表中找到对应的位置字符,后续不满足4的整数倍再去补=好。这就是整个base64加密过程
对于base64隐写的话
关键点在于虽然我们进行base64编码的时候后面是补了0的,但是在我们解码的时候它是会自动将后面的0舍去的而不影响我们解码的结果
比如上面的a编码后为YQ==,除去后面两个等于号,YQ在base64码表的位置是24,16.即011000 010000,但是事实上在解码时按8位8位算,只提取了前面的01100001,将其转换即为a
这里我们就注意的其实它后面的0000是没有用的,这时我们就可以在里面隐藏我们想要隐藏的数据,把它变成011000 010001,或者011000 010010这种,对应的是YR,YS。
这里感兴趣的可以自行去验证,无论是YQ还是YR还是YS解码出来的都是a,这也印证了解码不看后面的填充数据,一个原文的base64编码可能有多种结果!
对此进行脚本提取所有填充的数据
脚本如下:

from Crypto.Util.number import long_to_bytes
f=open('cipher.txt','r',encoding='utf-8') #其中cipher.txt为加密密文文件,每一行一个base64编码后数据,改成自己文件即可
base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
b=''
for line in f.readlines():

    line = line.rstrip('\n\r')  # 去除行尾的\n/\r,只保留有效内容
    if line[-1]=='=':
        if line[-2]=='=':
            last=line[-3]
            pos = base64_table.index(last)
            data=bin(pos).zfill(16)[-4:]
            b+=data
        else:
            last=line[-2]
            pos=base64_table.index(last)
            data = bin(pos).zfill(8)[-2:]
            b+=data
    else:
        continue

padding = 8 - (len(b) % 8)
for i in range(8-padding):
    b+=0
print(long_to_bytes(int(b,2)))

题目二为传统的逆向题,简单的几个变换
题目来源:攻防世界Mobile-easyjni
可以看出题目逻辑是对输入的32位字符串进行3轮变换
第一轮:后半部分和前半部分相交换 例如abcd变成cdab
第二轮:两两交换,例如cdab变成dcba
第三轮:变码表的base64编码即可
脚本如下:(脚本一定要自己学着写,提升一下代码能力,对于程序员来说是很重要的,每个人的代码都是独一无二的,看别人的使用别人的代码固然可以,但自己的代码思维是不可替代的,按照自己的想法去写属于自己的代码,虽然很烂,时间复杂度什么都很高,但最后能取得成功,都是一件很值得骄傲的事)

import base64
a = ['i', '5', 'j', 'L', 'W', '7', 'S', '0', 'G', 'X', '6', 'u', 'f', '1', 'c', 'v', '3', 'n', 'y', '4', 'q', '8', 'e', 's', '2', 'Q', '+', 'b', 'd', 'k', 'Y', 'g', 'K', 'O', 'I', 'T', '/', 't', 'A', 'x', 'U', 'r', 'F', 'l', 'V', 'P', 'z', 'h', 'm', 'o', 'w', '9', 'B', 'H', 'C', 'M', 'D', 'p', 'E', 'a', 'J', 'R', 'Z', 'N']
standard_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
const_table=''.join(a)
chiper_text='MbT3sQgX039i3g==AQOoMQFPskB1Bsc7'
newtext=''
for i in range(0,len(chiper_text),2):
    #print(i)
    temp=chiper_text[i]
    newtext+=chiper_text[i+1]
    newtext+=temp
#print(newtext)
new_chiper_text=newtext[len(newtext)//2:]+newtext[:len(newtext)//2]
#print('chiper_text=',chiper_text)
# 映射回标准表
mapped_text = ''
for char in new_chiper_text:
    if char != '=': # 忽略等号
        index = const_table.index(char)
        mapped_text += standard_table[index]
    else:
        mapped_text += char
#print(mapped_text)
# 解码
flag = base64.b64decode(mapped_text).decode()
print('flag=',flag)
posted @ 2025-12-24 17:39  ikunya520  阅读(1)  评论(0)    收藏  举报