首页
社区
课程
招聘
[原创]2020网鼎杯 青龙组 未完成的书 WP
发表于: 2020-5-28 09:09 10468

[原创]2020网鼎杯 青龙组 未完成的书 WP

2020-5-28 09:09
10468

作者jindaxia

下载附件是一个压缩包和一个Readme(如下)


压缩包内是一些svg图片

随便打开一个svg看下

这里比较简单,按顺序读出svg文件,然后把文言文的代码读出来,写了个python处理,代码如下

文言文程序大概长这样

打开这个在线ide,https://ide.wy-lang.org/ 把文言文代码贴左边,点compile,得到js的代码,大概如下

无法直接运行,需要修复下,里面的 function和new关键字后面缺一个空格,全盘替换下

修复之后的js文件保存为 wy.js

这是一个高度混淆过的js,初看上去毫无头绪。好在可以直接运行,先直接运行下输出一个false和一段中文

看下代码是哪里输出的信息,定位到 “天地初始” 这个函数

发现一个84长度的可疑字符串(506c6561736520696e70……..000),进行了一些运算之后,检查 ”造化玉碟“ 的值是否和 ”一念一生“ 相同,并且打印出 ”造化玉碟”的值,就是上面看到的中文,随意修改上面的可疑字符串,发现会输出不同的中文。猜测只要修改可疑字符串为, 计算之后函数打印出true和 “一念一生” 这段中文,这个字符串很可能就是flag, 就可以解出题目,下面先来分析下 “一念一生” 这段中文

一念一生:

你可曾听说过雪山悬崖曾让人魂绕梦牵传说中有宝藏在上面也藏着万丈深渊多少人为了他就此长眠却不能闭上双眼那是谁登上高高山顶让传说继续流传一段段一步步越来越近却咫尺天涯一天天一年年一遍又一遍什么都没变你以为这究竟是个传说相信的人并不多你可见过雪山洁白巍峨却闪耀金色的诱惑聪明的愚笨的善良的人还有你熟悉的人在山坡在悬崖在山顶深渊在一念之间雪花飞扬看雪

搜了下发现此为李健的一首歌,听了几遍之后没有发现什么线索

那么先看代码分析下是如何生成这段中文的, 方法 名为 “造化”,简单加了一些注释

这是一个base64算法,稍微不同的是先把16进制字符串转成大整数,然后进行base64编码输出,编码表长这样,总共有65个数组,对应base64编码的65个字符,后面的注释是我手工了加上标准base64表所对应的字符

根据下面的关键代码可知,生成最终的字符串时候,每次只从数组末尾取一个字,然后把这个字从数组里面移除,每个字只能用一次,比如 原来要输出的标准base64字符串是 “LPQ”,这里先输出L对应的那一行最后一个字”你“,然后把”你“字删掉,下次再输出L的时候就是“上”,依次输出PQ对应的 “的多”,最后输出完整的 “一念一生”的歌词,

return 大宇[光].pop();

所以这个时候需要先把中文恢复成标准的base64,然后解码看看到底是什么内容,根据上面的算法,简单写了一个逆算法把上来进行恢复base64。一开始是这么写的,遍历中文数组,如果某个数组的末尾汉字是要查找的汉字,就返回对应的标准值,在数组末尾删除这个字 (pop方法),

得到一个字符串

LaxcnWBAldy3iqX6/Nj2kCBHJfyEo8MwoLR46ouk7cKQQu8T75gbbQhtZlBx2AwLCZMgT5lOOCRz468Fpy7l0me0ZTKTrglEUW18D+E7xJz4ABI/CsKm5BPQS8WwnpUoPDSpk9PscMXLDJUGksO0/ggjvTjxyiFKPKKc6Fs4fKe

转成整数 16进制表示

0x2dac5c9d604095dcb78aa5fafcd8f690204725fc84a3c330a0b478ea8ba4edc29042ef13ef981b6d086d665071d80c0b0993204f994e382473e3af05a72ee5d267b4653293ae0944516d7c0fe13bc49cf800123f0ac2a6e413d04bc5b09e95283c34a993d3ec70c5cb0c950692c3b4fe0823bd38f1ca214a3ca29ce85b387ca7

js已经分析了一段时间了,根据题目有提示说是基础RSA,看到两个可疑变量,注意读音, 怀疑就是N和eimage-20200520095615350

但是这个是中文,程序运行时下断点,取出这两个值

N = 0xd1bcc2c2583a355489d4df31375ee3c91e6496632a966c8fe3501692f7d3c389533f178c3ca1163eb8d0c14a9e221ee4192f83c80477a609177f0d7861b395743cd51b00703e3b3238f57263f1ee15893caa99e2b7b70a47d78c32dedd966489888e38a2d47ccd2df3d1142cdcdd7e3abdc504ac48dbab4cd5e6cbdc2ba29205

e = 0x1a418b654d77d0f242ec5abfcde0451e8fd0076631d67819f53578b4fd349507e36115f43e40b7e3971c9681a6fa859fae52c66783c8ad9b6707816e5067b1e1c40ca7f840fd21c235d9ea9e81a4bb539b06ca528b3a5028f9186186b96f9f026552e74756bd3b85892ae98eebd3a0b952bd7d19d63f07c7d1eb6db093a91e95

但是只有N和e是没用的,必须知道d才能解密RSA,根据战友提供的S代码和思路,因为e非常大,很有可能可以通过Wiener attack方法解出d,试了下,真的解出了d,代码和输出如下:

通过得到的d,尝试解密第四步里面的大整数

0x2dac5c9d604095dcb78aa5fafcd8f690204725fc84a3c330a0b478ea8ba4edc29042ef13ef981b6d086d665071d80c0b0993204f994e382473e3af05a72ee5d267b4653293ae0944516d7c0fe13bc49cf800123f0ac2a6e413d04bc5b09e95283c34a993d3ec70c5cb0c950692c3b4fe0823bd38f1ca214a3ca29ce85b387ca7

顺便贴下RSA解密代码

发现解出来的原文并没有什么意义,可能哪里做错了

因为发现虽然好像算出来了RSA的秘钥d,但是解密出来的东西并没有任何作用,在这里卡住了很久,期间重新分析了js代码,并且对几个关键步骤进行了验证,确认了js代码的逻辑,流程图也非常简单

那么解密的思路就是 先把歌词还原成标准base64,解码base64得到一个数字B,然后RSA解密变成数字A,把数字A逆推出原始字符串,这个字符串很可能就是Flag,

怀疑歌词还原成标准base64的算法有问题。发现中文码表里面有大量相同的汉字,如果需要查找的汉字 同时在多个列表的末尾,那可能会有多种结果,上次的算法 只是解出了其中的一种情况,极大概率是错误的。动态调试了一下代码,发现确实有大量的位置,有相同的汉字候选,而且因为码表是动态的(每个字只用一次,pop了一个字之后,码表就改变了)无法做按照固定位置的遍历来输出所有可能性,这时候注意到题目提示

对比了一下提示里面的字符串长度,和需要求解标准base64字符串是匹配的,并且提供了sha256, 那么可以列出所有的可能性,逐个计算sha256,就可以找到真正的字符串。思考了一下,遍历出所有的可能性可以使用一种基于决策树的搜索算法,根据提供的字符串模板,可以快速排除错误答案。在原js的环境上写了一个回溯的深度优先搜索递归算法,提示模板作为限制条件,输出所有的可能字符串

输出的结果正好是 1024个,如下,这里任何一个都可以转换成 “一念一生”

逐个求sha256,和题目提示的进行对比

得到正确的base64字符串

LxnWBAlyiXc62kCBHfyEo8woR6oMuk7cKQQN8T75gbbQtZlLBx2AwL4CZ3M/JT5lOg4Fp6y70mle0ZTTgzKr8EUCW8R1D+E7x4AuBI/CsOKm5PWnhpJaUoPDpk9PscMXLQJUGkBsO80/SjggzjvDwxSiTqFjdKPKylKc6F4fKes=

然后 进行RSA解密,得到一个整数

0x222021b2311dfdddbdfdf1df31dc3dddfdbddc3dfdf1df3c3f21df321c3ddf31f1df221f3dfdfdddb2213

这个整数是怎么生成的呢? 看js代码

这是一个用字符串表示大整数的算法,简单解释下,接收下表范围内的字符串,每一个字符代表一个 0-35(10进制)的数字(下标)

abcdefghijklmnopqrstuvwxyz0123456789

比如a代表0,d代表3, 0代表26

把每个字符当成16进制的一位填入到16进制的模板里面,因为16进制每位只能填0-f 16个数,这里有36个数,一定存在溢出,溢出(进位)的部分和上一位取 ‘或’ 运算,下面字符串 c5y8就表示数字 0x3F82

根据这个规则,如果知道结果3F82,要倒推原文的话,先看最低位2,这时候会有三种可能的16进制下标(2,12,22),可能有三种结果,但是因为第二位是偶数,所以排除12这种可能,依此类推,每个位置上都有1-2种可能性,字符串长度是84,所以总共可能有 2^84种结果,不管了,先把算法写出来,试着跑一下,然后再考虑如何优化。下面是运行时的截图

跑了10几分钟 程序都没停,结果数量太大,需要去加一些限制条件,优化算法。一边调程序一边看这满屏幕的结果,突然发现结果里面有一些固定位置上是 ‘2d’ ,url编码 %2d不就是 ‘-’号吗,脑洞大开,如果再把这个字符每隔两位添加%,再urldecode一下。修改代码再跑一把,在增加限制条件 输出的字符串格式应该为 类似这样 flag{xxxxx-xxxx-xxx-xxx-xxxxxx}

重新修改下程序,把一些位置固定住,这样可能的结果就变得比较少了,再根据Readme内提示,逐个取 sha256

程序运行之后就去睡觉了,这是运行中的截图


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2020-5-28 14:11 被jfk_jin编辑 ,原因:
收藏
免费 5
支持
分享
最新回复 (11)
雪    币: 26205
活跃值: (63302)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
沙发 
2020-5-28 09:22
0
雪    币: 916
活跃值: (3434)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
3
楼主厉害!
2020-5-28 12:42
0
雪    币: 385
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
楼主厉害!楼主厉害!楼主厉害!
2020-5-28 13:05
0
雪    币: 386
活跃值: (98)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
楼主厉害
2020-5-28 13:15
0
雪    币: 1535
活跃值: (695)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
tql
2020-5-28 13:35
0
雪    币: 26205
活跃值: (63302)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
7

有一张图片没出来,麻烦楼主再上传一下哦

2020-5-28 13:55
0
雪    币: 1467
活跃值: (103)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
8
Editor 有一张图片没出来,麻烦楼主再上传一下哦
嗯,改好了。多谢版主提醒
2020-5-28 14:12
0
雪    币: 26205
活跃值: (63302)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
9
jfk_jin 嗯,改好了。多谢版主提醒
 文章已经设置精华,移到CTF 版块了,期待更多优秀文章!
2020-5-28 14:16
0
雪    币: 6064
活跃值: (12624)
能力值: ( LV12,RANK:312 )
在线值:
发帖
回帖
粉丝
10
nice,步骤精彩
2020-5-28 17:09
0
雪    币: 259
活跃值: (283)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
这是干啥的
2020-5-28 21:49
0
雪    币: 3372
活跃值: (762)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
楼主666
2020-5-29 13:53
0
游客
登录 | 注册 方可回帖
返回
//