CCSSSC-2026 题解
MailSystem
唯一的 pwn
checksec
1 | [*] '/home/kali/Desktop/attachment/pwn' |
保护全开
IDA
程序比较复杂,需要耐心分析,是一个简单的邮件系统
main
1 | void __fastcall __noreturn main(const char *a1, char **a2, char **a3) |
menu
1 | int menu() |
能注册和登录,可以正常退出
init
1 | int init() |
初始化管理员账号,管理员密码随机
login
1 | unsigned __int64 login() |
登录逻辑
register
1 | unsigned __int64 register() |
注册逻辑
admin_check
1 | __int64 __fastcall admin_check(const char *a1, const char *a2) |
检测管理员账号
admin_panel
1 | unsigned __int64 admin_panel() |
管理员面板
mail_panel
1 | unsigned __int64 __fastcall mail_panel(size_t *a1) |
用户面板
add_user
1 | __int64 __fastcall add_user(__int64 a1) |
添加用户,特定情况下存在正向越界写
mail_user_to_user
1 | unsigned __int64 mail_user_to_user() |
管理员以某一用户名义发邮件给另一名用户,存在越界读写
mail_menu
1 | int mail_menu() |
用户菜单
write_mail
1 | unsigned __int64 __fastcall write_mail(__int64 a1) |
写邮件
read_mail
1 | unsigned __int64 __fastcall read_mail(__int64 a1) |
读邮件
send_mail
1 | __int64 __fastcall send_mail(size_t *a1) |
发送邮件
read_menu
1 | int read_menu() |
读邮件面板
secure_check
1 | __int64 __fastcall secure_check(int a1) |
安全检测,发送频率过高会封号
bss
1 | .bss:0000000000007020 ; =========================================================================== |
bss 结构
攻击思路
难点是梳理程序流程和内存的结构以及识别漏洞点
管理员内存结构
管理员内存大小为 0x400
1 | 0x32: 名称 |
用户内存结构
用户内存大小为 0x410
1 | 0x0-0x100: 0x100 收件 |
漏洞点利用
在注册时有这样的逻辑:
1 | v2 = 0; |
这里 j 在出 for 循环时可以为 12 ,这样的话可以从用户表越界到管理员表,把管理员的名称和密码都清空,这样就可以直接登录管理员账号了
但是要使 j 为 12 ,就要绕过上面对 v2 的大小检验,这要求 *(_QWORD *)(*(_QWORD *)(8LL * i + a1) + 0x278LL) 为 0 而 *(_QWORD *)(*(_QWORD *)(8LL * j + a1) + 0x388LL 不为零,该情况发生的条件是用户被 ban
而要想用户被 ban ,根据 secure_check 的逻辑只要在 10 秒内发送超过四次邮件即可
于是我们每注册一个用户就 ban 一个,直到填满用户表使溢出发生后即可成为管理员
成为管理员后的 mail_user_to_user 中有反向越界读写,可以通过标准流指针泄露 libc 基址,然后通过往 stderr 里面发送 fake_io 信件打 house_of_apple2 ,走 setcontext 去跑 read 再写入 orw_chain
比赛时最后十分钟过了本地但是远程炸了,淦,好像是交互时间过长的问题。
exp
1 | from pwn import * |
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.