Программа должна вывести OK.

Solution

Первый взгляд

Посмотрю строки в файле:

root@3eac03729f34:/rev# strings const.elf
Flag{This_is_definetly_a_flag}
...

Подозрительно, но ладно. Попробую:

root@3eac03729f34:/rev# ./const.elf
Flag{This_is_definetly_a_flag}

Ничего. Перейду к статике.

Анализ main

int32_t main(int32_t argc, char** argv, char** envp)
{
    char buf[0x10c];
    int32_t var_c = fgets(&buf, 255, __TMC_END__);
    buf[strlen(&buf) - 1] = 0;

    if (!strcmp("Flag{This_is_definetly_a_flag}", &buf))
        puts("OK!");

    return 0;
}

Всё выглядит нормально. strcmp — библиотечная функция, strace не поможет. Но вот ltrace

root@3eac03729f34:/rev# ltrace ./const.elf
fgets(1234
"1234\n", 255, 0x7d597022e8e0) = 0x7ffc92f978e0
strlen("1234\n")                 = 5
strcmp("Flag{ehls_is_dTfineyti_a_flag}", "1234") = 21
+++ exited (status 0) +++

А вот и подвох — строка при сравнении уже изменена! Попробую:

root@3eac03729f34:/rev# ./const.elf
Flag{ehls_is_dTfineyti_a_flag}
OK!

Флаг есть. Разберёмся почему.

.init_array и конструкторы GCC

Секция .init выполняется раньше любого другого кода — до передачи управления main. Все функции, которые должны выполниться до main, находятся в списке .init_array.

Вот наша функция:

int64_t swaps()
{
    flag[5][0] = flag[0xe][0];
    flag[0xe][0] = flag[5][0];
    flag[0x14][0] = flag[0x15][0];
    flag[0x15][0] = flag[7][0];
    flag[7][0] = flag[0x14][0];
    char result = flag[0x13][0];
    flag[0x13][0] = flag[0x14][0];
    flag[0x14][0] = result;
    return result;
}

Она переставляет символы в строке флага до того, как main начинает работу.

В GCC для этого используется атрибут constructor:

#include <stdio.h>

void init_func() __attribute__((constructor));

void init_func() {
    puts("init function call");
}

int main() {
    puts("main function call");
    return 0;
}
root@4428be4b59d9:/rev# ./main
init function call
main function call

Секции в бинаре:

root@4428be4b59d9:/rev# readelf --sections main | grep init
  [12] .init             PROGBITS   0000000000001000  00001000
  [21] .init_array       INIT_ARRAY 0000000000003db0  00002db0

Именно там и лежит указатель на swaps.