某周末,在某大佬的推荐下打了下NahamCon CTF在最后几小时里体验了下这真’雨露均沾’的ctf的感觉.(但菜还是菜这点没变(눈_눈) )
web
Agent 95
进入题目,看到
分析要抓包改header,User-Agent改成: Mozilla/4.0(compatible;MSIE6.0;Windows 95)
Localghost
进入题目 F12查看原代码,发现可疑js。
进入http://jh2i.com:50003/jquery.jscroll2.js看到
1 | var _0xbcec=["\x75\x73\x65\x20\x73\x74\x72\x69\x63\x74","\x6A\x73\x63\x72\x6F\x6C\x6C","\x3C\x73\x6D\x61\x6C\x6C\x3E\x4C\x6F\x61\x64\x69\x6E\x67\x2E\x2E\x2E\x3C\x2F\x73\x6D\x61\x6C\x6C\x3E","\x61\x3A\x6C\x61\x73\x74","","\x66\x6C\x61\x67","\x53\x6B\x4E\x55\x52\x6E\x74\x7A\x63\x47\x39\x76\x62\x32\x39\x76\x61\x33\x6C\x66\x5A\x32\x68\x76\x63\x33\x52\x7A\x58\x32\x6C\x75\x58\x33\x4E\x30\x62\x33\x4A\x68\x5A\x32\x56\x39","\x73\x65\x74\x49\x74\x65\x6D","\x6C\x6F\x63\x61\x6C\x53\x74\x6F\x72\x61\x67\x65","\x64\x61\x74\x61","\x66\x75\x6E\x63\x74\x69\x6F\x6E","\x64\x65\x66\x61\x75\x6C\x74\x73","\x65\x78\x74\x65\x6E\x64","\x6F\x76\x65\x72\x66\x6C\x6F\x77\x2D\x79","\x63\x73\x73","\x76\x69\x73\x69\x62\x6C\x65","\x66\x69\x72\x73\x74","\x6E\x65\x78\x74\x53\x65\x6C\x65\x63\x74\x6F\x72","\x66\x69\x6E\x64","\x62\x6F\x64\x79","\x68\x72\x65\x66","\x61\x74\x74\x72","\x20","\x63\x6F\x6E\x74\x65\x6E\x74\x53\x65\x6C\x65\x63\x74\x6F\x72","\x74\x72\x69\x6D","\x73\x72\x63","\x69\x6D\x67","\x66\x69\x6C\x74\x65\x72","\x6C\x6F\x61\x64\x69\x6E\x67\x48\x74\x6D\x6C","\x6C\x65\x6E\x67\x74\x68","\x2E\x6A\x73\x63\x72\x6F\x6C\x6C\x2D\x69\x6E\x6E\x65\x72","\x3C\x64\x69\x76\x20\x63\x6C\x61\x73\x73\x3D\x22\x6A\x73\x63\x72\x6F\x6C\x6C\x2D\x69\x6E\x6E\x65\x72\x22\x20\x2F\x3E","\x77\x72\x61\x70\x41\x6C\x6C","\x63\x6F\x6E\x74\x65\x6E\x74\x73","\x70\x61\x67\x69\x6E\x67\x53\x65\x6C\x65\x63\x74\x6F\x72","\x68\x69\x64\x65","\x63\x6C\x6F\x73\x65\x73\x74","\x6A\x73\x63\x72\x6F\x6C\x6C\x2D\x6E\x65\x78\x74\x2D\x70\x61\x72\x65\x6E\x74","\x61\x64\x64\x43\x6C\x61\x73\x73","\x2E\x6A\x73\x63\x72\x6F\x6C\x6C\x2D\x69\x6E\x6E\x65\x72\x2C\x2E\x6A\x73\x63\x72\x6F\x6C\x6C\x2D\x61\x64\x64\x65\x64","\x6E\x6F\x74","\x70\x61\x72\x65\x6E\x74","\x3C\x64\x69\x76\x20\x63\x6C\x61\x73\x73\x3D\x22\x6A\x73\x63\x72\x6F\x6C\x6C\x2D\x6E\x65\x78\x74\x2D\x70\x61\x72\x65\x6E\x74\x22\x20\x2F\x3E","\x77\x72\x61\x70","\x75\x6E\x77\x72\x61\x70","\x63\x68\x69\x6C\x64\x72\x65\x6E","\x2E\x6A\x73\x63\x72\x6F\x6C\x6C\x2D\x61\x64\x64\x65\x64","\x72\x65\x6D\x6F\x76\x65\x44\x61\x74\x61","\x2E\x6A\x73\x63\x72\x6F\x6C\x6C","\x75\x6E\x62\x69\x6E\x64","\x64\x69\x76\x2E\x6A\x73\x63\x72\x6F\x6C\x6C\x2D\x69\x6E\x6E\x65\x72","\x62\x6F\x72\x64\x65\x72\x54\x6F\x70\x57\x69\x64\x74\x68","\x70\x61\x64\x64\x69\x6E\x67\x54\x6F\x70","\x73\x63\x72\x6F\x6C\x6C\x54\x6F\x70","\x74\x6F\x70","\x6F\x66\x66\x73\x65\x74","\x68\x65\x69\x67\x68\x74","\x63\x65\x69\x6C","\x77\x61\x69\x74\x69\x6E\x67","\x70\x61\x64\x64\x69\x6E\x67","\x6F\x75\x74\x65\x72\x48\x65\x69\x67\x68\x74","\x69\x6E\x66\x6F","\x6A\x53\x63\x72\x6F\x6C\x6C\x3A","\x66\x72\x6F\x6D\x20\x62\x6F\x74\x74\x6F\x6D\x2E\x20\x4C\x6F\x61\x64\x69\x6E\x67\x20\x6E\x65\x78\x74\x20\x72\x65\x71\x75\x65\x73\x74\x2E\x2E\x2E","\x6E\x65\x78\x74\x48\x72\x65\x66","\x77\x61\x72\x6E","\x6A\x53\x63\x72\x6F\x6C\x6C\x3A\x20\x6E\x65\x78\x74\x53\x65\x6C\x65\x63\x74\x6F\x72\x20\x6E\x6F\x74\x20\x66\x6F\x75\x6E\x64\x20\x2D\x20\x64\x65\x73\x74\x72\x6F\x79\x69\x6E\x67","\x61\x75\x74\x6F\x54\x72\x69\x67\x67\x65\x72","\x61\x75\x74\x6F\x54\x72\x69\x67\x67\x65\x72\x55\x6E\x74\x69\x6C","\x73\x63\x72\x6F\x6C\x6C\x2E\x6A\x73\x63\x72\x6F\x6C\x6C","\x62\x69\x6E\x64","\x63\x6C\x69\x63\x6B\x2E\x6A\x73\x63\x72\x6F\x6C\x6C","\x3C\x64\x69\x76\x20\x63\x6C\x61\x73\x73\x3D\x22\x6A\x73\x63\x72\x6F\x6C\x6C\x2D\x6C\x6F\x61\x64\x69\x6E\x67\x22\x3E","\x3C\x2F\x64\x69\x76\x3E","\x68\x74\x6D\x6C","\x6C\x61\x73\x74","\x3C\x64\x69\x76\x20\x63\x6C\x61\x73\x73\x3D\x22\x6A\x73\x63\x72\x6F\x6C\x6C\x2D\x61\x64\x64\x65\x64\x22\x20\x2F\x3E","\x61\x70\x70\x65\x6E\x64","\x65\x72\x72\x6F\x72","\x72\x65\x6D\x6F\x76\x65","\x2E\x6A\x73\x63\x72\x6F\x6C\x6C\x2D\x6E\x65\x78\x74\x2D\x70\x61\x72\x65\x6E\x74","\x63\x61\x6C\x6C\x62\x61\x63\x6B","\x63\x61\x6C\x6C","\x64\x69\x72","\x6C\x6F\x61\x64","\x64\x69\x76\x2E\x6A\x73\x63\x72\x6F\x6C\x6C\x2D\x61\x64\x64\x65\x64","\x61\x6E\x69\x6D\x61\x74\x65","\x64\x65\x62\x75\x67","\x6F\x62\x6A\x65\x63\x74","\x61\x70\x70\x6C\x79","\x6C\x6F\x67","\x73\x6C\x69\x63\x65","\x70\x72\x6F\x74\x6F\x74\x79\x70\x65","\x66\x6E","\x69\x6E\x69\x74\x69\x61\x6C\x69\x7A\x65\x64","\x65\x61\x63\x68"]; |
转为utf-8得到
1 | ['use strict', 'jscroll', '<small>Loading...</small>', 'a:last', '', 'flag', 'SkNURntzcG9vb29va3lfZ2hvc3RzX2luX3N0b3JhZ2V9', 'setItem', 'localStorage', 'data', 'function', 'defaults', 'extend', 'overflow-y', 'css', 'visible', 'first', 'nextSelector', 'find', 'body', 'href', 'attr', ' ', 'contentSelector', 'trim', 'src', 'img', 'filter', 'loadingHtml', 'length', '.jscroll-inner', '<div class="jscroll-inner" />', 'wrapAll', 'contents', 'pagingSelector', 'hide', 'closest', 'jscroll-next-parent', 'addClass', '.jscroll-inner,.jscroll-added', 'not', 'parent', '<div class="jscroll-next-parent" />', 'wrap', 'unwrap', 'children', '.jscroll-added', 'removeData', '.jscroll', 'unbind', 'div.jscroll-inner', 'borderTopWidth', 'paddingTop', 'scrollTop', 'top', 'offset', 'height', 'ceil', 'waiting', 'padding', 'outerHeight', 'info', 'jScroll:', 'from bottom. Loading next request...', 'nextHref', 'warn', 'jScroll: nextSelector not found - destroying', 'autoTrigger', 'autoTriggerUntil', 'scroll.jscroll', 'bind', 'click.jscroll', '<div class="jscroll-loading">', '</div>', 'html', 'last', '<div class="jscroll-added" />', 'append', 'error', 'remove', '.jscroll-next-parent', 'callback', 'call', 'dir', 'load', 'div.jscroll-added', 'animate', 'debug', 'object', 'apply', 'log', 'slice', 'prototype', 'fn', 'initialized', 'each'] |
将flag 进行base64解密:JCTF{spoooooky_ghosts_in_storage}
Phphonebook
进入题目发现疑有文件包含漏洞,
构造: http://jh2i.com:50002/?file=php://filter/read=convert.base64-encode/resource=index.php 得到index.php源码。
1 |
|
发现有waf ,file提交的参数里‘.php’会被过滤,并在末尾强制加上‘.php’.
同时发现phphonebook.php。同样用文件包含得到源码。
1 | <!DOCTYPE html> |
发现只要以post提交了emergency变量就可以得到flag
Cryptography
Homecooked
1 | import base64 |
粗略审计mian代码了解大概函数流程:当a()与b()返回结果为True 时(函数a的作用是判num是否为质数,函数b的作用是判断num是否为回数。),输出cipher[count]与num相与的字符串。且在才count==13时num陡然变为5000 在count==26时num陡然变为50000。
cipher_b64 经过解密分析cipher为一个字符串列表:
1 | cipher=[100,111,100,96,112,21,209,166,216,140,330,318,321,70221,70414,70544,71414,71810,72211,72827,73000,73319,73722,74088,74643,75542,1002903,1008094,1022089,1028104,1035337,1043448,1055587,1062541,1065715,1074749,1082844,1085696,1092966,1094000] |
发现cipher刚好在第13个元素后及第26后元素大小突然猛增。
因此推测这是一个解密脚本,而flag应该是print输出的结果。按道理直接运行就可以得flag。
于执行代码:
发现果然运行就可以得flag,但flag分三部分给,第二部分给的慢,第三部分更慢。
推测是考点 因该是提高解密脚本效率
仔细审计代码,发现函数a
1 | def a(num): |
这个代码的时间复杂度为N。有很大的优化空间。
解法1:
根据数论,如果X不能被2到根号X之间的任一整数整除,则不是质数。
我们可以优化函数a为:
1 | def a(num): |
这样下来函数a的空间效率只有√N。
解法2:
偶数中除了2都不是质数,且奇数的因数也没有偶数,因此可以进一步优化a函数:
1 | def a(num): |
这样来函数a的空间效率只有√N/2。
解法3:
利用6N±1素数筛选法任何一个自然数,总可以表示成如下形式之一:
6N,6N+1,6N+2,6N+3,6N+4,6N+5 (N=0,1,2,3,..),显然,当N≥1时,6N,6N+2,6N+3,6N+4都不是素数,只有形如6N+1和6N+5的自然数才可能是素数,所以除了2,3外,所有的素数都可以表示成6N±1的形式(N=0,1,2,3,..),根据上述分析可以构造一面筛子,只对形如6N±1的自然数进行筛选,来减少筛选的次数。故可以修改a函数为:
1 | def a(num): |
December
source.py:
1 | #!/usr/bin/env python |
ciphertext:
1 | 症o迩\"郥^N@]X蹶i1鱑WETR^D垶b裓*?^VAAVC绀n?I鬩RTLE[ZD荩y擅/蚗l]RTWN7 |
根据分析这两个文件。推测这是一道DES.MODE_OFB的知道加密方式破解原文。再仔细审计加密脚本。发现没有告诉我们DES.MODE_OFB加密的原始key。
于是,经过谷歌后发现这可能是考DES.MODE_OFB的弱key(详细请移步https://en.wikipedia.org/wiki/Weak_key#Weak_keys_in_DES)。
写脚本用常见弱key进行爆破:
1 | from Crypto.Cipher import DES |
Unvreakable Vase
1 | zmxhz3tkb2vzx3roaxnfzxzlbl9jb3vudf9hc19jcnlwdg9vb30= |
观测题目所给密文,发现是base64。密文中的大小写都变成小写。
我们可以根据不断测试大小写字符加语法判断,进行手动猜测…..
flag{does_this_even_count_as_cryptooo}
做完后,大佬才知道有专门的脚本还原(눈_눈)
1 | from base64 import b64decode as decode |
Ooo-la-la
1 | N = 3349683240683303752040100187123245076775802838668125325785318315004398778586538866210198083573169673444543518654385038484177110828274648967185831623610409867689938609495858551308025785883804091 |
传统的RSA加密,yafu N到pq 带到脚本即可:
1 | import gmpy2 |
Twinning
进入题目,nc jh2i.com 50013
得到:
1 | Generating public and private key... |
看见(e,n)推测是RSA.pin因该就是密文.我们要提交明文得到flag.
当我按照再次思路,yafu分解然后用Ooo-la-la提到rsa解密后提交答案是发现连接断开了.
看来得用全脚本来RSA.这时,有个问题出现了,怎么用python来分解N。
经过反复的nc:
1 | (e,n) is: (65537,28795374863) # 28795374863 = 169691 · 169693 |
发现n的值偏小,且分解出来的质数相近。
且p与q相差2
所以可以立一元二次方程 0 =p**2+2p-n
利用根为正数的求根公式得:
所以可以写代码为
1 | # -*- coding: utf-8 -*- |
Raspberry
1 | n = 7735208939848985079680614633581782274371148157293352904905313315409418467322726702848189532721490121708517697848255948254656192793679424796954743649810878292688507385952920229483776389922650388739975072587660866986603080986980359219525111589659191172937047869008331982383695605801970189336227832715706317 |
拿到题目分析发现 n、e、c,猜测是rsa解密。
分解N,发现分解出多个质数,但质数的数量刚好为整数:
按常规RSA的常规实现中 n=p*q(p、q均为质数)只有两个质数组成。
但根据rsa原理与数论知识,如果n可以分解为多个素数的乘积。可看成是RSA算法的推广形式。
例如:若n=p‘*q*s*t,则r=(p-1)*(q-1)*(s-1)*(t-1),d=e^-1 mod r。
同理写成脚本为:
1 | from Crypto.Util.number import long_to_bytes,bytes_to_long,getPrime,isPrime |
得flag: