4

[原创]2020网鼎杯 白虎组 b64 精析

 3 years ago
source link: https://bbs.pediy.com/thread-268043.htm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
[原创]2020网鼎杯 白虎组 b64 精析-CTF对抗-看雪论坛-安全社区|安全招聘|bbs.pediy.com
[Misc] [原创]2020网鼎杯 白虎组 b64 精析
2021-6-11 10:02 2033

  1. 不懂出题的师傅是哪位,但猜测很大可能性不超过25岁。

  2. 最近又在搞CTF,但看着余弦等大佬都已转战区块链领域良久,不觉心慌慌,感觉自己再亿次被时代抛弃。

题目很简练,类型:Crypto,最终解出人数是300队以内。
下载打开看是

密文:uLdAuO8duojAFLEKjIgdpfGeZoELjJp9kSieuIsAjJ/LpSXDuCGduouz
泄露的密文:pTjMwJ9WiQHfvC+eFCFKTBpWQtmgjopgqtmPjfKfjSmdFLpeFf/Aj2ud3tN7u2+enC9+nLN8kgdWo29ZnCrOFCDdFCrOFoF=
泄露的明文:ashlkj!@sj1223%^&*Sd4564sd879s5d12f231a46qwjkd12J;DJjl;LjL;KJ8729128713

几乎15分钟内就能看出,“泄露的密文”可能是个类似Base64的东西,把“泄露的明文”转换成base64编码看看:

YXNobGtqIUBzajEyMjMlXiYqU2Q0NTY0c2Q4NzlzNWQxMmYyMzFhNDZxd2prZDEySjtESmpsO0xqTDtLSjg3MjkxMjg3MTM=

注意:FoF=和MTM=
与泄露的密文对比后发现最后四位长得很像,猜测最后3位的加密过程肯定是M--->F,T---->o。

Vlookup

初步想法是先把“密文”按照替换法替换成明文(要注意Excel某些时候不区分大小写,不要直接Vlookup):

=LOOKUP(1,0/EXACT(A:A,D2),B:B)

解释:假如 D2和A:A列的某个项一致,则返回B:B列相应的项
至于1,0,Lookup啥意思,不知道。

明文的前半部分是不是很熟?基本上flag 的base64开头就是ZmxhZ
base64解码:flag{1e3a2。那接下来就很明显了。爆破下面六个字符对应的字母就可以了。
EIGsXz

我们知道base64的字典一般是大小写字母和数字,加号和斜杠组成(共计64个)
如果用python写就是

import string
string.letters+string.digits+'+/'

这个字典里要去掉参考明文的所有字母(这里需要思考一下),原因是:
参考密文当中不包含EIGsXz,假如 EIGsXz作为密文,明文肯定不是参考明文当中的字符。
所以字典64个字符要减掉参考明文中42个字符(注:不可用Excel 的自动去重功能,因为没区分大小写),共计22个。

#用未被映射的字符构造字典
newDic= ''
for x in dic:
if(x not in b ):
newDic+=x

python解析base64

同时又知道python有个解base64的包。

import base64
base64.b64decode('ZmxhZ3sxZTNhMm')

所以可以直接爆破了(引入个进度条,不然等待很绝望)记得要是

pip install progressbar2。
bar = progressbar.ProgressBar(max_value=scipy.special.perm(len(newDic),len(unknow)))

爆破核心代码

dic1=newDic
for E in newDic:
dic2=dic1.replace(E,'')
for G in dic2:
dic3=dic2.replace(G,'')
for I in dic3:
dic4=dic3.replace(I,'')
for s in dic4:
dic5=dic4.replace(s,'')
for X in dic5:
dic6=dic5.replace(X,'')
for z in dic6:
result='ZmxhZ3sxZTNhMm{E}lN{I}0xYz{G}yLT{E}mNGYtOWIyZ{I}{s}hNGFmYW{X}kZj{G}xZTZ{z}'.format(E=E,G=G,I=I,s=s,X=X,z=z)
#  '.............    . E .. I .... G ... E .........  .Is.....    .X ... G......z'
#       ZmxhZ3sxZTNhMm{E}lN{I}0xYz{G}yLT{E}mNGYtOWIyZ{I}{s}hNGFmYW{X}kZj{G}xZTZ{z}
count+=1
#进度条
bar.update(count)
combineAndDecode(result)
scipy.special.perm(len(newDic),len(unknow))

这一串是排列的意思,其实就是A22,6(22个字符中选择6个,有53721360种可能)。这个数字用于设计进度条。

一般盲猜的base64解密,会出一堆乱码字符

所以前面一般加个可打印字符判断,如果是乱码直接下一个尝试了

flag=base64.b64decode(result)
for x in flag:
if(x not in string.printable):
flag=''
break

然后再写个正则验证flag的符合性(根据其他题的flag,格式一般是)。

re.findall(r'flag{\w{8}-\w{4}-\w{4}-\w{4}-\w{12}}',flag)

字符串加工

因为要打出以下这串:

ZmxhZ3sxZTNhMm{E}lN{I}0xYz{G}yLT{E}mNGYtOWIyZ{I}{s}hNGFmYW{X}kZj{G}xZTZ{z}

所以加了个代码

for x in m:   
if (a.find(x)==-1):
n+='{'+x+'}'
unknow+=x
maskM+=x
# -*- coding: utf-8 -*-
import requests
import sys
import string
import base64
import re
import progressbar
import scipy.special
reload(sys)
sys.setdefaultencoding('utf8')
#a(cypher_base64)--->b(plain_base64)
a='pTjMwJ9WiQHfvC+eFCFKTBpWQtmgjopgqtmPjfKfjSmdFLpeFf/Aj2ud3tN7u2+enC9+nLN8kgdWo29ZnCrOFCDdFCrOFoF='
b='YXNobGtqIUBzajEyMjMlXiYqU2Q0NTY0c2Q4NzlzNWQxMmYyMzFhNDZxd2prZDEySjtESmpsO0xqTDtLSjg3MjkxMjg3MTM='
#m(cypher_base64)--->n(target_base64)
m='uLdAuO8duojAFLEKjIgdpfGeZoELjJp9kSieuIsAjJ/LpSXDuCGduouz'
#  ZmxhZ3sxZTNhMm.lN.0xYz.yLT.mNGYtOWIyZ..hNGFmYW.kZj.xZTZ.
n=''
maskM=''
unknow=''
dic=string.letters+string.digits+'+'+'/'
#用未被映射的字符构造字典
newDic= ''
for x in dic:
if(x not in b ):
newDic+=x
print "newDic:"+str(len(newDic))
print "newDic:"+newDic
for x in m:   
if (a.find(x)==-1):
n+='{'+x+'}'
unknow+=x
maskM+=x
else:
n+=b[a.find(x)]
maskM+='.'
print m
print maskM
print n
#未知字符
unknow= "".join(set(list(unknow)))
def combineAndDecode(result):
try:
flag=base64.b64decode(result)
#flag='flag{1e3a2de4-1c02-4f4f-9b2d-a4afabdf01e6}'
for x in flag:
if(x not in string.printable):
flag=''
break
if(len(re.findall(r'flag{\w{8}-\w{4}-\w{4}-\w{4}-\w{12}}',flag))>0):
#print flag
with open('results.txt','a+') as f:
f.write(result+'\n')
f.write(flag+'\n')
#pass
except Exception as e:
pass
count=0
bar = progressbar.ProgressBar(max_value=scipy.special.perm(len(newDic),len(unknow)))
dic1=newDic
for E in newDic:
dic2=dic1.replace(E,'')
for G in dic2:
dic3=dic2.replace(G,'')
for I in dic3:
dic4=dic3.replace(I,'')
for s in dic4:
dic5=dic4.replace(s,'')
for X in dic5:
dic6=dic5.replace(X,'')
for z in dic6:
result='ZmxhZ3sxZTNhMm{E}lN{I}0xYz{G}yLT{E}mNGYtOWIyZ{I}{s}hNGFmYW{X}kZj{G}xZTZ{z}'.format(E=E,G=G,I=I,s=s,X=X,z=z)
#  '.............    . E .. I .... G ... E .........  .Is.....    .X ... G......z'
#       ZmxhZ3sxZTNhMm{E}lN{I}0xYz{G}yLT{E}mNGYtOWIyZ{I}{s}hNGFmYW{X}kZj{G}xZTZ{z}
count+=1
#进度条
bar.update(count)
combineAndDecode(result)

跑的效果是这样:

大概5分钟内能跑完。

最终结果(21 flag):

(共计可能有21个flag)

ZmxhZ3sxZTNhMmJlNC0xYzAyLTJmNGYtOWIyZC1hNGFmYWRkZjAxZTZ9
flag{1e3a2be4-1c02-2f4f-9b2d-a4afaddf01e6}
ZmxhZ3sxZTNhMmJlNC0xYzAyLTJmNGYtOWIyZC1hNGFmYWVkZjAxZTZ9
flag{1e3a2be4-1c02-2f4f-9b2d-a4afaedf01e6}
ZmxhZ3sxZTNhMmJlNC0xYzAyLTJmNGYtOWIyZC1hNGFmYW5kZjAxZTZ9
flag{1e3a2be4-1c02-2f4f-9b2d-a4afandf01e6}
ZmxhZ3sxZTNhMmJlNC0xYzRyLTJmNGYtOWIyZC1hNGFmYWVkZjRxZTZ9
flag{1e3a2be4-1c4r-2f4f-9b2d-a4afaedf4qe6}
ZmxhZ3sxZTNhMmJlNC0xYzRyLTJmNGYtOWIyZC1hNGFmYW5kZjRxZTZ9
flag{1e3a2be4-1c4r-2f4f-9b2d-a4afandf4qe6}
ZmxhZ3sxZTNhMmJlNC0xYzVyLTJmNGYtOWIyZC1hNGFmYWRkZjVxZTZ9
flag{1e3a2be4-1c5r-2f4f-9b2d-a4afaddf5qe6}
ZmxhZ3sxZTNhMmJlNC0xYzVyLTJmNGYtOWIyZC1hNGFmYW5kZjVxZTZ9
flag{1e3a2be4-1c5r-2f4f-9b2d-a4afandf5qe6}
ZmxhZ3sxZTNhMmRlNC0xYzAyLTRmNGYtOWIyZC1hNGFmYWJkZjAxZTZ9
flag{1e3a2de4-1c02-4f4f-9b2d-a4afabdf01e6}
ZmxhZ3sxZTNhMmRlNC0xYzAyLTRmNGYtOWIyZC1hNGFmYWVkZjAxZTZ9
flag{1e3a2de4-1c02-4f4f-9b2d-a4afaedf01e6}
ZmxhZ3sxZTNhMmRlNC0xYzAyLTRmNGYtOWIyZC1hNGFmYW5kZjAxZTZ9
flag{1e3a2de4-1c02-4f4f-9b2d-a4afandf01e6}
ZmxhZ3sxZTNhMmRlNC0xYzJyLTRmNGYtOWIyZC1hNGFmYWVkZjJxZTZ9
flag{1e3a2de4-1c2r-4f4f-9b2d-a4afaedf2qe6}
ZmxhZ3sxZTNhMmRlNC0xYzJyLTRmNGYtOWIyZC1hNGFmYW5kZjJxZTZ9
flag{1e3a2de4-1c2r-4f4f-9b2d-a4afandf2qe6}
ZmxhZ3sxZTNhMmRlNC0xYzVyLTRmNGYtOWIyZC1hNGFmYWJkZjVxZTZ9
flag{1e3a2de4-1c5r-4f4f-9b2d-a4afabdf5qe6}
ZmxhZ3sxZTNhMmRlNC0xYzVyLTRmNGYtOWIyZC1hNGFmYW5kZjVxZTZ9
flag{1e3a2de4-1c5r-4f4f-9b2d-a4afandf5qe6}
ZmxhZ3sxZTNhMmVlNC0xYzAyLTVmNGYtOWIyZC1hNGFmYWJkZjAxZTZ9
flag{1e3a2ee4-1c02-5f4f-9b2d-a4afabdf01e6}
ZmxhZ3sxZTNhMmVlNC0xYzAyLTVmNGYtOWIyZC1hNGFmYWRkZjAxZTZ9
flag{1e3a2ee4-1c02-5f4f-9b2d-a4afaddf01e6}
ZmxhZ3sxZTNhMmVlNC0xYzAyLTVmNGYtOWIyZC1hNGFmYW5kZjAxZTZ9
flag{1e3a2ee4-1c02-5f4f-9b2d-a4afandf01e6}
ZmxhZ3sxZTNhMmVlNC0xYzJyLTVmNGYtOWIyZC1hNGFmYWRkZjJxZTZ9
flag{1e3a2ee4-1c2r-5f4f-9b2d-a4afaddf2qe6}
ZmxhZ3sxZTNhMmVlNC0xYzJyLTVmNGYtOWIyZC1hNGFmYW5kZjJxZTZ9
flag{1e3a2ee4-1c2r-5f4f-9b2d-a4afandf2qe6}
ZmxhZ3sxZTNhMmVlNC0xYzRyLTVmNGYtOWIyZC1hNGFmYWJkZjRxZTZ9
flag{1e3a2ee4-1c4r-5f4f-9b2d-a4afabdf4qe6}
ZmxhZ3sxZTNhMmVlNC0xYzRyLTVmNGYtOWIyZC1hNGFmYW5kZjRxZTZ9
flag{1e3a2ee4-1c4r-5f4f-9b2d-a4afandf4qe6}

要解这题门道还是挺多的,以下方面要快速知道并投入使用:
1、 python解base64
2、正则表达式
3、字符串快速转置去重分析
4、进度条设计
5、排列组合知识
6、基本是盲猜,连base64原理是什么都可以不用知道。但知道一下base64原理也挺好。

VLOOKUP函数不能区分大小写,该如何查找匹配?
https://cloud.tencent.com/developer/news/594528

附件下载(Excel和python文件)

https://github.com/8gg/BlogFile/issues/1

1、深入研究Excel Lookup如何匹配大小写
2、研究 Base64原理

[看雪官方培训] Unicorn Trace还原Ollvm算法!《安卓高级研修班》2021年秋季班火热招生!!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK