Ключ, передаваемый через аргументы командной строки, кодируется бинарным файлом. Для решения нужно найти исходную строку для вот этого вывода:

_A_m_aFneSuyn_w_IypvSr_ahIEwp_gitrnMhaetevT_so!

Solution

Начну со статического анализа.

int32_t main(int32_t argc, char** argv, char** envp)
    void* fsbase
    int64_t rax = *(fsbase + 0x28)
    int32_t result
    
    if (argc s> 1)
        if (strlen(argv[1]) u<= 0x80)
            void str
            strncpy(&str, argv[1], 0x80)
            swaper(&str, 0xa)
            swaper(&str, 9)
            swaper(&str, 8)
            swaper(&str, 7)
            swaper(&str, 6)
            swaper(&str, 5)
            swaper(&str, 4)
            swaper(&str, 3)
            swaper(&str, 2)
            puts(&str)
            result = 0
        else
            puts(str: "String is too long")
            result = 1
    else
        puts(str: "Give me a string")
        result = 1
    
    if (rax == *(fsbase + 0x28))
        return result
    
    __stack_chk_fail()
    noreturn

Хмм. Есть подозрение, что функция swapper меняет буквы местами. При этом результат сохраняется в str. С учетом того, что второй аргумент меняется линейно от 10 до 2, то у меня возникла идея - пропатчу я второй аргумент так, чтобы значения шли от 2 до 10:

IMG

Запущу пропатченный бинарь с нашей строкой:

root@9d3a65040c33:/rev# ./spbctf_3_x86_64_patched _A_m_aFneSuyn_w_IypvSr_ahIEwp_gitrnMhaetevT_so!
I_Am_Funny_Swaper_I_Swap_Everything_That_Moves!

IMG

Ладно. Теперь все-таки пореверсим. Гляну функцию swaper:

int64_t swaper(char* str, int32_t dist) {
    uint64_t len = strlen(str);
    int32_t pos = 0;
    int64_t result;
    
    while (true)
    {
        result = ((int64_t)pos);
        
        if (result >= (len - ((int64_t)dist)))
            break;
        
        char tmp = str[((int64_t)pos)];
        str[((int64_t)pos)] = str[(((int64_t)(dist + pos)) - 1)];
        *(uint8_t*)((((int64_t)(dist + pos)) - 1) + str) = tmp;
        pos += dist;
    }
    
    return result;
}

Я был прав. Ровно это алгоритм и делает. Напишу солвер на python:

def swaper(s: list[str], dist: int) -> int:
    for i in range(0, len(s) - dist, dist):
        s[i], s[i+dist - 1] = s[i+dist - 1], s[i]


if __name__ == "__main__":
    crypted = list('_A_m_aFneSuyn_w_IypvSr_ahIEwp_gitrnMhaetevT_so!')
    for i in range(2, 11):
        swaper(crypted, i)
    print(''.join(crypted))

Ожидаемо, что результат остался такой же:

I_Am_Funny_Swaper_I_Swap_Everything_That_Moves!

Сдам флаг властям на дашборде:

IMG